mirror of
https://github.com/openshift/installer.git
synced 2026-02-06 00:48:45 +01:00
types/vsphere: simplify vsphere platform
Remove most of the configuration from the vSphere platform, leaving only the options that a basic customer would need to get a cluster running.
This commit is contained in:
@@ -16,8 +16,6 @@ data:
|
||||
{{- else if .CloudCreds.OpenStack}}
|
||||
clouds.yaml: {{.CloudCreds.OpenStack.Base64encodeCloudCreds}}
|
||||
{{- else if .CloudCreds.VSphere}}
|
||||
{{- range .CloudCreds.VSphere.VirtualCenters}}
|
||||
{{.Name}}.username: {{.Base64encodeUsername}}
|
||||
{{.Name}}.password: {{.Base64encodePassword}}
|
||||
{{- end}}
|
||||
{{.CloudCreds.VSphere.VCenter}}.username: {{.CloudCreds.VSphere.Base64encodeUsername}}
|
||||
{{.CloudCreds.VSphere.VCenter}}.password: {{.CloudCreds.VSphere.Base64encodePassword}}
|
||||
{{- end}}
|
||||
|
||||
@@ -91,7 +91,10 @@ func (cpc *CloudProviderConfig) Generate(dependencies asset.Parents) error {
|
||||
}
|
||||
cm.Data[cloudProviderConfigDataKey] = string(marshalled)
|
||||
case vspheretypes.Name:
|
||||
vsphereConfig, err := vspheremanifests.CloudProviderConfig(installConfig.Config.Platform.VSphere)
|
||||
vsphereConfig, err := vspheremanifests.CloudProviderConfig(
|
||||
installConfig.Config.ObjectMeta.Name,
|
||||
installConfig.Config.Platform.VSphere,
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not create cloud provider config")
|
||||
}
|
||||
|
||||
@@ -97,15 +97,11 @@ func (o *Openshift) Generate(dependencies asset.Parents) error {
|
||||
},
|
||||
}
|
||||
case vspheretypes.Name:
|
||||
vcCreds := make([]VSphereVirtualCenterCredsSecretData, len(installConfig.Config.VSphere.VirtualCenters))
|
||||
for i, vc := range installConfig.Config.VSphere.VirtualCenters {
|
||||
vcCreds[i].Name = vc.Name
|
||||
vcCreds[i].Base64encodeUsername = base64.StdEncoding.EncodeToString([]byte(vc.Username))
|
||||
vcCreds[i].Base64encodePassword = base64.StdEncoding.EncodeToString([]byte(vc.Password))
|
||||
}
|
||||
cloudCreds = cloudCredsSecretData{
|
||||
VSphere: &VSphereCredsSecretData{
|
||||
VirtualCenters: vcCreds,
|
||||
VCenter: installConfig.Config.VSphere.VCenter,
|
||||
Base64encodeUsername: base64.StdEncoding.EncodeToString([]byte(installConfig.Config.VSphere.Username)),
|
||||
Base64encodePassword: base64.StdEncoding.EncodeToString([]byte(installConfig.Config.VSphere.Password)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/openshift/installer/pkg/asset/templates/content/bootkube"
|
||||
"github.com/openshift/installer/pkg/asset/tls"
|
||||
"github.com/openshift/installer/pkg/types"
|
||||
vspheretypes "github.com/openshift/installer/pkg/types/vsphere"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -268,12 +267,8 @@ func redactedInstallConfig(config types.InstallConfig) ([]byte, error) {
|
||||
config.PullSecret = ""
|
||||
if config.Platform.VSphere != nil {
|
||||
p := *config.Platform.VSphere
|
||||
p.VirtualCenters = make([]vspheretypes.VirtualCenter, len(config.Platform.VSphere.VirtualCenters))
|
||||
for i, vc := range config.Platform.VSphere.VirtualCenters {
|
||||
vc.Username = ""
|
||||
vc.Password = ""
|
||||
p.VirtualCenters[i] = vc
|
||||
}
|
||||
p.Username = ""
|
||||
p.Password = ""
|
||||
config.Platform.VSphere = &p
|
||||
}
|
||||
return yaml.Marshal(config)
|
||||
|
||||
@@ -44,29 +44,11 @@ func TestRedactedInstallConfig(t *testing.T) {
|
||||
},
|
||||
Platform: types.Platform{
|
||||
VSphere: &vspheretypes.Platform{
|
||||
VirtualCenters: []vspheretypes.VirtualCenter{
|
||||
{
|
||||
Name: "test-server-1",
|
||||
Username: "test-user-1",
|
||||
Password: "test-pass-1",
|
||||
Datacenters: []string{"test-datacenter-1"},
|
||||
},
|
||||
{
|
||||
Name: "test-server-2",
|
||||
Username: "test-user-2",
|
||||
Password: "test-pass-2",
|
||||
Datacenters: []string{"test-datacenter-2"},
|
||||
},
|
||||
},
|
||||
Workspace: vspheretypes.Workspace{
|
||||
Server: "test-server-1",
|
||||
Datacenter: "test-datacenter-1",
|
||||
DefaultDatastore: "test-datastore",
|
||||
ResourcePoolPath: "test-resource-pool",
|
||||
Folder: "test-folder",
|
||||
},
|
||||
SCSIControllerType: "test-controller-type",
|
||||
PublicNetwork: "test-network",
|
||||
VCenter: "test-server-1",
|
||||
Username: "test-user-1",
|
||||
Password: "test-pass-1",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
},
|
||||
},
|
||||
PullSecret: "test-pull-secret",
|
||||
@@ -95,25 +77,11 @@ networking:
|
||||
- 1.2.3.4/5
|
||||
platform:
|
||||
vsphere:
|
||||
publicNetwork: test-network
|
||||
scsiControllerType: test-controller-type
|
||||
virtualCenters:
|
||||
- datacenters:
|
||||
- test-datacenter-1
|
||||
name: test-server-1
|
||||
password: ""
|
||||
username: ""
|
||||
- datacenters:
|
||||
- test-datacenter-2
|
||||
name: test-server-2
|
||||
password: ""
|
||||
username: ""
|
||||
workspace:
|
||||
datacenter: test-datacenter-1
|
||||
defaultDatastore: test-datastore
|
||||
folder: test-folder
|
||||
resourcePoolPath: test-resource-pool
|
||||
server: test-server-1
|
||||
datacenter: test-datacenter
|
||||
defaultDatastore: test-datastore
|
||||
password: ""
|
||||
username: ""
|
||||
vCenter: test-server-1
|
||||
pullSecret: ""
|
||||
sshKey: test-ssh-key
|
||||
`
|
||||
|
||||
@@ -13,12 +13,7 @@ type OpenStackCredsSecretData struct {
|
||||
|
||||
// VSphereCredsSecretData holds encoded credentials and is used to generated cloud-creds secret
|
||||
type VSphereCredsSecretData struct {
|
||||
VirtualCenters []VSphereVirtualCenterCredsSecretData
|
||||
}
|
||||
|
||||
// VSphereVirtualCenterCredsSecretData holds the encoded credentials for a vSphere vCenter.
|
||||
type VSphereVirtualCenterCredsSecretData struct {
|
||||
Name string
|
||||
VCenter string
|
||||
Base64encodeUsername string
|
||||
Base64encodePassword string
|
||||
}
|
||||
|
||||
@@ -13,71 +13,53 @@ import (
|
||||
type config struct {
|
||||
Global global
|
||||
Workspace workspace
|
||||
Disk disk
|
||||
Network network
|
||||
}
|
||||
|
||||
type global struct {
|
||||
SecretName string `ini:"secret-name"`
|
||||
SecretNamespace string `ini:"secret-namespace"`
|
||||
InsecureFlag int `ini:"insecure-flag"`
|
||||
}
|
||||
|
||||
type workspace struct {
|
||||
Server string `ini:"server"`
|
||||
Datacenter string `ini:"datacenter"`
|
||||
DefaultDatastore string `ini:"default-datastore"`
|
||||
ResourcePoolPath string `ini:"resourcepool-path,omitempty"`
|
||||
Folder string `ini:"folder"`
|
||||
}
|
||||
|
||||
type disk struct {
|
||||
SCSIControllerType string `ini:"scsicontrollertype"`
|
||||
}
|
||||
|
||||
type network struct {
|
||||
PublicNetwork string `ini:"public-network"`
|
||||
}
|
||||
|
||||
type virtualCenter struct {
|
||||
Datacenters []string `ini:"datacenters"`
|
||||
Datacenters string `ini:"datacenters"`
|
||||
}
|
||||
|
||||
// CloudProviderConfig generates the cloud provider config for the vSphere platform.
|
||||
func CloudProviderConfig(p *vspheretypes.Platform) (string, error) {
|
||||
func CloudProviderConfig(clusterName string, p *vspheretypes.Platform) (string, error) {
|
||||
file := ini.Empty()
|
||||
config := &config{
|
||||
Global: global{
|
||||
SecretName: "vsphere-creds",
|
||||
SecretNamespace: "kube-system",
|
||||
InsecureFlag: 1,
|
||||
},
|
||||
Workspace: workspace{
|
||||
Server: p.Workspace.Server,
|
||||
Datacenter: p.Workspace.Datacenter,
|
||||
DefaultDatastore: p.Workspace.DefaultDatastore,
|
||||
ResourcePoolPath: p.Workspace.ResourcePoolPath,
|
||||
Folder: p.Workspace.Folder,
|
||||
},
|
||||
Disk: disk{
|
||||
SCSIControllerType: p.SCSIControllerType,
|
||||
},
|
||||
Network: network{
|
||||
PublicNetwork: p.PublicNetwork,
|
||||
Server: p.VCenter,
|
||||
Datacenter: p.Datacenter,
|
||||
DefaultDatastore: p.DefaultDatastore,
|
||||
Folder: clusterName,
|
||||
},
|
||||
}
|
||||
if err := file.ReflectFrom(config); err != nil {
|
||||
return "", errors.Wrap(err, "failed to reflect from config")
|
||||
}
|
||||
for _, vc := range p.VirtualCenters {
|
||||
s, err := file.NewSection(fmt.Sprintf("VirtualCenter %q", vc.Name))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create section for virtual center %q", vc.Name)
|
||||
}
|
||||
if err := s.ReflectFrom(
|
||||
&virtualCenter{
|
||||
Datacenters: vc.Datacenters,
|
||||
}); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to reflect from virtual center %q", vc.Name)
|
||||
}
|
||||
s, err := file.NewSection(fmt.Sprintf("VirtualCenter %q", p.VCenter))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to create section for virtual center")
|
||||
}
|
||||
if err := s.ReflectFrom(
|
||||
&virtualCenter{
|
||||
Datacenters: p.Datacenter,
|
||||
}); err != nil {
|
||||
return "", errors.Wrapf(err, "failed to reflect from virtual center")
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
if _, err := file.WriteTo(buf); err != nil {
|
||||
|
||||
@@ -9,196 +9,30 @@ import (
|
||||
)
|
||||
|
||||
func TestCloudProviderConfig(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
platform *vspheretypes.Platform
|
||||
expectedConfig string
|
||||
}{
|
||||
{
|
||||
name: "single virtualcenter",
|
||||
platform: &vspheretypes.Platform{
|
||||
VirtualCenters: []vspheretypes.VirtualCenter{
|
||||
{
|
||||
Name: "test-name",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
},
|
||||
Workspace: vspheretypes.Workspace{
|
||||
Server: "test-name",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
ResourcePoolPath: "test-resource-pool",
|
||||
Folder: "test-folder",
|
||||
},
|
||||
SCSIControllerType: "test-scsi",
|
||||
PublicNetwork: "test-network",
|
||||
},
|
||||
expectedConfig: `[Global]
|
||||
clusterName := "test-cluster"
|
||||
platform := &vspheretypes.Platform{
|
||||
VCenter: "test-name",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
}
|
||||
expectedConfig := `[Global]
|
||||
secret-name = vsphere-creds
|
||||
secret-namespace = kube-system
|
||||
insecure-flag = 1
|
||||
|
||||
[Workspace]
|
||||
server = test-name
|
||||
datacenter = test-datacenter
|
||||
default-datastore = test-datastore
|
||||
resourcepool-path = test-resource-pool
|
||||
folder = test-folder
|
||||
|
||||
[Disk]
|
||||
scsicontrollertype = test-scsi
|
||||
|
||||
[Network]
|
||||
public-network = test-network
|
||||
folder = test-cluster
|
||||
|
||||
[VirtualCenter "test-name"]
|
||||
datacenters = test-datacenter
|
||||
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "multiple datacenters",
|
||||
platform: &vspheretypes.Platform{
|
||||
VirtualCenters: []vspheretypes.VirtualCenter{
|
||||
{
|
||||
Name: "test-name",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenters: []string{"test-dc1", "test-dc2"},
|
||||
},
|
||||
},
|
||||
Workspace: vspheretypes.Workspace{
|
||||
Server: "test-name",
|
||||
Datacenter: "test-dc1",
|
||||
DefaultDatastore: "test-datastore",
|
||||
ResourcePoolPath: "test-resource-pool",
|
||||
Folder: "test-folder",
|
||||
},
|
||||
SCSIControllerType: "test-scsi",
|
||||
PublicNetwork: "test-network",
|
||||
},
|
||||
expectedConfig: `[Global]
|
||||
secret-name = vsphere-creds
|
||||
secret-namespace = kube-system
|
||||
|
||||
[Workspace]
|
||||
server = test-name
|
||||
datacenter = test-dc1
|
||||
default-datastore = test-datastore
|
||||
resourcepool-path = test-resource-pool
|
||||
folder = test-folder
|
||||
|
||||
[Disk]
|
||||
scsicontrollertype = test-scsi
|
||||
|
||||
[Network]
|
||||
public-network = test-network
|
||||
|
||||
[VirtualCenter "test-name"]
|
||||
datacenters = test-dc1,test-dc2
|
||||
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "multiple virtualcenters",
|
||||
platform: &vspheretypes.Platform{
|
||||
VirtualCenters: []vspheretypes.VirtualCenter{
|
||||
{
|
||||
Name: "test-name1",
|
||||
Username: "test-username1",
|
||||
Password: "test-password1",
|
||||
Datacenters: []string{"test-datacenter1"},
|
||||
},
|
||||
{
|
||||
Name: "test-name2",
|
||||
Username: "test-username2",
|
||||
Password: "test-password2",
|
||||
Datacenters: []string{"test-datacenter2"},
|
||||
},
|
||||
},
|
||||
Workspace: vspheretypes.Workspace{
|
||||
Server: "test-name",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
ResourcePoolPath: "test-resource-pool",
|
||||
Folder: "test-folder",
|
||||
},
|
||||
SCSIControllerType: "test-scsi",
|
||||
PublicNetwork: "test-network",
|
||||
},
|
||||
expectedConfig: `[Global]
|
||||
secret-name = vsphere-creds
|
||||
secret-namespace = kube-system
|
||||
|
||||
[Workspace]
|
||||
server = test-name
|
||||
datacenter = test-datacenter
|
||||
default-datastore = test-datastore
|
||||
resourcepool-path = test-resource-pool
|
||||
folder = test-folder
|
||||
|
||||
[Disk]
|
||||
scsicontrollertype = test-scsi
|
||||
|
||||
[Network]
|
||||
public-network = test-network
|
||||
|
||||
[VirtualCenter "test-name1"]
|
||||
datacenters = test-datacenter1
|
||||
|
||||
[VirtualCenter "test-name2"]
|
||||
datacenters = test-datacenter2
|
||||
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "empty resource pool path",
|
||||
platform: &vspheretypes.Platform{
|
||||
VirtualCenters: []vspheretypes.VirtualCenter{
|
||||
{
|
||||
Name: "test-name",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
},
|
||||
Workspace: vspheretypes.Workspace{
|
||||
Server: "test-name",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
Folder: "test-folder",
|
||||
},
|
||||
SCSIControllerType: "test-scsi",
|
||||
PublicNetwork: "test-network",
|
||||
},
|
||||
expectedConfig: `[Global]
|
||||
secret-name = vsphere-creds
|
||||
secret-namespace = kube-system
|
||||
|
||||
[Workspace]
|
||||
server = test-name
|
||||
datacenter = test-datacenter
|
||||
default-datastore = test-datastore
|
||||
folder = test-folder
|
||||
|
||||
[Disk]
|
||||
scsicontrollertype = test-scsi
|
||||
|
||||
[Network]
|
||||
public-network = test-network
|
||||
|
||||
[VirtualCenter "test-name"]
|
||||
datacenters = test-datacenter
|
||||
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
config, err := CloudProviderConfig(tc.platform)
|
||||
assert.NoError(t, err, "failed to create cloud provider config")
|
||||
assert.Equal(t, tc.expectedConfig, config, "unexpected cloud provider config")
|
||||
})
|
||||
}
|
||||
`
|
||||
actualConfig, err := CloudProviderConfig(clusterName, platform)
|
||||
assert.NoError(t, err, "failed to create cloud provider config")
|
||||
assert.Equal(t, expectedConfig, actualConfig, "unexpected cloud provider config")
|
||||
}
|
||||
|
||||
@@ -73,22 +73,11 @@ func validLibvirtPlatform() *libvirt.Platform {
|
||||
|
||||
func validVSpherePlatform() *vsphere.Platform {
|
||||
return &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
},
|
||||
Workspace: vsphere.Workspace{
|
||||
Server: "test-server",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
Folder: "test-folder",
|
||||
},
|
||||
SCSIControllerType: "test-controller-type",
|
||||
PublicNetwork: "test-network",
|
||||
VCenter: "test-server",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,10 +459,10 @@ func TestValidateInstallConfig(t *testing.T) {
|
||||
c.Platform = types.Platform{
|
||||
VSphere: validVSpherePlatform(),
|
||||
}
|
||||
c.Platform.VSphere.Workspace.Server = ""
|
||||
c.Platform.VSphere.VCenter = ""
|
||||
return c
|
||||
}(),
|
||||
expectedError: `^platform\.vsphere.workspace.server: Required value: must specify the workspace server$`,
|
||||
expectedError: `^platform\.vsphere.vCenter: Required value: must specify the name of the vCenter$`,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -7,25 +7,4 @@ import (
|
||||
|
||||
// SetPlatformDefaults sets the defaults for the platform.
|
||||
func SetPlatformDefaults(p *vsphere.Platform, installConfig *types.InstallConfig) {
|
||||
if p.Workspace.Server == "" {
|
||||
if len(p.VirtualCenters) == 1 {
|
||||
p.Workspace.Server = p.VirtualCenters[0].Name
|
||||
}
|
||||
}
|
||||
if p.Workspace.Datacenter == "" {
|
||||
for _, vc := range p.VirtualCenters {
|
||||
if p.Workspace.Server == vc.Name {
|
||||
if len(vc.Datacenters) == 1 {
|
||||
p.Workspace.Datacenter = vc.Datacenters[0]
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if p.Workspace.Folder == "" {
|
||||
p.Workspace.Folder = installConfig.ObjectMeta.Name
|
||||
}
|
||||
if p.SCSIControllerType == "" {
|
||||
p.SCSIControllerType = "pvscsi"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,7 @@ import (
|
||||
const testClusterName = "test-cluster"
|
||||
|
||||
func defaultPlatform() *vsphere.Platform {
|
||||
return &vsphere.Platform{
|
||||
Workspace: vsphere.Workspace{
|
||||
Folder: testClusterName,
|
||||
},
|
||||
SCSIControllerType: "pvscsi",
|
||||
}
|
||||
return &vsphere.Platform{}
|
||||
}
|
||||
|
||||
func TestSetPlatformDefaults(t *testing.T) {
|
||||
@@ -32,152 +27,6 @@ func TestSetPlatformDefaults(t *testing.T) {
|
||||
platform: &vsphere.Platform{},
|
||||
expected: defaultPlatform(),
|
||||
},
|
||||
{
|
||||
name: "single vCenter",
|
||||
platform: &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{{Name: "test-server"}},
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.VirtualCenters = []vsphere.VirtualCenter{{Name: "test-server"}}
|
||||
p.Workspace.Server = "test-server"
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "multiple vCenters",
|
||||
platform: &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{
|
||||
{Name: "test-server1"},
|
||||
{Name: "test-server2"},
|
||||
},
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.VirtualCenters = []vsphere.VirtualCenter{
|
||||
{Name: "test-server1"},
|
||||
{Name: "test-server2"},
|
||||
}
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "vCenter set",
|
||||
platform: &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{{Name: "test-server"}},
|
||||
Workspace: vsphere.Workspace{
|
||||
Server: "other-server",
|
||||
},
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.VirtualCenters = []vsphere.VirtualCenter{{Name: "test-server"}}
|
||||
p.Workspace.Server = "other-server"
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "single datacenter",
|
||||
platform: &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
},
|
||||
Workspace: vsphere.Workspace{
|
||||
Server: "test-server",
|
||||
},
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.VirtualCenters = []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
}
|
||||
p.Workspace.Server = "test-server"
|
||||
p.Workspace.Datacenter = "test-datacenter"
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "multiple datacenter",
|
||||
platform: &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server",
|
||||
Datacenters: []string{"test-datacenter1", "test-datacenter2"},
|
||||
},
|
||||
},
|
||||
Workspace: vsphere.Workspace{
|
||||
Server: "test-server",
|
||||
},
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.VirtualCenters = []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server",
|
||||
Datacenters: []string{"test-datacenter1", "test-datacenter2"},
|
||||
},
|
||||
}
|
||||
p.Workspace.Server = "test-server"
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "datacenter set",
|
||||
platform: &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
},
|
||||
Workspace: vsphere.Workspace{
|
||||
Server: "test-server",
|
||||
Datacenter: "other-datacenter",
|
||||
},
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.VirtualCenters = []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
}
|
||||
p.Workspace.Server = "test-server"
|
||||
p.Workspace.Datacenter = "other-datacenter"
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "folder set",
|
||||
platform: &vsphere.Platform{
|
||||
Workspace: vsphere.Workspace{
|
||||
Folder: "test-folder",
|
||||
},
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.Workspace.Folder = "test-folder"
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "SCSI controller type set",
|
||||
platform: &vsphere.Platform{
|
||||
SCSIControllerType: "test-controller-type",
|
||||
},
|
||||
expected: func() *vsphere.Platform {
|
||||
p := defaultPlatform()
|
||||
p.SCSIControllerType = "test-controller-type"
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -2,49 +2,14 @@ package vsphere
|
||||
|
||||
// Platform stores any global configuration used for vsphere platforms.
|
||||
type Platform struct {
|
||||
// VirtualCenters are the configurations for the vCenters.
|
||||
VirtualCenters []VirtualCenter `json:"virtualCenters"`
|
||||
// Workspace is the configuration for the workspace.
|
||||
Workspace Workspace `json:"workspace"`
|
||||
// SCSIControllerType is the SCSI controller type in use.
|
||||
// +optional
|
||||
// Default is pvscsi.
|
||||
SCSIControllerType string `json:"scsiControllerType"`
|
||||
// PublicNetwork is the name of the VM network to use.
|
||||
PublicNetwork string `json:"publicNetwork"`
|
||||
}
|
||||
|
||||
// VirtualCenter is the configuration of a vCenter.
|
||||
type VirtualCenter struct {
|
||||
// Name of the vCenter. This is the domain name or the IP address of the vCenter.
|
||||
Name string `json:"name"`
|
||||
// VCenter is the domain name or IP address of the vCenter.
|
||||
VCenter string `json:"vCenter"`
|
||||
// Username is the name of the user to use to connect to the vCenter.
|
||||
Username string `json:"username"`
|
||||
// Password is the password for the user to use to connect to the vCenter.
|
||||
Password string `json:"password"`
|
||||
// Datacenters are the names of the datacenters to use in the vCenter.
|
||||
Datacenters []string `json:"datacenters"`
|
||||
}
|
||||
|
||||
// Workspace is the configuration of the vSphere workspace.
|
||||
type Workspace struct {
|
||||
// Server is the server to use for provisioning.
|
||||
// +optional
|
||||
// Default is the name of the vCenter, if there is only a single vCenter.
|
||||
Server string `json:"server"`
|
||||
// Datacenter is the datacenter to use for provisioning.
|
||||
// +optional
|
||||
// Default is the datacenter in Server, if that vCenter has only a single
|
||||
// datacenter.
|
||||
// Datacenter is the name of the datacenter to use in the vCenter.
|
||||
Datacenter string `json:"datacenter"`
|
||||
// DefaultDatastore is the default datastore to use for provisioning volumes.
|
||||
DefaultDatastore string `json:"defaultDatastore"`
|
||||
// ResourcePoolPath is the resource pool to use in the datacenter.
|
||||
// +optional
|
||||
// Default is the name of the cluster.
|
||||
ResourcePoolPath string `json:"resourcePoolPath"`
|
||||
// Folder is the vCenter VM folder path in the datacenter.
|
||||
// +optional
|
||||
// Default is the name of the cluster.
|
||||
Folder string `json:"folder"`
|
||||
}
|
||||
|
||||
@@ -9,74 +9,20 @@ import (
|
||||
// ValidatePlatform checks that the specified platform is valid.
|
||||
func ValidatePlatform(p *vsphere.Platform, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(p.VirtualCenters) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("virtualCenters"), "must include at least one vCenter"))
|
||||
if len(p.VCenter) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("vCenter"), "must specify the name of the vCenter"))
|
||||
}
|
||||
foundServer := false
|
||||
vcNames := map[string]bool{}
|
||||
for i, vc := range p.VirtualCenters {
|
||||
allErrs = append(allErrs, validateVirtualCenter(&vc, fldPath.Child("virtualCenters").Index(i))...)
|
||||
if vcNames[vc.Name] {
|
||||
allErrs = append(allErrs, field.Duplicate(fldPath.Child("virtualCenters").Index(i), vc.Name))
|
||||
}
|
||||
vcNames[vc.Name] = true
|
||||
if vc.Name == p.Workspace.Server {
|
||||
foundDatacenter := false
|
||||
for _, dc := range vc.Datacenters {
|
||||
if dc == p.Workspace.Datacenter {
|
||||
foundDatacenter = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if p.Workspace.Datacenter != "" && !foundDatacenter {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("workspace").Child("datacenter"), p.Workspace.Datacenter, "workspace datacenter must be a datacenter in the workspace server"))
|
||||
}
|
||||
foundServer = true
|
||||
}
|
||||
if len(p.Username) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("username"), "must specify the username"))
|
||||
}
|
||||
if len(p.Workspace.Server) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("workspace").Child("server"), "must specify the workspace server"))
|
||||
} else if !foundServer {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("workspace").Child("server"), p.Workspace.Server, "workspace server must be a specified vCenter"))
|
||||
if len(p.Password) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("password"), "must specify the password"))
|
||||
}
|
||||
if len(p.Workspace.Datacenter) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("workspace").Child("datacenter"), "must specify the workspace datacenter"))
|
||||
if len(p.Datacenter) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("datacenter"), "must specify the datacenter"))
|
||||
}
|
||||
if len(p.Workspace.DefaultDatastore) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("workspace").Child("defaultDatastore"), "must specify the default datastore"))
|
||||
}
|
||||
if len(p.Workspace.Folder) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("workspace").Child("folder"), "must specify the VM folder"))
|
||||
}
|
||||
if len(p.SCSIControllerType) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("scsiControllerType"), "must specify the SCSI controller type"))
|
||||
}
|
||||
if len(p.PublicNetwork) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("publicNetwork"), "must specify the public VM network"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateVirtualCenter(vc *vsphere.VirtualCenter, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(vc.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "vCenter must have a name"))
|
||||
}
|
||||
if len(vc.Username) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("username"), "username required for each vCenter"))
|
||||
}
|
||||
if len(vc.Password) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("password"), "password required for each vCenter"))
|
||||
}
|
||||
if len(vc.Datacenters) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("datacenters"), "must include at least one datacenter"))
|
||||
}
|
||||
dcs := map[string]bool{}
|
||||
for i, dc := range vc.Datacenters {
|
||||
if dcs[dc] {
|
||||
allErrs = append(allErrs, field.Duplicate(fldPath.Child("datacenters").Index(i), dc))
|
||||
}
|
||||
dcs[dc] = true
|
||||
if len(p.DefaultDatastore) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("defaultDatastore"), "must specify the default datastore"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
@@ -11,23 +11,11 @@ import (
|
||||
|
||||
func validPlatform() *vsphere.Platform {
|
||||
return &vsphere.Platform{
|
||||
VirtualCenters: []vsphere.VirtualCenter{
|
||||
{
|
||||
Name: "test-server-name",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenters: []string{"test-datacenter"},
|
||||
},
|
||||
},
|
||||
Workspace: vsphere.Workspace{
|
||||
Server: "test-server-name",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
ResourcePoolPath: "test-resource-pool",
|
||||
Folder: "test-folder",
|
||||
},
|
||||
SCSIControllerType: "test-controller-type",
|
||||
PublicNetwork: "test-network",
|
||||
VCenter: "test-vcenter",
|
||||
Username: "test-username",
|
||||
Password: "test-password",
|
||||
Datacenter: "test-datacenter",
|
||||
DefaultDatastore: "test-datastore",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,139 +29,50 @@ func TestValidatePlatform(t *testing.T) {
|
||||
name: "minimal",
|
||||
platform: validPlatform(),
|
||||
},
|
||||
{
|
||||
name: "empty vCenters",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.VirtualCenters = nil
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^\[test-path\.virtualCenters: Required value: must include at least one vCenter, test-path\.workspace\.server: Invalid value: "test-server-name": workspace server must be a specified vCenter]$`,
|
||||
},
|
||||
{
|
||||
name: "missing vCenter name",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.VirtualCenters[0].Name = ""
|
||||
p.VCenter = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^\[test-path\.virtualCenters\[0]\.name: Required value: vCenter must have a name, test-path\.workspace\.server: Invalid value: "test-server-name": workspace server must be a specified vCenter]$`,
|
||||
expectedError: `^test-path\.vCenter: Required value: must specify the name of the vCenter$`,
|
||||
},
|
||||
{
|
||||
name: "missing vCenter username",
|
||||
name: "missing username",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.VirtualCenters[0].Username = ""
|
||||
p.Username = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.virtualCenters\[0]\.username: Required value: username required for each vCenter$`,
|
||||
expectedError: `^test-path\.username: Required value: must specify the username$`,
|
||||
},
|
||||
{
|
||||
name: "missing vCenter password",
|
||||
name: "missing password",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.VirtualCenters[0].Password = ""
|
||||
p.Password = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.virtualCenters\[0]\.password: Required value: password required for each vCenter$`,
|
||||
expectedError: `^test-path\.password: Required value: must specify the password$`,
|
||||
},
|
||||
{
|
||||
name: "empty vCenter datacenters",
|
||||
name: "missing datacenter",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.VirtualCenters[0].Datacenters = nil
|
||||
p.Datacenter = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^\[test-path\.virtualCenters\[0]\.datacenters: Required value: must include at least one datacenter, test-path\.workspace\.datacenter: Invalid value: "test-datacenter": workspace datacenter must be a datacenter in the workspace server]$`,
|
||||
},
|
||||
{
|
||||
name: "multiple vCenter datacenters",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.VirtualCenters[0].Datacenters = []string{"test-datacenter", "other-datacenter"}
|
||||
return p
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "duplicate vCenter datacenters",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.VirtualCenters[0].Datacenters = []string{"test-datacenter", "test-datacenter"}
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.virtualCenters\[0]\.datacenters\[1]: Duplicate value: "test-datacenter"$`,
|
||||
},
|
||||
{
|
||||
name: "missing workspace server",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.Workspace.Server = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.workspace\.server: Required value: must specify the workspace server$`,
|
||||
},
|
||||
{
|
||||
name: "no vCenter for workspace server",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.Workspace.Server = "other-server-name"
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.workspace\.server: Invalid value: "other-server-name": workspace server must be a specified vCenter$`,
|
||||
},
|
||||
{
|
||||
name: "missing workspace datacenter",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.Workspace.Datacenter = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.workspace\.datacenter: Required value: must specify the workspace datacenter$`,
|
||||
},
|
||||
{
|
||||
name: "missing workspace datacenter",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.Workspace.Datacenter = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.workspace\.datacenter: Required value: must specify the workspace datacenter$`,
|
||||
expectedError: `^test-path\.datacenter: Required value: must specify the datacenter$`,
|
||||
},
|
||||
{
|
||||
name: "missing default datastore",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.Workspace.DefaultDatastore = ""
|
||||
p.DefaultDatastore = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.workspace\.defaultDatastore: Required value: must specify the default datastore$`,
|
||||
},
|
||||
{
|
||||
name: "missing folder",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.Workspace.Folder = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.workspace\.folder: Required value: must specify the VM folder$`,
|
||||
},
|
||||
{
|
||||
name: "missing SCSI controller type",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.SCSIControllerType = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.scsiControllerType: Required value: must specify the SCSI controller type$`,
|
||||
},
|
||||
{
|
||||
name: "missing public network",
|
||||
platform: func() *vsphere.Platform {
|
||||
p := validPlatform()
|
||||
p.PublicNetwork = ""
|
||||
return p
|
||||
}(),
|
||||
expectedError: `^test-path\.publicNetwork: Required value: must specify the public VM network$`,
|
||||
expectedError: `^test-path\.defaultDatastore: Required value: must specify the default datastore$`,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -9,7 +9,12 @@ metadata:
|
||||
networking:
|
||||
machineCIDR: "139.178.89.192/26"
|
||||
platform:
|
||||
vsphere: {}
|
||||
vsphere:
|
||||
vCenter: vcsa.vmware.devcluster.openshift.com
|
||||
username: YOUR_VSPHERE_USER
|
||||
password: YOUR_VSPHERE_PASSWORD
|
||||
datacenter: dc1
|
||||
defaultDatastore: nvme-ds1
|
||||
pullSecret: YOUR_PULL_SECRET
|
||||
sshKey: YOUR_SSH_KEY
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user