diff --git a/cmd/flux/debug_helmrelease.go b/cmd/flux/debug_helmrelease.go index 0fcdfcab..040cae8f 100644 --- a/cmd/flux/debug_helmrelease.go +++ b/cmd/flux/debug_helmrelease.go @@ -40,15 +40,19 @@ WARNING: This command will print sensitive information if Kubernetes Secrets are flux debug hr podinfo --show-status # Export the final values of a Helm release composed from referred ConfigMaps and Secrets - flux debug hr podinfo --show-values > values.yaml`, + flux debug hr podinfo --show-values > values.yaml + + # Print the reconciliation history of a Helm release + flux debug hr podinfo --show-history`, RunE: debugHelmReleaseCmdRun, Args: cobra.ExactArgs(1), ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)), } type debugHelmReleaseFlags struct { - showStatus bool - showValues bool + showStatus bool + showValues bool + showHistory bool } var debugHelmReleaseArgs debugHelmReleaseFlags @@ -56,15 +60,26 @@ var debugHelmReleaseArgs debugHelmReleaseFlags func init() { debugHelmReleaseCmd.Flags().BoolVar(&debugHelmReleaseArgs.showStatus, "show-status", false, "print the status of the Helm release") debugHelmReleaseCmd.Flags().BoolVar(&debugHelmReleaseArgs.showValues, "show-values", false, "print the final values of the Helm release") + debugHelmReleaseCmd.Flags().BoolVar(&debugHelmReleaseArgs.showHistory, "show-history", false, "print the reconciliation history of the Helm release") debugCmd.AddCommand(debugHelmReleaseCmd) } func debugHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { name := args[0] - if (!debugHelmReleaseArgs.showStatus && !debugHelmReleaseArgs.showValues) || - (debugHelmReleaseArgs.showStatus && debugHelmReleaseArgs.showValues) { - return fmt.Errorf("either --show-status or --show-values must be set") + flagsSet := 0 + if debugHelmReleaseArgs.showStatus { + flagsSet++ + } + if debugHelmReleaseArgs.showValues { + flagsSet++ + } + if debugHelmReleaseArgs.showHistory { + flagsSet++ + } + + if flagsSet != 1 { + return fmt.Errorf("exactly one of --show-status, --show-values, or --show-history must be set") } ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) @@ -109,5 +124,19 @@ func debugHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { rootCmd.Print(string(values)) } + if debugHelmReleaseArgs.showHistory { + if len(hr.Status.History) == 0 { + hr.Status.History = helmv2.Snapshots{} + } + + history, err := yaml.Marshal(hr.Status.History) + if err != nil { + return err + } + + rootCmd.Println("# History documentation: https://fluxcd.io/flux/components/helm/helmreleases/#helmrelease-status") + rootCmd.Print(string(history)) + return nil + } return nil } diff --git a/cmd/flux/debug_helmrelease_test.go b/cmd/flux/debug_helmrelease_test.go index a9de9344..12f60017 100644 --- a/cmd/flux/debug_helmrelease_test.go +++ b/cmd/flux/debug_helmrelease_test.go @@ -56,6 +56,18 @@ func TestDebugHelmRelease(t *testing.T) { "testdata/debug_helmrelease/values-from.golden.yaml", tmpl, }, + { + "debug history", + "debug helmrelease test-with-history --show-history --show-status=false", + "testdata/debug_helmrelease/history.golden.yaml", + tmpl, + }, + { + "debug history empty", + "debug helmrelease test-values-inline --show-history --show-status=false", + "testdata/debug_helmrelease/history-empty.golden.yaml", + tmpl, + }, } for _, tt := range cases { diff --git a/cmd/flux/testdata/debug_helmrelease/history-empty.golden.yaml b/cmd/flux/testdata/debug_helmrelease/history-empty.golden.yaml new file mode 100644 index 00000000..c6ee02fa --- /dev/null +++ b/cmd/flux/testdata/debug_helmrelease/history-empty.golden.yaml @@ -0,0 +1,2 @@ +# History documentation: https://fluxcd.io/flux/components/helm/helmreleases/#helmrelease-status +[] diff --git a/cmd/flux/testdata/debug_helmrelease/history.golden.yaml b/cmd/flux/testdata/debug_helmrelease/history.golden.yaml new file mode 100644 index 00000000..5215ed77 --- /dev/null +++ b/cmd/flux/testdata/debug_helmrelease/history.golden.yaml @@ -0,0 +1,25 @@ +# History documentation: https://fluxcd.io/flux/components/helm/helmreleases/#helmrelease-status +- appVersion: 6.0.0 + chartName: podinfo + chartVersion: 6.0.0 + configDigest: sha256:abc123 + deleted: "2024-01-01T10:00:00Z" + digest: sha256:def456 + firstDeployed: "2024-01-01T09:00:00Z" + lastDeployed: "2024-01-01T10:00:00Z" + name: test-with-history + namespace: {{ .fluxns }} + status: superseded + version: 1 +- appVersion: 6.1.0 + chartName: podinfo + chartVersion: 6.1.0 + configDigest: sha256:xyz789 + deleted: null + digest: sha256:ghi012 + firstDeployed: "2024-01-01T11:00:00Z" + lastDeployed: "2024-01-01T11:00:00Z" + name: test-with-history + namespace: {{ .fluxns }} + status: deployed + version: 2 diff --git a/cmd/flux/testdata/debug_helmrelease/objects.yaml b/cmd/flux/testdata/debug_helmrelease/objects.yaml index 060aa71c..7083b1ef 100644 --- a/cmd/flux/testdata/debug_helmrelease/objects.yaml +++ b/cmd/flux/testdata/debug_helmrelease/objects.yaml @@ -46,6 +46,47 @@ spec: name: none optional: true --- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: test-with-history + namespace: {{ .fluxns }} +spec: + chartRef: + kind: OCIRepository + name: podinfo + interval: 5m0s + values: + image: + repository: stefanprodan/podinfo + tag: 5.0.0 +status: + observedGeneration: 1 + history: + - name: test-with-history + namespace: {{ .fluxns }} + version: 1 + configDigest: sha256:abc123 + chartName: podinfo + chartVersion: 6.0.0 + appVersion: 6.0.0 + deleted: "2024-01-01T10:00:00Z" + digest: sha256:def456 + firstDeployed: "2024-01-01T09:00:00Z" + lastDeployed: "2024-01-01T10:00:00Z" + status: superseded + - name: test-with-history + namespace: {{ .fluxns }} + version: 2 + configDigest: sha256:xyz789 + chartName: podinfo + chartVersion: 6.1.0 + appVersion: 6.1.0 + digest: sha256:ghi012 + firstDeployed: "2024-01-01T11:00:00Z" + lastDeployed: "2024-01-01T11:00:00Z" + status: deployed +--- apiVersion: v1 kind: ConfigMap metadata: