Skip to content

Commit

Permalink
Support add-on providers in clusterctl
Browse files Browse the repository at this point in the history
  • Loading branch information
Jont828 committed May 16, 2023
1 parent e774ad5 commit fc125b0
Show file tree
Hide file tree
Showing 24 changed files with 162 additions and 29 deletions.
2 changes: 2 additions & 0 deletions cmd/clusterctl/api/v1alpha3/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ func ManifestLabel(name string, providerType ProviderType) string {
return fmt.Sprintf("ipam-%s", name)
case RuntimeExtensionProviderType:
return fmt.Sprintf("runtime-extension-%s", name)
case AddonProviderType:
return fmt.Sprintf("addon-%s", name)
default:
return name
}
Expand Down
9 changes: 8 additions & 1 deletion cmd/clusterctl/api/v1alpha3/provider_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ func (p *Provider) GetProviderType() ProviderType {
InfrastructureProviderType,
ControlPlaneProviderType,
IPAMProviderType,
RuntimeExtensionProviderType:
RuntimeExtensionProviderType,
AddonProviderType:
return t
default:
return ProviderTypeUnknown
Expand Down Expand Up @@ -129,6 +130,10 @@ const (
// runtime extensions.
RuntimeExtensionProviderType = ProviderType("RuntimeExtensionProvider")

// AddonProviderType is the type associated with codebases that provide
// add-on capabilities.
AddonProviderType = ProviderType("AddonProvider")

// ProviderTypeUnknown is used when the type is unknown.
ProviderTypeUnknown = ProviderType("")
)
Expand All @@ -148,6 +153,8 @@ func (p ProviderType) Order() int {
return 4
case RuntimeExtensionProviderType:
return 5
case AddonProviderType:
return 6
default:
return 99
}
Expand Down
21 changes: 18 additions & 3 deletions cmd/clusterctl/client/config/providers_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ const (
KubeKeyK3sControlPlaneProviderName = "kubekey-k3s"
)

// Add-on providers.
const (
HelmAddonProviderName = "helm"
)

// Other.
const (
// ProvidersConfigKey is a constant for finding provider configurations with the ProvidersClient.
Expand Down Expand Up @@ -276,6 +281,7 @@ func (p *providersClient) defaults() []Provider {
url: "https://github.com/canonical/cluster-api-bootstrap-provider-microk8s/releases/latest/bootstrap-components.yaml",
providerType: clusterctlv1.BootstrapProviderType,
},

// ControlPlane providers
&provider{
name: KubeadmControlPlaneProviderName,
Expand All @@ -302,6 +308,13 @@ func (p *providersClient) defaults() []Provider {
url: "https://github.com/kubernetes-sigs/cluster-api-provider-nested/releases/latest/control-plane-components.yaml",
providerType: clusterctlv1.ControlPlaneProviderType,
},

// Add-on providers
&provider{
name: HelmAddonProviderName,
url: "https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm/releases/latest/addon-components.yaml",
providerType: clusterctlv1.AddonProviderType,
},
}

return defaults
Expand Down Expand Up @@ -401,16 +414,18 @@ func validateProvider(r Provider) error {
clusterctlv1.InfrastructureProviderType,
clusterctlv1.ControlPlaneProviderType,
clusterctlv1.IPAMProviderType,
clusterctlv1.RuntimeExtensionProviderType:
clusterctlv1.RuntimeExtensionProviderType,
clusterctlv1.AddonProviderType:
break
default:
return errors.Errorf("invalid provider type. Allowed values are [%s, %s, %s, %s, %s, %s]",
return errors.Errorf("invalid provider type. Allowed values are [%s, %s, %s, %s, %s, %s, %s]",
clusterctlv1.CoreProviderType,
clusterctlv1.BootstrapProviderType,
clusterctlv1.InfrastructureProviderType,
clusterctlv1.ControlPlaneProviderType,
clusterctlv1.IPAMProviderType,
clusterctlv1.RuntimeExtensionProviderType)
clusterctlv1.RuntimeExtensionProviderType,
clusterctlv1.AddonProviderType)
}
return nil
}
8 changes: 8 additions & 0 deletions cmd/clusterctl/client/config/providers_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"testing"

. "github.com/onsi/gomega"
"github.com/onsi/gomega/format"

clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
"sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test"
Expand All @@ -41,6 +42,10 @@ func Test_providers_List(t *testing.T) {
})

