Skip to content

Conversation

@grzpiotrowski
Copy link
Contributor

This PR fixes OCPBUGS-32275.

Adds spec.domain field in the Ingress config CRD validation to make it immutable and match the documentation. Prior to this commit the domain value could be changed and cause degraded state of some cluster operators.

@qodo-code-review
Copy link

Review Summary by Qodo

Add immutability validation for Ingress spec.domain field

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add immutability validation for spec.domain field in Ingress CRD
• Prevent domain changes after initial set to avoid cluster operator degradation
• Make domain field optional in validation schema
• Add comprehensive test cases for domain immutability behavior
Diagram
flowchart LR
  A["Ingress spec.domain"] -->|Add XValidation rule| B["Immutability constraint"]
  B -->|oldSelf == '' OR self == oldSelf| C["Allow initial set or no change"]
  C -->|Reject domain changes| D["Prevent operator degradation"]
  A -->|Make optional| E["Updated CRD schema"]
  F["Test cases"] -->|Validate behavior| G["Domain immutability verified"]
Loading

Grey Divider

File Changes

1. config/v1/types_ingress.go ✨ Enhancement +2/-0

Add domain immutability validation rule

• Add kubebuilder:validation:XValidation rule to enforce domain immutability
• Rule allows empty initial value or unchanged domain value
• Mark domain field as optional with +optional annotation
• Validation message: "domain is immutable once set"

config/v1/types_ingress.go


2. openapi/generated_openapi/zz_generated.openapi.go ⚙️ Configuration changes +0/-1

Remove domain from required fields

• Remove domain from required fields list in IngressSpec schema
• Makes domain field optional in OpenAPI specification

openapi/generated_openapi/zz_generated.openapi.go


3. config/v1/tests/ingresses.config.openshift.io/AAA_ungated.yaml 🧪 Tests +57/-0

Add comprehensive domain immutability tests

• Add test for creating Ingress with domain set
• Add test for setting domain initially when empty
• Add test verifying domain cannot be changed once set with expected error
• Add test for updating other fields without changing domain

config/v1/tests/ingresses.config.openshift.io/AAA_ungated.yaml


View more (3)
4. config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses.crd.yaml ⚙️ Configuration changes +3/-0

Add domain validation to CRD manifest

• Add x-kubernetes-validations section to domain field
• Include validation rule: oldSelf == '' || self == oldSelf
• Set validation message: "domain is immutable once set"

config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_ingresses.crd.yaml


5. config/v1/zz_generated.featuregated-crd-manifests/ingresses.config.openshift.io/AAA_ungated.yaml ⚙️ Configuration changes +3/-0

Add domain validation to featuregated CRD

• Add x-kubernetes-validations section to domain field
• Include validation rule: oldSelf == '' || self == oldSelf
• Set validation message: "domain is immutable once set"

config/v1/zz_generated.featuregated-crd-manifests/ingresses.config.openshift.io/AAA_ungated.yaml


6. payload-manifests/crds/0000_10_config-operator_01_ingresses.crd.yaml ⚙️ Configuration changes +3/-0

Add domain validation to payload CRD manifest

• Add x-kubernetes-validations section to domain field
• Include validation rule: oldSelf == '' || self == oldSelf
• Set validation message: "domain is immutable once set"

payload-manifests/crds/0000_10_config-operator_01_ingresses.crd.yaml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Domain markers undocumented 📘 Rule violation ✓ Correctness
Description
• The Domain field now has +optional and an XValidation immutability rule, but the field
  comment does not explicitly document optional/omitted behavior or clearly describe the validation
  behavior in human-readable terms.
• This creates an undocumented API constraint for consumers (especially around whether omission vs
  empty string is allowed and when updates are permitted), which can lead to misunderstanding and
  incorrect client usage.
Code

config/v1/types_ingress.go[R45-48]

	// Once set, changing domain is not currently supported.
+	// +kubebuilder:validation:XValidation:rule="oldSelf == '' || self == oldSelf",message="domain is immutable once set"
+	// +optional
	Domain string `json:"domain"`
Evidence
Compliance rule 7 requires that any kubebuilder validation markers and +optional behavior be
documented in the field’s Go comment, including what happens when the field is omitted. The Domain
field includes +optional and an XValidation rule, but its comment only states immutability at a
high level and does not explain omitted/empty behavior or the precise update allowance implied by
the CEL expression.

AGENTS.md
config/v1/types_ingress.go[37-48]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `Domain` field has kubebuilder markers (`+optional` and `+kubebuilder:validation:XValidation`) but the Go field comment does not fully document what those markers mean, including behavior when the field is omitted.

