vendor files

This commit is contained in:
Serguei Bezverkhi
2018-01-09 13:57:14 -05:00
parent 558bc6c02a
commit 7b24313bd6
16547 changed files with 4527373 additions and 0 deletions

56
vendor/k8s.io/kubernetes/test/images/webhook/BUILD generated vendored Normal file
View File

@ -0,0 +1,56 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"config.go",
"main.go",
"scheme.go",
],
importpath = "k8s.io/kubernetes/test/images/webhook",
visibility = ["//visibility:private"],
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/admission/v1beta1:go_default_library",
"//vendor/k8s.io/api/admissionregistration/v1beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//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/serializer:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
],
)
go_binary(
name = "webhook",
importpath = "k8s.io/kubernetes/test/images/webhook",
library = ":go_default_library",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["patch_test.go"],
importpath = "k8s.io/kubernetes/test/images/webhook",
library = ":go_default_library",
deps = [
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
],
)

View File

@ -0,0 +1,18 @@
# 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.
FROM alpine:latest
ADD webhook /webhook
ENTRYPOINT ["/webhook"]

20
vendor/k8s.io/kubernetes/test/images/webhook/Makefile generated vendored Normal file
View File

@ -0,0 +1,20 @@
# 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.
build:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o webhook .
docker build --no-cache -t gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.8v6 .
rm -rf webhook
push:
gcloud docker -- push gcr.io/kubernetes-e2e-test-images/k8s-sample-admission-webhook-amd64:1.8v6

51
vendor/k8s.io/kubernetes/test/images/webhook/README.md generated vendored Normal file
View File