defaultsAndZZZ := append(defaults, NewProvider("zzz", "https://zzz/infrastructure-components.yaml", "InfrastructureProvider"))
// AddonProviders are at the end of the list so we want to make sure this InfrastructureProvider is before the AddonProviders.
sort.Slice(defaultsAndZZZ, func(i, j int) bool {
return defaultsAndZZZ[i].Less(defaultsAndZZZ[j])
})

defaultsWithOverride := append([]Provider{}, defaults...)
defaultsWithOverride[0] = NewProvider(defaults[0].Name(), "https://zzz/infrastructure-components.yaml", defaults[0].Type())
Expand Down Expand Up @@ -135,6 +140,9 @@ func Test_providers_List(t *testing.T) {
wantErr: true,
},
}

format.MaxLength = 15000 // This way it doesn't truncate the output on test failure

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
Expand Down
2 changes: 2 additions & 0 deletions cmd/clusterctl/client/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func Test_clusterctlClient_GetProvidersConfig(t *testing.T) {
config.VclusterProviderName,
config.VirtinkProviderName,
config.VSphereProviderName,
config.HelmAddonProviderName,
},
wantErr: false,
},
Expand Down Expand Up @@ -136,6 +137,7 @@ func Test_clusterctlClient_GetProvidersConfig(t *testing.T) {
config.VclusterProviderName,
config.VirtinkProviderName,
config.VSphereProviderName,
config.HelmAddonProviderName,
},
wantErr: false,
},
Expand Down
8 changes: 8 additions & 0 deletions cmd/clusterctl/client/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type DeleteOptions struct {
// RuntimeExtensionProviders and versions (e.g. test:v0.0.1) to delete from the management cluster.
RuntimeExtensionProviders []string

// AddonProviders and versions (e.g. helm:v0.1.0) to delete from the management cluster.
AddonProviders []string

// DeleteAll set for deletion of all the providers.
DeleteAll bool

Expand Down Expand Up @@ -122,6 +125,11 @@ func (c *clusterctlClient) Delete(options DeleteOptions) error {
return err
}

providers, err = appendProviders(providers, clusterctlv1.AddonProviderType, options.AddonProviders...)
if err != nil {
return err
}

for _, provider := range providers {
// Try to detect the namespace where the provider lives
provider.Namespace, err = clusterClient.ProviderInventory().GetProviderNamespace(provider.ProviderName, provider.GetProviderType())
Expand Down
7 changes: 7 additions & 0 deletions cmd/clusterctl/client/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ type InitOptions struct {
// RuntimeExtensionProviders and versions (e.g. test:v0.0.1) to add to the management cluster.
RuntimeExtensionProviders []string

// AddonProviders and versions (e.g. helm:v0.1.0) to add to the management cluster.
AddonProviders []string

// TargetNamespace defines the namespace where the providers should be deployed. If unspecified, each provider
// will be installed in a provider's default namespace.
TargetNamespace string
Expand Down Expand Up @@ -255,6 +258,10 @@ func (c *clusterctlClient) setupInstaller(cluster cluster.Client, options InitOp
return nil, err
}

if err := c.addToInstaller(addOptions, clusterctlv1.AddonProviderType, options.AddonProviders...); err != nil {
return nil, err
}

return installer, nil
}

Expand Down
10 changes: 9 additions & 1 deletion cmd/clusterctl/client/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ type ApplyUpgradeOptions struct {
// RuntimeExtensionProviders instance and versions (e.g. runtime-extension-system/test:v0.0.1) to upgrade to. This field can be used as alternative to Contract.
RuntimeExtensionProviders []string

// AddonProviders instance and versions (e.g. caaph-system/helm:v0.1.0) to upgrade to. This field can be used as alternative to Contract.
AddonProviders []string

// WaitProviders instructs the upgrade apply command to wait till the providers are successfully upgraded.
WaitProviders bool

Expand Down Expand Up @@ -169,7 +172,8 @@ func (c *clusterctlClient) ApplyUpgrade(options ApplyUpgradeOptions) error {
len(options.ControlPlaneProviders) > 0 ||
len(options.InfrastructureProviders) > 0 ||
len(options.IPAMProviders) > 0 ||
len(options.RuntimeExtensionProviders) > 0
len(options.RuntimeExtensionProviders) > 0 ||
len(options.AddonProviders) > 0

opts := cluster.UpgradeOptions{
WaitProviders: options.WaitProviders,
Expand Down Expand Up @@ -207,6 +211,10 @@ func (c *clusterctlClient) ApplyUpgrade(options ApplyUpgradeOptions) error {
if err != nil {
return err
}
upgradeItems, err = addUpgradeItems(clusterClient, upgradeItems, clusterctlv1.AddonProviderType, options.AddonProviders...)
if err != nil {
return err
}

// Execute the upgrade using the custom upgrade items
return clusterClient.ProviderUpgrader().ApplyCustomPlan(opts, upgradeItems...)
Expand Down
12 changes: 10 additions & 2 deletions cmd/clusterctl/cmd/config_repositories_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"path/filepath"
"testing"

"github.com/google/go-cmp/cmp"
. "github.com/onsi/gomega"
)

Expand All @@ -45,11 +46,13 @@ func Test_runGetRepositories(t *testing.T) {
out, err := io.ReadAll(buf)
g.Expect(err).ToNot(HaveOccurred())

var diff string
if val == RepositoriesOutputText {
g.Expect(string(out)).To(Equal(expectedOutputText))
diff = cmp.Diff(expectedOutputText, string(out))
} else if val == RepositoriesOutputYaml {
g.Expect(string(out)).To(Equal(expectedOutputYaml))
diff = cmp.Diff(expectedOutputYaml, string(out))
}
g.Expect(diff).To(BeEmpty()) // Use diff to compare as Gomega output does not actually print the string values on failure
}
})

Expand Down Expand Up @@ -137,6 +140,7 @@ vcd InfrastructureProvider https://github.com/vmware/cluster-a
vcluster InfrastructureProvider https://github.com/loft-sh/cluster-api-provider-vcluster/releases/latest/ infrastructure-components.yaml
virtink InfrastructureProvider https://github.com/smartxworks/cluster-api-provider-virtink/releases/latest/ infrastructure-components.yaml
vsphere InfrastructureProvider https://github.com/kubernetes-sigs/cluster-api-provider-vsphere/releases/latest/ infrastructure-components.yaml
helm AddonProvider https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm/releases/latest/ addon-components.yaml
`

var expectedOutputYaml = `- File: core_components.yaml
Expand Down Expand Up @@ -287,4 +291,8 @@ var expectedOutputYaml = `- File: core_components.yaml
Name: vsphere
ProviderType: InfrastructureProvider
URL: https://github.com/kubernetes-sigs/cluster-api-provider-vsphere/releases/latest/
- File: addon-components.yaml
Name: helm
ProviderType: AddonProvider
URL: https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm/releases/latest/
`
11 changes: 8 additions & 3 deletions cmd/clusterctl/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type deleteOptions struct {
infrastructureProviders []string
ipamProviders []string
runtimeExtensionProviders []string
addonProviders []string
includeNamespace bool
includeCRDs bool
deleteAll bool
Expand Down Expand Up @@ -109,6 +110,8 @@ func init() {
"IPAM providers and versions (e.g. infoblox:v0.0.1) to delete from the management cluster")
deleteCmd.Flags().StringSliceVar(&dd.runtimeExtensionProviders, "runtime-extension", nil,
"Runtime extension providers and versions (e.g. test:v0.0.1) to delete from the management cluster")
deleteCmd.Flags().StringSliceVar(&dd.addonProviders, "addon", nil,
"Add-on providers and versions (e.g. helm:v0.1.0) to delete from the management cluster")

deleteCmd.Flags().BoolVar(&dd.deleteAll, "all", false,
"Force deletion of all the providers")
Expand All @@ -127,14 +130,15 @@ func runDelete() error {
(len(dd.controlPlaneProviders) > 0) ||
(len(dd.infrastructureProviders) > 0) ||
(len(dd.ipamProviders) > 0) ||
(len(dd.runtimeExtensionProviders) > 0)
(len(dd.runtimeExtensionProviders) > 0) ||
(len(dd.addonProviders) > 0)

if dd.deleteAll && hasProviderNames {
return errors.New("The --all flag can't be used in combination with --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension")
return errors.New("The --all flag can't be used in combination with --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon")
}

if !dd.deleteAll && !hasProviderNames {
return errors.New("At least one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension should be specified or the --all flag should be set")
return errors.New("At least one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be specified or the --all flag should be set")
}

return c.Delete(client.DeleteOptions{
Expand All @@ -147,6 +151,7 @@ func runDelete() error {
ControlPlaneProviders: dd.controlPlaneProviders,
IPAMProviders: dd.ipamProviders,
RuntimeExtensionProviders: dd.runtimeExtensionProviders,
AddonProviders: dd.addonProviders,
DeleteAll: dd.deleteAll,
})
}
22 changes: 16 additions & 6 deletions cmd/clusterctl/cmd/generate_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type generateProvidersOptions struct {
infrastructureProvider string
ipamProvider string
runtimeExtensionProvider string
addonProvider string
targetNamespace string
textOutput bool
raw bool
Expand Down Expand Up @@ -89,6 +90,8 @@ func init() {
"IPAM provider and version (e.g. infoblox:v0.0.1)")
generateProviderCmd.Flags().StringVar(&gpo.runtimeExtensionProvider, "runtime-extension", "",
"Runtime extension provider and version (e.g. test:v0.0.1)")
generateProviderCmd.Flags().StringVar(&gpo.addonProvider, "addon", "",
"Add-on provider and version (e.g. helm:v0.1.0)")
generateProviderCmd.Flags().StringVarP(&gpo.targetNamespace, "target-namespace", "n", "",
"The target namespace where the provider should be deployed. If unspecified, the components default namespace is used.")
generateProviderCmd.Flags().BoolVar(&gpo.textOutput, "describe", false,
Expand Down Expand Up @@ -134,41 +137,48 @@ func parseProvider() (string, clusterctlv1.ProviderType, error) {
providerType := clusterctlv1.CoreProviderType
if gpo.bootstrapProvider != "" {
if providerName != "" {
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension should be set")
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be set")
}
providerName = gpo.bootstrapProvider
providerType = clusterctlv1.BootstrapProviderType
}
if gpo.controlPlaneProvider != "" {
if providerName != "" {
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension should be set")
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be set")
}
providerName = gpo.controlPlaneProvider
providerType = clusterctlv1.ControlPlaneProviderType
}
if gpo.infrastructureProvider != "" {
if providerName != "" {
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension should be set")
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be set")
}
providerName = gpo.infrastructureProvider
providerType = clusterctlv1.InfrastructureProviderType
}
if gpo.ipamProvider != "" {
if providerName != "" {
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension should be set")
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be set")
}
providerName = gpo.ipamProvider
providerType = clusterctlv1.IPAMProviderType
}
if gpo.runtimeExtensionProvider != "" {
if providerName != "" {
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension should be set")
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be set")
}
providerName = gpo.runtimeExtensionProvider
providerType = clusterctlv1.RuntimeExtensionProviderType
}
if gpo.addonProvider != "" {
if providerName != "" {
return "", "", errors.New("only one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be set")
}
providerName = gpo.addonProvider
providerType = clusterctlv1.AddonProviderType
}
if providerName == "" {
return "", "", errors.New("at least one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension should be set")
return "", "", errors.New("at least one of --core, --bootstrap, --control-plane, --infrastructure, --ipam, --extension, --addon should be set")
}

return providerName, providerType, nil
Expand Down
Loading

0 comments on commit fc125b0

Please sign in to comment.