Skip to content

Commit 45caf45

Browse files
authored
feat(instance): add --wait to server terminate (#3046)
1 parent 9ed70a3 commit 45caf45

File tree

8 files changed

+2412
-1479
lines changed

8 files changed

+2412
-1479
lines changed

cmd/scw/testdata/test-all-usage-instance-server-terminate-usage.golden

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ARGS:
2323

2424
FLAGS:
2525
-h, --help help for terminate
26+
-w, --wait wait until the server and its resources are deleted
2627

2728
GLOBAL FLAGS:
2829
-c, --config string The path to the config file

internal/core/cobra_builder.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,11 @@ func (b *cobraBuilder) hydrateCobra(cobraCmd *cobra.Command, cmd *Command, group
170170
}
171171

172172
if cmd.WaitFunc != nil {
173-
cobraCmd.PersistentFlags().BoolP("wait", "w", false, "wait until the "+cmd.Resource+" is ready")
173+
waitUsage := "wait until the " + cmd.Resource + " is ready"
174+
if cmd.WaitUsage != "" {
175+
waitUsage = cmd.WaitUsage
176+
}
177+
cobraCmd.PersistentFlags().BoolP("wait", "w", false, waitUsage)
174178
}
175179
}
176180

internal/core/command.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ type Command struct {
7575
// WaitFunc will be called if non-nil when the -w (--wait) flag is passed.
7676
WaitFunc WaitFunc
7777

78+
// WaitUsage override the usage for the -w (--wait) flag
79+
WaitUsage string
80+
7881
// Aliases contains a list of aliases for a command
7982
Aliases []string
8083
// cache command path

internal/core/result.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ type SuccessResult struct {
1919
Resource string
2020
Verb string
2121
Empty bool
22+
// Used to pass resource to an AfterFunc on success
23+
TargetResource any
2224
}
2325

2426
// This type can be return by a command that need to output specific content on stdout directly.

internal/namespaces/instance/v1/custom_server.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package instance
33
import (
44
"bytes"
55
"context"
6+
"errors"
67
"fmt"
78
"net"
89
"reflect"
@@ -1127,6 +1128,48 @@ func serverTerminateCommand() *core.Command {
11271128
Short: "Stop a running server",
11281129
},
11291130
},
1131+
WaitUsage: "wait until the server and its resources are deleted",
1132+
WaitFunc: func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
1133+
terminateServerArgs := argsI.(*customTerminateServerRequest)
1134+
server := respI.(*core.SuccessResult).TargetResource.(*instance.Server)
1135+
client := core.ExtractClient(ctx)
1136+
api := instance.NewAPI(client)
1137+
1138+
notFoundErr := &scw.ResourceNotFoundError{}
1139+
1140+
_, err := api.WaitForServer(&instance.WaitForServerRequest{
1141+
Zone: server.Zone,
1142+
ServerID: server.ID,
1143+
Timeout: scw.TimeDurationPtr(serverActionTimeout),
1144+
RetryInterval: core.DefaultRetryInterval,
1145+
})
1146+
if err != nil {
1147+
err = errors.Unwrap(err)
1148+
if !errors.As(err, &notFoundErr) {
1149+
return nil, err
1150+
}
1151+
}
1152+
1153+
if terminateServerArgs.WithBlock == withBlockTrue {
1154+
for _, volume := range server.Volumes {
1155+
if volume.VolumeType != instance.VolumeServerVolumeTypeBSSD {
1156+
continue
1157+
}
1158+
_, err := api.WaitForVolume(&instance.WaitForVolumeRequest{
1159+
VolumeID: volume.ID,
1160+
Zone: volume.Zone,
1161+
})
1162+
if err != nil {
1163+
if errors.As(err, &notFoundErr) {
1164+
continue
1165+
}
1166+
return nil, err
1167+
}
1168+
}
1169+
}
1170+
1171+
return respI, nil
1172+
},
11301173
Run: func(ctx context.Context, argsI interface{}) (interface{}, error) {
11311174
terminateServerArgs := argsI.(*customTerminateServerRequest)
11321175

@@ -1183,7 +1226,9 @@ func serverTerminateCommand() *core.Command {
11831226
_, _ = interactive.Printf("successfully deleted ip %s\n", server.Server.PublicIP.Address.String())
11841227
}
11851228

1186-
return &core.SuccessResult{}, err
1229+
return &core.SuccessResult{
1230+
TargetResource: server.Server,
1231+
}, err
11871232
},
11881233
}
11891234
}

internal/namespaces/instance/v1/custom_server_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,19 @@ func Test_ServerTerminate(t *testing.T) {
357357
t.Run("with block", core.Test(&core.TestConfig{
358358
Commands: GetCommands(),
359359
BeforeFunc: core.ExecStoreBeforeCmd("Server", "scw instance server create image=ubuntu-bionic additional-volumes.0=block:10G -w"),
360-
Cmd: `scw instance server terminate {{ .Server.ID }} with-ip=true with-block=true`,
360+
Cmd: `scw instance server terminate {{ .Server.ID }} with-ip=true with-block=true -w`,
361361
Check: core.TestCheckCombine(
362362
core.TestCheckGolden(),
363363
core.TestCheckExitCode(0),
364+
func(t *testing.T, ctx *core.CheckFuncCtx) {
365+
api := instance.NewAPI(ctx.Client)
366+
server := ctx.Meta["Server"].(*instance.Server)
367+
_, err := api.GetVolume(&instance.GetVolumeRequest{
368+
VolumeID: server.Volumes["0"].ID,
369+
Zone: server.Zone,
370+
})
371+
require.IsType(t, &scw.ResourceNotFoundError{}, err)
372+
},
364373
),
365374
DisableParallel: true,
366375
}))

internal/namespaces/instance/v1/testdata/test-server-terminate-with-block.cassette.yaml

Lines changed: 2344 additions & 1475 deletions
Large diffs are not rendered by default.

internal/namespaces/instance/v1/testdata/test-server-terminate-with-block.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
🟩🟩🟩 STDOUT️ 🟩🟩🟩️
33
✅ Success.
44
🟥🟥🟥 STDERR️️ 🟥🟥🟥️
5-
successfully deleted ip 51.158.108.20
5+
successfully deleted ip 51.158.115.98
66
🟩🟩🟩 JSON STDOUT 🟩🟩🟩
77
{
88
"message": "Success",

0 commit comments

Comments
 (0)