Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OpenStack provider #540

Merged
merged 21 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project's packages adheres to [Semantic Versioning](http://semver.org/s

## [Unreleased]

### Added

- Add alpha support for OpenStack cluster templating.

## [1.54.0] - 2021-12-03

### Fixed
Expand Down
61 changes: 44 additions & 17 deletions cmd/get/capi/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ import (
const (
giantswarmNamespace = "giantswarm"

providerAll = "All"
providerAWS = "AWS"
providerAzure = "Azure"
providerVMware = "VMware"
providerAll = "All"
providerAWS = "AWS"
providerAzure = "Azure"
providerOpenStack = "OpenStack"
providerVSphere = "vSphere"
)

type runner struct {
Expand All @@ -47,6 +48,7 @@ type controller struct {

var (
crds = []crd{
// All
{
DisplayName: "Cluster",
Name: "clusters.cluster.x-k8s.io",
Expand Down Expand Up @@ -102,6 +104,7 @@ var (
Name: "kubeadmconfigtemplates.bootstrap.cluster.x-k8s.io",
Provider: providerAll,
},
// AWS
{
DisplayName: "AWS Cluster",
Name: "awsclusters.infrastructure.cluster.x-k8s.io",
Expand All @@ -122,6 +125,7 @@ var (
Name: "awsmachinetemplates.infrastructure.cluster.x-k8s.io",
Provider: providerAWS,
},
// Azure
{
DisplayName: "Azure Cluster",
Name: "azureclusters.infrastructure.cluster.x-k8s.io",
Expand All @@ -142,30 +146,47 @@ var (
Name: "azuremachinetemplates.infrastructure.cluster.x-k8s.io",
Provider: providerAzure,
},
// Open Stack
{
DisplayName: "VMware Cluster",
DisplayName: "OpenStack Cluster",
Name: "openstackclusters.infrastructure.cluster.x-k8s.io",
Provider: providerOpenStack,
},
{
DisplayName: "OpenStack Machine",
Name: "openstackmachines.infrastructure.cluster.x-k8s.io",
Provider: providerOpenStack,
},
{
DisplayName: "OpenStack Machine Template",
Name: "openstackmachinetemplates.infrastructure.cluster.x-k8s.io",
Provider: providerOpenStack,
},
// vSphere
{
DisplayName: "vSphere Cluster",
Name: "vsphereclusters.infrastructure.cluster.x-k8s.io",
Provider: providerVMware,
Provider: providerVSphere,
},
{
DisplayName: "VMware Machine",
DisplayName: "vSphere Machine",
Name: "vspheremachines.infrastructure.cluster.x-k8s.io",
Provider: providerVMware,
Provider: providerVSphere,
},
{
DisplayName: "VMware Machine Template",
DisplayName: "vSphere Machine Template",
Name: "vspheremachinetemplates.infrastructure.cluster.x-k8s.io",
Provider: providerVMware,
Provider: providerVSphere,
},
{
DisplayName: "VMware VM",
DisplayName: "vSphere VM",
Name: "vspherevms.infrastructure.cluster.x-k8s.io",
Provider: providerVMware,
Provider: providerVSphere,
},
{
DisplayName: "VMware HAProxy",
DisplayName: "vSphere HAProxy",
Name: "haproxyloadbalancers.infrastructure.cluster.x-k8s.io",
Provider: providerVMware,
Provider: providerVSphere,
},
}

Expand Down Expand Up @@ -201,10 +222,16 @@ var (
Provider: providerAzure,
},
{
DisplayName: "VMWare Provider",
LabelSelector: "app.kubernetes.io/name=cluster-api-provider-vmware",
DisplayName: "OpenStack Provider",
LabelSelector: "app.kubernetes.io/name=cluster-api-provider-openstack",
ContainerName: "manager",
Provider: providerOpenStack,
},
{
DisplayName: "vSphere Provider",
LabelSelector: "app.kubernetes.io/name=cluster-api-provider-vsphere",
ContainerName: "manager",
Provider: providerVMware,
Provider: providerVSphere,
},
}
)
Expand Down
100 changes: 82 additions & 18 deletions cmd/template/cluster/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@ const (
flagProvider = "provider"

// AWS only.
flagExternalSNAT = "external-snat"
flagEKS = "aws-eks"
flagPodsCIDR = "pods-cidr"
flagControlPlaneSubnet = "control-plane-subnet"
flagAWSExternalSNAT = "external-snat"
flagAWSEKS = "aws-eks"
flagAWSControlPlaneSubnet = "control-plane-subnet"

// OpenStack only.
flagOpenStackCloud = "cloud"
flagOpenStackCloudConfig = "cloud-config"
flagOpenStackDNSNameservers = "dns-nameservers"
flagOpenStackExternalNetworkID = "external-network-id"
flagOpenStackFailureDomain = "failure-domain"
flagOpenStackImageName = "image-name"
flagOpenStackNodeMachineFlavor = "node-machine-flavor"
flagOpenStackNodeCIDR = "node-cidr"
flagOpenStackRootVolumeDiskSize = "root-volume-disk-size"
flagOpenStackRootVolumeSourceType = "root-volume-source-type"
flagOpenStackRootVolumeSourceUUID = "root-volume-source-uuid"

// Common.
flagClusterIDDeprecated = "cluster-id"
Expand All @@ -31,18 +43,36 @@ const (
flagOutput = "output"
flagOrganization = "organization"
flagOwner = "owner" // TODO: Remove some time after December 2021
flagPodsCIDR = "pods-cidr"
flagRelease = "release"
flagLabel = "label"
)

type flag struct {
Provider string

// AWS only.
type awsFlag struct {
ControlPlaneSubnet string
ExternalSNAT bool
EKS bool
PodsCIDR string
}

type openStackFlag struct {
Cloud string // OPENSTACK_CLOUD
CloudConfig string // <no equivalent env var>
DNSNameservers []string // OPENSTACK_DNS_NAMESERVERS
ExternalNetworkID string // <no equivalent env var>
FailureDomain string // OPENSTACK_FAILURE_DOMAIN
ImageName string // OPENSTACK_IMAGE_NAME
NodeMachineFlavor string // OPENSTACK_NODE_MACHINE_FLAVOR
RootVolumeDiskSize string // <no equivalent env var>
RootVolumeSourceType string // <no equivalent env var>
RootVolumeSourceUUID string // <no equivalent env var>
NodeCIDR string // <no equivalent env var>
}

type flag struct {
Provider string

AWS awsFlag
OpenStack openStackFlag

// Common.
ClusterIDDeprecated string
Expand All @@ -53,6 +83,7 @@ type flag struct {
Output string
Organization string
Owner string
PodsCIDR string
Release string
Label []string

Expand All @@ -64,10 +95,35 @@ func (f *flag) Init(cmd *cobra.Command) {
cmd.Flags().StringVar(&f.Provider, flagProvider, "", "Installation infrastructure provider.")

// AWS only.
cmd.Flags().StringVar(&f.ControlPlaneSubnet, flagControlPlaneSubnet, "", "Subnet used for the Control Plane.")
cmd.Flags().BoolVar(&f.ExternalSNAT, flagExternalSNAT, false, "AWS CNI configuration.")
cmd.Flags().BoolVar(&f.EKS, flagEKS, false, "Enable EKS. Only available for AWS Release v20.0.0 (CAPA)")
cmd.Flags().StringVar(&f.PodsCIDR, flagPodsCIDR, "", "CIDR used for the pods.")
cmd.Flags().StringVar(&f.AWS.ControlPlaneSubnet, flagAWSControlPlaneSubnet, "", "Subnet used for the Control Plane.")
cmd.Flags().BoolVar(&f.AWS.ExternalSNAT, flagAWSExternalSNAT, false, "AWS CNI configuration.")
cmd.Flags().BoolVar(&f.AWS.EKS, flagAWSEKS, false, "Enable AWSEKS. Only available for AWS Release v20.0.0 (CAPA)")

// OpenStack only.
cmd.Flags().StringVar(&f.OpenStack.Cloud, flagOpenStackCloud, "openstack", "Name of cloud (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.CloudConfig, flagOpenStackCloudConfig, "cloud-config", "Name of cloud config (OpenStack only).")
cmd.Flags().StringSliceVar(&f.OpenStack.DNSNameservers, flagOpenStackDNSNameservers, nil, "DNS nameservers (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.ExternalNetworkID, flagOpenStackExternalNetworkID, "", "External network ID (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.FailureDomain, flagOpenStackFailureDomain, "", "Failure domain (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.ImageName, flagOpenStackImageName, "ubuntu-2004-kube-v1.20.9", "Image name (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.NodeMachineFlavor, flagOpenStackNodeMachineFlavor, "", "Node machine flavor (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.RootVolumeDiskSize, flagOpenStackRootVolumeDiskSize, "", "Root volume disk size (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.RootVolumeSourceType, flagOpenStackRootVolumeSourceType, "", "Root volume source type (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.RootVolumeSourceUUID, flagOpenStackRootVolumeSourceUUID, "", "Root volume source UUID (OpenStack only).")
cmd.Flags().StringVar(&f.OpenStack.NodeCIDR, flagOpenStackNodeCIDR, "", "CIDR used for the nodes.")

// TODO: Make these flags visible once we have a better method for displaying provider-specific flags.
_ = cmd.Flags().MarkHidden(flagOpenStackCloud)
_ = cmd.Flags().MarkHidden(flagOpenStackCloudConfig)
_ = cmd.Flags().MarkHidden(flagOpenStackDNSNameservers)
_ = cmd.Flags().MarkHidden(flagOpenStackExternalNetworkID)
_ = cmd.Flags().MarkHidden(flagOpenStackFailureDomain)
_ = cmd.Flags().MarkHidden(flagOpenStackImageName)
_ = cmd.Flags().MarkHidden(flagOpenStackNodeMachineFlavor)
_ = cmd.Flags().MarkHidden(flagOpenStackRootVolumeDiskSize)
_ = cmd.Flags().MarkHidden(flagOpenStackRootVolumeSourceType)
_ = cmd.Flags().MarkHidden(flagOpenStackRootVolumeSourceUUID)
_ = cmd.Flags().MarkHidden(flagOpenStackNodeCIDR)

// Common.
cmd.Flags().StringVar(&f.ClusterIDDeprecated, flagClusterIDDeprecated, "", "Unique identifier of the cluster (deprecated).")
Expand All @@ -78,11 +134,12 @@ func (f *flag) Init(cmd *cobra.Command) {
cmd.Flags().StringVar(&f.Output, flagOutput, "", "File path for storing CRs.")
cmd.Flags().StringVar(&f.Organization, flagOrganization, "", "Workload cluster organization.")
cmd.Flags().StringVar(&f.Owner, flagOwner, "", "Workload cluster owner organization (deprecated).")
cmd.Flags().StringVar(&f.PodsCIDR, flagPodsCIDR, "", "CIDR used for the pods.")
cmd.Flags().StringVar(&f.Release, flagRelease, "", "Workload cluster release.")
cmd.Flags().StringSliceVar(&f.Label, flagLabel, nil, "Workload cluster label.")

// TODO: Make this flag visible when we roll CAPA/EKS out for customers
_ = cmd.Flags().MarkHidden(flagEKS)
_ = cmd.Flags().MarkHidden(flagAWSEKS)

// TODO: Remove the flag completely some time after August 2021
_ = cmd.Flags().MarkDeprecated(flagMasterAZ, "please use --control-plane-az.")
Expand Down Expand Up @@ -124,7 +181,8 @@ func (f *flag) Validate() error {
validProviders := []string{
key.ProviderAWS,
key.ProviderAzure,
key.ProviderVsphere,
key.ProviderOpenStack,
key.ProviderVSphere,
}
isValidProvider := false
for _, p := range validProviders {
Expand Down Expand Up @@ -159,10 +217,10 @@ func (f *flag) Validate() error {
return microerror.Maskf(invalidFlagError, "--%s must only contain alphanumeric characters, and start with a letter", flagName)
}

if f.ControlPlaneSubnet != "" {
matchedSubnet, err := regexp.MatchString("^20|21|22|23|24|25$", f.ControlPlaneSubnet)
if f.AWS.ControlPlaneSubnet != "" {
matchedSubnet, err := regexp.MatchString("^20|21|22|23|24|25$", f.AWS.ControlPlaneSubnet)
if err == nil && !matchedSubnet {
return microerror.Maskf(invalidFlagError, "--%s must be a valid subnet size (20, 21, 22, 23, 24 or 25)", flagControlPlaneSubnet)
return microerror.Maskf(invalidFlagError, "--%s must be a valid subnet size (20, 21, 22, 23, 24 or 25)", flagAWSControlPlaneSubnet)
}
}
}
Expand Down Expand Up @@ -198,6 +256,12 @@ func (f *flag) Validate() error {
if len(f.ControlPlaneAZ) > 1 {
return microerror.Maskf(invalidFlagError, "--%s supports one availability zone only", flagControlPlaneAZ)
}
case key.ProviderOpenStack:
if f.OpenStack.NodeCIDR != "" {
tfussell marked this conversation as resolved.
Show resolved Hide resolved
if !validateCIDR(f.OpenStack.NodeCIDR) {
return microerror.Maskf(invalidFlagError, "--%s must be a valid CIDR", flagOpenStackNodeCIDR)
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions cmd/template/cluster/provider/capa.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func WriteCAPATemplate(ctx context.Context, client k8sclient.Interface, out io.W
Name string
Namespace string
Organization string
PodsCIDR string
ReleaseVersion string
SSHDConfig string
SSOPublicKey string
Expand All @@ -39,6 +40,7 @@ func WriteCAPATemplate(ctx context.Context, client k8sclient.Interface, out io.W
Name: config.Name,
Namespace: key.OrganizationNamespaceFromName(config.Organization),
Organization: config.Organization,
PodsCIDR: config.PodsCIDR,
ReleaseVersion: config.ReleaseVersion,
SSHDConfig: key.NodeSSHDConfigEncoded(),
SSOPublicKey: sshSSOPublicKey,
Expand Down
67 changes: 67 additions & 0 deletions cmd/template/cluster/provider/capo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package provider

import (
"context"
"io"

"github.com/giantswarm/k8sclient/v5/pkg/k8sclient"
"github.com/giantswarm/microerror"

"github.com/giantswarm/kubectl-gs/cmd/template/cluster/provider/templates/openstack"
)

func WriteOpenStackTemplate(ctx context.Context, client k8sclient.Interface, out io.Writer, config ClusterCRsConfig) error {
data := struct {
Description string
KubernetesVersion string
Name string
Namespace string
Organization string
PodsCIDR string
ReleaseVersion string

Cloud string // OPENSTACK_CLOUD
CloudConfig string // <no equivalent env var>
DNSNameservers []string // OPENSTACK_DNS_NAMESERVERS
ExternalNetworkID string // <no equivalent env var>
FailureDomain string // OPENSTACK_FAILURE_DOMAIN
ImageName string // OPENSTACK_IMAGE_NAME
NodeCIDR string // <no equivalent env var>
NodeMachineFlavor string // OPENSTACK_NODE_MACHINE_FLAVOR
RootVolumeDiskSize string // <no equivalent env var>
RootVolumeSourceType string // <no equivalent env var>
RootVolumeSourceUUID string // <no equivalent env var>
}{
Description: config.Description,
KubernetesVersion: "v1.20.9",
Name: config.Name,
Namespace: config.Namespace,
Organization: config.Organization,
PodsCIDR: config.PodsCIDR,
ReleaseVersion: config.ReleaseVersion,

Cloud: config.Cloud,
CloudConfig: config.CloudConfig,
DNSNameservers: config.DNSNameservers,
ExternalNetworkID: config.ExternalNetworkID,
FailureDomain: config.FailureDomain,
ImageName: config.ImageName,
NodeCIDR: config.NodeCIDR,
NodeMachineFlavor: config.NodeMachineFlavor,
RootVolumeDiskSize: config.RootVolumeDiskSize,
RootVolumeSourceType: config.RootVolumeSourceType,
RootVolumeSourceUUID: config.RootVolumeSourceUUID,
}

var templates []templateConfig
for _, t := range openstack.GetTemplates() {
templates = append(templates, templateConfig(t))
}

err := runMutation(ctx, client, data, templates, out)
if err != nil {
return microerror.Mask(err)
}

return nil
}