Skip to content

Commit d0bf5bb

Browse files
committed
Webhook support in envtest
1 parent 066ff64 commit d0bf5bb

File tree

9 files changed

+726
-4
lines changed

9 files changed

+726
-4
lines changed

pkg/cache/cache_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca
9696
Expect(cfg).NotTo(BeNil())
9797

9898
By("creating three pods")
99+
cl, err := client.New(cfg, client.Options{})
100+
Expect(err).NotTo(HaveOccurred())
101+
err = ensureNamespace(testNamespaceOne, cl)
102+
Expect(err).NotTo(HaveOccurred())
103+
err = ensureNamespace(testNamespaceTwo, cl)
104+
Expect(err).NotTo(HaveOccurred())
105+
err = ensureNamespace(testNamespaceThree, cl)
106+
Expect(err).NotTo(HaveOccurred())
99107
// Includes restart policy since these objects are indexed on this field.
100108
knownPod1 = createPod("test-pod-1", testNamespaceOne, kcorev1.RestartPolicyNever)
101109
knownPod2 = createPod("test-pod-2", testNamespaceTwo, kcorev1.RestartPolicyAlways)
@@ -111,7 +119,6 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca
111119
knownPod4.GetObjectKind().SetGroupVersionKind(podGVK)
112120

113121
By("creating the informer cache")
114-
var err error
115122
informerCache, err = createCacheFunc(cfg, cache.Options{})
116123
Expect(err).NotTo(HaveOccurred())
117124
By("running the cache and waiting for it to sync")
@@ -667,3 +674,21 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca
667674
})
668675
})
669676
}
677+
678+
// ensureNamespace installs namespace of a given name if not exists
679+
func ensureNamespace(namespace string, client client.Client) error {
680+
ns := kcorev1.Namespace{
681+
ObjectMeta: kmetav1.ObjectMeta{
682+
Name: namespace,
683+
},
684+
TypeMeta: kmetav1.TypeMeta{
685+
Kind: "Namespace",
686+
APIVersion: "v1",
687+
},
688+
}
689+
err := client.Create(context.TODO(), &ns)
690+
if errors.IsAlreadyExists(err) {
691+
return nil
692+
}
693+
return err
694+
}

pkg/envtest/envtest_suite_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121

2222
. "github.com/onsi/ginkgo"
2323
. "github.com/onsi/gomega"
24+
admissionv1beta1 "k8s.io/api/admissionregistration/v1beta1"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2426
logf "sigs.k8s.io/controller-runtime/pkg/log"
2527
"sigs.k8s.io/controller-runtime/pkg/log/zap"
2628
)
@@ -35,12 +37,62 @@ var env *Environment
3537
var _ = BeforeSuite(func(done Done) {
3638
logf.SetLogger(zap.LoggerTo(GinkgoWriter, true))
3739
env = &Environment{}
40+
// we're initializing webhook here and not in webhook.go to also test the envtest install code via WebhookOptions
41+
initializeWebhookInEnvironment()
3842
_, err := env.Start()
3943
Expect(err).NotTo(HaveOccurred())
4044

4145
close(done)
4246
}, StartTimeout)
4347

