From 9fd7159bebee421395a496ba3ae828ebb9a474a3 Mon Sep 17 00:00:00 2001 From: "Sam Wang (holyspectral)" Date: Tue, 13 Feb 2024 13:25:01 -0500 Subject: [PATCH] feat: support helm dryrun=server Signed-off-by: Sam Wang (holyspectral) --- internal/cmd/helm-operator/run/cmd.go | 1 + internal/helm/controller/controller.go | 2 ++ internal/helm/controller/reconcile.go | 3 ++- internal/helm/release/manager.go | 3 +++ internal/helm/release/manager_factory.go | 11 ++++++----- internal/helm/watches/watches.go | 1 + internal/helm/watches/watches_test.go | 25 +++++++++++++++++++++++- 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/internal/cmd/helm-operator/run/cmd.go b/internal/cmd/helm-operator/run/cmd.go index 91eb4aa7e9c..960d75a2352 100644 --- a/internal/cmd/helm-operator/run/cmd.go +++ b/internal/cmd/helm-operator/run/cmd.go @@ -203,6 +203,7 @@ func run(cmd *cobra.Command, f *flags.Flags) { SuppressOverrideValues: f.SuppressOverrideValues, MaxConcurrentReconciles: f.MaxConcurrentReconciles, Selector: w.Selector, + DryRunOption: w.DryRunOption, }) if err != nil { log.Error(err, "Failed to add manager factory to controller.") diff --git a/internal/helm/controller/controller.go b/internal/helm/controller/controller.go index af007f856ce..b958911ce87 100644 --- a/internal/helm/controller/controller.go +++ b/internal/helm/controller/controller.go @@ -52,6 +52,7 @@ type WatchOptions struct { SuppressOverrideValues bool MaxConcurrentReconciles int Selector metav1.LabelSelector + DryRunOption string } // Add creates a new helm operator controller and adds it to the manager @@ -66,6 +67,7 @@ func Add(mgr manager.Manager, options WatchOptions) error { ReconcilePeriod: options.ReconcilePeriod, OverrideValues: options.OverrideValues, SuppressOverrideValues: options.SuppressOverrideValues, + DryRunOption: options.DryRunOption, } c, err := controller.New(controllerName, mgr, controller.Options{ diff --git a/internal/helm/controller/reconcile.go b/internal/helm/controller/reconcile.go index 386b37aba25..f35dbbaf26e 100644 --- a/internal/helm/controller/reconcile.go +++ b/internal/helm/controller/reconcile.go @@ -55,6 +55,7 @@ type HelmOperatorReconciler struct { OverrideValues map[string]string SuppressOverrideValues bool releaseHook ReleaseHookFunc + DryRunOption string } const ( @@ -96,7 +97,7 @@ func (r HelmOperatorReconciler) Reconcile(ctx context.Context, request reconcile return reconcile.Result{}, err } - manager, err := r.ManagerFactory.NewManager(o, r.OverrideValues) + manager, err := r.ManagerFactory.NewManager(o, r.OverrideValues, r.DryRunOption) if err != nil { log.Error(err, "Failed to get release manager") return reconcile.Result{}, err diff --git a/internal/helm/release/manager.go b/internal/helm/release/manager.go index 62744efcd12..f4b97d0714f 100644 --- a/internal/helm/release/manager.go +++ b/internal/helm/release/manager.go @@ -75,6 +75,8 @@ type manager struct { isUpgradeRequired bool deployedRelease *rpb.Release chart *cpb.Chart + + dryRunOption string } type InstallOption func(*action.Install) error @@ -159,6 +161,7 @@ func (m manager) getCandidateRelease(namespace, name string, chart *cpb.Chart, upgrade := action.NewUpgrade(m.actionConfig) upgrade.Namespace = namespace upgrade.DryRun = true + upgrade.DryRunOption = m.dryRunOption return upgrade.Run(name, chart, values) } diff --git a/internal/helm/release/manager_factory.go b/internal/helm/release/manager_factory.go index d0eeb4704ff..452266de4e2 100644 --- a/internal/helm/release/manager_factory.go +++ b/internal/helm/release/manager_factory.go @@ -33,7 +33,7 @@ import ( // improves decoupling between reconciliation logic and the Helm backend // components used to manage releases. type ManagerFactory interface { - NewManager(r *unstructured.Unstructured, overrideValues map[string]string) (Manager, error) + NewManager(r *unstructured.Unstructured, overrideValues map[string]string, dryRunOption string) (Manager, error) } type managerFactory struct { @@ -47,7 +47,7 @@ func NewManagerFactory(mgr crmanager.Manager, acg client.ActionConfigGetter, cha return &managerFactory{mgr, acg, chartDir} } -func (f managerFactory) NewManager(cr *unstructured.Unstructured, overrideValues map[string]string) (Manager, error) { +func (f managerFactory) NewManager(cr *unstructured.Unstructured, overrideValues map[string]string, dryRunOption string) (Manager, error) { actionConfig, err := f.acg.ActionConfigFor(cr) if err != nil { return nil, fmt.Errorf("failed to get helm action config: %w", err) @@ -86,9 +86,10 @@ func (f managerFactory) NewManager(cr *unstructured.Unstructured, overrideValues releaseName: releaseName, namespace: cr.GetNamespace(), - chart: crChart, - values: values, - status: types.StatusFor(cr), + chart: crChart, + values: values, + status: types.StatusFor(cr), + dryRunOption: dryRunOption, }, nil } diff --git a/internal/helm/watches/watches.go b/internal/helm/watches/watches.go index e1bbfadac6d..17fdcb35d3e 100644 --- a/internal/helm/watches/watches.go +++ b/internal/helm/watches/watches.go @@ -40,6 +40,7 @@ type Watch struct { OverrideValues map[string]string `json:"overrideValues,omitempty"` Selector metav1.LabelSelector `json:"selector"` ReconcilePeriod metav1.Duration `json:"reconcilePeriod,omitempty"` + DryRunOption string `json:"dryRunOption,omitempty"` } // UnmarshalYAML unmarshals an individual watch from the Helm watches.yaml file diff --git a/internal/helm/watches/watches_test.go b/internal/helm/watches/watches_test.go index 86f1e2826d7..9c8721ab1b9 100644 --- a/internal/helm/watches/watches_test.go +++ b/internal/helm/watches/watches_test.go @@ -101,7 +101,30 @@ func TestLoadReader(t *testing.T) { }, expectErr: false, }, - + { + name: "valid with dry run option", + data: `--- +- group: mygroup + version: v1alpha1 + kind: MyKind + chart: ../../../internal/plugins/helm/v1/chartutil/testdata/test-chart + watchDependentResources: false + overrideValues: + key: $MY_VALUE + dryRunOption: server +`, + env: map[string]string{"MY_VALUE": "value"}, + expectWatches: []Watch{ + { + GroupVersionKind: schema.GroupVersionKind{Group: "mygroup", Version: "v1alpha1", Kind: "MyKind"}, + ChartDir: "../../../internal/plugins/helm/v1/chartutil/testdata/test-chart", + WatchDependentResources: &falseVal, + OverrideValues: map[string]string{"key": "value"}, + DryRunOption: "server", + }, + }, + expectErr: false, + }, { name: "invalid with override template expansion", data: `---