Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ ARGS:

FLAGS:
-h, --help help for create
-w, --wait wait until the backup is ready

GLOBAL FLAGS:
-c, --config string The path to the config file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ARGS:

FLAGS:
-h, --help help for export
-w, --wait wait until the backup is ready

GLOBAL FLAGS:
-c, --config string The path to the config file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ ARGS:

FLAGS:
-h, --help help for restore
-w, --wait wait until the backup is ready

GLOBAL FLAGS:
-c, --config string The path to the config file
Expand Down
1 change: 1 addition & 0 deletions cmd/scw/testdata/test-all-usage-rdb-backup-usage.golden
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ AVAILABLE COMMANDS:
list List database backups
restore Restore a database backup
update Update a database backup
wait Wait for a backup to reach a stable state

FLAGS:
-h, --help help for backup
Expand Down
23 changes: 23 additions & 0 deletions cmd/scw/testdata/test-all-usage-rdb-backup-wait-usage.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲
🟥🟥🟥 STDERR️️ 🟥🟥🟥️
Wait for a backup to reach a stable state. This is similar to using --wait flag.

USAGE:
scw rdb backup wait <backup-id ...> [arg=value ...]

EXAMPLES:
Wait for a backup to reach a stable state
scw rdb backup wait

ARGS:
backup-id ID of the backup you want to wait for.
[region=fr-par] Region to target. If none is passed will use default region from the config (fr-par | nl-ams)

FLAGS:
-h, --help help for wait

GLOBAL FLAGS:
-c, --config string The path to the config file
-D, --debug Enable debug mode
-o, --output string Output format: json or human, see 'scw help output' for more info (default "human")
-p, --profile string The config profile to use
6 changes: 5 additions & 1 deletion internal/namespaces/rdb/v1/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ func GetCommands() *core.Commands {
cmds.Merge(core.NewCommands(
instanceWaitCommand(),
instanceConnectCommand(),
backupWaitCommand(),
))
cmds.MustFind("rdb", "backup", "create").Override(backupCreateBuilder)
cmds.MustFind("rdb", "backup", "export").Override(backupExportBuilder)
cmds.MustFind("rdb", "backup", "restore").Override(backupRestoreBuilder)

cmds.MustFind("rdb", "instance", "create").Override(instanceCreateBuilder)
cmds.MustFind("rdb", "instance", "clone").Override(instanceCloneBuilder)
cmds.MustFind("rdb", "instance", "create").Override(instanceCreateBuilder)

cmds.MustFind("rdb", "instance", "upgrade").Override(instanceUpgradeBuilder)

cmds.MustFind("rdb", "engine", "list").Override(engineListBuilder)
Expand Down
100 changes: 100 additions & 0 deletions internal/namespaces/rdb/v1/custom_backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package rdb

import (
"context"
"reflect"
"time"

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

const (
backupActionTimeout = 20 * time.Minute
)

type backupWaitRequest struct {
DatabaseBackupID string
Region scw.Region
}

func backupWaitCommand() *core.Command {
return &core.Command{
Short: `Wait for a backup to reach a stable state`,
Long: `Wait for a backup to reach a stable state. This is similar to using --wait flag.`,
Namespace: "rdb",
Resource: "backup",
Verb: "wait",
ArgsType: reflect.TypeOf(backupWaitRequest{}),
Run: func(ctx context.Context, argsI interface{}) (i interface{}, err error) {
api := rdb.NewAPI(core.ExtractClient(ctx))
return api.WaitForDatabaseBackup(&rdb.WaitForDatabaseBackupRequest{
DatabaseBackupID: argsI.(*backupWaitRequest).DatabaseBackupID,
Region: argsI.(*backupWaitRequest).Region,
Timeout: scw.TimeDurationPtr(backupActionTimeout),
RetryInterval: core.DefaultRetryInterval,
})
},
ArgSpecs: core.ArgSpecs{
{
Name: "backup-id",
Short: `ID of the backup you want to wait for.`,
Required: true,
Positional: true,
},
core.RegionArgSpec(scw.RegionFrPar, scw.RegionNlAms),
},
Examples: []*core.Example{
{
Short: "Wait for a backup to reach a stable state",
ArgsJSON: `{"backup_id": "11111111-1111-1111-1111-111111111111"}`,
},
},
}
}

func backupCreateBuilder(c *core.Command) *core.Command {
timeout := backupActionTimeout
c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := rdb.NewAPI(core.ExtractClient(ctx))
return api.WaitForDatabaseBackup(&rdb.WaitForDatabaseBackupRequest{
DatabaseBackupID: respI.(*rdb.DatabaseBackup).ID,
Region: respI.(*rdb.DatabaseBackup).Region,
Timeout: &timeout,
RetryInterval: core.DefaultRetryInterval,
})
}

return c
}

func backupExportBuilder(c *core.Command) *core.Command {
timeout := backupActionTimeout
c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := rdb.NewAPI(core.ExtractClient(ctx))
return api.WaitForDatabaseBackup(&rdb.WaitForDatabaseBackupRequest{
DatabaseBackupID: respI.(*rdb.DatabaseBackup).ID,
Region: respI.(*rdb.DatabaseBackup).Region,
Timeout: &timeout,
RetryInterval: core.DefaultRetryInterval,
})
}

return c
}

