Skip to content

fix: comment status without SSA options#660

Open
fernandezcuesta wants to merge 2 commits into
crossplane:mainfrom
fernandezcuesta:fix/observation-ssa-markers
Open

fix: comment status without SSA options#660
fernandezcuesta wants to merge 2 commits into
crossplane:mainfrom
fernandezcuesta:fix/observation-ssa-markers

Conversation

@fernandezcuesta

@fernandezcuesta fernandezcuesta commented May 21, 2026

Copy link
Copy Markdown
Contributor

Description of your changes

Remove SSA markers for listType: map and injected key defaults in the observation (status) fields.

Fixes #659

I have:

  • Read and followed Upjet's contribution process.
  • Run make reviewable to ensure this PR is ready for review.
    - [ ] Added backport release-x.y labels to auto-backport this PR if necessary.

How has this code been tested

Added a test.

Real e2e tested with provider-pageduty in fernandezcuesta/provider-pagerduty:fix-ssa-markers.

Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com>
@fernandezcuesta fernandezcuesta marked this pull request as ready for review May 22, 2026 11:09
@fernandezcuesta fernandezcuesta changed the title fix: comment status without ssa options fix: comment status without SSA options May 22, 2026
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR fixes a bug where server-side apply merge-strategy markers were incorrectly applied to Observation struct fields. When status lists contained multiple items, the API server rejected updates due to conflicting default values. The fix strips SSA markers and defaults from Observation fields, with test coverage validating that markers appear only in the Spec side (Parameters) but not in the Status side (Observation).

Changes

SSA Marker Removal and Test Coverage

Layer / File(s) Summary
Strip SSA markers from Observation fields
pkg/types/field.go
When adding a field to the Observation type, the code now clears ServerSideApplyOptions list-map merge markers (setting ListType and ListMapKey to nil), removes KubebuilderOptions.Default, and unsets Comment.Reference to prevent conflicts from duplicate default values in multi-item lists.
Validate SSA marker isolation in test coverage
pkg/types/builder_test.go
TestBuild test infrastructure gains optional commentChecks callbacks to verify comment output. A new test case SSA_InjectedKey_Not_In_Observation_Comments asserts that +listType=map and +listMapKey markers appear in Parameters.Rule comments but are absent from Observation.Rule comments, and that kubebuilder defaults do not appear on the Observation.RuleIndex field.

🎯 2 (Simple) | ⏱️ ~10 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error)

Check name Status Explanation Resolution
Configuration Api Breaking Changes ❌ Error PR removes multiple public exported entities from pkg/config/: deletes conversion.go (removing RegisterAutoConversions and ExcludeTypeChangesFromIdentity functions), removes AutoConversionRegistrat... Add 'breaking-change' label to PR to acknowledge configuration API breaking changes, or document the migration path for downstream providers.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main fix: removing SSA options/markers from observation (status) comment fields, which aligns with the primary changeset.
Linked Issues check ✅ Passed The changes implement the refined surgical approach from issue #659: removing only SSA markers and injected-key defaults related to listType=map from observation fields, while preserving other markers to minimize CRD changes.
Out of Scope Changes check ✅ Passed All changes are scoped to the stated objectives: test coverage for SSA marker verification and sanitization of listType=map-related markers in observation field comments.
Generated Code Manual Edits ✅ Passed No files matching the zz_*.go pattern were modified in this PR. All changes are to hand-written source files (pkg/types/field.go, pkg/types/builder_test.go, etc.) and not generated code.
Template Breaking Changes ✅ Passed This PR does not modify any pkg/controller/external*.go template files. Changes are limited to pkg/types/field.go and pkg/types/builder_test.go, affecting type comment generation for observat...
Description check ✅ Passed The PR description clearly describes the changeset: removing SSA markers and injected key defaults from observation fields for listType: map configurations.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
pkg/types/builder_test.go (1)

642-642: ⚡ Quick win

Please rename the test case key to PascalCase (no underscores).

Nice coverage addition here. Could you rename "SSA_InjectedKey_Not_In_Observation_Comments" to a PascalCase form (for example, SSAInjectedKeyNotInObservationComments) to match repo test naming conventions? Thanks for adding this regression case.

