update dependencies

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-12-22 16:48:26 +08:00
parent 4a11a50544
commit fe6c5de00f
2857 changed files with 252134 additions and 115656 deletions

View File

@@ -0,0 +1,44 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package webhook
import (
admissionregv1 "k8s.io/api/admissionregistration/v1"
admissionregv1beta1 "k8s.io/api/admissionregistration/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var (
conversionScheme = runtime.NewScheme()
)
func init() {
utilruntime.Must(admissionregv1.AddToScheme(conversionScheme))
utilruntime.Must(admissionregv1beta1.AddToScheme(conversionScheme))
}
// MutatingWebhookConfigurationAsVersion converts a MutatingWebhookConfiguration from the canonical internal form (currently v1) to some external form.
func MutatingWebhookConfigurationAsVersion(original *admissionregv1.MutatingWebhookConfiguration, gv schema.GroupVersion) (runtime.Object, error) {
return conversionScheme.ConvertToVersion(original, gv)
}
// ValidatingWebhookConfigurationAsVersion converts a ValidatingWebhookConfiguration from the canonical internal form (currently v1) to some external form.
func ValidatingWebhookConfigurationAsVersion(original *admissionregv1.ValidatingWebhookConfiguration, gv schema.GroupVersion) (runtime.Object, error) {
return conversionScheme.ConvertToVersion(original, gv)
}

View File

