Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,11 @@ generate-restore-yaml:
generate-backup-yaml:
./cmd/example-gen/scripts/generate.sh ps-backup

manifests: kustomize generate generate-cr-yaml generate-restore-yaml generate-backup-yaml ## Generate Kubernetes manifests (CRDs, RBAC, operator deployment)
.PHONY: generate-helm-chart
generate-helm-chart:
./cmd/example-gen/scripts/generate.sh chart

manifests: kustomize generate generate-cr-yaml generate-restore-yaml generate-backup-yaml generate-helm-chart ## Generate Kubernetes manifests (CRDs, RBAC, operator deployment)
$(KUSTOMIZE) build config/crd/ > $(DEPLOYDIR)/crd.yaml
echo "---" >> $(DEPLOYDIR)/crd.yaml

Expand Down
63 changes: 63 additions & 0 deletions cmd/example-gen/cmd/chart-gen/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main

import (
"embed"
"fmt"
"os"

"github.com/elastic/crd-ref-docs/config"
"github.com/elastic/crd-ref-docs/processor"
"github.com/pkg/errors"

"github.com/percona/percona-server-mysql-operator/cmd/example-gen/internal/render"
)

//go:embed templates/*.tpl
var templates embed.FS

func main() {
if len(os.Args) != 2 {
fmt.Printf("Expected 1 argument (source path). Got %d\n", len(os.Args)-1)
os.Exit(1)
}
if err := printHelm(os.Args[1]); err != nil {
panic(err)
}
}

func printHelm(sourcePath string) error {
conf := &config.Config{
Processor: config.ProcessorConfig{
IgnoreTypes: []string{
"PerconaServerMySQLStatus",
"PiTRSpec",
},
IgnoreFields: []string{
// Deprecated field
"initImage",
},
},
Flags: config.Flags{
SourcePath: sourcePath,
MaxDepth: 20,
},
}

gvd, err := processor.Process(conf)
if err != nil {
return errors.Wrap(err, "process")
}
if len(gvd) != 1 {
return errors.New("unexpected gvd length")
}

t, ok := gvd[0].Types["PerconaServerMySQL"]
if !ok {
return errors.New("PerconaServerMySQL type is not found")
}
if err := render.Helm(os.Stdout, t, templates); err != nil {
return errors.Wrap(err, "render")
}

return nil
}
61 changes: 61 additions & 0 deletions cmd/example-gen/cmd/chart-gen/templates/helm.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{{/* vim: filetype=gotmpl */}}
{{- define "main" -}}
{{ "{{/* vim: filetype=helm */}}" }}
{{ "{{/* AUTOGENERATED FILE — DO NOT EDIT */}}\n" }}
{{- range $m := .Members }}
{{- template "member" (list $m 0 "") }}
{{- end }}
{{- end -}}

{{- define "member" -}}
{{- $field := index . 0 -}}
{{- $depth := index . 1 -}}
{{- $prefix := index . 2 -}}
{{- $width := mul $depth 2 -}}
{{- $pad := printf "%*s" $width "" -}}

{{- $path := $field.Name -}}
{{- if and (ne $prefix "") -}}
{{- $path = printf "%s.%s" $prefix $field.Name -}}
{{- end -}}

{{- if and (ne $width 0) (not (helmIsRequired $field)) -}}
{{- printf "%s" $pad -}}
{{- printf "{{- if .Values.%s }}\n" (trimPrefix "spec." $path) -}}
{{- end -}}

{{- printf "%s%s: " $pad $field.Name -}}

