Skip to content

Commit

Permalink
(helm/v1alpha1) - fix webhook generation by removing data from helm c…
Browse files Browse the repository at this point in the history
…hart values

This commit changes the code implementation to not generate the webhook values in the helm chart values. Instead only expose on the values to enable or not webhooks
  • Loading branch information
camilamacedo86 committed Dec 30, 2024
1 parent 6fb374f commit 2c9f1e3
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 233 deletions.
82 changes: 62 additions & 20 deletions pkg/plugins/optional/helm/v1alpha/scaffolds/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates"
chart_templates "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates/chart-templates"
chartTemplates "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates/chart-templates"
templatescertmanager "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates/chart-templates/cert-manager"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates/chart-templates/manager"
templatesmetrics "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates/chart-templates/metrics"
Expand Down Expand Up @@ -70,11 +70,9 @@ func (s *initScaffolder) InjectFS(fs machinery.Filesystem) {
func (s *initScaffolder) Scaffold() error {
log.Println("Generating Helm Chart to distribute project")

// Extract Images scaffolded with DeployImage to add ENVVAR to the values
imagesEnvVars := s.getDeployImagesEnvVars()

// Extract webhooks from generated YAML files (generated by controller-gen)
webhooks, err := extractWebhooksFromGeneratedFiles()
webhooks, err := s.extractWebhooks()
if err != nil {
return fmt.Errorf("failed to extract webhooks: %w", err)
}
Expand All @@ -88,12 +86,11 @@ func (s *initScaffolder) Scaffold() error {
&templates.HelmChart{},
&templates.HelmValues{
HasWebhooks: len(webhooks) > 0,
Webhooks: webhooks,
DeployImages: imagesEnvVars,
Force: s.force,
},
&templates.HelmIgnore{},
&chart_templates.HelmHelpers{},
&chartTemplates.HelmHelpers{},
&manager.ManagerDeployment{
Force: s.force,
DeployImages: len(imagesEnvVars) > 0,
Expand All @@ -105,8 +102,12 @@ func (s *initScaffolder) Scaffold() error {
}

if len(webhooks) > 0 {
buildScaffold = append(buildScaffold, &templateswebhooks.WebhookTemplate{})
buildScaffold = append(buildScaffold, &templateswebhooks.WebhookService{})
buildScaffold = append(buildScaffold,
&templateswebhooks.WebhookTemplate{
Webhooks: webhooks,
},
&templateswebhooks.WebhookService{},
)
}

if err := scaffold.Execute(buildScaffold...); err != nil {
Expand Down Expand Up @@ -146,23 +147,64 @@ func (s *initScaffolder) getDeployImagesEnvVars() map[string]string {
return deployImages
}

// Extract webhooks from manifests.yaml file
func extractWebhooksFromGeneratedFiles() ([]helm.WebhookYAML, error) {
var webhooks []helm.WebhookYAML
// extractWebhooks reads webhook YAML configurations and converts them to Webhook structs.
func (s *initScaffolder) extractWebhooks() ([]templateswebhooks.Webhook, error) {
var webhooks []templateswebhooks.Webhook
manifestFile := "config/webhook/manifests.yaml"
if _, err := os.Stat(manifestFile); err == nil {
content, err := os.ReadFile(manifestFile)
if err != nil {
return nil, fmt.Errorf("failed to read manifests.yaml: %w", err)
}

// Process the content to extract webhooks
webhooks = append(webhooks, extractWebhookYAML(content)...)
} else {
// Return empty if no webhooks were found
if _, err := os.Stat(manifestFile); os.IsNotExist(err) {
log.Printf("No webhook manifests found at %s", manifestFile)
return webhooks, nil
}

content, err := os.ReadFile(manifestFile)
if err != nil {
return nil, fmt.Errorf("failed to read %s: %w", manifestFile, err)
}

docs := strings.Split(string(content), "---")
for _, doc := range docs {
var webhookConfig struct {
Kind string `yaml:"kind"`
Webhooks []struct {
Name string `yaml:"name"`
ClientConfig struct {
Service struct {
Name string `yaml:"name"`
Namespace string `yaml:"namespace"`
Path string `yaml:"path"`
} `yaml:"service"`
} `yaml:"clientConfig"`
Rules []templateswebhooks.WebhookRule `yaml:"rules"`
FailurePolicy string `yaml:"failurePolicy"`
SideEffects string `yaml:"sideEffects"`
AdmissionReviewVersions []string `yaml:"admissionReviewVersions"`
} `yaml:"webhooks"`
}

if err := yaml.Unmarshal([]byte(doc), &webhookConfig); err != nil {
log.Errorf("Error parsing webhook YAML: %v", err)
continue
}

webhookType := "validating"
if webhookConfig.Kind == "MutatingWebhookConfiguration" {
webhookType = "mutating"
}

for _, w := range webhookConfig.Webhooks {
webhooks = append(webhooks, templateswebhooks.Webhook{
Name: w.Name,
Type: webhookType,
ServiceName: w.ClientConfig.Service.Name,
Path: w.ClientConfig.Service.Path,
FailurePolicy: w.FailurePolicy,
SideEffects: w.SideEffects,
AdmissionReviewVersions: w.AdmissionReviewVersions,
Rules: w.Rules,
})
}
}
return webhooks, nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ var _ machinery.Template = &WebhookTemplate{}
type WebhookTemplate struct {
machinery.TemplateMixin
machinery.ProjectNameMixin

Webhooks []Webhook
}

// SetTemplateDefaults sets default configuration for the webhook template
Expand All @@ -42,12 +44,32 @@ func (f *WebhookTemplate) SetTemplateDefaults() error {
return nil
}

const webhookTemplate = `{{` + "`" + `{{- if .Values.webhook.enable }}` + "`" + `}}
// Webhook helps generate the bollerplate with the Webhook values
type Webhook struct {
ServiceName string
Name string
Path string
Type string
FailurePolicy string
SideEffects string
AdmissionReviewVersions []string
Rules []WebhookRule
}

// WebhookRule to help map the rules
type WebhookRule struct {
Operations []string
APIGroups []string
APIVersions []string
Resources []string
}

const webhookTemplate = `{{` + "`" + `{{- if .Values.webhook.enable }}` + "`" + `}}
{{- range .Webhooks }}
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
kind: {{ if eq .Type "mutating" }}MutatingWebhookConfiguration{{ else }}ValidatingWebhookConfiguration{{ end }}
metadata:
name: {{ .ProjectName }}-mutating-webhook-configuration
name: {{ .Name }}
namespace: {{ "{{ .Release.Namespace }}" }}
annotations:
{{` + "`" + `{{- if .Values.certmanager.enable }}` + "`" + `}}
Expand All @@ -56,87 +78,38 @@ metadata:
labels:
{{ "{{- include \"chart.labels\" . | nindent 4 }}" }}
webhooks:
{{` + "`" + `{{- range .Values.webhook.services }}` + "`" + `}}
{{` + "`" + `{{- if eq .type "mutating" }}` + "`" + `}}
- name: {{` + "`" + `{{ .name }}` + "`" + `}}
clientConfig:
service:
name: {{ .ProjectName }}-webhook-service
namespace: {{` + "`" + `{{ $.Release.Namespace }}` + "`" + `}}
path: {{` + "`" + `{{ .path }}` + "`" + `}}
failurePolicy: {{` + "`" + `{{ .failurePolicy }}` + "`" + `}}
sideEffects: {{` + "`" + `{{ .sideEffects }}` + "`" + `}}
admissionReviewVersions:
{{` + "`" + `{{- range .admissionReviewVersions }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
rules:
{{` + "`" + `{{- range .rules }}` + "`" + `}}
- operations:
{{` + "`" + `{{- range .operations }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
apiGroups:
{{` + "`" + `{{- range .apiGroups }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
apiVersions:
{{` + "`" + `{{- range .apiVersions }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
resources:
{{` + "`" + `{{- range .resources }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: {{ .ProjectName }}-validating-webhook-configuration
namespace: {{ "{{ .Release.Namespace }}" }}
annotations:
{{` + "`" + `{{- if .Values.certmanager.enable }}` + "`" + `}}
cert-manager.io/inject-ca-from: "{{` + "`" + `{{ $.Release.Namespace }}` + "`" + `}}/serving-cert"
{{` + "`" + `{{- end }}` + "`" + `}}
webhooks:
{{` + "`" + `{{- range .Values.webhook.services }}` + "`" + `}}
{{` + "`" + `{{- if eq .type "validating" }}` + "`" + `}}
- name: {{` + "`" + `{{ .name }}` + "`" + `}}
- name: {{ .Name }}
clientConfig:
service:
name: {{ .ProjectName }}-webhook-service
namespace: {{` + "`" + `{{ $.Release.Namespace }}` + "`" + `}}
path: {{` + "`" + `{{ .path }}` + "`" + `}}
failurePolicy: {{` + "`" + `{{ .failurePolicy }}` + "`" + `}}
sideEffects: {{` + "`" + `{{ .sideEffects }}` + "`" + `}}
name: {{ .ServiceName }}
namespace: {{ "{{ .Release.Namespace }}" }}
path: {{ .Path }}
failurePolicy: {{ .FailurePolicy }}
sideEffects: {{ .SideEffects }}
admissionReviewVersions:
{{` + "`" + `{{- range .admissionReviewVersions }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{- range .AdmissionReviewVersions }}
- {{ . }}
{{- end }}
rules:
{{` + "`" + `{{- range .rules }}` + "`" + `}}
{{- range .Rules }}
- operations:
{{` + "`" + `{{- range .operations }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{- range .Operations }}
- {{ . }}
{{- end }}
apiGroups:
{{` + "`" + `{{- range .apiGroups }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{- range .APIGroups }}
- {{ . }}
{{- end }}
apiVersions:
{{` + "`" + `{{- range .apiVersions }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{- range .APIVersions }}
- {{ . }}
{{- end }}
resources:
{{` + "`" + `{{- range .resources }}` + "`" + `}}
- {{` + "`" + `{{ . }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{` + "`" + `{{- end }}` + "`" + `}}
{{- range .Resources }}
- {{ . }}
{{- end }}
{{- end }}
---
{{- end }}
{{` + "`" + `{{- end }}` + "`" + `}}
`
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"path/filepath"

"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm"
)

var _ machinery.Template = &HelmValues{}
Expand All @@ -33,8 +32,6 @@ type HelmValues struct {
DeployImages map[string]string
// Force if true allows overwriting the scaffolded file
Force bool
// Webhooks stores the webhook configurations
Webhooks []helm.WebhookYAML
// HasWebhooks is true when webhooks were found in the config
HasWebhooks bool
}
Expand Down Expand Up @@ -125,52 +122,13 @@ crd:
# ControllerManager argument "--metrics-bind-address=:8443" is removed.
metrics:
enable: true
{{ if .Webhooks }}
{{ if .HasWebhooks }}
# [WEBHOOKS]: Webhooks configuration
# The following configuration is automatically generated from the manifests
# generated by controller-gen. To update run 'make manifests' and
# the edit command with the '--force' flag
webhook:
enable: true
services:
{{- range .Webhooks }}
- name: {{ .Name }}
type: {{ .Type }}
path: {{ .Path }}
failurePolicy: {{ .FailurePolicy }}
sideEffects: {{ .SideEffects }}
admissionReviewVersions:
{{- range .AdmissionReviewVersions }}
- {{ . }}
{{- end }}
rules:
{{- range .Rules }}
- operations:
{{- range .Operations }}
- {{ . }}
{{- end }}
apiGroups:
{{- if .APIGroups }}
{{- range .APIGroups }}
{{- if eq . "" }}
- ""
{{- else }}
- {{ . }}
{{- end }}
{{- end }}
{{- else }}
- ""
{{- end }}
apiVersions:
{{- range .APIVersions }}
- {{ . }}
{{- end }}
resources:
{{- range .Resources }}
- {{ . }}
{{- end }}
{{- end }}
{{- end }}
{{ end }}
# [PROMETHEUS]: To enable a ServiceMonitor to export metrics to Prometheus set true
prometheus:
Expand Down
Loading

0 comments on commit 2c9f1e3

Please sign in to comment.