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(rdb): add instance update settings #2549

Merged
merged 5 commits into from
Oct 17, 2022
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 @@ -5,6 +5,16 @@ Update an instance.
USAGE:
scw rdb instance update <instance-id ...> [arg=value ...]

EXAMPLES:
Update instance name
scw rdb instance update 11111111-1111-1111-1111-111111111111 name=foo --wait

Update instance tags
scw rdb instance update 11111111-1111-1111-1111-111111111111 tags.0=a --wait

Set a timezone
scw rdb instance update 11111111-1111-1111-1111-111111111111 settings.0.name=timezone settings.0.value=UTC --wait

ARGS:
[backup-schedule-frequency] In hours
[backup-schedule-retention] In days
Expand All @@ -15,10 +25,13 @@ ARGS:
[logs-policy.max-age-retention] Max age (in day) of remote logs to keep on the database instance
[logs-policy.total-disk-retention] Max disk size of remote logs to keep on the database instance
[backup-same-region] Store logical backups in the same region as the database instance
[settings.{index}.name] Setting name of a given instance
[settings.{index}.value] Setting value of a given instance
[region=fr-par] Region to target. If none is passed will use default region from the config (fr-par | nl-ams | pl-waw)

FLAGS:
-h, --help help for update
-w, --wait wait until the instance is ready

GLOBAL FLAGS:
-c, --config string The path to the config file
Expand Down
22 changes: 22 additions & 0 deletions docs/commands/rdb.md
Original file line number Diff line number Diff line change
Expand Up @@ -685,9 +685,31 @@ scw rdb instance update <instance-id ...> [arg=value ...]
| logs-policy.max-age-retention | | Max age (in day) of remote logs to keep on the database instance |
| logs-policy.total-disk-retention | | Max disk size of remote logs to keep on the database instance |
| backup-same-region | | Store logical backups in the same region as the database instance |
| settings.{index}.name | | Setting name of a given instance |
| settings.{index}.value | | Setting value of a given instance |
| region | Default: `fr-par`<br />One of: `fr-par`, `nl-ams`, `pl-waw` | Region to target. If none is passed will use default region from the config |


**Examples:**


Update instance name
```
scw rdb instance update 11111111-1111-1111-1111-111111111111 name=foo --wait
```

Update instance tags
```
scw rdb instance update 11111111-1111-1111-1111-111111111111 tags.0=a --wait
```

Set a timezone
```
scw rdb instance update 11111111-1111-1111-1111-111111111111 settings.0.name=timezone settings.0.value=UTC --wait
```




### Upgrade an instance to an higher instance type

