sigs.k8s.io/kubebuilder/v3@v3.14.0/pkg/plugins/golang/v4/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 v4 18 19 import ( 20 "fmt" 21 22 "github.com/spf13/pflag" 23 24 "sigs.k8s.io/kubebuilder/v3/pkg/config" 25 "sigs.k8s.io/kubebuilder/v3/pkg/machinery" 26 "sigs.k8s.io/kubebuilder/v3/pkg/model/resource" 27 "sigs.k8s.io/kubebuilder/v3/pkg/plugin" 28 pluginutil "sigs.k8s.io/kubebuilder/v3/pkg/plugin/util" 29 goPlugin "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang" 30 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/v4/scaffolds" 31 ) 32 33 // defaultWebhookVersion is the default mutating/validating webhook config API version to scaffold. 34 const defaultWebhookVersion = "v1" 35 36 var _ plugin.CreateWebhookSubcommand = &createWebhookSubcommand{} 37 38 type createWebhookSubcommand struct { 39 config config.Config 40 // For help text. 41 commandName string 42 43 options *goPlugin.Options 44 45 resource *resource.Resource 46 47 // force indicates that the resource should be created even if it already exists 48 force bool 49 } 50 51 func (p *createWebhookSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) { 52 p.commandName = cliMeta.CommandName 53 54 subcmdMeta.Description = `Scaffold a webhook for an API resource. You can choose to scaffold defaulting, 55 validating and/or conversion webhooks. 56 ` 57 subcmdMeta.Examples = fmt.Sprintf(` # Create defaulting and validating webhooks for Group: ship, Version: v1beta1 58 # and Kind: Frigate 59 %[1]s create webhook --group ship --version v1beta1 --kind Frigate --defaulting --programmatic-validation 60 61 # Create conversion webhook for Group: ship, Version: v1beta1 62 # and Kind: Frigate 63 %[1]s create webhook --group ship --version v1beta1 --kind Frigate --conversion 64 `, cliMeta.CommandName) 65 } 66 67 func (p *createWebhookSubcommand) BindFlags(fs *pflag.FlagSet) { 68 p.options = &goPlugin.Options{} 69 70 fs.StringVar(&p.options.Plural, "plural", "", "resource irregular plural form") 71 72 fs.BoolVar(&p.options.DoDefaulting, "defaulting", false, 73 "if set, scaffold the defaulting webhook") 74 fs.BoolVar(&p.options.DoValidation, "programmatic-validation", false, 75 "if set, scaffold the validating webhook") 76 fs.BoolVar(&p.options.DoConversion, "conversion", false, 77 "if set, scaffold the conversion webhook") 78 79 fs.BoolVar(&p.force, "force", false, 80 "attempt to create resource even if it already exists") 81 } 82 83 func (p *createWebhookSubcommand) InjectConfig(c config.Config) error { 84 p.config = c 85 // go/v4 no longer supports v1beta1 option 86 p.options.WebhookVersion = defaultWebhookVersion 87 return nil 88 } 89 90 func (p *createWebhookSubcommand) InjectResource(res *resource.Resource) error { 91 p.resource = res 92 93 p.options.UpdateResource(p.resource, p.config) 94 95 if err := p.resource.Validate(); err != nil { 96 return err 97 } 98 99 if !p.resource.HasDefaultingWebhook() && !p.resource.HasValidationWebhook() && !p.resource.HasConversionWebhook() { 100 return fmt.Errorf("%s create webhook requires at least one of --defaulting,"+ 101 " --programmatic-validation and --conversion to be true", p.commandName) 102 } 103 104 // check if resource exist to create webhook 105 if r, err := p.config.GetResource(p.resource.GVK); err != nil { 106 return fmt.Errorf("%s create webhook requires a previously created API ", p.commandName) 107 } else if r.Webhooks != nil && !r.Webhooks.IsEmpty() && !p.force { 108 return fmt.Errorf("webhook resource already exists") 109 } 110 111 return nil 112 } 113 114 func (p *createWebhookSubcommand) Scaffold(fs machinery.Filesystem) error { 115 scaffolder := scaffolds.NewWebhookScaffolder(p.config, *p.resource, p.force) 116 scaffolder.InjectFS(fs) 117 return scaffolder.Scaffold() 118 } 119 120 func (p *createWebhookSubcommand) PostScaffold() error { 121 err := pluginutil.RunCmd("Update dependencies", "go", "mod", "tidy") 122 if err != nil { 123 return err 124 } 125 126 err = pluginutil.RunCmd("Running make", "make", "generate") 127 if err != nil { 128 return err 129 } 130 fmt.Print("Next: implement your new Webhook and generate the manifests with:\n$ make manifests\n") 131 132 return nil 133 }