Skip to content

Conversation

@grzpiotrowski
Copy link
Contributor

@grzpiotrowski grzpiotrowski commented May 2, 2025

This PR fixes OCPBUGS-55192.

Add ratcheting validation of the .spec.domain field of ingress controller.

Previously, the user could configure the .spec.domain field incorrectly which could result in the router pods entering a CrashLoopBackOff state immediately upon creation with error: invalid canonical hostname: [...].

Domain must consist of DNS labels separated by periods, where each label contains only lowercase alphanumeric characters and hyphens, must start and end with an alphanumeric character, and must not exceed 63 characters. The domain must not exceed 253 characters.

As part of the ingressController's implementation, cluster-ingress-operator always composes the router's canonical hostname from: "router-" + ingressController.Name + ingressController.Status.Domain.
For this reason, the maximum length of the .spec.domain field can vary based on the ingressController name set by the user (if it is not "default").
Validation of the IC's .spec.domain field introduced by this commit takes into consideration the actual length of the ingressController.Name, by adding a CEL validation rule on the IngressController object.

The .spec.domain field itself needed an additional length limit to pass the validation budget check. The shortest possible variant of the prefix and the ingress controller name was considered: for example "router-a.", which sets the max length of the domain field itself at 244 characters.

Changes to:

  • operator/v1/types_ingress.go
    (IngressControllerSpec): Add ratcheting validation of the Domain field.
  • operator/v1/tests/ingresscontrollers.operator.openshift.io/AAA_ungated.yaml
    Add test cases for the ingress controller .spec.domain field validation

Generated files:

  • openapi/openapi.json
  • openapi/generated_openapi/zz_generated.openapi.go
  • operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers.crd.yaml
  • operator/v1/zz_generated.featuregated-crd-manifests/ingresscontrollers.operator.openshift.io/AAA_ungated.yaml
  • operator/v1/zz_generated.featuregated-crd-manifests/ingresscontrollers.operator.openshift.io/SetEIPForNLBIngressController.yaml
  • operator/v1/zz_generated.swagger_doc_generated.go

@openshift-ci
Copy link
Contributor

openshift-ci bot commented May 2, 2025

Hello @grzpiotrowski! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@openshift-ci openshift-ci bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label May 2, 2025
@openshift-ci openshift-ci bot requested review from deads2k and everettraven May 2, 2025 15:03
@grzpiotrowski grzpiotrowski changed the title Add IngressController .spec.domain validation OCPBUGS-55192: Add IngressController .spec.domain validation May 2, 2025
@openshift-ci-robot openshift-ci-robot added jira/severity-critical Referenced Jira bug's severity is critical for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. labels May 2, 2025
@openshift-ci-robot
Copy link

@grzpiotrowski: This pull request references Jira Issue OCPBUGS-55192, which is invalid:

  • expected the bug to target the "4.20.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

In response to this:

This PR fixes OCPBUGS-55192.

Add ratcheting validation of the .spec.domain field of ingress controller.
Domain must consist of lowercase alphanumeric characters '-' or '.', and each label must start and end with an alphanumeric character.

Previously, the user could configure the .spec.domain field incorrectly which could result in the router pods entering a CrashLoopBackOff state immediately upon creation with error: invalid canonical hostname: [...].