## Issue Context
Compliance requires that every kubebuilder validation marker applied to a field be documented in the field comment, including optional vs required behavior (and what happens when omitted), and the meaning/behavior of the validation rule.

## Fix Focus Areas
- config/v1/types_ingress.go[37-48]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

This commit fixes OCPBUGS-32275.
https://issues.redhat.com/browse/OCPBUGS-32275

Adds `spec.domain` field in the Ingress config CRD validation
to make it immutable and match the documentation. Prior to this
commit the domain value could be changed and cause degraded state
of some cluster operators.
@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

📝 Walkthrough

Walkthrough

This pull request implements immutability validation for the Ingress domain field. The changes include adding a kubebuilder validation annotation to the Domain field in the IngressSpec type definition, updating the CRD schema validation to include x-kubernetes-validations enforcing that the domain field cannot be changed after initial creation, and adding test cases that verify domain immutability behavior and validate the error message when attempting to update the domain.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding immutability validation to the ingress.spec.domain field.
Description check ✅ Passed The description is directly related to the changeset, explaining the purpose, the bug fix reference, and the impact of enforcing domain immutability.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.5.0)

Error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented
The command is terminated due to an error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci openshift-ci bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Feb 9, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@config/v1/tests/ingresses.config.openshift.io/AAA_ungated.yaml`:
- Around line 26-38: Add a new onUpdate test case named "Should not be able to
set domain if initially empty" that uses an initial Ingress manifest with spec:
{} and an updated manifest that sets spec.domain to apps.example.com, and assert
expectedError: "domain is immutable once set"; place this case alongside the
existing "Should not be able to change domain once set" entry so the suite
verifies the transition from empty→set and ensures the validation rule for
immutability-once-set is covered.

In `@payload-manifests/crds/0000_10_config-operator_01_ingresses.crd.yaml`:
- Around line 132-134: The current validation rule "self == oldSelf" (under
x-kubernetes-validations) prevents any change including setting domain from
empty; update the rule to allow initial population by changing it to something
like "oldSelf.domain == null || oldSelf.domain == '' || self == oldSelf" so the
domain can be set when previously empty but remains immutable afterwards;
alternatively, if domain is always set at creation, simply reword the message to
"domain is immutable" instead of implying an initial set is allowed.

Comment on lines +26 to +38
onUpdate:
- name: Should not be able to change domain once set
initial: |
apiVersion: config.openshift.io/v1
kind: Ingress
spec:
domain: apps.example.com
updated: |
apiVersion: config.openshift.io/v1
kind: Ingress
spec:
domain: test.example.com
expectedError: "domain is immutable once set"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing test for setting domain on an initially empty resource.

There is no test covering the case where the Ingress is created without a domain and then updated to set one. This is the edge case that distinguishes "immutable" from "immutable once set" and directly relates to the concern about the validation rule. Adding this test would clarify the intended behavior:

    - name: Should not be able to set domain if initially empty
      initial: |
        apiVersion: config.openshift.io/v1
        kind: Ingress
        spec: {}
      updated: |
        apiVersion: config.openshift.io/v1
        kind: Ingress
        spec:
          domain: apps.example.com
      expectedError: "domain is immutable once set"

If this transition should be allowed, this test (and the rule) need adjusting accordingly.

🤖 Prompt for AI Agents
In `@config/v1/tests/ingresses.config.openshift.io/AAA_ungated.yaml` around lines
26 - 38, Add a new onUpdate test case named "Should not be able to set domain if
initially empty" that uses an initial Ingress manifest with spec: {} and an
updated manifest that sets spec.domain to apps.example.com, and assert
expectedError: "domain is immutable once set"; place this case alongside the
existing "Should not be able to change domain once set" entry so the suite
verifies the transition from empty→set and ensures the validation rule for
immutability-once-set is covered.

Comment on lines +132 to +134
x-kubernetes-validations:
- message: domain is immutable once set
rule: self == oldSelf
Copy link

@coderabbitai coderabbitai bot Feb 9, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Rule self == oldSelf prevents setting domain for the first time, not just "once set".

The message says "domain is immutable once set," implying it should be possible to set the domain initially on a resource created without one. However, self == oldSelf blocks all changes, including transitioning from an empty string to a value. If the Ingress resource is ever created (or exists) with an empty domain, this rule locks it to empty permanently.

If the intent is truly "immutable once set," the rule should allow setting an empty field:

Proposed fix
                x-kubernetes-validations:
-               - message: domain is immutable once set
-                 rule: self == oldSelf
+               - message: domain is immutable once set
+                 rule: oldSelf == '' || self == oldSelf

If, on the other hand, the domain is always populated at creation time by the installer and an empty-to-non-empty transition is never expected, then self == oldSelf is correct but the message is misleading — consider rewording to "domain is immutable".

🤖 Prompt for AI Agents
In `@payload-manifests/crds/0000_10_config-operator_01_ingresses.crd.yaml` around
lines 132 - 134, The current validation rule "self == oldSelf" (under
x-kubernetes-validations) prevents any change including setting domain from
empty; update the rule to allow initial population by changing it to something
like "oldSelf.domain == null || oldSelf.domain == '' || self == oldSelf" so the
domain can be set when previously empty but remains immutable afterwards;
alternatively, if domain is always set at creation, simply reword the message to
"domain is immutable" instead of implying an initial set is allowed.

Copy link
Contributor Author

@grzpiotrowski grzpiotrowski Feb 9, 2026

Choose a reason for hiding this comment

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

Looking at the test cases the domain value can be set initially when the self == oldSelf validation is in place. Rewording the validation error to "domain is immutable" is something to consider maybe, but the current on follows the wording existing in the documentation.

Copy link

Choose a reason for hiding this comment

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

@grzpiotrowski, you're absolutely right, and I apologize for the confusion. I misunderstood how self == oldSelf behaves in Kubernetes CEL validations.

On CREATE operations, oldSelf is not available, so the rule doesn't block setting the domain initially. On UPDATE operations, the rule correctly prevents any changes. Your test cases confirm this works as intended—the domain can be set on creation but cannot be modified afterward.

The message "domain is immutable once set" accurately describes this behavior and aligns with your documentation. Thank you for the clarification!

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 9, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign deads2k for approval. For more information see the Code Review Process.

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

Details 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

@grzpiotrowski
Copy link
Contributor Author

/test verify

@qodo-code-review
Copy link

qodo-code-review bot commented Feb 9, 2026

PR-Agent: could not fine a component named verify in a supported language in this PR.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 9, 2026

@grzpiotrowski: all tests passed!

Full PR test history. Your PR dashboard.

Details

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.

@grzpiotrowski
Copy link
Contributor Author

/jira refresh

@openshift-ci-robot openshift-ci-robot added jira/severity-important Referenced Jira bug's severity is important for the branch this PR is targeting. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Feb 9, 2026
@openshift-ci-robot
Copy link

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

  • expected the bug to target the "4.22.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.

Details

In response to this:

/jira refresh

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.

@grzpiotrowski
Copy link
Contributor Author

/jira refresh

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Feb 9, 2026
@openshift-ci-robot
Copy link

@grzpiotrowski: This pull request references Jira Issue OCPBUGS-32275, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (4.22.0) matches configured target version for branch (4.22.0)
  • bug is in the state ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)

Requesting review from QA contact:
/cc @lihongan

Details

In response to this:

/jira refresh

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 openshift-ci bot requested a review from lihongan February 9, 2026 19:54
@grzpiotrowski
Copy link
Contributor Author

/jira refresh

@openshift-ci-robot
Copy link

@grzpiotrowski: An error was encountered querying GitHub for users with public email (hongli@redhat.com) for bug OCPBUGS-32275 on the Jira server at https://issues.redhat.com/. No known errors were detected, please see the full error message for details.

Full error message. non-200 OK status code: 429 Too Many Requests body: "{\"message\":\"This endpoint is temporarily being throttled. Please try again later. For more on scraping GitHub and how it may affect your rights, please review our Terms of Service (https://docs.github.com/en/site-policy/github-terms/github-terms-of-service)\",\"documentation_url\":\"https://docs.github.com/graphql/using-the-rest-api/rate-limits-for-the-rest-api\",\"status\":\"429\"}"

Please contact an administrator to resolve this issue, then request a bug refresh with /jira refresh.

Details

In response to this:

/jira refresh

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.

@lihongan
Copy link
Contributor

/jira refresh

@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Feb 10, 2026
@openshift-ci-robot
Copy link

@lihongan: This pull request references Jira Issue OCPBUGS-32275, which is valid.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (4.22.0) matches configured target version for branch (4.22.0)
  • bug is in the state POST, which is one of the valid states (NEW, ASSIGNED, POST)

Requesting review from QA contact:
/cc @lihongan

Details

In response to this:

/jira refresh

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.

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

Labels

jira/severity-important Referenced Jira bug's severity is important 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. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants