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