sigs.k8s.io/kubebuilder/v3@v3.14.0/pkg/plugins/golang/v3/scaffolds/internal/templates/api/webhook.go (about)

     1  /*
     2  Copyright 2020 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 {
    50  			if f.Resource.Group != "" {
    51  				f.Path = filepath.Join("apis", "%[group]", "%[version]", "%[kind]_webhook.go")
    52  			} else {
    53  				f.Path = filepath.Join("apis", "%[version]", "%[kind]_webhook.go")
    54  			}
    55  		} else {
    56  			f.Path = filepath.Join("api", "%[version]", "%[kind]_webhook.go")
    57  		}
    58  	}
    59  	f.Path = f.Resource.Replacer().Replace(f.Path)
    60  	log.Println(f.Path)
    61  
    62  	webhookTemplate := webhookTemplate
    63  	if f.Resource.HasDefaultingWebhook() {
    64  		webhookTemplate = webhookTemplate + defaultingWebhookTemplate
    65  	}
    66  	if f.Resource.HasValidationWebhook() {
    67  		webhookTemplate = webhookTemplate + validatingWebhookTemplate
    68  	}
    69  	f.TemplateBody = webhookTemplate
    70  
    71  	if f.Force {
    72  		f.IfExistsAction = machinery.OverwriteFile
    73  	} else {
    74  		f.IfExistsAction = machinery.Error
    75  	}
    76  
    77  	f.AdmissionReviewVersions = "v1"
    78  	if f.Resource.Webhooks.WebhookVersion == "v1beta1" {
    79  		f.AdmissionReviewVersions = "{v1,v1beta1}"
    80  	}
    81  
    82  	f.QualifiedGroupWithDash = strings.Replace(f.Resource.QualifiedGroup(), ".", "-", -1)
    83  
    84  	return nil
    85  }
    86  
    87  const (
    88  	webhookTemplate = `{{ .Boilerplate }}
    89  
    90  package {{ .Resource.Version }}
    91  
    92  import (
    93  	ctrl "sigs.k8s.io/controller-runtime"
    94  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    95  	{{- if .Resource.HasValidationWebhook }}
    96  	"k8s.io/apimachinery/pkg/runtime"
    97  	{{- end }}
    98  	{{- if or .Resource.HasValidationWebhook .Resource.HasDefaultingWebhook }}
    99  	"sigs.k8s.io/controller-runtime/pkg/webhook"
   100  	{{- end }}
   101  )
   102  
   103  // log is for logging in this package.
   104  var {{ lower .Resource.Kind }}log = logf.Log.WithName("{{ lower .Resource.Kind }}-resource")
   105  
   106  func (r *{{ .Resource.Kind }}) SetupWebhookWithManager(mgr ctrl.Manager) error {
   107  	return ctrl.NewWebhookManagedBy(mgr).
   108  		For(r).
   109  		Complete()
   110  }
   111  
   112  // TODO(user): EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
   113  `
   114  
   115  	//nolint:lll
   116  	defaultingWebhookTemplate = `
   117  //+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 }}
   118  
   119  var _ webhook.Defaulter = &{{ .Resource.Kind }}{}
   120  
   121  // Default implements webhook.Defaulter so a webhook will be registered for the type
   122  func (r *{{ .Resource.Kind }}) Default() {
   123  	{{ lower .Resource.Kind }}log.Info("default", "name", r.Name)
   124  
   125  	// TODO(user): fill in your defaulting logic.
   126  }
   127  `
   128  
   129  	//nolint:lll
   130  	validatingWebhookTemplate = `
   131  // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation.
   132  //+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 }}
   133  
   134  var _ webhook.Validator = &{{ .Resource.Kind }}{}
   135  
   136  // ValidateCreate implements webhook.Validator so a webhook will be registered for the type
   137  func (r *{{ .Resource.Kind }}) ValidateCreate() error {
   138  	{{ lower .Resource.Kind }}log.Info("validate create", "name", r.Name)
   139  
   140  	// TODO(user): fill in your validation logic upon object creation.
   141  	return nil
   142  }
   143  
   144  // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
   145  func (r *{{ .Resource.Kind }}) ValidateUpdate(old runtime.Object) error {
   146  	{{ lower .Resource.Kind }}log.Info("validate update", "name", r.Name)
   147  
   148  	// TODO(user): fill in your validation logic upon object update.
   149  	return nil
   150  }
   151  
   152  // ValidateDelete implements webhook.Validator so a webhook will be registered for the type
   153  func (r *{{ .Resource.Kind }}) ValidateDelete() error {
   154  	{{ lower .Resource.Kind }}log.Info("validate delete", "name", r.Name)
   155  
   156  	// TODO(user): fill in your validation logic upon object deletion.
   157  	return nil
   158  }
   159  `
   160  )