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`
pull/6/head
Kubernetes Submit Queue 2017-11-21 17:57:29 -08:00 committed by GitHub
commit 25ebf875b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 671 additions and 42 deletions

View File

@ -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/namespace/lifecycle
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/testcerts
staging/src/k8s.io/apiserver/pkg/admission/plugin/webhook/validating

View File

@ -28,6 +28,7 @@ import (
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/quota"
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"
)
@ -48,6 +49,10 @@ func Register(plugins *admission.Plugins) {
}
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

View File

@ -882,6 +882,14 @@
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config",
"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",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

View File

@ -21,6 +21,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/runtime: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/v1alpha1:go_default_library",
],
)
@ -41,15 +42,12 @@ go_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/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/schema: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/sets: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/authentication/user:go_default_library",
],

View File

@ -29,27 +29,14 @@ import (
"bytes"
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/apis/apiserver"
"k8s.io/apiserver/pkg/apis/apiserver/install"
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) {
if filepath.IsAbs(path) {
return path, nil
@ -70,7 +57,7 @@ func makeAbs(path, base string) (string, error) {
// set of pluginNames whose config location references the specified configFilePath.
// It does this to preserve backward compatibility when admission control files were opaque.
// 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 == "" {
return configProvider{config: &apiserver.AdmissionConfiguration{}}, nil
}
@ -79,6 +66,7 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co
if err != nil {
return nil, fmt.Errorf("unable to read admission control configuration from %q [%v]", configFilePath, err)
}
codecs := serializer.NewCodecFactory(configScheme)
decoder := codecs.UniversalDecoder()
decodedObj, err := runtime.Decode(decoder, data)
// we were able to decode the file successfully
@ -99,7 +87,10 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co
}
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
if !(runtime.IsMissingVersion(err) || runtime.IsMissingKind(err) || runtime.IsNotRegisteredError(err)) {
@ -119,25 +110,29 @@ func ReadAdmissionConfiguration(pluginNames []string, configFilePath string) (Co
Path: configFilePath})
}
}
scheme.Default(externalConfig)
configScheme.Default(externalConfig)
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 configProvider{config: internalConfig}, nil
return configProvider{
config: internalConfig,
scheme: configScheme,
}, nil
}
type configProvider struct {
config *apiserver.AdmissionConfiguration
scheme *runtime.Scheme
}
// 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
obj := pluginCfg.Configuration
if obj != nil {
// serialize the configuration and build a reader for it
content, err := writeYAML(obj)
content, err := writeYAML(obj, scheme)
if err != nil {
return nil, err
}
@ -168,7 +163,7 @@ func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) {
if pluginName != pluginCfg.Name {
continue
}
pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg)
pluginConfig, err := GetAdmissionPluginConfigurationFor(pluginCfg, p.scheme)
if err != nil {
return nil, err
}
@ -179,8 +174,17 @@ func (p configProvider) ConfigFor(pluginName string) (io.Reader, error) {
}
// writeYAML writes the specified object to a byte array as yaml.
func writeYAML(obj runtime.Object) ([]byte, error) {
json, err := runtime.Encode(codecs.LegacyCodec(), obj)
func writeYAML(obj runtime.Object, scheme *runtime.Scheme) ([]byte, error) {
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 {
return nil, err
}

View File

@ -22,7 +22,10 @@ import (
"reflect"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"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) {
@ -132,11 +135,16 @@ func TestReadAdmissionConfiguration(t *testing.T) {
PluginNames: []string{"NamespaceLifecycle", "InitialResources"},
},
}
scheme := runtime.NewScheme()
apiserverapi.AddToScheme(scheme)
apiserverapiv1alpha1.AddToScheme(scheme)
for testName, testCase := range testCases {
if err = ioutil.WriteFile(configFileName, []byte(testCase.ConfigBody), 0644); err != nil {
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 {
t.Fatalf("unexpected err: %v", err)
}

View File

@ -14,8 +14,10 @@ go_library(
"//vendor/github.com/hashicorp/golang-lru: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/serializer: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/client-go/rest:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
@ -48,7 +50,10 @@ filegroup(
filegroup(
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"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,36 @@
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"],
)

View File

@ -0,0 +1,19 @@
/*
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

View File

@ -0,0 +1,29 @@
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"],
)

View File

@ -0,0 +1,43 @@
/*
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)
}
}

View File

@ -0,0 +1,51 @@
/*
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
}

View File

@ -0,0 +1,29 @@
/*
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
}

View File

@ -0,0 +1,36 @@
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"],
)

View File

@ -0,0 +1,23 @@
/*
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

View File

@ -0,0 +1,50 @@
/*
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
}

View File

@ -0,0 +1,29 @@
/*
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"`
}

