-
Notifications
You must be signed in to change notification settings - Fork 221
/
destroy.go
120 lines (100 loc) · 2.89 KB
/
destroy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package machine
import (
"context"
"fmt"
"github.com/spf13/cobra"
"github.com/superfly/flyctl/api"
"github.com/superfly/flyctl/client"
"github.com/superfly/flyctl/flaps"
"github.com/superfly/flyctl/internal/appconfig"
"github.com/superfly/flyctl/internal/command"
"github.com/superfly/flyctl/internal/flag"
"github.com/superfly/flyctl/iostreams"
)
func newDestroy() *cobra.Command {
const (
short = "Destroy a Fly machine."
long = `Destroy a Fly machine.
This command requires a machine to be in a stopped state unless the force flag is used.
`
usage = "destroy [id]"
)
cmd := command.New(usage, short, long, runMachineDestroy,
command.RequireSession,
command.LoadAppNameIfPresent,
)
cmd.Aliases = []string{"remove", "rm"}
flag.Add(
cmd,
flag.App(),
flag.AppConfig(),
selectFlag,
flag.Bool{
Name: "force",
Shorthand: "f",
Description: "force kill machine regardless of current state",
},
)
cmd.Args = cobra.RangeArgs(0, 1)
return cmd
}
func runMachineDestroy(ctx context.Context) (err error) {
var (
out = iostreams.FromContext(ctx).Out
force = flag.GetBool(ctx, "force")
)
machineID := flag.FirstArg(ctx)
haveMachineID := len(flag.Args(ctx)) > 0
current, ctx, err := selectOneMachine(ctx, nil, machineID, haveMachineID)
if err != nil {
return err
}
appName := appconfig.NameFromContext(ctx)
// This is used for the deletion hook below.
client := client.FromContext(ctx).API()
app, err := client.GetAppCompact(ctx, appName)
if err != nil {
return fmt.Errorf("could not get app '%s': %w", appName, err)
}
err = Destroy(ctx, app, current, force)
if err != nil {
return err
}
fmt.Fprintf(out, "%s has been destroyed\n", current.ID)
return nil
}
func Destroy(ctx context.Context, app *api.AppCompact, machine *api.Machine, force bool) error {
var (
out = iostreams.FromContext(ctx).Out
flapsClient = flaps.FromContext(ctx)
input = api.RemoveMachineInput{
ID: machine.ID,
Kill: force,
}
)
switch machine.State {
case "stopped":
break
case "destroyed":
return fmt.Errorf("machine %s has already been destroyed", machine.ID)
case "started":
if !force {
return fmt.Errorf("machine %s currently started, either stop first or use --force flag", machine.ID)
}
default:
if !force {
return fmt.Errorf("machine %s is in a %s state and cannot be destroyed since it is not stopped, either stop first or use --force flag", machine.ID, machine.State)
}
}
fmt.Fprintf(out, "machine %s was found and is currently in %s state, attempting to destroy...\n", machine.ID, machine.State)
err := flapsClient.Destroy(ctx, input, machine.LeaseNonce)
if err != nil {
if err := rewriteMachineNotFoundErrors(ctx, err, machine.ID); err != nil {
return err
}
return fmt.Errorf("could not destroy machine %s: %w", machine.ID, err)
}
// Best effort post-deletion hook.
runOnDeletionHook(ctx, app, machine)
return nil
}