Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(instance): add with-snapshots arg on delete image #877

Merged
merged 4 commits into from
Apr 21, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ EXAMPLES:
scw instance image delete 11111111-1111-1111-1111-111111111111 zone=fr-par-1

ARGS:
image-id
[zone] Zone to target. If none is passed will use default zone from the config (fr-par-1 | nl-ams-1)
image-id
[with-snapshots] Delete the snapshots attached to this image
[zone] Zone to target. If none is passed will use default zone from the config (fr-par-1 | nl-ams-1)

FLAGS:
-h, --help help for delete
Expand Down
4 changes: 4 additions & 0 deletions internal/core/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type CheckFuncCtx struct {

// Meta bag
Meta map[string]interface{}

// Scaleway client
Client *scw.Client
}

// TestCheck is a function that perform assertion on a CheckFuncCtx
Expand Down Expand Up @@ -261,6 +264,7 @@ func Test(config *TestConfig) func(t *testing.T) {
Meta: meta,
Result: result,
Err: err,
Client: client,
})
}

Expand Down
1 change: 1 addition & 0 deletions internal/namespaces/instance/v1/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func GetCommands() *core.Commands {

cmds.MustFind("instance", "image", "create").Override(imageCreateBuilder)
cmds.MustFind("instance", "image", "list").Override(imageListBuilder)
cmds.MustFind("instance", "image", "delete").Override(imageDeleteBuilder)

//
// Snapshot
Expand Down
62 changes: 62 additions & 0 deletions internal/namespaces/instance/v1/custom_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,65 @@ func imageListBuilder(c *core.Command) *core.Command {

return c
}

// imageDeleteBuilder override delete command to:
// - add a with-snapshots parameter
func imageDeleteBuilder(c *core.Command) *core.Command {
type customDeleteImageRequest struct {
*instance.DeleteImageRequest
WithSnapshots bool
}

c.ArgsType = reflect.TypeOf(customDeleteImageRequest{})
c.ArgSpecs.AddBefore("zone", &core.ArgSpec{
Name: "with-snapshots",
Short: "Delete the snapshots attached to this image",
})

c.AddInterceptors(func(ctx context.Context, argsI interface{}, runner core.CommandRunner) (i interface{}, err error) {
args := argsI.(*customDeleteImageRequest)

api := instance.NewAPI(core.ExtractClient(ctx))

// If we want to delete snapshot we must GET image before we delete it
image := (*instance.Image)(nil)
if args.WithSnapshots {
res, err := api.GetImage(&instance.GetImageRequest{
Zone: args.Zone,
ImageID: args.ImageID,
})
if err != nil {
return nil, err
}
image = res.Image
}

// Call the generated delete
runnerRes, err := runner(ctx, args.DeleteImageRequest)
if err != nil {
return nil, err
}

// Once the image is deleted we can delete snapshots.
if args.WithSnapshots {
snapshotIDs := []string{
image.RootVolume.ID,
}
for _, snapshot := range image.ExtraVolumes {
snapshotIDs = append(snapshotIDs, snapshot.ID)
}
for _, snapshotID := range snapshotIDs {
err := api.DeleteSnapshot(&instance.DeleteSnapshotRequest{
Zone: args.Zone,
SnapshotID: snapshotID,
})
if err != nil {
return nil, err
}
}
}
return runnerRes, nil
})

return c
}
32 changes: 32 additions & 0 deletions internal/namespaces/instance/v1/custom_image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package instance
import (
"testing"

"github.com/alecthomas/assert"
"github.com/scaleway/scaleway-cli/internal/core"
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

func Test_ImageCreate(t *testing.T) {
Expand All @@ -25,3 +28,32 @@ func Test_ImageCreate(t *testing.T) {
),
}))
}

func Test_ImageDelete(t *testing.T) {
t.Run("simple", core.Test(&core.TestConfig{
BeforeFunc: createImage("Image"),
Commands: GetCommands(),
Cmd: "scw instance image delete {{ .Image.Image.ID }} with-snapshots=true",
Check: core.TestCheckCombine(
core.TestCheckGolden(),
core.TestCheckExitCode(0),
func(t *testing.T, ctx *core.CheckFuncCtx) {
// Assert snapshot are deleted with the image
api := instance.NewAPI(ctx.Client)
_, err := api.GetSnapshot(&instance.GetSnapshotRequest{
SnapshotID: ctx.Meta["Snapshot"].(*instance.CreateSnapshotResponse).Snapshot.ID,
})
assert.IsType(t, &scw.ResourceNotFoundError{}, err)
},
),
AfterFunc: deleteServer("Server"),
}))
}

func createImage(metaKey string) core.BeforeFunc {
return core.BeforeFuncCombine(
createServer("Server"),
core.ExecStoreBeforeCmd("Snapshot", `scw instance snapshot create volume-id={{ (index .Server.Volumes "0").ID }}`),
core.ExecStoreBeforeCmd(metaKey, `scw instance image create snapshot-id={{ .Snapshot.Snapshot.ID }} arch=x86_64`),
)
}
Loading