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
8 changes: 4 additions & 4 deletions internal/command/deploy/machines_deploymachinesapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ func (md *machineDeployment) updateExistingMachinesWRecovery(ctx context.Context
// TODO(billy) do machine checks here
return md.updateUsingBlueGreenStrategy(ctx, updateEntries)
case "immediate":
return md.updateMachinesWRecovery(ctx, oldAppState, &newAppState, nil, updateMachineSettings{
return md.updateMachinesWRecovery(ctx, oldAppState, oldAppState, &newAppState, nil, updateMachineSettings{
pushForward: true,
skipHealthChecks: true,
skipSmokeChecks: true,
Expand Down Expand Up @@ -724,7 +724,7 @@ func (md *machineDeployment) updateExistingMachinesWRecovery(ctx context.Context
}
newCanaryAppState.Machines = []*fly.Machine{canaryMach}

if err := md.updateMachinesWRecovery(ctx, &canaryAppState, &newCanaryAppState, nil, updateMachineSettings{
if err := md.updateMachinesWRecovery(ctx, &canaryAppState, &canaryAppState, &newCanaryAppState, nil, updateMachineSettings{
pushForward: true,
skipHealthChecks: md.skipHealthChecks,
skipSmokeChecks: md.skipSmokeChecks,
Expand All @@ -740,7 +740,7 @@ func (md *machineDeployment) updateExistingMachinesWRecovery(ctx context.Context
return fmt.Errorf("failed to refresh app state after canary: %w", err)
}

return md.updateMachinesWRecovery(ctx, refreshedState, &newAppState, nil, updateMachineSettings{
return md.updateMachinesWRecovery(ctx, oldAppState, refreshedState, &newAppState, nil, updateMachineSettings{
pushForward: true,
skipHealthChecks: md.skipHealthChecks,
skipSmokeChecks: md.skipSmokeChecks,
Expand All @@ -749,7 +749,7 @@ func (md *machineDeployment) updateExistingMachinesWRecovery(ctx context.Context
case "rolling":
fallthrough
default:
return md.updateMachinesWRecovery(ctx, oldAppState, &newAppState, nil, updateMachineSettings{
return md.updateMachinesWRecovery(ctx, oldAppState, oldAppState, &newAppState, nil, updateMachineSettings{
pushForward: true,
skipHealthChecks: md.skipHealthChecks,
skipSmokeChecks: md.skipSmokeChecks,
Expand Down
8 changes: 4 additions & 4 deletions internal/command/deploy/machines_launchinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (md *machineDeployment) launchInputForRestart(origMachineRaw *fly.Machine)
ID: origMachineRaw.ID,
Config: mConfig,
Region: origMachineRaw.Region,
SkipLaunch: skipLaunch(origMachineRaw, mConfig),
SkipLaunch: shouldSkipLaunch(origMachineRaw, mConfig),
MinSecretsVersion: minvers,
}, nil
}
Expand Down Expand Up @@ -81,7 +81,7 @@ func (md *machineDeployment) launchInputForLaunch(processGroup string, guest *fl
return &fly.LaunchMachineInput{
Region: region,
Config: mConfig,
SkipLaunch: skipLaunch(nil, mConfig),
SkipLaunch: shouldSkipLaunch(nil, mConfig),
MinSecretsVersion: minvers,
}, nil
}
Expand Down Expand Up @@ -241,7 +241,7 @@ func (md *machineDeployment) launchInputForUpdate(origMachineRaw *fly.Machine) (
ID: mID,
Region: origMachineRaw.Region,
Config: mConfig,
SkipLaunch: skipLaunch(origMachineRaw, mConfig),
SkipLaunch: shouldSkipLaunch(origMachineRaw, mConfig),
RequiresReplacement: machineShouldBeReplaced,
MinSecretsVersion: minvers,
}, nil
Expand Down Expand Up @@ -292,7 +292,7 @@ func (md *machineDeployment) setMachineReleaseData(mConfig *fly.MachineConfig) {
// Skip launching currently-stopped or suspended machines if:
// * any services use autoscaling (autostop or autostart).
// * it is a standby machine
func skipLaunch(origMachineRaw *fly.Machine, mConfig *fly.MachineConfig) bool {
func shouldSkipLaunch(origMachineRaw *fly.Machine, mConfig *fly.MachineConfig) bool {
state := "<not-set>"
if origMachineRaw != nil {
state = origMachineRaw.State
Expand Down
57 changes: 38 additions & 19 deletions internal/command/deploy/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ type AppState struct {
}

type machinePairing struct {
oldMachine *fly.Machine
newMachine *fly.Machine
// originalMachine is this machine as read before the deploy began. It's not re-read on recovery retries.
// nil for machines being created during the deploy.
originalMachine *fly.Machine
oldMachine *fly.Machine
newMachine *fly.Machine
}

// appState returns the app's state from Flaps.
Expand Down Expand Up @@ -109,7 +112,7 @@ type updateMachineSettings struct {

const rollingStrategyMaxConcurrentGroups = 16

func (md *machineDeployment) updateMachinesWRecovery(ctx context.Context, oldAppState, newAppState *AppState, statusLogger statuslogger.StatusLogger, settings updateMachineSettings) error {
func (md *machineDeployment) updateMachinesWRecovery(ctx context.Context, originalAppState, oldAppState, newAppState *AppState, statusLogger statuslogger.StatusLogger, settings updateMachineSettings) error {
ctx, span := tracing.GetTracer().Start(
ctx, "update_machines_w_recovery",
trace.WithAttributes(attribute.Bool("push_forward", settings.pushForward)),
Expand All @@ -121,6 +124,12 @@ func (md *machineDeployment) updateMachinesWRecovery(ctx context.Context, oldApp
ctx, cancel = ctrlc.HookCancelableContext(ctx, cancel)
defer cancel()

originalMachines := make(map[string]*fly.Machine)
if originalAppState != nil {
for _, machine := range originalAppState.Machines {
originalMachines[machine.ID] = machine
}
}
oldMachines := make(map[string]*fly.Machine)
for _, machine := range oldAppState.Machines {
oldMachines[machine.ID] = machine
Expand All @@ -139,7 +148,7 @@ func (md *machineDeployment) updateMachinesWRecovery(ctx context.Context, oldApp
machineChecksPassed: settings.skipHealthChecks,
smokeChecksPassed: settings.skipSmokeChecks,
})
machineTuples = append(machineTuples, machinePairing{oldMachine: oldMachine, newMachine: newMachine})
machineTuples = append(machineTuples, machinePairing{originalMachine: originalMachines[oldMachine.ID], oldMachine: oldMachine, newMachine: newMachine})
}
}

Expand All @@ -151,7 +160,7 @@ func (md *machineDeployment) updateMachinesWRecovery(ctx context.Context, oldApp
machineChecksPassed: settings.skipHealthChecks,
smokeChecksPassed: settings.skipSmokeChecks,
})
machineTuples = append(machineTuples, machinePairing{oldMachine: nil, newMachine: newMachine})
machineTuples = append(machineTuples, machinePairing{originalMachine: originalMachines[newMachine.ID], oldMachine: nil, newMachine: newMachine})
}
}

Expand Down Expand Up @@ -309,7 +318,7 @@ func (md *machineDeployment) updateMachinesWRecovery(ctx context.Context, oldApp
if err != nil {
return err
}
err = md.updateMachinesWRecovery(ctx, currentState, newAppState, sl, updateMachineSettings{
err = md.updateMachinesWRecovery(ctx, originalAppState, currentState, newAppState, sl, updateMachineSettings{
pushForward: false,
skipHealthChecks: settings.skipHealthChecks,
skipSmokeChecks: settings.skipSmokeChecks,
Expand Down Expand Up @@ -345,6 +354,7 @@ func (md *machineDeployment) updateProcessGroup(ctx context.Context, machineTupl
group.SetLimit(poolSize)

for _, machPair := range machineTuples {
originalMachine := machPair.originalMachine
oldMachine := machPair.oldMachine
newMachine := machPair.newMachine

Expand All @@ -356,6 +366,14 @@ func (md *machineDeployment) updateProcessGroup(ctx context.Context, machineTupl
return nil
}

// Determine if the machine should be started after deployment. This is based
// on the state of originalMachine, which was captured pre-deploy and won't
// change during deploy recovery retries.
skipLaunch := false
if newMachine != nil {
skipLaunch = shouldSkipLaunch(originalMachine, newMachine.Config)
}

var machineID string
if oldMachine != nil {
machineID = oldMachine.ID
Expand All @@ -382,7 +400,7 @@ func (md *machineDeployment) updateProcessGroup(ctx context.Context, machineTupl
}
machineCheckResult := checkResult.(*healthcheckResult)

err := md.updateMachineWChecks(gCtx, oldMachine, newMachine, sl, md.io, machineCheckResult)
err := md.updateMachineWChecks(gCtx, oldMachine, newMachine, skipLaunch, sl, md.io, machineCheckResult)
if err != nil {
sl.LogStatus(statuslogger.StatusFailure, err.Error())
span.RecordError(err)
Expand Down Expand Up @@ -565,7 +583,7 @@ func isEmptyOrNilSlice(v interface{}) bool {
return rv.Kind() == reflect.Slice && rv.Len() == 0
}

func (md *machineDeployment) updateMachineWChecks(ctx context.Context, oldMachine, newMachine *fly.Machine, sl statuslogger.StatusLine, io *iostreams.IOStreams, healthcheckResult *healthcheckResult) error {
func (md *machineDeployment) updateMachineWChecks(ctx context.Context, oldMachine, newMachine *fly.Machine, skipLaunch bool, sl statuslogger.StatusLine, io *iostreams.IOStreams, healthcheckResult *healthcheckResult) error {
ctx, span := tracing.GetTracer().Start(ctx, "update_machine_w_checks", trace.WithAttributes(
attribute.Bool("smoke_checks", healthcheckResult.smokeChecksPassed),
attribute.Bool("machine_checks", healthcheckResult.machineChecksPassed),
Expand All @@ -578,7 +596,7 @@ func (md *machineDeployment) updateMachineWChecks(ctx context.Context, oldMachin

var err error

machine, lease, err = md.updateOrCreateMachine(ctx, oldMachine, newMachine, sl)
machine, lease, err = md.updateOrCreateMachine(ctx, oldMachine, newMachine, skipLaunch, sl)
// if machine is nil and the lease is nil, it means we don't need to check on this machine
if err != nil || (machine == nil && lease == nil) {
span.RecordError(err)
Expand All @@ -588,8 +606,7 @@ func (md *machineDeployment) updateMachineWChecks(ctx context.Context, oldMachin

lm := mach.NewLeasableMachine(md.flapsClient, io, md.app.Name, machine, false)

shouldStart := lo.Contains([]string{"started", "replacing"}, newMachine.State)
span.SetAttributes(attribute.Bool("should_start", shouldStart))
span.SetAttributes(attribute.Bool("should_start", !skipLaunch))

if !healthcheckResult.machineChecksPassed || !healthcheckResult.smokeChecksPassed {
sl.LogStatus(statuslogger.StatusRunning, fmt.Sprintf("Waiting for machine %s to reach a good state", machine.ID))
Expand All @@ -601,7 +618,7 @@ func (md *machineDeployment) updateMachineWChecks(ctx context.Context, oldMachin
}
}

if !shouldStart {
if skipLaunch {
sl.LogStatus(statuslogger.StatusSuccess, fmt.Sprintf("Machine %s is now in a good state", machine.ID))

return nil
Expand Down Expand Up @@ -649,7 +666,7 @@ func (md *machineDeployment) updateMachineWChecks(ctx context.Context, oldMachin
return nil
}

func (md *machineDeployment) updateOrCreateMachine(ctx context.Context, oldMachine, newMachine *fly.Machine, sl statuslogger.StatusLine) (*fly.Machine, *fly.MachineLease, error) {
func (md *machineDeployment) updateOrCreateMachine(ctx context.Context, oldMachine, newMachine *fly.Machine, skipLaunch bool, sl statuslogger.StatusLine) (*fly.Machine, *fly.MachineLease, error) {
ctx, span := tracing.GetTracer().Start(ctx, "update_or_create_machine")
defer span.End()

Expand All @@ -668,7 +685,7 @@ func (md *machineDeployment) updateOrCreateMachine(ctx context.Context, oldMachi
} else {
span.AddEvent("Updating old machine")
sl.LogStatus(statuslogger.StatusRunning, fmt.Sprintf("Updating machine config for %s", oldMachine.ID))
machine, err := md.updateMachineConfig(ctx, oldMachine, newMachine.Config, sl, newMachine.State == "replacing")
machine, err := md.updateMachineConfig(ctx, oldMachine, newMachine.Config, sl, newMachine.State == "replacing", skipLaunch)
if err != nil {
span.RecordError(err)

Expand All @@ -681,7 +698,7 @@ func (md *machineDeployment) updateOrCreateMachine(ctx context.Context, oldMachi
} else if newMachine != nil {
span.AddEvent("Creating a new machine")
sl.LogStatus(statuslogger.StatusRunning, fmt.Sprintf("Creating machine for %s", newMachine.ID))
machine, err := md.createMachine(ctx, newMachine.Config, newMachine.Region)
machine, err := md.createMachine(ctx, newMachine.Config, newMachine.Region, skipLaunch)
if err != nil {
span.RecordError(err)

Expand Down Expand Up @@ -807,7 +824,7 @@ func (md *machineDeployment) acquireMachineLease(ctx context.Context, machID str
return lease, nil
}

func (md *machineDeployment) updateMachineConfig(ctx context.Context, oldMachine *fly.Machine, newMachineConfig *fly.MachineConfig, sl statuslogger.StatusLine, shouldReplace bool) (*fly.Machine, error) {
func (md *machineDeployment) updateMachineConfig(ctx context.Context, oldMachine *fly.Machine, newMachineConfig *fly.MachineConfig, sl statuslogger.StatusLine, shouldReplace bool, skipLaunch bool) (*fly.Machine, error) {
ctx, span := tracing.GetTracer().Start(ctx, "update_machine_config")
defer span.End()
if compareConfigs(ctx, oldMachine.Config, newMachineConfig) {
Expand All @@ -820,6 +837,7 @@ func (md *machineDeployment) updateMachineConfig(ctx context.Context, oldMachine
}
input.Config = newMachineConfig
input.RequiresReplacement = input.RequiresReplacement || shouldReplace
input.SkipLaunch = skipLaunch

lm := mach.NewLeasableMachine(md.flapsClient, md.io, md.app.Name, oldMachine, false)
entry := &machineUpdateEntry{
Expand All @@ -834,10 +852,11 @@ func (md *machineDeployment) updateMachineConfig(ctx context.Context, oldMachine
return entry.leasableMachine.Machine(), nil
}

func (md *machineDeployment) createMachine(ctx context.Context, machConfig *fly.MachineConfig, region string) (*fly.Machine, error) {
func (md *machineDeployment) createMachine(ctx context.Context, machConfig *fly.MachineConfig, region string, skipLaunch bool) (*fly.Machine, error) {
machine, err := md.flapsClient.Launch(ctx, md.app.Name, fly.LaunchMachineInput{
Config: machConfig,
Region: region,
Config: machConfig,
Region: region,
SkipLaunch: skipLaunch,
})
if err != nil {
return nil, err
Expand Down
Loading
Loading