Skip to content

Commit 70d00ff

Browse files
committed
NE-1953: Add experimental Gateway API group to Validating Admission Policy
This commit adds "gateway.networking.x-k8s.io" to the match condition of the operator's Validating Admission Policy. This change ensures that modifications to experimental Gateway API CRDs can be made only by the ingress operator.
1 parent 924279a commit 70d00ff

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

manifests/01-validating-admission-policy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ spec:
2020
# Consider only request to Gateway API CRDs.
2121
- name: "check-only-gateway-api-crds"
2222
# When the operation is DELETE, the "object" variable is null.
23-
expression: "(request.operation == 'DELETE' ? oldObject : object).spec.group == 'gateway.networking.k8s.io'"
23+
expression: "(request.operation == 'DELETE' ? oldObject : object).spec.group == 'gateway.networking.k8s.io' || (request.operation == 'DELETE' ? oldObject : object).spec.group == 'gateway.networking.x-k8s.io'"
2424
# Validations are evaluated in the the order of their declaration.
2525
validations:
2626
# Verify that the request was sent by the ingress operator's service account.

test/e2e/gateway_api_test.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ var crdNames = []string{
4747
"referencegrants.gateway.networking.k8s.io",
4848
}
4949

50+
var xcrdNames = []string{
51+
"listenersets.gateway.networking.x-k8s.io",
52+
}
53+
5054
// Global variables for testing.
5155
// The default route name to be constructed.
5256
var defaultRoutename = ""
@@ -83,6 +87,13 @@ func TestGatewayAPI(t *testing.T) {
8387
// TODO: Uninstall OSSM after test is completed.
8488
})
8589

90+
// Create test experimental CRDs for the subsequent subtests.
91+
// Specifically, `testGatewayAPIResourcesProtection`, which tests VAP protection
92+
// for the experimental Gateway API group, needs to check the update verb.
93+
// Since an API `Get` is called before the update, the CRD must exist in the cluster,
94+
// just like standard Gateway API CRDs.
95+
ensureExperimentalCRDs(t)
96+
8697
t.Run("testGatewayAPIResources", testGatewayAPIResources)
8798
if gatewayAPIControllerEnabled {
8899
t.Run("testGatewayAPIObjects", testGatewayAPIObjects)
@@ -195,7 +206,7 @@ func testGatewayAPIResourcesProtection(t *testing.T) {
195206

196207
// Create test CRDs.
197208
var testCRDs []*apiextensionsv1.CustomResourceDefinition
198-
for _, name := range crdNames {
209+
for _, name := range append(crdNames, xcrdNames...) {
199210
testCRDs = append(testCRDs, buildGWAPICRDFromName(name))
200211
}
201212

@@ -297,6 +308,26 @@ func deleteCRDs(t *testing.T) {
297308
}
298309
}
299310

311+
// ensureExperimentalCRDs creates experimental Gateway API custom resource definitions.
312+
// This function temporarily disables the ingress operator's VAP to allow CRD creation.
313+
// The VAP is re-enabled before the function returns.
314+
func ensureExperimentalCRDs(t *testing.T) {
315+
vm := newVAPManager(t, gwapiCRDVAPName)
316+
if err, recoverFn := vm.disable(); err != nil {
317+
defer recoverFn()
318+
t.Fatalf("failed to disable vap: %v", err)
319+
}
320+
defer vm.enable()
321+
322+
for _, crdName := range xcrdNames {
323+
if _, err := createCRD(crdName); err != nil {
324+
t.Fatalf("failed to create experimental crd %q: %v", crdName, err)
325+
} else {
326+
t.Logf("created experimental crd %q", crdName)
327+
}
328+
}
329+
}
330+
300331
// ensureGatewayObjectCreation tests that gateway class, gateway, and http route objects can be created.
301332
func ensureGatewayObjectCreation(ns *corev1.Namespace) error {
302333
var domain string

test/e2e/util_gatewayapi_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,21 @@ func createGatewayClass(name, controllerName string) (*gatewayapiv1.GatewayClass
271271
return gatewayClass, nil
272272
}
273273

274+
// createCRD creates the CRD with the given name or retrieves it if already exists.
275+
func createCRD(name string) (*apiextensionsv1.CustomResourceDefinition, error) {
276+
crd := buildGWAPICRDFromName(name)
277+
if err := kclient.Create(context.Background(), crd); err != nil {
278+
if kerrors.IsAlreadyExists(err) {
279+
if err := kclient.Get(context.Background(), types.NamespacedName{Name: name}, crd); err != nil {
280+
return nil, fmt.Errorf("failed to get crd %q: %w", name, err)
281+
}
282+
return crd, nil
283+
}
284+
return nil, fmt.Errorf("failed to create crd %q: %w", name, err)
285+
}
286+
return crd, nil
287+
}
288+
274289
// buildGatewayClass initializes the GatewayClass and returns its address.
275290
func buildGatewayClass(name, controllerName string) *gatewayapiv1.GatewayClass {
276291
return &gatewayapiv1.GatewayClass{
@@ -348,6 +363,12 @@ func buildGWAPICRDFromName(name string) *apiextensionsv1.CustomResourceDefinitio
348363
case "referencegrants":
349364
kind = "ReferenceGrant"
350365
versions = []map[string]bool{{"v1beta1": true}}
366+
case "listenersets":
367+
kind = "ListenerSet"
368+
versions = []map[string]bool{{"v1alpha1": true}}
369+
case "grpcroutes":
370+
kind = "GRPCRoute"
371+
versions = []map[string]bool{{"v1": true}}
351372
}
352373

353374
crd := &apiextensionsv1.CustomResourceDefinition{

0 commit comments

Comments
 (0)