Skip to content

Commit 6f812a1

Browse files
committed
feat: Allow helm templater plugin to get custom prefixes from kustomize
1 parent 7b0ca3b commit 6f812a1

File tree

9 files changed

+145
-15
lines changed

9 files changed

+145
-15
lines changed

pkg/plugins/optional/helm/v2alpha/scaffolds/edit_kustomize.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ func (s *editKustomizeScaffolder) Scaffold() error {
109109
slog.Warn("failed to remove stale generic ServiceMonitor", "path", staleSM, "error", rmErr)
110110
}
111111
}
112-
chartConverter := kustomize.NewChartConverter(resources, s.config.GetProjectName(), s.outputDir)
112+
namePrefix := resources.EstimatePrefix(s.config.GetProjectName())
113+
chartConverter := kustomize.NewChartConverter(resources, s.config.GetProjectName(), namePrefix, s.outputDir)
113114
deploymentConfig := chartConverter.ExtractDeploymentConfig()
114115

115116
// Create scaffold for standard Helm chart files
@@ -119,7 +120,8 @@ func (s *editKustomizeScaffolder) Scaffold() error {
119120
chartFiles := []machinery.Builder{
120121
&github.HelmChartCI{}, // GitHub Actions workflow for chart testing
121122
&templates.HelmChart{OutputDir: s.outputDir}, // Chart.yaml metadata
122-
&templates.HelmValuesBasic{ // values.yaml with dynamic config
123+
&templates.HelmValuesBasic{
124+
// values.yaml with dynamic config
123125
HasWebhooks: hasWebhooks,
124126
HasMetrics: hasMetrics,
125127
DeploymentConfig: deploymentConfig,
@@ -134,7 +136,20 @@ func (s *editKustomizeScaffolder) Scaffold() error {
134136
// provide one via kustomize (../prometheus). This avoids duplicate objects
135137
// with the same name within the Helm chart.
136138
if !hasPrometheus {
137-
chartFiles = append(chartFiles, &charttemplates.ServiceMonitor{OutputDir: s.outputDir})
139+
// Find the metrics service name from parsed resources
140+
metricsServiceName := namePrefix + "-controller-manager-metrics-service"
141+
for _, svc := range resources.Services {
142+
if strings.Contains(svc.GetName(), "metrics-service") {
143+
metricsServiceName = svc.GetName()
144+
break
145+
}
146+
}
147+
148+
chartFiles = append(chartFiles, &charttemplates.ServiceMonitor{
149+
OutputDir: s.outputDir,
150+
NamePrefix: namePrefix,
151+
ServiceName: metricsServiceName,
152+
})
138153
}
139154

140155
// Generate template files from kustomize output

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/chart_converter.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ type ChartConverter struct {
3737
}
3838

3939
// NewChartConverter creates a new chart converter with all necessary components
40-
func NewChartConverter(resources *ParsedResources, projectName, outputDir string) *ChartConverter {
40+
func NewChartConverter(resources *ParsedResources, projectName, namePrefix, outputDir string) *ChartConverter {
4141
organizer := NewResourceOrganizer(resources)
42-
templater := NewHelmTemplater(projectName)
42+
templater := NewHelmTemplater(projectName, namePrefix)
4343
writer := NewChartWriter(templater, outputDir)
4444

4545
return &ChartConverter{

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/chart_converter_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ var _ = Describe("ChartConverter", func() {
5555
fs = machinery.Filesystem{FS: afero.NewMemMapFs()}
5656

5757
// Create converter
58-
converter = NewChartConverter(resources, "test-project", "dist")
58+
converter = NewChartConverter(resources, "test-project", "test-project", "dist")
5959
})
6060

6161
Context("NewChartConverter", func() {

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/chart_writer.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ func NewChartWriter(templater *HelmTemplater, outputDir string) *ChartWriter {
4444
}
4545

4646
// WriteResourceGroup writes a group of resources to a Helm template file
47-
func (w *ChartWriter) WriteResourceGroup(fs machinery.Filesystem, groupName string,
47+
func (w *ChartWriter) WriteResourceGroup(
48+
fs machinery.Filesystem, groupName string,
4849
resources []*unstructured.Unstructured,
4950
) error {
5051
// Special handling for namespace - write as single file
@@ -73,7 +74,8 @@ func (w *ChartWriter) writeNamespaceFile(fs machinery.Filesystem, namespace *uns
7374
}
7475

7576
// writeGroupDirectory writes resources as files in a group-specific directory
76-
func (w *ChartWriter) writeGroupDirectory(fs machinery.Filesystem, groupName string,
77+
func (w *ChartWriter) writeGroupDirectory(
78+
fs machinery.Filesystem, groupName string,
7779
resources []*unstructured.Unstructured,
7880
) error {
7981
var finalContent bytes.Buffer
@@ -112,7 +114,8 @@ func (w *ChartWriter) shouldSplitFiles(groupName string) bool {
112114
}
113115

114116
// writeSplitFiles writes each resource in the group to its own file
115-
func (w *ChartWriter) writeSplitFiles(fs machinery.Filesystem, groupName string,
117+
func (w *ChartWriter) writeSplitFiles(
118+
fs machinery.Filesystem, groupName string,
116119
resources []*unstructured.Unstructured,
117120
) error {
118121
// Create the group directory
@@ -142,7 +145,7 @@ func (w *ChartWriter) generateFileName(resource *unstructured.Unstructured, inde
142145
// Try to use the resource name if available
143146
if name := resource.GetName(); name != "" {
144147
// Remove project prefix from the filename for cleaner file names
145-
projectPrefix := w.templater.projectName + "-"
148+
projectPrefix := w.templater.namePrefix + "-"
146149
fileName := name
147150
if strings.HasPrefix(name, projectPrefix) {
148151
fileName = strings.TrimPrefix(name, projectPrefix)

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ const (
4848
// HelmTemplater handles converting YAML content to Helm templates
4949
type HelmTemplater struct {
5050
projectName string
51+
namePrefix string
5152
}
5253

5354
// NewHelmTemplater creates a new Helm templater
54-
func NewHelmTemplater(projectName string) *HelmTemplater {
55+
func NewHelmTemplater(projectName string, namePrefix string) *HelmTemplater {
5556
return &HelmTemplater{
5657
projectName: projectName,
58+
namePrefix: namePrefix,
5759
}
5860
}
5961

@@ -184,11 +186,16 @@ func (t *HelmTemplater) templateServiceMonitorNames(yamlContent string, resource
184186

185187
// Normalize suffix by stripping the project prefix if present
186188
suffix := origName
187-
prefix := t.projectName + "-"
189+
prefix := t.namePrefix + "-"
188190
if strings.HasPrefix(origName, prefix) {
189191
suffix = strings.TrimPrefix(origName, prefix)
190192
}
191193

194+
// If the prefix is not the project name, we should keep the original name intact
195+
if prefix != t.projectName+"-" {
196+
return yamlContent
197+
}
198+
192199
// Only template if the intended target follows the conventional suffix
193200
// This keeps any custom user-provided names intact
194201
// For default scaffolding, suffix is typically "controller-manager-metrics-monitor"

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var _ = Describe("HelmTemplater", func() {
2828
BeforeEach(func() {
2929
templater = &HelmTemplater{
3030
projectName: "test-project",
31+
namePrefix: "test-project",
3132
}
3233
})
3334

@@ -225,6 +226,43 @@ metadata:
225226
Expect(result).To(ContainSubstring("{{- end }}"))
226227
})
227228

229+
Describe("should generate ServiceMonitor name correctly", func() {
230+
var serviceMonitorResource *unstructured.Unstructured
231+
var content string
232+
233+
BeforeEach(func() {
234+
serviceMonitorResource = &unstructured.Unstructured{}
235+
serviceMonitorResource.SetAPIVersion("monitoring.coreos.com/v1")
236+
serviceMonitorResource.SetKind("ServiceMonitor")
237+
serviceMonitorResource.SetName("test-project-controller-manager-metrics-monitor")
238+
239+
// Test content must end with a newline
240+
// If not, the `name` regex in the ServiceMonitor replacement will never match
241+
content = `apiVersion: monitoring.coreos.com/v1
242+
kind: ServiceMonitor
243+
metadata:
244+
name: test-project-controller-manager-metrics-monitor
245+
`
246+
})
247+
248+
It("should use chart.name template when namePrefix and project name are the same", func() {
249+
result := templater.ApplyHelmSubstitutions(content, serviceMonitorResource)
250+
// If the namePrefix and default chart name match, should use chart.name template
251+
Expect(result).To(ContainSubstring("{{ include \"chart.name\" . }}"),
252+
"Should use chart.name template when namePrefix and project name match")
253+
})
254+
It("should preserve the original name when the namePrefix and project name differ", func() {
255+
templaterDiff := &HelmTemplater{
256+
projectName: "project-with-a-long-name",
257+
namePrefix: "test-project",
258+
}
259+
result := templaterDiff.ApplyHelmSubstitutions(content, serviceMonitorResource)
260+
// If the namePrefix and default chart name differ, should use namePrefix variable
261+
Expect(result).ToNot(ContainSubstring("{{ include \"chart.name\" . }}"),
262+
"Should not use chart.name template when namePrefix and project name differ")
263+
})
264+
})
265+
228266
It("should add metrics conditional for metrics services", func() {
229267
serviceResource := &unstructured.Unstructured{}
230268
serviceResource.SetAPIVersion("v1")

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/parser.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"io"
2222
"os"
23+
"strings"
2324

2425
"gopkg.in/yaml.v3"
2526
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -151,3 +152,26 @@ func (p *Parser) categorizeResource(obj *unstructured.Unstructured, resources *P
151152
resources.Other = append(resources.Other, obj)
152153
}
153154
}
155+
156+
func (pr *ParsedResources) EstimatePrefix(projectName string) string {
157+
prefix := projectName
158+
if pr.Deployment != nil {
159+
if name := pr.Deployment.GetName(); name != "" {
160+
deploymentPrefix, found := strings.CutSuffix(name, "-controller-manager")
161+
if found {
162+
prefix = deploymentPrefix
163+
}
164+
}
165+
}
166+
// Double check that the prefix is also the prefix for the service names
167+
for _, svc := range pr.Services {
168+
if name := svc.GetName(); name != "" {
169+
if !strings.HasPrefix(name, prefix) {
170+
// If not, fallback to just project name
171+
prefix = projectName
172+
break
173+
}
174+
}
175+
}
176+
return prefix
177+
}

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/parser_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,4 +283,42 @@ spec:
283283
Expect(issuer.GetKind()).To(Equal("Issuer"))
284284
})
285285
})
286+
287+
Context("with custom prefix", func() {
288+
BeforeEach(func() {
289+
yamlContent := `---
290+
apiVersion: apps/v1
291+
kind: Deployment
292+
metadata:
293+
name: ln-controller-manager
294+
namespace: long-name-test-system
295+
spec:
296+
replicas: 1
297+
---
298+
apiVersion: v1
299+
kind: Service
300+
metadata:
301+
name: ln-controller-manager-metrics-service
302+
namespace: long-name-test-system
303+
spec:
304+
ports:
305+
- name: https
306+
port: 8443
307+
targetPort: 8443
308+
selector:
309+
control-plane: ln-controller-manager
310+
`
311+
err := os.WriteFile(tempFile, []byte(yamlContent), 0o600)
312+
Expect(err).NotTo(HaveOccurred())
313+
314+
parser = NewParser(tempFile)
315+
})
316+
317+
It("should use the correct prefix", func() {
318+
resources, err := parser.Parse()
319+
Expect(err).NotTo(HaveOccurred())
320+
321+
Expect(resources.EstimatePrefix("long-name")).To(Equal("ln"))
322+
})
323+
})
286324
})

pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates/chart-templates/servicemonitor.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ var _ machinery.Template = &ServiceMonitor{}
2929
// ServiceMonitor scaffolds a ServiceMonitor for Prometheus monitoring in the Helm chart
3030
type ServiceMonitor struct {
3131
machinery.TemplateMixin
32-
machinery.ProjectNameMixin
32+
33+
// Prefix
34+
NamePrefix string
35+
36+
// ServiceName is the full name of the metrics service, derived from Kustomize
37+
ServiceName string
3338

3439
// OutputDir specifies the output directory for the chart
3540
OutputDir string
@@ -59,7 +64,7 @@ metadata:
5964
labels:
6065
{{ "{{- include \"chart.labels\" . | nindent 4 }}" }}
6166
control-plane: controller-manager
62-
name: {{ .ProjectName }}-controller-manager-metrics-monitor
67+
name: {{ .NamePrefix }}-controller-manager-metrics-monitor
6368
namespace: {{ "{{ .Release.Namespace }}" }}
6469
spec:
6570
endpoints:
@@ -69,7 +74,7 @@ spec:
6974
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
7075
tlsConfig:
7176
{{ "{{- if .Values.certManager.enable }}" }}
72-
serverName: {{ .ProjectName }}-controller-manager-metrics-service.{{ "{{ .Release.Namespace }}" }}.svc
77+
serverName: {{ .ServiceName }}.{{ "{{ .Release.Namespace }}" }}.svc
7378
# Apply secure TLS configuration with cert-manager
7479
insecureSkipVerify: false
7580
ca:

0 commit comments

Comments
 (0)