Repository: Azure/aks-app-routing-operator
Pull request #362: Http crd flag
Author: login: meecethereese
Created: 2025-02-11T16:17:22Z | Merged: 2025-03-13T18:19:26Z

# Description

Adds the HTTPDisabled flag to the CRD for the NginxIngressController.

Fixes # (issue)
Feature # (details)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration. Is it a breaking change which will impact consuming tool(s)?

- [ ] Test A
- [ ] Test B


# Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules



Diff:
diff --git a/Makefile b/Makefile
index 91757cff..a8a03b5b 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ GOBIN=$(shell go env GOBIN)
 endif
 
 CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
-CONTROLLER_TOOLS_VERSION ?= v0.13.0
+CONTROLLER_TOOLS_VERSION ?= v0.17.2
 
 # Setting SHELL to bash allows bash commands to be executed by recipes.
 # Options are set to exit when a recipe line exits non-zero or a piped command fails.
diff --git a/api/v1alpha1/clusterexternaldns_types.go b/api/v1alpha1/clusterexternaldns_types.go
index 8401d912..4827add9 100644
--- a/api/v1alpha1/clusterexternaldns_types.go
+++ b/api/v1alpha1/clusterexternaldns_types.go
@@ -55,8 +55,6 @@ type ClusterExternalDNSSpec struct {
 	// +kubebuilder:validation:MinItems:=1
 	// +kubebuilder:validation:MaxItems:=7
 	// +kubebuilder:validation:items:UniqueItems:=true
-	// +kubebuilder:validation:items:MaxLength:=172
-	// +kubebuilder:validation:items:MinLength:=103
 	// +kubebuilder:validation:items:MaxProperties:=1
 	// +kubebuilder:validation:XValidation:rule="self.all(item, item.split('/')[2] == self[0].split('/')[2])",message="all items must have the same subscription ID"
 	// +kubebuilder:validation:XValidation:rule="self.all(item, item.split('/')[4] == self[0].split('/')[4])",message="all items must have the same resource group"
diff --git a/api/v1alpha1/externaldns_types.go b/api/v1alpha1/externaldns_types.go
index fc6774ae..02b89314 100644
--- a/api/v1alpha1/externaldns_types.go
+++ b/api/v1alpha1/externaldns_types.go
@@ -66,8 +66,6 @@ type ExternalDNSSpec struct {
 	// +kubebuilder:validation:MinItems:=1
 	// +kubebuilder:validation:MaxItems:=7
 	// +kubebuilder:validation:items:UniqueItems:=true
-	// +kubebuilder:validation:items:MaxLength:=172
-	// +kubebuilder:validation:items:MinLength:=103
 	// +kubebuilder:validation:items:MaxProperties:=1
 	// +kubebuilder:validation:XValidation:rule="self.all(item, item.split('/')[2] == self[0].split('/')[2])",message="all items must have the same subscription ID"
 	// +kubebuilder:validation:XValidation:rule="self.all(item, item.split('/')[4] == self[0].split('/')[4])",message="all items must have the same resource group"
diff --git a/api/v1alpha1/nginxingresscontroller_types.go b/api/v1alpha1/nginxingresscontroller_types.go
index f4287c1b..af125e04 100644
--- a/api/v1alpha1/nginxingresscontroller_types.go
+++ b/api/v1alpha1/nginxingresscontroller_types.go
@@ -69,6 +69,10 @@ type NginxIngressControllerSpec struct {
 	// Scaling defines configuration options for how the Ingress Controller scales
 	// +optional
 	Scaling *Scaling `json:"scaling,omitempty"`
+
+	// HTTPDisabled is a flag that disables HTTP traffic to the NginxIngressController
+	// +optional
+	HTTPDisabled bool `json:"httpDisabled,omitempty"`
 }
 
 // DefaultSSLCertificate holds a secret in the form of a secret struct with name and namespace properties or a key vault uri
diff --git a/config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml b/config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
index a3804658..bce3b51e 100644
--- a/config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
+++ b/config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.14.0
+    controller-gen.kubebuilder.io/version: v0.17.2
   name: clusterexternaldnses.approuting.kubernetes.azure.com
 spec:
   group: approuting.kubernetes.azure.com
@@ -152,16 +152,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the ExternalDNS
                 items:
-                  description: "Condition contains details for one aspect of the current
-                    state of this API Resource.\n---\nThis struct is intended for
-                    direct use as an array at the field path .status.conditions.  For
-                    example,\n\n\n\ttype FooStatus struct{\n\t    // Represents the
-                    observations of a foo's current state.\n\t    // Known .status.conditions.type
-                    are: \"Available\", \"Progressing\", and \"Degraded\"\n\t    //
-                    +patchMergeKey=type\n\t    // +patchStrategy=merge\n\t    // +listType=map\n\t
-                    \   // +listMapKey=type\n\t    Conditions []metav1.Condition `json:\"conditions,omitempty\"
-                    patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
-                    \   // other fields\n\t}"
+                  description: Condition contains details for one aspect of the current
+                    state of this API Resource.
                   properties:
                     lastTransitionTime:
                       description: |-
@@ -202,12 +194,7 @@ spec:
                       - Unknown
                       type: string
                     type:
-                      description: |-
-                        type of condition in CamelCase or in foo.example.com/CamelCase.
-                        ---
-                        Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
-                        useful (see .node.status.conditions), the ability to deconflict is important.
-                        The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+                      description: type of condition in CamelCase or in foo.example.com/CamelCase.
                       maxLength: 316
                       pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
                       type: string
@@ -257,6 +244,8 @@ spec:
             - externalDNSReadyReplicas
             - externalDNSUnavailableReplicas
             type: object
+        required:
+        - spec
         type: object
     served: true
     storage: true
diff --git a/config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml b/config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
index 1e68a72c..8daab638 100644
--- a/config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
+++ b/config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.14.0
+    controller-gen.kubebuilder.io/version: v0.17.2
   name: externaldnses.approuting.kubernetes.azure.com
 spec:
   group: approuting.kubernetes.azure.com
@@ -143,16 +143,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the ExternalDNS
                 items:
-                  description: "Condition contains details for one aspect of the current
-                    state of this API Resource.\n---\nThis struct is intended for
-                    direct use as an array at the field path .status.conditions.  For
-                    example,\n\n\n\ttype FooStatus struct{\n\t    // Represents the
-                    observations of a foo's current state.\n\t    // Known .status.conditions.type
-                    are: \"Available\", \"Progressing\", and \"Degraded\"\n\t    //
-                    +patchMergeKey=type\n\t    // +patchStrategy=merge\n\t    // +listType=map\n\t
-                    \   // +listMapKey=type\n\t    Conditions []metav1.Condition `json:\"conditions,omitempty\"
-                    patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
-                    \   // other fields\n\t}"
+                  description: Condition contains details for one aspect of the current
+                    state of this API Resource.
                   properties:
                     lastTransitionTime:
                       description: |-
@@ -193,12 +185,7 @@ spec:
                       - Unknown
                       type: string
                     type:
-                      description: |-
-                        type of condition in CamelCase or in foo.example.com/CamelCase.
-                        ---
-                        Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
-                        useful (see .node.status.conditions), the ability to deconflict is important.
-                        The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+                      description: type of condition in CamelCase or in foo.example.com/CamelCase.
                       maxLength: 316
                       pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
                       type: string
@@ -248,6 +235,8 @@ spec:
             - externalDNSReadyReplicas
             - externalDNSUnavailableReplicas
             type: object
+        required:
+        - spec
         type: object
     served: true
     storage: true
diff --git a/config/crd/bases/approuting.kubernetes.azure.com_nginxingresscontrollers.yaml b/config/crd/bases/approuting.kubernetes.azure.com_nginxingresscontrollers.yaml
index 90f43242..d1822789 100644
--- a/config/crd/bases/approuting.kubernetes.azure.com_nginxingresscontrollers.yaml
+++ b/config/crd/bases/approuting.kubernetes.azure.com_nginxingresscontrollers.yaml
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
 kind: CustomResourceDefinition
 metadata:
   annotations:
-    controller-gen.kubebuilder.io/version: v0.14.0
+    controller-gen.kubebuilder.io/version: v0.17.2
   name: nginxingresscontrollers.approuting.kubernetes.azure.com
 spec:
   group: approuting.kubernetes.azure.com
@@ -129,6 +129,10 @@ spec:
                 - rule: (isURL(self.keyVaultURI) || !has(self.keyVaultURI))
                 - rule: ((self.forceSSLRedirect == true) && (has(self.secret) || has(self.keyVaultURI))
                     || (self.forceSSLRedirect == false))
+              httpDisabled:
+                description: HTTPDisabled is a flag that disables HTTP traffic to
+                  the NginxIngressController
+                type: boolean
               ingressClassName:
                 default: nginx.approuting.kubernetes.azure.com
                 description: |-
@@ -199,16 +203,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the NGINX Ingress Controller
                 items:
-                  description: "Condition contains details for one aspect of the current
-                    state of this API Resource.\n---\nThis struct is intended for
-                    direct use as an array at the field path .status.conditions.  For
-                    example,\n\n\n\ttype FooStatus struct{\n\t    // Represents the
-                    observations of a foo's current state.\n\t    // Known .status.conditions.type
-                    are: \"Available\", \"Progressing\", and \"Degraded\"\n\t    //
-                    +patchMergeKey=type\n\t    // +patchStrategy=merge\n\t    // +listType=map\n\t
-                    \   // +listMapKey=type\n\t    Conditions []metav1.Condition `json:\"conditions,omitempty\"
-                    patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
-                    \   // other fields\n\t}"
+                  description: Condition contains details for one aspect of the current
+                    state of this API Resource.
                   properties:
                     lastTransitionTime:
                       description: |-
@@ -249,12 +245,7 @@ spec:
                       - Unknown
                       type: string
                     type:
-                      description: |-
-                        type of condition in CamelCase or in foo.example.com/CamelCase.
-                        ---
-                        Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
-                        useful (see .node.status.conditions), the ability to deconflict is important.
-                        The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
+                      description: type of condition in CamelCase or in foo.example.com/CamelCase.
                       maxLength: 316
                       pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
                       type: string
diff --git a/pkg/controller/nginxingress/nginx_ingress_controller.go b/pkg/controller/nginxingress/nginx_ingress_controller.go
index c3bcb55d..c7d6ed7a 100644
--- a/pkg/controller/nginxingress/nginx_ingress_controller.go
+++ b/pkg/controller/nginxingress/nginx_ingress_controller.go
@@ -560,6 +560,7 @@ func ToNginxIngressConfig(nic *approutingv1alpha1.NginxIngressController, defaul
 		ServiceConfig: &manifests.ServiceConfig{
 			Annotations: nic.Spec.LoadBalancerAnnotations,
 		},
+		HTTPDisabled:                   nic.Spec.HTTPDisabled,
 		MinReplicas:                    minReplicas,
 		MaxReplicas:                    maxReplicas,
 		TargetCPUUtilizationPercentage: getTargetCPUUtilizationPercentage(nic),
diff --git a/pkg/controller/nginxingress/nginx_ingress_controller_test.go b/pkg/controller/nginxingress/nginx_ingress_controller_test.go
index b83bfa1b..2e6db728 100644
--- a/pkg/controller/nginxingress/nginx_ingress_controller_test.go
+++ b/pkg/controller/nginxingress/nginx_ingress_controller_test.go
@@ -1423,6 +1423,33 @@ func TestToNginxIngressConfig(t *testing.T) {
 				TargetCPUUtilizationPercentage: balancedTargetCPUUtilization,
 			},
 		},
+		{
+			name: "default controller class with HTTPDisabled set to true",
+			nic: &approutingv1alpha1.NginxIngressController{
+				TypeMeta: metav1.TypeMeta{
+					APIVersion: approutingv1alpha1.GroupVersion.String(),
+					Kind:       "NginxIngressController",
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name: DefaultNicName,
+				},
+				Spec: approutingv1alpha1.NginxIngressControllerSpec{
+					ControllerNamePrefix: DefaultNicResourceName,
+					IngressClassName:     DefaultIcName,
+					HTTPDisabled:         true,
+				},
+			},
+			want: manifests.NginxIngressConfig{
+				ControllerClass:                defaultCc,
+				ResourceName:                   DefaultNicResourceName,
+				IcName:                         DefaultIcName,
+				ServiceConfig:                  &manifests.ServiceConfig{},
+				HTTPDisabled:                   true,
+				MaxReplicas:                    defaultMaxReplicas,
+				MinReplicas:                    defaultMinReplicas,
+				TargetCPUUtilizationPercentage: defaultTargetCPUUtilization,
+			},
+		},
 	}
 
 	for _, c := range cases {
diff --git a/testing/e2e/suites/nginxIngressController.go b/testing/e2e/suites/nginxIngressController.go
index 0e8ca253..3d5e4750 100644
--- a/testing/e2e/suites/nginxIngressController.go
+++ b/testing/e2e/suites/nginxIngressController.go
@@ -331,6 +331,64 @@ func nicTests(in infra.Provisioned) []test {
 				return nil
 			},
 		},
+		{
+			name: "ingress with http disabled",
+			cfgs: builderFromInfra(in).
+				withOsm(in, false, true).
+				withVersions(manifests.OperatorVersionLatest).
+				withZones([]manifests.DnsZoneCount{manifests.DnsZoneCountNone}, []manifests.DnsZoneCount{manifests.DnsZoneCountNone}).
+				build(),
+			run: func(ctx context.Context, config *rest.Config, operator manifests.OperatorConfig) error {
+				lgr := logger.FromContext(ctx)
+				lgr.Info("starting test")
+
+				c, err := client.New(config, client.Options{
+					Scheme: scheme,
+				})
+				if err != nil {
+					return fmt.Errorf("creating client: %w", err)
+				}
+
+				testNIC := manifests.NewNginxIngressController("nginx-ingress-controller-with-http-disabled", "nginxingressclass-http-disabled")
+				testNIC.Spec.HTTPDisabled = true
+				if err := upsert(ctx, c, testNIC); err != nil {
+					return fmt.Errorf("upserting NIC: %w", err)
+				}
+
+				nic, err := waitForNICAvailable(ctx, c, testNIC)
+				if err != nil {
+					return fmt.Errorf("waiting for NIC to become available: %w", err)
+				}
+
+				service, err := getNginxLbServiceRef(nic)
+				if err != nil {
+					return fmt.Errorf("finding nginx lb service: %w", err)
+				}
+
+				lgr.Info("validating service does not contain http port")
+				var serviceCopy corev1.Service
+				if err := c.Get(ctx, client.ObjectKey{Namespace: service.Namespace, Name: service.Name}, &serviceCopy); err != nil {
+					return fmt.Errorf("getting service: %w", err)
+				}
+
+				for _, port := range serviceCopy.Spec.Ports {
+					if port.Name == "http" {
+						lgr.Error("http port found despite HTTPDisabled")
+						return errors.New("http port found despite HTTPDisabled")
+					}
+				}
+
+				if err := clientServerTest(ctx, config, operator, nil, in, func(ingress *netv1.Ingress, service *corev1.Service, z zoner) error {
+					ingress.Spec.IngressClassName = to.Ptr(testNIC.Spec.IngressClassName)
+					return nil
+				}, to.Ptr(service.Name)); err != nil {
+					return err
+				}
+
+				lgr.Info("finished testing")
+				return nil
+			},
+		},
 		{
 			name: "testing DefaultSSLCertificate validity",
 			cfgs: builderFromInfra(in).


Reviews:
user: login: OliverMKing
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-12T14:47:08Z
user: login: OliverMKing
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-12T14:47:24Z
user: login: OliverMKing
body: looks good to me. Just need to rename some things in e2e test. It's not a private nic
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-02-12T14:48:45Z
user: login: meecethereese
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-12T17:07:57Z
user: login: jaiveerk
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-27T19:59:56Z
user: login: meecethereese
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-27T20:03:08Z
user: login: meecethereese
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-27T20:13:01Z
user: login: OliverMKing
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-27T22:36:40Z
user: login: OliverMKing
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-02-27T22:38:02Z
user: login: OliverMKing
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-06T20:18:53Z
user: login: jaiveerk
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-10T15:00:50Z
user: login: OliverMKing
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-10T15:26:11Z
user: login: jaiveerk
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-10T15:41:00Z
user: login: jaiveerk
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-10T15:43:43Z
user: login: jaiveerk
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-10T15:44:54Z
user: login: jaiveerk
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-10T22:30:24Z
user: login: meecethereese
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-11T14:40:18Z
user: login: jaiveerk
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-11T21:13:13Z
user: login: jaiveerk
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-11T21:13:34Z
user: login: jaiveerk
body: lgtm
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-11T21:17:46Z
user: login: OliverMKing
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-13T18:19:09Z

Review comments:
diff_hunk: @@ -331,6 +331,81 @@ func nicTests(in infra.Provisioned) []test {
 				return nil
 			},
 		},
+		{
+			name: "private ingress with http disabled",
path: testing/e2e/suites/nginxIngressController.go
user: login: OliverMKing
body: it's not a private ingress
created_at: 2025-02-12T14:47:07Z
author_association: COLLABORATOR
diff_hunk: @@ -331,6 +331,81 @@ func nicTests(in infra.Provisioned) []test {
 				return nil
 			},
 		},
+		{
+			name: "private ingress with http disabled",
+			cfgs: builderFromInfra(in).
+				withOsm(in, false, true).
+				withVersions(manifests.OperatorVersionLatest).
+				withZones([]manifests.DnsZoneCount{manifests.DnsZoneCountNone}, []manifests.DnsZoneCount{manifests.DnsZoneCountNone}).
+				build(),
+			run: func(ctx context.Context, config *rest.Config, operator manifests.OperatorConfig) error {
+				lgr := logger.FromContext(ctx)
+				lgr.Info("starting test")
+
+				c, err := client.New(config, client.Options{
+					Scheme: scheme,
+				})
+				if err != nil {
+					return fmt.Errorf("creating client: %w", err)
+				}
+
+				privateNic := manifests.NewNginxIngressController("private", "private.ingress.class")
+				privateNic.Spec.HTTPDisabled = true
+				if err := upsert(ctx, c, privateNic); err != nil {
+					return fmt.Errorf("ensuring private NIC: %w", err)
path: testing/e2e/suites/nginxIngressController.go
user: login: OliverMKing
body: not private
created_at: 2025-02-12T14:47:23Z
author_association: COLLABORATOR
diff_hunk: @@ -331,6 +331,81 @@ func nicTests(in infra.Provisioned) []test {
 				return nil
 			},
 		},
+		{
+			name: "private ingress with http disabled",
+			cfgs: builderFromInfra(in).
+				withOsm(in, false, true).
+				withVersions(manifests.OperatorVersionLatest).
+				withZones([]manifests.DnsZoneCount{manifests.DnsZoneCountNone}, []manifests.DnsZoneCount{manifests.DnsZoneCountNone}).
+				build(),
+			run: func(ctx context.Context, config *rest.Config, operator manifests.OperatorConfig) error {
+				lgr := logger.FromContext(ctx)
+				lgr.Info("starting test")
+
+				c, err := client.New(config, client.Options{
+					Scheme: scheme,
+				})
+				if err != nil {
+					return fmt.Errorf("creating client: %w", err)
+				}
+
+				privateNic := manifests.NewNginxIngressController("private", "private.ingress.class")
+				privateNic.Spec.HTTPDisabled = true
+				if err := upsert(ctx, c, privateNic); err != nil {
+					return fmt.Errorf("ensuring private NIC: %w", err)
path: testing/e2e/suites/nginxIngressController.go
user: login: meecethereese
body: I've changed the test to mirror the logic in the test under it rather than the private test above it, lmk what you think of it
created_at: 2025-02-12T17:07:57Z
author_association: COLLABORATOR
diff_hunk: @@ -143,16 +145,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the ExternalDNS
                 items:
-                  description: "Condition contains details for one aspect of the current
path: config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
user: login: jaiveerk
body: did you run make crd after merging master? wonder why these are getting affected
created_at: 2025-02-27T19:59:56Z
author_association: COLLABORATOR
diff_hunk: @@ -143,16 +145,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the ExternalDNS
                 items:
-                  description: "Condition contains details for one aspect of the current
path: config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
user: login: meecethereese
body: yes, I did. @OliverMKing had me run it when he was initially showing me the e2es, I can't remember why though. It also kept throwing an error on generators not running successfully.
created_at: 2025-02-27T20:03:08Z
author_association: COLLABORATOR
diff_hunk: @@ -143,16 +145,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the ExternalDNS
                 items:
-                  description: "Condition contains details for one aspect of the current
path: config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
user: login: meecethereese
body: also, after checking my commit history I couldn't track it down but I must've ran it on one of my early commits
created_at: 2025-02-27T20:13:01Z
author_association: COLLABORATOR
diff_hunk: @@ -143,16 +145,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the ExternalDNS
                 items:
-                  description: "Condition contains details for one aspect of the current
path: config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
user: login: OliverMKing
body: it's probably just something to do with the version bump. Likely changes which kinds of comments are carried over
created_at: 2025-02-27T22:36:40Z
author_association: COLLABORATOR
diff_hunk: @@ -143,16 +145,8 @@ spec:
                 description: Conditions is an array of current observed conditions
                   for the ExternalDNS
                 items:
-                  description: "Condition contains details for one aspect of the current
path: config/crd/bases/approuting.kubernetes.azure.com_externaldnses.yaml
user: login: OliverMKing
body: Yup

https://github.com/Azure/aks-app-routing-operator/pull/373
created_at: 2025-02-27T22:38:02Z
author_association: COLLABORATOR
diff_hunk: @@ -331,6 +331,64 @@ func nicTests(in infra.Provisioned) []test {
 				return nil
 			},
 		},
+		{
+			name: "ingress with http disabled",
+			cfgs: builderFromInfra(in).
+				withOsm(in, false, true).
+				withVersions(manifests.OperatorVersionLatest).
+				withZones([]manifests.DnsZoneCount{manifests.DnsZoneCountNone}, []manifests.DnsZoneCount{manifests.DnsZoneCountNone}).
+				build(),
+			run: func(ctx context.Context, config *rest.Config, operator manifests.OperatorConfig) error {
+				lgr := logger.FromContext(ctx)
+				lgr.Info("starting test")
+
+				c, err := client.New(config, client.Options{
+					Scheme: scheme,
+				})
+				if err != nil {
+					return fmt.Errorf("creating client: %w", err)
+				}
+
+				testNIC := manifests.NewNginxIngressController("nginx-ingress-controller-with-http-disabled", "nginxingressclass")
path: testing/e2e/suites/nginxIngressController.go
user: login: OliverMKing
body: change the ingress class name to something unique too
created_at: 2025-03-06T20:18:53Z
author_association: COLLABORATOR
diff_hunk: @@ -51,6 +51,8 @@ spec:
                   or private). The number of zones is currently capped at 7 but may
                   be expanded in the future.
                 items:
+                  maxLength: 172
path: config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
user: login: jaiveerk
body: I believe this is unintentional? not sure we should be seeing any changes here
created_at: 2025-03-10T15:00:50Z
author_association: COLLABORATOR
diff_hunk: @@ -51,6 +51,8 @@ spec:
                   or private). The number of zones is currently capped at 7 but may
                   be expanded in the future.
                 items:
+                  maxLength: 172
path: config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
user: login: OliverMKing
body: the min length is odd too
created_at: 2025-03-10T15:26:11Z
author_association: COLLABORATOR
diff_hunk: @@ -51,6 +51,8 @@ spec:
                   or private). The number of zones is currently capped at 7 but may
                   be expanded in the future.
                 items:
+                  maxLength: 172
path: config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
user: login: jaiveerk
body: Going through spec - that's actually expected

https://github.com/Azure/aks-app-routing-operator/blob/2388d8c57bda42f7ef58e4f5dc4bb4b375b844db/api/v1alpha1/clusterexternaldns_types.go#L59

Again, just not sure why kubebuilder is being inconsistent with output
created_at: 2025-03-10T15:41:00Z
author_association: COLLABORATOR
diff_hunk: @@ -51,6 +51,8 @@ spec:
                   or private). The number of zones is currently capped at 7 but may
                   be expanded in the future.
                 items:
+                  maxLength: 172
path: config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
user: login: jaiveerk
body: I believe that was initially added because of resource constraints in azure - but not sure where I got either number from because I'm revising that now and we can definitely have dns zones outside those bounds
created_at: 2025-03-10T15:43:43Z
author_association: COLLABORATOR
diff_hunk: @@ -51,6 +51,8 @@ spec:
                   or private). The number of zones is currently capped at 7 but may
                   be expanded in the future.
                 items:
+                  maxLength: 172
path: config/crd/bases/approuting.kubernetes.azure.com_clusterexternaldnses.yaml
user: login: jaiveerk
body: @meecethereese would you mind adjusting the spec on externaldns CRDs to remove the min/max len fields on dns zone resource ids? We already have validation within the manifests, and CEL validation was too complex to ensure each item actually resembled an Azure resource ID
created_at: 2025-03-10T15:44:54Z
author_association: COLLABORATOR
diff_hunk: @@ -1423,6 +1423,33 @@ func TestToNginxIngressConfig(t *testing.T) {
 				TargetCPUUtilizationPercentage: balancedTargetCPUUtilization,
 			},
 		},
+		{
+			name: "default controller class with HTTPDisabled set to true",
path: pkg/controller/nginxingress/nginx_ingress_controller_test.go
user: login: jaiveerk
body: good start - but you should add a fixture test too, which allows us to ensure that the service that we deploy doesn't have the http port - https://github.com/Azure/aks-app-routing-operator/blob/677ddc611bff379091265603858a41799484071e/pkg/manifests/nginx_test.go#L52C1-L53C1 
created_at: 2025-03-10T22:30:20Z
author_association: COLLABORATOR
diff_hunk: @@ -1423,6 +1423,33 @@ func TestToNginxIngressConfig(t *testing.T) {
 				TargetCPUUtilizationPercentage: balancedTargetCPUUtilization,
 			},
 		},
+		{
+			name: "default controller class with HTTPDisabled set to true",
path: pkg/controller/nginxingress/nginx_ingress_controller_test.go
user: login: meecethereese
body: So, I think that the fixtures you're referring to were actually done in this other PR

[HTTP Disabled Flag for Nginx Ingress Config by meecethereese · Pull Request #358 · Azure/aks-app-routing-operator](https://github.com/Azure/aks-app-routing-operator/pull/358/files)

lmk if this is what you meant
created_at: 2025-03-11T14:40:18Z
author_association: COLLABORATOR
diff_hunk: @@ -1423,6 +1423,33 @@ func TestToNginxIngressConfig(t *testing.T) {
 				TargetCPUUtilizationPercentage: balancedTargetCPUUtilization,
 			},
 		},
+		{
+			name: "default controller class with HTTPDisabled set to true",
path: pkg/controller/nginxingress/nginx_ingress_controller_test.go
user: login: jaiveerk
body: yep that's exactly it!
created_at: 2025-03-11T21:13:12Z
author_association: COLLABORATOR

PR comments:
user: login: OliverMKing
created_at: 2025-02-12T14:48:21Z
body: /ok-to-test sha=40c61f7
author_association: COLLABORATOR
user: login: OliverMKing
created_at: 2025-02-12T18:05:01Z
body: /ok-to-test sha=00cd7c2
author_association: COLLABORATOR
user: login: OliverMKing
created_at: 2025-02-12T19:14:13Z
body: e2e tests are all failing.

https://github.com/Azure/aks-app-routing-operator/blob/main/docs/e2e.md
author_association: COLLABORATOR
user: login: meecethereese
created_at: 2025-02-14T18:36:35Z
body: /ok-to-test sha=cf4217a
author_association: COLLABORATOR
user: login: bfoley13
created_at: 2025-02-14T19:37:44Z
body: /ok-to-test sha=cf4217a
author_association: MEMBER
user: login: OliverMKing
created_at: 2025-03-06T20:32:44Z
body: /ok-to-test sha=6bd59ff
author_association: COLLABORATOR
user: login: meecethereese
created_at: 2025-03-10T19:49:34Z
body: /ok-to-test sha=d0adc03
author_association: COLLABORATOR
user: login: meecethereese
created_at: 2025-03-12T21:07:48Z
body: /ok-to-test sha=d0adc03
author_association: COLLABORATOR