package state import ( "encoding/json" "fmt" "os" "path/filepath" "time" ) const ( IntentNormal = "normal" IntentStartupInProgress = "startup_in_progress" IntentShuttingDown = "shutting_down" IntentShutdownComplete = "shutdown_complete" ) type Intent struct { State string `json:"state"` Reason string `json:"reason,omitempty"` Source string `json:"source,omitempty"` UpdatedAt time.Time `json:"updated_at"` } func ReadIntent(path string) (Intent, error) { b, err := os.ReadFile(path) if err != nil { if os.IsNotExist(err) { return Intent{}, nil } return Intent{}, err } if len(b) == 0 { return Intent{}, nil } var in Intent if err := json.Unmarshal(b, &in); err != nil { return Intent{}, err } return in, nil } func WriteIntent(path string, in Intent) error { if in.UpdatedAt.IsZero() { in.UpdatedAt = time.Now().UTC() } if err := os.MkdirAll(filepath.Dir(path), 0o750); err != nil { return err } b, err := json.MarshalIndent(in, "", " ") if err != nil { return err } return os.WriteFile(path, b, 0o640) } func MustWriteIntent(path string, state string, reason string, source string) error { switch state { case IntentNormal, IntentStartupInProgress, IntentShuttingDown, IntentShutdownComplete: default: return fmt.Errorf("invalid intent state: %s", state) } return WriteIntent(path, Intent{ State: state, Reason: reason, Source: source, UpdatedAt: time.Now().UTC(), }) }