Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/metal-api/internal/fsm/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ func Events() fsm.Events {
Src: []string{
states.PlannedReboot.String(),
states.PhonedHome.String(),
states.PXEBooting.String(),
states.Preparing.String(),
states.Registering.String(),
states.Waiting.String(),
},
Dst: SelfTransitionState,
},
Expand Down
69 changes: 64 additions & 5 deletions cmd/metal-api/internal/fsm/fsm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fsm
import (
"context"
"log/slog"
"os"
"testing"
"time"

Expand All @@ -13,7 +14,8 @@ import (
func TestHandleProvisioningEvent(t *testing.T) {
now := time.Now()
lastEventTime := now.Add(-time.Minute * 4)
exceedThresholdTime := now.Add(-time.Minute * 10)
exceedReclaimThresholdTime := now.Add(-time.Minute * 10)
exceedBufferedPhonedHomeThreshold := now.Add(-time.Minute * 10)
tests := []struct {
event *metal.ProvisioningEvent
container *metal.ProvisioningEventContainer
Expand Down Expand Up @@ -427,12 +429,12 @@ func TestHandleProvisioningEvent(t *testing.T) {
container: &metal.ProvisioningEventContainer{
Events: metal.ProvisioningEvents{
{
Time: exceedThresholdTime,
Time: exceedReclaimThresholdTime,
Event: metal.ProvisioningEventMachineReclaim,
},
},
Liveliness: metal.MachineLivelinessAlive,
LastEventTime: &exceedThresholdTime,
LastEventTime: &exceedReclaimThresholdTime,
},
event: &metal.ProvisioningEvent{
Time: now,
Expand All @@ -446,7 +448,7 @@ func TestHandleProvisioningEvent(t *testing.T) {
LastEventTime: &now,
Events: metal.ProvisioningEvents{
{
Time: exceedThresholdTime,
Time: exceedReclaimThresholdTime,
Event: metal.ProvisioningEventMachineReclaim,
},
},
Expand Down Expand Up @@ -626,12 +628,69 @@ func TestHandleProvisioningEvent(t *testing.T) {
},
},
},
{
name: "swallow delayed buffered phoned home event",
container: &metal.ProvisioningEventContainer{
Events: metal.ProvisioningEvents{
{
Time: lastEventTime,
Event: metal.ProvisioningEventWaiting,
},
},
Liveliness: metal.MachineLivelinessAlive,
LastEventTime: &lastEventTime,
},
event: &metal.ProvisioningEvent{
Time: now,
Event: metal.ProvisioningEventPhonedHome,
},
want: &metal.ProvisioningEventContainer{
Liveliness: metal.MachineLivelinessAlive,
LastEventTime: &lastEventTime,
Events: metal.ProvisioningEvents{
{
Time: lastEventTime,
Event: metal.ProvisioningEventWaiting,
},
},
},
},
{
name: "buffered phoned home event threshold exceeded",
container: &metal.ProvisioningEventContainer{
Events: metal.ProvisioningEvents{
{
Time: exceedBufferedPhonedHomeThreshold,
Event: metal.ProvisioningEventWaiting,
},
},
Liveliness: metal.MachineLivelinessAlive,
},
event: &metal.ProvisioningEvent{
Time: now,
Event: metal.ProvisioningEventPhonedHome,
},
want: &metal.ProvisioningEventContainer{
Liveliness: metal.MachineLivelinessAlive,
LastEventTime: &now,
Events: metal.ProvisioningEvents{
{
Time: now,
Event: metal.ProvisioningEventPhonedHome,
},
{
Time: exceedBufferedPhonedHomeThreshold,
Event: metal.ProvisioningEventWaiting,
},
},
},
},
}
for i := range tests {
ctx := context.Background()
tt := tests[i]
t.Run(tt.name, func(t *testing.T) {
got, err := HandleProvisioningEvent(ctx, slog.Default(), tt.container, tt.event)
got, err := HandleProvisioningEvent(ctx, slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})), tt.container, tt.event)
if diff := cmp.Diff(tt.wantErr, err); diff != "" {
t.Errorf("HandleProvisioningEvent() diff = %s", diff)
}
Expand Down
14 changes: 6 additions & 8 deletions cmd/metal-api/internal/fsm/states/alive.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@ package states

import (
"context"
"log/slog"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type AliveState struct {
log *slog.Logger
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newAlive(c *StateConfig) *AliveState {
return &AliveState{
log: c.Log,
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
11 changes: 6 additions & 5 deletions cmd/metal-api/internal/fsm/states/booting-new-kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import (
"context"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type BootingNewKernelState struct {
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newBootingNewKernel(c *StateConfig) *BootingNewKernelState {
return &BootingNewKernelState{
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
11 changes: 6 additions & 5 deletions cmd/metal-api/internal/fsm/states/crashed.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import (
"context"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type CrashState struct {
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newCrash(c *StateConfig) *CrashState {
return &CrashState{
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
11 changes: 6 additions & 5 deletions cmd/metal-api/internal/fsm/states/initial.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@ import (
"fmt"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type InitialState struct {
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newInitial(c *StateConfig) *InitialState {
return &InitialState{
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
11 changes: 6 additions & 5 deletions cmd/metal-api/internal/fsm/states/installing.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import (
"context"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type InstallingState struct {
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newInstalling(c *StateConfig) *InstallingState {
return &InstallingState{
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
11 changes: 6 additions & 5 deletions cmd/metal-api/internal/fsm/states/machine-reclaim.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import (
"context"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type MachineReclaimState struct {
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newMachineReclaim(c *StateConfig) *MachineReclaimState {
return &MachineReclaimState{
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
18 changes: 6 additions & 12 deletions cmd/metal-api/internal/fsm/states/phoned-home.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,21 @@ package states

import (
"context"
"log/slog"
"time"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

// failedMachineReclaimThreshold is the duration after which the machine reclaim is assumed to have failed.
const failedMachineReclaimThreshold = 5 * time.Minute

type PhonedHomeState struct {
log *slog.Logger
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newPhonedHome(c *StateConfig) *PhonedHomeState {
return &PhonedHomeState{
log: c.Log,
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
11 changes: 6 additions & 5 deletions cmd/metal-api/internal/fsm/states/planned-reboot.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import (
"context"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type PlannedRebootState struct {
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newPlannedReboot(c *StateConfig) *PlannedRebootState {
return &PlannedRebootState{
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

Expand Down
15 changes: 9 additions & 6 deletions cmd/metal-api/internal/fsm/states/preparing.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,26 @@ import (
"context"

"github.com/looplab/fsm"
"github.com/metal-stack/metal-api/cmd/metal-api/internal/metal"
)

type PreparingState struct {
container *metal.ProvisioningEventContainer
event *metal.ProvisioningEvent
*FSMState
}

func newPreparing(c *StateConfig) *PreparingState {
return &PreparingState{
container: c.Container,
event: c.Event,
FSMState: &FSMState{
container: c.Container,
event: c.Event,
log: c.Log,
},
}
}

func (p *PreparingState) OnTransition(ctx context.Context, e *fsm.Event) {
if p.swallowBufferedPhonedHome(e) {
return
}
p.container.FailedMachineReclaim = false

appendEventToContainer(p.event, p.container)
}
Loading