test(e2e): add composed resource observation test (#6788)#7360
test(e2e): add composed resource observation test (#6788)#7360boxcee-interview wants to merge 2 commits into
Conversation
Add an e2e test that verifies composed resource changes are detected and reflected in XR status within a tight timeout. The test: - Creates a ConfigMap with initial data - Creates an XR that observes the ConfigMap via function-python - Verifies the initial observation is reflected in XR status - Modifies the ConfigMap directly using Server-Side Apply - Verifies the XR status reflects the change within 30 seconds Closes crossplane#6788 Signed-off-by: Moritz Schmitz von Hülst <[email protected]>
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThis PR adds a comprehensive end-to-end test (TestComposedResourceObservation) that validates realtime composition observation for namespaced composite resources. The test creates a schema, function, composition, and resource instance to verify that composed resource changes propagate to XR status within tight timeouts. ChangesComposed Resource Observation E2E Test
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
test/e2e/apiextensions_compositions_test.go (2)
542-562: ⚡ Quick winSame
t.Errorf→t.Fatalfconcern applies here; also, the modify patch drops theapp: crossplane-e2elabel.Two small points:
t.Errorf+return ctx(line 556) shares the same concern as the setup step — downstream assertions become noisy.t.Fatalfis cleaner.- The creation patch (line 517) sets
labels: {app: crossplane-e2e}. The modify patch here omits labels entirely. Because both patches are under the sameFieldOwner, SSA will relinquish ownership of theapplabel and it will be removed. This is harmless for the test's purpose, but worth knowing — could you confirm this is intentional?🛠️ Proposed fix for t.Fatalf
- if err := cfg.Client().Resources().GetControllerRuntimeClient().Patch(ctx, cm, client.Apply, client.FieldOwner(FieldManager), client.ForceOwnership); err != nil { - t.Errorf("failed to modify ConfigMap: %v", err) - return ctx - } + if err := cfg.Client().Resources().GetControllerRuntimeClient().Patch(ctx, cm, client.Apply, client.FieldOwner(FieldManager), client.ForceOwnership); err != nil { + t.Fatalf("failed to modify ConfigMap: %v", err) + }🤖 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 `@test/e2e/apiextensions_compositions_test.go` around lines 542 - 562, In the Assess "ModifyConfigMapDirectly" closure, replace the t.Errorf call that returns ctx with t.Fatalf to stop the test on patch failure (change the error path in the closure using t.Fatalf). Also ensure the patch preserves the app label so SSA doesn't remove it: when building the unstructured cm before calling cfg.Client().Resources().GetControllerRuntimeClient().Patch(..., client.Apply, client.FieldOwner(FieldManager), ...), set metadata.labels.app="crossplane-e2e" (or fetch the existing resource first and modify only data.message) so the FieldManager/Apply call does not drop the label; confirm if removing the label was intentional and keep the label-preserving approach if not.
509-528: ⚡ Quick winConsider using
t.Fatalfinstead oft.Errorfin the setup step.
t.Errorfmarks the test failed but execution continues, so all downstreamAssesssteps will also run (and likely fail with confusing errors) even though the ConfigMap was never created.t.Fatalfimmediately stops the goroutine and gives a cleaner failure signal. The existingModifyConfigMapDirectlystep at line 556 has the same pattern.Contrast this with
TestCircuitBreaker's inline step (line 387), which usest.Logfbecause failures there are non-critical; here the ConfigMap must exist for the test to make sense.🛠️ Proposed fix
- if err := cfg.Client().Resources().GetControllerRuntimeClient().Patch(ctx, cm, client.Apply, client.FieldOwner(FieldManager), client.ForceOwnership); err != nil { - t.Errorf("failed to create ConfigMap: %v", err) - return ctx - } + if err := cfg.Client().Resources().GetControllerRuntimeClient().Patch(ctx, cm, client.Apply, client.FieldOwner(FieldManager), client.ForceOwnership); err != nil { + t.Fatalf("failed to create ConfigMap: %v", err) + }🤖 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 `@test/e2e/apiextensions_compositions_test.go` around lines 509 - 528, Replace the non-fatal test failure in the setup step by calling t.Fatalf instead of t.Errorf inside the WithSetup("CreateConfigMap", func(ctx context.Context, t *testing.T, cfg *envconf.Config) ...) so the test goroutine stops immediately when the ConfigMap creation Patch fails; do the same change for the similar setup helper used by ModifyConfigMapDirectly so that creation failures abort the test rather than allowing downstream Assess steps to run.
🤖 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.
Inline comments:
In `@test/e2e/apiextensions_compositions_test.go`:
- Around line 536-538: The status schema in the CompositeResourceDefinition's
definition.yaml is missing the status.resourceReceived property so Kubernetes
prunes the field written by the composition (see composition.yaml usage); add
resourceReceived: type: boolean under status.properties in that definition.yaml
so status.resourceReceived is declared and persisted during reconciliation.
In
`@test/e2e/manifests/apiextensions/composition/composed-resource-observation/setup/composition.yaml`:
- Line 17: The YAML uses an invalid block scalar indicator "|\\" under the
script key which causes YAML parsers to fail; edit the composition.yaml entry
for the script key (the line starting with "script:") and remove the trailing
backslash so it reads "script: |" (i.e., replace "|\\" with a plain pipe),
preserving the existing indented block content below it.
---
Nitpick comments:
In `@test/e2e/apiextensions_compositions_test.go`:
- Around line 542-562: In the Assess "ModifyConfigMapDirectly" closure, replace
the t.Errorf call that returns ctx with t.Fatalf to stop the test on patch
failure (change the error path in the closure using t.Fatalf). Also ensure the
patch preserves the app label so SSA doesn't remove it: when building the
unstructured cm before calling
cfg.Client().Resources().GetControllerRuntimeClient().Patch(..., client.Apply,
client.FieldOwner(FieldManager), ...), set metadata.labels.app="crossplane-e2e"
(or fetch the existing resource first and modify only data.message) so the
FieldManager/Apply call does not drop the label; confirm if removing the label
was intentional and keep the label-preserving approach if not.
- Around line 509-528: Replace the non-fatal test failure in the setup step by
calling t.Fatalf instead of t.Errorf inside the WithSetup("CreateConfigMap",
func(ctx context.Context, t *testing.T, cfg *envconf.Config) ...) so the test
goroutine stops immediately when the ConfigMap creation Patch fails; do the same
change for the similar setup helper used by ModifyConfigMapDirectly so that
creation failures abort the test rather than allowing downstream Assess steps to
run.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 79709d10-fb60-41c8-9fce-7dd394d7c806
📒 Files selected for processing (5)
test/e2e/apiextensions_compositions_test.gotest/e2e/manifests/apiextensions/composition/composed-resource-observation/setup/composition.yamltest/e2e/manifests/apiextensions/composition/composed-resource-observation/setup/definition.yamltest/e2e/manifests/apiextensions/composition/composed-resource-observation/setup/functions.yamltest/e2e/manifests/apiextensions/composition/composed-resource-observation/xr.yaml
- Fix invalid YAML block scalar indicator (|\ -> |) in composition.yaml - Add resourceReceived status field to definition.yaml schema - Use t.Fatalf instead of t.Errorf in ConfigMap setup steps Signed-off-by: Moritz Schmitz von Hülst <[email protected]>
Closes #6788
What
Add an e2e test that verifies composed resource changes are detected and reflected in XR status within a tight timeout.
Why
Issue #6788 requested a test to verify that Crossplane detects changes to composed resources and reflects them in the XR status. This is important for testing the composition pipeline's observation mechanism.
How
The test uses function-python with
require_resourcesto observe a ConfigMap and write its data to the XR status:Testing
The test follows the existing e2e test patterns in
apiextensions_compositions_test.go, using the same setup/teardown structure asTestRequiredResourcesandTestCircuitBreaker.