func backupRestoreBuilder(c *core.Command) *core.Command {
timeout := backupActionTimeout
c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := rdb.NewAPI(core.ExtractClient(ctx))
return api.WaitForDatabaseBackup(&rdb.WaitForDatabaseBackupRequest{
DatabaseBackupID: respI.(*rdb.DatabaseBackup).ID,
Region: respI.(*rdb.DatabaseBackup).Region,
Timeout: &timeout,
RetryInterval: core.DefaultRetryInterval,
})
}

return c
}
83 changes: 83 additions & 0 deletions internal/namespaces/rdb/v1/custom_backup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package rdb

import (
"testing"
"time"

"github.com/scaleway/scaleway-cli/internal/core"
"github.com/scaleway/scaleway-sdk-go/scw"
)

func Test_CreateBackup(t *testing.T) {
t.Run("Simple", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: core.BeforeFuncCombine(
createInstance(engine),
// We opened an internal issue about the fact that the instance is considered ready even if rdb is not yet available.
core.BeforeFuncWhenUpdatingCassette(
func(ctx *core.BeforeFuncCtx) error {
time.Sleep(1 * time.Minute)
return nil
},
),
),
Cmd: "scw rdb backup create name=foobar expires-at=2999-01-02T15:04:05-07:00 instance-id={{ .Instance.ID }} database-name=rdb --wait",
Check: core.TestCheckGolden(),
AfterFunc: deleteInstance(),
DefaultRegion: scw.RegionNlAms,
}))
}

func Test_RestoreBackup(t *testing.T) {
t.Run("Simple", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: core.BeforeFuncCombine(
createInstance(engine),
// We opened an internal issue about the fact that the instance is considered ready even if rdb is not yet available.
core.BeforeFuncWhenUpdatingCassette(
func(ctx *core.BeforeFuncCtx) error {
time.Sleep(1 * time.Minute)
return nil
},
),
core.ExecStoreBeforeCmd(
"Backup",
"scw rdb backup create name=foobar expires-at=2999-01-02T15:04:05-07:00 instance-id={{ .Instance.ID }} database-name=rdb --wait",
),
),
Cmd: "scw rdb backup restore {{ .Backup.ID }} instance-id={{ .Instance.ID }} --wait",
Check: core.TestCheckCombine(
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
AfterFunc: deleteInstance(),
DefaultRegion: scw.RegionNlAms,
}))
}

func Test_ExportBackup(t *testing.T) {
t.Run("Simple", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: core.BeforeFuncCombine(
createInstance(engine),
// We opened an internal issue about the fact that the instance is considered ready even if rdb is not yet available.
core.BeforeFuncWhenUpdatingCassette(
func(ctx *core.BeforeFuncCtx) error {
time.Sleep(1 * time.Minute)
return nil
},
),
core.ExecStoreBeforeCmd(
"Backup",
"scw rdb backup create name=foobar expires-at=2999-01-02T15:04:05-07:00 instance-id={{ .Instance.ID }} database-name=rdb --wait",
),
),
Cmd: "scw rdb backup export {{ .Backup.ID }} --wait",
Check: core.TestCheckCombine(
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
AfterFunc: deleteInstance(),
DefaultRegion: scw.RegionNlAms,
}))
}
Loading