48+
func initializeWebhookInEnvironment() {
49+
namespacedScope := admissionv1beta1.NamespacedScope
50+
failedType := admissionv1beta1.Fail
51+
equivalentType := admissionv1beta1.Equivalent
52+
noSideEffects := admissionv1beta1.SideEffectClassNone
53+
webhookPath := "/failing"
54+
55+
env.WebhookInstallOptions = WebhookInstallOptions{
56+
ValidatingWebhooks: []*admissionv1beta1.ValidatingWebhookConfiguration{
57+
{
58+
ObjectMeta: metav1.ObjectMeta{
59+
Name: "deployment-validation-webhook-config",
60+
},
61+
TypeMeta: metav1.TypeMeta{
62+
Kind: "ValidatingWebhookConfiguration",
63+
APIVersion: "admissionregistration.k8s.io/v1beta1",
64+
},
65+
Webhooks: []admissionv1beta1.ValidatingWebhook{
66+
{
67+
Name: "deployment-validation.kubebuilder.io",
68+
Rules: []admissionv1beta1.RuleWithOperations{
69+
{
70+
Operations: []admissionv1beta1.OperationType{"CREATE", "UPDATE"},
71+
Rule: admissionv1beta1.Rule{
72+
APIGroups: []string{"apps"},
73+
APIVersions: []string{"v1"},
74+
Resources: []string{"deployments"},
75+
Scope: &namespacedScope,
76+
},
77+
},
78+
},
79+
FailurePolicy: &failedType,
80+
MatchPolicy: &equivalentType,
81+
SideEffects: &noSideEffects,
82+
ClientConfig: admissionv1beta1.WebhookClientConfig{
83+
Service: &admissionv1beta1.ServiceReference{
84+
Name: "deployment-validation-service",
85+
Namespace: "default",
86+
Path: &webhookPath,
87+
},
88+
},
89+
},
90+
},
91+
},
92+
},
93+
}
94+
}
95+
4496
var _ = AfterSuite(func(done Done) {
4597
Expect(env.Stop()).NotTo(HaveOccurred())
4698

pkg/envtest/envtest_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,14 +777,16 @@ var _ = Describe("Test", func() {
777777

778778
Describe("Start", func() {
779779
It("should raise an error on invalid dir when flag is enabled", func(done Done) {
780-
env = &Environment{ErrorIfCRDPathMissing: true, CRDDirectoryPaths: []string{invalidDirectory}}
780+
env := &Environment{ErrorIfCRDPathMissing: true, CRDDirectoryPaths: []string{invalidDirectory}}
781+
defer env.Stop()
781782
_, err := env.Start()
782783
Expect(err).To(HaveOccurred())
783784
close(done)
784785
}, 30)
785786

786787
It("should not raise an error on invalid dir when flag is disabled", func(done Done) {
787-
env = &Environment{ErrorIfCRDPathMissing: false, CRDDirectoryPaths: []string{invalidDirectory}}
788+
env := &Environment{ErrorIfCRDPathMissing: false, CRDDirectoryPaths: []string{invalidDirectory}}
789+
defer env.Stop()
788790
_, err := env.Start()
789791
Expect(err).NotTo(HaveOccurred())
790792
close(done)

pkg/envtest/server.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ var DefaultKubeAPIServerFlags = []string{
8282
"--insecure-port={{ if .URL }}{{ .URL.Port }}{{ end }}",
8383
"--insecure-bind-address={{ if .URL }}{{ .URL.Hostname }}{{ end }}",
8484
"--secure-port={{ if .SecurePort }}{{ .SecurePort }}{{ end }}",
85-
"--admission-control=AlwaysAdmit",
85+
"--enable-admission-plugins=ValidatingAdmissionWebhook",
86+
"--disable-admission-plugins=ServiceAccount",
8687
"--service-cluster-ip-range=10.0.0.0/24",
8788
"--allow-privileged=true",
8889
}
@@ -101,6 +102,9 @@ type Environment struct {
101102
// CRDInstallOptions are the options for installing CRDs.
102103
CRDInstallOptions CRDInstallOptions
103104

105+
// CRDInstallOptions are the options for installing webhooks.
106+
WebhookInstallOptions WebhookInstallOptions
107+
104108
// ErrorIfCRDPathMissing provides an interface for the underlying
105109
// CRDInstallOptions.ErrorIfPathMissing. It prevents silent failures
106110
// for missing CRD paths.
@@ -255,6 +259,13 @@ func (te *Environment) Start() (*rest.Config, error) {
255259
te.CRDInstallOptions.ErrorIfPathMissing = te.ErrorIfCRDPathMissing
256260
crds, err := InstallCRDs(te.Config, te.CRDInstallOptions)
257261
te.CRDs = crds
262+
if err != nil {
263+
return te.Config, err
264+
}
265+
266+
log.V(1).Info("installing webhooks")
267+
err = te.WebhookInstallOptions.Install(te.Config)
268+
258269
return te.Config, err
259270
}
260271

0 commit comments

Comments
 (0)