ananke/internal/state/intent.go

70 lines
1.5 KiB
Go
Raw Normal View History

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(),
})
}