Opted not to add the max length validation // +kubebuilder:validation:MaxLength=253 as it could be slightly misleading, because even if .spec.domain does not exceed that 253 characters limit, we could end up with an invalid canonical hostname error as this is constructed from the router name and the IC domain, which length could not be predicted here.

  • operator/v1/types_ingress.go (IngressControllerSpec): Add ratcheting validation of the Domain field.
  • operator/v1/tests/ingresscontrollers.operator.openshift.io/AAA_ungated.yaml Add test cases for the ingress controller .spec.domain field validation

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. label May 2, 2025
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from 2e10452 to a538d6c Compare May 2, 2025 15:34
@openshift-ci openshift-ci bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels May 2, 2025
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from a538d6c to d5e7974 Compare May 2, 2025 15:44
@openshift-ci openshift-ci bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 2, 2025
@grzpiotrowski grzpiotrowski changed the title OCPBUGS-55192: Add IngressController .spec.domain validation [WIP] OCPBUGS-55192: Add IngressController .spec.domain validation May 2, 2025
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 2, 2025
@grzpiotrowski grzpiotrowski marked this pull request as draft May 2, 2025 16:01
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from d5e7974 to a179eae Compare May 13, 2025 14:52
@openshift-ci openshift-ci bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels May 13, 2025
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch 2 times, most recently from c4e9ebf to 9a9eb85 Compare May 13, 2025 15:15
@grzpiotrowski grzpiotrowski marked this pull request as ready for review May 13, 2025 15:17
@grzpiotrowski
Copy link
Contributor Author

/retitle OCPBUGS-55192: Add IngressController .spec.domain validation

@openshift-ci openshift-ci bot requested a review from JoelSpeed May 13, 2025 15:18
@openshift-ci openshift-ci bot changed the title [WIP] OCPBUGS-55192: Add IngressController .spec.domain validation OCPBUGS-55192: Add IngressController .spec.domain validation May 13, 2025
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 13, 2025
@grzpiotrowski
Copy link
Contributor Author

/jira refresh

@openshift-ci-robot openshift-ci-robot added the jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. label May 13, 2025
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from 0e36abc to eb307b4 Compare October 3, 2025 15:28
@openshift-ci openshift-ci bot requested a review from Miciah October 3, 2025 15:40
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from eb307b4 to 2aa449e Compare October 3, 2025 15:41
//
// +kubebuilder:validation:MaxLength=253
// +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
// +kubebuilder:validation:XValidation:rule="self.split('.').all(label, !format.dns1123Label().validate(label).hasValue())",message="each DNS label must not exceed 63 characters"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does validating against the dns1123Label gain us anything here? Anything that isn't a valid label (apart from length) is validated in the previous rule. So here we just need to check that each label segment has length <= 63 right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I agree that it could be replaced with just a length check for each label, which would be cheaper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the label validation to only check for the max length of 63 chars, since the regex check is done in format.dns1123Subdomain() already as you mentioned.

@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from 2aa449e to 677e4a4 Compare October 8, 2025 18:30
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 8, 2025
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from 677e4a4 to a6fda06 Compare October 8, 2025 19:39
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 8, 2025
//
// +kubebuilder:validation:MaxLength=244
// +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
// +kubebuilder:validation:XValidation:rule="self.split('.').all(label, size(label) <= 63)",message="each DNS label must not exceed 63 characters"
Copy link
Contributor Author

@grzpiotrowski grzpiotrowski Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So to summarize so far.
The current approach I have is to validate at the level of the IngressController struct, to check for the length (253 max) of the combined domain there, since the ingress controller name can vary, impacting how long the .spec.domain can be in consequence.

I have two validations of the dns domain on the .spec.domain field.
One that uses format.dns1123Subdomain() and the other to check if each label does not exceed 63 chars limit, since the function above doesn't include this.

I needed to set some max length on the .spec.domain field, as to satisfy the validation budget. It is (I think) somewhat superficial, since the real length restriction is checked including the IC.name. I set it to 244 chars, which would be the shortest IC.name (1 char), resulting in the router-a. prefix (9 chars) for the router's canonical domain. Hence 244 chars max for the .spec.domain
Though the format.dns1123Subdomain() also checks for the max length of 253 chars, but this wouldn't come into play here.

Copy link
Contributor

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small docs update and then I'm happy with this

//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +openshift:compatibility-gen:level=1
// +kubebuilder:validation:XValidation:rule="!has(self.spec.domain) || size('router-' + self.metadata.name + '.' + self.spec.domain) <= 253",message="The combined 'router-' + IngressController.Name + '.' + .spec.domain cannot exceed 253 characters"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably easier to understand as metadata.name no? Since that's the first we are checking?

