From 1b4e02eb6234eb3492a944e5d9647543f164bcfe Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 8 Jul 2025 22:30:20 -0400 Subject: [PATCH] feat: create a KustomizeRenderer The KustomizeRenderer is used to invoke Kustomize to the generated renderer.yaml. --- plugins/scheduler-k3s/go.mod | 3 +- plugins/scheduler-k3s/go.sum | 2 + plugins/scheduler-k3s/helm.go | 89 +++++++++++++++++++++++++++++++---- 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/plugins/scheduler-k3s/go.mod b/plugins/scheduler-k3s/go.mod index 2e7f2df80..bf48e9f6f 100644 --- a/plugins/scheduler-k3s/go.mod +++ b/plugins/scheduler-k3s/go.mod @@ -11,6 +11,7 @@ require ( github.com/dokku/dokku/plugins/logs v0.0.0-20250618161309-8d0c35f1333c github.com/dokku/dokku/plugins/nginx-vhosts v0.0.0-20250618161309-8d0c35f1333c github.com/fatih/color v1.18.0 + github.com/fluxcd/pkg/kustomize v1.18.0 github.com/go-openapi/jsonpointer v0.21.1 github.com/go-resty/resty/v2 v2.16.5 github.com/gofrs/flock v0.12.1 @@ -30,6 +31,7 @@ require ( k8s.io/kubernetes v1.33.2 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 mvdan.cc/sh/v3 v3.12.0 + sigs.k8s.io/kustomize/api v0.20.0 ) require ( @@ -168,7 +170,6 @@ require ( sigs.k8s.io/controller-runtime v0.21.0 // indirect sigs.k8s.io/gateway-api v1.3.0 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect - sigs.k8s.io/kustomize/api v0.20.0 // indirect sigs.k8s.io/kustomize/kyaml v0.20.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect diff --git a/plugins/scheduler-k3s/go.sum b/plugins/scheduler-k3s/go.sum index 46f0a044d..08511dbb7 100644 --- a/plugins/scheduler-k3s/go.sum +++ b/plugins/scheduler-k3s/go.sum @@ -89,6 +89,8 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fluxcd/pkg/kustomize v1.18.0 h1:wWK+qYwmBmba3N3VAqZ9ijnfVGGaIjcaHWo033URZTw= +github.com/fluxcd/pkg/kustomize v1.18.0/go.mod h1:Ij9722MdWIE6B1EPg2ZJUf6npycgfRfN4Lohi7D/Kic= github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= diff --git a/plugins/scheduler-k3s/helm.go b/plugins/scheduler-k3s/helm.go index da4cd008c..8eb42d4a8 100644 --- a/plugins/scheduler-k3s/helm.go +++ b/plugins/scheduler-k3s/helm.go @@ -14,6 +14,7 @@ import ( "unicode" "github.com/dokku/dokku/plugins/common" + "github.com/fluxcd/pkg/kustomize/filesys" "github.com/gofrs/flock" "gopkg.in/yaml.v3" "helm.sh/helm/v3/pkg/action" @@ -21,9 +22,13 @@ import ( "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/kube" + "helm.sh/helm/v3/pkg/postrender" "helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/repo" "helm.sh/helm/v3/pkg/storage/driver" + "sigs.k8s.io/kustomize/api/konfig" + "sigs.k8s.io/kustomize/api/krusty" + "sigs.k8s.io/kustomize/api/types" ) var DevNullPrinter = func(format string, v ...interface{}) {} @@ -337,16 +342,6 @@ func (h *HelmAgent) ListRevisions(input ListRevisionsInput) ([]Release, error) { return releases, nil } -type DebugRenderer struct { -} - -func (p *DebugRenderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { - for _, line := range strings.Split(renderedManifests.String(), "\n") { - common.LogWarn(line) - } - return renderedManifests, nil -} - func (h *HelmAgent) UpgradeChart(ctx context.Context, input ChartInput) error { namespace := input.Namespace if namespace == "" { @@ -417,3 +412,77 @@ func (h *HelmAgent) UninstallChart(releaseName string) error { return nil } + +type DebugRenderer struct { + Renderer *postrender.PostRenderer +} + +func (p *DebugRenderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { + if p.Renderer != nil { + var err error + renderer := *p.Renderer + renderedManifests, err = renderer.Run(renderedManifests) + if err != nil { + return nil, err + } + } + + for _, line := range strings.Split(renderedManifests.String(), "\n") { + common.LogWarn(line) + } + return renderedManifests, nil +} + +type KustomizeRenderer struct { + Renderer *postrender.PostRenderer + KustomizeRootPath string +} + +func (p *KustomizeRenderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { + if p.KustomizeRootPath == "" { + return nil, nil + } + + if !common.DirectoryExists(p.KustomizeRootPath) { + return nil, nil + } + + fs, err := filesys.MakeFsOnDiskSecureBuild(p.KustomizeRootPath) + if err != nil { + return nil, fmt.Errorf("Error creating filesystem: %w", err) + } + + var kfile string + for _, f := range konfig.RecognizedKustomizationFileNames() { + if kf := filepath.Join(p.KustomizeRootPath, f); fs.Exists(kf) { + kfile = kf + break + } + } + if kfile == "" { + return nil, fmt.Errorf("%s not found", konfig.DefaultKustomizationFileName()) + } + + renderedYamlPath := filepath.Join(p.KustomizeRootPath, "rendered.yaml") + if err := os.WriteFile(renderedYamlPath, renderedManifests.Bytes(), 0644); err != nil { + return nil, fmt.Errorf("Error writing rendered.yaml: %w", err) + } + + buildOptions := &krusty.Options{ + LoadRestrictions: types.LoadRestrictionsNone, + PluginConfig: types.DisabledPluginConfig(), + } + + k := krusty.MakeKustomizer(buildOptions) + m, err := k.Run(fs, p.KustomizeRootPath) + if err != nil { + return nil, err + } + + resources, err := m.AsYaml() + if err != nil { + return nil, err + } + + return bytes.NewBuffer(resources), nil +}