@@ -19,26 +19,38 @@ limitations under the License.
//
// The markers take the form:
//
// +kubebuilder:webhook:failurePolicy=<string>,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=<string>,path=<string>,mutating=<bool>
// +kubebuilder:webhook:webhookVersions=<[]string>,failurePolicy=<string>,matchPolicy=<string>,groups=<[]string>,resources=<[]string>,verbs=<[]string>,versions=<[]string>,name=<string>,path=<string>,mutating=<bool>,sideEffects=<string>
package webhook
import (
"fmt"
"strings"
admissionreg "k8s.io/api/admissionregistration/v1beta1"
admissionregv1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-tools/pkg/genall"
"sigs.k8s.io/controller-tools/pkg/markers"
)
// The default {Mutating,Validating}WebhookConfiguration version to generate.
const (
defaultWebhookVersion = "v1"
)
var (
// ConfigDefinition s a marker for defining Webhook manifests.
// Call ToWebhook on the value to get a Kubernetes Webhook.
ConfigDefinition = markers.Must(markers.MakeDefinition("kubebuilder:webhook", markers.DescribesPackage, Config{}))
)
// supportedWebhookVersions returns currently supported API version of {Mutating,Validating}WebhookConfiguration.
func supportedWebhookVersions() []string {
return []string{defaultWebhookVersion, "v1beta1"}
}
// +controllertools:marker:generateHelp:category=Webhook
// Config specifies how a webhook should be served.
@@ -57,6 +69,17 @@ type Config struct {
// It may be either "ignore" (to skip the webhook and continue on) or "fail" (to reject
// the object in question).
FailurePolicy string
// MatchPolicy defines how the "rules" list is used to match incoming requests.
// Allowed values are "Exact" (match only if it exactly matches the specified rule)
// or "Equivalent" (match a request if it modifies a resource listed in rules, even via another API group or version).
MatchPolicy string `marker:",optional"`
// SideEffects specify whether calling the webhook will have side effects.
// This has an impact on dry runs and `kubectl diff`: if the sideEffect is "Unknown" (the default) or "Some", then
// the API server will not call the webhook on a dry-run request and fails instead.
// If the value is "None", then the webhook has no side effects and the API server will call it on dry-run.
// If the value is "NoneOnDryRun", then the webhook is responsible for inspecting the "dryRun" property of the
// AdmissionReview sent in the request, and avoiding side effects if that value is "true."
SideEffects string `marker:",optional"`
// Groups specifies the API groups that this webhook receives requests for.
Groups []string
@@ -70,69 +93,99 @@ type Config struct {
// Versions specifies the API versions that this webhook receives requests for.
Versions []string
// Name indicates the name of this webhook configuration.
// Name indicates the name of this webhook configuration. Should be a domain with at least three segments separated by dots
Name string
// Path specifies that path that the API server should connect to this webhook on.
// Path specifies that path that the API server should connect to this webhook on. Must be
// prefixed with a '/validate-' or '/mutate-' depending on the type, and followed by
// $GROUP-$VERSION-$KIND where all values are lower-cased and the periods in the group
// are substituted for hyphens. For example, a validating webhook path for type
// batch.tutorial.kubebuilder.io/v1,Kind=CronJob would be
// /validate-batch-tutorial-kubebuilder-io-v1-cronjob
Path string
// WebhookVersions specifies the target API versions of the {Mutating,Validating}WebhookConfiguration objects
// itself to generate. Defaults to v1.
WebhookVersions []string `marker:"webhookVersions,optional"`
}
// verbToAPIVariant converts a marker's verb to the proper value for the API.
// Unrecognized verbs are passed through.
func verbToAPIVariant(verbRaw string) admissionreg.OperationType {
func verbToAPIVariant(verbRaw string) admissionregv1.OperationType {
switch strings.ToLower(verbRaw) {
case strings.ToLower(string(admissionreg.Create)):
return admissionreg.Create
case strings.ToLower(string(admissionreg.Update)):
return admissionreg.Update
case strings.ToLower(string(admissionreg.Delete)):
return admissionreg.Delete
case strings.ToLower(string(admissionreg.Connect)):
return admissionreg.Connect
case strings.ToLower(string(admissionreg.OperationAll)):
return admissionreg.OperationAll
case strings.ToLower(string(admissionregv1.Create)):
return admissionregv1.Create
case strings.ToLower(string(admissionregv1.Update)):
return admissionregv1.Update
case strings.ToLower(string(admissionregv1.Delete)):
return admissionregv1.Delete
case strings.ToLower(string(admissionregv1.Connect)):
return admissionregv1.Connect
case strings.ToLower(string(admissionregv1.OperationAll)):
return admissionregv1.OperationAll
default:
return admissionreg.OperationType(verbRaw)
return admissionregv1.OperationType(verbRaw)
}
}
// ToMutatingWebhook converts this rule to its Kubernetes API form.
func (c Config) ToMutatingWebhook() (admissionreg.MutatingWebhook, error) {
func (c Config) ToMutatingWebhook() (admissionregv1.MutatingWebhook, error) {
if !c.Mutating {
return admissionreg.MutatingWebhook{}, fmt.Errorf("%s is a validating webhook", c.Name)
return admissionregv1.MutatingWebhook{}, fmt.Errorf("%s is a validating webhook", c.Name)
}
return admissionreg.MutatingWebhook{
matchPolicy, err := c.matchPolicy()
if err != nil {
return admissionregv1.MutatingWebhook{}, err
}
return admissionregv1.MutatingWebhook{
Name: c.Name,
Rules: c.rules(),
FailurePolicy: c.failurePolicy(),
MatchPolicy: matchPolicy,
ClientConfig: c.clientConfig(),
SideEffects: c.sideEffects(),
// TODO(jiachengxu): AdmissionReviewVersions becomes required in admissionregistration/v1, here we default it
// to `v1` and `v1beta1`, and we should support to config the `AdmissionReviewVersions` as a marker.
AdmissionReviewVersions: []string{defaultWebhookVersion, "v1beta1"},
}, nil
}
// ToValidatingWebhook converts this rule to its Kubernetes API form.
func (c Config) ToValidatingWebhook() (admissionreg.ValidatingWebhook, error) {
func (c Config) ToValidatingWebhook() (admissionregv1.ValidatingWebhook, error) {
if c.Mutating {
return admissionreg.ValidatingWebhook{}, fmt.Errorf("%s is a mutating webhook", c.Name)
return admissionregv1.ValidatingWebhook{}, fmt.Errorf("%s is a mutating webhook", c.Name)
}
return admissionreg.ValidatingWebhook{
matchPolicy, err := c.matchPolicy()
if err != nil {
return admissionregv1.ValidatingWebhook{}, err
}
return admissionregv1.ValidatingWebhook{
Name: c.Name,
Rules: c.rules(),
FailurePolicy: c.failurePolicy(),
MatchPolicy: matchPolicy,
ClientConfig: c.clientConfig(),
SideEffects: c.sideEffects(),
// TODO(jiachengxu): AdmissionReviewVersions becomes required in admissionregistration/v1, here we default it
// to `v1` and `v1beta1`, and we should support to config the `AdmissionReviewVersions` as a marker.
AdmissionReviewVersions: []string{defaultWebhookVersion, "v1beta1"},
}, nil
}
// rules returns the configuration of what operations on what
// resources/subresources a webhook should care about.
func (c Config) rules() []admissionreg.RuleWithOperations {
whConfig := admissionreg.RuleWithOperations{
Rule: admissionreg.Rule{
func (c Config) rules() []admissionregv1.RuleWithOperations {
whConfig := admissionregv1.RuleWithOperations{
Rule: admissionregv1.Rule{
APIGroups: c.Groups,
APIVersions: c.Versions,
Resources: c.Resources,
},
Operations: make([]admissionreg.OperationType, len(c.Verbs)),
Operations: make([]admissionregv1.OperationType, len(c.Verbs)),
}
for i, verbRaw := range c.Verbs {
@@ -146,29 +199,45 @@ func (c Config) rules() []admissionreg.RuleWithOperations {
}
}
return []admissionreg.RuleWithOperations{whConfig}
return []admissionregv1.RuleWithOperations{whConfig}
}
// failurePolicy converts the string value to the proper value for the API.
// Unrecognized values are passed through.
func (c Config) failurePolicy() *admissionreg.FailurePolicyType {
var failurePolicy admissionreg.FailurePolicyType
func (c Config) failurePolicy() *admissionregv1.FailurePolicyType {
var failurePolicy admissionregv1.FailurePolicyType
switch strings.ToLower(c.FailurePolicy) {
case strings.ToLower(string(admissionreg.Ignore)):
failurePolicy = admissionreg.Ignore
case strings.ToLower(string(admissionreg.Fail)):
failurePolicy = admissionreg.Fail
case strings.ToLower(string(admissionregv1.Ignore)):
failurePolicy = admissionregv1.Ignore
case strings.ToLower(string(admissionregv1.Fail)):
failurePolicy = admissionregv1.Fail
default:
failurePolicy = admissionreg.FailurePolicyType(c.FailurePolicy)
failurePolicy = admissionregv1.FailurePolicyType(c.FailurePolicy)
}
return &failurePolicy
}
// matchPolicy converts the string value to the proper value for the API.
func (c Config) matchPolicy() (*admissionregv1.MatchPolicyType, error) {
var matchPolicy admissionregv1.MatchPolicyType
switch strings.ToLower(c.MatchPolicy) {
case strings.ToLower(string(admissionregv1.Exact)):
matchPolicy = admissionregv1.Exact
case strings.ToLower(string(admissionregv1.Equivalent)):
matchPolicy = admissionregv1.Equivalent
case "":
return nil, nil
default:
return nil, fmt.Errorf("unknown value %q for matchPolicy", c.MatchPolicy)
}
return &matchPolicy, nil
}
// clientConfig returns the client config for a webhook.
func (c Config) clientConfig() admissionreg.WebhookClientConfig {
func (c Config) clientConfig() admissionregv1.WebhookClientConfig {
path := c.Path
return admissionreg.WebhookClientConfig{
Service: &admissionreg.ServiceReference{
return admissionregv1.WebhookClientConfig{
Service: &admissionregv1.ServiceReference{
Name: "webhook-service",
Namespace: "system",
Path: &path,
@@ -180,6 +249,39 @@ func (c Config) clientConfig() admissionreg.WebhookClientConfig {
}
}
// sideEffects returns the sideEffects config for a webhook.
func (c Config) sideEffects() *admissionregv1.SideEffectClass {
var sideEffects admissionregv1.SideEffectClass
switch strings.ToLower(c.SideEffects) {
case strings.ToLower(string(admissionregv1.SideEffectClassNone)):
sideEffects = admissionregv1.SideEffectClassNone
case strings.ToLower(string(admissionregv1.SideEffectClassNoneOnDryRun)):
sideEffects = admissionregv1.SideEffectClassNoneOnDryRun
case strings.ToLower(string(admissionregv1.SideEffectClassSome)):
sideEffects = admissionregv1.SideEffectClassSome
case "":
return nil
default:
return nil
}
return &sideEffects
}
// webhookVersions returns the target API versions of the {Mutating,Validating}WebhookConfiguration objects for a webhook.
func (c Config) webhookVersions() ([]string, error) {
// If WebhookVersions is not specified, we default it to `v1`.
if len(c.WebhookVersions) == 0 {
return []string{defaultWebhookVersion}, nil
}
supportedWebhookVersions := sets.NewString(supportedWebhookVersions()...)
for _, version := range c.WebhookVersions {
if !supportedWebhookVersions.Has(version) {
return nil, fmt.Errorf("unsupported webhook version: %s", version)
}
}
return sets.NewString(c.WebhookVersions...).UnsortedList(), nil
}
// +controllertools:marker:generateHelp
// Generator generates (partial) {Mutating,Validating}WebhookConfiguration objects.
@@ -194,8 +296,9 @@ func (Generator) RegisterMarkers(into *markers.Registry) error {
}
func (Generator) Generate(ctx *genall.GenerationContext) error {
var mutatingCfgs []admissionreg.MutatingWebhook
var validatingCfgs []admissionreg.ValidatingWebhook
supportedWebhookVersions := supportedWebhookVersions()
mutatingCfgs := make(map[string][]admissionregv1.MutatingWebhook, len(supportedWebhookVersions))
validatingCfgs := make(map[string][]admissionregv1.ValidatingWebhook, len(supportedWebhookVersions))
for _, root := range ctx.Roots {
markerSet, err := markers.PackageMarkers(ctx.Collector, root)
if err != nil {
@@ -204,47 +307,128 @@ func (Generator) Generate(ctx *genall.GenerationContext) error {
for _, cfg := range markerSet[ConfigDefinition.Name] {
cfg := cfg.(Config)
webhookVersions, err := cfg.webhookVersions()
if err != nil {
return err
}
if cfg.Mutating {
w, _ := cfg.ToMutatingWebhook()
mutatingCfgs = append(mutatingCfgs, w)
w, err := cfg.ToMutatingWebhook()
if err != nil {
return err
}
for _, webhookVersion := range webhookVersions {
mutatingCfgs[webhookVersion] = append(mutatingCfgs[webhookVersion], w)
}
} else {
w, _ := cfg.ToValidatingWebhook()
validatingCfgs = append(validatingCfgs, w)
w, err := cfg.ToValidatingWebhook()
if err != nil {
return err
}
for _, webhookVersion := range webhookVersions {
validatingCfgs[webhookVersion] = append(validatingCfgs[webhookVersion], w)
}
}
}
}
var objs []interface{}
if len(mutatingCfgs) > 0 {
objs = append(objs, &admissionreg.MutatingWebhookConfiguration{
TypeMeta: metav1.TypeMeta{
Kind: "MutatingWebhookConfiguration",
APIVersion: admissionreg.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "mutating-webhook-configuration",
},
Webhooks: mutatingCfgs,
})
versionedWebhooks := make(map[string][]interface{}, len(supportedWebhookVersions))
for _, version := range supportedWebhookVersions {
if cfgs, ok := mutatingCfgs[version]; ok {
objRaw := &admissionregv1.MutatingWebhookConfiguration{
TypeMeta: metav1.TypeMeta{
Kind: "MutatingWebhookConfiguration",
APIVersion: admissionregv1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "mutating-webhook-configuration",
},
Webhooks: cfgs,
}
// SideEffects in required in admissionregistration/v1, if this is not set or set to `Some` or `Known`,
// we return an error
if version == defaultWebhookVersion {
for i := range objRaw.Webhooks {
if err := checkSideEffectsForV1(objRaw.Webhooks[i].SideEffects); err != nil {
return err
}
}
}
// AdmissionReviewVersions is optional in admissionregistration/v1beta1, so let kubernetes to default it.
if version == "v1beta1" {
for i := range objRaw.Webhooks {
objRaw.Webhooks[i].AdmissionReviewVersions = nil
}
}
if version != defaultWebhookVersion {
conv, err := MutatingWebhookConfigurationAsVersion(objRaw, schema.GroupVersion{Group: admissionregv1.SchemeGroupVersion.Group, Version: version})
versionedWebhooks[version] = append(versionedWebhooks[version], conv)
if err != nil {
return err
}
} else {
versionedWebhooks[version] = append(versionedWebhooks[version], objRaw)
}
}
if cfgs, ok := validatingCfgs[version]; ok {
objRaw := &admissionregv1.ValidatingWebhookConfiguration{
TypeMeta: metav1.TypeMeta{
Kind: "ValidatingWebhookConfiguration",
APIVersion: admissionregv1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "validating-webhook-configuration",
},
Webhooks: cfgs,
}
// SideEffects in required in admissionregistration/v1, if this is not set or set to `Some` or `Known`,
// we return an error
if version == defaultWebhookVersion {
for i := range objRaw.Webhooks {
if err := checkSideEffectsForV1(objRaw.Webhooks[i].SideEffects); err != nil {
return err
}
}
}
// AdmissionReviewVersions is optional in admissionregistration/v1beta1, so let kubernetes to default it.
if version == "v1beta1" {
for i := range objRaw.Webhooks {
objRaw.Webhooks[i].AdmissionReviewVersions = nil
}
}
if version != defaultWebhookVersion {
conv, err := ValidatingWebhookConfigurationAsVersion(objRaw, schema.GroupVersion{Group: admissionregv1.SchemeGroupVersion.Group, Version: version})
versionedWebhooks[version] = append(versionedWebhooks[version], conv)
if err != nil {
return err
}
} else {
versionedWebhooks[version] = append(versionedWebhooks[version], objRaw)
}
}
}
if len(validatingCfgs) > 0 {
objs = append(objs, &admissionreg.ValidatingWebhookConfiguration{
TypeMeta: metav1.TypeMeta{
Kind: "ValidatingWebhookConfiguration",
APIVersion: admissionreg.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "validating-webhook-configuration",
},
Webhooks: validatingCfgs,
})
for k, v := range versionedWebhooks {
var fileName string
if k == defaultWebhookVersion {
fileName = fmt.Sprintf("manifests.yaml")
} else {
fileName = fmt.Sprintf("manifests.%s.yaml", k)
}
if err := ctx.WriteYAML(fileName, v...); err != nil {
return err
}
}
return nil
}
func checkSideEffectsForV1(sideEffects *admissionregv1.SideEffectClass) error {
if sideEffects == nil {
return fmt.Errorf("SideEffects is required for creating v1 {Mutating,Validating}WebhookConfiguration")
}
if *sideEffects == admissionregv1.SideEffectClassUnknown ||
*sideEffects == admissionregv1.SideEffectClassSome {
return fmt.Errorf("SideEffects should not be set to `Some` or `Unknown` for v1 {Mutating,Validating}WebhookConfiguration")
}
if err := ctx.WriteYAML("manifests.yaml", objs...); err != nil {
return err
}
return nil
}

View File

@@ -40,6 +40,14 @@ func (Config) Help() *markers.DefinitionHelp {
Summary: "specifies what should happen if the API server cannot reach the webhook. ",
Details: "It may be either \"ignore\" (to skip the webhook and continue on) or \"fail\" (to reject the object in question).",
},
"MatchPolicy": markers.DetailedHelp{
Summary: "defines how the \"rules\" list is used to match incoming requests. Allowed values are \"Exact\" (match only if it exactly matches the specified rule) or \"Equivalent\" (match a request if it modifies a resource listed in rules, even via another API group or version).",
Details: "",
},
"SideEffects": markers.DetailedHelp{
Summary: "specify whether calling the webhook will have side effects. This has an impact on dry runs and `kubectl diff`: if the sideEffect is \"Unknown\" (the default) or \"Some\", then the API server will not call the webhook on a dry-run request and fails instead. If the value is \"None\", then the webhook has no side effects and the API server will call it on dry-run. If the value is \"NoneOnDryRun\", then the webhook is responsible for inspecting the \"dryRun\" property of the AdmissionReview sent in the request, and avoiding side effects if that value is \"true.\"",
Details: "",
},
"Groups": markers.DetailedHelp{
Summary: "specifies the API groups that this webhook receives requests for.",
Details: "",
@@ -57,11 +65,15 @@ func (Config) Help() *markers.DefinitionHelp {
Details: "",
},
"Name": markers.DetailedHelp{
Summary: "indicates the name of this webhook configuration.",
Summary: "indicates the name of this webhook configuration. Should be a domain with at least three segments separated by dots",
Details: "",
},
"Path": markers.DetailedHelp{
Summary: "specifies that path that the API server should connect to this webhook on.",
Summary: "specifies that path that the API server should connect to this webhook on. Must be prefixed with a '/validate-' or '/mutate-' depending on the type, and followed by $GROUP-$VERSION-$KIND where all values are lower-cased and the periods in the group are substituted for hyphens. For example, a validating webhook path for type batch.tutorial.kubebuilder.io/v1,Kind=CronJob would be /validate-batch-tutorial-kubebuilder-io-v1-cronjob",
Details: "",
},
"WebhookVersions": markers.DetailedHelp{
Summary: "specifies the target API versions of the {Mutating,Validating}WebhookConfiguration objects itself to generate. Defaults to v1.",
Details: "",
},
},