From 151ff937847b284080fd39cae3ef330c731d5ddb Mon Sep 17 00:00:00 2001 From: Rafal Korepta Date: Tue, 8 Oct 2024 14:01:46 +0200 Subject: [PATCH] Use new Chart Render functionality in console The `_shims.render-manifest` will call `console.render` only once to generate all console resources. It's prelude for redpanda helm chart and de-flux controller. --- charts/console/chart.go | 77 +++++++++++++++++++ charts/console/chart_test.go | 67 ++++++++++++++++ charts/console/deployment.go | 2 +- charts/console/helpers.go | 4 +- charts/console/templates/_chart.go.tpl | 13 ++++ charts/console/templates/_deployment.go.tpl | 2 +- charts/console/templates/_helpers.go.tpl | 4 +- charts/console/templates/configmap.yaml | 17 ---- charts/console/templates/deployment.yaml | 17 ---- .../{secret.yaml => entry-point.yaml} | 4 +- charts/console/templates/hpa.yaml | 17 ---- charts/console/templates/ingress.yaml | 17 ---- charts/console/templates/service.yaml | 17 ---- charts/console/templates/serviceaccount.yaml | 17 ---- 14 files changed, 165 insertions(+), 110 deletions(-) create mode 100644 charts/console/chart.go create mode 100644 charts/console/templates/_chart.go.tpl delete mode 100644 charts/console/templates/configmap.yaml delete mode 100644 charts/console/templates/deployment.yaml rename charts/console/templates/{secret.yaml => entry-point.yaml} (91%) delete mode 100644 charts/console/templates/hpa.yaml delete mode 100644 charts/console/templates/ingress.yaml delete mode 100644 charts/console/templates/service.yaml delete mode 100644 charts/console/templates/serviceaccount.yaml diff --git a/charts/console/chart.go b/charts/console/chart.go new file mode 100644 index 0000000000..03275b2b5e --- /dev/null +++ b/charts/console/chart.go @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You 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. +// +// +gotohelm:filename=_chart.go.tpl +package console + +import ( + _ "embed" + + "github.com/redpanda-data/helm-charts/pkg/gotohelm" + "github.com/redpanda-data/helm-charts/pkg/gotohelm/helmette" + "github.com/redpanda-data/helm-charts/pkg/kube" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" +) + +var ( + // Scheme is a [runtime.Scheme] with the appropriate extensions to load all + // objects produced by the redpanda chart. + Scheme = runtime.NewScheme() + + //go:embed Chart.yaml + chartYAML []byte + + //go:embed values.yaml + defaultValuesYAML []byte + + // ChartLabel is the go version of the redpanda helm chart. + Chart = gotohelm.MustLoad(chartYAML, defaultValuesYAML, render) +) + +// +gotohelm:ignore=true +func init() { + must(scheme.AddToScheme(Scheme)) +} + +// +gotohelm:ignore=true +func must(err error) { + if err != nil { + panic(err) + } +} + +// render is the entrypoint to both the go and helm versions of the redpanda +// helm chart. +// In helm, _shims.render-manifest is used to call and filter the output of +// this function. +// In go, this function should be call by executing [ChartLabel.Render], which will +// handle construction of [helmette.Dot], subcharting, and output filtering. +func render(dot *helmette.Dot) []kube.Object { + manifests := []kube.Object{ + ServiceAccount(dot), + Secret(dot), + ConfigMap(dot), + Service(dot), + Ingress(dot), + Deployment(dot), + HorizontalPodAutoscaler(dot), + } + + // NB: This slice may contain nil interfaces! + // Filtering happens elsewhere, don't call this function directly if you + // can avoid it. + return manifests +} diff --git a/charts/console/chart_test.go b/charts/console/chart_test.go index 0e652c13e1..6e84f963df 100644 --- a/charts/console/chart_test.go +++ b/charts/console/chart_test.go @@ -1,21 +1,28 @@ package console import ( + "context" "encoding/json" "fmt" "os" "regexp" "slices" + "strings" "testing" fuzz "github.com/google/gofuzz" + "github.com/redpanda-data/helm-charts/charts/redpanda" + "github.com/redpanda-data/helm-charts/pkg/gotohelm/helmette" "github.com/redpanda-data/helm-charts/pkg/helm" + "github.com/redpanda-data/helm-charts/pkg/kube" "github.com/redpanda-data/helm-charts/pkg/testutil" "github.com/santhosh-tekuri/jsonschema/v5" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/tools/txtar" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" "sigs.k8s.io/yaml" ) @@ -156,3 +163,63 @@ func TestGenerateCases(t *testing.T) { require.NoError(t, os.WriteFile("testdata/template-cases-generated.txtar", archive, 0o644)) } + +func TestGoHelmEquivalence(t *testing.T) { + client, err := helm.New(helm.Options{ConfigHome: testutil.TempDir(t)}) + require.NoError(t, err) + + values := PartialValues{ + Tests: &PartialEnableable{ + Enabled: ptr.To(false), + }, + Secret: &PartialSecretConfig{ + Login: &PartialLoginSecrets{ + JWTSecret: ptr.To("SECRET"), + }, + }, + Ingress: &PartialIngressConfig{ + Enabled: ptr.To(true), + }, + } + + goObjs, err := Chart.Render(kube.Config{}, helmette.Release{ + Name: "gotohelm", + Namespace: "mynamespace", + Service: "Helm", + }, values) + require.NoError(t, err) + + rendered, err := client.Template(context.Background(), ".", helm.TemplateOptions{ + Name: "gotohelm", + Namespace: "mynamespace", + Values: values, + }) + require.NoError(t, err) + + helmObjs, err := kube.DecodeYAML(rendered, redpanda.Scheme) + require.NoError(t, err) + + slices.SortStableFunc(helmObjs, func(a, b kube.Object) int { + aStr := fmt.Sprintf("%s/%s/%s", a.GetObjectKind().GroupVersionKind().String(), a.GetNamespace(), a.GetName()) + bStr := fmt.Sprintf("%s/%s/%s", b.GetObjectKind().GroupVersionKind().String(), b.GetNamespace(), b.GetName()) + return strings.Compare(aStr, bStr) + }) + + slices.SortStableFunc(goObjs, func(a, b kube.Object) int { + aStr := fmt.Sprintf("%s/%s/%s", a.GetObjectKind().GroupVersionKind().String(), a.GetNamespace(), a.GetName()) + bStr := fmt.Sprintf("%s/%s/%s", b.GetObjectKind().GroupVersionKind().String(), b.GetNamespace(), b.GetName()) + return strings.Compare(aStr, bStr) + }) + + // resource.Quantity is a special object. To Ensure they compare correctly, + // we'll round trip it through JSON so the internal representations will + // match (assuming the values are actually equal). + assert.Equal(t, len(helmObjs), len(goObjs)) + + // Iterate and compare instead of a single comparison for better error + // messages. Some divergences will fail an Equal check on slices but not + // report which element(s) aren't equal. + for i := range helmObjs { + assert.Equal(t, helmObjs[i], goObjs[i]) + } +} diff --git a/charts/console/deployment.go b/charts/console/deployment.go index 47537d40d2..67ed5669df 100644 --- a/charts/console/deployment.go +++ b/charts/console/deployment.go @@ -59,7 +59,7 @@ func Deployment(dot *helmette.Dot) *appsv1.Deployment { } var initContainers []corev1.Container - if values.InitContainers.ExtraInitContainers != nil { + if !helmette.Empty(values.InitContainers.ExtraInitContainers) { initContainers = helmette.UnmarshalYamlArray[corev1.Container](helmette.Tpl(*values.InitContainers.ExtraInitContainers, dot)) } diff --git a/charts/console/helpers.go b/charts/console/helpers.go index eed4aa7119..64f3da5d17 100644 --- a/charts/console/helpers.go +++ b/charts/console/helpers.go @@ -51,7 +51,7 @@ func Fullname(dot *helmette.Dot) string { } // Create chart name and version as used by the chart label. -func Chart(dot *helmette.Dot) string { +func ChartLabel(dot *helmette.Dot) string { chart := fmt.Sprintf("%s-%s", dot.Chart.Name, dot.Chart.Version) return cleanForK8s(strings.ReplaceAll(chart, "+", "_")) } @@ -61,7 +61,7 @@ func Labels(dot *helmette.Dot) map[string]string { values := helmette.Unwrap[Values](dot.Values) labels := map[string]string{ - "helm.sh/chart": Chart(dot), + "helm.sh/chart": ChartLabel(dot), "app.kubernetes.io/managed-by": dot.Release.Service, } diff --git a/charts/console/templates/_chart.go.tpl b/charts/console/templates/_chart.go.tpl new file mode 100644 index 0000000000..47f236d6ff --- /dev/null +++ b/charts/console/templates/_chart.go.tpl @@ -0,0 +1,13 @@ +{{- /* Generated from "chart.go" */ -}} + +{{- define "console.render" -}} +{{- $dot := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $manifests := (list (get (fromJson (include "console.ServiceAccount" (dict "a" (list $dot) ))) "r") (get (fromJson (include "console.Secret" (dict "a" (list $dot) ))) "r") (get (fromJson (include "console.ConfigMap" (dict "a" (list $dot) ))) "r") (get (fromJson (include "console.Service" (dict "a" (list $dot) ))) "r") (get (fromJson (include "console.Ingress" (dict "a" (list $dot) ))) "r") (get (fromJson (include "console.Deployment" (dict "a" (list $dot) ))) "r") (get (fromJson (include "console.HorizontalPodAutoscaler" (dict "a" (list $dot) ))) "r")) -}} +{{- $_is_returning = true -}} +{{- (dict "r" $manifests) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + diff --git a/charts/console/templates/_deployment.go.tpl b/charts/console/templates/_deployment.go.tpl index 1cba99dac4..b9e686da40 100644 --- a/charts/console/templates/_deployment.go.tpl +++ b/charts/console/templates/_deployment.go.tpl @@ -39,7 +39,7 @@ {{- $replicas = ($values.replicaCount | int) -}} {{- end -}} {{- $initContainers := (coalesce nil) -}} -{{- if (ne $values.initContainers.extraInitContainers (coalesce nil)) -}} +{{- if (not (empty $values.initContainers.extraInitContainers)) -}} {{- $initContainers = (fromYamlArray (tpl $values.initContainers.extraInitContainers $dot)) -}} {{- end -}} {{- $volumeMounts := (list (mustMergeOverwrite (dict "name" "" "mountPath" "" ) (dict "name" "configs" "mountPath" "/etc/console/configs" "readOnly" true ))) -}} diff --git a/charts/console/templates/_helpers.go.tpl b/charts/console/templates/_helpers.go.tpl index 88b00025d7..05ad609654 100644 --- a/charts/console/templates/_helpers.go.tpl +++ b/charts/console/templates/_helpers.go.tpl @@ -34,7 +34,7 @@ {{- end -}} {{- end -}} -{{- define "console.Chart" -}} +{{- define "console.ChartLabel" -}} {{- $dot := (index .a 0) -}} {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} @@ -50,7 +50,7 @@ {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} {{- $values := $dot.Values.AsMap -}} -{{- $labels := (dict "helm.sh/chart" (get (fromJson (include "console.Chart" (dict "a" (list $dot) ))) "r") "app.kubernetes.io/managed-by" $dot.Release.Service ) -}} +{{- $labels := (dict "helm.sh/chart" (get (fromJson (include "console.ChartLabel" (dict "a" (list $dot) ))) "r") "app.kubernetes.io/managed-by" $dot.Release.Service ) -}} {{- if (ne $dot.Chart.AppVersion "") -}} {{- $_ := (set $labels "app.kubernetes.io/version" $dot.Chart.AppVersion) -}} {{- end -}} diff --git a/charts/console/templates/configmap.yaml b/charts/console/templates/configmap.yaml deleted file mode 100644 index cffd69938f..0000000000 --- a/charts/console/templates/configmap.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You 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. -*/}} -{{- include "_shims.render-manifest" (list "console.ConfigMap" .) -}} diff --git a/charts/console/templates/deployment.yaml b/charts/console/templates/deployment.yaml deleted file mode 100644 index 48a149041b..0000000000 --- a/charts/console/templates/deployment.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You 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. -*/}} -{{- include "_shims.render-manifest" (list "console.Deployment" .) -}} diff --git a/charts/console/templates/secret.yaml b/charts/console/templates/entry-point.yaml similarity index 91% rename from charts/console/templates/secret.yaml rename to charts/console/templates/entry-point.yaml index aeeeba25e1..01fb6d68b2 100644 --- a/charts/console/templates/secret.yaml +++ b/charts/console/templates/entry-point.yaml @@ -1,4 +1,4 @@ -{{/* +{{- /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. @@ -14,4 +14,4 @@ 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. */}} -{{- include "_shims.render-manifest" (list "console.Secret" .) -}} +{{- include "_shims.render-manifest" (list "console.render" .) -}} diff --git a/charts/console/templates/hpa.yaml b/charts/console/templates/hpa.yaml deleted file mode 100644 index 9cfc4a132e..0000000000 --- a/charts/console/templates/hpa.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You 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. -*/}} -{{- include "_shims.render-manifest" (list "console.HorizontalPodAutoscaler" .) -}} diff --git a/charts/console/templates/ingress.yaml b/charts/console/templates/ingress.yaml deleted file mode 100644 index ef3867869c..0000000000 --- a/charts/console/templates/ingress.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You 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. -*/}} -{{- include "_shims.render-manifest" (list "console.Ingress" .) -}} diff --git a/charts/console/templates/service.yaml b/charts/console/templates/service.yaml deleted file mode 100644 index 0f1621fafc..0000000000 --- a/charts/console/templates/service.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You 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. -*/}} -{{- include "_shims.render-manifest" (list "console.Service" .) -}} diff --git a/charts/console/templates/serviceaccount.yaml b/charts/console/templates/serviceaccount.yaml deleted file mode 100644 index 9215af70ed..0000000000 --- a/charts/console/templates/serviceaccount.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{/* -Licensed to the Apache Software Foundation (ASF) under one or more -contributor license agreements. See the NOTICE file distributed with -this work for additional information regarding copyright ownership. -The ASF licenses this file to You 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. -*/}} -{{- include "_shims.render-manifest" (list "console.ServiceAccount" .) -}}