Skip to content

Add state machine for image switch (milestone 4c)#50

Open
alicefr wants to merge 7 commits into
bootc-dev:mainfrom
alicefr:milestone-4c
Open

Add state machine for image switch (milestone 4c)#50
alicefr wants to merge 7 commits into
bootc-dev:mainfrom
alicefr:milestone-4c

Conversation

@alicefr

@alicefr alicefr commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Implements the daemon-side state machine that detects image mismatches between spec.desiredImage and the booted image,
stages updates via bootc switch in a background goroutine, and triggers reboot when desiredImageState == Booted.

  • Add Switch(ctx, image, apply) to the Executor interface
  • Rewrite the reconciler with async staging, cancel-on-spec-change, and single-patch-per-reconcile
  • Background goroutine signals completion via source.Channel, letting the reconcile loop handle all status updates through
    one path
  • Apply operations (reboot) are never cancelled — the daemon restarts after reboot and reconciles fresh

@alicefr

alicefr commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator Author

@jlebon I skipped the e2e test since we still need to define how to test the upgrade. The state machine is only checked by the env tests for now

@alicefr alicefr marked this pull request as draft June 3, 2026 09:52
@alicefr alicefr marked this pull request as ready for review June 3, 2026 11:50
Comment thread internal/daemon/fake_test.go Outdated
Comment thread internal/daemon/reconciler.go Outdated
Comment thread internal/daemon/reconciler.go
Comment thread internal/daemon/reconciler.go Outdated

mu sync.Mutex
switchImage string
switchApply bool

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.

I think we discussed this at some point. My inclination is to not try to optimize this. I.e. let's not support an --apply special-case at all. We just do the bootc switch and then use the GenericEvent to immediately do another reconcile if desiredImageState is booted.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

To clarify, --apply is not used during staging, we always stage with plain bootc switch . The --apply is only used in the reboot step: when the image is already staged and desiredImageState is Booted, we run bootc switch --apply to boot into it.

Are you suggesting we should decouple this further and trigger the reboot through a different mechanism (e.g. systemctl reboot) instead of bootc switch --apply?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Sorry, this is wrong bootc switch --apply doesn't reboot, but it is instead bootc upgrade --apply, the right command

Comment thread internal/daemon/reconciler.go Outdated
Comment thread internal/daemon/reconciler.go Outdated
Comment thread internal/bootc/executor.go Outdated
Comment thread internal/daemon/reconciler.go Outdated
Comment thread internal/daemon/reconciler.go Outdated
Comment thread internal/daemon/reconciler_test.go Outdated
@alicefr alicefr force-pushed the milestone-4c branch 4 times, most recently from 7e1ff20 to 2afd447 Compare June 10, 2026 12:36
@alicefr alicefr marked this pull request as draft June 11, 2026 13:49
@alicefr

alicefr commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

There are still some issue with this PR... investigating.

@alicefr alicefr force-pushed the milestone-4c branch 2 times, most recently from 56119dc to ba87f0d Compare June 11, 2026 14:21
@alicefr alicefr marked this pull request as ready for review June 11, 2026 15:14
@alicefr

alicefr commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator Author

I think we should prioritize #57 and implement at least the happy path test for the reboot

@alicefr alicefr force-pushed the milestone-4c branch 2 times, most recently from e4557ce to 413cf0d Compare June 12, 2026 11:47
alicefr added 7 commits June 12, 2026 11:45
Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alice Frosi <afrosi@redhat.com>
Rewrite the reconciler to detect image mismatches between
spec.desiredImage and the booted image, stage via bootc switch in a
background goroutine.

Once, it finished to staged the image, the termination of the
goroutine triggers once more the reconciliation loop which will detect
that the system requires a reboot.

The reconciliation function ensures that the bootc node transitions from
Staging to Staged, and then to Rebooting.

Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alice Frosi <afrosi@redhat.com>
Replace raw JSON bytes with a bootc.Status struct in the test fake.
Status() serializes the struct via json.Marshal, and Switch()
auto-mutates the status (staging sets Staged). Upgrade() records the
call for test assertions.

Add newBootcStatus() and newBootEntry() helpers to build test state
without verbose JSON constants.

Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alice Frosi <afrosi@redhat.com>
Add envtest cases for the daemon reconciler state machine:

- TestStagingTriggered: image mismatch triggers bootc switch
- TestStagingError: switch failure sets Degraded condition
- TestAlreadyStaged: skip switch when image already staged
- TestRebootingSet: reboot triggered when desiredImageState is Booted
- TestRollback: restage when desired image changes
- TestCancelInflightSwitch: spec change cancels in-flight switch

Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Alice Frosi <afrosi@redhat.com>
Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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