View File

@ -0,0 +1,60 @@
// +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)
}

View File

@ -0,0 +1,51 @@
// +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
}
}

View File

@ -0,0 +1,32 @@
// +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
}

View File

@ -0,0 +1,51 @@
// +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
}
}

View File

@ -18,27 +18,45 @@ package config
import (
"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"
)
// AdmissionConfig holds config data that is unique to each API server.
type AdmissionConfig struct {
// KubeConfigFile is the path to the kubeconfig file.
KubeConfigFile string `json:"kubeConfigFile"`
var (
scheme = runtime.NewScheme()
codecs = serializer.NewCodecFactory(scheme)
)
func init() {
webhookadmission.AddToScheme(scheme)
v1alpha1.AddToScheme(scheme)
}
// LoadConfig extract the KubeConfigFile from configFile
func LoadConfig(configFile io.Reader) (string, error) {
var kubeconfigFile string
if configFile != nil {
// TODO: move this to a versioned configuration file format
var config AdmissionConfig
d := yaml.NewYAMLOrJSONDecoder(configFile, 4096)
err := d.Decode(&config)
// we have a config so parse it.
data, err := ioutil.ReadAll(configFile)
if err != nil {
return "", err
}
decoder := codecs.UniversalDecoder()
decodedObj, err := runtime.Decode(decoder, data)
if err != nil {
return "", err
}
config, ok := decodedObj.(*webhookadmission.WebhookAdmission)
if !ok {
return "", fmt.Errorf("unexpected type: %T", decodedObj)
}
kubeconfigFile = config.KubeConfigFile
}
return kubeconfigFile, nil

View File

@ -23,6 +23,8 @@ go_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/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/namespace:go_default_library",
"//vendor/k8s.io/apiserver/pkg/admission/plugin/webhook/request:go_default_library",

View File

@ -40,6 +40,8 @@ import (
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
admissionmetrics "k8s.io/apiserver/pkg/admission/metrics"
"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"
"k8s.io/apiserver/pkg/admission/plugin/webhook/namespace"
"k8s.io/apiserver/pkg/admission/plugin/webhook/request"
@ -64,6 +66,9 @@ func Register(plugins *admission.Plugins) {
return plugin, nil
})
// add our config types
webhookadmissionapi.AddToScheme(plugins.ConfigScheme)
webhookadmissionapiv1alpha1.AddToScheme(plugins.ConfigScheme)
}
// WebhookSource can list dynamic webhook plugins.

View File

@ -25,6 +25,8 @@ import (
"sort"
"sync"
"k8s.io/apimachinery/pkg/runtime"
"github.com/golang/glog"
)
@ -37,6 +39,16 @@ type Factory func(config io.Reader) (Interface, error)
type Plugins struct {
lock sync.Mutex
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.

View File

@ -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/webhook/mutating: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/audit:go_default_library",
"//vendor/k8s.io/apiserver/pkg/audit/policy:go_default_library",

View File

@ -29,6 +29,8 @@ import (
"k8s.io/apiserver/pkg/admission/plugin/namespace/lifecycle"
mutatingwebhook "k8s.io/apiserver/pkg/admission/plugin/webhook/mutating"
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/client-go/informers"
"k8s.io/client-go/kubernetes"
@ -43,7 +45,8 @@ type AdmissionOptions struct {
DefaultOffPlugins []string
PluginNames []string
ConfigFile string
Plugins *admission.Plugins
Plugins *admission.Plugins
}
// NewAdmissionOptions creates a new instance of AdmissionOptions
@ -56,11 +59,13 @@ type AdmissionOptions struct {
// Servers that do care can overwrite/append that field after creation.
func NewAdmissionOptions() *AdmissionOptions {
options := &AdmissionOptions{
Plugins: &admission.Plugins{},
Plugins: admission.NewPlugins(),
PluginNames: []string{},
RecommendedPluginOrder: []string{mutatingwebhook.PluginName, lifecycle.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)
return options
}
@ -96,7 +101,7 @@ func (a *AdmissionOptions) ApplyTo(
pluginNames = a.enabledPluginNames()
}
pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile)
pluginsConfigProvider, err := admission.ReadAdmissionConfiguration(pluginNames, a.ConfigFile, a.Plugins.ConfigScheme)
if err != nil {
return fmt.Errorf("failed to read plugin config: %v", err)
}

View File

@ -850,6 +850,14 @@
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config",
"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",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

View File

@ -846,6 +846,14 @@
"ImportPath": "k8s.io/apiserver/pkg/admission/plugin/webhook/config",
"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",
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"