|
1 | 1 | package serving |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
4 | 5 | "testing" |
5 | 6 |
|
6 | 7 | "github.com/google/go-cmp/cmp" |
| 8 | + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
7 | 9 | "knative.dev/operator/pkg/apis/operator/base" |
8 | 10 | operatorv1beta1 "knative.dev/operator/pkg/apis/operator/v1beta1" |
| 11 | + |
| 12 | + configfake "github.com/openshift-knative/serverless-operator/pkg/client/config/injection/client/fake" |
| 13 | + routefake "github.com/openshift-knative/serverless-operator/pkg/client/route/injection/client/fake" |
| 14 | + kubefake "knative.dev/pkg/client/injection/kube/client/fake" |
9 | 15 | ) |
10 | 16 |
|
11 | 17 | func TestDefaultIngressClass(t *testing.T) { |
@@ -63,3 +69,65 @@ func TestDefaultIngressClass(t *testing.T) { |
63 | 69 | }) |
64 | 70 | } |
65 | 71 | } |
| 72 | + |
| 73 | +// TestReconcileEnsuresWebhookNetworkPolicy verifies that, with Istio ingress |
| 74 | +// enabled, Reconcile eagerly creates the "webhook" NetworkPolicy so the apiserver |
| 75 | +// can reach the validation webhook before the install stage triggers it - |
| 76 | +// without it, the Service Mesh deny-all policy deadlocks the install. |
| 77 | +func TestReconcileEnsuresWebhookNetworkPolicy(t *testing.T) { |
| 78 | + ks := &operatorv1beta1.KnativeServing{ |
| 79 | + ObjectMeta: metav1.ObjectMeta{Namespace: servingNamespace.Name}, |
| 80 | + Spec: operatorv1beta1.KnativeServingSpec{ |
| 81 | + Ingress: &operatorv1beta1.IngressConfigs{ |
| 82 | + Istio: base.IstioIngressConfiguration{Enabled: true}, |
| 83 | + }, |
| 84 | + }, |
| 85 | + } |
| 86 | + |
| 87 | + ctx, _ := routefake.With(context.Background()) |
| 88 | + ctx, _ = configfake.With(ctx, defaultIngress) |
| 89 | + ctx, kube := kubefake.With(ctx, &servingNamespace) |
| 90 | + ext := newFakeExtension(ctx, t) |
| 91 | + |
| 92 | + if err := ext.Reconcile(ctx, ks); err != nil { |
| 93 | + t.Fatalf("Reconcile() returned error: %v", err) |
| 94 | + } |
| 95 | + |
| 96 | + np, err := kube.NetworkingV1().NetworkPolicies(servingNamespace.Name).Get(context.Background(), "webhook", metav1.GetOptions{}) |
| 97 | + if err != nil { |
| 98 | + t.Fatalf("expected 'webhook' NetworkPolicy to exist after Reconcile: %v", err) |
| 99 | + } |
| 100 | + if np.Spec.PodSelector.MatchLabels["app"] != "webhook" { |
| 101 | + t.Errorf("expected podSelector app=webhook, got: %+v", np.Spec.PodSelector) |
| 102 | + } |
| 103 | + // Allow-all ingress is a single rule with no "from" peers. |
| 104 | + if len(np.Spec.Ingress) != 1 || len(np.Spec.Ingress[0].From) != 0 { |
| 105 | + t.Errorf("expected a single allow-all ingress rule, got: %+v", np.Spec.Ingress) |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +// TestReconcileSkipsWebhookNetworkPolicyWithoutIstio verifies that with Istio |
| 110 | +// ingress disabled (e.g. Kourier), Reconcile creates no istio NetworkPolicies. |
| 111 | +func TestReconcileSkipsWebhookNetworkPolicyWithoutIstio(t *testing.T) { |
| 112 | + ks := &operatorv1beta1.KnativeServing{ |
| 113 | + ObjectMeta: metav1.ObjectMeta{Namespace: servingNamespace.Name}, |
| 114 | + Spec: operatorv1beta1.KnativeServingSpec{ |
| 115 | + Ingress: &operatorv1beta1.IngressConfigs{ |
| 116 | + Kourier: base.KourierIngressConfiguration{Enabled: true}, |
| 117 | + }, |
| 118 | + }, |
| 119 | + } |
| 120 | + |
| 121 | + ctx, _ := routefake.With(context.Background()) |
| 122 | + ctx, _ = configfake.With(ctx, defaultIngress) |
| 123 | + ctx, kube := kubefake.With(ctx, &servingNamespace) |
| 124 | + ext := newFakeExtension(ctx, t) |
| 125 | + |
| 126 | + if err := ext.Reconcile(ctx, ks); err != nil { |
| 127 | + t.Fatalf("Reconcile() returned error: %v", err) |
| 128 | + } |
| 129 | + |
| 130 | + if _, err := kube.NetworkingV1().NetworkPolicies(servingNamespace.Name).Get(context.Background(), "webhook", metav1.GetOptions{}); err == nil { |
| 131 | + t.Errorf("did not expect 'webhook' NetworkPolicy to be created when Istio ingress is disabled") |
| 132 | + } |
| 133 | +} |
0 commit comments