package host import ( "errors" "github.com/carlosframework/platform/internal/hostbox" "github.com/carlosframework/platform/internal/registry" "github.com/carlosframework/platform/internal/schedule" "os" ) func (h ClaimRootHTTP) verifyTimerMutationRow(host string, owner registry.ClaimOwnership, e hostbox.StopInventoryEntry, m *hostbox.TimerMutation) error { if m == nil || e.RelativePath != m.Timer.Host+"/"+m.Timer.Name { return h.verifyInventoryTimer(host, owner, e) } t := m.Timer if t.Host != host || !schedule.ValidName(t.Name) || !t.ClaimOwnership.Valid() || t.ClaimIncarnation != owner.ClaimIncarnation || t.ClaimStamp != owner.ClaimStamp || t.ClaimOwner != owner.ClaimOwner || t.ClaimRowID != t.Registration || t.Registration == "" || e.Kind != "timer" || e.ManagedRoot != "registry" || e.Ownership != owner.ClaimOwner || e.RowIdentity != t.Registration || e.Materialization != "materialized" || e.TimerRetired != m.Remove || e.Device != 0 || e.Inode != 0 || e.Type != 0 { return hostbox.ErrTypedInventory } if t.Kind != schedule.KindOnce && t.Kind != schedule.KindSchedule { return hostbox.ErrTypedInventory } if schedule.ValidPath(t.Path) != nil { return hostbox.ErrTypedInventory } row, err := h.Reconcile.Registry.GetTimer(host, t.Name) if errors.Is(err, os.ErrNotExist) { if m.Expected == "" || m.Remove { return nil } return hostbox.ErrChanged } if err != nil { return err } if row == nil || row.ClaimIncarnation != t.ClaimIncarnation || row.ClaimStamp != t.ClaimStamp || row.ClaimOwner != t.ClaimOwner || row.ClaimRowID != row.Registration || row.Kind != t.Kind { return hostbox.ErrChanged } if *row == t || row.Registration == m.Expected { return nil } return hostbox.ErrChanged } func (h ClaimRootHTTP) verifyTimerMutation(prior, next hostbox.StopInventory, m *hostbox.TimerMutation) error { if m == nil { return h.verifyNewTimerIntentions(prior, next) } var old, entry *hostbox.StopInventoryEntry name := m.Timer.Host + "/" + m.Timer.Name for i := range prior.Entries { e := &prior.Entries[i] if e.Kind == "timer" && e.RelativePath == name { if old != nil { return hostbox.ErrTypedInventory } old = e } } for i := range next.Entries { e := &next.Entries[i] if e.Kind == "timer" && e.RelativePath == name { if entry != nil { return hostbox.ErrTypedInventory } entry = e } } if entry == nil { return hostbox.ErrTypedInventory } if old == nil || old.TimerRetired { if m.Expected != "" || m.Remove { return hostbox.ErrChanged } } else if old.RowIdentity != m.Expected { return hostbox.ErrChanged } if old != nil && (old.ArtifactID != entry.ArtifactID || old.Ownership != entry.Ownership || old.ManagedRoot != entry.ManagedRoot) { return hostbox.ErrChanged } if m.Remove && (old == nil || old.RowIdentity != entry.RowIdentity) { return hostbox.ErrChanged } if !m.Remove && m.Expected != "" && m.Expected == entry.RowIdentity { return hostbox.ErrChanged } // Check every other new entry through the ordinary intention rules. filtered := next filtered.Entries = nil for _, e := range next.Entries { if e.RelativePath != name || e.Kind != "timer" { filtered.Entries = append(filtered.Entries, e) } } return h.verifyNewTimerIntentions(prior, filtered) } func (h ClaimRootHTTP) applyTimerMutation(m hostbox.TimerMutation) error { if m.Remove { err := h.Reconcile.Registry.DeleteTimerOwnedRegistration(m.Timer) if errors.Is(err, registry.ErrTimerChanged) { _, err = h.Reconcile.Registry.GetTimer(m.Timer.Host, m.Timer.Name) if errors.Is(err, os.ErrNotExist) { return nil } if err == nil { return hostbox.ErrChanged } } return err } _, err := h.Reconcile.Registry.MaterializeTimerRegistration(m.Timer, m.Expected) return err }