Expand Down
1 change: 1 addition & 0 deletions internal/namespaces/rdb/v1/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func GetCommands() *core.Commands {
cmds.MustFind("rdb", "instance", "clone").Override(instanceCloneBuilder)
cmds.MustFind("rdb", "instance", "create").Override(instanceCreateBuilder)
cmds.MustFind("rdb", "instance", "upgrade").Override(instanceUpgradeBuilder)
cmds.MustFind("rdb", "instance", "update").Override(instanceUpdateBuilder)

cmds.MustFind("rdb", "engine", "list").Override(engineListBuilder)

Expand Down
170 changes: 170 additions & 0 deletions internal/namespaces/rdb/v1/custom_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,176 @@ func instanceUpgradeBuilder(c *core.Command) *core.Command {
return c
}

func instanceUpdateBuilder(c *core.Command) *core.Command {
type rdbUpdateInstanceRequestCustom struct {
*rdb.UpdateInstanceRequest
Settings []*rdb.InstanceSetting
}

return &core.Command{
Short: `Update an instance`,
Long: `Update an instance.`,
Namespace: "rdb",
Resource: "instance",
Verb: "update",
ArgsType: reflect.TypeOf(rdbUpdateInstanceRequestCustom{}),
ArgSpecs: core.ArgSpecs{
{
Name: "backup-schedule-frequency",
Short: `In hours`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "backup-schedule-retention",
Short: `In days`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "is-backup-schedule-disabled",
Short: `Whether or not the backup schedule is disabled`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "name",
Short: `Name of the instance`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "instance-id",
Short: `UUID of the instance to update`,
Required: true,
Deprecated: false,
Positional: true,
},
{
Name: "tags.{index}",
Short: `Tags of a given instance`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "logs-policy.max-age-retention",
Short: `Max age (in day) of remote logs to keep on the database instance`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "logs-policy.total-disk-retention",
Short: `Max disk size of remote logs to keep on the database instance`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "backup-same-region",
Short: `Store logical backups in the same region as the database instance`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "settings.{index}.name",
Short: `Setting name of a given instance`,
Required: false,
Deprecated: false,
Positional: false,
},
{
Name: "settings.{index}.value",
Short: `Setting value of a given instance`,
Required: false,
Deprecated: false,
Positional: false,
},
core.RegionArgSpec(scw.RegionFrPar, scw.RegionNlAms, scw.RegionPlWaw),
},
Run: func(ctx context.Context, args interface{}) (i interface{}, e error) {
customRequest := args.(*rdbUpdateInstanceRequestCustom)

updateInstanceRequest := customRequest.UpdateInstanceRequest

client := core.ExtractClient(ctx)
api := rdb.NewAPI(client)

getResp, err := api.GetInstance(&rdb.GetInstanceRequest{
Region: customRequest.Region,
InstanceID: customRequest.InstanceID,
})
if err != nil {
return nil, err
}

if customRequest.Settings != nil {
settings := getResp.Settings
changes := customRequest.Settings

for _, change := range changes {
matched := false
for _, setting := range settings {
if change.Name == setting.Name {
setting.Value = change.Value
matched = true
break
}
}
if !matched {
settings = append(settings, change)
}
}

_, err = api.SetInstanceSettings(&rdb.SetInstanceSettingsRequest{
Region: updateInstanceRequest.Region,
InstanceID: updateInstanceRequest.InstanceID,
Settings: settings,
})
if err != nil {
return nil, err
}
}

updateInstanceResponse, err := api.UpdateInstance(updateInstanceRequest)
if err != nil {
return nil, err
}

return updateInstanceResponse, nil
},
WaitFunc: func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := rdb.NewAPI(core.ExtractClient(ctx))
return api.WaitForInstance(&rdb.WaitForInstanceRequest{
InstanceID: respI.(*rdb.Instance).ID,
Region: respI.(*rdb.Instance).Region,
Timeout: scw.TimeDurationPtr(instanceActionTimeout),
RetryInterval: core.DefaultRetryInterval,
})
},
Examples: []*core.Example{
{
Short: "Update instance name",
Raw: "scw rdb instance update 11111111-1111-1111-1111-111111111111 name=foo --wait",
},
{
Short: "Update instance tags",
Raw: "scw rdb instance update 11111111-1111-1111-1111-111111111111 tags.0=a --wait",
},
{
Short: "Set a timezone",
Raw: "scw rdb instance update 11111111-1111-1111-1111-111111111111 settings.0.name=timezone settings.0.value=UTC --wait",
},
},
}
}

func instanceWaitCommand() *core.Command {
return &core.Command{
Short: `Wait for an instance to reach a stable state`,
Expand Down
94 changes: 94 additions & 0 deletions internal/namespaces/rdb/v1/custom_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"fmt"
"testing"

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

func Test_ListInstance(t *testing.T) {
Expand Down Expand Up @@ -56,6 +58,98 @@ func Test_UpgradeInstance(t *testing.T) {
}))
}

func Test_UpdateInstance(t *testing.T) {
t.Run("Update instance name", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: createInstance("PostgreSQL-12"),
Cmd: "scw rdb instance update {{ .Instance.ID }} name=foo --wait",
Check: core.TestCheckCombine(
func(t *testing.T, ctx *core.CheckFuncCtx) {
assert.Equal(t, "foo", ctx.Result.(*rdb.Instance).Name)
},
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
AfterFunc: deleteInstance(),
}))

