Skip to content

Commit

Permalink
[databases]: add support for MongoDB advanced configuration (#1582)
Browse files Browse the repository at this point in the history
* [databases]: add support for MongoDB advanced configuration

* use mongodb as a slug
  • Loading branch information
loosla committed Sep 18, 2024
1 parent aa0ecb5 commit 61ea343
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 10 deletions.
36 changes: 28 additions & 8 deletions commands/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -2439,6 +2439,7 @@ func databaseConfiguration() *Command {
displayerType(&displayers.MySQLConfiguration{}),
displayerType(&displayers.PostgreSQLConfiguration{}),
displayerType(&displayers.RedisConfiguration{}),
displayerType(&displayers.MongoDBConfiguration{}),
)
AddStringFlag(
getDatabaseCfgCommand,
Expand Down Expand Up @@ -2493,12 +2494,13 @@ func RunDatabaseConfigurationGet(c *CmdConfig) error {
}

allowedEngines := map[string]any{
"mysql": nil,
"pg": nil,
"redis": nil,
"mysql": nil,
"pg": nil,
"redis": nil,
"mongodb": nil,
}
if _, ok := allowedEngines[engine]; !ok {
return fmt.Errorf("(%s) command: engine must be one of: 'pg', 'mysql', 'redis'", c.NS)
return fmt.Errorf("(%s) command: engine must be one of: 'pg', 'mysql', 'redis', 'mongodb'", c.NS)
}

dbId := args[0]
Expand Down Expand Up @@ -2532,7 +2534,18 @@ func RunDatabaseConfigurationGet(c *CmdConfig) error {
RedisConfig: *config,
}
return c.Display(&displayer)
} else if engine == "mongodb" {
config, err := c.Databases().GetMongoDBConfiguration(dbId)
if err != nil {
return err
}

displayer := displayers.MongoDBConfiguration{
MongoDBConfig: *config,
}
return c.Display(&displayer)
}

return nil
}

Expand All @@ -2551,12 +2564,13 @@ func RunDatabaseConfigurationUpdate(c *CmdConfig) error {
}

allowedEngines := map[string]any{
"mysql": nil,
"pg": nil,
"redis": nil,
"mysql": nil,
"pg": nil,
"redis": nil,
"mongodb": nil,
}
if _, ok := allowedEngines[engine]; !ok {
return fmt.Errorf("(%s) command: engine must be one of: 'pg', 'mysql', 'redis'", c.NS)
return fmt.Errorf("(%s) command: engine must be one of: 'pg', 'mysql', 'redis', 'mongodb'", c.NS)
}

configJson, err := c.Doit.GetString(c.NS, doctl.ArgDatabaseConfigJson)
Expand All @@ -2580,7 +2594,13 @@ func RunDatabaseConfigurationUpdate(c *CmdConfig) error {
if err != nil {
return err
}
} else if engine == "mongodb" {
err := c.Databases().UpdateMongoDBConfiguration(dbId, configJson)
if err != nil {
return err
}
}

return nil
}

Expand Down
78 changes: 78 additions & 0 deletions commands/databases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ var (
RedisConfig: &godo.RedisConfig{},
}

testMongoDBConfiguration = do.MongoDBConfig{
MongoDBConfig: &godo.MongoDBConfig{},
}

