Skip to content

Commit

Permalink
Implement flux debug helmrelease command
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
  • Loading branch information
stefanprodan committed Dec 10, 2024
1 parent b1bdab4 commit b16bbaa
Show file tree
Hide file tree
Showing 10 changed files with 306 additions and 2 deletions.
31 changes: 31 additions & 0 deletions cmd/flux/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2024 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"github.com/spf13/cobra"
)

var debugCmd = &cobra.Command{
Use: "debug",
Short: "Debug a flux resource",
Long: `The debug command can be used to troubleshoot failing resource reconciliations.`,
}

func init() {
rootCmd.AddCommand(debugCmd)
}
122 changes: 122 additions & 0 deletions cmd/flux/debug_helmrelease.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
Copyright 2024 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"context"
"fmt"

helmv2 "github.com/fluxcd/helm-controller/api/v2"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/chartutil"
"github.com/go-logr/logr"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/yaml"

"github.com/fluxcd/flux2/v2/internal/utils"
)

var debugHelmReleaseCmd = &cobra.Command{
Use: "helmrelease [name]",
Aliases: []string{"hr"},
Short: "Debug a HelmRelease resource",
Long: `The debug helmrelease command can be used to troubleshoot failing Helm release reconciliations.
WARNING: This command will print sensitive information if Kubernetes Secrets are referenced in the HelmRelease .spec.valuesFrom field.`,
Example: ` # Print the status of a Helm release
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`,
RunE: debugHelmReleaseCmdRun,
Args: cobra.ExactArgs(1),
}

type debugHelmReleaseFlags struct {
name string
showStatus bool
showValues bool
}

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")
debugCmd.AddCommand(debugHelmReleaseCmd)
}

func debugHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
name := args[0]

if debugHelmReleaseArgs.showStatus == false && debugHelmReleaseArgs.showValues == false {
return fmt.Errorf("either --show-status or --show-values must be set")
}

ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()

kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return err
}

hr := &helmv2.HelmRelease{}
hrName := types.NamespacedName{Namespace: *kubeconfigArgs.Namespace, Name: name}
if err := kubeClient.Get(ctx, hrName, hr); err != nil {
return err
}

if debugHelmReleaseArgs.showStatus {
status, err := yaml.Marshal(hr.Status)
if err != nil {
return err
}
rootCmd.Print(string(status))
}

if debugHelmReleaseArgs.showValues {
// TODO(stefan): remove the mapping when helm-controller/api v1.2.0 has been released
var valuesRefs []meta.ValuesReference
for _, source := range hr.Spec.ValuesFrom {
valuesRefs = append(valuesRefs, meta.ValuesReference{
Kind: source.Kind,
Name: source.Name,
ValuesKey: source.ValuesKey,
Optional: source.Optional,
})
}

finalValues, err := chartutil.ChartValuesFromReferences(ctx,
logr.Discard(),
kubeClient,
hr.GetNamespace(),
hr.GetValues(),
valuesRefs...)
if err != nil {
return err
}

values, err := yaml.Marshal(finalValues)
if err != nil {
return err
}
rootCmd.Print(string(values))
}

return nil
}
55 changes: 55 additions & 0 deletions cmd/flux/debug_helmrelease_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//go:build unit
// +build unit

package main

import (
"testing"
)

func TestDebugHelmRelease(t *testing.T) {
namespace := allocateNamespace("debug")

objectFile := "testdata/debug_helmrelease/objects.yaml"
tmpl := map[string]string{
"fluxns": namespace,
}
testEnv.CreateObjectFile(objectFile, tmpl, t)

cases := []struct {
name string
arg string
goldenFile string
tmpl map[string]string
}{
{
"debug status",
"debug helmrelease test-values-inline --show-status --show-values=false",
"testdata/debug_helmrelease/status.golden.yaml",
tmpl,
},
{
"debug values",
"debug helmrelease test-values-inline --show-values --show-status=false",
"testdata/debug_helmrelease/values-inline.golden.yaml",
tmpl,
},
{
"debug values from",
"debug helmrelease test-values-from --show-values --show-status=false",
"testdata/debug_helmrelease/values-from.golden.yaml",
tmpl,
},
}

for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
cmd := cmdTestCase{
args: tt.arg + " -n=" + namespace,
assert: assertGoldenTemplateFile(tt.goldenFile, tmpl),
}

cmd.runTestCmd(t)
})
}
}
1 change: 1 addition & 0 deletions cmd/flux/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ func resetCmdArgs() {
output: "yaml",
}
envsubstArgs = envsubstFlags{}
debugHelmReleaseArgs = debugHelmReleaseFlags{}
}

func isChangeError(err error) bool {
Expand Down
63 changes: 63 additions & 0 deletions cmd/flux/testdata/debug_helmrelease/objects.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .fluxns }}
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: test-values-inline
namespace: {{ .fluxns }}
spec:
chartRef:
kind: OCIRepository
name: podinfo
interval: 5m0s
values:
image:
repository: stefanprodan/podinfo
tag: 5.0.0
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: test-values-from
namespace: {{ .fluxns }}
spec:
chartRef:
kind: OCIRepository
name: podinfo
interval: 5m0s
values:
image:
repository: stefanprodan/podinfo
tag: 5.0.0
valuesFrom:
- kind: ConfigMap
name: test
- kind: Secret
name: test
valuesKey: secrets.yaml
- kind: ConfigMap
name: none
optional: true
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test
namespace: {{ .fluxns }}
data:
values.yaml: |
cm: "test"
override: "cm"
---
apiVersion: v1
kind: Secret
metadata:
name: test
namespace: {{ .fluxns }}
stringData:
secrets.yaml: |
secret: "test"
override: "secret"
1 change: 1 addition & 0 deletions cmd/flux/testdata/debug_helmrelease/status.golden.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
observedGeneration: -1
6 changes: 6 additions & 0 deletions cmd/flux/testdata/debug_helmrelease/values-from.golden.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cm: test
image:
repository: stefanprodan/podinfo
tag: 5.0.0
override: secret
secret: test
3 changes: 3 additions & 0 deletions cmd/flux/testdata/debug_helmrelease/values-inline.golden.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
image:
repository: stefanprodan/podinfo
tag: 5.0.0
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/fluxcd/notification-controller/api v1.4.0
github.com/fluxcd/pkg/apis/event v0.11.0
github.com/fluxcd/pkg/apis/meta v1.8.0
github.com/fluxcd/pkg/chartutil v1.0.0
github.com/fluxcd/pkg/envsubst v1.2.0
github.com/fluxcd/pkg/git v0.22.0
github.com/fluxcd/pkg/git/gogit v0.22.0
Expand Down Expand Up @@ -172,10 +173,12 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/hashstructure v1.1.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/spdystream v0.4.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
Expand Down Expand Up @@ -210,6 +213,9 @@ require (
github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/go-gitlab v0.114.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
go.opentelemetry.io/contrib/bridges/prometheus v0.54.0 // indirect
go.opentelemetry.io/contrib/exporters/autoexport v0.54.0 // indirect
Expand Down Expand Up @@ -248,6 +254,7 @@ require (
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
helm.sh/helm/v3 v3.16.3 // indirect
k8s.io/component-base v0.31.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3 // indirect
Expand Down
19 changes: 17 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapw
github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
Expand Down Expand Up @@ -177,6 +177,8 @@ github.com/fluxcd/pkg/apis/meta v1.8.0 h1:wF7MJ3mu5ds9Y/exWU1yU0YyDb8s1VwwQnZYuM
github.com/fluxcd/pkg/apis/meta v1.8.0/go.mod h1:OJGH7I//SNO6zcso80oBRuf5H8oU8etZDeTgCcH7qHo=
github.com/fluxcd/pkg/auth v0.1.0 h1:qODzb3BeW/8hkzVeq+8GqZlOEm39xeaxAkJn02Jc+Fo=
github.com/fluxcd/pkg/auth v0.1.0/go.mod h1:34t6toih5y9W53kIBTubQsGwKsNnBlc7VDE+FqZenyk=
github.com/fluxcd/pkg/chartutil v1.0.0 h1:Hj5mPiUp/nanZPVK7Ur0TDN4BCMhuoxKjvAmBbnX7DE=
github.com/fluxcd/pkg/chartutil v1.0.0/go.mod h1:GBo3G78aiK48BppJ/YoDUv8L1NDLHrMpK3K5uiazQ0A=
github.com/fluxcd/pkg/envsubst v1.2.0 h1:hbn3Zie/+/88uDTw4EbqD9/SXO+LP97FZhZFzPtVVug=
github.com/fluxcd/pkg/envsubst v1.2.0/go.mod h1:ws8rM2Zmy+wm4iryW6pnTBuerMtwT5JQpDty+sHtCG8=
github.com/fluxcd/pkg/git v0.22.0 h1:3O7XgQEaCgjC0irKkXkT1wWi5r1o4AnrxGhV8Mao85o=
Expand Down Expand Up @@ -401,6 +403,8 @@ github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
Expand All @@ -409,6 +413,8 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0=
github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
Expand Down Expand Up @@ -538,6 +544,13 @@ github.com/xanzy/go-gitlab v0.114.0 h1:0wQr/KBckwrZPfEMjRqpUz0HmsKKON9UhCYv9KDy1
github.com/xanzy/go-gitlab v0.114.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down Expand Up @@ -727,6 +740,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
helm.sh/helm/v3 v3.16.3 h1:kb8bSxMeRJ+knsK/ovvlaVPfdis0X3/ZhYCSFRP+YmY=
helm.sh/helm/v3 v3.16.3/go.mod h1:zeVWGDR4JJgiRbT3AnNsjYaX8OTJlIE9zC+Q7F7iUSU=
k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8=
k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE=
k8s.io/apiextensions-apiserver v0.31.3 h1:+GFGj2qFiU7rGCsA5o+p/rul1OQIq6oYpQw4+u+nciE=
Expand Down

0 comments on commit b16bbaa

Please sign in to comment.