From d01518cc6b0332ad84397b5efa727e24c55f1bf7 Mon Sep 17 00:00:00 2001 From: Soule BA Date: Tue, 5 Mar 2024 15:42:40 +0100 Subject: [PATCH] enable reusing an existing OCIRepo as chartRef Signed-off-by: Soule BA --- api/v2beta2/helmrelease_types.go | 7 ++++- api/v2beta2/reference_types.go | 26 ++++++++++++++++ api/v2beta2/zz_generated.deepcopy.go | 20 ++++++++++++ .../helm.toolkit.fluxcd.io_helmreleases.yaml | 31 ++++++++++++++++++- internal/controller/helmrelease_controller.go | 19 +++++++++--- 5 files changed, 97 insertions(+), 6 deletions(-) diff --git a/api/v2beta2/helmrelease_types.go b/api/v2beta2/helmrelease_types.go index 6651a841d..71f4243e5 100644 --- a/api/v2beta2/helmrelease_types.go +++ b/api/v2beta2/helmrelease_types.go @@ -74,12 +74,17 @@ type PostRenderer struct { } // HelmReleaseSpec defines the desired state of a Helm release. +// +kubebuilder:validation:XValidation:rule="(has(self.chart) && !has(self.chartRef) || (!has(self.chart) && has(self.chartRef))", message="either chart or chartRef must be set" type HelmReleaseSpec struct { // Chart defines the template of the v1beta2.HelmChart that should be created // for this HelmRelease. - // +required + // +optional Chart HelmChartTemplate `json:"chart"` + // ChartRef holds a reference to a v1beta2.HelmChart resource + // +optional + ChartRef *CrosssNameSpaceSourceReference `json:"chartRef,omitempty"` + // Interval at which to reconcile the Helm release. // +kubebuilder:validation:Type=string // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" diff --git a/api/v2beta2/reference_types.go b/api/v2beta2/reference_types.go index 4c899fe5d..40acd5c68 100644 --- a/api/v2beta2/reference_types.go +++ b/api/v2beta2/reference_types.go @@ -42,6 +42,32 @@ type CrossNamespaceObjectReference struct { Namespace string `json:"namespace,omitempty"` } +// CrosssNameSpaceSourceReference contains enough information to let you locate +// the typed referenced object at cluster level. +type CrosssNameSpaceSourceReference struct { + // APIVersion of the referent. + // +optional + APIVersion string `json:"apiVersion,omitempty"` + + // Kind of the referent. + // +kubebuilder:validation:Enum=OCIRepository;HelmChart + // +required + Kind string `json:"kind"` + + // Name of the referent. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +required + Name string `json:"name"` + + // Namespace of the referent. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Optional + // +optional + Namespace string `json:"namespace,omitempty"` +} + // ValuesReference contains a reference to a resource containing Helm values, // and optionally the key they can be found at. type ValuesReference struct { diff --git a/api/v2beta2/zz_generated.deepcopy.go b/api/v2beta2/zz_generated.deepcopy.go index f58cdc02f..0d4f6491f 100644 --- a/api/v2beta2/zz_generated.deepcopy.go +++ b/api/v2beta2/zz_generated.deepcopy.go @@ -44,6 +44,21 @@ func (in *CrossNamespaceObjectReference) DeepCopy() *CrossNamespaceObjectReferen return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CrosssNameSpaceSourceReference) DeepCopyInto(out *CrosssNameSpaceSourceReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CrosssNameSpaceSourceReference. +func (in *CrosssNameSpaceSourceReference) DeepCopy() *CrosssNameSpaceSourceReference { + if in == nil { + return nil + } + out := new(CrosssNameSpaceSourceReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DriftDetection) DeepCopyInto(out *DriftDetection) { *out = *in @@ -245,6 +260,11 @@ func (in *HelmReleaseList) DeepCopyObject() runtime.Object { func (in *HelmReleaseSpec) DeepCopyInto(out *HelmReleaseSpec) { *out = *in in.Chart.DeepCopyInto(&out.Chart) + if in.ChartRef != nil { + in, out := &in.ChartRef, &out.ChartRef + *out = new(CrosssNameSpaceSourceReference) + **out = **in + } out.Interval = in.Interval if in.KubeConfig != nil { in, out := &in.KubeConfig, &out.KubeConfig diff --git a/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml b/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml index 77256224a..551f0cd3b 100644 --- a/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml +++ b/config/crd/bases/helm.toolkit.fluxcd.io_helmreleases.yaml @@ -1292,6 +1292,32 @@ spec: required: - spec type: object + chartRef: + description: ChartRef holds a reference to a v1beta2.HelmChart resource + properties: + apiVersion: + description: APIVersion of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - OCIRepository + - HelmChart + type: string + name: + description: Name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: Namespace of the referent. + maxLength: 63 + minLength: 1 + type: string + required: + - kind + - name + type: object dependsOn: description: DependsOn may contain a meta.NamespacedObjectReference slice with references to HelmRelease resources that must be ready @@ -2002,9 +2028,12 @@ spec: type: object type: array required: - - chart - interval type: object + x-kubernetes-validations: + - message: either chart or chartRef must be set + rule: (has(self.chart) && !has(self.chartRef) || (!has(self.chart) && + has(self.chartRef)) status: default: observedGeneration: -1 diff --git a/internal/controller/helmrelease_controller.go b/internal/controller/helmrelease_controller.go index 8e5d84e09..1068ae84d 100644 --- a/internal/controller/helmrelease_controller.go +++ b/internal/controller/helmrelease_controller.go @@ -108,11 +108,17 @@ func (r *HelmReleaseReconciler) SetupWithManager(ctx context.Context, mgr ctrl.M if err := mgr.GetFieldIndexer().IndexField(ctx, &v2.HelmRelease{}, v2.SourceIndexKey, func(o client.Object) []string { obj := o.(*v2.HelmRelease) + namespacedName := types.NamespacedName{} + if obj.Spec.ChartRef != nil { + namespacedName.Namespace = obj.Spec.ChartRef.Namespace + namespacedName.Name = obj.Spec.ChartRef.Name + } else { + namespacedName.Namespace = obj.Spec.Chart.GetNamespace(obj.GetNamespace()) + namespacedName.Name = obj.GetHelmChartName() + } + return []string{ - types.NamespacedName{ - Namespace: obj.Spec.Chart.GetNamespace(obj.GetNamespace()), - Name: obj.GetHelmChartName(), - }.String(), + namespacedName.String(), } }, ); err != nil { @@ -131,6 +137,11 @@ func (r *HelmReleaseReconciler) SetupWithManager(ctx context.Context, mgr ctrl.M handler.EnqueueRequestsFromMapFunc(r.requestsForHelmChartChange), builder.WithPredicates(intpredicates.SourceRevisionChangePredicate{}), ). + Watches( + &sourcev1.OCIRepository{}, + handler.EnqueueRequestsFromMapFunc(r.requestsForOCIRrepositoryChange), + builder.WithPredicates(intpredicates.SourceRevisionChangePredicate{}), + ). WithOptions(controller.Options{ RateLimiter: opts.RateLimiter, }).