package statemachine import ( "fmt" "provisioning/internal/model" ) type Trigger string const ( TriggerRebuildRequested Trigger = "RebuildRequested" TriggerPXEScriptServed Trigger = "PXEScriptServed" TriggerAnswerServed Trigger = "AnswerServed" TriggerInstallWebhook Trigger = "InstallWebhook" TriggerPhoneHome Trigger = "PhoneHome" TriggerClusterJoinStart Trigger = "ClusterJoinStarted" TriggerJoinComplete Trigger = "JoinComplete" TriggerFailed Trigger = "Failed" ) type transition struct { from []model.HostState to model.HostState } var allActiveStates = []model.HostState{ model.StatePXEReady, model.StatePXEBooted, model.StateInstalling, model.StateInstalled, model.StateFirstBoot, model.StateJoining, } var table = map[Trigger]transition{ TriggerRebuildRequested: { from: []model.HostState{model.StateRegistered, model.StateReady, model.StateFailed}, to: model.StatePXEReady, }, TriggerPXEScriptServed: { from: []model.HostState{model.StatePXEReady}, to: model.StatePXEBooted, }, TriggerAnswerServed: { from: []model.HostState{model.StatePXEBooted}, to: model.StateInstalling, }, TriggerInstallWebhook: { from: []model.HostState{model.StateInstalling}, to: model.StateInstalled, }, TriggerPhoneHome: { from: []model.HostState{model.StateInstalled}, to: model.StateFirstBoot, }, TriggerClusterJoinStart: { from: []model.HostState{model.StateFirstBoot}, to: model.StateJoining, }, TriggerJoinComplete: { from: []model.HostState{model.StateJoining}, to: model.StateReady, }, TriggerFailed: { from: allActiveStates, to: model.StateFailed, }, } func Next(current model.HostState, t Trigger) (model.HostState, error) { tr, ok := table[t] if !ok { return "", fmt.Errorf("unknown trigger %q", t) } for _, s := range tr.from { if s == current { return tr.to, nil } } return "", fmt.Errorf("trigger %q not allowed from state %q", t, current) }