diff --git a/args.go b/args.go index 6e2499eac..d2ee82424 100644 --- a/args.go +++ b/args.go @@ -368,6 +368,8 @@ const ( ArgDatabaseEngine = "engine" // ArgDatabaseNumNodes is the number of nodes in the database cluster ArgDatabaseNumNodes = "num-nodes" + // ArgDatabaseStorageSizeMib is the amount of disk space, in MiB, that should be allocated to the database cluster + ArgDatabaseStorageSizeMib = "storage-size-mib" // ArgDatabaseMaintenanceDay is the new day for the maintenance window ArgDatabaseMaintenanceDay = "day" // ArgDatabaseMaintenanceHour is the new hour for the maintenance window diff --git a/commands/databases.go b/commands/databases.go index 13c58290e..8f0a76566 100644 --- a/commands/databases.go +++ b/commands/databases.go @@ -69,6 +69,7 @@ func Databases() *Command { nodeSizeDetails := "The size of the nodes in the database cluster, e.g. `db-s-1vcpu-1gb`` for a 1 CPU, 1GB node. For a list of available size slugs, visit: https://docs.digitalocean.com/reference/api/api-reference/#tag/Databases" nodeNumberDetails := "The number of nodes in the database cluster. Valid values are 1-3. In addition to the primary node, up to two standby nodes may be added for high availability." + storageSizeMiBDetails := "The amount of disk space allocated to the cluster. Applicable for PostgreSQL and MySQL clusters. This will be set to a default level based on the plan size selected, but can be increased in increments up to a maximum amount. For ranges, visit: https://www.digitalocean.com/pricing/managed-databases" cmdDatabaseCreate := CmdBuilder(cmd, RunDatabaseCreate, "create ", "Create a database cluster", `This command creates a database cluster with the specified name. There are a number of flags that customize the configuration, all of which are optional. Without any flags set, a single-node, single-CPU PostgreSQL database cluster will be created.`, Writer, @@ -76,6 +77,7 @@ There are a number of flags that customize the configuration, all of which are o AddIntFlag(cmdDatabaseCreate, doctl.ArgDatabaseNumNodes, "", defaultDatabaseNodeCount, nodeNumberDetails) AddStringFlag(cmdDatabaseCreate, doctl.ArgRegionSlug, "", defaultDatabaseRegion, "The region where the database cluster will be created, e.g. `nyc1` or `sfo2`") AddStringFlag(cmdDatabaseCreate, doctl.ArgSizeSlug, "", defaultDatabaseNodeSize, nodeSizeDetails) + AddIntFlag(cmdDatabaseCreate, doctl.ArgDatabaseStorageSizeMib, "", 0, storageSizeMiBDetails) AddStringFlag(cmdDatabaseCreate, doctl.ArgDatabaseEngine, "", defaultDatabaseEngine, "The database engine to be used for the cluster. Possible values are: `pg` for PostgreSQL, `mysql`, `redis`, `mongodb`, and `kafka`.") AddStringFlag(cmdDatabaseCreate, doctl.ArgVersion, "", "", "The database engine version, e.g. 14 for PostgreSQL version 14") AddStringFlag(cmdDatabaseCreate, doctl.ArgPrivateNetworkUUID, "", "", "The UUID of a VPC to create the database cluster in; the default VPC for the region will be used if excluded") @@ -115,10 +117,15 @@ You must specify the desired number of nodes and size of the nodes. For example: doctl databases resize ca9f591d-9999-5555-a0ef-1c02d1d1e352 --num-nodes 2 --size db-s-16vcpu-64gb -Database nodes cannot be resized to smaller sizes due to the risk of data loss.`, Writer, +Database nodes cannot be resized to smaller sizes due to the risk of data loss. + +In addition, for PostgreSQL and MySQL clusters, you can provide a disk size in MiB, which will set the total storage (up to a certain range) to the cluster independently. Storage cannot be reduced from its current levels. For example: + + doctl databases resize ca9f591d-9999-5555-a0ef-1c02d1d1e352 --num-nodes 2 --size db-s-16vcpu-64gb --storage-size-mib 2048000`, Writer, aliasOpt("rs")) AddIntFlag(cmdDatabaseResize, doctl.ArgDatabaseNumNodes, "", 0, nodeNumberDetails, requiredOpt()) AddStringFlag(cmdDatabaseResize, doctl.ArgSizeSlug, "", "", nodeSizeDetails, requiredOpt()) + AddIntFlag(cmdDatabaseResize, doctl.ArgDatabaseStorageSizeMib, "", 0, storageSizeMiBDetails) cmdDatabaseMigrate := CmdBuilder(cmd, RunDatabaseMigrate, "migrate ", "Migrate a database cluster to a new region", `This command migrates the specified database cluster to a new region`, Writer, aliasOpt("m")) @@ -292,6 +299,12 @@ func buildDatabaseCreateRequestFromArgs(c *CmdConfig) (*godo.DatabaseCreateReque r.PrivateNetworkUUID = privateNetworkUUID + storageSizeMibInt, err := c.Doit.GetInt(c.NS, doctl.ArgDatabaseStorageSizeMib) + if err != nil { + return nil, err + } + r.StorageSizeMib = uint64(storageSizeMibInt) + return r, nil } @@ -494,6 +507,12 @@ func buildDatabaseResizeRequestFromArgs(c *CmdConfig) (*godo.DatabaseResizeReque } r.SizeSlug = size + storageSizeMibInt, err := c.Doit.GetInt(c.NS, doctl.ArgDatabaseStorageSizeMib) + if err != nil { + return nil, err + } + r.StorageSizeMib = uint64(storageSizeMibInt) + return r, nil } diff --git a/commands/databases_test.go b/commands/databases_test.go index 4b9e52ba6..2d9de8748 100644 --- a/commands/databases_test.go +++ b/commands/databases_test.go @@ -62,6 +62,7 @@ var ( }, PrivateNetworkUUID: "1fe49b6c-ac8e-11e9-98cb-3bec94f411bc", Tags: []string{"testing"}, + StorageSizeMib: 20480, }, } @@ -341,6 +342,7 @@ func TestDatabasesCreate(t *testing.T) { SizeSlug: testDBCluster.SizeSlug, PrivateNetworkUUID: testDBCluster.PrivateNetworkUUID, Tags: testDBCluster.Tags, + StorageSizeMib: testDBCluster.StorageSizeMib, } // Successful call @@ -355,6 +357,7 @@ func TestDatabasesCreate(t *testing.T) { config.Doit.Set(config.NS, doctl.ArgDatabaseNumNodes, testDBCluster.NumNodes) config.Doit.Set(config.NS, doctl.ArgPrivateNetworkUUID, testDBCluster.PrivateNetworkUUID) config.Doit.Set(config.NS, doctl.ArgTag, testDBCluster.Tags) + config.Doit.Set(config.NS, doctl.ArgDatabaseStorageSizeMib, testDBCluster.StorageSizeMib) err := RunDatabaseCreate(config) assert.NoError(t, err) @@ -507,8 +510,9 @@ func TestDatabaseMigrate(t *testing.T) { func TestDatabaseResize(t *testing.T) { r := &godo.DatabaseResizeRequest{ - SizeSlug: testDBCluster.SizeSlug, - NumNodes: testDBCluster.NumNodes, + SizeSlug: testDBCluster.SizeSlug, + NumNodes: testDBCluster.NumNodes, + StorageSizeMib: testDBCluster.StorageSizeMib, } // Success @@ -517,6 +521,7 @@ func TestDatabaseResize(t *testing.T) { config.Args = append(config.Args, testDBCluster.ID) config.Doit.Set(config.NS, doctl.ArgSizeSlug, testDBCluster.SizeSlug) config.Doit.Set(config.NS, doctl.ArgDatabaseNumNodes, testDBCluster.NumNodes) + config.Doit.Set(config.NS, doctl.ArgDatabaseStorageSizeMib, testDBCluster.StorageSizeMib) err := RunDatabaseResize(config) assert.NoError(t, err) @@ -528,6 +533,7 @@ func TestDatabaseResize(t *testing.T) { config.Args = append(config.Args, testDBCluster.ID) config.Doit.Set(config.NS, doctl.ArgSizeSlug, testDBCluster.SizeSlug) config.Doit.Set(config.NS, doctl.ArgDatabaseNumNodes, testDBCluster.NumNodes) + config.Doit.Set(config.NS, doctl.ArgDatabaseStorageSizeMib, testDBCluster.StorageSizeMib) err := RunDatabaseResize(config) assert.EqualError(t, err, errTest.Error()) diff --git a/commands/displayers/database.go b/commands/displayers/database.go index 157c8747f..0653d2c4a 100644 --- a/commands/displayers/database.go +++ b/commands/displayers/database.go @@ -45,6 +45,7 @@ func (d *Databases) Cols() []string { "Region", "Status", "Size", + "StorageMib", } } @@ -59,34 +60,37 @@ func (d *Databases) Cols() []string { "Size", "URI", "Created", + "StorageMib", } } func (d *Databases) ColMap() map[string]string { if d.Short { return map[string]string{ - "ID": "ID", - "Name": "Name", - "Engine": "Engine", - "Version": "Version", - "NumNodes": "Number of Nodes", - "Region": "Region", - "Status": "Status", - "Size": "Size", + "ID": "ID", + "Name": "Name", + "Engine": "Engine", + "Version": "Version", + "NumNodes": "Number of Nodes", + "Region": "Region", + "Status": "Status", + "Size": "Size", + "StorageMib": "Storage (MiB)", } } return map[string]string{ - "ID": "ID", - "Name": "Name", - "Engine": "Engine", - "Version": "Version", - "NumNodes": "Number of Nodes", - "Region": "Region", - "Status": "Status", - "Size": "Size", - "URI": "URI", - "Created": "Created At", + "ID": "ID", + "Name": "Name", + "Engine": "Engine", + "Version": "Version", + "NumNodes": "Number of Nodes", + "Region": "Region", + "Status": "Status", + "Size": "Size", + "StorageMib": "Storage (MiB)", + "URI": "URI", + "Created": "Created At", } } @@ -95,16 +99,17 @@ func (d *Databases) KV() []map[string]interface{} { for _, db := range d.Databases { o := map[string]interface{}{ - "ID": db.ID, - "Name": db.Name, - "Engine": db.EngineSlug, - "Version": db.VersionSlug, - "NumNodes": db.NumNodes, - "Region": db.RegionSlug, - "Status": db.Status, - "Size": db.SizeSlug, - "URI": db.Connection.URI, - "Created": db.CreatedAt, + "ID": db.ID, + "Name": db.Name, + "Engine": db.EngineSlug, + "Version": db.VersionSlug, + "NumNodes": db.NumNodes, + "Region": db.RegionSlug, + "Status": db.Status, + "Size": db.SizeSlug, + "StorageMib": db.StorageSizeMib, + "URI": db.Connection.URI, + "Created": db.CreatedAt, } out = append(out, o) }