Skip to content

Commit 1f0444b

Browse files
committed
test/e2e: Add test for Istio manual deployment
This commit resolves NE-1994. https://issues.redhat.com/browse/NE-1994 * test/e2e/gateway_api_test.go (TestGatewayAPI): Run the new test, testGatewayAPIManualDeployment. Update a log message. (testGatewayAPIManualDeployment): New test. Verify that Istio is configured not to allow manual deployment.
1 parent 1b72b75 commit 1f0444b

File tree

1 file changed

+104
-1
lines changed

1 file changed

+104
-1
lines changed

test/e2e/gateway_api_test.go

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"strings"
1010
"testing"
11+
"time"
1112

1213
"github.com/openshift/api/features"
1314
operatorclient "github.com/openshift/cluster-ingress-operator/pkg/operator/client"
@@ -18,8 +19,10 @@ import (
1819
"k8s.io/apimachinery/pkg/api/errors"
1920
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2021
"k8s.io/apimachinery/pkg/types"
22+
"k8s.io/apimachinery/pkg/util/wait"
2123
"k8s.io/apiserver/pkg/storage/names"
2224
"k8s.io/client-go/rest"
25+
"k8s.io/utils/ptr"
2326

2427
"sigs.k8s.io/controller-runtime/pkg/client"
2528
"sigs.k8s.io/controller-runtime/pkg/client/config"
@@ -96,9 +99,10 @@ func TestGatewayAPI(t *testing.T) {
9699
t.Run("testGatewayAPIResources", testGatewayAPIResources)
97100
if gatewayAPIControllerEnabled {
98101
t.Run("testGatewayAPIObjects", testGatewayAPIObjects)
102+
t.Run("testGatewayAPIManualDeployment", testGatewayAPIManualDeployment)
99103
t.Run("testGatewayAPIIstioInstallation", testGatewayAPIIstioInstallation)
100104
} else {
101-
t.Log("Gateway API Controller not enabled, skipping testGatewayAPIObjects and testGatewayAPIIstioInstallation")
105+
t.Log("Gateway API Controller not enabled, skipping controller tests")
102106
}
103107
t.Run("testGatewayAPIResourcesProtection", testGatewayAPIResourcesProtection)
104108
}
@@ -191,6 +195,105 @@ func testGatewayAPIObjects(t *testing.T) {
191195
}
192196
}
193197

198+
// testGatewayAPIManualDeployment verifies that Istio's manual deployment is not
199+
// enabled. When manual deployment is enabled, then Istio allows a gateway use
200+
// to another gateway's service by specifying that gateway's service in
201+
// spec.addresses. This results in behavior similar to gateway listener
202+
// merging, which we do not want to allow at this time. Instead, we expect
203+
// Istio to provision a service for this specific gateway, even if it specifies
204+
// spec.addresses.
205+
func testGatewayAPIManualDeployment(t *testing.T) {
206+
gatewayClass, err := createGatewayClass("openshift-default", "openshift.io/gateway-controller")
207+
if err != nil {
208+
t.Fatalf("Failed to create gatewayclass: %v", err)
209+
}
210+
211+
gatewayName := types.NamespacedName{
212+
Name: "manual-deployment",
213+
Namespace: "openshift-ingress",
214+
}
215+
gateway := gatewayapiv1.Gateway{
216+
ObjectMeta: metav1.ObjectMeta{
217+
Name: gatewayName.Name,
218+
Namespace: gatewayName.Namespace,
219+
},
220+
Spec: gatewayapiv1.GatewaySpec{
221+
GatewayClassName: gatewayapiv1.ObjectName(gatewayClass.Name),
222+
Addresses: []gatewayapiv1.GatewayAddress{{
223+
Type: ptr.To(gatewayapiv1.HostnameAddressType),
224+
Value: "lb.example.com",
225+
}},
226+
Listeners: []gatewayapiv1.Listener{{
227+
Name: "http",
228+
Hostname: ptr.To(gatewayapiv1.Hostname(fmt.Sprintf("*.manual-deployment.%s", dnsConfig.Spec.BaseDomain))),
229+
Port: 80,
230+
Protocol: "HTTP",
231+
}},
232+
},
233+
}
234+
t.Logf("Creating gateway %q...", gatewayName)
235+
if err := kclient.Create(context.Background(), &gateway); err != nil {
236+
t.Fatalf("Failed to create gateway %v: %v", gatewayName, err)
237+
}
238+
t.Cleanup(func() {
239+
if err := kclient.Delete(context.Background(), &gateway); err != nil {
240+
if !errors.IsNotFound(err) {
241+
t.Errorf("Failed to delete gateway %v: %v", gatewayName, err)
242+
}
243+
}
244+
})
245+
246+
interval, timeout := 5*time.Second, 1*time.Minute
247+
t.Logf("Polling for up to %v to verify that the gateway is accepted...", timeout)
248+
if err := wait.PollUntilContextTimeout(context.Background(), interval, timeout, false, func(context context.Context) (bool, error) {
249+
if err := kclient.Get(context, gatewayName, &gateway); err != nil {
250+
t.Logf("Failed to get gateway %s: %v", gatewayName, err)
251+
252+
return false, nil
253+
}
254+
255+
for _, condition := range gateway.Status.Conditions {
256+
if condition.Type == string(gatewayapiv1.GatewayConditionAccepted) {
257+
t.Logf("Found %q status condition: %+v", gatewayapiv1.GatewayConditionAccepted, condition)
258+
259+
if condition.Status == metav1.ConditionTrue {
260+
return true, nil
261+
}
262+
}
263+
}
264+
265+
return false, nil
266+
}); err != nil {
267+
t.Errorf("Failed to observe the expected condition: %v", err)
268+
}
269+
270+
serviceName := types.NamespacedName{
271+
Name: fmt.Sprintf("%s-%s", gateway.Name, gatewayClass.Name),
272+
Namespace: gateway.Namespace,
273+
}
274+
var service corev1.Service
275+
t.Logf("Polling for up to %v to verify that service %q is created...", timeout, serviceName)
276+
if err := wait.PollUntilContextTimeout(context.Background(), interval, timeout, false, func(context context.Context) (bool, error) {
277+
if err := kclient.Get(context, serviceName, &service); err != nil {
278+
t.Logf("Failed to get service %s: %v", serviceName, err)
279+
280+
return false, nil
281+
}
282+
283+
// Just verify that the service is created. No need to verify
284+
// that a load balancer is provisioned. Indeed, provisioning
285+
// will likely fail because Istio copies the address hostname to
286+
// the service spec.loadBalancerIP field, which at least some
287+
// cloud provider implementations reject.
288+
289+
t.Logf("Found service %q", serviceName)
290+
291+
return true, nil
292+
}); err != nil {
293+
t.Errorf("Failed to observe the expected condition: %v", err)
294+
}
295+
}
296+
194297
// testGatewayAPIResourcesProtection verifies that the ingress operator's Validating Admission Policy
195298
// denies admission requests attempting to modify Gateway API CRDs on behalf of a user
196299
// who is not the ingress operator's service account.

0 commit comments

Comments
 (0)