From c16aa2e352bb7cf1dbd943d0fc5258ebd2c1129a Mon Sep 17 00:00:00 2001 From: zerospiel Date: Thu, 24 Oct 2024 15:31:22 +0200 Subject: [PATCH] Update templates with compatibility attributes * added core CAPI contracts * added providertemplates capi and crds versions * added compatibility to the clustertemplates * runtime: added support for multiproviders via multi-annotations to allow set provider crds contracts separately per provider only for clustertemplates --- api/v1alpha1/clustertemplate_types.go | 29 +++++---- api/v1alpha1/providertemplate_types.go | 17 ++--- api/v1alpha1/servicetemplate_types.go | 2 +- api/v1alpha1/templates_common.go | 56 ++++++++++------- api/v1alpha1/zz_generated.deepcopy.go | 8 +-- internal/controller/management_controller.go | 2 +- internal/controller/template_controller.go | 32 +++++----- .../controller/template_controller_test.go | 63 ++++++++++++------- templates/cluster/aws-eks/Chart.yaml | 1 + templates/cluster/aws-hosted-cp/Chart.yaml | 3 + .../cluster/aws-standalone-cp/Chart.yaml | 3 + templates/cluster/azure-hosted-cp/Chart.yaml | 3 + .../cluster/azure-standalone-cp/Chart.yaml | 3 + .../cluster/vsphere-hosted-cp/Chart.yaml | 3 + .../cluster/vsphere-standalone-cp/Chart.yaml | 3 + .../cluster-api-provider-aws/Chart.yaml | 3 + .../cluster-api-provider-azure/Chart.yaml | 1 + .../cluster-api-provider-vsphere/Chart.yaml | 1 + templates/provider/cluster-api/Chart.yaml | 4 ++ .../hmc.mirantis.com_clustertemplates.yaml | 44 ++++++------- templates/provider/k0smotron/Chart.yaml | 3 + 21 files changed, 171 insertions(+), 113 deletions(-) diff --git a/api/v1alpha1/clustertemplate_types.go b/api/v1alpha1/clustertemplate_types.go index 25da38ed9..9d7c16b0f 100644 --- a/api/v1alpha1/clustertemplate_types.go +++ b/api/v1alpha1/clustertemplate_types.go @@ -30,8 +30,14 @@ const ( // ClusterTemplateSpec defines the desired state of ClusterTemplate type ClusterTemplateSpec struct { - Helm HelmSpec `json:"helm"` - CAPIContracts CompatibilityContracts `json:"capiContracts,omitempty"` + Helm HelmSpec `json:"helm"` + // Holds key-value pairs with compatibility [contract versions], + // where the key is the name of the provider, + // and the value is the provider contract version + // required to be supported by the provider. + // + // [contract versions]: https://cluster-api.sigs.k8s.io/developer/providers/contracts + ProviderContracts CompatibilityContracts `json:"providerContracts,omitempty"` // Kubernetes exact version in the SemVer format provided by this ClusterTemplate. KubernetesVersion string `json:"k8sVersion,omitempty"` // Providers represent required CAPI providers with supported contract versions. @@ -42,7 +48,13 @@ type ClusterTemplateSpec struct { // ClusterTemplateStatus defines the observed state of ClusterTemplate type ClusterTemplateStatus struct { - CAPIContracts CompatibilityContracts `json:"capiContracts,omitempty"` + // Holds key-value pairs with compatibility [contract versions], + // where the key is the name of the provider, + // and the value is the provider contract version + // required to be supported by the provider. + // + // [contract versions]: https://cluster-api.sigs.k8s.io/developer/providers/contracts + ProviderContracts CompatibilityContracts `json:"providerContracts,omitempty"` // Kubernetes exact version in the SemVer format provided by this ClusterTemplate. KubernetesVersion string `json:"k8sVersion,omitempty"` // Providers represent required CAPI providers with supported contract versions @@ -55,14 +67,14 @@ type ClusterTemplateStatus struct { // FillStatusWithProviders sets the status of the template with providers // either from the spec or from the given annotations. func (t *ClusterTemplate) FillStatusWithProviders(annotations map[string]string) error { - t.Status.Providers = getProvidersList(t, annotations) + t.Status.Providers = getProvidersList(t.Spec.Providers, annotations) - contractsStatus, err := getCAPIContracts(t, annotations) + contractsStatus, err := getCAPIContracts(t.Kind, t.Spec.ProviderContracts, annotations) if err != nil { return fmt.Errorf("failed to get CAPI contract versions for ClusterTemplate %s/%s: %v", t.GetNamespace(), t.GetName(), err) } - t.Status.CAPIContracts = contractsStatus + t.Status.ProviderContracts = contractsStatus kversion := annotations[ChartAnnotationKubernetesVersion] if t.Spec.KubernetesVersion != "" { @@ -81,11 +93,6 @@ func (t *ClusterTemplate) FillStatusWithProviders(annotations map[string]string) return nil } -// GetContracts returns .spec.capiContracts of the Template. -func (t *ClusterTemplate) GetContracts() CompatibilityContracts { - return t.Spec.CAPIContracts -} - // GetSpecProviders returns .spec.providers of the Template. func (t *ClusterTemplate) GetSpecProviders() Providers { return t.Spec.Providers diff --git a/api/v1alpha1/providertemplate_types.go b/api/v1alpha1/providertemplate_types.go index ad102bfcf..a9982f674 100644 --- a/api/v1alpha1/providertemplate_types.go +++ b/api/v1alpha1/providertemplate_types.go @@ -20,6 +20,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// ProviderTemplateKind denotes the providertemplate resource Kind. +const ProviderTemplateKind = "ProviderTemplate" + // ProviderTemplateSpec defines the desired state of ProviderTemplate type ProviderTemplateSpec struct { Helm HelmSpec `json:"helm,omitempty"` @@ -43,9 +46,9 @@ type ProviderTemplateStatus struct { // FillStatusWithProviders sets the status of the template with providers // either from the spec or from the given annotations. func (t *ProviderTemplate) FillStatusWithProviders(annotations map[string]string) error { - t.Status.Providers = getProvidersList(t, annotations) + t.Status.Providers = getProvidersList(t.Spec.Providers, annotations) - contractsStatus, err := getCAPIContracts(t, annotations) + contractsStatus, err := getCAPIContracts(t.Kind, t.Spec.CAPIContracts, annotations) if err != nil { return fmt.Errorf("failed to get CAPI contract versions for ProviderTemplate %s: %v", t.GetName(), err) } @@ -55,16 +58,6 @@ func (t *ProviderTemplate) FillStatusWithProviders(annotations map[string]string return nil } -// GetContracts returns .spec.capiContracts of the Template. -func (t *ProviderTemplate) GetContracts() CompatibilityContracts { - return t.Spec.CAPIContracts -} - -// GetSpecProviders returns .spec.providers of the Template. -func (t *ProviderTemplate) GetSpecProviders() Providers { - return t.Spec.Providers -} - // GetHelmSpec returns .spec.helm of the Template. func (t *ProviderTemplate) GetHelmSpec() *HelmSpec { return &t.Spec.Helm diff --git a/api/v1alpha1/servicetemplate_types.go b/api/v1alpha1/servicetemplate_types.go index ddca28629..97d52fb3e 100644 --- a/api/v1alpha1/servicetemplate_types.go +++ b/api/v1alpha1/servicetemplate_types.go @@ -51,7 +51,7 @@ type ServiceTemplateStatus struct { // FillStatusWithProviders sets the status of the template with providers // either from the spec or from the given annotations. func (t *ServiceTemplate) FillStatusWithProviders(annotations map[string]string) error { - t.Status.Providers = getProvidersList(t, annotations) + t.Status.Providers = getProvidersList(t.Spec.Providers, annotations) kconstraint := annotations[ChartAnnotationKubernetesConstraint] if t.Spec.KubernetesConstraint != "" { diff --git a/api/v1alpha1/templates_common.go b/api/v1alpha1/templates_common.go index 98c840af6..6bbcb5404 100644 --- a/api/v1alpha1/templates_common.go +++ b/api/v1alpha1/templates_common.go @@ -77,21 +77,22 @@ type TemplateValidationStatus struct { Valid bool `json:"valid"` } -func getProvidersList(providersGetter interface{ GetSpecProviders() Providers }, annotations map[string]string) Providers { +func getProvidersList(providers Providers, annotations map[string]string) Providers { const multiProviderSeparator = "," - if spec := providersGetter.GetSpecProviders(); len(spec) > 0 { - slices.Sort(spec) - return slices.Compact(spec) + if len(providers) > 0 { + res := slices.Clone(providers) + slices.Sort(res) + return slices.Compact(res) } - providers := annotations[ChartAnnotationProviderName] - if len(providers) == 0 { + providersFromAnno := annotations[ChartAnnotationProviderName] + if len(providersFromAnno) == 0 { return Providers{} } var ( - splitted = strings.Split(providers, multiProviderSeparator) + splitted = strings.Split(providersFromAnno, multiProviderSeparator) pstatus = make([]string, 0, len(splitted)) ) for _, v := range splitted { @@ -104,23 +105,30 @@ func getProvidersList(providersGetter interface{ GetSpecProviders() Providers }, return slices.Compact(pstatus) } -func getCAPIContracts(contractsGetter interface{ GetContracts() CompatibilityContracts }, annotations map[string]string) (_ CompatibilityContracts, merr error) { +func getCAPIContracts(kind string, contracts CompatibilityContracts, annotations map[string]string) (_ CompatibilityContracts, merr error) { contractsStatus := make(map[string]string) // spec preceding the annos - if contracts := contractsGetter.GetContracts(); len(contracts) > 0 { - for capiContract, providerContract := range contracts { - if !isCAPIContractSingleVersion(capiContract) { - merr = errors.Join(merr, fmt.Errorf("incorrect CAPI contract version %s in the spec", capiContract)) + if len(contracts) > 0 { + for key, providerContract := range contracts { // key is either CAPI contract version or the name of a provider + // for provider templates the key must be contract version + // for cluster template the key must be the name of a provider + if kind == ProviderTemplateKind && !isCAPIContractSingleVersion(key) { + merr = errors.Join(merr, fmt.Errorf("incorrect CAPI contract version %s in the spec", key)) continue } - if providerContract != "" && !isCAPIContractVersion(providerContract) { // special case for either CAPI or deliberately set empty - merr = errors.Join(merr, fmt.Errorf("incorrect provider contract version %s in the spec for the %s CAPI contract version", providerContract, capiContract)) + // for provider templates it is allowed to have a list of contract versions, or be empty for the core CAPI case + // for cluster templates the contract versions should be single + if kind == ProviderTemplateKind && providerContract != "" && !isCAPIContractVersion(providerContract) { + merr = errors.Join(merr, fmt.Errorf("incorrect provider contract version %s in the spec for the %s CAPI contract version", providerContract, key)) + continue + } else if kind == ClusterTemplateKind && !isCAPIContractSingleVersion(providerContract) { + merr = errors.Join(merr, fmt.Errorf("incorrect provider contract version %s in the spec for the %s provider name", providerContract, key)) continue } - contractsStatus[capiContract] = providerContract + contractsStatus[key] = providerContract } return contractsStatus, merr @@ -132,19 +140,23 @@ func getCAPIContracts(contractsGetter interface{ GetContracts() CompatibilityCon continue } - capiContract := k[idx+len(chartAnnoCAPIPrefix):] - if isCAPIContractSingleVersion(capiContract) { - if providerContract == "" { // special case for either CAPI or deliberately set empty - contractsStatus[capiContract] = "" + capiContractOrProviderName := k[idx+len(chartAnnoCAPIPrefix):] + if (kind == ProviderTemplateKind && isCAPIContractSingleVersion(capiContractOrProviderName)) || + (kind == ClusterTemplateKind && (strings.HasPrefix(capiContractOrProviderName, "bootstrap-") || + strings.HasPrefix(capiContractOrProviderName, "control-plane-") || + strings.HasPrefix(capiContractOrProviderName, "infrastructure-"))) { + if kind == ProviderTemplateKind && providerContract == "" { // special case for the core CAPI + contractsStatus[capiContractOrProviderName] = "" continue } - if isCAPIContractVersion(providerContract) { - contractsStatus[capiContract] = providerContract + if (kind == ProviderTemplateKind && isCAPIContractVersion(providerContract)) || + (kind == ClusterTemplateKind && isCAPIContractSingleVersion(providerContract)) { + contractsStatus[capiContractOrProviderName] = providerContract } else { // since we parsed capi contract version, // then treat the provider's invalid version as an error - merr = errors.Join(merr, fmt.Errorf("incorrect provider contract version %s given for the %s CAPI contract version annotation", providerContract, k)) + merr = errors.Join(merr, fmt.Errorf("incorrect provider contract version %s given for the %s annotation", providerContract, k)) } } } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 01b001861..0e7794334 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -188,8 +188,8 @@ func (in *ClusterTemplateList) DeepCopyObject() runtime.Object { func (in *ClusterTemplateSpec) DeepCopyInto(out *ClusterTemplateSpec) { *out = *in in.Helm.DeepCopyInto(&out.Helm) - if in.CAPIContracts != nil { - in, out := &in.CAPIContracts, &out.CAPIContracts + if in.ProviderContracts != nil { + in, out := &in.ProviderContracts, &out.ProviderContracts *out = make(CompatibilityContracts, len(*in)) for key, val := range *in { (*out)[key] = val @@ -215,8 +215,8 @@ func (in *ClusterTemplateSpec) DeepCopy() *ClusterTemplateSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterTemplateStatus) DeepCopyInto(out *ClusterTemplateStatus) { *out = *in - if in.CAPIContracts != nil { - in, out := &in.CAPIContracts, &out.CAPIContracts + if in.ProviderContracts != nil { + in, out := &in.ProviderContracts, &out.ProviderContracts *out = make(CompatibilityContracts, len(*in)) for key, val := range *in { (*out)[key] = val diff --git a/internal/controller/management_controller.go b/internal/controller/management_controller.go index b2e906e5f..6c9728810 100644 --- a/internal/controller/management_controller.go +++ b/internal/controller/management_controller.go @@ -438,7 +438,7 @@ func updateComponentsStatus( *providers = slices.Compact(*providers) for _, v := range templateProviders { - capiContracts[v] = templateContracts // TODO (zerospiel): not sure whether it's okay to overwrite if the same provider + capiContracts[v] = templateContracts } } } diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index 8310c6ada..c12a36e8e 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -341,8 +341,9 @@ func (r *ClusterTemplateReconciler) validateCompatibilityAttrs(ctx context.Conte exposedProviders, requiredProviders := management.Status.AvailableProviders, template.Status.Providers - ctrl.LoggerFrom(ctx).V(1).Info("providers to check", "exposed", exposedProviders, "required", requiredProviders, - "exposed_capi_contract_versions", management.Status.CAPIContracts, "required_capi_contract_versions", template.Status.CAPIContracts) + l := ctrl.LoggerFrom(ctx) + l.V(1).Info("providers to check", "exposed", exposedProviders, "required", requiredProviders, + "exposed_capi_contract_versions", management.Status.CAPIContracts, "required_provider_contract_versions", template.Status.ProviderContracts) var ( merr error @@ -354,26 +355,25 @@ func (r *ClusterTemplateReconciler) validateCompatibilityAttrs(ctx context.Conte missing = append(missing, v) continue } + } + + // already validated contract versions format + for providerName, requiredContract := range template.Status.ProviderContracts { + l.V(1).Info("validating contracts", "exposed_provider_capi_contracts", management.Status.CAPIContracts, "required_provider_name", providerName) - providerCAPIContracts, ok := management.Status.CAPIContracts[v] + providerCAPIContracts, ok := management.Status.CAPIContracts[providerName] // capi_version: provider_version(s) if !ok { continue // both the provider and cluster templates contract versions must be set for the validation } - // already validated contract versions format - for capi, providerReq := range template.Status.CAPIContracts { - providerSupported, ok := providerCAPIContracts[capi] - if !ok { - // TODO (zerospiel): should we also consider it as a missing error? capi req from cluster missing in provider tpl - continue - } + var exposedProviderContracts []string + for _, supportedVersions := range providerCAPIContracts { + exposedProviderContracts = append(exposedProviderContracts, strings.Split(supportedVersions, "_")...) + } - providerSupportedContracts := strings.Split(providerSupported, "_") - for _, v := range strings.Split(providerReq, "_") { - if !slices.Contains(providerSupportedContracts, v) { - nonSatisfying = append(nonSatisfying, v) - } - } + l.V(1).Info("checking if contract is supported", "exposed_provider_contracts_final_list", exposedProviderContracts, "required_contract", requiredContract) + if !slices.Contains(exposedProviderContracts, requiredContract) { + nonSatisfying = append(nonSatisfying, "provider "+providerName+" does not support "+requiredContract) } } diff --git a/internal/controller/template_controller_test.go b/internal/controller/template_controller_test.go index dc1c38991..1669ff343 100644 --- a/internal/controller/template_controller_test.go +++ b/internal/controller/template_controller_test.go @@ -198,12 +198,15 @@ var _ = Describe("Template Controller", func() { It("should successfully validate cluster templates providers compatibility attributes", func() { const ( - clusterTemplateName = "cluster-template-test-name" - mgmtName = hmcmirantiscomv1alpha1.ManagementName - someProviderName = "test-provider-name" - someRequiredContract = "v1beta2" - someExposedContract = "v1beta1_v1beta2" - capiVersion = "v1beta1" + clusterTemplateName = "cluster-template-test-name" + mgmtName = hmcmirantiscomv1alpha1.ManagementName + someProviderName = "test-provider-name" + otherProviderName = "test-provider-name-other" + someRequiredContract = "v1beta2" + otherRequiredContract = "v1beta1" + someExposedContract = "v1beta1_v1beta2" + otherExposedContract = "v1beta1" + capiVersion = "v1beta1" timeout = time.Second * 10 interval = time.Millisecond * 250 @@ -217,9 +220,9 @@ var _ = Describe("Template Controller", func() { Namespace: metav1.NamespaceDefault, }, Spec: hmcmirantiscomv1alpha1.ClusterTemplateSpec{ - Helm: helmSpec, - Providers: []string{someProviderName}, - CAPIContracts: hmcmirantiscomv1alpha1.CompatibilityContracts{capiVersion: someRequiredContract}, + Helm: helmSpec, + Providers: []string{someProviderName, otherProviderName}, + ProviderContracts: hmcmirantiscomv1alpha1.CompatibilityContracts{someProviderName: someRequiredContract, otherProviderName: otherRequiredContract}, }, } Expect(k8sClient.Create(ctx, clusterTemplate)).To(Succeed()) @@ -230,18 +233,24 @@ var _ = Describe("Template Controller", func() { return err } - if l := len(clusterTemplate.Spec.Providers); l != 1 { - return fmt.Errorf("expected .spec.providers length to be exactly 1, got %d", l) + if l := len(clusterTemplate.Spec.Providers); l != 2 { + return fmt.Errorf("expected .spec.providers length to be exactly 2, got %d", l) } - if l := len(clusterTemplate.Spec.CAPIContracts); l != 1 { - return fmt.Errorf("expected .spec.capiContracts length to be exactly 1, got %d", l) + if l := len(clusterTemplate.Spec.ProviderContracts); l != 2 { + return fmt.Errorf("expected .spec.capiContracts length to be exactly 2, got %d", l) } if v := clusterTemplate.Spec.Providers[0]; v != someProviderName { return fmt.Errorf("expected .spec.providers[0] to be %s, got %s", someProviderName, v) } - if v := clusterTemplate.Spec.CAPIContracts[capiVersion]; v != someRequiredContract { - return fmt.Errorf("expected .spec.capiContracts[%s] to be %s, got %s", capiVersion, someRequiredContract, v) + if v := clusterTemplate.Spec.Providers[1]; v != otherProviderName { + return fmt.Errorf("expected .spec.providers[1] to be %s, got %s", otherProviderName, v) + } + if v := clusterTemplate.Spec.ProviderContracts[someProviderName]; v != someRequiredContract { + return fmt.Errorf("expected .spec.capiContracts[%s] to be %s, got %s", someProviderName, someRequiredContract, v) + } + if v := clusterTemplate.Spec.ProviderContracts[otherProviderName]; v != otherRequiredContract { + return fmt.Errorf("expected .spec.capiContracts[%s] to be %s, got %s", otherProviderName, otherRequiredContract, v) } return nil @@ -256,8 +265,8 @@ var _ = Describe("Template Controller", func() { } Expect(k8sClient.Create(ctx, mgmt)).To(Succeed()) mgmt.Status = hmcmirantiscomv1alpha1.ManagementStatus{ - AvailableProviders: []string{someProviderName}, - CAPIContracts: map[string]hmcmirantiscomv1alpha1.CompatibilityContracts{someProviderName: {capiVersion: someExposedContract}}, + AvailableProviders: []string{someProviderName, otherProviderName}, + CAPIContracts: map[string]hmcmirantiscomv1alpha1.CompatibilityContracts{someProviderName: {capiVersion: someExposedContract}, otherProviderName: {capiVersion: otherExposedContract}}, } Expect(k8sClient.Status().Update(ctx, mgmt)).To(Succeed()) @@ -267,19 +276,25 @@ var _ = Describe("Template Controller", func() { return err } - if l := len(mgmt.Status.AvailableProviders); l != 1 { - return fmt.Errorf("expected .status.availableProviders length to be exactly 1, got %d", l) + if l := len(mgmt.Status.AvailableProviders); l != 2 { + return fmt.Errorf("expected .status.availableProviders length to be exactly 2, got %d", l) } - if l := len(mgmt.Status.CAPIContracts); l != 1 { - return fmt.Errorf("expected .status.capiContracts length to be exactly 1, got %d", l) + if l := len(mgmt.Status.CAPIContracts); l != 2 { + return fmt.Errorf("expected .status.capiContracts length to be exactly 2, got %d", l) } if v := mgmt.Status.AvailableProviders[0]; v != someProviderName { return fmt.Errorf("expected .status.availableProviders[0] to be %s, got %s", someProviderName, v) } + if v := mgmt.Status.AvailableProviders[1]; v != otherProviderName { + return fmt.Errorf("expected .status.availableProviders[1] to be %s, got %s", otherProviderName, v) + } if v := mgmt.Status.CAPIContracts[someProviderName]; v[capiVersion] != someExposedContract { return fmt.Errorf("expected .status.capiContracts[%s][%s] to be %s, got %s", someProviderName, capiVersion, someExposedContract, v[capiVersion]) } + if v := mgmt.Status.CAPIContracts[otherProviderName]; v[capiVersion] != otherExposedContract { + return fmt.Errorf("expected .status.capiContracts[%s][%s] to be %s, got %s", otherProviderName, capiVersion, otherExposedContract, v[capiVersion]) + } return nil }).WithTimeout(timeout).WithPolling(interval).Should(Succeed()) @@ -298,10 +313,10 @@ var _ = Describe("Template Controller", func() { By("Having the valid cluster template status") Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterTemplate), clusterTemplate)).To(Succeed()) Expect(clusterTemplate.Status.Valid && clusterTemplate.Status.ValidationError == "").To(BeTrue()) - Expect(clusterTemplate.Status.Providers).To(HaveLen(1)) - Expect(clusterTemplate.Status.CAPIContracts).To(HaveLen(1)) + Expect(clusterTemplate.Status.Providers).To(HaveLen(2)) + Expect(clusterTemplate.Status.ProviderContracts).To(HaveLen(2)) Expect(clusterTemplate.Status.Providers[0]).To(Equal(someProviderName)) - Expect(clusterTemplate.Status.CAPIContracts).To(BeEquivalentTo(map[string]string{capiVersion: someRequiredContract})) + Expect(clusterTemplate.Status.ProviderContracts).To(BeEquivalentTo(map[string]string{otherProviderName: otherRequiredContract, someProviderName: someRequiredContract})) By("Removing the created objects") Expect(k8sClient.Delete(ctx, mgmt)).To(Succeed()) diff --git a/templates/cluster/aws-eks/Chart.yaml b/templates/cluster/aws-eks/Chart.yaml index 610a5cc4f..f0707095d 100644 --- a/templates/cluster/aws-eks/Chart.yaml +++ b/templates/cluster/aws-eks/Chart.yaml @@ -9,3 +9,4 @@ type: application version: 0.0.2 annotations: cluster.x-k8s.io/provider: infrastructure-aws + cluster.x-k8s.io/infrastructure-aws: v1beta2 diff --git a/templates/cluster/aws-hosted-cp/Chart.yaml b/templates/cluster/aws-hosted-cp/Chart.yaml index 0d6656d0f..50588dac0 100644 --- a/templates/cluster/aws-hosted-cp/Chart.yaml +++ b/templates/cluster/aws-hosted-cp/Chart.yaml @@ -15,3 +15,6 @@ version: 0.0.2 appVersion: "v1.31.1+k0s.1" annotations: cluster.x-k8s.io/provider: infrastructure-aws, control-plane-k0smotron, bootstrap-k0smotron + cluster.x-k8s.io/bootstrap-k0smotron: v1beta1 + cluster.x-k8s.io/control-plane-k0smotron: v1beta1 + cluster.x-k8s.io/infrastructure-aws: v1beta2 diff --git a/templates/cluster/aws-standalone-cp/Chart.yaml b/templates/cluster/aws-standalone-cp/Chart.yaml index beebc934b..94b9847fc 100644 --- a/templates/cluster/aws-standalone-cp/Chart.yaml +++ b/templates/cluster/aws-standalone-cp/Chart.yaml @@ -14,3 +14,6 @@ version: 0.0.2 appVersion: "v1.31.1+k0s.1" annotations: cluster.x-k8s.io/provider: infrastructure-aws, control-plane-k0smotron, bootstrap-k0smotron + cluster.x-k8s.io/bootstrap-k0smotron: v1beta1 + cluster.x-k8s.io/control-plane-k0smotron: v1beta1 + cluster.x-k8s.io/infrastructure-aws: v1beta2 diff --git a/templates/cluster/azure-hosted-cp/Chart.yaml b/templates/cluster/azure-hosted-cp/Chart.yaml index b6c8ff28c..77dbeac0e 100644 --- a/templates/cluster/azure-hosted-cp/Chart.yaml +++ b/templates/cluster/azure-hosted-cp/Chart.yaml @@ -15,3 +15,6 @@ version: 0.0.3 appVersion: "v1.31.1+k0s.1" annotations: cluster.x-k8s.io/provider: infrastructure-azure, control-plane-k0smotron, bootstrap-k0smotron + cluster.x-k8s.io/bootstrap-k0smotron: v1beta1 + cluster.x-k8s.io/control-plane-k0smotron: v1beta1 + cluster.x-k8s.io/infrastructure-azure: v1beta1 diff --git a/templates/cluster/azure-standalone-cp/Chart.yaml b/templates/cluster/azure-standalone-cp/Chart.yaml index 94294173c..786a464b3 100644 --- a/templates/cluster/azure-standalone-cp/Chart.yaml +++ b/templates/cluster/azure-standalone-cp/Chart.yaml @@ -14,3 +14,6 @@ version: 0.0.3 appVersion: "1.31.1+k0s.1" annotations: cluster.x-k8s.io/provider: infrastructure-azure, control-plane-k0smotron, bootstrap-k0smotron + cluster.x-k8s.io/bootstrap-k0smotron: v1beta1 + cluster.x-k8s.io/control-plane-k0smotron: v1beta1 + cluster.x-k8s.io/infrastructure-azure: v1beta1 diff --git a/templates/cluster/vsphere-hosted-cp/Chart.yaml b/templates/cluster/vsphere-hosted-cp/Chart.yaml index c6d97d674..a945b881c 100644 --- a/templates/cluster/vsphere-hosted-cp/Chart.yaml +++ b/templates/cluster/vsphere-hosted-cp/Chart.yaml @@ -16,3 +16,6 @@ appVersion: "v1.31.1+k0s.1" annotations: cluster.x-k8s.io/provider: infrastructure-vsphere, control-plane-k0smotron, bootstrap-k0smotron hmc.mirantis.com/type: deployment + cluster.x-k8s.io/bootstrap-k0smotron: v1beta1 + cluster.x-k8s.io/control-plane-k0smotron: v1beta1 + cluster.x-k8s.io/infrastructure-vsphere: v1beta1 diff --git a/templates/cluster/vsphere-standalone-cp/Chart.yaml b/templates/cluster/vsphere-standalone-cp/Chart.yaml index 9a6e77398..493a5c70c 100644 --- a/templates/cluster/vsphere-standalone-cp/Chart.yaml +++ b/templates/cluster/vsphere-standalone-cp/Chart.yaml @@ -15,3 +15,6 @@ appVersion: "v1.31.1+k0s.1" annotations: cluster.x-k8s.io/provider: infrastructure-vsphere, control-plane-k0smotron, bootstrap-k0smotron hmc.mirantis.com/type: deployment + cluster.x-k8s.io/bootstrap-k0smotron: v1beta1 + cluster.x-k8s.io/control-plane-k0smotron: v1beta1 + cluster.x-k8s.io/infrastructure-vsphere: v1beta1 diff --git a/templates/provider/cluster-api-provider-aws/Chart.yaml b/templates/provider/cluster-api-provider-aws/Chart.yaml index 86821d729..e14986f4e 100644 --- a/templates/provider/cluster-api-provider-aws/Chart.yaml +++ b/templates/provider/cluster-api-provider-aws/Chart.yaml @@ -21,3 +21,6 @@ version: 0.0.2 appVersion: "2.6.1" annotations: cluster.x-k8s.io/provider: infrastructure-aws + cluster.x-k8s.io/v1alpha3: v1alpha3 + cluster.x-k8s.io/v1alpha4: v1alpha4 + cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 diff --git a/templates/provider/cluster-api-provider-azure/Chart.yaml b/templates/provider/cluster-api-provider-azure/Chart.yaml index 02feff0d7..a54cb76d8 100644 --- a/templates/provider/cluster-api-provider-azure/Chart.yaml +++ b/templates/provider/cluster-api-provider-azure/Chart.yaml @@ -21,3 +21,4 @@ version: 0.0.2 appVersion: "1.17.0" annotations: cluster.x-k8s.io/provider: infrastructure-azure + cluster.x-k8s.io/v1beta1: v1beta1 diff --git a/templates/provider/cluster-api-provider-vsphere/Chart.yaml b/templates/provider/cluster-api-provider-vsphere/Chart.yaml index ce9008714..943236e7b 100644 --- a/templates/provider/cluster-api-provider-vsphere/Chart.yaml +++ b/templates/provider/cluster-api-provider-vsphere/Chart.yaml @@ -21,3 +21,4 @@ version: 0.0.2 appVersion: "1.11.1" annotations: cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 diff --git a/templates/provider/cluster-api/Chart.yaml b/templates/provider/cluster-api/Chart.yaml index e2fb4937d..582df467f 100644 --- a/templates/provider/cluster-api/Chart.yaml +++ b/templates/provider/cluster-api/Chart.yaml @@ -19,3 +19,7 @@ version: 0.0.2 # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. appVersion: "1.8.4" +annotations: + cluster.x-k8s.io/v1beta1: "" + cluster.x-k8s.io/v1alpha3: "" + cluster.x-k8s.io/v1alpha4: "" diff --git a/templates/provider/hmc/templates/crds/hmc.mirantis.com_clustertemplates.yaml b/templates/provider/hmc/templates/crds/hmc.mirantis.com_clustertemplates.yaml index 9d38efd6f..acb5ac0bf 100644 --- a/templates/provider/hmc/templates/crds/hmc.mirantis.com_clustertemplates.yaml +++ b/templates/provider/hmc/templates/crds/hmc.mirantis.com_clustertemplates.yaml @@ -56,17 +56,6 @@ spec: spec: description: ClusterTemplateSpec defines the desired state of ClusterTemplate properties: - capiContracts: - additionalProperties: - type: string - description: |- - Holds key-value pairs with compatibility [contract versions], - where the key is the core CAPI contract version, - and the value is an underscore-delimited (_) list of provider contract versions - supported by the core CAPI. - - [contract versions]: https://cluster-api.sigs.k8s.io/developer/providers/contracts - type: object helm: description: HelmSpec references a Helm chart representing the HMC template @@ -118,6 +107,17 @@ spec: description: Kubernetes exact version in the SemVer format provided by this ClusterTemplate. type: string + providerContracts: + additionalProperties: + type: string + description: |- + Holds key-value pairs with compatibility [contract versions], + where the key is the name of the provider, + and the value is the provider contract version + required to be supported by the provider. + + [contract versions]: https://cluster-api.sigs.k8s.io/developer/providers/contracts + type: object providers: description: |- Providers represent required CAPI providers with supported contract versions. @@ -135,17 +135,6 @@ spec: status: description: ClusterTemplateStatus defines the observed state of ClusterTemplate properties: - capiContracts: - additionalProperties: - type: string - description: |- - Holds key-value pairs with compatibility [contract versions], - where the key is the core CAPI contract version, - and the value is an underscore-delimited (_) list of provider contract versions - supported by the core CAPI. - - [contract versions]: https://cluster-api.sigs.k8s.io/developer/providers/contracts - type: object chartRef: description: |- ChartRef is a reference to a source controller resource containing the @@ -192,6 +181,17 @@ spec: description: ObservedGeneration is the last observed generation. format: int64 type: integer + providerContracts: + additionalProperties: + type: string + description: |- + Holds key-value pairs with compatibility [contract versions], + where the key is the name of the provider, + and the value is the provider contract version + required to be supported by the provider. + + [contract versions]: https://cluster-api.sigs.k8s.io/developer/providers/contracts + type: object providers: description: |- Providers represent required CAPI providers with supported contract versions diff --git a/templates/provider/k0smotron/Chart.yaml b/templates/provider/k0smotron/Chart.yaml index 5db0e9a69..8b838e733 100644 --- a/templates/provider/k0smotron/Chart.yaml +++ b/templates/provider/k0smotron/Chart.yaml @@ -21,3 +21,6 @@ version: 0.0.2 appVersion: "1.0.4" annotations: cluster.x-k8s.io/provider: infrastructure-k0smotron, bootstrap-k0smotron, control-plane-k0smotron + cluster.x-k8s.io/bootstrap-k0smotron: v1beta1 + cluster.x-k8s.io/control-plane-k0smotron: v1beta1 + cluster.x-k8s.io/infrastructure-k0smotron: v1beta1