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  )