t.Run("Update instance tags", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: createInstance("PostgreSQL-12"),
Cmd: "scw rdb instance update {{ .Instance.ID }} tags.0=a --wait",
Check: core.TestCheckCombine(
func(t *testing.T, ctx *core.CheckFuncCtx) {
assert.Equal(t, "a", ctx.Result.(*rdb.Instance).Tags[0])
},
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
AfterFunc: deleteInstance(),
}))

t.Run("Set a timezone", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: createInstance("PostgreSQL-12"),
Cmd: "scw rdb instance update {{ .Instance.ID }} settings.0.name=timezone settings.0.value=UTC --wait",
Check: core.TestCheckCombine(
func(t *testing.T, ctx *core.CheckFuncCtx) {
assert.Equal(t, "timezone", ctx.Result.(*rdb.Instance).Settings[6].Name)
assert.Equal(t, "UTC", ctx.Result.(*rdb.Instance).Settings[6].Value)
},
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
AfterFunc: deleteInstance(),
}))

t.Run("Modify default work_mem from 4 to 8 MB", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: createInstance("PostgreSQL-12"),
Cmd: "scw rdb instance update {{ .Instance.ID }} settings.0.name=work_mem settings.0.value=8 --wait",
Check: core.TestCheckCombine(
func(t *testing.T, ctx *core.CheckFuncCtx) {
assert.Equal(t, "work_mem", ctx.Result.(*rdb.Instance).Settings[0].Name)
assert.Equal(t, "8", ctx.Result.(*rdb.Instance).Settings[0].Value)
},
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
AfterFunc: deleteInstance(),
}))

t.Run("Modify 3 settings + add a new one", core.Test(&core.TestConfig{
Commands: GetCommands(),
BeforeFunc: core.BeforeFuncCombine(
createInstance("PostgreSQL-12"),
core.ExecBeforeCmd("scw rdb instance update {{ .Instance.ID }} settings.0.name=work_mem settings.0.value=8"+
" settings.1.name=max_connections settings.1.value=200"+
" settings.2.name=effective_cache_size settings.2.value=1000"+
" name=foo1 --wait"),
),
Cmd: "scw rdb instance update {{ .Instance.ID }} settings.0.name=work_mem settings.0.value=16" +
" settings.1.name=max_connections settings.1.value=150" +
" settings.2.name=effective_cache_size settings.2.value=1200" +
" settings.3.name=maintenance_work_mem settings.3.value=200" +
" name=foo2 --wait",
Check: core.TestCheckCombine(
func(t *testing.T, ctx *core.CheckFuncCtx) {
assert.Equal(t, "work_mem", ctx.Result.(*rdb.Instance).Settings[0].Name)
assert.Equal(t, "16", ctx.Result.(*rdb.Instance).Settings[0].Value)
assert.Equal(t, "max_connections", ctx.Result.(*rdb.Instance).Settings[1].Name)
assert.Equal(t, "150", ctx.Result.(*rdb.Instance).Settings[1].Value)
assert.Equal(t, "effective_cache_size", ctx.Result.(*rdb.Instance).Settings[2].Name)
assert.Equal(t, "1200", ctx.Result.(*rdb.Instance).Settings[2].Value)
assert.Equal(t, "maintenance_work_mem", ctx.Result.(*rdb.Instance).Settings[3].Name)
assert.Equal(t, "200", ctx.Result.(*rdb.Instance).Settings[3].Value)
assert.Equal(t, "foo2", ctx.Result.(*rdb.Instance).Name)
},
core.TestCheckGolden(),
core.TestCheckExitCode(0),
),
AfterFunc: deleteInstance(),
}))
}

func Test_Connect(t *testing.T) {
t.Run("mysql", core.Test(&core.TestConfig{
Commands: GetCommands(),
Expand Down
Loading