package hostbox import ( "context" "encoding/json" "github.com/carlosframework/platform/internal/hostguard" "github.com/carlosframework/platform/internal/registry" ) type InventoryExpectation struct { Revision uint64 RecordKey, RecordETag string Target hostguard.FenceTarget } func (d *StopInventoryDB) Snapshot(ctx context.Context, host string, captured hostguard.Captured) (StopInventory, uint64, error) { if d == nil { return StopInventory{}, 0, ErrUnsupported } target := hostguard.FenceTarget{Host: host, Incarnation: captured.Incarnation, Stamp: captured.Stamp} var out JournalResponse var err error if d.remote != nil { out, err = journalCall(ctx, d.remote, JournalRequest{Op: "inventory-version", Target: target}) } else { out, err = d.inventoryVersion(ctx, target) } return out.Inventory, out.Revision, err } type TimerMutation struct { Timer registry.Timer Expected string Remove bool } func (d *StopInventoryDB) WriteTimerExpected(ctx context.Context, in StopInventory, expected InventoryExpectation, timer TimerMutation) (uint64, error) { return d.writeExpected(ctx, in, expected, &timer) } func (d *StopInventoryDB) WriteExpected(ctx context.Context, in StopInventory, expected InventoryExpectation) (uint64, error) { return d.writeExpected(ctx, in, expected, nil) } func (d *StopInventoryDB) writeExpected(ctx context.Context, in StopInventory, expected InventoryExpectation, timer *TimerMutation) (uint64, error) { if d == nil || d.remote == nil || expected.Target.Host != in.Host || expected.Target.Incarnation != in.Incarnation || expected.Target.Stamp != in.InstallationStamp { return 0, ErrTypedInventory } out, err := journalCall(ctx, d.remote, JournalRequest{Timer: timer, Op: "inventory-write", Inventory: in, Revision: expected.Revision, Target: expected.Target, RecordKey: expected.RecordKey, RecordETag: expected.RecordETag}) if err != nil { return 0, err } if out.Revision != expected.Revision+1 { return 0, ErrChanged } return out.Revision, nil } func (d *StopInventoryDB) Remote() bool { return d != nil && d.remote != nil } func (d *StopInventoryDB) SnapshotRequest(ctx context.Context, target hostguard.FenceTarget) (JournalResponse, error) { if d == nil { return JournalResponse{}, ErrUnsupported } if d.remote != nil { return journalCall(ctx, d.remote, JournalRequest{Op: "inventory-version", Target: target}) } return d.inventoryVersion(ctx, target) } func (m TimerMutation) MarshalJSON() ([]byte, error) { type wire TimerMutation return json.Marshal(struct { wire Registration string }{wire(m), m.Timer.Registration}) } func (m *TimerMutation) UnmarshalJSON(raw []byte) error { type wire TimerMutation var v struct { wire Registration string } if err := json.Unmarshal(raw, &v); err != nil { return err } *m = TimerMutation(v.wire) m.Timer.Registration = v.Registration return nil }