Suggested change
// +kubebuilder:validation:XValidation:rule="!has(self.spec.domain) || size('router-' + self.metadata.name + '.' + self.spec.domain) <= 253",message="The combined 'router-' + IngressController.Name + '.' + .spec.domain cannot exceed 253 characters"
// +kubebuilder:validation:XValidation:rule="!has(self.spec.domain) || size('router-' + self.metadata.name + '.' + self.spec.domain) <= 253",message="The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, done now.

This commit fixes OCPBUGS-55192.

https://issues.redhat.com/browse/OCPBUGS-55192

Add ratcheting validation of the .spec.domain field of ingress controller.

Domain must consist of DNS labels separated by periods, where each label
contains only lowercase alphanumeric characters and hyphens, must start
and end with an alphanumeric character, and must not exceed 63 characters.
The domain must not exceed 253 characters.

As part of the ingressController's implementation, cluster-ingress-operator
always composes the router's canonical hostname from:
`"router-" + ingressController.Name + ingressController.Status.Domain`.
For this reason, the maximum length of the .spec.domain field can vary
based on the ingressController name set by the user (if it is not "default").

Validation of the IC's .spec.domain field introduced by this commit
takes into consideration the actual length of the ingressController.Name,
by adding a CEL validation rule on the IngressController object.

The .spec.domain field itself needed an additional length limit to pass
the validation budget check. The shortest possible variant of the prefix
and the ingress controller name was considered: for example "router-a.",
which sets the max length of the domain field itself at 244 characters.

* operator/v1/types_ingress.go
(IngressControllerSpec): Add ratcheting validation of the Domain field.
* operator/v1/tests/ingresscontrollers.operator.openshift.io/AAA_ungated.yaml
Add test cases for the ingress controller .spec.domain field validation

Generated files:
* openapi/openapi.json
* openapi/generated_openapi/zz_generated.openapi.go
* operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers.crd.yaml
* operator/v1/zz_generated.featuregated-crd-manifests/ingresscontrollers.operator.openshift.io/AAA_ungated.yaml
* operator/v1/zz_generated.swagger_doc_generated.go
@grzpiotrowski grzpiotrowski force-pushed the OCPBUGS-55192-ic-spec-domain-validation branch from a6fda06 to 63691f4 Compare October 14, 2025 14:10
@grzpiotrowski
Copy link
Contributor Author

About verify-crdify

ERROR: (v1) ^.spec.domain - maxLength: maximum constraint added when there was none previously : 244

Is this something to worry about or override?

@everettraven
Copy link
Contributor

About verify-crdify

ERROR: (v1) ^.spec.domain - maxLength: maximum constraint added when there was none previously : 244

Is this something to worry about or override?

In this case, it is likely overridable. IIRC this is adding validation for something that would have never been valid in the first place.

@grzpiotrowski
Copy link
Contributor Author

grzpiotrowski commented Oct 16, 2025

Tested manually in a cluster:

$ oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
  name: internal
  namespace: openshift-ingress-operator
spec:
  domain: '*.myexampledomain.com'
  replicas: 1
  endpointPublishingStrategy:
    loadBalancer:
      scope: Internal
    type: LoadBalancerService
EOF
The IngressController "internal" is invalid: spec.domain: Invalid value: "string": domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character
$ oc create -f -<<'EOF'                                                            
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
  name: ic-name-containing-exactly-40-characters
  namespace: openshift-ingress-operator
spec:
  domain: 'this-domain.has-208-characters.which-on.its-own-would-not-exceed.the-limit-of-253-chars.but-combined-with-the-ingress-controller-name.with-40-chars.and-the-router-prefix.ends-up-as-a-too-long.canonical-domain'
  replicas: 1
  endpointPublishingStrategy:
    loadBalancer:
      scope: Internal
    type: LoadBalancerService
EOF
The IngressController "ic-name-containing-exactly-40-characters" is invalid: <nil>: Invalid value: "object": The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters
$ oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
  name: a       
  namespace: openshift-ingress-operator
