add IgnoreIfAbsent for optional read-only resources#120
Open
sourcehawk wants to merge 7 commits into
Open
Conversation
Captures the agreed API, build-time validation rules (including tightening BlockOnAbsence to require ReadOnly), runtime behavior, and test coverage for adding a third NotFound mode that lets read-only resources be genuinely optional. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bite-sized task breakdown with exact file paths, code, and test cases for the IgnoreIfAbsent feature. Five tasks: field wiring, build validation, runtime branch, docs, full verification. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the field, builder method, and Build() passthrough. Build-time validation and runtime behavior land in follow-up commits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ResourceOptionsBuilder.Build() now returns an error when: - IgnoreIfAbsent is set without ReadOnly. - BlockOnAbsence is set without ReadOnly (previously a silent no-op). - BlockOnAbsence and IgnoreIfAbsent are both set. The BlockOnAbsence ReadOnly requirement is a tightening of existing behavior. Setting the flag on a managed resource was always a misconfiguration; surfacing it at Build is an improvement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extends the NotFound branch in reconcileResources to a switch over the two absence flags. IgnoreIfAbsent continues the loop without appending a condition entry or invoking the data extractor; BlockOnAbsence keeps its existing guard-blocked short-circuit behavior. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds rows for ReadOnly+IgnoreIfAbsent and the IgnoreIfAbsent() builder method to docs/component.md. Updates the BlockOnAbsence() method row to state that it now requires ReadOnly and is mutually exclusive with IgnoreIfAbsent. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings the IgnoreIfAbsent spec and implementation plan into the project's canonical markdown formatting; cosmetic only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a third NotFound-handling mode for read-only resources (IgnoreIfAbsent) so optional external resources can be referenced without failing or blocking reconciliation, and tightens builder validation around absence-related flags.
Changes:
- Adds
ResourceOptions.IgnoreIfAbsent+ResourceOptionsBuilder.IgnoreIfAbsent()and build-time validation (mutual exclusion withBlockOnAbsence, both requireReadOnly). - Extends
reconcileResourcesNotFound handling for read-only reads tocontinuewhenIgnoreIfAbsentis set. - Updates unit tests and documentation/spec/plan to cover and describe the new behavior and the
BlockOnAbsencetightening.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/component/resource_options_builder.go | Adds IgnoreIfAbsent flag, builder method, and Build-time validation |
| pkg/component/resource_options_builder_test.go | Adds happy-path + validation error tests for new options |
| pkg/component/create.go | Updates NotFound behavior in reconcileResources for IgnoreIfAbsent/BlockOnAbsence |
| pkg/component/create_test.go | Adds reconcileResources tests for IgnoreIfAbsent semantics |
| pkg/component/builder.go | Extends ResourceOptions with IgnoreIfAbsent and updates GoDoc |
| docs/component.md | Documents IgnoreIfAbsent option and builder method; updates BlockOnAbsence row |
| docs/superpowers/specs/2026-05-26-ignore-if-absent-design.md | Design spec for IgnoreIfAbsent semantics |
| docs/superpowers/plans/2026-05-26-ignore-if-absent.md | Implementation plan for the change |
Comment on lines
+132
to
+146
| if b.blockOnAbsence && b.ignoreIfAbsent { | ||
| return ResourceOptions{}, fmt.Errorf( | ||
| "BlockOnAbsence and IgnoreIfAbsent are mutually exclusive", | ||
| ) | ||
| } | ||
| if b.blockOnAbsence && !b.readOnly { | ||
| return ResourceOptions{}, fmt.Errorf( | ||
| "BlockOnAbsence requires ReadOnly", | ||
| ) | ||
| } | ||
| if b.ignoreIfAbsent && !b.readOnly { | ||
| return ResourceOptions{}, fmt.Errorf( | ||
| "IgnoreIfAbsent requires ReadOnly", | ||
| ) | ||
| } |
Comment on lines
210
to
+216
| if err != nil { | ||
| if entry.Options.ReadOnly && entry.Options.BlockOnAbsence && apierrors.IsNotFound(err) { | ||
| results = append(results, reconcileResult{ | ||
| Entry: entry, | ||
| Status: convergingStatusWithReason{ | ||
| Status: convergingStatusGuardBlocked, | ||
| Reason: fmt.Sprintf("waiting for %s", resource.Identity()), | ||
| }, | ||
| }) | ||
| return results, nil | ||
| if entry.Options.ReadOnly && apierrors.IsNotFound(err) { | ||
| switch { | ||
| case entry.Options.IgnoreIfAbsent: | ||
| continue | ||
| case entry.Options.BlockOnAbsence: | ||
| results = append(results, reconcileResult{ |
Comment on lines
+1
to
+4
| # IgnoreIfAbsent for read-only resources | ||
|
|
||
| Status: design approved, pending implementation plan Date: 2026-05-26 | ||
|
|
| - `docs/component.md` — add table rows for `IgnoreIfAbsent()` and update the `BlockOnAbsence()` row to reflect the | ||
| tightened ReadOnly requirement. | ||
|
|
||
| No new files. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a third NotFound mode for read-only resources:
IgnoreIfAbsent. When the cluster reports the resource is missing, the framework silently skips the entry and continues reconciliation — no condition recorded, no observation, no data extractor invocation. Fills the gap between plainReadOnly()(errors on absence) andBlockOnAbsence()(waits for it).ResourceOptions.IgnoreIfAbsentfield andResourceOptionsBuilder.IgnoreIfAbsent()method.IgnoreIfAbsentrequiresReadOnly, is mutually exclusive withBlockOnAbsence.BlockOnAbsence()withoutReadOnly()is now a Build error (previously a silent no-op). Misconfiguration that was always meaningless is now caught at construction.Design spec:
docs/superpowers/specs/2026-05-26-ignore-if-absent-design.md.Test Plan
make allclean (tests + lint + format)pkg/component/resource_options_builder_test.gocover all three Build-error cases plus the happy-path table entries.TestReconcileResources_IgnoreIfAbsentinpkg/component/create_test.gomirrors theBlockOnAbsencetest shape: silent skip on absence, subsequent resources still reconcile, defaultReadOnlystill errors on absence.TestReconcileResources_BlockOnAbsencecontinues to pass against the refactoredswitchbranch.BlockOnAbsencetightening is acceptable (small behavior change called out in release notes).🤖 Generated with Claude Code