topicReplicationFactor = uint32(3)
testKafkaTopic = do.DatabaseTopic{
DatabaseTopic: &godo.DatabaseTopic{
Expand Down Expand Up @@ -1652,6 +1656,16 @@ func TestDatabaseConfigurationGet(t *testing.T) {
assert.NoError(t, err)
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.databases.EXPECT().GetMongoDBConfiguration(testDBCluster.ID).Return(&testMongoDBConfiguration, nil)
config.Args = append(config.Args, testDBCluster.ID)
config.Doit.Set(config.NS, doctl.ArgDatabaseEngine, "mongodb")

err := RunDatabaseConfigurationGet(config)

assert.NoError(t, err)
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
err := RunDatabaseConfigurationGet(config)

Expand All @@ -1674,3 +1688,67 @@ func TestDatabaseConfigurationGet(t *testing.T) {
assert.Error(t, err)
})
}

func TestDatabaseConfigurationUpdate(t *testing.T) {
withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.databases.EXPECT().UpdateMySQLConfiguration(testDBCluster.ID, "").Return(nil)
config.Args = append(config.Args, testDBCluster.ID)
config.Doit.Set(config.NS, doctl.ArgDatabaseEngine, "mysql")

err := RunDatabaseConfigurationUpdate(config)

assert.NoError(t, err)
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.databases.EXPECT().UpdatePostgreSQLConfiguration(testDBCluster.ID, "").Return(nil)
config.Args = append(config.Args, testDBCluster.ID)
config.Doit.Set(config.NS, doctl.ArgDatabaseEngine, "pg")

err := RunDatabaseConfigurationUpdate(config)

assert.NoError(t, err)
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.databases.EXPECT().UpdateRedisConfiguration(testDBCluster.ID, "").Return(nil)
config.Args = append(config.Args, testDBCluster.ID)
config.Doit.Set(config.NS, doctl.ArgDatabaseEngine, "redis")

err := RunDatabaseConfigurationUpdate(config)

assert.NoError(t, err)
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
tm.databases.EXPECT().UpdateMongoDBConfiguration(testDBCluster.ID, "").Return(nil)
config.Args = append(config.Args, testDBCluster.ID)
config.Doit.Set(config.NS, doctl.ArgDatabaseEngine, "mongodb")

err := RunDatabaseConfigurationUpdate(config)

assert.NoError(t, err)
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
err := RunDatabaseConfigurationUpdate(config)

assert.Equal(t, err, doctl.NewMissingArgsErr(config.NS))
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
config.Args = append(config.Args, testDBCluster.ID, "extra arg")

err := RunDatabaseConfigurationUpdate(config)

assert.Equal(t, err, doctl.NewTooManyArgsErr(config.NS))
})

withTestClient(t, func(config *CmdConfig, tm *tcMocks) {
config.Args = append(config.Args, testDBCluster.ID)

err := RunDatabaseConfigurationUpdate(config)

assert.Error(t, err)
})
}
61 changes: 61 additions & 0 deletions commands/displayers/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,67 @@ func (dc *RedisConfiguration) KV() []map[string]any {
return o
}

type MongoDBConfiguration struct {
MongoDBConfig do.MongoDBConfig
}

var _ Displayable = &MongoDBConfiguration{}

func (dc *MongoDBConfiguration) JSON(out io.Writer) error {
return writeJSON(dc.MongoDBConfig, out)
}

func (dc *MongoDBConfiguration) Cols() []string {
return []string{
"key",
"value",
}
}

func (dc *MongoDBConfiguration) ColMap() map[string]string {
return map[string]string{
"key": "key",
"value": "value",
}
}

func (dc *MongoDBConfiguration) KV() []map[string]any {
c := dc.MongoDBConfig
o := []map[string]any{}
if c.DefaultReadConcern != nil {
o = append(o, map[string]any{
"key": "DefaultReadConcern",
"value": *c.DefaultReadConcern,
})
}
if c.DefaultWriteConcern != nil {
o = append(o, map[string]any{
"key": "DefaultWriteConcern",
"value": *c.DefaultWriteConcern,
})
}
if c.SlowOpThresholdMs != nil {
o = append(o, map[string]any{
"key": "SlowOpThresholdMs",
"value": *c.SlowOpThresholdMs,
})
}
if c.TransactionLifetimeLimitSeconds != nil {
o = append(o, map[string]any{
"key": "TransactionLifetimeLimitSeconds",
"value": *c.TransactionLifetimeLimitSeconds,
})
}
if c.Verbosity != nil {
o = append(o, map[string]any{
"key": "Verbosity",
"value": *c.Verbosity,
})
}

return o
}