spec:
  domain: 'this-domain.has-exactly-245-characters.for-the-purpose-of-testing.the-spec-domain-field-length-validation.it-exceeds-the-limit-set-on-the-spec-domain-field.by-one-character-to-test-the-error.message-from-this-validation.otherwise-it-is-valid.com'
  replicas: 1
  endpointPublishingStrategy:
    loadBalancer:
      scope: Internal
    type: LoadBalancerService
EOF
The IngressController "a" is invalid: 
* spec.domain: Too long: may not be more than 244 bytes
* <nil>: Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation
$ oc create -f -<<'EOF'                                                            
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
  name: internal
  namespace: openshift-ingress-operator
spec:
  domain: 'foo.this-label-exceeds-63-characters-for-the-purpose-of-testing-the-domain-validation.com'
  replicas: 1
  endpointPublishingStrategy:
    loadBalancer:
      scope: Internal
    type: LoadBalancerService
EOF                          
The IngressController "internal" is invalid: spec.domain: Invalid value: "string": each DNS label must not exceed 63 characters
$ oc create -f -<<'EOF'                                                            
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
  name: ic-name-containing-exactly-40-characters
  namespace: openshift-ingress-operator
spec:
  domain: '*.this-domain.has-210-characters.which-on.its-own-would-not-exceed.the-limit-of-253-chars.but-combined-with-the-ingress-controller-name.with-40-chars.and-the-router-prefix.ends-up-as-a-too-long.canonical-domain'
  replicas: 1
  endpointPublishingStrategy:
    loadBalancer:
      scope: Internal
    type: LoadBalancerService
EOF
The IngressController "ic-name-containing-exactly-40-characters" is invalid: 
* <nil>: Invalid value: "object": The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters
* spec.domain: Invalid value: "string": domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character
$ oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
  name: internal                                
  namespace: openshift-ingress-operator
spec:
  domain: 'exampledomain.com'
  replicas: 1                               
  endpointPublishingStrategy:
    loadBalancer:
      scope: Internal
    type: LoadBalancerService
EOF                          
ingresscontroller.operator.openshift.io/internal created

@melvinjoseph86
Copy link

Tested along with openshift/cluster-ingress-operator#1295.
the fix is working and the ingress controller is creating with wrong values in .spec.domain

mjoseph@mjoseph-mac Downloads % oc get clusterversion
NAME VERSION AVAILABLE PROGRESSING SINCE STATUS
version 4.21.0-0-2025-10-17-143658-test-ci-ln-gk30bwk-latest True False 45m Cluster version is 4.21.0-0-2025-10-17-143658-test-ci-ln-gk30bwk-latest

mjoseph@mjoseph-mac Downloads % oc create -f - < kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: internal
namespace: openshift-ingress-operator
spec:
domain: '*.myexampledomain.com'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
heredoc> EOF
The IngressController "internal" is invalid: spec.domain: Invalid value: "string": domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character
mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: ic-name-containing-exactly-40-characters
namespace: openshift-ingress-operator
spec:
domain: 'this-domain.has-208-characters.which-on.its-own-would-not-exceed.the-limit-of-253-chars.but-combined-with-the-ingress-controller-name.with-40-chars.and-the-router-prefix.ends-up-as-a-too-long.canonical-domain'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "ic-name-containing-exactly-40-characters" is invalid: : Invalid value: "object": The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters
mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: a
namespace: openshift-ingress-operator
spec:
domain: 'this-domain.has-exactly-245-characters.for-the-purpose-of-testing.the-spec-domain-field-length-validation.it-exceeds-the-limit-set-on-the-spec-domain-field.by-one-character-to-test-the-error.message-from-this-validation.otherwise-it-is-valid.com'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "a" is invalid:

  • spec.domain: Too long: may not be more than 244 bytes
  • : Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation
    mjoseph@mjoseph-mac Downloads %
    mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: internal
