From f350f2ceb2a92a515f0fb470c8915f6c921fc6e3 Mon Sep 17 00:00:00 2001 From: Alex Crawford Date: Wed, 2 Jan 2019 16:38:15 -0800 Subject: [PATCH] *: add support for platform none This adds support for the "none" platform. This is used in situations where the infrastructure will not be managed (bring-your-own). Additionally, since the infrastructure is unmanaged, the installer cannot create the infrastructure and the "cluster" target is therefore invalid when used with the "none" platform. For this reason, the "none" platform is hidden in the UX. It is still possible to use, but the install-config will need an empty "none" object under platform. --- pkg/asset/cluster/cluster.go | 8 ++++++-- pkg/asset/installconfig/installconfig.go | 6 ++++-- pkg/asset/installconfig/platform.go | 11 +++++++---- pkg/asset/installconfig/ssh.go | 6 +++--- pkg/asset/machines/master.go | 11 ++++++++--- pkg/asset/machines/worker.go | 9 ++++++--- pkg/types/installconfig.go | 19 +++++++++++++++++-- pkg/types/none/doc.go | 6 ++++++ pkg/types/none/platform.go | 5 +++++ pkg/types/validation/installconfig.go | 10 +++++++--- pkg/types/validation/installconfig_test.go | 8 ++++---- 11 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 pkg/types/none/doc.go create mode 100644 pkg/types/none/platform.go diff --git a/pkg/asset/cluster/cluster.go b/pkg/asset/cluster/cluster.go index 39a79c9da3e..326bdc05447 100644 --- a/pkg/asset/cluster/cluster.go +++ b/pkg/asset/cluster/cluster.go @@ -63,6 +63,10 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) { kubeadminPassword := &password.KubeadminPassword{} parents.Get(installConfig, terraformVariables, adminKubeconfig, kubeadminPassword) + if installConfig.Config.Platform.None != nil { + return errors.New("cluster cannot be created with platform set to 'none'") + } + // Copy the terraform.tfvars to a temp directory where the terraform will be invoked within. tmpDir, err := ioutil.TempDir("", "openshift-install-") if err != nil { @@ -103,10 +107,10 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) { switch { case installConfig.Config.Platform.AWS != nil: metadata.ClusterPlatformMetadata.AWS = aws.Metadata(installConfig.Config) - case installConfig.Config.Platform.OpenStack != nil: - metadata.ClusterPlatformMetadata.OpenStack = openstack.Metadata(installConfig.Config) case installConfig.Config.Platform.Libvirt != nil: metadata.ClusterPlatformMetadata.Libvirt = libvirt.Metadata(installConfig.Config) + case installConfig.Config.Platform.OpenStack != nil: + metadata.ClusterPlatformMetadata.OpenStack = openstack.Metadata(installConfig.Config) default: return fmt.Errorf("no known platform") } diff --git a/pkg/asset/installconfig/installconfig.go b/pkg/asset/installconfig/installconfig.go index c974dce8a88..48664684c8e 100644 --- a/pkg/asset/installconfig/installconfig.go +++ b/pkg/asset/installconfig/installconfig.go @@ -94,12 +94,14 @@ func (a *InstallConfig) Generate(parents asset.Parents) error { switch { case platform.AWS != nil: a.Config.AWS = platform.AWS - case platform.OpenStack != nil: - a.Config.OpenStack = platform.OpenStack case platform.Libvirt != nil: a.Config.Libvirt = platform.Libvirt numberOfMasters = 1 numberOfWorkers = 1 + case platform.None != nil: + a.Config.None = platform.None + case platform.OpenStack != nil: + a.Config.OpenStack = platform.OpenStack default: panic("unknown platform type") } diff --git a/pkg/asset/installconfig/platform.go b/pkg/asset/installconfig/platform.go index f2e6974e24d..adb1f72fb9f 100644 --- a/pkg/asset/installconfig/platform.go +++ b/pkg/asset/installconfig/platform.go @@ -14,6 +14,7 @@ import ( "github.com/openshift/installer/pkg/types" "github.com/openshift/installer/pkg/types/aws" "github.com/openshift/installer/pkg/types/libvirt" + "github.com/openshift/installer/pkg/types/none" "github.com/openshift/installer/pkg/types/openstack" ) @@ -41,13 +42,15 @@ func (a *platform) Generate(asset.Parents) error { if err != nil { return err } - case openstack.Name: - a.OpenStack, err = openstackconfig.Platform() + case libvirt.Name: + a.Libvirt, err = libvirtconfig.Platform() if err != nil { return err } - case libvirt.Name: - a.Libvirt, err = libvirtconfig.Platform() + case none.Name: + a.None = &none.Platform{} + case openstack.Name: + a.OpenStack, err = openstackconfig.Platform() if err != nil { return err } diff --git a/pkg/asset/installconfig/ssh.go b/pkg/asset/installconfig/ssh.go index 0e57cc7ab9d..41cfafad3f5 100644 --- a/pkg/asset/installconfig/ssh.go +++ b/pkg/asset/installconfig/ssh.go @@ -15,7 +15,7 @@ import ( ) const ( - none = "" + noSSHKey = "" ) type sshPublicKey struct { @@ -48,7 +48,7 @@ func readSSHKey(path string) (string, error) { // Generate generates the SSH public key asset. func (a *sshPublicKey) Generate(asset.Parents) error { pubKeys := map[string]string{ - none: "", + noSSHKey: "", } home := os.Getenv("HOME") if home != "" { @@ -83,7 +83,7 @@ func (a *sshPublicKey) Generate(asset.Parents) error { Message: "SSH Public Key", Help: "The SSH public key used to access all nodes within the cluster. This is optional.", Options: paths, - Default: none, + Default: noSSHKey, }, &path, func(ans interface{}) error { choice := ans.(string) i := sort.SearchStrings(paths, choice) diff --git a/pkg/asset/machines/master.go b/pkg/asset/machines/master.go index a409569a174..21515aad227 100644 --- a/pkg/asset/machines/master.go +++ b/pkg/asset/machines/master.go @@ -19,6 +19,10 @@ import ( "github.com/openshift/installer/pkg/asset/machines/openstack" "github.com/openshift/installer/pkg/rhcos" "github.com/openshift/installer/pkg/types" + awstypes "github.com/openshift/installer/pkg/types/aws" + libvirttypes "github.com/openshift/installer/pkg/types/libvirt" + nonetypes "github.com/openshift/installer/pkg/types/none" + openstacktypes "github.com/openshift/installer/pkg/types/openstack" ) // Master generates the machines for the `master` machine pool. @@ -59,7 +63,7 @@ func (m *Master) Generate(dependencies asset.Parents) error { ic := installconfig.Config pool := masterPool(ic.Machines) switch ic.Platform.Name() { - case "aws": + case awstypes.Name: mpool := defaultAWSMachinePoolPlatform() mpool.Set(ic.Platform.AWS.DefaultMachinePlatform) mpool.Set(pool.Platform.AWS) @@ -92,7 +96,7 @@ func (m *Master) Generate(dependencies asset.Parents) error { return errors.Wrap(err, "failed to marshal") } m.MachinesRaw = raw - case "libvirt": + case libvirttypes.Name: machines, err := libvirt.Machines(ic, &pool, "master", "master-user-data") if err != nil { return errors.Wrap(err, "failed to create master machine objects") @@ -104,7 +108,8 @@ func (m *Master) Generate(dependencies asset.Parents) error { return errors.Wrap(err, "failed to marshal") } m.MachinesRaw = raw - case "openstack": + case nonetypes.Name: + case openstacktypes.Name: numOfMasters := int64(0) if pool.Replicas != nil { numOfMasters = *pool.Replicas diff --git a/pkg/asset/machines/worker.go b/pkg/asset/machines/worker.go index 910c2f3d05f..89e71014ece 100644 --- a/pkg/asset/machines/worker.go +++ b/pkg/asset/machines/worker.go @@ -22,6 +22,8 @@ import ( "github.com/openshift/installer/pkg/rhcos" "github.com/openshift/installer/pkg/types" awstypes "github.com/openshift/installer/pkg/types/aws" + libvirttypes "github.com/openshift/installer/pkg/types/libvirt" + nonetypes "github.com/openshift/installer/pkg/types/none" openstacktypes "github.com/openshift/installer/pkg/types/openstack" ) @@ -75,7 +77,7 @@ func (w *Worker) Generate(dependencies asset.Parents) error { ic := installconfig.Config pool := workerPool(ic.Machines) switch ic.Platform.Name() { - case "aws": + case awstypes.Name: mpool := defaultAWSMachinePoolPlatform() mpool.Set(ic.Platform.AWS.DefaultMachinePlatform) mpool.Set(pool.Platform.AWS) @@ -107,7 +109,7 @@ func (w *Worker) Generate(dependencies asset.Parents) error { return errors.Wrap(err, "failed to marshal") } w.MachineSetRaw = raw - case "libvirt": + case libvirttypes.Name: sets, err := libvirt.MachineSets(ic, &pool, "worker", "worker-user-data") if err != nil { return errors.Wrap(err, "failed to create worker machine objects") @@ -119,7 +121,8 @@ func (w *Worker) Generate(dependencies asset.Parents) error { return errors.Wrap(err, "failed to marshal") } w.MachineSetRaw = raw - case "openstack": + case nonetypes.Name: + case openstacktypes.Name: numOfWorkers := int64(0) if pool.Replicas != nil { numOfWorkers = *pool.Replicas diff --git a/pkg/types/installconfig.go b/pkg/types/installconfig.go index 3e105bb2441..23b02381472 100644 --- a/pkg/types/installconfig.go +++ b/pkg/types/installconfig.go @@ -5,17 +5,25 @@ import ( "github.com/openshift/installer/pkg/ipnet" "github.com/openshift/installer/pkg/types/aws" "github.com/openshift/installer/pkg/types/libvirt" + "github.com/openshift/installer/pkg/types/none" "github.com/openshift/installer/pkg/types/openstack" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var ( - // PlatformNames is a slice with all the supported platform names in - // alphabetical order. + // PlatformNames is a slice with all the visibly-supported + // platform names in alphabetical order. This is the list of + // platforms presented to the user in the interactive wizard. PlatformNames = []string{ aws.Name, openstack.Name, } + // HiddenPlatformNames is a slice with all the + // hidden-but-supported platform names. This list isn't presented + // to the user in the interactive wizard. + HiddenPlatformNames = []string{ + none.Name, + } ) // InstallConfig is the configuration for an OpenShift install. @@ -68,6 +76,10 @@ type Platform struct { // Libvirt is the configuration used when installing on libvirt. Libvirt *libvirt.Platform `json:"libvirt,omitempty"` + // None is the empty configuration used when installing on an unsupported + // platform. + None *none.Platform `json:"none,omitempty"` + // OpenStack is the configuration used when installing on OpenStack. OpenStack *openstack.Platform `json:"openstack,omitempty"` } @@ -85,6 +97,9 @@ func (p *Platform) Name() string { if p.Libvirt != nil { return libvirt.Name } + if p.None != nil { + return none.Name + } if p.OpenStack != nil { return openstack.Name } diff --git a/pkg/types/none/doc.go b/pkg/types/none/doc.go new file mode 100644 index 00000000000..e16709984b6 --- /dev/null +++ b/pkg/types/none/doc.go @@ -0,0 +1,6 @@ +// Package none contains generic structures for installer +// configuration and management. +package none + +// Name is name for the None platform. +const Name string = "none" diff --git a/pkg/types/none/platform.go b/pkg/types/none/platform.go new file mode 100644 index 00000000000..32ac0f07a5f --- /dev/null +++ b/pkg/types/none/platform.go @@ -0,0 +1,5 @@ +package none + +// Platform stores any global configuration used for generic +// platforms. +type Platform struct{} diff --git a/pkg/types/validation/installconfig.go b/pkg/types/validation/installconfig.go index 1f91d8725a3..84d7e47ddd7 100644 --- a/pkg/types/validation/installconfig.go +++ b/pkg/types/validation/installconfig.go @@ -111,9 +111,13 @@ func validateMachinePools(pools []types.MachinePool, fldPath *field.Path, platfo func validatePlatform(platform *types.Platform, fldPath *field.Path, openStackValidValuesFetcher openstackvalidation.ValidValuesFetcher) field.ErrorList { allErrs := field.ErrorList{} activePlatform := platform.Name() - i := sort.SearchStrings(types.PlatformNames, activePlatform) - if i == len(types.PlatformNames) || types.PlatformNames[i] != activePlatform { - allErrs = append(allErrs, field.Invalid(fldPath, platform, fmt.Sprintf("must specify one of the platforms (%s)", strings.Join(types.PlatformNames, ", ")))) + platforms := make([]string, len(types.PlatformNames)) + copy(platforms, types.PlatformNames) + platforms = append(platforms, types.HiddenPlatformNames...) + sort.Strings(platforms) + i := sort.SearchStrings(platforms, activePlatform) + if i == len(platforms) || platforms[i] != activePlatform { + allErrs = append(allErrs, field.Invalid(fldPath, platform, fmt.Sprintf("must specify one of the platforms (%s)", strings.Join(platforms, ", ")))) } validate := func(n string, value interface{}, validation func(*field.Path) field.ErrorList) { if n != activePlatform { diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index c1ec64800ef..cd1e7e6c95f 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -197,7 +197,7 @@ func TestValidateInstallConfig(t *testing.T) { c.Platform = types.Platform{} return c }(), - expectedError: `^platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(nil\), Libvirt:\(\*libvirt\.Platform\)\(nil\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must specify one of the platforms \(aws, openstack\)$`, + expectedError: `^platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(nil\), Libvirt:\(\*libvirt\.Platform\)\(nil\), None:\(\*none\.Platform\)\(nil\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must specify one of the platforms \(aws, none, openstack\)$`, }, { name: "multiple platforms", @@ -206,7 +206,7 @@ func TestValidateInstallConfig(t *testing.T) { c.Platform.Libvirt = &libvirt.Platform{} return c }(), - expectedError: `^\[platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(0x[0-9a-f]*\), Libvirt:\(\*libvirt\.Platform\)\(0x[0-9a-f]*\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must only specify a single type of platform; cannot use both "aws" and "libvirt", platform\.libvirt\.uri: Invalid value: "": invalid URI "" \(no scheme\), platform\.libvirt\.network\.if: Required value, platform\.libvirt\.network\.ipRange: Invalid value: ipnet\.IPNet{IPNet:net\.IPNet{IP:net\.IP\(nil\), Mask:net\.IPMask\(nil\)}}: must use IPv4]$`, + expectedError: `^\[platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(0x[0-9a-f]*\), Libvirt:\(\*libvirt\.Platform\)\(0x[0-9a-f]*\), None:\(\*none\.Platform\)\(nil\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must only specify a single type of platform; cannot use both "aws" and "libvirt", platform\.libvirt\.uri: Invalid value: "": invalid URI "" \(no scheme\), platform\.libvirt\.network\.if: Required value, platform\.libvirt\.network\.ipRange: Invalid value: ipnet\.IPNet{IPNet:net\.IPNet{IP:net\.IP\(nil\), Mask:net\.IPMask\(nil\)}}: must use IPv4]$`, }, { name: "invalid aws platform", @@ -234,7 +234,7 @@ func TestValidateInstallConfig(t *testing.T) { } return c }(), - expectedError: `^platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(nil\), Libvirt:\(\*libvirt\.Platform\)\(0x[0-9a-f]*\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must specify one of the platforms \(aws, openstack\)$`, + expectedError: `^platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(nil\), Libvirt:\(\*libvirt\.Platform\)\(0x[0-9a-f]*\), None:\(\*none\.Platform\)\(nil\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must specify one of the platforms \(aws, none, openstack\)$`, }, { name: "invalid libvirt platform", @@ -245,7 +245,7 @@ func TestValidateInstallConfig(t *testing.T) { } return c }(), - expectedError: `^\[platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(nil\), Libvirt:\(\*libvirt\.Platform\)\(0x[0-9a-f]*\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must specify one of the platforms \(aws, openstack\), platform\.libvirt\.uri: Invalid value: "": invalid URI "" \(no scheme\), platform\.libvirt\.network\.if: Required value, platform\.libvirt\.network\.ipRange: Invalid value: ipnet\.IPNet{IPNet:net\.IPNet{IP:net\.IP\(nil\), Mask:net\.IPMask\(nil\)}}: must use IPv4]$`, + expectedError: `^\[platform: Invalid value: types\.Platform{AWS:\(\*aws\.Platform\)\(nil\), Libvirt:\(\*libvirt\.Platform\)\(0x[0-9a-f]*\), None:\(\*none\.Platform\)\(nil\), OpenStack:\(\*openstack\.Platform\)\(nil\)}: must specify one of the platforms \(aws, none, openstack\), platform\.libvirt\.uri: Invalid value: "": invalid URI "" \(no scheme\), platform\.libvirt\.network\.if: Required value, platform\.libvirt\.network\.ipRange: Invalid value: ipnet\.IPNet{IPNet:net\.IPNet{IP:net\.IP\(nil\), Mask:net\.IPMask\(nil\)}}: must use IPv4]$`, }, { name: "valid openstack platform",