From e6cfe949253fcc43ec5fd4f3d1b7aac2730b2001 Mon Sep 17 00:00:00 2001 From: tharun Date: Thu, 13 Jan 2022 17:18:02 +0530 Subject: [PATCH] introduce version check validation for generate provider command Signed-off-by: tharun --- cmd/clusterctl/client/client.go | 3 ++ cmd/clusterctl/client/client_test.go | 4 +++ cmd/clusterctl/client/config.go | 40 +++++++++++++++++++++++++ cmd/clusterctl/cmd/generate_provider.go | 2 +- 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/cmd/clusterctl/client/client.go b/cmd/clusterctl/client/client.go index 7e85b2a35b9f..9573ed138e79 100644 --- a/cmd/clusterctl/client/client.go +++ b/cmd/clusterctl/client/client.go @@ -75,6 +75,9 @@ type Client interface { // DescribeCluster returns the object tree representing the status of a Cluster API cluster. DescribeCluster(options DescribeClusterOptions) (*tree.ObjectTree, error) + // GenerateProvider validates the input provider version is compatible with the version of clusterctl and returns the provider components. + GenerateProvider(providerName string, providerType clusterctlv1.ProviderType, options ComponentsOptions) (Components, error) + // AlphaClient is an Interface for alpha features in clusterctl AlphaClient } diff --git a/cmd/clusterctl/client/client_test.go b/cmd/clusterctl/client/client_test.go index 752a17d2640a..2398260cdfbc 100644 --- a/cmd/clusterctl/client/client_test.go +++ b/cmd/clusterctl/client/client_test.go @@ -80,6 +80,10 @@ func (f fakeClient) GetProviderComponents(provider string, providerType clusterc return f.internalClient.GetProviderComponents(provider, providerType, options) } +func (f fakeClient) GenerateProvider(provider string, providerType clusterctlv1.ProviderType, options ComponentsOptions) (Components, error) { + return f.internalClient.GenerateProvider(provider, providerType, options) +} + func (f fakeClient) GetClusterTemplate(options GetClusterTemplateOptions) (Template, error) { return f.internalClient.GetClusterTemplate(options) } diff --git a/cmd/clusterctl/client/config.go b/cmd/clusterctl/client/config.go index 3c79fe7bfce6..6d45396dee04 100644 --- a/cmd/clusterctl/client/config.go +++ b/cmd/clusterctl/client/config.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/util/version" "k8s.io/utils/pointer" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" "sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster" "sigs.k8s.io/cluster-api/cmd/clusterctl/client/repository" @@ -54,6 +55,45 @@ func (c *clusterctlClient) GetProviderComponents(provider string, providerType c return components, nil } +func (c *clusterctlClient) GenerateProvider(providerName string, providerType clusterctlv1.ProviderType, options ComponentsOptions) (Components, error) { + + providerName, providerVersion, err := parseProviderName(providerName) + if err != nil { + return nil, err + } + + // Gets the provider configuration (that includes the location of the provider repository) + providerConfig, err := c.configClient.Providers().Get(providerName, providerType) + if err != nil { + return nil, err + } + + // Get a client for the provider repository and read the provider components; + // during the process, provider components will be processed performing variable substitution, customization of target + // namespace etc. + // Currently we are not supporting custom yaml processors for the provider + // components. So we revert to using the default SimpleYamlProcessor. + repositoryClientFactory, err := c.repositoryClientFactory(RepositoryClientFactoryInput{Provider: providerConfig}) + if err != nil { + return nil, err + } + + latestMetadata, err := repositoryClientFactory.Metadata(providerVersion).Get() + if err != nil { + return nil, err + } + // Gets the contract for the current release. + currentVersion, err := version.ParseSemantic(providerVersion) + if err != nil { + return nil, errors.Wrapf(err, "failed to parse current version for the %s provider", providerName) + } + releaseSeries := latestMetadata.GetReleaseSeriesForVersion(currentVersion) + if releaseSeries.Contract != clusterv1.GroupVersion.Version { + return nil, errors.Errorf("current version of clusterctl is only compatible with %s providers, detected %s for provider %s", clusterv1.GroupVersion.Version, releaseSeries.Contract, providerVersion) + } + return c.GetProviderComponents(providerName, providerType, options) +} + // ReaderSourceOptions define the options to be used when reading a template // from an arbitrary reader. type ReaderSourceOptions struct { diff --git a/cmd/clusterctl/cmd/generate_provider.go b/cmd/clusterctl/cmd/generate_provider.go index 0816cdda8f5a..ed70beb03e08 100644 --- a/cmd/clusterctl/cmd/generate_provider.go +++ b/cmd/clusterctl/cmd/generate_provider.go @@ -107,7 +107,7 @@ func runGenerateProviderComponents() error { SkipTemplateProcess: gpo.raw, } - components, err := c.GetProviderComponents(providerName, providerType, options) + components, err := c.GenerateProvider(providerName, providerType, options) if err != nil { return err }