Skip to content

Commit 06592e1

Browse files
committed
remove all usages for admissionregistration.k8s.io/v1beta1 mutating and validating webhook configs
Signed-off-by: Joe Lanford <[email protected]>
1 parent 884806c commit 06592e1

File tree

5 files changed

+73
-130
lines changed

5 files changed

+73
-130
lines changed

pkg/envtest/envtest_suite_test.go

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ import (
2222
. "github.com/onsi/ginkgo"
2323
. "github.com/onsi/gomega"
2424
admissionv1 "k8s.io/api/admissionregistration/v1"
25-
admissionv1beta1 "k8s.io/api/admissionregistration/v1beta1"
2625
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27-
"sigs.k8s.io/controller-runtime/pkg/client"
26+
2827
"sigs.k8s.io/controller-runtime/pkg/envtest/printer"
2928
logf "sigs.k8s.io/controller-runtime/pkg/log"
3029
"sigs.k8s.io/controller-runtime/pkg/log/zap"
@@ -48,60 +47,57 @@ var _ = BeforeSuite(func() {
4847
}, StartTimeout)
4948

5049
func initializeWebhookInEnvironment() {
51-
namespacedScopeV1Beta1 := admissionv1beta1.NamespacedScope
5250
namespacedScopeV1 := admissionv1.NamespacedScope
53-
failedTypeV1Beta1 := admissionv1beta1.Fail
5451
failedTypeV1 := admissionv1.Fail
55-
equivalentTypeV1Beta1 := admissionv1beta1.Equivalent
5652
equivalentTypeV1 := admissionv1.Equivalent
57-
noSideEffectsV1Beta1 := admissionv1beta1.SideEffectClassNone
5853
noSideEffectsV1 := admissionv1.SideEffectClassNone
5954
webhookPathV1 := "/failing"
6055

6156
env.WebhookInstallOptions = WebhookInstallOptions{
62-
ValidatingWebhooks: []client.Object{
63-
&admissionv1beta1.ValidatingWebhookConfiguration{
57+
ValidatingWebhooks: []admissionv1.ValidatingWebhookConfiguration{
58+
{
6459
ObjectMeta: metav1.ObjectMeta{
6560
Name: "deployment-validation-webhook-config",
6661
},
6762
TypeMeta: metav1.TypeMeta{
6863
Kind: "ValidatingWebhookConfiguration",
69-
APIVersion: "admissionregistration.k8s.io/v1beta1",
64+
APIVersion: "admissionregistration.k8s.io/v1",
7065
},
71-
Webhooks: []admissionv1beta1.ValidatingWebhook{
66+
Webhooks: []admissionv1.ValidatingWebhook{
7267
{
7368
Name: "deployment-validation.kubebuilder.io",
74-
Rules: []admissionv1beta1.RuleWithOperations{
69+
Rules: []admissionv1.RuleWithOperations{
7570
{
76-
Operations: []admissionv1beta1.OperationType{"CREATE", "UPDATE"},
77-
Rule: admissionv1beta1.Rule{
71+
Operations: []admissionv1.OperationType{"CREATE", "UPDATE"},
72+
Rule: admissionv1.Rule{
7873
APIGroups: []string{"apps"},
7974
APIVersions: []string{"v1"},
8075
Resources: []string{"deployments"},
81-
Scope: &namespacedScopeV1Beta1,
76+
Scope: &namespacedScopeV1,
8277
},
8378
},
8479
},
85-
FailurePolicy: &failedTypeV1Beta1,
86-
MatchPolicy: &equivalentTypeV1Beta1,
87-
SideEffects: &noSideEffectsV1Beta1,
88-
ClientConfig: admissionv1beta1.WebhookClientConfig{
89-
Service: &admissionv1beta1.ServiceReference{
80+
FailurePolicy: &failedTypeV1,
81+
MatchPolicy: &equivalentTypeV1,
82+
SideEffects: &noSideEffectsV1,
83+
ClientConfig: admissionv1.WebhookClientConfig{
84+
Service: &admissionv1.ServiceReference{
9085
Name: "deployment-validation-service",
9186
Namespace: "default",
9287
Path: &webhookPathV1,
9388
},
9489
},
90+
AdmissionReviewVersions: []string{"v1"},
9591
},
9692
},
9793
},
98-
&admissionv1.ValidatingWebhookConfiguration{
94+
{
9995
ObjectMeta: metav1.ObjectMeta{
10096
Name: "deployment-validation-webhook-config",
10197
},
10298
TypeMeta: metav1.TypeMeta{
10399
Kind: "ValidatingWebhookConfiguration",
104-
APIVersion: "admissionregistration.k8s.io/v1beta1",
100+
APIVersion: "admissionregistration.k8s.io/v1",
105101
},
106102
Webhooks: []admissionv1.ValidatingWebhook{
107103
{
@@ -127,6 +123,7 @@ func initializeWebhookInEnvironment() {
127123
Path: &webhookPathV1,
128124
},
129125
},
126+
AdmissionReviewVersions: []string{"v1"},
130127
},
131128
},
132129
},

pkg/envtest/testdata/webhooks/manifests.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
apiVersion: admissionregistration.k8s.io/v1beta1
2+
apiVersion: admissionregistration.k8s.io/v1
33
kind: MutatingWebhookConfiguration
44
metadata:
55
creationTimestamp: null
@@ -10,7 +10,7 @@ webhooks:
1010
service:
1111
name: webhook-service
1212
namespace: system
13-
path: /mutate-v1beta1
13+
path: /mutate-v1
1414
failurePolicy: Fail
1515
name: mpods.kb.io
1616
rules:
@@ -49,7 +49,7 @@ webhooks:
4949
resources:
5050
- pods
5151
---
52-
apiVersion: admissionregistration.k8s.io/v1beta1
52+
apiVersion: admissionregistration.k8s.io/v1
5353
kind: ValidatingWebhookConfiguration
5454
metadata:
5555
creationTimestamp: null
@@ -60,7 +60,7 @@ webhooks:
6060
service:
6161
name: webhook-service
6262
namespace: system
63-
path: /validate-v1beta1
63+
path: /validate-v1
6464
failurePolicy: Fail
6565
name: vpods.kb.io
6666
rules:

pkg/envtest/webhook.go

Lines changed: 46 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,26 @@ package envtest
1515

1616
import (
1717
"context"
18-
"encoding/base64"
1918
"fmt"
2019
"io/ioutil"
2120
"net"
2221
"os"
2322
"path/filepath"
2423
"time"
2524

25+
admissionv1 "k8s.io/api/admissionregistration/v1"
2626
apierrors "k8s.io/apimachinery/pkg/api/errors"
2727
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2828
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29-
"k8s.io/apimachinery/pkg/runtime"
3029
"k8s.io/apimachinery/pkg/runtime/schema"
3130
"k8s.io/apimachinery/pkg/util/sets"
3231
"k8s.io/apimachinery/pkg/util/wait"
3332
"k8s.io/client-go/rest"
33+
"sigs.k8s.io/yaml"
34+
3435
"sigs.k8s.io/controller-runtime/pkg/client"
3536
"sigs.k8s.io/controller-runtime/pkg/internal/testing/addr"
3637
"sigs.k8s.io/controller-runtime/pkg/internal/testing/certs"
37-
"sigs.k8s.io/yaml"
3838
)
3939

4040
// WebhookInstallOptions are the options for installing mutating or validating webhooks.
@@ -43,10 +43,10 @@ type WebhookInstallOptions struct {
4343
Paths []string
4444

4545
// MutatingWebhooks is a list of MutatingWebhookConfigurations to install
46-
MutatingWebhooks []client.Object
46+
MutatingWebhooks []admissionv1.MutatingWebhookConfiguration
4747

4848
// ValidatingWebhooks is a list of ValidatingWebhookConfigurations to install
49-
ValidatingWebhooks []client.Object
49+
ValidatingWebhooks []admissionv1.ValidatingWebhookConfiguration
5050

5151
// IgnoreErrorIfPathMissing will ignore an error if a DirectoryPath does not exist when set to true
5252
IgnoreErrorIfPathMissing bool
@@ -88,57 +88,27 @@ func (o *WebhookInstallOptions) ModifyWebhookDefinitions() error {
8888
return err
8989
}
9090

91-
for i, unstructuredHook := range runtimeListToUnstructured(o.MutatingWebhooks) {
92-
webhooks, found, err := unstructured.NestedSlice(unstructuredHook.Object, "webhooks")
93-
if !found || err != nil {
94-
return fmt.Errorf("unexpected object, %v", err)
95-
}
96-
for j := range webhooks {
97-
webhook, err := modifyWebhook(webhooks[j].(map[string]interface{}), caData, hostPort)
98-
if err != nil {
99-
return err
100-
}
101-
webhooks[j] = webhook
102-
unstructuredHook.Object["webhooks"] = webhooks
103-
o.MutatingWebhooks[i] = unstructuredHook
91+
for i := range o.MutatingWebhooks {
92+
for j := range o.MutatingWebhooks[i].Webhooks {
93+
updateClientConfig(&o.MutatingWebhooks[i].Webhooks[j].ClientConfig, hostPort, caData)
10494
}
10595
}
10696

107-
for i, unstructuredHook := range runtimeListToUnstructured(o.ValidatingWebhooks) {
108-
webhooks, found, err := unstructured.NestedSlice(unstructuredHook.Object, "webhooks")
109-
if !found || err != nil {
110-
return fmt.Errorf("unexpected object, %v", err)
111-
}
112-
for j := range webhooks {
113-
webhook, err := modifyWebhook(webhooks[j].(map[string]interface{}), caData, hostPort)
114-
if err != nil {
115-
return err
116-
}
117-
webhooks[j] = webhook
118-
unstructuredHook.Object["webhooks"] = webhooks
119-
o.ValidatingWebhooks[i] = unstructuredHook
97+
for i := range o.ValidatingWebhooks {
98+
for j := range o.ValidatingWebhooks[i].Webhooks {
99+
updateClientConfig(&o.ValidatingWebhooks[i].Webhooks[j].ClientConfig, hostPort, caData)
120100
}
121101
}
122102
return nil
123103
}
124104

125-
func modifyWebhook(webhook map[string]interface{}, caData []byte, hostPort string) (map[string]interface{}, error) {
126-
clientConfig, found, err := unstructured.NestedMap(webhook, "clientConfig")
127-
if !found || err != nil {
128-
return nil, fmt.Errorf("cannot find clientconfig: %v", err)
129-
}
130-
clientConfig["caBundle"] = base64.StdEncoding.EncodeToString(caData)
131-
servicePath, found, err := unstructured.NestedString(clientConfig, "service", "path")
132-
if found && err == nil {
133-
// we cannot use service in integration tests since we're running controller outside cluster
134-
// the intent here is that we swap out service for raw address because we don't have an actually standard kube service network.
135-
// We want to users to be able to use your standard config though
136-
url := fmt.Sprintf("https://%s/%s", hostPort, servicePath)
137-
clientConfig["url"] = url
138-
clientConfig["service"] = nil
105+
func updateClientConfig(cc *admissionv1.WebhookClientConfig, hostPort string, caData []byte) {
106+
cc.CABundle = caData
107+
if cc.Service != nil && cc.Service.Path != nil {
108+
url := fmt.Sprintf("https://%s/%s", hostPort, *cc.Service.Path)
109+
cc.URL = &url
110+
cc.Service = nil
139111
}
140-
webhook["clientConfig"] = clientConfig
141-
return webhook, nil
142112
}
143113

144114
func (o *WebhookInstallOptions) generateHostPort() (string, error) {
@@ -199,12 +169,19 @@ func (o *WebhookInstallOptions) Cleanup() error {
199169

200170
// WaitForWebhooks waits for the Webhooks to be available through API server.
201171
func WaitForWebhooks(config *rest.Config,
202-
mutatingWebhooks []client.Object,
203-
validatingWebhooks []client.Object,
172+
mutatingWebhooks []admissionv1.MutatingWebhookConfiguration,
173+
validatingWebhooks []admissionv1.ValidatingWebhookConfiguration,
204174
options WebhookInstallOptions) error {
205175
waitingFor := map[schema.GroupVersionKind]*sets.String{}
206176

207-
for _, hook := range runtimeListToUnstructured(append(validatingWebhooks, mutatingWebhooks...)) {
177+
for _, hook := range mutatingWebhooks {
178+
if _, ok := waitingFor[hook.GroupVersionKind()]; !ok {
179+
waitingFor[hook.GroupVersionKind()] = &sets.String{}
180+
}
181+
waitingFor[hook.GroupVersionKind()].Insert(hook.GetName())
182+
}
183+
184+
for _, hook := range validatingWebhooks {
208185
if _, ok := waitingFor[hook.GroupVersionKind()]; !ok {
209186
waitingFor[hook.GroupVersionKind()] = &sets.String{}
210187
}
@@ -297,31 +274,33 @@ func (o *WebhookInstallOptions) setupCA() error {
297274
return err
298275
}
299276

300-
func createWebhooks(config *rest.Config, mutHooks []client.Object, valHooks []client.Object) error {
277+
func createWebhooks(config *rest.Config, mutHooks []admissionv1.MutatingWebhookConfiguration, valHooks []admissionv1.ValidatingWebhookConfiguration) error {
301278
cs, err := client.New(config, client.Options{})
302279
if err != nil {
303280
return err
304281
}
305282

306283
// Create each webhook
307-
for _, hook := range runtimeListToUnstructured(mutHooks) {
284+
for _, hook := range mutHooks {
285+
hook := hook
308286
log.V(1).Info("installing mutating webhook", "webhook", hook.GetName())
309-
if err := ensureCreated(cs, hook); err != nil {
287+
if err := ensureCreated(cs, &hook); err != nil {
310288
return err
311289
}
312290
}
313-
for _, hook := range runtimeListToUnstructured(valHooks) {
291+
for _, hook := range valHooks {
292+
hook := hook
314293
log.V(1).Info("installing validating webhook", "webhook", hook.GetName())
315-
if err := ensureCreated(cs, hook); err != nil {
294+
if err := ensureCreated(cs, &hook); err != nil {
316295
return err
317296
}
318297
}
319298
return nil
320299
}
321300

322301
// ensureCreated creates or update object if already exists in the cluster.
323-
func ensureCreated(cs client.Client, obj *unstructured.Unstructured) error {
324-
existing := obj.DeepCopy()
302+
func ensureCreated(cs client.Client, obj client.Object) error {
303+
existing := obj.DeepCopyObject().(client.Object)
325304
err := cs.Get(context.Background(), client.ObjectKey{Name: obj.GetName()}, existing)
326305
switch {
327306
case apierrors.IsNotFound(err):
@@ -364,7 +343,7 @@ func parseWebhook(options *WebhookInstallOptions) error {
364343

365344
// readWebhooks reads the Webhooks from files and Unmarshals them into structs
366345
// returns slice of mutating and validating webhook configurations.
367-
func readWebhooks(path string) ([]client.Object, []client.Object, error) {
346+
func readWebhooks(path string) ([]admissionv1.MutatingWebhookConfiguration, []admissionv1.ValidatingWebhookConfiguration, error) {
368347
// Get the webhook files
369348
var files []os.FileInfo
370349
var err error
@@ -382,8 +361,8 @@ func readWebhooks(path string) ([]client.Object, []client.Object, error) {
382361
// file extensions that may contain Webhooks
383362
resourceExtensions := sets.NewString(".json", ".yaml", ".yml")
384363

385-
var mutHooks []client.Object
386-
var valHooks []client.Object
364+
var mutHooks []admissionv1.MutatingWebhookConfiguration
365+
var valHooks []admissionv1.ValidatingWebhookConfiguration
387366
for _, file := range files {
388367
// Only parse allowlisted file types
389368
if !resourceExtensions.Has(filepath.Ext(file.Name())) {
@@ -403,24 +382,23 @@ func readWebhooks(path string) ([]client.Object, []client.Object, error) {
403382
}
404383

405384
const (
406-
admissionregv1 = "admissionregistration.k8s.io/v1"
407-
admissionregv1beta1 = "admissionregistration.k8s.io/v1beta1"
385+
admissionregv1 = "admissionregistration.k8s.io/v1"
408386
)
409387
switch {
410388
case generic.Kind == "MutatingWebhookConfiguration":
411-
if generic.APIVersion != admissionregv1beta1 && generic.APIVersion != admissionregv1 {
412-
return nil, nil, fmt.Errorf("only v1beta1 and v1 are supported right now for MutatingWebhookConfiguration (name: %s)", generic.Name)
389+
if generic.APIVersion != admissionregv1 {
390+
return nil, nil, fmt.Errorf("only v1 is supported right now for MutatingWebhookConfiguration (name: %s)", generic.Name)
413391
}
414-
hook := &unstructured.Unstructured{}
392+
hook := admissionv1.MutatingWebhookConfiguration{}
415393
if err := yaml.Unmarshal(doc, &hook); err != nil {
416394
return nil, nil, err
417395
}
418396
mutHooks = append(mutHooks, hook)
419397
case generic.Kind == "ValidatingWebhookConfiguration":
420-
if generic.APIVersion != admissionregv1beta1 && generic.APIVersion != admissionregv1 {
421-
return nil, nil, fmt.Errorf("only v1beta1 and v1 are supported right now for ValidatingWebhookConfiguration (name: %s)", generic.Name)
398+
if generic.APIVersion != admissionregv1 {
399+
return nil, nil, fmt.Errorf("only v1 is supported right now for ValidatingWebhookConfiguration (name: %s)", generic.Name)
422400
}
423-
hook := &unstructured.Unstructured{}
401+
hook := admissionv1.ValidatingWebhookConfiguration{}
424402
if err := yaml.Unmarshal(doc, &hook); err != nil {
425403
return nil, nil, err
426404
}
@@ -434,17 +412,3 @@ func readWebhooks(path string) ([]client.Object, []client.Object, error) {
434412
}
435413
return mutHooks, valHooks, nil
436414
}
437-
438-
func runtimeListToUnstructured(l []client.Object) []*unstructured.Unstructured {
439-
res := []*unstructured.Unstructured{}
440-
for _, obj := range l {
441-
m, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj.DeepCopyObject())
442-
if err != nil {
443-
continue
444-
}
445-
res = append(res, &unstructured.Unstructured{
446-
Object: m,
447-
})
448-
}
449-
return res
450-
}

0 commit comments

Comments
 (0)