mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Add admission e2e tests for untested stable operations
This commit is contained in:
parent
f4e39afea0
commit
3121773af7
@ -74,6 +74,7 @@ go_library(
|
||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/cert:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/keyutil:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/retry:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||
"//staging/src/k8s.io/kube-aggregator/pkg/apis/apiregistration/v1:go_default_library",
|
||||
"//staging/src/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset:go_default_library",
|
||||
|
@ -22,6 +22,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
@ -33,17 +35,18 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
utilversion "k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/dynamic"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
e2edeploy "k8s.io/kubernetes/test/e2e/framework/deployment"
|
||||
e2elog "k8s.io/kubernetes/test/e2e/framework/log"
|
||||
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
||||
"k8s.io/kubernetes/test/utils/crd"
|
||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/gomega"
|
||||
@ -244,6 +247,269 @@ var _ = SIGDescribe("AdmissionWebhook", func() {
|
||||
slowWebhookCleanup()
|
||||
})
|
||||
|
||||
ginkgo.It("patching/updating a validating webhook should work", func() {
|
||||
client := f.ClientSet
|
||||
admissionClient := client.AdmissionregistrationV1()
|
||||
|
||||
ginkgo.By("Creating a validating webhook configuration")
|
||||
hook, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: f.UniqueName,
|
||||
},
|
||||
Webhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
newDenyConfigMapWebhookFixture(f, context),
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err, "Creating validating webhook configuration")
|
||||
defer func() {
|
||||
err := client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Delete(hook.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting validating webhook configuration")
|
||||
}()
|
||||
ginkgo.By("Creating a configMap that does not comply to the validation webhook rules")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedNonCompliantConfigMap(string(uuid.NewUUID()), f)
|
||||
_, err = client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err == nil {
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
return false, nil
|
||||
}
|
||||
if !strings.Contains(err.Error(), "denied") {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
ginkgo.By("Updating a validating webhook configuration's rules to not include the create operation")
|
||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
h, err := admissionClient.ValidatingWebhookConfigurations().Get(f.UniqueName, metav1.GetOptions{})
|
||||
framework.ExpectNoError(err, "Getting validating webhook configuration")
|
||||
h.Webhooks[0].Rules[0].Operations = []admissionregistrationv1.OperationType{admissionregistrationv1.Update}
|
||||
_, err = admissionClient.ValidatingWebhookConfigurations().Update(h)
|
||||
return err
|
||||
})
|
||||
framework.ExpectNoError(err, "Updating validating webhook configuration")
|
||||
|
||||
ginkgo.By("Creating a configMap that does not comply to the validation webhook rules")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedNonCompliantConfigMap(string(uuid.NewUUID()), f)
|
||||
_, err = client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "denied") {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
return true, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s to be allowed creation since webhook was updated to not validate create", f.Namespace.Name)
|
||||
|
||||
ginkgo.By("Patching a validating webhook configuration's rules to include the create operation")
|
||||
hook, err = admissionClient.ValidatingWebhookConfigurations().Patch(
|
||||
f.UniqueName,
|
||||
types.JSONPatchType,
|
||||
[]byte(`[{"op": "replace", "path": "/webhooks/0/rules/0/operations", "value": ["CREATE"]}]`))
|
||||
framework.ExpectNoError(err, "Patching validating webhook configuration")
|
||||
|
||||
ginkgo.By("Creating a configMap that does not comply to the validation webhook rules")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedNonCompliantConfigMap(string(uuid.NewUUID()), f)
|
||||
_, err = client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err == nil {
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
return false, nil
|
||||
}
|
||||
if !strings.Contains(err.Error(), "denied") {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s to be denied creation by validating webhook", f.Namespace.Name)
|
||||
})
|
||||
|
||||
ginkgo.It("patching/updating a mutating webhook should work", func() {
|
||||
client := f.ClientSet
|
||||
admissionClient := client.AdmissionregistrationV1()
|
||||
|
||||
ginkgo.By("Creating a mutating webhook configuration")
|
||||
hook, err := createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: f.UniqueName,
|
||||
},
|
||||
Webhooks: []admissionregistrationv1.MutatingWebhook{
|
||||
newMutateConfigMapWebhookFixture(f, context, 1),
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err, "Creating mutating webhook configuration")
|
||||
defer func() {
|
||||
err := client.AdmissionregistrationV1().MutatingWebhookConfigurations().Delete(hook.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting mutating webhook configuration")
|
||||
}()
|
||||
|
||||
hook, err = admissionClient.MutatingWebhookConfigurations().Get(f.UniqueName, metav1.GetOptions{})
|
||||
framework.ExpectNoError(err, "Getting mutating webhook configuration")
|
||||
ginkgo.By("Updating a mutating webhook configuration's rules to not include the create operation")
|
||||
hook.Webhooks[0].Rules[0].Operations = []admissionregistrationv1.OperationType{admissionregistrationv1.Update}
|
||||
hook, err = admissionClient.MutatingWebhookConfigurations().Update(hook)
|
||||
framework.ExpectNoError(err, "Updating mutating webhook configuration")
|
||||
|
||||
ginkgo.By("Creating a configMap that should not be mutated")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedToBeMutatedConfigMap(string(uuid.NewUUID()), f)
|
||||
created, err := client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
_, ok := created.Data["mutation-stage-1"]
|
||||
return !ok, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s this is not mutated", f.Namespace.Name)
|
||||
|
||||
ginkgo.By("Patching a mutating webhook configuration's rules to include the create operation")
|
||||
hook, err = admissionClient.MutatingWebhookConfigurations().Patch(
|
||||
f.UniqueName,
|
||||
types.JSONPatchType,
|
||||
[]byte(`[{"op": "replace", "path": "/webhooks/0/rules/0/operations", "value": ["CREATE"]}]`))
|
||||
framework.ExpectNoError(err, "Patching mutating webhook configuration")
|
||||
|
||||
ginkgo.By("Creating a configMap that should be mutated")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedToBeMutatedConfigMap(string(uuid.NewUUID()), f)
|
||||
created, err := client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
_, ok := created.Data["mutation-stage-1"]
|
||||
return ok, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s to be mutated", f.Namespace.Name)
|
||||
})
|
||||
|
||||
ginkgo.It("listing validating webhooks should work", func() {
|
||||
testListSize := 10
|
||||
testUUID := string(uuid.NewUUID())
|
||||
|
||||
for i := 0; i < testListSize; i++ {
|
||||
name := fmt.Sprintf("%s-%d", f.UniqueName, i)
|
||||
_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: map[string]string{"e2e-list-test-uuid": testUUID},
|
||||
},
|
||||
Webhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
newDenyConfigMapWebhookFixture(f, context),
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err, "Creating validating webhook configuration")
|
||||
}
|
||||
selectorListOpts := metav1.ListOptions{LabelSelector: "e2e-list-test-uuid=" + testUUID}
|
||||
|
||||
ginkgo.By("Listing all of the created validation webhooks")
|
||||
list, err := client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().List(selectorListOpts)
|
||||
framework.ExpectNoError(err, "Listing validating webhook configurations")
|
||||
framework.ExpectEqual(len(list.Items), testListSize)
|
||||
|
||||
ginkgo.By("Creating a configMap that does not comply to the validation webhook rules")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedNonCompliantConfigMap(string(uuid.NewUUID()), f)
|
||||
_, err = client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err == nil {
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
return false, nil
|
||||
}
|
||||
if !strings.Contains(err.Error(), "denied") {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s to be denied creation by validating webhook", f.Namespace.Name)
|
||||
|
||||
ginkgo.By("Deleting the collection of validation webhooks")
|
||||
err = client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().DeleteCollection(nil, selectorListOpts)
|
||||
framework.ExpectNoError(err, "Deleting collection of validating webhook configurations")
|
||||
|
||||
ginkgo.By("Creating a configMap that does not comply to the validation webhook rules")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedNonCompliantConfigMap(string(uuid.NewUUID()), f)
|
||||
_, err = client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "denied") {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
return true, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s to be allowed creation since there are no webhooks", f.Namespace.Name)
|
||||
})
|
||||
|
||||
ginkgo.It("listing mutating webhooks should work", func() {
|
||||
testListSize := 10
|
||||
testUUID := string(uuid.NewUUID())
|
||||
|
||||
for i := 0; i < testListSize; i++ {
|
||||
name := fmt.Sprintf("%s-%d", f.UniqueName, i)
|
||||
_, err := createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: map[string]string{"e2e-list-test-uuid": testUUID},
|
||||
},
|
||||
Webhooks: []admissionregistrationv1.MutatingWebhook{
|
||||
newMutateConfigMapWebhookFixture(f, context, 1),
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err, "Creating mutating webhook configuration")
|
||||
}
|
||||
selectorListOpts := metav1.ListOptions{LabelSelector: "e2e-list-test-uuid=" + testUUID}
|
||||
|
||||
ginkgo.By("Listing all of the created validation webhooks")
|
||||
list, err := client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().List(selectorListOpts)
|
||||
framework.ExpectNoError(err, "Listing mutating webhook configurations")
|
||||
framework.ExpectEqual(len(list.Items), testListSize)
|
||||
|
||||
ginkgo.By("Creating a configMap that should be mutated")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedToBeMutatedConfigMap(string(uuid.NewUUID()), f)
|
||||
created, err := client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
_, ok := created.Data["mutation-stage-1"]
|
||||
return ok, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s to be mutated", f.Namespace.Name)
|
||||
|
||||
ginkgo.By("Deleting the collection of validation webhooks")
|
||||
err = client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().DeleteCollection(nil, selectorListOpts)
|
||||
framework.ExpectNoError(err, "Deleting collection of mutating webhook configurations")
|
||||
|
||||
ginkgo.By("Creating a configMap that should not be mutated")
|
||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
cm := namedToBeMutatedConfigMap(string(uuid.NewUUID()), f)
|
||||
created, err := client.CoreV1().ConfigMaps(f.Namespace.Name).Create(cm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = client.CoreV1().ConfigMaps(f.Namespace.Name).Delete(cm.Name, nil)
|
||||
framework.ExpectNoError(err, "Deleting successfully created configMap")
|
||||
_, ok := created.Data["mutation-stage-1"]
|
||||
return !ok, nil
|
||||
})
|
||||
framework.ExpectNoError(err, "Waiting for configMap in namespace %s this is not mutated", f.Namespace.Name)
|
||||
})
|
||||
|
||||
// TODO: add more e2e tests for mutating webhooks
|
||||
// 1. mutating webhook that mutates pod
|
||||
// 2. mutating webhook that sends empty patch
|
||||
@ -413,72 +679,13 @@ func registerWebhook(f *framework.Framework, configName string, context *certCon
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
}
|
||||
|
||||
sideEffectsNone := admissionregistrationv1.SideEffectClassNone
|
||||
|
||||
_, err := createValidatingWebhookConfiguration(f, &admissionregistrationv1.ValidatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: configName,
|
||||
},
|
||||
Webhooks: []admissionregistrationv1.ValidatingWebhook{
|
||||
{
|
||||
Name: "deny-unwanted-pod-container-name-and-label.k8s.io",
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
}},
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1.ServiceReference{
|
||||
Namespace: namespace,
|
||||
Name: serviceName,
|
||||
Path: strPtr("/pods"),
|
||||
Port: pointer.Int32Ptr(servicePort),
|
||||
},
|
||||
CABundle: context.signingCert,
|
||||
},
|
||||
SideEffects: &sideEffectsNone,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
// Scope the webhook to just this namespace
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "deny-unwanted-configmap-data.k8s.io",
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create, admissionregistrationv1.Update, admissionregistrationv1.Delete},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"configmaps"},
|
||||
},
|
||||
}},
|
||||
// The webhook skips the namespace that has label "skip-webhook-admission":"yes"
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: skipNamespaceLabelKey,
|
||||
Operator: metav1.LabelSelectorOpNotIn,
|
||||
Values: []string{skipNamespaceLabelValue},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1.ServiceReference{
|
||||
Namespace: namespace,
|
||||
Name: serviceName,
|
||||
Path: strPtr("/configmaps"),
|
||||
Port: pointer.Int32Ptr(servicePort),
|
||||
},
|
||||
CABundle: context.signingCert,
|
||||
},
|
||||
SideEffects: &sideEffectsNone,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
},
|
||||
newDenyPodWebhookFixture(f, context),
|
||||
newDenyConfigMapWebhookFixture(f, context),
|
||||
// Server cannot talk to this webhook, so it always fails.
|
||||
// Because this webhook is configured fail-open, request should be admitted after the call fails.
|
||||
failOpenHook,
|
||||
@ -549,65 +756,14 @@ func registerMutatingWebhookForConfigMap(f *framework.Framework, configName stri
|
||||
ginkgo.By("Registering the mutating configmap webhook via the AdmissionRegistration API")
|
||||
|
||||
namespace := f.Namespace.Name
|
||||
sideEffectsNone := admissionregistrationv1.SideEffectClassNone
|
||||
|
||||
_, err := createMutatingWebhookConfiguration(f, &admissionregistrationv1.MutatingWebhookConfiguration{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: configName,
|
||||
},
|
||||
Webhooks: []admissionregistrationv1.MutatingWebhook{
|
||||
{
|
||||
Name: "adding-configmap-data-stage-1.k8s.io",
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"configmaps"},
|
||||
},
|
||||
}},
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1.ServiceReference{
|
||||
Namespace: namespace,
|
||||
Name: serviceName,
|
||||
Path: strPtr("/mutating-configmaps"),
|
||||
Port: pointer.Int32Ptr(servicePort),
|
||||
},
|
||||
CABundle: context.signingCert,
|
||||
},
|
||||
SideEffects: &sideEffectsNone,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
// Scope the webhook to just this namespace
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "adding-configmap-data-stage-2.k8s.io",
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"configmaps"},
|
||||
},
|
||||
}},
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1.ServiceReference{
|
||||
Namespace: namespace,
|
||||
Name: serviceName,
|
||||
Path: strPtr("/mutating-configmaps"),
|
||||
Port: pointer.Int32Ptr(servicePort),
|
||||
},
|
||||
CABundle: context.signingCert,
|
||||
},
|
||||
SideEffects: &sideEffectsNone,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
// Scope the webhook to just this namespace
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
},
|
||||
},
|
||||
newMutateConfigMapWebhookFixture(f, context, 1),
|
||||
newMutateConfigMapWebhookFixture(f, context, 2),
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err, "registering mutating webhook config %s with namespace %s", configName, namespace)
|
||||
@ -1259,9 +1415,13 @@ func toBeAttachedPod(f *framework.Framework) *v1.Pod {
|
||||
}
|
||||
|
||||
func nonCompliantConfigMap(f *framework.Framework) *v1.ConfigMap {
|
||||
return namedNonCompliantConfigMap(disallowedConfigMapName, f)
|
||||
}
|
||||
|
||||
func namedNonCompliantConfigMap(name string, f *framework.Framework) *v1.ConfigMap {
|
||||
return &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: disallowedConfigMapName,
|
||||
Name: name,
|
||||
},
|
||||
Data: map[string]string{
|
||||
"webhook-e2e-test": "webhook-disallow",
|
||||
@ -1281,9 +1441,13 @@ func nonDeletableConfigmap(f *framework.Framework) *v1.ConfigMap {
|
||||
}
|
||||
|
||||
func toBeMutatedConfigMap(f *framework.Framework) *v1.ConfigMap {
|
||||
return namedToBeMutatedConfigMap("to-be-mutated", f)
|
||||
}
|
||||
|
||||
func namedToBeMutatedConfigMap(name string, f *framework.Framework) *v1.ConfigMap {
|
||||
return &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "to-be-mutated",
|
||||
Name: name,
|
||||
},
|
||||
Data: map[string]string{
|
||||
"mutation-start": "yes",
|
||||
@ -1851,3 +2015,100 @@ func createMutatingWebhookConfiguration(f *framework.Framework, config *admissio
|
||||
}
|
||||
return f.ClientSet.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(config)
|
||||
}
|
||||
|
||||
func newDenyPodWebhookFixture(f *framework.Framework, context *certContext) admissionregistrationv1.ValidatingWebhook {
|
||||
sideEffectsNone := admissionregistrationv1.SideEffectClassNone
|
||||
return admissionregistrationv1.ValidatingWebhook{
|
||||
Name: "deny-unwanted-pod-container-name-and-label.k8s.io",
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"pods"},
|
||||
},
|
||||
}},
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1.ServiceReference{
|
||||
Namespace: f.Namespace.Name,
|
||||
Name: serviceName,
|
||||
Path: strPtr("/pods"),
|
||||
Port: pointer.Int32Ptr(servicePort),
|
||||
},
|
||||
CABundle: context.signingCert,
|
||||
},
|
||||
SideEffects: &sideEffectsNone,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
// Scope the webhook to just this namespace
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newDenyConfigMapWebhookFixture(f *framework.Framework, context *certContext) admissionregistrationv1.ValidatingWebhook {
|
||||
sideEffectsNone := admissionregistrationv1.SideEffectClassNone
|
||||
return admissionregistrationv1.ValidatingWebhook{
|
||||
Name: "deny-unwanted-configmap-data.k8s.io",
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create, admissionregistrationv1.Update, admissionregistrationv1.Delete},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"configmaps"},
|
||||
},
|
||||
}},
|
||||
// The webhook skips the namespace that has label "skip-webhook-admission":"yes"
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: skipNamespaceLabelKey,
|
||||
Operator: metav1.LabelSelectorOpNotIn,
|
||||
Values: []string{skipNamespaceLabelValue},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1.ServiceReference{
|
||||
Namespace: f.Namespace.Name,
|
||||
Name: serviceName,
|
||||
Path: strPtr("/configmaps"),
|
||||
Port: pointer.Int32Ptr(servicePort),
|
||||
},
|
||||
CABundle: context.signingCert,
|
||||
},
|
||||
SideEffects: &sideEffectsNone,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
}
|
||||
}
|
||||
|
||||
func newMutateConfigMapWebhookFixture(f *framework.Framework, context *certContext, stage int) admissionregistrationv1.MutatingWebhook {
|
||||
sideEffectsNone := admissionregistrationv1.SideEffectClassNone
|
||||
return admissionregistrationv1.MutatingWebhook{
|
||||
Name: fmt.Sprintf("adding-configmap-data-stage-%d.k8s.io", stage),
|
||||
Rules: []admissionregistrationv1.RuleWithOperations{{
|
||||
Operations: []admissionregistrationv1.OperationType{admissionregistrationv1.Create},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"configmaps"},
|
||||
},
|
||||
}},
|
||||
ClientConfig: admissionregistrationv1.WebhookClientConfig{
|
||||
Service: &admissionregistrationv1.ServiceReference{
|
||||
Namespace: f.Namespace.Name,
|
||||
Name: serviceName,
|
||||
Path: strPtr("/mutating-configmaps"),
|
||||
Port: pointer.Int32Ptr(servicePort),
|
||||
},
|
||||
CABundle: context.signingCert,
|
||||
},
|
||||
SideEffects: &sideEffectsNone,
|
||||
AdmissionReviewVersions: []string{"v1beta1"},
|
||||
// Scope the webhook to just this namespace
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{f.UniqueName: "true"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user