As per coding guidelines, **/*_test.go: “Enforce table-driven test structure: PascalCase test names (no underscores)”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/types/builder_test.go` at line 642, Rename the table-driven test case key
"SSA_InjectedKey_Not_In_Observation_Comments" to a PascalCase identifier (no
underscores), e.g., SSAInjectedKeyNotInObservationComments, so it matches the
repository's test naming convention; update any places that reference this map
key inside builder_test.go (the test cases map entry and any lookups/assertions)
to use the new PascalCase name.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/types/builder_test.go`:
- Line 642: Rename the table-driven test case key
"SSA_InjectedKey_Not_In_Observation_Comments" to a PascalCase identifier (no
underscores), e.g., SSAInjectedKeyNotInObservationComments, so it matches the
repository's test naming convention; update any places that reference this map
key inside builder_test.go (the test cases map entry and any lookups/assertions)
to use the new PascalCase name.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 89a04c5c-8ca1-44c4-ab0b-02e8246b30d5

📥 Commits

Reviewing files that changed from the base of the PR and between 0beea8e and a7c0393.

📒 Files selected for processing (2)
  • pkg/types/builder_test.go
  • pkg/types/field.go

@Upbound-CLA

Upbound-CLA commented Jun 2, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Upbound-CLA

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@jonasz-lasut

Copy link
Copy Markdown
Collaborator

Hi @fernandezcuesta I've tested your upjet fork against provider-upjet-azure and noticed a side affect which was most likely not planned - x-kubernetes-list-type: map and injected key defaults were removed from the observation which is a viable solution to issues related to observations defaulting injected key multiple times but x-kubernetes-list-type: set and x-kubernetes-map-type: granular markers were also removed which introduces possible regressions and does not solve any existing issue like the one related to injected keys.

Would you be open to implementing a filter so that only the fields related to the injected key behavior are removed from observation? So default: nil + removal of x-kubernetes-list-type: map as it requires now non-existing required/defaulting field

@fernandezcuesta

fernandezcuesta commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

Hi @jonasz-lasut, I thought a bit about that when first implementing this PR, then decided to be pragmatic and remove all observation markers. The reasoning supporting it is that we don't do SSA patch operations (honoring SSA merge markers) on .status field. See https://github.com/crossplane/crossplane-runtime/blob/main/pkg/reconciler/managed/reconciler.go#L1005 where calling Status().Update() effectively does a classic PUT in /status, not an SSA patch operation.

Having said that, if you still prefer to go fine-grained and only remove those markers, I'm completely fine too (we would avoid unnecessary CRD changes).

@jonasz-lasut

Copy link
Copy Markdown
Collaborator

Thank you for having a look @fernandezcuesta . My main goal was to avoid unnecessary CRD changes as it would lead to 1000+ file diffs in major cloud providers without any visible benefit at this moment. However I completely agree with the PUT on .status reasoning

@fernandezcuesta

Copy link
Copy Markdown
Contributor Author

OK let's be minimally intrusive by now and do a surgical removal as you suggest, idk if at some point the behavior will change from crossplane-runtime, but going too broad would indeed break it. I'll amend it during the day.

Signed-off-by: Jesús Fernández <7312236+fernandezcuesta@users.noreply.github.com>
@jonasz-lasut

Copy link
Copy Markdown
Collaborator

Thank you for pushing the change, I'll try to test it with Azure ApplicationGateway today or tomorrow

@jonasz-lasut jonasz-lasut left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tested it with provider-upjet-azure and ApplicationGateway which ahd a long standing bug (linked to this issue already).
Following resources were used for the test, first with provider-azure in version 2.6.0 where Observe was failing and with provider built based on this upjet diff.

# SPDX-FileCopyrightText: 2024 The Crossplane Authors <https://crossplane.io>
#
# SPDX-License-Identifier: Apache-2.0

apiVersion: network.azure.m.upbound.io/v1beta1
kind: ApplicationGateway
metadata:
  annotations:
    meta.upbound.io/example-id: network/v1beta2/applicationgateway
    uptest.upbound.io/timeout: "7200"
  labels:
    testing.upbound.io/example-name: network
  name: example
  namespace: upbound-system
spec:
  forProvider:
    backendAddressPool:
      - name: example
    backendHttpSettings:
      - cookieBasedAffinity: Disabled
        name: example
        path: /path1/
        port: 80
        protocol: Http
        requestTimeout: 60
    frontendIpConfiguration:
      - name: example
        index: index1
        publicIpAddressIdSelector:
          matchLabels:
            testing.upbound.io/example-name: example
      - name: example2
        index: index2
        publicIpAddressIdSelector:
          matchLabels:
            testing.upbound.io/example-name: example2
    frontendPort:
      - name: example
        port: 80
    gatewayIpConfiguration:
      - name: my-gateway-ip-configuration
        subnetIdSelector:
          matchLabels:
            testing.upbound.io/example-name: frontend
    httpListener:
      - frontendIpConfigurationName: example
        frontendPortName: example
        name: example
        protocol: Http
    location: West Europe
    requestRoutingRule:
      - backendAddressPoolName: example
        backendHttpSettingsName: example
        httpListenerName: example
        name: example
        priority: 9
        ruleType: Basic
    resourceGroupNameSelector:
      matchLabels:
        testing.upbound.io/example-name: example
    sku:
      capacity: 2
      name: Standard_v2
      tier: Standard_v2
---
apiVersion: network.azure.m.upbound.io/v1beta1
kind: PublicIP
metadata:
  annotations:
    meta.upbound.io/example-id: network/v1beta2/applicationgateway
  labels:
    testing.upbound.io/example-name: example
  name: example
  namespace: upbound-system
spec:
  forProvider:
    allocationMethod: Static
    location: West Europe
    resourceGroupNameSelector:
      matchLabels:
        testing.upbound.io/example-name: example
    sku: Standard
---
apiVersion: network.azure.m.upbound.io/v1beta1
kind: PublicIP
metadata:
  annotations:
    meta.upbound.io/example-id: network/v1beta2/applicationgateway
  labels:
    testing.upbound.io/example-name: example2
  name: example2
  namespace: upbound-system
spec:
  forProvider:
    allocationMethod: Static
    location: West Europe
    resourceGroupNameSelector:
      matchLabels:
        testing.upbound.io/example-name: example
    ipVersion: IPv6
    sku: Standard
---
apiVersion: network.azure.m.upbound.io/v1beta1
kind: Subnet
metadata:
  annotations:
    meta.upbound.io/example-id: network/v1beta2/applicationgateway
  labels:
    testing.upbound.io/example-name: frontend
  name: frontend
  namespace: upbound-system
spec:
  forProvider:
    addressPrefixes:
      - 10.254.0.0/24
      - 2001:db8:1234:5601::/64
    resourceGroupNameSelector:
      matchLabels:
        testing.upbound.io/example-name: example
    virtualNetworkNameSelector:
      matchLabels:
        testing.upbound.io/example-name: example
---
apiVersion: network.azure.m.upbound.io/v1beta1
kind: VirtualNetwork
metadata:
  annotations:
    meta.upbound.io/example-id: network/v1beta2/applicationgateway
  labels:
    testing.upbound.io/example-name: example
  name: example
  namespace: upbound-system
spec:
  forProvider:
    addressSpace:
      - 10.254.0.0/16
      - 2001:db8:1234:5601::/64
    location: West Europe
    resourceGroupNameSelector:
      matchLabels:
        testing.upbound.io/example-name: example
---
apiVersion: azure.m.upbound.io/v1beta1
kind: ResourceGroup
metadata:
  annotations:
    meta.upbound.io/example-id: network/v1beta1/applicationgateway
  labels:
    testing.upbound.io/example-name: example
  name: example
  namespace: upbound-system
spec:
  forProvider:
    location: West Europe

@jonasz-lasut

Copy link
Copy Markdown
Collaborator

Thank you for your contribution @fernandezcuesta , I'll discuss this PR with the rest of maintainers on Monday but from my perspective it's ok to merge

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSA markers fails on Observation for multi-item lists

3 participants