Unverified Commit 25ebf875 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #55812 from deads2k/admission-17-external

Automatic merge from submit-queue (batch tested with PRs 55812, 55752, 55447, 55848, 50984). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Make versioned types for webhook admission config Versioned webhook admission config type as promised in https://github.com/kubernetes/kubernetes/pull/54414. @kubernetes/sig-api-machinery-pr-reviews @ericchiang as promised. fyi. ```yaml kind: AdmissionConfiguration apiVersion: apiserver.k8s.io/v1alpha1 plugins: - name: GenericAdmissionWebhook configuration: kind: WebhookAdmission apiVersion: apiserver.config.k8s.io/v1alpha1 kubeConfigFile: /path/to/my/file ``` `ADMISSION_CONTROL_CONFIG_FILE=../foo.yaml hack/local-up-cluster.sh`
parents 630dbede ccd4f4a4
...@@ -544,6 +544,8 @@ staging/src/k8s.io/apiserver/pkg/admission/configuration ...@@ -544,6 +544,8 @@ staging/src/k8s.io/apiserver/pkg/admission/configuration
staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization
staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle staging/src/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/testcerts
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating
......
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission" kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/quota" "k8s.io/kubernetes/pkg/quota"
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota" resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
resourcequotaapiv1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1"
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation" "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation"
) )
...@@ -48,6 +49,10 @@ func Register(plugins *admission.Plugins) { ...@@ -48,6 +49,10 @@ func Register(plugins *admission.Plugins) {
} }
return NewResourceQuota(configuration, 5, make(chan struct{})) return NewResourceQuota(configuration, 5, make(chan struct{}))
}) })
// add our config types
resourcequotaapi.AddToScheme(plugins.ConfigScheme)
resourcequotaapiv1alpha1.AddToScheme(plugins.ConfigScheme)
} }
// QuotaAdmission implements an admission controller that can enforce quota constraints // QuotaAdmission implements an admission controller that can enforce quota constraints
......
...@@ -883,6 +883,14 @@ ...@@ -883,6 +883,14 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors", "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
......
...@@ -21,6 +21,7 @@ go_test( ...@@ -21,6 +21,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library",
], ],
) )
...@@ -41,15 +42,12 @@ go_library( ...@@ -41,15 +42,12 @@ go_library(
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver/install:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
], ],
......
...@@ -29,27 +29,14 @@ import ( ...@@ -29,27 +29,14 @@ import (
"bytes" "bytes"
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver"
"k8s.io/apiserver/pkg/apis/apiserver/install"
apiserverv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1" apiserverv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
) )
var (
groupFactoryRegistry = make(announced.APIGroupFactoryRegistry)
registry = registered.NewOrDie(os.Getenv("KUBE_API_VERSIONS"))
scheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(scheme)
)
func init() {
install.Install(groupFactoryRegistry, registry, scheme)
}
func makeAbs(path, base string) (string, error) { func makeAbs(path, base string) (string, error) {
if filepath.IsAbs(path) { if filepath.IsAbs(path) {
return path, nil return path, nil
...@@ -70,7 +57,7 @@ func makeAbs(path, base string) (string, error) { ...@@ -70,7 +57,7 @@ func makeAbs(path, base string) (string, error) {
// set of pluginNames whose config location references the specified configFilePath. // set of pluginNames whose config location references the specified configFilePath.
// It does this to preserve backward compatibility when admission control files were opaque. // It does this to preserve backward compatibility when admission control files were opaque.
// It returns an error if the file did not exist. // It returns an error if the file did not exist.
func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (ConfigProvider, error) { func ReadAdmissionConfiguration(pluginNames []string, configFilePath string, configScheme *runtime.Scheme) (ConfigProvider, error) {
if configFilePath == "" { if configFilePath == "" {
return configProvider{config: &apiserver.AdmissionConfiguration{}}, nil return configProvider{config: &apiserver.AdmissionConfiguration{}}, nil
} }
...@@ -79,6 +66,7 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co ...@@ -79,6 +66,7 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to read admission control configuration from %q [%v]", configFilePath, err) return nil, fmt.Errorf("unable to read admission control configuration from %q [%v]", configFilePath, err)
} }
codecs := serializer.NewCodecFactory(configScheme)
decoder := codecs.UniversalDecoder() decoder := codecs.UniversalDecoder()
decodedObj, err := runtime.Decode(decoder, data) decodedObj, err := runtime.Decode(decoder, data)
// we were able to decode the file successfully // we were able to decode the file successfully
...@@ -99,7 +87,10 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co ...@@ -99,7 +87,10 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co
} }
decodedConfig.Plugins[i].Path = absPath decodedConfig.Plugins[i].Path = absPath
} }
return configProvider{config: decodedConfig}, nil return configProvider{
config: decodedConfig,
scheme: configScheme,
}, nil
} }
// we got an error where the decode wasn't related to a missing type // we got an error where the decode wasn't related to a missing type
if !(runtime.IsMissingVersion(err) || runtime.IsMissingKind(err) || runtime.IsNotRegisteredError(err)) { if !(runtime.IsMissingVersion(err) || runtime.IsMissingKind(err) || runtime.IsNotRegisteredError(err)) {
...@@ -119,25 +110,29 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co ...@@ -119,25 +110,29 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co
Path: configFilePath}) Path: configFilePath})
} }
} }
scheme.Default(externalConfig) configScheme.Default(externalConfig)
internalConfig := &apiserver.AdmissionConfiguration{} internalConfig := &apiserver.AdmissionConfiguration{}
if err := scheme.Convert(externalConfig, internalConfig, nil); err != nil { if err := configScheme.Convert(externalConfig, internalConfig, nil); err != nil {
return nil, err return nil, err
} }
return configProvider{config: internalConfig}, nil return configProvider{
config: internalConfig,
scheme: configScheme,
}, nil
} }
type configProvider struct { type configProvider struct {
config *apiserver.AdmissionConfiguration config *apiserver.AdmissionConfiguration
scheme *runtime.Scheme
} }
// GetAdmissionPluginConfigurationFor returns a reader that holds the admission plugin configuration. // GetAdmissionPluginConfigurationFor returns a reader that holds the admission plugin configuration.
func GetAdmissionPluginConfigurationFor(pluginCfg apiserver.AdmissionPluginConfiguration) (io.Reader, error) { func GetAdmissionPluginConfigurationFor(pluginCfg apiserver.AdmissionPluginConfiguration, scheme *runtime.Scheme) (io.Reader, error) {
// if there is nothing nested in the object, we return the named location // if there is nothing nested in the object, we return the named location
obj := pluginCfg.Configuration obj := pluginCfg.Configuration
if obj != nil { if obj != nil {
// serialize the configuration and build a reader for it // serialize the configuration and build a reader for it
content, err := writeYAML(obj) content, err := writeYAML(obj, scheme)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -168,7 +163,7 @@ func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) { ...@@ -168,7 +163,7 @@ func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) {
if pluginName != pluginCfg.Name { if pluginName != pluginCfg.Name {
continue continue
} }
pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg) pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg, p.scheme)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -179,8 +174,17 @@ func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) { ...@@ -179,8 +174,17 @@ func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) {
} }
// writeYAML writes the specified object to a byte array as yaml. // writeYAML writes the specified object to a byte array as yaml.
func writeYAML(obj runtime.Object) ([]byte, error) { func writeYAML(obj runtime.Object, scheme *runtime.Scheme) ([]byte, error) {
json, err := runtime.Encode(codecs.LegacyCodec(), obj) gvks, _, err := scheme.ObjectKinds(obj)
if err != nil {
return nil, err
}
gvs := []schema.GroupVersion{}
for _, gvk := range gvks {
gvs = append(gvs, gvk.GroupVersion())
}
codecs := serializer.NewCodecFactory(scheme)
json, err := runtime.Encode(codecs.LegacyCodec(gvs...), obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -22,7 +22,10 @@ import ( ...@@ -22,7 +22,10 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/apis/apiserver" "k8s.io/apiserver/pkg/apis/apiserver"
apiserverapi "k8s.io/apiserver/pkg/apis/apiserver"
apiserverapiv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
) )
func TestReadAdmissionConfiguration(t *testing.T) { func TestReadAdmissionConfiguration(t *testing.T) {
...@@ -132,11 +135,16 @@ func TestReadAdmissionConfiguration(t *testing.T) { ...@@ -132,11 +135,16 @@ func TestReadAdmissionConfiguration(t *testing.T) {
PluginNames: []string{"NamespaceLifecycle", "InitialResources"}, PluginNames: []string{"NamespaceLifecycle", "InitialResources"},
}, },
} }
scheme := runtime.NewScheme()
apiserverapi.AddToScheme(scheme)
apiserverapiv1alpha1.AddToScheme(scheme)
for testName, testCase := range testCases { for testName, testCase := range testCases {
if err = ioutil.WriteFile(configFileName, []byte(testCase.ConfigBody), 0644); err != nil { if err = ioutil.WriteFile(configFileName, []byte(testCase.ConfigBody), 0644); err != nil {
t.Fatalf("unexpected err writing temp file: %v", err) t.Fatalf("unexpected err writing temp file: %v", err)
} }
config, err := ReadAdmissionConfiguration(testCase.PluginNames, configFileName) config, err := ReadAdmissionConfiguration(testCase.PluginNames, configFileName, scheme)
if err != nil { if err != nil {
t.Fatalf("unexpected err: %v", err) t.Fatalf("unexpected err: %v", err)
} }
......
...@@ -14,8 +14,10 @@ go_library( ...@@ -14,8 +14,10 @@ go_library(
"//vendor/github.com/hashicorp/golang-lru:go_default_library", "//vendor/github.com/hashicorp/golang-lru:go_default_library",
"//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library", "//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
...@@ -48,7 +50,10 @@ filegroup( ...@@ -48,7 +50,10 @@ filegroup(
filegroup( filegroup(
name = "all-srcs", name = "all-srcs",
srcs = [":package-srcs"], srcs = [
":package-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission:all-srcs",
],
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
"types.go",
"zz_generated.deepcopy.go",
],
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install:all-srcs",
"//staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 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.
*/
// +k8s:deepcopy-gen=package
package webhookadmission
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["install.go"],
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/install",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 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 install installs the experimental API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install
import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
)
// Install registers the API group and adds types to a scheme
func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{
GroupName: webhookadmission.GroupName,
VersionPreferenceOrder: []string{v1alpha1.SchemeGroupVersion.Version},
AddInternalObjectsToScheme: webhookadmission.AddToScheme,
},
announced.VersionToSchemeFunc{
v1alpha1.SchemeGroupVersion.Version: v1alpha1.AddToScheme,
},
).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil {
panic(err)
}
}
/*
Copyright 2017 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 webhookadmission
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// GroupName is the group name use in this package
const GroupName = "apiserver.config.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
func addKnownTypes(scheme *runtime.Scheme) error {
// TODO this will get cleaned up with the scheme types are fixed
scheme.AddKnownTypes(SchemeGroupVersion,
&WebhookAdmission{},
)
return nil
}
/*
Copyright 2017 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 webhookadmission
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// WebhookAdmission provides configuration for the webhook admission controller.
type WebhookAdmission struct {
metav1.TypeMeta
// KubeConfigFile is the path to the kubeconfig file.
KubeConfigFile string
}
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
"types.go",
"zz_generated.conversion.go",
"zz_generated.deepcopy.go",
"zz_generated.defaults.go",
],
importpath = "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2017 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.
*/
// +k8s:deepcopy-gen=package
// +k8s:conversion-gen=k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission
// +k8s:defaulter-gen=TypeMeta
// Package v1alpha1 is the v1alpha1 version of the API.
// +groupName=apiserver.config.k8s.io
package v1alpha1
/*
Copyright 2017 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 v1alpha1
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name use in this package
const GroupName = "apiserver.config.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
}
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&WebhookAdmission{},
)
return nil
}
/*
Copyright 2017 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 v1alpha1
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// WebhookAdmission provides configuration for the webhook admission controller.
type WebhookAdmission struct {
metav1.TypeMeta `json:",inline"`
// KubeConfigFile is the path to the kubeconfig file.
KubeConfigFile string `json:"kubeConfigFile"`
}
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by conversion-gen. Do not edit it manually!
package v1alpha1
import (
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
webhookadmission "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission,
Convert_webhookadmission_WebhookAdmission_To_v1alpha1_WebhookAdmission,
)
}
func autoConvert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission(in *WebhookAdmission, out *webhookadmission.WebhookAdmission, s conversion.Scope) error {
out.KubeConfigFile = in.KubeConfigFile
return nil
}
// Convert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission is an autogenerated conversion function.
func Convert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission(in *WebhookAdmission, out *webhookadmission.WebhookAdmission, s conversion.Scope) error {
return autoConvert_v1alpha1_WebhookAdmission_To_webhookadmission_WebhookAdmission(in, out, s)
}
func autoConvert_webhookadmission_WebhookAdmission_To_v1alpha1_WebhookAdmission(in *webhookadmission.WebhookAdmission, out *WebhookAdmission, s conversion.Scope) error {
out.KubeConfigFile = in.KubeConfigFile
return nil
}
// Convert_webhookadmission_WebhookAdmission_To_v1alpha1_WebhookAdmission is an autogenerated conversion function.
func Convert_webhookadmission_WebhookAdmission_To_v1alpha1_WebhookAdmission(in *webhookadmission.WebhookAdmission, out *WebhookAdmission, s conversion.Scope) error {
return autoConvert_webhookadmission_WebhookAdmission_To_v1alpha1_WebhookAdmission(in, out, s)
}
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookAdmission) DeepCopyInto(out *WebhookAdmission) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookAdmission.
func (in *WebhookAdmission) DeepCopy() *WebhookAdmission {
if in == nil {
return nil
}
out := new(WebhookAdmission)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *WebhookAdmission) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by defaulter-gen. Do not edit it manually!
package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
return nil
}
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package webhookadmission
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *WebhookAdmission) DeepCopyInto(out *WebhookAdmission) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookAdmission.
func (in *WebhookAdmission) DeepCopy() *WebhookAdmission {
if in == nil {
return nil
}
out := new(WebhookAdmission)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *WebhookAdmission) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
...@@ -18,27 +18,45 @@ package config ...@@ -18,27 +18,45 @@ package config
import ( import (
"io" "io"
"io/ioutil"
"k8s.io/apimachinery/pkg/util/yaml" "fmt"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
)
var (
scheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(scheme)
) )
// AdmissionConfig holds config data that is unique to each API server. func init() {
type AdmissionConfig struct { webhookadmission.AddToScheme(scheme)
// KubeConfigFile is the path to the kubeconfig file. v1alpha1.AddToScheme(scheme)
KubeConfigFile string `json:"kubeConfigFile"`
} }
// LoadConfig extract the KubeConfigFile from configFile // LoadConfig extract the KubeConfigFile from configFile
func LoadConfig(configFile io.Reader) (string, error) { func LoadConfig(configFile io.Reader) (string, error) {
var kubeconfigFile string var kubeconfigFile string
if configFile != nil { if configFile != nil {
// TODO: move this to a versioned configuration file format // we have a config so parse it.
var config AdmissionConfig data, err := ioutil.ReadAll(configFile)
d := yaml.NewYAMLOrJSONDecoder(configFile, 4096) if err != nil {
err := d.Decode(&config) return "", err
}
decoder := codecs.UniversalDecoder()
decodedObj, err := runtime.Decode(decoder, data)
if err != nil { if err != nil {
return "", err return "", err
} }
config, ok := decodedObj.(*webhookadmission.WebhookAdmission)
if !ok {
return "", fmt.Errorf("unexpected type: %T", decodedObj)
}
kubeconfigFile = config.KubeConfigFile kubeconfigFile = config.KubeConfigFile
} }
return kubeconfigFile, nil return kubeconfigFile, nil
......
...@@ -23,6 +23,8 @@ go_library( ...@@ -23,6 +23,8 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/metrics:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/metrics:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/errors:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/namespace:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request:go_default_library",
......
...@@ -40,6 +40,8 @@ import ( ...@@ -40,6 +40,8 @@ import (
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer" genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics" admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
"k8s.io/apiserver/pkg/admission/plugin/webhook/config" "k8s.io/apiserver/pkg/admission/plugin/webhook/config"
webhookadmissionapi "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission"
webhookadmissionapiv1alpha1 "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1"
webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors" webhookerrors "k8s.io/apiserver/pkg/admission/plugin/webhook/errors"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace" "k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request" "k8s.io/apiserver/pkg/admission/plugin/webhook/request"
...@@ -64,6 +66,9 @@ func Register(plugins *admission.Plugins) { ...@@ -64,6 +66,9 @@ func Register(plugins *admission.Plugins) {
return plugin, nil return plugin, nil
}) })
// add our config types
webhookadmissionapi.AddToScheme(plugins.ConfigScheme)
webhookadmissionapiv1alpha1.AddToScheme(plugins.ConfigScheme)
} }
// WebhookSource can list dynamic webhook plugins. // WebhookSource can list dynamic webhook plugins.
......
...@@ -25,6 +25,8 @@ import ( ...@@ -25,6 +25,8 @@ import (
"sort" "sort"
"sync" "sync"
"k8s.io/apimachinery/pkg/runtime"
"github.com/golang/glog" "github.com/golang/glog"
) )
...@@ -37,6 +39,16 @@ type Factory func(config io.Reader) (Interface, error) ...@@ -37,6 +39,16 @@ type Factory func(config io.Reader) (Interface, error)
type Plugins struct { type Plugins struct {
lock sync.Mutex lock sync.Mutex
registry map[string]Factory registry map[string]Factory
// ConfigScheme is used to parse the admission plugin config file.
// It is exposed to act as a hook for extending server providing their own config.
ConfigScheme *runtime.Scheme
}
func NewPlugins() *Plugins {
return &Plugins{
ConfigScheme: runtime.NewScheme(),
}
} }
// All registered admission options. // All registered admission options.
......
...@@ -35,6 +35,8 @@ go_library( ...@@ -35,6 +35,8 @@ go_library(
"//vendor/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/mutating:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:go_default_library", "//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/validating:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit/v1beta1:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit:go_default_library", "//vendor/k8s.io/apiserver/pkg/audit:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit/policy:go_default_library", "//vendor/k8s.io/apiserver/pkg/audit/policy:go_default_library",
......
...@@ -29,6 +29,8 @@ import ( ...@@ -29,6 +29,8 @@ import (
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle" "k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating" mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating" validatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/validating"
apiserverapi "k8s.io/apiserver/pkg/apis/apiserver"
apiserverapiv1alpha1 "k8s.io/apiserver/pkg/apis/apiserver/v1alpha1"
"k8s.io/apiserver/pkg/server" "k8s.io/apiserver/pkg/server"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
...@@ -43,6 +45,7 @@ type AdmissionOptions struct { ...@@ -43,6 +45,7 @@ type AdmissionOptions struct {
DefaultOffPlugins []string DefaultOffPlugins []string
PluginNames []string PluginNames []string
ConfigFile string ConfigFile string
Plugins *admission.Plugins Plugins *admission.Plugins
} }
...@@ -56,11 +59,13 @@ type AdmissionOptions struct { ...@@ -56,11 +59,13 @@ type AdmissionOptions struct {
// Servers that do care can overwrite/append that field after creation. // Servers that do care can overwrite/append that field after creation.
func NewAdmissionOptions() *AdmissionOptions { func NewAdmissionOptions() *AdmissionOptions {
options := &AdmissionOptions{ options := &AdmissionOptions{
Plugins: &admission.Plugins{}, Plugins: admission.NewPlugins(),
PluginNames: []string{}, PluginNames: []string{},
RecommendedPluginOrder: []string{mutatingwebhook.PluginName, lifecycle.PluginName, initialization.PluginName, validatingwebhook.PluginName}, RecommendedPluginOrder: []string{mutatingwebhook.PluginName, lifecycle.PluginName, initialization.PluginName, validatingwebhook.PluginName},
DefaultOffPlugins: []string{mutatingwebhook.PluginName, initialization.PluginName, validatingwebhook.PluginName}, DefaultOffPlugins: []string{mutatingwebhook.PluginName, initialization.PluginName, validatingwebhook.PluginName},
} }
apiserverapi.AddToScheme(options.Plugins.ConfigScheme)
apiserverapiv1alpha1.AddToScheme(options.Plugins.ConfigScheme)
server.RegisterAllAdmissionPlugins(options.Plugins) server.RegisterAllAdmissionPlugins(options.Plugins)
return options return options
} }
...@@ -96,7 +101,7 @@ func (a *AdmissionOptions) ApplyTo( ...@@ -96,7 +101,7 @@ func (a *AdmissionOptions) ApplyTo(
pluginNames = a.enabledPluginNames() pluginNames = a.enabledPluginNames()
} }
pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile) pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile, a.Plugins.ConfigScheme)
if err != nil { if err != nil {
return fmt.Errorf("failed to read plugin config: %v", err) return fmt.Errorf("failed to read plugin config: %v", err)
} }
......
...@@ -851,6 +851,14 @@ ...@@ -851,6 +851,14 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors", "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
......
...@@ -847,6 +847,14 @@ ...@@ -847,6 +847,14 @@
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
{ {
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config/apis/webhookadmission/v1alpha1",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors", "ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/errors",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment