diff options
| author | Claude <noreply@anthropic.com> | 2026-08-07 00:03:04 -0500 |
|---|---|---|
| committer | Claude <noreply@anthropic.com> | 2026-08-07 00:03:04 -0500 |
| commit | d1e1c226d9a63432c652d373c039a3ae4430f3a2 (patch) | |
| tree | 79b72917b757f6807c1beb9872efc2ea694cce6d /internal/zfsutil | |
| parent | f34ba20fc566ab861179a8ac2fd55eaabbc6a327 (diff) | |
Guard deploys and config changes against leftover state on retry
- Extract deploy.Run's snapshot -> apply -> restart -> health-check ->
rollback-on-failure sequence into deploy.GuardedApply, shared with
cmd/skiff's applyConfigChange, which duplicated it verbatim.
- Clean up the worktree and snapshot a deploy creates when it fails
before cutover (e.g. a failing release-phase migration), so retrying
the same sha no longer needs manual cleanup.
- Make checkout and snapshotting idempotent for a same-sha retry after
a cutover that later got rolled back on a failed health check, where
the release dir and snapshot are deliberately left behind by design.
- Document the actual cause of a jail not surviving a host reboot:
FreeBSD ships no /etc/jail.conf, so boot-time `service jail start`
finds nothing to start regardless of jail.conf.d - only name-targeted
starts read jail.conf.d directly, which is why manual starts worked.
Diffstat (limited to 'internal/zfsutil')
| -rw-r--r-- | internal/zfsutil/zfsutil.go | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/internal/zfsutil/zfsutil.go b/internal/zfsutil/zfsutil.go index 8f1b0e2..918289c 100644 --- a/internal/zfsutil/zfsutil.go +++ b/internal/zfsutil/zfsutil.go @@ -33,6 +33,14 @@ func Rollback(ctx context.Context, out io.Writer, dataset, tag string) error { return sh.Run(ctx, out, "", "zfs", "rollback", "-r", snapRef(dataset, tag)) } +// DestroySnapshot removes a snapshot that was never needed as a rollback +// target - e.g. one taken right before an apply step that failed before +// anything actually changed. Left behind, it collides with the same tag on +// the next retry. +func DestroySnapshot(ctx context.Context, out io.Writer, dataset, tag string) error { + return sh.Run(ctx, out, "", "zfs", "destroy", snapRef(dataset, tag)) +} + // Snapshots lists snapshot names (without the dataset@ prefix), newest last. func Snapshots(ctx context.Context, dataset string) ([]string, error) { raw, err := sh.Output(ctx, "", "zfs", "list", "-H", "-t", "snapshot", "-o", "name", "-s", "creation", "-r", dataset) |