namespace: openshift-ingress-operator
spec:
domain: 'foo.this-label-exceeds-63-characters-for-the-purpose-of-testing-the-domain-validation.com'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "internal" is invalid: spec.domain: Invalid value: "string": each DNS label must not exceed 63 characters
mjoseph@mjoseph-mac Downloads %
mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: ic-name-containing-exactly-40-characters
namespace: openshift-ingress-operator
spec:
domain: '*.this-domain.has-210-characters.which-on.its-own-would-not-exceed.the-limit-of-253-chars.but-combined-with-the-ingress-controller-name.with-40-chars.and-the-router-prefix.ends-up-as-a-too-long.canonical-domain'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "ic-name-containing-exactly-40-characters" is invalid:

  • : Invalid value: "object": The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters
  • spec.domain: Invalid value: "string": domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character
    mjoseph@mjoseph-mac Downloads %

/label qe-approved
/verified by @mjoseph

@openshift-ci openshift-ci bot added the qe-approved Signifies that QE has signed off on this PR label Oct 17, 2025
@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Oct 17, 2025
@openshift-ci-robot
Copy link

@melvinjoseph86: This PR has been marked as verified by @mjoseph.

In response to this:

Tested along with openshift/cluster-ingress-operator#1295.
the fix is working and the ingress controller is creating with wrong values in .spec.domain

mjoseph@mjoseph-mac Downloads % oc get clusterversion
NAME VERSION AVAILABLE PROGRESSING SINCE STATUS
version 4.21.0-0-2025-10-17-143658-test-ci-ln-gk30bwk-latest True False 45m Cluster version is 4.21.0-0-2025-10-17-143658-test-ci-ln-gk30bwk-latest

mjoseph@mjoseph-mac Downloads % oc create -f - < kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: internal
namespace: openshift-ingress-operator
spec:
domain: '*.myexampledomain.com'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
heredoc> EOF
The IngressController "internal" is invalid: spec.domain: Invalid value: "string": domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character
mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: ic-name-containing-exactly-40-characters
namespace: openshift-ingress-operator
spec:
domain: 'this-domain.has-208-characters.which-on.its-own-would-not-exceed.the-limit-of-253-chars.but-combined-with-the-ingress-controller-name.with-40-chars.and-the-router-prefix.ends-up-as-a-too-long.canonical-domain'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "ic-name-containing-exactly-40-characters" is invalid: : Invalid value: "object": The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters
mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: a
namespace: openshift-ingress-operator
spec:
domain: 'this-domain.has-exactly-245-characters.for-the-purpose-of-testing.the-spec-domain-field-length-validation.it-exceeds-the-limit-set-on-the-spec-domain-field.by-one-character-to-test-the-error.message-from-this-validation.otherwise-it-is-valid.com'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "a" is invalid:

  • spec.domain: Too long: may not be more than 244 bytes
  • : Invalid value: "null": some validation rules were not checked because the object was invalid; correct the existing errors to complete validation
    mjoseph@mjoseph-mac Downloads %
    mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: internal
namespace: openshift-ingress-operator
spec:
domain: 'foo.this-label-exceeds-63-characters-for-the-purpose-of-testing-the-domain-validation.com'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "internal" is invalid: spec.domain: Invalid value: "string": each DNS label must not exceed 63 characters
mjoseph@mjoseph-mac Downloads %
mjoseph@mjoseph-mac Downloads %

mjoseph@mjoseph-mac Downloads % oc create -f -<<'EOF'
kind: IngressController
apiVersion: operator.openshift.io/v1
metadata:
name: ic-name-containing-exactly-40-characters
namespace: openshift-ingress-operator
spec:
domain: '*.this-domain.has-210-characters.which-on.its-own-would-not-exceed.the-limit-of-253-chars.but-combined-with-the-ingress-controller-name.with-40-chars.and-the-router-prefix.ends-up-as-a-too-long.canonical-domain'
replicas: 1
endpointPublishingStrategy:
loadBalancer:
scope: Internal
type: LoadBalancerService
EOF
The IngressController "ic-name-containing-exactly-40-characters" is invalid:

  • : Invalid value: "object": The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters
  • spec.domain: Invalid value: "string": domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character
    mjoseph@mjoseph-mac Downloads %

