diff --git a/internal/workflows/steps/chart.go b/internal/workflows/steps/chart.go index e36a1a5..fa5fdac 100644 --- a/internal/workflows/steps/chart.go +++ b/internal/workflows/steps/chart.go @@ -128,7 +128,7 @@ func (r *chartStepHandler) valuesOptions(id string, res []*v1alpha1.Data) (opts } r.logr.Debug(fmt.Sprintf( - "DBG [chart:%s]: set (name: %s, value: %s)", + "[chart:%s]: set (name: %s, value: %s)", id, el.Name, ellipsis(strval(val), 20))) } } diff --git a/internal/workflows/steps/chart_test.go b/internal/workflows/steps/chart_test.go new file mode 100644 index 0000000..c900ae8 --- /dev/null +++ b/internal/workflows/steps/chart_test.go @@ -0,0 +1,110 @@ +//go:build integration +// +build integration + +package steps + +import ( + "fmt" + "os" + "testing" + + "github.com/krateoplatformops/installer/apis/workflows/v1alpha1" + "github.com/krateoplatformops/installer/internal/cache" + "github.com/krateoplatformops/installer/internal/helmclient" + "github.com/krateoplatformops/installer/internal/ptr" + "github.com/krateoplatformops/provider-runtime/pkg/logging" + "helm.sh/helm/v3/pkg/action" + pkgcli "helm.sh/helm/v3/pkg/cli" + "helm.sh/helm/v3/pkg/getter" +) + +func TestChartTemplate(t *testing.T) { + const ( + ns = "demo-system" + chartPath = "../../../testdata/chart-unit-test" + ) + + data := []*v1alpha1.Data{ + { + Name: "sftp.allowedMACs", + Value: "null", + AsString: ptr.To(true), + }, + { + Name: "env.KRATEO_GATEWAY_DNS_NAMES", + Value: "{krateo-gateway.sticz.svc,$KRATEO_GATEWAY_INGRESS_HOST}", + }, + } + + env := cache.New[string, string]() + env.Set("KRATEO_GATEWAY_INGRESS_HOST", "http://sti.cz") + + hdl, err := chartStepHandlerForNamespace(ns, env) + if err != nil { + t.Fatal(err) + } + + opts := hdl.valuesOptions("test", data) + + yml, err := renderChart(&helmclient.ChartSpec{ + Namespace: ns, + ValuesOptions: opts, + }, ns, chartPath) + if err != nil { + t.Fatal(err) + } + + fmt.Println(yml) +} + +func chartStepHandlerForNamespace(ns string, env *cache.Cache[string, string]) (*chartStepHandler, error) { + rc, err := newRestConfig() + if err != nil { + return nil, err + } + + cli, err := helmClientForNamespace(rc, ns) + if err != nil { + return nil, err + } + + logr := logging.NewLogrLogger(newStdoutLogger()) + + return &chartStepHandler{ + cli: cli, env: env, + subst: func(k string) string { + if v, ok := env.Get(k); ok { + return v + } + + return "$" + k + }, + logr: logr, + }, nil +} + +func renderChart(spec *helmclient.ChartSpec, ns, chartPath string) (string, error) { + p := getter.All(pkgcli.New()) + values, err := spec.GetValuesMap(p) + if err != nil { + return "", err + } + + chart, err := loadChart(os.DirFS(chartPath)) + if err != nil { + return "", err + } + + client := action.NewInstall(&action.Configuration{}) + client.ClientOnly = true + client.DryRun = true + client.ReleaseName = "test" + client.IncludeCRDs = true + client.Namespace = ns + + rel, err := client.Run(chart, values) + if err != nil { + return "", fmt.Errorf("could not render helm chart correctly: %w", err) + } + return rel.Manifest, nil +} diff --git a/internal/workflows/steps/support_test.go b/internal/workflows/steps/support_test.go index d86e214..7f7b39a 100644 --- a/internal/workflows/steps/support_test.go +++ b/internal/workflows/steps/support_test.go @@ -6,6 +6,7 @@ package steps import ( "fmt" "io" + "io/fs" "log" "os" "path/filepath" @@ -15,6 +16,8 @@ import ( "github.com/go-logr/logr/funcr" "github.com/krateoplatformops/installer/internal/helmclient" "github.com/krateoplatformops/provider-runtime/pkg/logging" + "helm.sh/helm/v3/pkg/chart" + "helm.sh/helm/v3/pkg/chart/loader" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" ) @@ -86,3 +89,34 @@ func newStdoutLogger() logr.Logger { } }, funcr.Options{}) } + +func loadChart(f fs.FS) (*chart.Chart, error) { + files := []*loader.BufferedFile{} + + err := fs.WalkDir(f, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.IsDir() { + return nil + } + + data, err := fs.ReadFile(f, path) + if err != nil { + return fmt.Errorf("could not read manifest %s: %w", path, err) + } + + files = append(files, &loader.BufferedFile{ + Name: path, + Data: data, + }) + + return nil + }) + if err != nil { + return nil, fmt.Errorf("could not walk chart directory: %w", err) + } + + return loader.LoadFiles(files) +} diff --git a/testdata/chart-unit-test/Chart.yaml b/testdata/chart-unit-test/Chart.yaml new file mode 100644 index 0000000..b0b23f4 --- /dev/null +++ b/testdata/chart-unit-test/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: some-chart +version: 1.0.0 +appVersion: 1.0.0 diff --git a/testdata/chart-unit-test/templates/configmap.yaml b/testdata/chart-unit-test/templates/configmap.yaml new file mode 100644 index 0000000..ad550fb --- /dev/null +++ b/testdata/chart-unit-test/templates/configmap.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-%s" .Chart.Name .Release.Name | trunc 63 | trimSuffix "-" }} + namespace: {{ .Release.Namespace }} + labels: + {{- with .Values.labels -}} + {{ toYaml . | nindent 4 }} + {{- end }} +data: + allowedMACs: {{ .Values.sftp.allowedMACs }} + KRATEO_GATEWAY_DNS_NAMES: {{ .Values.env.KRATEO_GATEWAY_DNS_NAMES }} + something: something diff --git a/testdata/chart-unit-test/templates/secret.yaml b/testdata/chart-unit-test/templates/secret.yaml new file mode 100644 index 0000000..bc1bdd6 --- /dev/null +++ b/testdata/chart-unit-test/templates/secret.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-%s" .Chart.Name .Release.Name | trunc 63 | trimSuffix "-" }} + namespace: {{ .Release.Namespace }} + labels: + {{- with .Values.labels -}} + {{ toYaml . | nindent 4 }} + {{- end }} +stringData: + something-secret: shhhhh \ No newline at end of file diff --git a/testdata/chart-unit-test/values.yaml b/testdata/chart-unit-test/values.yaml new file mode 100644 index 0000000..7c98ad8 --- /dev/null +++ b/testdata/chart-unit-test/values.yaml @@ -0,0 +1,8 @@ +labels: + some: default + +sftp: + allowedMAC: xxx + +env: + KRATEO_GATEWAY_DNS_NAMES: yyy \ No newline at end of file