{{- if ne (helmCustomValue $path) "" }}
{{- helmCustomValue $path -}}{{- printf "\n" -}}
{{- else -}}
{{- if helmShouldRenderInner $field.Type }}
{{- printf "\n" -}}
{{- range $child := $field.Type.Members }}
{{- template "member" (list $child (add $depth 1) $path) }}
{{- end }}
{{- else }}
{{- if gt (len $field.Type.Members) 0 }}
{{- $innerPad := printf "%*s" (add $width 2) "" -}}
{{- if eq $prefix "" -}}
{{- printf "\n%s{{- .Values.%s | toYaml | nindent %d }}\n" $innerPad (trimPrefix "spec." $path) $width -}}
{{- else -}}
{{- printf "\n%s{{- .Values.%s | toYaml | nindent %d }}\n" $innerPad (trimPrefix "spec." $path) (add $width 2) -}}
{{- end -}}
{{- else -}}
{{- printf "{{ .Values.%s }}\n" (trimPrefix "spec." $path) -}}
{{- if and (ne $width 0) (not (helmIsRequired $field)) (ne (helmDefault $path) "") -}}
{{- printf "%s{{- else }}\n" $pad -}}
{{- printf "%s%s: %s\n" $pad $field.Name (helmDefault $path) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{- if and (ne $width 0) (not (helmIsRequired $field)) -}}
{{- printf "%s" $pad -}}
{{- printf "{{- end }}\n" -}}
{{- end -}}

{{- end -}}

File renamed without changes.
101 changes: 101 additions & 0 deletions cmd/example-gen/internal/render/helm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package render

import (
"io"
"io/fs"
"maps"
"text/template"

"github.com/Masterminds/sprig"
"github.com/elastic/crd-ref-docs/types"
"github.com/pkg/errors"
)

func Helm(wr io.Writer, t *types.Type, f fs.FS) error {
tplFS, err := fs.Sub(f, "templates")
if err != nil {
return errors.Wrap(err, "sub")
}

tmpl, err := template.New("").Funcs(funcMap()).ParseFS(tplFS, "*.tpl")
if err != nil {
return errors.Wrap(err, "parse fs")
}

if err := tmpl.ExecuteTemplate(wr, "main", t); err != nil {
return errors.Wrap(err, "execute template")
}
return nil
}

func funcMap() template.FuncMap {
fm := template.FuncMap{
"helmShouldRenderInner": shouldRenderInner,
"helmIsRequired": isRequired,
"helmCustomValue": customValue,
"helmDefault": defaultValue,
}
maps.Copy(fm, sprig.TxtFuncMap())
return fm
}

func shouldRenderInner(t *types.Type) bool {
return t != nil && t.Package == "github.com/percona/percona-server-mysql-operator/api/v1" && len(t.Members()) > 0
}

func isRequired(t *types.Field) bool {
if t == nil {
return false
}
_, ok := t.Markers["kubebuilder:validation:Required"]
return ok
}

func customValue(keyPath string) string {
switch keyPath {
case "spec.mysql.image":
return `"{{ .Values.mysql.image.repository }}:{{ .Values.mysql.image.tag }}"`
case "spec.proxy.haproxy.image":
return `"{{ .Values.proxy.haproxy.image.repository }}:{{ .Values.proxy.haproxy.image.tag }}"`
case "spec.proxy.router.image":
return `"{{ .Values.proxy.router.image.repository }}:{{ .Values.proxy.router.image.tag }}"`
case "spec.orchestrator.image":
return `"{{ .Values.orchestrator.image.repository }}:{{ .Values.orchestrator.image.tag }}"`
case "spec.toolkit.image":
return `"{{ .Values.toolkit.image.repository }}:{{ .Values.toolkit.image.tag }}"`
case "spec.pmm.image":
return `"{{ .Values.pmm.image.repository }}:{{ .Values.pmm.image.tag }}"`
case "spec.crVersion":
return `{{ .Chart.AppVersion }}`
case "apiVersion":
return `ps.percona.com/v1alpha1`
case "kind":
return `PerconaServerMySQL`
case "metadata":
return `
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"ps.percona.com/v1alpha1","kind":"PerconaServerMySQL"}
name: {{ include "ps-database.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{ include "ps-database.labels" . | indent 4 }}
finalizers:
{{ .Values.finalizers | toYaml | indent 4 }}`
default:
return ""
}
}

func defaultValue(keyPath string) string {
switch keyPath {
case "spec.secretsName":
return `{{ include "ps-database.fullname" . }}-secrets`
case "spec.sslSecretName":
return `{{ include "ps-database.fullname" . }}-ssl`
case "spec.proxy.haproxy.initContainer.image", "spec.backup.initContainer.image", "spec.initContainer.image", "spec.mysql.initContainer.image":
return `{{ include "ps-database.operator-image" . }}`
default:
return ""
}
}
27 changes: 25 additions & 2 deletions cmd/example-gen/scripts/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,36 @@ case "$resource" in
# shellcheck source=cmd/example-gen/scripts/lib/ps-restore.sh
. "$SCRIPT_DIR/lib/ps-restore.sh"
;;
chart)
# shellcheck source=cmd/example-gen/scripts/lib/chart.sh
. "$SCRIPT_DIR/lib/chart.sh"

go run cmd/example-gen/cmd/cr-gen/main.go "ps" \
| remove_fields \
| yq 'del(.kind) | del(.apiVersion) | del(.status)' \
| yq '.finalizers = .metadata.finalizers | del(.metadata)' \
| yq '. = (. + .spec) | del(.spec)' \
| yq '.nameOverride = ""' \
| yq '.fullnameOverride = ""' \
| replace_image ".mysql" \
| replace_image ".orchestrator" \
| replace_image ".proxy.haproxy" \
| replace_image ".proxy.router" \
| replace_image ".toolkit" \
| replace_image ".pmm" \
| sort_yaml '.' \
| comment_fields '.' >deploy/chart/values.yaml

go run cmd/example-gen/cmd/chart-gen/main.go api/v1 >deploy/chart/templates/cluster.yaml
exit 0
;;
*)
echo "Usage: $0 {ps|ps-backup|ps-restore}" >&2
echo "Usage: $0 {ps|ps-backup|ps-restore|chart}" >&2
exit 2
;;
esac

go run cmd/example-gen/main.go "$resource" \
go run cmd/example-gen/cmd/cr-gen/main.go "$resource" \
| sort_yaml \
| remove_fields \
| comment_fields \
Expand Down
24 changes: 24 additions & 0 deletions cmd/example-gen/scripts/lib/chart.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash

# shellcheck source=cmd/example-gen/scripts/lib/ps.sh
. "$SCRIPT_DIR/lib/ps.sh"

replace_image() {
local path=$1

local image
local repository
local tag

tmp="$(mktemp)"
cat >"$tmp"

image=$(yq "$path.image" "$tmp")

tag="${image##*:}"
repository="${image%:*}"

yq "del($path.image) | $path.image.repository=\"$repository\" | $path.image.tag=\"$tag\"" "$tmp"

rm -f "$tmp"
}
Loading
Loading