Skip to content

add IgnoreIfAbsent for optional read-only resources#120

Open
sourcehawk wants to merge 7 commits into
mainfrom
feat/ignore-if-absent
Open

add IgnoreIfAbsent for optional read-only resources#120
sourcehawk wants to merge 7 commits into
mainfrom
feat/ignore-if-absent

Conversation

@sourcehawk
Copy link
Copy Markdown
Owner

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 plain ReadOnly() (errors on absence) and BlockOnAbsence() (waits for it).

  • New ResourceOptions.IgnoreIfAbsent field and ResourceOptionsBuilder.IgnoreIfAbsent() method.
  • Build-time validation: IgnoreIfAbsent requires ReadOnly, is mutually exclusive with BlockOnAbsence.
  • Behavior tightening: BlockOnAbsence() without ReadOnly() 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 all clean (tests + lint + format)
  • New unit tests in pkg/component/resource_options_builder_test.go cover all three Build-error cases plus the happy-path table entries.
  • New TestReconcileResources_IgnoreIfAbsent in pkg/component/create_test.go mirrors the BlockOnAbsence test shape: silent skip on absence, subsequent resources still reconcile, default ReadOnly still errors on absence.
  • Existing TestReconcileResources_BlockOnAbsence continues to pass against the refactored switch branch.
  • Reviewer to confirm the BlockOnAbsence tightening is acceptable (small behavior change called out in release notes).

🤖 Generated with Claude Code

sourcehawk and others added 7 commits May 26, 2026 01:09
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>
Copilot AI review requested due to automatic review settings May 26, 2026 00:38
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 with BlockOnAbsence, both require ReadOnly).
  • Extends reconcileResources NotFound handling for read-only reads to continue when IgnoreIfAbsent is set.
  • Updates unit tests and documentation/spec/plan to cover and describe the new behavior and the BlockOnAbsence tightening.

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 thread pkg/component/create.go
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.
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.

2 participants