From 29484afa2a4a5eaa7a3ca5da1de72b3bc4bf3c5c Mon Sep 17 00:00:00 2001 From: Ekaterina Kazakova Date: Fri, 22 Nov 2024 17:20:05 +0400 Subject: [PATCH] Extend helm chart configuration for Templates Closes #615 --- api/v1alpha1/templates_common.go | 19 ++- api/v1alpha1/zz_generated.deepcopy.go | 6 + hack/templates.sh | 9 +- .../controller/managedcluster_controller.go | 10 +- internal/controller/management_controller.go | 10 +- .../controller/management_controller_test.go | 6 +- .../multiclusterservice_controller_test.go | 6 +- internal/controller/release_controller.go | 13 +- internal/controller/template_controller.go | 32 +--- .../templatechain_controller_test.go | 3 +- internal/telemetry/tracker.go | 2 +- internal/webhook/template_webhook.go | 39 ++++- .../files/templates/aws-eks-0-0-2.yaml | 9 +- .../files/templates/aws-hosted-cp-0-0-3.yaml | 9 +- .../templates/aws-standalone-cp-0-0-3.yaml | 9 +- .../templates/azure-hosted-cp-0-0-3.yaml | 9 +- .../templates/azure-standalone-cp-0-0-3.yaml | 9 +- .../templates/cluster-api-provider-aws.yaml | 9 +- .../templates/cluster-api-provider-azure.yaml | 9 +- .../cluster-api-provider-vsphere.yaml | 9 +- .../files/templates/cluster-api.yaml | 9 +- .../hmc-templates/files/templates/hmc.yaml | 9 +- .../files/templates/ingress-nginx-4-11-0.yaml | 9 +- .../files/templates/ingress-nginx-4-11-3.yaml | 9 +- .../files/templates/k0smotron.yaml | 9 +- .../files/templates/kyverno-3-2-6.yaml | 9 +- .../files/templates/projectsveltos.yaml | 9 +- .../templates/vsphere-hosted-cp-0-0-3.yaml | 9 +- .../vsphere-standalone-cp-0-0-3.yaml | 9 +- .../hmc.mirantis.com_clustertemplates.yaml | 151 ++++++++++++++++-- .../hmc.mirantis.com_providertemplates.yaml | 151 ++++++++++++++++-- .../hmc.mirantis.com_servicetemplates.yaml | 151 ++++++++++++++++-- .../provider/hmc/templates/webhooks.yaml | 66 ++++++++ test/objects/template/template.go | 3 +- 34 files changed, 709 insertions(+), 121 deletions(-) diff --git a/api/v1alpha1/templates_common.go b/api/v1alpha1/templates_common.go index 6bbcb5404..fd5e4f1da 100644 --- a/api/v1alpha1/templates_common.go +++ b/api/v1alpha1/templates_common.go @@ -21,6 +21,7 @@ import ( "strings" helmcontrollerv2 "github.com/fluxcd/helm-controller/api/v2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) @@ -30,19 +31,25 @@ const ( ChartAnnotationProviderName = "cluster.x-k8s.io/provider" chartAnnoCAPIPrefix = "cluster.x-k8s.io/" + + DefaultRepoName = "hmc-templates" ) -// +kubebuilder:validation:XValidation:rule="(has(self.chartName) && !has(self.chartRef)) || (!has(self.chartName) && has(self.chartRef))", message="either chartName or chartRef must be set" +var DefaultSourceRef = sourcev1.LocalHelmChartSourceReference{ + Kind: sourcev1.HelmRepositoryKind, + Name: DefaultRepoName, +} + +// +kubebuilder:validation:XValidation:rule="(has(self.chartSpec) && !has(self.chartRef)) || (!has(self.chartSpec) && has(self.chartRef))", message="either chartSpec or chartRef must be set" // HelmSpec references a Helm chart representing the HMC template type HelmSpec struct { + // ChartSpec defines the desired state of the HelmChart to be created by the controller + ChartSpec *sourcev1.HelmChartSpec `json:"chartSpec,omitempty"` + // ChartRef is a reference to a source controller resource containing the // Helm chart representing the template. ChartRef *helmcontrollerv2.CrossNamespaceSourceReference `json:"chartRef,omitempty"` - // ChartName is a name of a Helm chart representing the template in the HMC repository. - ChartName string `json:"chartName,omitempty"` - // ChartVersion is a version of a Helm chart representing the template in the HMC repository. - ChartVersion string `json:"chartVersion,omitempty"` } func (s *HelmSpec) String() string { @@ -50,7 +57,7 @@ func (s *HelmSpec) String() string { return s.ChartRef.Namespace + "/" + s.ChartRef.Name + ", Kind=" + s.ChartRef.Kind } - return s.ChartName + ": " + s.ChartVersion + return s.ChartSpec.Chart + ": " + s.ChartSpec.Version } // TemplateStatusCommon defines the observed state of Template common for all Template types diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 48fbe8536..426660e91 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -20,6 +20,7 @@ package v1alpha1 import ( "github.com/fluxcd/helm-controller/api/v2" + apiv1 "github.com/fluxcd/source-controller/api/v1" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -540,6 +541,11 @@ func (in *CredentialStatus) DeepCopy() *CredentialStatus { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HelmSpec) DeepCopyInto(out *HelmSpec) { *out = *in + if in.ChartSpec != nil { + in, out := &in.ChartSpec, &out.ChartSpec + *out = new(apiv1.HelmChartSpec) + (*in).DeepCopyInto(*out) + } if in.ChartRef != nil { in, out := &in.ChartRef, &out.ChartRef *out = new(v2.CrossNamespaceSourceReference) diff --git a/hack/templates.sh b/hack/templates.sh index e1fa62301..ac73ed156 100755 --- a/hack/templates.sh +++ b/hack/templates.sh @@ -47,8 +47,13 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: $name - chartVersion: $version + chartSpec: + chart: $name + version: $version + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates EOF echo "Generated $TEMPLATES_OUTPUT_DIR/$name.yaml" diff --git a/internal/controller/managedcluster_controller.go b/internal/controller/managedcluster_controller.go index 3df786aef..3dcc43ade 100644 --- a/internal/controller/managedcluster_controller.go +++ b/internal/controller/managedcluster_controller.go @@ -302,7 +302,7 @@ func (r *ManagedClusterReconciler) updateCluster(ctx context.Context, mc *hmc.Ma return ctrl.Result{}, fmt.Errorf("error setting identity values: %w", err) } - hr, _, err := helm.ReconcileHelmRelease(ctx, r.Client, mc.Name, mc.Namespace, helm.ReconcileHelmReleaseOpts{ + hrReconcileOpts := helm.ReconcileHelmReleaseOpts{ Values: helmValues, OwnerReference: &metav1.OwnerReference{ APIVersion: hmc.GroupVersion.String(), @@ -311,7 +311,13 @@ func (r *ManagedClusterReconciler) updateCluster(ctx context.Context, mc *hmc.Ma UID: mc.UID, }, ChartRef: clusterTpl.Status.ChartRef, - }) + } + reconcileInterval := clusterTpl.Spec.Helm.ChartSpec.Interval.Duration + if reconcileInterval != 0 { + hrReconcileOpts.ReconcileInterval = &reconcileInterval + } + + hr, _, err := helm.ReconcileHelmRelease(ctx, r.Client, mc.Name, mc.Namespace, hrReconcileOpts) if err != nil { apimeta.SetStatusCondition(mc.GetConditions(), metav1.Condition{ Type: hmc.HelmReleaseReadyCondition, diff --git a/internal/controller/management_controller.go b/internal/controller/management_controller.go index 52b618408..8e43c0137 100644 --- a/internal/controller/management_controller.go +++ b/internal/controller/management_controller.go @@ -142,13 +142,19 @@ func (r *ManagementReconciler) Update(ctx context.Context, management *hmc.Manag continue } - if _, _, err := helm.ReconcileHelmRelease(ctx, r.Client, component.helmReleaseName, r.SystemNamespace, helm.ReconcileHelmReleaseOpts{ + hrReconcileOpts := helm.ReconcileHelmReleaseOpts{ Values: component.Config, ChartRef: template.Status.ChartRef, DependsOn: component.dependsOn, TargetNamespace: component.targetNamespace, CreateNamespace: component.createNamespace, - }); err != nil { + } + reconcileInterval := template.Spec.Helm.ChartSpec.Interval.Duration + if reconcileInterval != 0 { + hrReconcileOpts.ReconcileInterval = &reconcileInterval + } + + if _, _, err := helm.ReconcileHelmRelease(ctx, r.Client, component.helmReleaseName, r.SystemNamespace, hrReconcileOpts); err != nil { errMsg := fmt.Sprintf("Failed to reconcile HelmRelease %s/%s: %s", r.SystemNamespace, component.helmReleaseName, err) updateComponentsStatus(statusAccumulator, component, nil, errMsg) errs = errors.Join(errs, errors.New(errMsg)) diff --git a/internal/controller/management_controller_test.go b/internal/controller/management_controller_test.go index bf527fcd3..ed71052fd 100644 --- a/internal/controller/management_controller_test.go +++ b/internal/controller/management_controller_test.go @@ -157,8 +157,10 @@ var _ = Describe("Management Controller", func() { }, Spec: hmcmirantiscomv1alpha1.ProviderTemplateSpec{ Helm: hmcmirantiscomv1alpha1.HelmSpec{ - ChartName: "required-chart", - ChartVersion: "required-version", + ChartSpec: &sourcev1.HelmChartSpec{ + Chart: "required-chart", + Version: "required-version", + }, }, }, } diff --git a/internal/controller/multiclusterservice_controller_test.go b/internal/controller/multiclusterservice_controller_test.go index 0d72fe711..f3f7f9b79 100644 --- a/internal/controller/multiclusterservice_controller_test.go +++ b/internal/controller/multiclusterservice_controller_test.go @@ -162,8 +162,10 @@ var _ = Describe("MultiClusterService Controller", func() { }, Spec: hmc.ServiceTemplateSpec{ Helm: hmc.HelmSpec{ - ChartName: helmChartName, - ChartVersion: helmChartVersion, + ChartSpec: &sourcev1.HelmChartSpec{ + Chart: helmChartName, + Version: helmChartVersion, + }, }, }, } diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index 37260c1d0..be19aa876 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -249,7 +249,7 @@ func (r *ReleaseReconciler) reconcileHMCTemplates(ctx context.Context, releaseNa if releaseName == "" { releaseName = utils.ReleaseNameFromVersion(build.Version) releaseVersion = build.Version - err := helm.ReconcileHelmRepository(ctx, r.Client, defaultRepoName, r.SystemNamespace, r.DefaultRegistryConfig.HelmRepositorySpec()) + err := helm.ReconcileHelmRepository(ctx, r.Client, hmc.DefaultRepoName, r.SystemNamespace, r.DefaultRegistryConfig.HelmRepositorySpec()) if err != nil { l.Error(err, "Failed to reconcile default HelmRepository", "namespace", r.SystemNamespace) return err @@ -280,13 +280,10 @@ func (r *ReleaseReconciler) reconcileHMCTemplates(ctx context.Context, releaseNa } helmChart.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue helmChart.Spec = sourcev1.HelmChartSpec{ - Chart: r.HMCTemplatesChartName, - Version: releaseVersion, - SourceRef: sourcev1.LocalHelmChartSourceReference{ - Kind: sourcev1.HelmRepositoryKind, - Name: defaultRepoName, - }, - Interval: metav1.Duration{Duration: helm.DefaultReconcileInterval}, + Chart: r.HMCTemplatesChartName, + Version: releaseVersion, + SourceRef: hmc.DefaultSourceRef, + Interval: metav1.Duration{Duration: helm.DefaultReconcileInterval}, } return nil }) diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index 560f7c02f..32f33a521 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -41,11 +41,7 @@ import ( "github.com/Mirantis/hmc/internal/utils" ) -const ( - defaultRepoName = "hmc-templates" - - defaultRequeueTime = 1 * time.Minute -) +const defaultRequeueTime = 1 * time.Minute // TemplateReconciler reconciles a *Template object type TemplateReconciler struct { @@ -184,8 +180,8 @@ func (r *TemplateReconciler) ReconcileTemplate(ctx context.Context, template tem return ctrl.Result{}, err } } else { - if helmSpec.ChartName == "" { - err := errors.New("neither chartName nor chartRef is set") + if helmSpec.ChartSpec == nil { + err := errors.New("neither chartSpec nor chartRef is set") l.Error(err, "invalid helm chart reference") return ctrl.Result{}, err } @@ -194,7 +190,7 @@ func (r *TemplateReconciler) ReconcileTemplate(ctx context.Context, template tem if namespace == "" { namespace = r.SystemNamespace } - err := helm.ReconcileHelmRepository(ctx, r.Client, defaultRepoName, namespace, r.DefaultRegistryConfig.HelmRepositorySpec()) + err := helm.ReconcileHelmRepository(ctx, r.Client, hmc.DefaultRepoName, namespace, r.DefaultRegistryConfig.HelmRepositorySpec()) if err != nil { l.Error(err, "Failed to reconcile default HelmRepository") return ctrl.Result{}, err @@ -314,25 +310,9 @@ func (r *TemplateReconciler) reconcileHelmChart(ctx context.Context, template te } helmChart.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue - helmChart.OwnerReferences = []metav1.OwnerReference{ - { - APIVersion: hmc.GroupVersion.String(), - Kind: template.GetObjectKind().GroupVersionKind().Kind, - Name: template.GetName(), - UID: template.GetUID(), - }, - } - - helmChart.Spec = sourcev1.HelmChartSpec{ - Chart: helmSpec.ChartName, - Version: helmSpec.ChartVersion, - SourceRef: sourcev1.LocalHelmChartSourceReference{ - Kind: sourcev1.HelmRepositoryKind, - Name: defaultRepoName, - }, - Interval: metav1.Duration{Duration: helm.DefaultReconcileInterval}, - } + utils.AddOwnerReference(helmChart, template) + helmChart.Spec = *helmSpec.ChartSpec return nil }) diff --git a/internal/controller/templatechain_controller_test.go b/internal/controller/templatechain_controller_test.go index 4457644d4..7ca319c3a 100644 --- a/internal/controller/templatechain_controller_test.go +++ b/internal/controller/templatechain_controller_test.go @@ -20,6 +20,7 @@ import ( "time" helmcontrollerv2 "github.com/fluxcd/helm-controller/api/v2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -52,7 +53,7 @@ var _ = Describe("Template Chain Controller", func() { } chartName := "test" - templateHelmSpec := hmcmirantiscomv1alpha1.HelmSpec{ChartName: chartName} + templateHelmSpec := hmcmirantiscomv1alpha1.HelmSpec{ChartSpec: &sourcev1.HelmChartSpec{Chart: chartName}} chartRef := &helmcontrollerv2.CrossNamespaceSourceReference{ Kind: "HelmChart", Namespace: utils.DefaultSystemNamespace, diff --git a/internal/telemetry/tracker.go b/internal/telemetry/tracker.go index bf8aec325..b44d90573 100644 --- a/internal/telemetry/tracker.go +++ b/internal/telemetry/tracker.go @@ -91,7 +91,7 @@ func (t *Tracker) trackManagedClusterHeartbeat(ctx context.Context) error { string(managedCluster.UID), clusterID, managedCluster.Spec.Template, - template.Spec.Helm.ChartVersion, + template.Spec.Helm.ChartSpec.Version, template.Status.Providers, ) if err != nil { diff --git a/internal/webhook/template_webhook.go b/internal/webhook/template_webhook.go index e6dfe9e47..a58f61056 100644 --- a/internal/webhook/template_webhook.go +++ b/internal/webhook/template_webhook.go @@ -27,6 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/Mirantis/hmc/internal/helm" ) type ClusterTemplateValidator struct { @@ -82,7 +83,12 @@ func (v *ClusterTemplateValidator) ValidateDelete(ctx context.Context, obj runti } // Default implements webhook.Defaulter so a webhook will be registered for the type. -func (*ClusterTemplateValidator) Default(context.Context, runtime.Object) error { +func (*ClusterTemplateValidator) Default(_ context.Context, obj runtime.Object) error { + template, ok := obj.(*v1alpha1.ClusterTemplate) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected ClusterTemplate but got a %T", obj)) + } + setHelmChartDefaults(template) return nil } @@ -152,7 +158,12 @@ func (v *ServiceTemplateValidator) ValidateDelete(ctx context.Context, obj runti } // Default implements webhook.Defaulter so a webhook will be registered for the type. -func (*ServiceTemplateValidator) Default(_ context.Context, _ runtime.Object) error { +func (*ServiceTemplateValidator) Default(_ context.Context, obj runtime.Object) error { + template, ok := obj.(*v1alpha1.ServiceTemplate) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected ServiceTemplate but got a %T", obj)) + } + setHelmChartDefaults(template) return nil } @@ -190,6 +201,28 @@ func (*ProviderTemplateValidator) ValidateDelete(_ context.Context, _ runtime.Ob } // Default implements webhook.Defaulter so a webhook will be registered for the type. -func (*ProviderTemplateValidator) Default(_ context.Context, _ runtime.Object) error { +func (*ProviderTemplateValidator) Default(_ context.Context, obj runtime.Object) error { + template, ok := obj.(*v1alpha1.ProviderTemplate) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected ProviderTemplate but got a %T", obj)) + } + setHelmChartDefaults(template) return nil } + +type templateCommon interface { + GetHelmSpec() *v1alpha1.HelmSpec +} + +func setHelmChartDefaults(template templateCommon) { + helmSpec := template.GetHelmSpec() + if helmSpec.ChartRef == nil && helmSpec.ChartSpec != nil { + chartSpec := helmSpec.ChartSpec + if chartSpec.SourceRef.Name == "" && chartSpec.SourceRef.Kind == "" { + chartSpec.SourceRef = v1alpha1.DefaultSourceRef + } + if chartSpec.Interval.Duration == 0 { + chartSpec.Interval.Duration = helm.DefaultReconcileInterval + } + } +} diff --git a/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml b/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml index 57e5fd6a5..fa3d75fd7 100644 --- a/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml +++ b/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: aws-eks - chartVersion: 0.0.2 + chartSpec: + chart: aws-eks + version: 0.0.2 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml index 092a37072..30b3fd57a 100644 --- a/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: aws-hosted-cp - chartVersion: 0.0.3 + chartSpec: + chart: aws-hosted-cp + version: 0.0.3 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-3.yaml index 9b1f98f2f..60a1c1015 100644 --- a/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-3.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: aws-standalone-cp - chartVersion: 0.0.3 + chartSpec: + chart: aws-standalone-cp + version: 0.0.3 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml index 64cd4ebab..aabd521bb 100644 --- a/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: azure-hosted-cp - chartVersion: 0.0.3 + chartSpec: + chart: azure-hosted-cp + version: 0.0.3 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-3.yaml index 8b867c342..9e4f9c8b3 100644 --- a/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-3.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: azure-standalone-cp - chartVersion: 0.0.3 + chartSpec: + chart: azure-standalone-cp + version: 0.0.3 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml b/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml index 298e24ec3..ddf83128a 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: cluster-api-provider-aws - chartVersion: 0.0.4 + chartSpec: + chart: cluster-api-provider-aws + version: 0.0.4 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml b/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml index 9c653b64a..a92b7d9d8 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: cluster-api-provider-azure - chartVersion: 0.0.4 + chartSpec: + chart: cluster-api-provider-azure + version: 0.0.4 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml b/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml index 98535e57b..57a07e833 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: cluster-api-provider-vsphere - chartVersion: 0.0.4 + chartSpec: + chart: cluster-api-provider-vsphere + version: 0.0.4 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/cluster-api.yaml b/templates/provider/hmc-templates/files/templates/cluster-api.yaml index dafa76028..602c182dc 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: cluster-api - chartVersion: 0.0.4 + chartSpec: + chart: cluster-api + version: 0.0.4 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/hmc.yaml b/templates/provider/hmc-templates/files/templates/hmc.yaml index 6dbdca7a7..5cb8fcd9a 100644 --- a/templates/provider/hmc-templates/files/templates/hmc.yaml +++ b/templates/provider/hmc-templates/files/templates/hmc.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: hmc - chartVersion: 0.0.4 + chartSpec: + chart: hmc + version: 0.0.4 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml index 741648320..c7092d713 100644 --- a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml +++ b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: ingress-nginx - chartVersion: 4.11.0 + chartSpec: + chart: ingress-nginx + version: 4.11.0 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml index 6e33c5e85..a55506fc6 100644 --- a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml +++ b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: ingress-nginx - chartVersion: 4.11.3 + chartSpec: + chart: ingress-nginx + version: 4.11.3 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/k0smotron.yaml b/templates/provider/hmc-templates/files/templates/k0smotron.yaml index 5f5cc9203..3f2d16371 100644 --- a/templates/provider/hmc-templates/files/templates/k0smotron.yaml +++ b/templates/provider/hmc-templates/files/templates/k0smotron.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: k0smotron - chartVersion: 0.0.4 + chartSpec: + chart: k0smotron + version: 0.0.4 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml b/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml index 7474853cc..dc2ecb4da 100644 --- a/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml +++ b/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: kyverno - chartVersion: 3.2.6 + chartSpec: + chart: kyverno + version: 3.2.6 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/projectsveltos.yaml b/templates/provider/hmc-templates/files/templates/projectsveltos.yaml index aef1719b6..42af81dd1 100644 --- a/templates/provider/hmc-templates/files/templates/projectsveltos.yaml +++ b/templates/provider/hmc-templates/files/templates/projectsveltos.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: projectsveltos - chartVersion: 0.42.0 + chartSpec: + chart: projectsveltos + version: 0.42.0 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml index d6fa8db18..4fcc0b118 100644 --- a/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: vsphere-hosted-cp - chartVersion: 0.0.3 + chartSpec: + chart: vsphere-hosted-cp + version: 0.0.3 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates diff --git a/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml index a45ec8d2b..f628b7350 100644 --- a/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml @@ -6,5 +6,10 @@ metadata: helm.sh/resource-policy: keep spec: helm: - chartName: vsphere-standalone-cp - chartVersion: 0.0.3 + chartSpec: + chart: vsphere-standalone-cp + version: 0.0.3 + interval: 10m0s + sourceRef: + kind: HelmRepository + name: hmc-templates 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 94bfcbb20..e207d6ec4 100644 --- a/templates/provider/hmc/templates/crds/hmc.mirantis.com_clustertemplates.yaml +++ b/templates/provider/hmc/templates/crds/hmc.mirantis.com_clustertemplates.yaml @@ -60,10 +60,6 @@ spec: description: HelmSpec references a Helm chart representing the HMC template properties: - chartName: - description: ChartName is a name of a Helm chart representing - the template in the HMC repository. - type: string chartRef: description: |- ChartRef is a reference to a source controller resource containing the @@ -94,14 +90,149 @@ spec: - kind - name type: object - chartVersion: - description: ChartVersion is a version of a Helm chart representing - the template in the HMC repository. - type: string + chartSpec: + description: ChartSpec defines the desired state of the HelmChart + to be created by the controller + properties: + chart: + description: |- + Chart is the name or path the Helm chart is available at in the + SourceRef. + type: string + ignoreMissingValuesFiles: + description: |- + IgnoreMissingValuesFiles controls whether to silently ignore missing values + files rather than failing. + type: boolean + interval: + description: |- + Interval at which the HelmChart SourceRef is checked for updates. + This interval is approximate and may be subject to jitter to ensure + efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + reconcileStrategy: + default: ChartVersion + description: |- + ReconcileStrategy determines what enables the creation of a new artifact. + Valid values are ('ChartVersion', 'Revision'). + See the documentation of the values for an explanation on their behavior. + Defaults to ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: SourceRef is the reference to the Source the + chart is available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: |- + Kind of the referent, valid values are ('HelmRepository', 'GitRepository', + 'Bucket'). + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + required: + - kind + - name + type: object + suspend: + description: |- + Suspend tells the controller to suspend the reconciliation of this + source. + type: boolean + valuesFiles: + description: |- + ValuesFiles is an alternative list of values files to use as the chart + values (values.yaml is not included by default), expected to be a + relative path in the SourceRef. + Values files are merged in the order of this list with the last file + overriding the first. Ignored when omitted. + items: + type: string + type: array + verify: + description: |- + Verify contains the secret name containing the trusted public keys + used to verify the signature and specifies which provider to use to check + whether OCI image is authentic. + This field is only supported when using HelmRepository source with spec.type 'oci'. + Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. + properties: + matchOIDCIdentity: + description: |- + MatchOIDCIdentity specifies the identity matching criteria to use + while verifying an OCI artifact which was signed using Cosign keyless + signing. The artifact's identity is deemed to be verified if any of the + specified matchers match against the identity. + items: + description: |- + OIDCIdentityMatch specifies options for verifying the certificate identity, + i.e. the issuer and the subject of the certificate. + properties: + issuer: + description: |- + Issuer specifies the regex pattern to match against to verify + the OIDC issuer in the Fulcio certificate. The pattern must be a + valid Go regular expression. + type: string + subject: + description: |- + Subject specifies the regex pattern to match against to verify + the identity subject in the Fulcio certificate. The pattern must + be a valid Go regular expression. + type: string + required: + - issuer + - subject + type: object + type: array + provider: + default: cosign + description: Provider specifies the technology used to + sign the OCI Artifact. + enum: + - cosign + - notation + type: string + secretRef: + description: |- + SecretRef specifies the Kubernetes Secret containing the + trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + version: + default: '*' + description: |- + Version is the chart version semver expression, ignored for charts from + GitRepository and Bucket sources. Defaults to latest when omitted. + type: string + required: + - chart + - interval + - sourceRef + type: object type: object x-kubernetes-validations: - - message: either chartName or chartRef must be set - rule: (has(self.chartName) && !has(self.chartRef)) || (!has(self.chartName) + - message: either chartSpec or chartRef must be set + rule: (has(self.chartSpec) && !has(self.chartRef)) || (!has(self.chartSpec) && has(self.chartRef)) k8sVersion: description: Kubernetes exact version in the SemVer format provided diff --git a/templates/provider/hmc/templates/crds/hmc.mirantis.com_providertemplates.yaml b/templates/provider/hmc/templates/crds/hmc.mirantis.com_providertemplates.yaml index 3157fb79c..449faa5a3 100644 --- a/templates/provider/hmc/templates/crds/hmc.mirantis.com_providertemplates.yaml +++ b/templates/provider/hmc/templates/crds/hmc.mirantis.com_providertemplates.yaml @@ -71,10 +71,6 @@ spec: description: HelmSpec references a Helm chart representing the HMC template properties: - chartName: - description: ChartName is a name of a Helm chart representing - the template in the HMC repository. - type: string chartRef: description: |- ChartRef is a reference to a source controller resource containing the @@ -105,14 +101,149 @@ spec: - kind - name type: object - chartVersion: - description: ChartVersion is a version of a Helm chart representing - the template in the HMC repository. - type: string + chartSpec: + description: ChartSpec defines the desired state of the HelmChart + to be created by the controller + properties: + chart: + description: |- + Chart is the name or path the Helm chart is available at in the + SourceRef. + type: string + ignoreMissingValuesFiles: + description: |- + IgnoreMissingValuesFiles controls whether to silently ignore missing values + files rather than failing. + type: boolean + interval: + description: |- + Interval at which the HelmChart SourceRef is checked for updates. + This interval is approximate and may be subject to jitter to ensure + efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + reconcileStrategy: + default: ChartVersion + description: |- + ReconcileStrategy determines what enables the creation of a new artifact. + Valid values are ('ChartVersion', 'Revision'). + See the documentation of the values for an explanation on their behavior. + Defaults to ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: SourceRef is the reference to the Source the + chart is available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: |- + Kind of the referent, valid values are ('HelmRepository', 'GitRepository', + 'Bucket'). + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + required: + - kind + - name + type: object + suspend: + description: |- + Suspend tells the controller to suspend the reconciliation of this + source. + type: boolean + valuesFiles: + description: |- + ValuesFiles is an alternative list of values files to use as the chart + values (values.yaml is not included by default), expected to be a + relative path in the SourceRef. + Values files are merged in the order of this list with the last file + overriding the first. Ignored when omitted. + items: + type: string + type: array + verify: + description: |- + Verify contains the secret name containing the trusted public keys + used to verify the signature and specifies which provider to use to check + whether OCI image is authentic. + This field is only supported when using HelmRepository source with spec.type 'oci'. + Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. + properties: + matchOIDCIdentity: + description: |- + MatchOIDCIdentity specifies the identity matching criteria to use + while verifying an OCI artifact which was signed using Cosign keyless + signing. The artifact's identity is deemed to be verified if any of the + specified matchers match against the identity. + items: + description: |- + OIDCIdentityMatch specifies options for verifying the certificate identity, + i.e. the issuer and the subject of the certificate. + properties: + issuer: + description: |- + Issuer specifies the regex pattern to match against to verify + the OIDC issuer in the Fulcio certificate. The pattern must be a + valid Go regular expression. + type: string + subject: + description: |- + Subject specifies the regex pattern to match against to verify + the identity subject in the Fulcio certificate. The pattern must + be a valid Go regular expression. + type: string + required: + - issuer + - subject + type: object + type: array + provider: + default: cosign + description: Provider specifies the technology used to + sign the OCI Artifact. + enum: + - cosign + - notation + type: string + secretRef: + description: |- + SecretRef specifies the Kubernetes Secret containing the + trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + version: + default: '*' + description: |- + Version is the chart version semver expression, ignored for charts from + GitRepository and Bucket sources. Defaults to latest when omitted. + type: string + required: + - chart + - interval + - sourceRef + type: object type: object x-kubernetes-validations: - - message: either chartName or chartRef must be set - rule: (has(self.chartName) && !has(self.chartRef)) || (!has(self.chartName) + - message: either chartSpec or chartRef must be set + rule: (has(self.chartSpec) && !has(self.chartRef)) || (!has(self.chartSpec) && has(self.chartRef)) providers: description: |- diff --git a/templates/provider/hmc/templates/crds/hmc.mirantis.com_servicetemplates.yaml b/templates/provider/hmc/templates/crds/hmc.mirantis.com_servicetemplates.yaml index 84c17f57f..739906789 100644 --- a/templates/provider/hmc/templates/crds/hmc.mirantis.com_servicetemplates.yaml +++ b/templates/provider/hmc/templates/crds/hmc.mirantis.com_servicetemplates.yaml @@ -60,10 +60,6 @@ spec: description: HelmSpec references a Helm chart representing the HMC template properties: - chartName: - description: ChartName is a name of a Helm chart representing - the template in the HMC repository. - type: string chartRef: description: |- ChartRef is a reference to a source controller resource containing the @@ -94,14 +90,149 @@ spec: - kind - name type: object - chartVersion: - description: ChartVersion is a version of a Helm chart representing - the template in the HMC repository. - type: string + chartSpec: + description: ChartSpec defines the desired state of the HelmChart + to be created by the controller + properties: + chart: + description: |- + Chart is the name or path the Helm chart is available at in the + SourceRef. + type: string + ignoreMissingValuesFiles: + description: |- + IgnoreMissingValuesFiles controls whether to silently ignore missing values + files rather than failing. + type: boolean + interval: + description: |- + Interval at which the HelmChart SourceRef is checked for updates. + This interval is approximate and may be subject to jitter to ensure + efficient use of resources. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + reconcileStrategy: + default: ChartVersion + description: |- + ReconcileStrategy determines what enables the creation of a new artifact. + Valid values are ('ChartVersion', 'Revision'). + See the documentation of the values for an explanation on their behavior. + Defaults to ChartVersion when omitted. + enum: + - ChartVersion + - Revision + type: string + sourceRef: + description: SourceRef is the reference to the Source the + chart is available at. + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: |- + Kind of the referent, valid values are ('HelmRepository', 'GitRepository', + 'Bucket'). + enum: + - HelmRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + required: + - kind + - name + type: object + suspend: + description: |- + Suspend tells the controller to suspend the reconciliation of this + source. + type: boolean + valuesFiles: + description: |- + ValuesFiles is an alternative list of values files to use as the chart + values (values.yaml is not included by default), expected to be a + relative path in the SourceRef. + Values files are merged in the order of this list with the last file + overriding the first. Ignored when omitted. + items: + type: string + type: array + verify: + description: |- + Verify contains the secret name containing the trusted public keys + used to verify the signature and specifies which provider to use to check + whether OCI image is authentic. + This field is only supported when using HelmRepository source with spec.type 'oci'. + Chart dependencies, which are not bundled in the umbrella chart artifact, are not verified. + properties: + matchOIDCIdentity: + description: |- + MatchOIDCIdentity specifies the identity matching criteria to use + while verifying an OCI artifact which was signed using Cosign keyless + signing. The artifact's identity is deemed to be verified if any of the + specified matchers match against the identity. + items: + description: |- + OIDCIdentityMatch specifies options for verifying the certificate identity, + i.e. the issuer and the subject of the certificate. + properties: + issuer: + description: |- + Issuer specifies the regex pattern to match against to verify + the OIDC issuer in the Fulcio certificate. The pattern must be a + valid Go regular expression. + type: string + subject: + description: |- + Subject specifies the regex pattern to match against to verify + the identity subject in the Fulcio certificate. The pattern must + be a valid Go regular expression. + type: string + required: + - issuer + - subject + type: object + type: array + provider: + default: cosign + description: Provider specifies the technology used to + sign the OCI Artifact. + enum: + - cosign + - notation + type: string + secretRef: + description: |- + SecretRef specifies the Kubernetes Secret containing the + trusted public keys. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + version: + default: '*' + description: |- + Version is the chart version semver expression, ignored for charts from + GitRepository and Bucket sources. Defaults to latest when omitted. + type: string + required: + - chart + - interval + - sourceRef + type: object type: object x-kubernetes-validations: - - message: either chartName or chartRef must be set - rule: (has(self.chartName) && !has(self.chartRef)) || (!has(self.chartName) + - message: either chartSpec or chartRef must be set + rule: (has(self.chartSpec) && !has(self.chartRef)) || (!has(self.chartSpec) && has(self.chartRef)) k8sConstraint: description: Constraint describing compatible K8S versions of the diff --git a/templates/provider/hmc/templates/webhooks.yaml b/templates/provider/hmc/templates/webhooks.yaml index 4d11300fb..aa40b486d 100644 --- a/templates/provider/hmc/templates/webhooks.yaml +++ b/templates/provider/hmc/templates/webhooks.yaml @@ -50,6 +50,72 @@ webhooks: resources: - managements sideEffects: None + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: {{ include "hmc.webhook.serviceName" . }} + namespace: {{ include "hmc.webhook.serviceNamespace" . }} + path: /mutate-hmc-mirantis-com-v1alpha1-clustertemplate + failurePolicy: Fail + matchPolicy: Equivalent + name: mutation.clustertemplate.hmc.mirantis.com + rules: + - apiGroups: + - hmc.mirantis.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - clustertemplates + sideEffects: None + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: {{ include "hmc.webhook.serviceName" . }} + namespace: {{ include "hmc.webhook.serviceNamespace" . }} + path: /mutate-hmc-mirantis-com-v1alpha1-servicetemplate + failurePolicy: Fail + matchPolicy: Equivalent + name: mutation.servicetemplate.hmc.mirantis.com + rules: + - apiGroups: + - hmc.mirantis.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - servicetemplates + sideEffects: None + - admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + service: + name: {{ include "hmc.webhook.serviceName" . }} + namespace: {{ include "hmc.webhook.serviceNamespace" . }} + path: /mutate-hmc-mirantis-com-v1alpha1-providertemplate + failurePolicy: Fail + matchPolicy: Equivalent + name: mutation.providertemplate.hmc.mirantis.com + rules: + - apiGroups: + - hmc.mirantis.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - providertemplates + sideEffects: None --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration diff --git a/test/objects/template/template.go b/test/objects/template/template.go index c26a50668..513097248 100644 --- a/test/objects/template/template.go +++ b/test/objects/template/template.go @@ -128,9 +128,8 @@ func ManagedByHMC() Opt { func WithHelmSpec(helmSpec v1alpha1.HelmSpec) Opt { return func(t Template) { spec := t.GetHelmSpec() - spec.ChartName = helmSpec.ChartName + spec.ChartSpec = helmSpec.ChartSpec spec.ChartRef = helmSpec.ChartRef - spec.ChartVersion = helmSpec.ChartVersion } }