/label qe-approved
/verified by @mjoseph

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link
Contributor

@JoelSpeed JoelSpeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Oct 19, 2025
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 19, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: JoelSpeed

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 19, 2025
@JoelSpeed
Copy link
Contributor

/override ci/prow/verify-crdify

The complaint is about adding a new maximum length constraint, but that is a property that ratchets, so I'm happy we are ok doing this

CC @everettraven we might want to teach crdify to ignore (or have an option to ignore) ratchetable changes

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 19, 2025

@JoelSpeed: Overrode contexts on behalf of JoelSpeed: ci/prow/verify-crdify

In response to this:

/override ci/prow/verify-crdify

The complaint is about adding a new maximum length constraint, but that is a property that ratchets, so I'm happy we are ok doing this

CC @everettraven we might want to teach crdify to ignore (or have an option to ignore) ratchetable changes

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 19, 2025

@grzpiotrowski: all tests passed!

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-merge-bot openshift-merge-bot bot merged commit a8a5157 into openshift:master Oct 19, 2025
14 checks passed
@openshift-ci-robot
Copy link

@grzpiotrowski: Jira Issue Verification Checks: Jira Issue OCPBUGS-55192
✔️ This pull request was pre-merge verified.
✔️ All associated pull requests have merged.
✔️ All associated, merged pull requests were pre-merge verified.

Jira Issue OCPBUGS-55192 has been moved to the MODIFIED state and will move to the VERIFIED state when the change is available in an accepted nightly payload. 🕓

In response to this:

This PR fixes OCPBUGS-55192.

Add ratcheting validation of the .spec.domain field of ingress controller.

Previously, the user could configure the .spec.domain field incorrectly which could result in the router pods entering a CrashLoopBackOff state immediately upon creation with error: invalid canonical hostname: [...].

Domain must consist of DNS labels separated by periods, where each label contains only lowercase alphanumeric characters and hyphens, must start and end with an alphanumeric character, and must not exceed 63 characters. The domain must not exceed 253 characters.

As part of the ingressController's implementation, cluster-ingress-operator always composes the router's canonical hostname from: "router-" + ingressController.Name + ingressController.Status.Domain.
For this reason, the maximum length of the .spec.domain field can vary based on the ingressController name set by the user (if it is not "default").
Validation of the IC's .spec.domain field introduced by this commit takes into consideration the actual length of the ingressController.Name, by adding a CEL validation rule on the IngressController object.

The .spec.domain field itself needed an additional length limit to pass the validation budget check. The shortest possible variant of the prefix and the ingress controller name was considered: for example "router-a.", which sets the max length of the domain field itself at 244 characters.

Changes to:

  • operator/v1/types_ingress.go
    (IngressControllerSpec): Add ratcheting validation of the Domain field.
  • operator/v1/tests/ingresscontrollers.operator.openshift.io/AAA_ungated.yaml
    Add test cases for the ingress controller .spec.domain field validation

Generated files:

  • openapi/openapi.json
  • openapi/generated_openapi/zz_generated.openapi.go
  • operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers.crd.yaml
  • operator/v1/zz_generated.featuregated-crd-manifests/ingresscontrollers.operator.openshift.io/AAA_ungated.yaml
  • operator/v1/zz_generated.featuregated-crd-manifests/ingresscontrollers.operator.openshift.io/SetEIPForNLBIngressController.yaml
  • operator/v1/zz_generated.swagger_doc_generated.go

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-merge-robot
Copy link
Contributor

Fix included in accepted release 4.21.0-0.nightly-2025-10-22-123727

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/severity-critical Referenced Jira bug's severity is critical for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. qe-approved Signifies that QE has signed off on this PR size/L Denotes a PR that changes 100-499 lines, ignoring generated files. verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants