diff --git a/conformance/tests/gateway-observed-generation-bump.go b/conformance/tests/gateway-observed-generation-bump.go new file mode 100644 index 0000000000..5dc9bf2b20 --- /dev/null +++ b/conformance/tests/gateway-observed-generation-bump.go @@ -0,0 +1,100 @@ +/* +Copyright 2022 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 tests + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/types" + + "sigs.k8s.io/gateway-api/apis/v1beta1" + "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" + "sigs.k8s.io/gateway-api/conformance/utils/suite" +) + +func init() { + ConformanceTests = append(ConformanceTests, GatewayObservedGenerationBump) +} + +var GatewayObservedGenerationBump = suite.ConformanceTest{ + ShortName: "GatewayObservedGenerationBump", + Description: "A Gateway in the gateway-conformance-infra namespace should update the observedGeneration in all of it's Status.Conditions after an update to the spec", + Manifests: []string{"tests/gateway-observed-generation-bump.yaml"}, + Test: func(t *testing.T, s *suite.ConformanceTestSuite) { + + gwNN := types.NamespacedName{Name: "observed-generation-bump", Namespace: "gateway-conformance-infra"} + + t.Run("observedGeneration should increment", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second) + defer cancel() + + namespaces := []string{"gateway-conformance-infra"} + kubernetes.NamespacesMustBeAccepted(t, s.Client, s.TimeoutConfig, namespaces) + + existing := &v1beta1.Gateway{} + err := s.Client.Get(ctx, gwNN, existing) + require.NoErrorf(t, err, "error getting Gateway: %v", err) + + // Sanity check + if kubernetes.ConditionsHaveLatestObservedGeneration(existing, existing.Status.Conditions) { + t.Fatal("Not all the condition's observedGeneration were updated") + } + + all := v1beta1.NamespacesFromAll + + // mutate the Gateway Spec + existing.Spec.Listeners = append(existing.Spec.Listeners, v1beta1.Listener{ + Name: "alternate", + Port: 80, + Protocol: v1beta1.HTTPProtocolType, + AllowedRoutes: &v1beta1.AllowedRoutes{ + Namespaces: &v1beta1.RouteNamespaces{From: &all}, + }, + }) + + err = s.Client.Update(ctx, existing) + require.NoErrorf(t, err, "error updating the Gateway: %v", err) + + // Ensure the generation and observedGeneration sync up + kubernetes.NamespacesMustBeAccepted(t, s.Client, s.TimeoutConfig, namespaces) + + updated := &v1beta1.Gateway{} + err = s.Client.Get(ctx, gwNN, updated) + require.NoErrorf(t, err, "error getting Gateway: %v", err) + + // Sanity check + if kubernetes.ConditionsHaveLatestObservedGeneration(updated, updated.Status.Conditions) { + t.Fatal("Not all the condition's observedGeneration were updated") + } + + if existing.Generation == updated.Generation { + t.Errorf("expected generation to change because of spec change - remained at %v", updated.Generation) + } + + for _, uc := range updated.Status.Conditions { + for _, ec := range existing.Status.Conditions { + if ec.Type == uc.Type && ec.ObservedGeneration == uc.ObservedGeneration { + t.Errorf("expected status condition %v observedGeneration to change - remained at %v", updated.Generation) + } + } + } + }) + }, +} diff --git a/conformance/tests/gateway-observed-generation-bump.yaml b/conformance/tests/gateway-observed-generation-bump.yaml new file mode 100644 index 0000000000..31fe593d9f --- /dev/null +++ b/conformance/tests/gateway-observed-generation-bump.yaml @@ -0,0 +1,14 @@ +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: Gateway +metadata: + name: gateway-observed-generation-bump + namespace: gateway-conformance-infra +spec: + gatewayClassName: "{GATEWAY_CLASS_NAME}" + listeners: + - name: http + port: 80 + protocol: HTTP + allowedRoutes: + namespaces: + from: All