package hostguard import ( "bytes" "context" "github.com/carlosframework/platform/internal/hostclaim" ) func (g Guard) RebindRootInventory(ctx context.Context, prior Captured, revision uint64, next RootInstallation, intent []byte, check func(*hostclaim.Claim) error, commit func() error) error { if g.Root == nil || check == nil || commit == nil || len(intent) == 0 || prior.Incarnation != next.Incarnation || prior.Stamp == 0 || next.Stamp <= prior.Stamp || revision == 0 || next.InventoryRevision == 0 { return ErrInvalidInput } return g.locked(ctx, next.Host, func(d *recordDir) error { c, err := g.fresh(ctx, next.Host) if err != nil { return err } if err = check(c); err != nil { return err } if c.Holder.Incarnation != next.Incarnation || c.Holder.Stamp != next.Stamp || c.Holder.Account != next.Account || c.Holder.App != next.App { return ErrClaimIncarnation } r, err := d.read(next.Host) if err != nil { return err } if r.barrier != nil { return ErrFenced } want := Captured{Incarnation: next.Incarnation, Stamp: next.Stamp} for _, denied := range r.rootRetired { if denied == want { return ErrRetiredStamp } } if r.ActiveFence != nil && r.ActiveFence.matchesSession(c, want) { return ErrFenced } for _, receipt := range r.FenceJournal { if receipt.Target.matchesSession(c, want) { return ErrFenced } } next.Artifacts = r.installation.Artifacts if r.installation == next && r.pendingInstallation == nil && bytes.Equal(r.rebindCommit, intent) { return d.sync(next.Host) } old := r.installation if r.Incarnation != prior.Incarnation || r.ActiveStamp != prior.Stamp || old.InventoryRevision != revision || old.Empty || old.Account != next.Account || old.App != next.App || old.Record != next.Record || old.Box != next.Box || old.Enrollment != next.Enrollment || old.Migration != next.Migration { return ErrRecordIncarnation } if r.pendingInstallation != nil && (*r.pendingInstallation != next || !bytes.Equal(r.pendingInventory, intent)) { return ErrFenced } r.pendingInventory = append([]byte(nil), intent...) r.pendingInstallation = &next if err = d.write(r); err != nil { return err } c, err = g.fresh(ctx, next.Host) if err != nil { return err } if err = check(c); err != nil { return err } if err = commit(); err != nil { return err } r.retire() r.Incarnation, r.ActiveStamp, r.installation = next.Incarnation, next.Stamp, next r.pendingInventory, r.pendingInstallation = nil, nil r.quarantined, r.settled = false, false r.rebindCommit = append([]byte(nil), intent...) return d.write(r) }) }