diff --git a/manifests/00-cluster-role.yaml b/manifests/00-cluster-role.yaml index c863851d29..0614370811 100644 --- a/manifests/00-cluster-role.yaml +++ b/manifests/00-cluster-role.yaml @@ -83,6 +83,14 @@ rules: verbs: - get +- apiGroups: + - config.openshift.io + resources: + - ingresses + verbs: + - list + - watch + - apiGroups: - config.openshift.io resources: diff --git a/pkg/manifests/bindata.go b/pkg/manifests/bindata.go index 0c29606dc7..d57ebb9dee 100644 --- a/pkg/manifests/bindata.go +++ b/pkg/manifests/bindata.go @@ -11,7 +11,7 @@ // assets/router/service-account.yaml (213B) // assets/router/service-cloud.yaml (631B) // assets/router/service-internal.yaml (429B) -// manifests/00-cluster-role.yaml (2.318kB) +// manifests/00-cluster-role.yaml (2.411kB) // manifests/00-custom-resource-definition-internal.yaml (5.796kB) // manifests/00-custom-resource-definition.yaml (42.103kB) // manifests/00-ingress-credentials-request.yaml (1.464kB) @@ -316,7 +316,7 @@ func assetsRouterServiceInternalYaml() (*asset, error) { return a, nil } -var _manifests00ClusterRoleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x95\xcd\x8e\x13\x31\x0c\xc7\xef\xf3\x14\xd1\xf6\x86\xd4\xa9\xb8\xa1\xde\x10\x48\x9c\x60\x25\x84\xb8\xa7\x89\xa7\x63\x9a\x89\x23\xdb\x69\x29\x4f\x8f\xe6\x6b\x97\x9d\xce\xb6\x03\x2c\x9c\x66\xe2\x38\xf6\x2f\xf6\x3f\xc9\xca\xbc\x0b\x59\x14\xd8\x30\x05\x30\x15\xb1\xd1\x1a\x0c\x25\x60\xab\xc4\x06\x55\x20\x54\x65\xb1\x32\x5f\xee\xdf\xdf\x6f\xcd\x5b\x13\x48\x0d\x55\xad\x97\x80\x91\x9a\x72\xf0\x66\x07\x86\x21\x05\xeb\xc0\x9b\xdd\xb9\x0b\x25\x06\x63\x17\x2a\xda\x06\x24\x59\x07\xd2\x45\x3f\xd5\xe8\xea\x62\xf5\x34\x8b\x75\x9a\x6d\x08\x67\x13\x01\xbc\x18\xeb\x1c\x88\x94\xc5\x01\xa3\xdf\x8e\x80\x9f\x29\x40\x61\x13\x7e\x05\x16\xa4\xb8\x35\xbc\xb3\xae\xb4\x59\x6b\x62\xfc\x61\x15\x29\x96\x87\x37\x52\x22\x6d\x8e\xaf\x8b\x06\xd4\x7a\xab\x76\x5b\x98\x8e\x60\xdb\x26\x8b\x52\x63\xa5\x6b\x8c\x7b\x06\x91\xf5\x98\xbe\xe0\x1c\x40\xb6\xc5\xda\xd8\x84\x1f\x98\x72\x92\x76\xd9\xda\xdc\xdd\x15\xc6\x30\x08\x65\x76\x30\xd8\x1c\xc5\x0a\xf7\x8d\x4d\xd2\x0d\x1f\x77\xd7\x0d\x05\xf8\x88\x0e\xac\x73\x94\xa3\xf6\x36\x88\x3e\x11\x8e\xa3\xc1\x63\x1c\x38\x86\x61\x22\x91\x1f\xfc\x8f\xd0\x3b\x1f\x81\x77\x23\xc9\xab\xbb\xe2\x92\xcf\xa6\x8e\x62\x42\xe8\x21\x05\x3a\x37\x4b\x83\x24\x0a\xe8\xce\x97\x61\x12\x79\x8f\xc2\x39\xb5\x95\xdd\x65\xbf\x87\x65\xf1\x1a\x8a\xa8\xc4\x18\xf7\xa5\x23\x06\x92\xd2\x51\x73\x19\x7e\xa8\xc3\xe0\x3d\x89\xec\x18\xac\x42\xf7\xbb\x07\xed\xbe\x39\xf9\xd6\x74\x99\xef\x59\x19\xcc\xf4\xae\x57\x52\x27\xcf\xa9\x61\x87\xd1\x63\xdc\xf7\xf6\x47\x8f\xc9\xd4\x75\xc6\x80\xd2\xff\x9c\xac\xba\x7a\x86\x75\x54\x5c\xf9\x20\xc6\x59\xce\x41\xa0\x8e\xa2\x32\x85\x00\x2c\xcf\x98\x37\xa2\x56\xf3\xa2\xb6\x0c\x8b\xcb\x85\x08\x3e\x0a\x83\x23\x1e\x34\xf9\x38\xfc\x8d\x94\xfd\x51\xb9\xb9\xd7\x8a\xad\x28\x67\xa7\x99\xe1\xc9\x46\xe1\x21\xf7\xf0\x67\x13\xb6\xb2\x19\xeb\x11\x41\x4f\xc4\x87\x09\x4b\xdb\x8c\x3f\x64\x19\xe4\x30\x96\xe8\x7a\xc3\x5f\x28\xc7\x6c\x3d\x47\xb1\xaf\xcc\x47\x64\x26\x06\x6f\x2a\xa6\xc6\x58\x11\x50\xd9\x30\x65\x05\xde\x34\xa0\x8c\x4e\x36\x43\xc8\x75\xab\xd5\xf2\x6c\x9b\x30\x73\x48\xda\x15\x37\xc8\xfa\xa8\x32\x86\x9d\xa9\xea\x75\x9c\x05\x18\xed\x31\x85\xa8\xe8\xae\x9f\x53\xa5\x03\x44\x86\x23\xc2\x69\xbe\x07\x2f\x43\x72\xfb\xc2\x90\xbc\xfb\x06\x4e\xfb\xf7\xe8\xdf\x02\x2d\xee\xd0\x04\x60\x7a\xe7\xfc\x47\x90\xbf\x90\xee\x02\x0e\x01\x97\x19\xf5\x7c\x03\x65\x74\x6b\x6f\x45\xf8\xae\x8e\xa2\x28\x5b\xbc\x78\xfc\xb2\xc0\x2f\x8b\x3f\xb5\xcf\x76\x3f\x51\x93\xe8\x70\x93\x14\x3f\x03\x00\x00\xff\xff\x48\x0b\x32\x3b\x0e\x09\x00\x00") +var _manifests00ClusterRoleYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x96\xcf\x8e\xdb\x38\x0c\xc6\xef\x7e\x0a\x61\x72\x5b\x20\x0e\xf6\xb6\xc8\x6d\xb1\x0b\xf4\xd4\x0e\x50\x14\xbd\xcb\x12\x1d\xb3\x91\x45\x81\xa4\x92\xa6\x4f\x5f\xf8\xdf\x64\x26\xf1\x24\x6e\x3b\xed\x29\x16\x4d\x7d\xfc\x49\xfc\x24\x67\x65\xfe\x0b\x59\x14\xd8\x30\x05\x30\x35\xb1\xd1\x06\x0c\x25\x60\xab\xc4\x06\x55\x20\xd4\x65\xb1\x32\x9f\x1e\xff\x7f\xdc\x9a\x7f\x4d\x20\x35\x54\x77\x59\x02\x46\x1a\xca\xc1\x9b\x0a\x0c\x43\x0a\xd6\x81\x37\xd5\xa9\x97\x12\x83\xb1\x97\x8a\xb6\x05\x49\xd6\x81\xf4\xea\xc7\x06\x5d\x53\xac\x5e\x56\xb1\x4e\xb3\x0d\xe1\x64\x22\x80\x17\x63\x9d\x03\x91\xb2\xd8\x63\xf4\xdb\x09\xf0\x23\x05\x28\x6c\xc2\xcf\xc0\x82\x14\xb7\x86\x2b\xeb\x4a\x9b\xb5\x21\xc6\x6f\x56\x91\x62\xb9\xff\x47\x4a\xa4\xcd\xe1\xef\xa2\x05\xb5\xde\xaa\xdd\x16\xa6\x27\xd8\x76\xc5\xa2\x34\x58\xeb\x1a\xe3\x8e\x41\x64\x3d\x95\x2f\x38\x07\x90\x6d\xb1\x36\x36\xe1\x3b\xa6\x9c\xa4\x9b\xb6\x36\x0f\x0f\x85\x31\x0c\x42\x99\x1d\x8c\x31\x47\xb1\xc6\x5d\x6b\x93\xf4\xc3\xf3\xea\xfa\xa1\x00\x1f\xd0\x81\x75\x8e\x72\xd4\x21\x06\xd1\x27\xc2\x69\x34\x66\x4c\x03\xc7\x30\xbe\x48\xe4\xc7\xfc\x03\x0c\xc9\x07\xe0\x6a\x22\xf9\xeb\xa1\xb8\xe6\xb3\xa9\xa7\xb8\x20\xf4\x90\x02\x9d\xda\xa5\x22\x89\x02\xba\xd3\xb5\x4c\x22\xef\x51\x38\xa7\x6e\x67\xab\xec\x77\xb0\x4c\xaf\xa5\x88\x4a\x8c\x71\x57\x3a\x62\x20\x29\x1d\xb5\xd7\xf2\xe3\x3e\x8c\xd9\x17\xca\x8e\xc1\x2a\xf4\x8f\x3b\xd0\xfe\x37\x27\xdf\x85\xae\xeb\xbd\x6a\x83\x99\xde\x0d\x4e\xea\xed\x79\x19\xa8\x30\x7a\x8c\xbb\x21\x7e\xce\xb8\x78\x75\x9b\x31\xa0\x0c\x0f\x47\xab\xae\x99\x61\x9d\x1c\x57\x3e\x99\x71\x96\x73\x34\xa8\xa3\xa8\x4c\x21\x00\xcb\x2b\xe1\x8d\xa8\xd5\xbc\xa8\x2d\xe3\xe4\x72\x21\x82\x8f\xc2\xe0\x88\x47\x4f\x9e\x87\x3f\x50\x72\x38\x2a\x77\xd7\x5a\xb3\x15\xe5\xec\x34\x33\xbc\x58\x28\x3c\xd5\x1e\x9f\x6c\xc2\xce\x36\xd3\x7e\x44\xd0\x23\xf1\xfe\x82\xa5\x6b\xc6\x4f\xb3\x9c\xeb\x3e\x53\xbc\xdb\xd6\x45\xe2\xa3\xd7\xa6\xfd\xbf\xed\xa6\x37\xaa\x31\xdb\xac\xe9\x24\xad\xcc\x7b\x64\x26\x06\x6f\x6a\xa6\xd6\x58\x11\x50\xd9\x30\x65\x05\xde\xb4\xa0\x8c\x4e\x36\xa3\xe4\xba\x3b\x08\xe5\xc9\xb6\x61\xe6\x04\x76\x33\xee\x90\x0d\xaa\x32\xc9\xce\xb4\xec\x36\xce\x02\x8c\xee\x0e\x80\xa8\xe8\x6e\x5f\x02\x4a\x7b\x88\x0c\x07\x84\xe3\x7c\x0f\xde\x86\xe4\xfe\x6d\x24\xb9\xfa\x02\x4e\x87\x8f\xdd\xef\x05\x5a\xdc\xa1\x3b\xce\xff\x83\x20\xbf\x60\xdd\x05\x1c\x02\x2e\x33\xea\xe9\x0e\xca\x94\xd6\x5d\xb9\xf0\x55\x1d\x45\x51\xb6\x78\xf5\x65\xcd\x02\xcf\x26\x7f\xe8\xfe\x13\x0c\x2f\x1a\x12\x1d\xaf\xa9\xe2\x7b\x00\x00\x00\xff\xff\x37\x23\x0f\x74\x6b\x09\x00\x00") func manifests00ClusterRoleYamlBytes() ([]byte, error) { return bindataRead( @@ -331,8 +331,8 @@ func manifests00ClusterRoleYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "manifests/00-cluster-role.yaml", size: 2318, mode: os.FileMode(420), modTime: time.Unix(1, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x92, 0xe, 0x7b, 0xf0, 0x5e, 0xc8, 0xe4, 0x9d, 0x70, 0x9f, 0xfe, 0x9, 0x4c, 0xf7, 0xfb, 0xe1, 0xfa, 0x8, 0xe0, 0x29, 0x46, 0x50, 0x1a, 0x97, 0x7f, 0xbb, 0xc0, 0xfb, 0x7b, 0x49, 0x34, 0x18}} + info := bindataFileInfo{name: "manifests/00-cluster-role.yaml", size: 2411, mode: os.FileMode(420), modTime: time.Unix(1, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5e, 0x59, 0xbf, 0x86, 0x16, 0xa4, 0xe7, 0xa3, 0xa8, 0xb7, 0xfb, 0x93, 0x93, 0x19, 0x47, 0x9d, 0xe2, 0x50, 0xe, 0xe3, 0x6a, 0x20, 0x29, 0x75, 0x76, 0x36, 0x35, 0x9d, 0x58, 0x6c, 0x36, 0x4a}} return a, nil } diff --git a/pkg/operator/controller/ingress/controller.go b/pkg/operator/controller/ingress/controller.go index 26c6df2a2d..e3eb98bde4 100644 --- a/pkg/operator/controller/ingress/controller.go +++ b/pkg/operator/controller/ingress/controller.go @@ -83,9 +83,32 @@ func New(mgr manager.Manager, config Config) (controller.Controller, error) { if err := c.Watch(&source.Kind{Type: &iov1.DNSRecord{}}, &handler.EnqueueRequestForOwner{OwnerType: &operatorv1.IngressController{}}); err != nil { return nil, err } + if err := c.Watch(&source.Kind{Type: &configv1.Ingress{}}, &handler.EnqueueRequestsFromMapFunc{ToRequests: handler.ToRequestsFunc(reconciler.ingressConfigToIngressController)}); err != nil { + return nil, err + } return c, nil } +func (r *reconciler) ingressConfigToIngressController(o handler.MapObject) []reconcile.Request { + var requests []reconcile.Request + controllers := &operatorv1.IngressControllerList{} + if err := r.cache.List(context.Background(), controllers, client.InNamespace(r.Namespace)); err != nil { + log.Error(err, "failed to list ingresscontrollers for ingress", "related", o.Meta.GetSelfLink()) + return requests + } + for _, ic := range controllers.Items { + log.Info("queueing ingresscontroller", "name", ic.Name, "related", o.Meta.GetSelfLink()) + request := reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: ic.Namespace, + Name: ic.Name, + }, + } + requests = append(requests, request) + } + return requests +} + func enqueueRequestForOwningIngressController(namespace string) handler.EventHandler { return &handler.EnqueueRequestsFromMapFunc{ ToRequests: handler.ToRequestsFunc(func(a handler.MapObject) []reconcile.Request { diff --git a/pkg/operator/controller/ingress/deployment.go b/pkg/operator/controller/ingress/deployment.go index 4dbf11846e..747c4ebda9 100644 --- a/pkg/operator/controller/ingress/deployment.go +++ b/pkg/operator/controller/ingress/deployment.go @@ -8,6 +8,7 @@ import ( "net" "path/filepath" "sort" + "strconv" "strings" "github.com/davecgh/go-spew/spew" @@ -38,6 +39,9 @@ const ( RouterSyslogAddressEnvName = "ROUTER_SYSLOG_ADDRESS" RouterSyslogFormatEnvName = "ROUTER_SYSLOG_FORMAT" RouterSyslogFacilityEnvName = "ROUTER_LOG_FACILITY" + + RouterDisableHTTP2EnvName = "ROUTER_DISABLE_HTTP2" + RouterDisableHTTP2Annotation = "ingress.operator.openshift.io/unsupported-disable-http2" ) // ensureRouterDeployment ensures the router deployment exists for a given @@ -81,6 +85,18 @@ func (r *reconciler) ensureRouterDeleted(ci *operatorv1.IngressController) error return nil } +// HTTP2IsDisabledByAnnotation returns true if the map m has the key +// RouterDisableHTTP2Annotation present and it has "true" as its +// value. +func HTTP2IsDisabledByAnnotation(m map[string]string) bool { + if mval, ok := m[RouterDisableHTTP2Annotation]; ok { + if val, err := strconv.ParseBool(mval); err == nil && val { + return true + } + } + return false +} + // desiredRouterDeployment returns the desired router deployment. func desiredRouterDeployment(ci *operatorv1.IngressController, ingressControllerImage string, infraConfig *configv1.Infrastructure, ingressConfig *configv1.Ingress, apiConfig *configv1.APIServer, networkConfig *configv1.Network) (*appsv1.Deployment, error) { deployment := manifests.RouterDeployment() @@ -498,6 +514,10 @@ func desiredRouterDeployment(ci *operatorv1.IngressController, ingressController env = append(env, corev1.EnvVar{Name: WildcardRouteAdmissionPolicy, Value: "false"}) } + if HTTP2IsDisabledByAnnotation(ci.Annotations) || HTTP2IsDisabledByAnnotation(ingressConfig.Annotations) { + env = append(env, corev1.EnvVar{Name: RouterDisableHTTP2EnvName, Value: "true"}) + } + deployment.Spec.Template.Spec.Volumes = volumes deployment.Spec.Template.Spec.Containers[0].VolumeMounts = routerVolumeMounts deployment.Spec.Template.Spec.Containers[0].Env = append(deployment.Spec.Template.Spec.Containers[0].Env, env...) diff --git a/pkg/operator/controller/ingress/deployment_test.go b/pkg/operator/controller/ingress/deployment_test.go index 9a624ebd82..b70d611cd2 100644 --- a/pkg/operator/controller/ingress/deployment_test.go +++ b/pkg/operator/controller/ingress/deployment_test.go @@ -372,6 +372,7 @@ func TestDesiredRouterDeployment(t *testing.T) { checkDeploymentHasEnvVar(t, deployment, "ROUTER_SYSLOG_FORMAT", false, "") checkDeploymentHasEnvVar(t, deployment, "ROUTER_IP_V4_V6_MODE", true, "v6") + checkDeploymentHasEnvVar(t, deployment, RouterDisableHTTP2EnvName, false, "") } func TestInferTLSProfileSpecFromDeployment(t *testing.T) { diff --git a/test/e2e/http2_disable_test.go b/test/e2e/http2_disable_test.go new file mode 100644 index 0000000000..e333628188 --- /dev/null +++ b/test/e2e/http2_disable_test.go @@ -0,0 +1,239 @@ +// +build e2e + +package e2e + +import ( + "context" + "fmt" + "strconv" + "testing" + "time" + + configv1 "github.com/openshift/api/config/v1" + operatorv1 "github.com/openshift/api/operator/v1" + + "github.com/openshift/cluster-ingress-operator/pkg/operator/controller" + "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/ingress" + ingresscontroller "github.com/openshift/cluster-ingress-operator/pkg/operator/controller/ingress" + + "sigs.k8s.io/controller-runtime/pkg/client" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" +) + +// NOTE: This test will mutate the default ingresscontroller and the +// "cluster" ingress configuration. +func TestRouteHTTP2EnableAndDisable(t *testing.T) { + routerDeployTimeout := 1 * time.Minute + + if err := waitForIngressControllerCondition(kclient, 5*time.Minute, defaultName, defaultAvailableConditions...); err != nil { + t.Fatalf("failed to observe expected conditions: %v", err) + } + ic, ingressConfig, routerDeployment, err := http2RefreshTestObjects(t, kclient, 1*time.Minute) + if err != nil { + t.Fatalf("failed to get test objects: %v", err) + } + if err := checkHTTP2IsEnabled(ic, ingressConfig, routerDeployment); err != nil { + t.Fatalf("test assertions failed: %v", err) + } + + // Disable http/2 on the default ingresscontroller + if err := setHTTP2DisabledForIngressController(t, kclient, 1*time.Minute, true, ic); err != nil { + t.Fatalf("failed to update ingresscontroller: %v", err) + } + if err := waitForIngressControllerCondition(kclient, 5*time.Minute, defaultName, defaultAvailableConditions...); err != nil { + t.Fatalf("failed to observe expected conditions: %v", err) + } + if err := waitForRouterDeploymentHTTP2Disabled(kclient, routerDeployTimeout, ic, true); err != nil { + t.Fatalf("expected router deployment to have http/2 disabled: %v", err) + } + + // Revert the previous change to the default ingresscontroller + if err := setHTTP2DisabledForIngressController(t, kclient, 1*time.Minute, false, ic); err != nil { + t.Fatalf("failed to update ingresscontroller: %v", err) + } + if err := waitForIngressControllerCondition(kclient, 5*time.Minute, defaultName, defaultAvailableConditions...); err != nil { + t.Fatalf("failed to observe expected conditions: %v", err) + } + if err := waitForRouterDeploymentHTTP2Disabled(kclient, routerDeployTimeout, ic, false); err != nil { + t.Fatalf("expected router deployment to have http/2 enabled: %v", err) + } + + // + // Now assert that changing the "cluster" ingress + // configuration will also disable/enable http/2 for all + // ingress controllers. + ic, ingressConfig, routerDeployment, err = http2RefreshTestObjects(t, kclient, 1*time.Minute) + if err != nil { + t.Fatalf("failed to get test objects: %v", err) + } + if err := checkHTTP2IsEnabled(ic, ingressConfig, routerDeployment); err != nil { + t.Fatalf("test assertions failed: %v", err) + } + + // Disable http/2 on the ingress config "cluster" + if err := setHTTP2DisabledForIngressConfig(t, kclient, 1*time.Minute, true, ingressConfig); err != nil { + t.Fatalf("failed to update ingress config: %v", err) + } + if err := waitForIngressControllerCondition(kclient, 5*time.Minute, defaultName, defaultAvailableConditions...); err != nil { + t.Fatalf("failed to observe expected conditions: %v", err) + } + if err := waitForRouterDeploymentHTTP2Disabled(kclient, routerDeployTimeout, ic, true); err != nil { + t.Fatalf("expected router deployment to have http/2 disabled: %v", err) + } + + // Revert the previous change to the ingress config + ic, ingressConfig, routerDeployment, err = http2RefreshTestObjects(t, kclient, 1*time.Minute) + if err != nil { + t.Fatalf("failed to get test objects: %v", err) + } + if err := setHTTP2DisabledForIngressConfig(t, kclient, 1*time.Minute, false, ingressConfig); err != nil { + t.Fatalf("failed to update ingress config: %v", err) + } + if err := waitForIngressControllerCondition(kclient, 5*time.Minute, defaultName, defaultAvailableConditions...); err != nil { + t.Fatalf("failed to observe expected conditions: %v", err) + } + if err := waitForRouterDeploymentHTTP2Disabled(kclient, routerDeployTimeout, ic, false); err != nil { + t.Fatalf("expected router deployment to have http/2 enabled: %v", err) + } + + // Assert all our mutations are back to their initial state + ic, ingressConfig, routerDeployment, err = http2RefreshTestObjects(t, kclient, 1*time.Minute) + if err != nil { + t.Fatalf("failed to get test objects: %v", err) + } + if err := checkHTTP2IsEnabled(ic, ingressConfig, routerDeployment); err != nil { + t.Fatalf("test assertions failed: %v", err) + } +} + +func http2IsDisabledInEnv(env []corev1.EnvVar) bool { + for _, v := range env { + if v.Name == ingresscontroller.RouterDisableHTTP2EnvName { + if val, err := strconv.ParseBool(v.Value); err == nil { + return val + } + } + } + return false +} + +func http2RefreshTestObjects(t *testing.T, client client.Client, timeout time.Duration) (*operatorv1.IngressController, *configv1.Ingress, *appsv1.Deployment, error) { + ic := operatorv1.IngressController{} + if err := wait.PollImmediate(1*time.Second, timeout, func() (bool, error) { + if err := client.Get(context.TODO(), defaultName, &ic); err != nil { + t.Logf("Get %q failed: %v, retrying...", defaultName, err) + return false, nil + } + return true, nil + }); err != nil { + return nil, nil, nil, fmt.Errorf("failed to get %q: %v", defaultName, err) + } + + deployment := appsv1.Deployment{} + if err := wait.PollImmediate(1*time.Second, timeout, func() (bool, error) { + if err := client.Get(context.TODO(), controller.RouterDeploymentName(&ic), &deployment); err != nil { + t.Logf("Get %q failed: %v, retrying...", controller.RouterDeploymentName(&ic), err) + return false, nil + } + return true, nil + }); err != nil { + return nil, nil, nil, fmt.Errorf("failed to get default ingresscontroller router deployment: %v", err) + } + + ingressConfig := configv1.Ingress{} + if err := wait.PollImmediate(1*time.Second, timeout, func() (bool, error) { + name := types.NamespacedName{Name: "cluster"} + if err := client.Get(context.TODO(), name, &ingressConfig); err != nil { + t.Logf("Get %q failed: %v, retrying...", name, err) + return false, nil + } + return true, nil + }); err != nil { + return nil, nil, nil, fmt.Errorf("failed to get ingress configuration: %v", err) + } + + return &ic, &ingressConfig, &deployment, nil +} + +func checkHTTP2IsEnabled(ic *operatorv1.IngressController, ingressConfig *configv1.Ingress, d *appsv1.Deployment) error { + icName := fmt.Sprintf("%s/%s", ic.Namespace, ic.Name) + deploymentName := fmt.Sprintf("%s/%s", d.Namespace, d.Name) + ingressConfigName := fmt.Sprintf("%s/%s", ingressConfig.Namespace, ingressConfig.Name) + + if ingress.HTTP2IsDisabledByAnnotation(ic.Annotations) { + return fmt.Errorf("expected ingress controller %q to have HTTP/2 enabled by default", icName) + } + if ingress.HTTP2IsDisabledByAnnotation(ingressConfig.Annotations) { + return fmt.Errorf("expected ingress config %q to have HTTP/2 enabled by default", ingressConfigName) + } + if len(d.Spec.Template.Spec.Containers) < 1 { + return fmt.Errorf("expected deployment %q to have at least one container", deploymentName) + } + if http2IsDisabledInEnv(d.Spec.Template.Spec.Containers[0].Env) { + return fmt.Errorf("expected deployment %q to have http/2 enabled by default", deploymentName) + } + return nil +} + +func waitForRouterDeploymentHTTP2Disabled(client client.Client, timeout time.Duration, c *operatorv1.IngressController, expectedDisabledStatus bool) error { + return wait.PollImmediate(1*time.Second, timeout, func() (bool, error) { + deployment := &appsv1.Deployment{} + if err := client.Get(context.TODO(), controller.RouterDeploymentName(c), deployment); err != nil { + return false, nil + } + return http2IsDisabledInEnv(deployment.Spec.Template.Spec.Containers[0].Env) == expectedDisabledStatus, nil + }) +} + +func setHTTP2DisabledForIngressConfig(t *testing.T, client client.Client, timeout time.Duration, disableHTTP2 bool, c *configv1.Ingress) error { + name := types.NamespacedName{Namespace: c.Namespace, Name: c.Name} + + return wait.PollImmediate(1*time.Second, timeout, func() (bool, error) { + if err := client.Get(context.TODO(), name, c); err != nil { + t.Logf("Get %q failed: %v, retrying...", name, err) + return false, nil + } + if c.Annotations == nil { + c.Annotations = map[string]string{} + } + if disableHTTP2 { + c.Annotations[ingress.RouterDisableHTTP2Annotation] = "true" + } else { + delete(c.Annotations, ingress.RouterDisableHTTP2Annotation) + } + if err := client.Update(context.TODO(), c); err != nil { + t.Logf("Update %q failed: %v, retrying...", name, err) + return false, nil + } + return true, nil + }) +} + +func setHTTP2DisabledForIngressController(t *testing.T, client client.Client, timeout time.Duration, disableHTTP2 bool, c *operatorv1.IngressController) error { + name := types.NamespacedName{Namespace: c.Namespace, Name: c.Name} + + return wait.PollImmediate(1*time.Second, timeout, func() (bool, error) { + if err := client.Get(context.TODO(), name, c); err != nil { + t.Logf("Get %q failed: %v, retrying...", name, err) + return false, nil + } + if c.Annotations == nil { + c.Annotations = map[string]string{} + } + if disableHTTP2 { + c.Annotations[ingress.RouterDisableHTTP2Annotation] = "true" + } else { + delete(c.Annotations, ingress.RouterDisableHTTP2Annotation) + } + if err := client.Update(context.TODO(), c); err != nil { + t.Logf("Update %q failed: %v, retrying...", name, err) + return false, nil + } + return true, nil + }) +}