type DatabaseEvents struct {
DatabaseEvents do.DatabaseEvents
}
Expand Down
33 changes: 33 additions & 0 deletions do/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ type RedisConfig struct {
*godo.RedisConfig
}

// MongoDBConfig is a wrapper for godo.MongoDBConfig
type MongoDBConfig struct {
*godo.MongoDBConfig
}

// DatabaseTopics is a slice of DatabaseTopic
type DatabaseTopics []DatabaseTopic

Expand Down Expand Up @@ -200,10 +205,12 @@ type DatabasesService interface {
GetMySQLConfiguration(databaseID string) (*MySQLConfig, error)
GetPostgreSQLConfiguration(databaseID string) (*PostgreSQLConfig, error)
GetRedisConfiguration(databaseID string) (*RedisConfig, error)
GetMongoDBConfiguration(databaseID string) (*MongoDBConfig, error)

UpdateMySQLConfiguration(databaseID string, confString string) error
UpdatePostgreSQLConfiguration(databaseID string, confString string) error
UpdateRedisConfiguration(databaseID string, confString string) error
UpdateMongoDBConfiguration(databaseID string, confString string) error

ListTopics(string) (DatabaseTopics, error)
GetTopic(string, string) (*DatabaseTopic, error)
Expand Down Expand Up @@ -695,6 +702,17 @@ func (ds *databasesService) GetRedisConfiguration(databaseID string) (*RedisConf
}, nil
}

func (ds *databasesService) GetMongoDBConfiguration(databaseID string) (*MongoDBConfig, error) {
cfg, _, err := ds.client.Databases.GetMongoDBConfig(context.TODO(), databaseID)
if err != nil {
return nil, err
}

return &MongoDBConfig{
MongoDBConfig: cfg,
}, nil
}

func (ds *databasesService) UpdateMySQLConfiguration(databaseID string, confString string) error {
var conf godo.MySQLConfig
err := json.Unmarshal([]byte(confString), &conf)
Expand Down Expand Up @@ -740,6 +758,21 @@ func (ds *databasesService) UpdateRedisConfiguration(databaseID string, confStri
return nil
}

func (ds *databasesService) UpdateMongoDBConfiguration(databaseID string, confString string) error {
var conf godo.MongoDBConfig
err := json.Unmarshal([]byte(confString), &conf)
if err != nil {
return err
}

_, err = ds.client.Databases.UpdateMongoDBConfig(context.TODO(), databaseID, &conf)
if err != nil {
return err
}

return nil
}

func (ds *databasesService) ListTopics(databaseID string) (DatabaseTopics, error) {
f := func(opt *godo.ListOptions) ([]any, *godo.Response, error) {
list, resp, err := ds.client.Databases.ListTopics(context.TODO(), databaseID, opt)
Expand Down
29 changes: 29 additions & 0 deletions do/mocks/DatabasesService.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 23 additions & 2 deletions integration/database_config_get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ var _ = suite("database/config/get", func(t *testing.T, when spec.G, it spec.S)
}

w.Write([]byte(databaseConfigRedisGetResponse))
case "/v2/databases/mongodb-database-id/config":
auth := req.Header.Get("Authorization")
if auth != "Bearer some-magic-token" {
w.WriteHeader(http.StatusTeapot)
}

if req.Method != http.MethodGet {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}

w.Write([]byte(databaseConfigMongoDBGetResponse))
default:
dump, err := httputil.DumpRequest(req, true)
if err != nil {
Expand Down Expand Up @@ -256,6 +268,15 @@ RedisACLChannelsDefault allchannels
"redis_persistence": "rdb",
"redis_acl_channels_default": "allchannels"
}
}
`
}`

databaseConfigMongoDBGetResponse = `{
"config": {
"default_read_concern": "local",
"default_write_concern": "majority",
"slow_op_threshold_ms": 100,
"transaction_lifetime_limit_seconds": 60,
"verbosity": 1
}
}`
)
Loading

0 comments on commit 61ea343

Please sign in to comment.