@ -0,0 +1,51 @@
# Kubernetes External Admission Webhook Example
The example shows how to build and deploy an external webhook that only admits
pods creation and update if the container images have the "grc.io" prefix.
## Prerequisites
Please use a Kubernetes release at least as new as v1.8.0 or v1.9.0-alpha.1,
because the generated server cert/key only works with Kubernetes release that
contains this [change](https://github.com/kubernetes/kubernetes/pull/50476).
Please checkout the `pre-v1.8` tag for an example that works with older
clusters.
Please enable the admission webhook feature
([doc](https://kubernetes.io/docs/admin/extensible-admission-controllers/#enable-external-admission-webhooks)).
## Build the code
```bash
make build
```
## Deploy the code
```bash
make deploy-only
```
The Makefile assumes your cluster is created by the
[hack/local-up-cluster.sh](https://github.com/kubernetes/kubernetes/blob/master/hack/local-up-cluster.sh).
Please modify the Makefile accordingly if your cluster is created differently.
## Explanation on the CAs/Certs/Keys
The apiserver initiates a tls connection with the webhook, so the apiserver is
the tls client, and the webhook is the tls server.
The webhook proves its identity by the `serverCert` in the certs.go. The server
cert is signed by the CA in certs.go. To let the apiserver trust the `caCert`,
the webhook registers itself with the apiserver via the
`admissionregistration/v1beta1/externalAdmissionHook` API, with
`clientConfig.caBundle=caCert`.
For maximum protection, this example webhook requires and verifies the client
(i.e., the apiserver in this case) cert. The cert presented by the apiserver is
signed by a client CA, whose cert is stored in the configmap
`extension-apiserver-authentication` in the `kube-system` namespace. See the
`getAPIServerCert` function for more information. Usually you don't need to
worry about setting up this CA cert. It's taken care of when the cluster is
created. You can disable the client cert verification by setting the
`tls.Config.ClientAuth` to `tls.NoClientCert` in `config.go`.

51
vendor/k8s.io/kubernetes/test/images/webhook/config.go generated vendored Normal file
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 main
import (
"crypto/tls"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"github.com/golang/glog"
)
// Get a clientset with in-cluster config.
func getClient() *kubernetes.Clientset {
config, err := rest.InClusterConfig()
if err != nil {
glog.Fatal(err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
glog.Fatal(err)
}
return clientset
}
func configTLS(config Config, clientset *kubernetes.Clientset) *tls.Config {
sCert, err := tls.LoadX509KeyPair(config.CertFile, config.KeyFile)
if err != nil {
glog.Fatal(err)
}
return &tls.Config{
Certificates: []tls.Certificate{sCert},
// TODO: uses mutual tls after we agree on what cert the apiserver should use.
// ClientAuth: tls.RequireAndVerifyClientCert,
}
}

301
vendor/k8s.io/kubernetes/test/images/webhook/main.go generated vendored Normal file
View File

@ -0,0 +1,301 @@
/*
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 main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/golang/glog"
"k8s.io/api/admission/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
// TODO: try this library to see if it generates correct json patch
// https://github.com/mattbaird/jsonpatch
)
const (
patch1 string = `[
{ "op": "add", "path": "/data/mutation-stage-1", "value": "yes" }
]`
patch2 string = `[
{ "op": "add", "path": "/data/mutation-stage-2", "value": "yes" }
]`
)
// Config contains the server (the webhook) cert and key.
type Config struct {
CertFile string
KeyFile string
}
func (c *Config) addFlags() {
flag.StringVar(&c.CertFile, "tls-cert-file", c.CertFile, ""+
"File containing the default x509 Certificate for HTTPS. (CA cert, if any, concatenated "+
"after server cert).")
flag.StringVar(&c.KeyFile, "tls-private-key-file", c.KeyFile, ""+
"File containing the default x509 private key matching --tls-cert-file.")
}
func toAdmissionResponse(err error) *v1beta1.AdmissionResponse {
return &v1beta1.AdmissionResponse{
Result: &metav1.Status{
Message: err.Error(),
},
}
}
// only allow pods to pull images from specific registry.
func admitPods(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
glog.V(2).Info("admitting pods")
podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
if ar.Request.Resource != podResource {
err := fmt.Errorf("expect resource to be %s", podResource)
glog.Error(err)
return toAdmissionResponse(err)
}
raw := ar.Request.Object.Raw
pod := corev1.Pod{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(raw, nil, &pod); err != nil {
glog.Error(err)
return toAdmissionResponse(err)
}
reviewResponse := v1beta1.AdmissionResponse{}
reviewResponse.Allowed = true
var msg string
for k, v := range pod.Labels {
if k == "webhook-e2e-test" && v == "webhook-disallow" {
reviewResponse.Allowed = false
msg = msg + "the pod contains unwanted label; "
}
}
for _, container := range pod.Spec.Containers {
if strings.Contains(container.Name, "webhook-disallow") {
reviewResponse.Allowed = false
msg = msg + "the pod contains unwanted container name; "
}
}
if !reviewResponse.Allowed {
reviewResponse.Result = &metav1.Status{Message: strings.TrimSpace(msg)}
}
return &reviewResponse
}
// deny configmaps with specific key-value pair.
func admitConfigMaps(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
glog.V(2).Info("admitting configmaps")
configMapResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}
if ar.Request.Resource != configMapResource {
glog.Errorf("expect resource to be %s", configMapResource)
return nil
}
raw := ar.Request.Object.Raw
configmap := corev1.ConfigMap{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(raw, nil, &configmap); err != nil {
glog.Error(err)
return toAdmissionResponse(err)
}
reviewResponse := v1beta1.AdmissionResponse{}
reviewResponse.Allowed = true
for k, v := range configmap.Data {
if k == "webhook-e2e-test" && v == "webhook-disallow" {
reviewResponse.Allowed = false
reviewResponse.Result = &metav1.Status{
Reason: "the configmap contains unwanted key and value",
}
}
}
return &reviewResponse
}
func mutateConfigmaps(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
glog.V(2).Info("mutating configmaps")
configMapResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "configmaps"}
if ar.Request.Resource != configMapResource {
glog.Errorf("expect resource to be %s", configMapResource)
return nil
}
raw := ar.Request.Object.Raw
configmap := corev1.ConfigMap{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(raw, nil, &configmap); err != nil {
glog.Error(err)
return toAdmissionResponse(err)
}
reviewResponse := v1beta1.AdmissionResponse{}
reviewResponse.Allowed = true
if configmap.Data["mutation-start"] == "yes" {
reviewResponse.Patch = []byte(patch1)
}
if configmap.Data["mutation-stage-1"] == "yes" {
reviewResponse.Patch = []byte(patch2)
}
pt := v1beta1.PatchTypeJSONPatch
reviewResponse.PatchType = &pt
return &reviewResponse
}
func mutateCRD(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
glog.V(2).Info("mutating crd")
cr := struct {
metav1.ObjectMeta
Data map[string]string
}{}
raw := ar.Request.Object.Raw
err := json.Unmarshal(raw, &cr)
if err != nil {
glog.Error(err)
return toAdmissionResponse(err)
}
reviewResponse := v1beta1.AdmissionResponse{}
reviewResponse.Allowed = true
if cr.Data["mutation-start"] == "yes" {
reviewResponse.Patch = []byte(patch1)
}
if cr.Data["mutation-stage-1"] == "yes" {
reviewResponse.Patch = []byte(patch2)
}
pt := v1beta1.PatchTypeJSONPatch
reviewResponse.PatchType = &pt
return &reviewResponse
}
func admitCRD(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
glog.V(2).Info("admitting crd")
cr := struct {
metav1.ObjectMeta
Data map[string]string
}{}
raw := ar.Request.Object.Raw
err := json.Unmarshal(raw, &cr)
if err != nil {
glog.Error(err)
return toAdmissionResponse(err)
}
reviewResponse := v1beta1.AdmissionResponse{}
reviewResponse.Allowed = true
for k, v := range cr.Data {
if k == "webhook-e2e-test" && v == "webhook-disallow" {
reviewResponse.Allowed = false
reviewResponse.Result = &metav1.Status{
Reason: "the custom resource contains unwanted data",
}
}
}
return &reviewResponse
}
type admitFunc func(v1beta1.AdmissionReview) *v1beta1.AdmissionResponse
func serve(w http.ResponseWriter, r *http.Request, admit admitFunc) {
var body []byte
if r.Body != nil {
if data, err := ioutil.ReadAll(r.Body); err == nil {
body = data
}
}
// verify the content type is accurate
contentType := r.Header.Get("Content-Type")
if contentType != "application/json" {
glog.Errorf("contentType=%s, expect application/json", contentType)
return
}
var reviewResponse *v1beta1.AdmissionResponse
ar := v1beta1.AdmissionReview{}
deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(body, nil, &ar); err != nil {
glog.Error(err)
reviewResponse = toAdmissionResponse(err)
} else {
reviewResponse = admit(ar)
}
response := v1beta1.AdmissionReview{}
if reviewResponse != nil {
response.Response = reviewResponse
response.Response.UID = ar.Request.UID
}
// reset the Object and OldObject, they are not needed in a response.
ar.Request.Object = runtime.RawExtension{}
ar.Request.OldObject = runtime.RawExtension{}
resp, err := json.Marshal(response)
if err != nil {
glog.Error(err)
}
if _, err := w.Write(resp); err != nil {
glog.Error(err)
}
}
func servePods(w http.ResponseWriter, r *http.Request) {
serve(w, r, admitPods)
}
func serveConfigmaps(w http.ResponseWriter, r *http.Request) {
serve(w, r, admitConfigMaps)
}
func serveMutateConfigmaps(w http.ResponseWriter, r *http.Request) {
serve(w, r, mutateConfigmaps)
}
func serveCRD(w http.ResponseWriter, r *http.Request) {
serve(w, r, admitCRD)
}
func serveMutateCRD(w http.ResponseWriter, r *http.Request) {
serve(w, r, mutateCRD)
}
func main() {
var config Config
config.addFlags()
flag.Parse()
http.HandleFunc("/pods", servePods)
http.HandleFunc("/configmaps", serveConfigmaps)
http.HandleFunc("/mutating-configmaps", serveMutateConfigmaps)
http.HandleFunc("/crd", serveCRD)
http.HandleFunc("/mutating-crd", serveMutateCRD)
clientset := getClient()
server := &http.Server{
Addr: ":443",
TLSConfig: configTLS(config, clientset),
}
server.ListenAndServeTLS("", "")
}

View File

@ -0,0 +1,95 @@
/*
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 main
import (
"encoding/json"
"reflect"
"testing"
jsonpatch "github.com/evanphx/json-patch"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func TestJSONPatchForConfigMap(t *testing.T) {
cm := corev1.ConfigMap{
Data: map[string]string{
"mutation-start": "yes",
},
}
cmJS, err := json.Marshal(cm)
if err != nil {
t.Fatal(err)
}
patchObj, err := jsonpatch.DecodePatch([]byte(patch1))
if err != nil {
t.Fatal(err)
}
patchedJS, err := patchObj.Apply(cmJS)
patchedObj := corev1.ConfigMap{}
err = json.Unmarshal(patchedJS, &patchedObj)
if err != nil {
t.Fatal(err)
}
expected := corev1.ConfigMap{
Data: map[string]string{
"mutation-start": "yes",
"mutation-stage-1": "yes",
},
}
if !reflect.DeepEqual(patchedObj, expected) {
t.Errorf("\nexpected %#v\n, got %#v", expected, patchedObj)
}
}
func TestJSONPatchForUnstructured(t *testing.T) {
cr := &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "Something",
"apiVersion": "somegroup/v1",
"data": map[string]interface{}{
"mutation-start": "yes",
},
},
}
crJS, err := json.Marshal(cr)
if err != nil {
t.Fatal(err)
}
patchObj, err := jsonpatch.DecodePatch([]byte(patch1))
if err != nil {
t.Fatal(err)
}
patchedJS, err := patchObj.Apply(crJS)
patchedObj := unstructured.Unstructured{}
err = json.Unmarshal(patchedJS, &patchedObj)
if err != nil {
t.Fatal(err)
}
expectedData := map[string]interface{}{
"mutation-start": "yes",
"mutation-stage-1": "yes",
}
if !reflect.DeepEqual(patchedObj.Object["data"], expectedData) {
t.Errorf("\nexpected %#v\n, got %#v", expectedData, patchedObj.Object["data"])
}
}

36
vendor/k8s.io/kubernetes/test/images/webhook/scheme.go generated vendored Normal file
View File

@ -0,0 +1,36 @@
/*
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 main
import (
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
)
var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
func init() {
addToScheme(scheme)
}
func addToScheme(scheme *runtime.Scheme) {
corev1.AddToScheme(scheme)
admissionregistrationv1beta1.AddToScheme(scheme)
}