• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubernetes-sigs / kubebuilder / 21336133158

25 Jan 2026 04:52PM UTC coverage: 73.801% (+0.06%) from 73.737%
21336133158

Pull #5392

github

camilamacedo86
(chore): (helm/v2-alpha): Add Notes.txt
Pull Request #5392: ✨ (helm/v2-alpha): Add Notes.txt

24 of 24 new or added lines in 3 files covered. (100.0%)

15 existing lines in 2 files now uncovered.

6617 of 8966 relevant lines covered (73.8%)

40.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

56.91
/pkg/plugins/optional/helm/v2alpha/scaffolds/edit_kustomize.go
1
/*
2
Copyright 2025 The Kubernetes Authors.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package scaffolds
18

19
import (
20
        "fmt"
21
        "log/slog"
22
        "os"
23
        "os/exec"
24
        "path/filepath"
25
        "strings"
26

27
        "sigs.k8s.io/kubebuilder/v4/pkg/config"
28
        "sigs.k8s.io/kubebuilder/v4/pkg/machinery"
29
        "sigs.k8s.io/kubebuilder/v4/pkg/plugins"
30
        "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize"
31
        "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates"
32
        charttemplates "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates/chart-templates"
33
        "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates/github"
34
)
35

36
const (
37
        defaultManifestsFile = "dist/install.yaml"
38
)
39

40
var _ plugins.Scaffolder = &editKustomizeScaffolder{}
41

42
type editKustomizeScaffolder struct {
43
        config        config.Config
44
        fs            machinery.Filesystem
45
        force         bool
46
        manifestsFile string
47
        outputDir     string
48
}
49

50
// NewKustomizeHelmScaffolder returns a new Scaffolder for HelmPlugin using kustomize output
51
func NewKustomizeHelmScaffolder(cfg config.Config, force bool, manifestsFile, outputDir string) plugins.Scaffolder {
×
52
        return &editKustomizeScaffolder{
×
53
                config:        cfg,
×
54
                force:         force,
×
55
                manifestsFile: manifestsFile,
×
56
                outputDir:     outputDir,
×
57
        }
×
58
}
×
59

60
// InjectFS implements cmdutil.Scaffolder
61
func (s *editKustomizeScaffolder) InjectFS(fs machinery.Filesystem) {
×
62
        s.fs = fs
×
63
}
×
64

65
// Scaffold generates the complete Helm chart from kustomize output
66
func (s *editKustomizeScaffolder) Scaffold() error {
10✔
67
        slog.Info("Generating Helm Chart from kustomize output")
10✔
68

10✔
69
        // Ensure chart directory structure exists
10✔
70
        if err := s.ensureChartDirectoryExists(); err != nil {
10✔
71
                return fmt.Errorf("failed to create chart directory: %w", err)
×
72
        }
×
73

74
        // Generate fresh kustomize output if using default file
75
        if s.manifestsFile == defaultManifestsFile {
10✔
76
                if err := s.generateKustomizeOutput(); err != nil {
×
77
                        return fmt.Errorf("failed to generate kustomize output: %w", err)
×
78
                }
×
79
        }
80

81
        // Parse the kustomize output into organized resource groups
82
        parser := kustomize.NewParser(s.manifestsFile)
10✔
83
        resources, err := parser.Parse()
10✔
84
        if err != nil {
10✔
85
                return fmt.Errorf("failed to parse kustomize output from %s: %w", s.manifestsFile, err)
×
86
        }
×
87

88
        // Analyze resources to determine chart features
89
        hasWebhooks := len(resources.WebhookConfigurations) > 0 || len(resources.Certificates) > 0
10✔
90
        // Prometheus is enabled when ServiceMonitor resources exist (../prometheus enabled)
10✔
91
        hasPrometheus := len(resources.ServiceMonitors) > 0
10✔
92
        // Metrics are enabled either when ServiceMonitor exists or when a metrics service is present
10✔
93
        hasMetrics := hasPrometheus
10✔
94
        if !hasMetrics {
20✔
95
                for _, svc := range resources.Services {
10✔
96
                        if strings.Contains(svc.GetName(), "metrics") {
×
97
                                hasMetrics = true
×
98
                                break
×
99
                        }
100
                }
101
        }
102

103
        // When Prometheus is enabled via kustomize, ensure any previously-generated
104
        // generic ServiceMonitor file is removed to avoid duplicates in the chart.
105
        if hasPrometheus {
10✔
106
                staleSM := filepath.Join(s.outputDir, "chart", "templates", "monitoring", "servicemonitor.yaml")
×
107
                if rmErr := s.fs.FS.Remove(staleSM); rmErr != nil && !os.IsNotExist(rmErr) {
×
108
                        // Not fatal; log and continue
×
109
                        slog.Warn("failed to remove stale generic ServiceMonitor", "path", staleSM, "error", rmErr)
×
110
                }
×
111
        }
112
        namePrefix := resources.EstimatePrefix(s.config.GetProjectName())
10✔
113
        chartName := s.config.GetProjectName()
10✔
114
        chartConverter := kustomize.NewChartConverter(resources, namePrefix, chartName, s.outputDir)
10✔
115
        deploymentConfig := chartConverter.ExtractDeploymentConfig()
10✔
116

10✔
117
        // Create scaffold for standard Helm chart files
10✔
118
        scaffold := machinery.NewScaffold(s.fs, machinery.WithConfig(s.config))
10✔
119

10✔
120
        // Define the standard Helm chart files to generate
10✔
121
        chartFiles := []machinery.Builder{
10✔
122
                &github.HelmChartCI{Force: s.force},                          // GitHub Actions workflow for chart testing
10✔
123
                &templates.HelmChart{OutputDir: s.outputDir, Force: s.force}, // Chart.yaml metadata
10✔
124
                &templates.HelmValuesBasic{
10✔
125
                        // values.yaml with dynamic config
10✔
126
                        HasWebhooks:      hasWebhooks,
10✔
127
                        HasMetrics:       hasMetrics,
10✔
128
                        DeploymentConfig: deploymentConfig,
10✔
129
                        OutputDir:        s.outputDir,
10✔
130
                        Force:            s.force,
10✔
131
                },
10✔
132
                &templates.HelmIgnore{OutputDir: s.outputDir, Force: s.force},       // .helmignore file
10✔
133
                &charttemplates.HelmHelpers{OutputDir: s.outputDir, Force: s.force}, // _helpers.tpl template functions
10✔
134
                &charttemplates.Notes{
10✔
135
                        OutputDir: s.outputDir,
10✔
136
                        Force:     s.force,
10✔
137
                },
10✔
138
        }
10✔
139

10✔
140
        // Only scaffold the generic ServiceMonitor when the project does NOT already
10✔
141
        // provide one via kustomize (../prometheus). This avoids duplicate objects
10✔
142
        // with the same name within the Helm chart.
10✔
143
        if !hasPrometheus {
20✔
144
                // Find the metrics service name from parsed resources
10✔
145
                metricsServiceName := namePrefix + "-controller-manager-metrics-service"
10✔
146
                for _, svc := range resources.Services {
10✔
UNCOV
147
                        if strings.Contains(svc.GetName(), "metrics-service") {
×
UNCOV
148
                                metricsServiceName = svc.GetName()
×
UNCOV
149
                                break
×
150
                        }
151
                }
152

153
                chartFiles = append(chartFiles, &charttemplates.ServiceMonitor{
10✔
154
                        OutputDir:   s.outputDir,
10✔
155
                        ServiceName: metricsServiceName,
10✔
156
                        Force:       s.force,
10✔
157
                })
10✔
158
        }
159

160
        // Generate template files from kustomize output
161
        if writeErr := chartConverter.WriteChartFiles(s.fs); writeErr != nil {
10✔
162
                return fmt.Errorf("failed to write chart template files: %w", writeErr)
×
163
        }
×
164

165
        // Generate standard Helm chart files
166
        if err = scaffold.Execute(chartFiles...); err != nil {
10✔
167
                return fmt.Errorf("failed to generate Helm chart files: %w", err)
×
168
        }
×
169

170
        slog.Info("Helm Chart generation completed successfully")
10✔
171
        return nil
10✔
172
}
173

174
// generateKustomizeOutput runs make build-installer to generate the manifests file
175
func (s *editKustomizeScaffolder) generateKustomizeOutput() error {
×
176
        slog.Info("Generating kustomize output with make build-installer")
×
177

×
178
        // Check if Makefile exists
×
179
        if _, err := os.Stat("Makefile"); os.IsNotExist(err) {
×
180
                return fmt.Errorf("makefile not found in current directory")
×
181
        }
×
182

183
        // Run make build-installer
184
        cmd := exec.Command("make", "build-installer")
×
185
        cmd.Stdout = os.Stdout
×
186
        cmd.Stderr = os.Stderr
×
187

×
188
        if err := cmd.Run(); err != nil {
×
189
                return fmt.Errorf("failed to run make build-installer: %w", err)
×
190
        }
×
191

192
        // Verify that the manifests file was created
193
        if _, err := os.Stat(defaultManifestsFile); os.IsNotExist(err) {
×
194
                return fmt.Errorf("%s was not generated by make build-installer", defaultManifestsFile)
×
195
        }
×
196

197
        return nil
×
198
}
199

200
// ensureChartDirectoryExists creates the chart directory structure if it doesn't exist
201
func (s *editKustomizeScaffolder) ensureChartDirectoryExists() error {
10✔
202
        dirs := []string{
10✔
203
                filepath.Join(s.outputDir, "chart"),
10✔
204
                filepath.Join(s.outputDir, "chart", "templates"),
10✔
205
        }
10✔
206

10✔
207
        for _, dir := range dirs {
30✔
208
                if err := os.MkdirAll(dir, 0o755); err != nil {
20✔
209
                        return fmt.Errorf("failed to create directory %s: %w", dir, err)
×
210
                }
×
211
        }
212

213
        return nil
10✔
214
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc