sigs.k8s.io/kubebuilder/v3@v3.14.0/pkg/plugins/golang/v4/scaffolds/internal/templates/api/webhook.go (about) 1 /* 2 Copyright 2022 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 api 18 19 import ( 20 "path/filepath" 21 "strings" 22 23 log "github.com/sirupsen/logrus" 24 25 "sigs.k8s.io/kubebuilder/v3/pkg/machinery" 26 ) 27 28 var _ machinery.Template = &Webhook{} 29 30 // Webhook scaffolds the file that defines a webhook for a CRD or a builtin resource 31 type Webhook struct { // nolint:maligned 32 machinery.TemplateMixin 33 machinery.MultiGroupMixin 34 machinery.BoilerplateMixin 35 machinery.ResourceMixin 36 37 // Is the Group domain for the Resource replacing '.' with '-' 38 QualifiedGroupWithDash string 39 40 // Define value for AdmissionReviewVersions marker 41 AdmissionReviewVersions string 42 43 Force bool 44 } 45 46 // SetTemplateDefaults implements file.Template 47 func (f *Webhook) SetTemplateDefaults() error { 48 if f.Path == "" { 49 if f.MultiGroup && f.Resource.Group != "" { 50 f.Path = filepath.Join("api", "%[group]", "%[version]", "%[kind]_webhook.go") 51 } else { 52 f.Path = filepath.Join("api", "%[version]", "%[kind]_webhook.go") 53 } 54 } 55 56 f.Path = f.Resource.Replacer().Replace(f.Path) 57 log.Println(f.Path) 58 59 webhookTemplate := webhookTemplate 60 if f.Resource.HasDefaultingWebhook() { 61 webhookTemplate = webhookTemplate + defaultingWebhookTemplate 62 } 63 if f.Resource.HasValidationWebhook() { 64 webhookTemplate = webhookTemplate + validatingWebhookTemplate 65 } 66 f.TemplateBody = webhookTemplate 67 68 if f.Force { 69 f.IfExistsAction = machinery.OverwriteFile 70 } else { 71 f.IfExistsAction = machinery.Error 72 } 73 74 f.AdmissionReviewVersions = "v1" 75 f.QualifiedGroupWithDash = strings.Replace(f.Resource.QualifiedGroup(), ".", "-", -1) 76 77 return nil 78 } 79 80 const ( 81 webhookTemplate = `{{ .Boilerplate }} 82 83 package {{ .Resource.Version }} 84 85 import ( 86 ctrl "sigs.k8s.io/controller-runtime" 87 logf "sigs.k8s.io/controller-runtime/pkg/log" 88 {{- if .Resource.HasValidationWebhook }} 89 "k8s.io/apimachinery/pkg/runtime" 90 "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 91 {{- end }} 92 {{- if or .Resource.HasValidationWebhook .Resource.HasDefaultingWebhook }} 93 "sigs.k8s.io/controller-runtime/pkg/webhook" 94 {{- end }} 95 96 ) 97 98 // log is for logging in this package. 99 var {{ lower .Resource.Kind }}log = logf.Log.WithName("{{ lower .Resource.Kind }}-resource") 100 101 // SetupWebhookWithManager will setup the manager to manage the webhooks 102 func (r *{{ .Resource.Kind }}) SetupWebhookWithManager(mgr ctrl.Manager) error { 103 return ctrl.NewWebhookManagedBy(mgr). 104 For(r). 105 Complete() 106 } 107 108 // TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 109 ` 110 111 //nolint:lll 112 defaultingWebhookTemplate = ` 113 //+kubebuilder:webhook:{{ if ne .Resource.Webhooks.WebhookVersion "v1" }}webhookVersions={{"{"}}{{ .Resource.Webhooks.WebhookVersion }}{{"}"}},{{ end }}path=/mutate-{{ .QualifiedGroupWithDash }}-{{ .Resource.Version }}-{{ lower .Resource.Kind }},mutating=true,failurePolicy=fail,sideEffects=None,groups={{ .Resource.QualifiedGroup }},resources={{ .Resource.Plural }},verbs=create;update,versions={{ .Resource.Version }},name=m{{ lower .Resource.Kind }}.kb.io,admissionReviewVersions={{ .AdmissionReviewVersions }} 114 115 var _ webhook.Defaulter = &{{ .Resource.Kind }}{} 116 117 // Default implements webhook.Defaulter so a webhook will be registered for the type 118 func (r *{{ .Resource.Kind }}) Default() { 119 {{ lower .Resource.Kind }}log.Info("default", "name", r.Name) 120 121 // TODO(user): fill in your defaulting logic. 122 } 123 ` 124 125 //nolint:lll 126 validatingWebhookTemplate = ` 127 // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. 128 //+kubebuilder:webhook:{{ if ne .Resource.Webhooks.WebhookVersion "v1" }}webhookVersions={{"{"}}{{ .Resource.Webhooks.WebhookVersion }}{{"}"}},{{ end }}path=/validate-{{ .QualifiedGroupWithDash }}-{{ .Resource.Version }}-{{ lower .Resource.Kind }},mutating=false,failurePolicy=fail,sideEffects=None,groups={{ .Resource.QualifiedGroup }},resources={{ .Resource.Plural }},verbs=create;update,versions={{ .Resource.Version }},name=v{{ lower .Resource.Kind }}.kb.io,admissionReviewVersions={{ .AdmissionReviewVersions }} 129 130 var _ webhook.Validator = &{{ .Resource.Kind }}{} 131 132 // ValidateCreate implements webhook.Validator so a webhook will be registered for the type 133 func (r *{{ .Resource.Kind }}) ValidateCreate() (admission.Warnings, error) { 134 {{ lower .Resource.Kind }}log.Info("validate create", "name", r.Name) 135 136 // TODO(user): fill in your validation logic upon object creation. 137 return nil, nil 138 } 139 140 // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type 141 func (r *{{ .Resource.Kind }}) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { 142 {{ lower .Resource.Kind }}log.Info("validate update", "name", r.Name) 143 144 // TODO(user): fill in your validation logic upon object update. 145 return nil, nil 146 } 147 148 // ValidateDelete implements webhook.Validator so a webhook will be registered for the type 149 func (r *{{ .Resource.Kind }}) ValidateDelete() (admission.Warnings, error) { 150 {{ lower .Resource.Kind }}log.Info("validate delete", "name", r.Name) 151 152 // TODO(user): fill in your validation logic upon object deletion. 153 return nil,nil 154 } 155 ` 156 )