Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metadata:
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/name: project
control-plane: controller-manager
name: {{ include "chart.name" . }}-controller-manager-metrics-monitor
name: project-controller-manager-metrics-monitor
namespace: {{ .Release.Namespace }}
spec:
endpoints:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metadata:
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/name: project
control-plane: controller-manager
name: {{ include "chart.name" . }}-controller-manager-metrics-monitor
name: project-controller-manager-metrics-monitor
namespace: {{ .Release.Namespace }}
spec:
endpoints:
Expand Down
19 changes: 17 additions & 2 deletions pkg/plugins/optional/helm/v2alpha/scaffolds/edit_kustomize.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func (s *editKustomizeScaffolder) Scaffold() error {
slog.Warn("failed to remove stale generic ServiceMonitor", "path", staleSM, "error", rmErr)
}
}
namePrefix := resources.EstimatePrefix(s.config.GetProjectName())
chartConverter := kustomize.NewChartConverter(resources, s.config.GetProjectName(), s.outputDir)
deploymentConfig := chartConverter.ExtractDeploymentConfig()

Expand All @@ -119,7 +120,8 @@ func (s *editKustomizeScaffolder) Scaffold() error {
chartFiles := []machinery.Builder{
&github.HelmChartCI{}, // GitHub Actions workflow for chart testing
&templates.HelmChart{OutputDir: s.outputDir}, // Chart.yaml metadata
&templates.HelmValuesBasic{ // values.yaml with dynamic config
&templates.HelmValuesBasic{
// values.yaml with dynamic config
HasWebhooks: hasWebhooks,
HasMetrics: hasMetrics,
DeploymentConfig: deploymentConfig,
Expand All @@ -134,7 +136,20 @@ func (s *editKustomizeScaffolder) Scaffold() error {
// provide one via kustomize (../prometheus). This avoids duplicate objects
// with the same name within the Helm chart.
if !hasPrometheus {
chartFiles = append(chartFiles, &charttemplates.ServiceMonitor{OutputDir: s.outputDir})
// Find the metrics service name from parsed resources
metricsServiceName := namePrefix + "-controller-manager-metrics-service"
for _, svc := range resources.Services {
if strings.Contains(svc.GetName(), "metrics-service") {
metricsServiceName = svc.GetName()
break
}
}

chartFiles = append(chartFiles, &charttemplates.ServiceMonitor{
OutputDir: s.outputDir,
NamePrefix: namePrefix,
ServiceName: metricsServiceName,
})
}

// Generate template files from kustomize output
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ func NewChartWriter(templater *HelmTemplater, outputDir string) *ChartWriter {
}

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

// writeGroupDirectory writes resources as files in a group-specific directory
func (w *ChartWriter) writeGroupDirectory(fs machinery.Filesystem, groupName string,
func (w *ChartWriter) writeGroupDirectory(
fs machinery.Filesystem, groupName string,
resources []*unstructured.Unstructured,
) error {
var finalContent bytes.Buffer
Expand Down Expand Up @@ -112,7 +114,8 @@ func (w *ChartWriter) shouldSplitFiles(groupName string) bool {
}

// writeSplitFiles writes each resource in the group to its own file
func (w *ChartWriter) writeSplitFiles(fs machinery.Filesystem, groupName string,
func (w *ChartWriter) writeSplitFiles(
fs machinery.Filesystem, groupName string,
resources []*unstructured.Unstructured,
) error {
// Create the group directory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ func (t *HelmTemplater) ApplyHelmSubstitutions(yamlContent string, resource *uns
// Apply namespace substitutions
yamlContent = t.substituteNamespace(yamlContent, resource)

// Template ServiceMonitor metadata.name to be chart.name-scoped for consistency
yamlContent = t.templateServiceMonitorNames(yamlContent, resource)

// Apply cert-manager and webhook-specific templating AFTER other substitutions
yamlContent = t.substituteCertManagerReferences(yamlContent, resource)

Expand Down Expand Up @@ -159,47 +156,6 @@ func (t *HelmTemplater) substituteCertManagerReferences(yamlContent string, _ *u
return yamlContent
}

// templateServiceNames ensures Service metadata.name uses Helm helpers for release-scoped naming.
// It converts hardcoded names like "<project>-webhook-service" or
// "<project>-controller-manager-metrics-service" to:
//
// name: {{ include "chart.serviceName" (dict "suffix" "<suffix>" "context" .) }}
// NOTE: Service names are intentionally left as project-scoped (no release prefix)
// to match existing samples and e2e tests that refer to fixed service names.

// templateServiceMonitorNames ensures ServiceMonitor metadata.name uses chart.name-based naming for consistency
// with existing tests and samples. It converts names like "controller-manager-metrics-monitor" or
// "<project>-controller-manager-metrics-monitor" to:
//
// name: {{ include "chart.name" . }}-controller-manager-metrics-monitor
func (t *HelmTemplater) templateServiceMonitorNames(yamlContent string, resource *unstructured.Unstructured) string {
if resource.GetKind() != kindServiceMonitor {
return yamlContent
}

origName := resource.GetName()
if origName == "" {
return yamlContent
}

// Normalize suffix by stripping the project prefix if present
suffix := origName
prefix := t.projectName + "-"
if strings.HasPrefix(origName, prefix) {
suffix = strings.TrimPrefix(origName, prefix)
}

// Only template if the intended target follows the conventional suffix
// This keeps any custom user-provided names intact
// For default scaffolding, suffix is typically "controller-manager-metrics-monitor"
templated := "{{ include \"chart.name\" . }}-" + suffix

nameRe := regexp.MustCompile("(?m)^([\t ]*)name:\\s*" + regexp.QuoteMeta(origName) + "\\s*$")
yamlContent = nameRe.ReplaceAllString(yamlContent, "${1}name: "+templated)

return yamlContent
}

// addHelmLabelsAndAnnotations replaces kustomize managed-by labels with Helm equivalents
func (t *HelmTemplater) addHelmLabelsAndAnnotations(yamlContent string, _ *unstructured.Unstructured) string {
// Replace app.kubernetes.io/managed-by: kustomize with Helm template
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,23 @@ metadata:
Expect(result).To(ContainSubstring("name: test-project-controller-manager"))
Expect(result).NotTo(ContainSubstring("{{ include"))
})
It("should preserve name for ServiceMonitor", func() {
serviceMonitorResource := &unstructured.Unstructured{}
serviceMonitorResource.SetAPIVersion("monitoring.coreos.com/v1")
serviceMonitorResource.SetKind("ServiceMonitor")
serviceMonitorResource.SetName("test-project-controller-manager-metrics-monitor")

content := `apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: test-project-controller-manager-metrics-monitor`

result := templater.ApplyHelmSubstitutions(content, serviceMonitorResource)

// Name should remain unchanged
Expect(result).To(ContainSubstring("name: test-project-controller-manager-metrics-monitor"))
Expect(result).NotTo(ContainSubstring("{{ include"))
})
})

Context("edge cases", func() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"io"
"os"
"strings"

"gopkg.in/yaml.v3"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -151,3 +152,26 @@ func (p *Parser) categorizeResource(obj *unstructured.Unstructured, resources *P
resources.Other = append(resources.Other, obj)
}
}

func (pr *ParsedResources) EstimatePrefix(projectName string) string {
prefix := projectName
if pr.Deployment != nil {
if name := pr.Deployment.GetName(); name != "" {
deploymentPrefix, found := strings.CutSuffix(name, "-controller-manager")
if found {
prefix = deploymentPrefix
}
}
}
// Double check that the prefix is also the prefix for the service names
for _, svc := range pr.Services {
if name := svc.GetName(); name != "" {
if !strings.HasPrefix(name, prefix) {
// If not, fallback to just project name
prefix = projectName
break
}
}
}
return prefix
}
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,42 @@ spec:
Expect(issuer.GetKind()).To(Equal("Issuer"))
})
})

Context("with custom prefix", func() {
BeforeEach(func() {
yamlContent := `---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ln-controller-manager
namespace: long-name-test-system
spec:
replicas: 1
---
apiVersion: v1
kind: Service
metadata:
name: ln-controller-manager-metrics-service
namespace: long-name-test-system
spec:
ports:
- name: https
port: 8443
targetPort: 8443
selector:
control-plane: ln-controller-manager
`
err := os.WriteFile(tempFile, []byte(yamlContent), 0o600)
Expect(err).NotTo(HaveOccurred())

parser = NewParser(tempFile)
})

It("should use the correct prefix", func() {
resources, err := parser.Parse()
Expect(err).NotTo(HaveOccurred())

Expect(resources.EstimatePrefix("long-name")).To(Equal("ln"))
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ var _ machinery.Template = &ServiceMonitor{}
// ServiceMonitor scaffolds a ServiceMonitor for Prometheus monitoring in the Helm chart
type ServiceMonitor struct {
machinery.TemplateMixin
machinery.ProjectNameMixin

// Prefix
NamePrefix string

// ServiceName is the full name of the metrics service, derived from Kustomize
ServiceName string

// OutputDir specifies the output directory for the chart
OutputDir string
Expand Down Expand Up @@ -59,7 +64,7 @@ metadata:
labels:
{{ "{{- include \"chart.labels\" . | nindent 4 }}" }}
control-plane: controller-manager
name: {{ .ProjectName }}-controller-manager-metrics-monitor
name: {{ .NamePrefix }}-controller-manager-metrics-monitor
namespace: {{ "{{ .Release.Namespace }}" }}
spec:
endpoints:
Expand All @@ -69,7 +74,7 @@ spec:
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
tlsConfig:
{{ "{{- if .Values.certManager.enable }}" }}
serverName: {{ .ProjectName }}-controller-manager-metrics-service.{{ "{{ .Release.Namespace }}" }}.svc
serverName: {{ .ServiceName }}.{{ "{{ .Release.Namespace }}" }}.svc
# Apply secure TLS configuration with cert-manager
insecureSkipVerify: false
ca:
Expand Down
Loading