From 3e5d4cd81cd7221f362427d94a78da7e1845a40a Mon Sep 17 00:00:00 2001 From: Anna Lushnikova Date: Mon, 16 Sep 2024 15:08:45 -0400 Subject: [PATCH] [databases]: add support for MongoDB advanced configuration (#726) --- databases.go | 47 ++++++++++++++++++++++++++++++ databases_test.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/databases.go b/databases.go index 8305770c..c0c91e2b 100644 --- a/databases.go +++ b/databases.go @@ -152,9 +152,11 @@ type DatabasesService interface { GetPostgreSQLConfig(context.Context, string) (*PostgreSQLConfig, *Response, error) GetRedisConfig(context.Context, string) (*RedisConfig, *Response, error) GetMySQLConfig(context.Context, string) (*MySQLConfig, *Response, error) + GetMongoDBConfig(context.Context, string) (*MongoDBConfig, *Response, error) UpdatePostgreSQLConfig(context.Context, string, *PostgreSQLConfig) (*Response, error) UpdateRedisConfig(context.Context, string, *RedisConfig) (*Response, error) UpdateMySQLConfig(context.Context, string, *MySQLConfig) (*Response, error) + UpdateMongoDBConfig(context.Context, string, *MongoDBConfig) (*Response, error) ListOptions(todo context.Context) (*DatabaseOptions, *Response, error) UpgradeMajorVersion(context.Context, string, *UpgradeVersionRequest) (*Response, error) ListTopics(context.Context, string, *ListOptions) ([]DatabaseTopic, *Response, error) @@ -648,6 +650,15 @@ type MySQLConfig struct { BinlogRetentionPeriod *int `json:"binlog_retention_period,omitempty"` } +// MongoDBConfig holds advanced configurations for MongoDB database clusters. +type MongoDBConfig struct { + DefaultReadConcern *string `json:"default_read_concern,omitempty"` + DefaultWriteConcern *string `json:"default_write_concern,omitempty"` + TransactionLifetimeLimitSeconds *int `json:"transaction_lifetime_limit_seconds,omitempty"` + SlowOpThresholdMs *int `json:"slow_op_threshold_ms,omitempty"` + Verbosity *int `json:"verbosity,omitempty"` +} + type databaseUserRoot struct { User *DatabaseUser `json:"user"` } @@ -688,6 +699,10 @@ type databaseMySQLConfigRoot struct { Config *MySQLConfig `json:"config"` } +type databaseMongoDBConfigRoot struct { + Config *MongoDBConfig `json:"config"` +} + type databaseBackupsRoot struct { Backups []DatabaseBackup `json:"backups"` } @@ -1499,6 +1514,38 @@ func (svc *DatabasesServiceOp) UpdateMySQLConfig(ctx context.Context, databaseID return resp, nil } +// GetMongoDBConfig retrieves the config for a MongoDB database cluster. +func (svc *DatabasesServiceOp) GetMongoDBConfig(ctx context.Context, databaseID string) (*MongoDBConfig, *Response, error) { + path := fmt.Sprintf(databaseConfigPath, databaseID) + req, err := svc.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + root := new(databaseMongoDBConfigRoot) + resp, err := svc.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Config, resp, nil +} + +// UpdateMongoDBConfig updates the config for a MongoDB database cluster. +func (svc *DatabasesServiceOp) UpdateMongoDBConfig(ctx context.Context, databaseID string, config *MongoDBConfig) (*Response, error) { + path := fmt.Sprintf(databaseConfigPath, databaseID) + root := &databaseMongoDBConfigRoot{ + Config: config, + } + req, err := svc.client.NewRequest(ctx, http.MethodPatch, path, root) + if err != nil { + return nil, err + } + resp, err := svc.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + // ListOptions gets the database options available. func (svc *DatabasesServiceOp) ListOptions(ctx context.Context) (*DatabaseOptions, *Response, error) { root := new(databaseOptionsRoot) diff --git a/databases_test.go b/databases_test.go index 601a6b4e..2721b9dc 100644 --- a/databases_test.go +++ b/databases_test.go @@ -2991,6 +2991,79 @@ func TestDatabases_UpdateConfigMySQL(t *testing.T) { require.NoError(t, err) } +func TestDatabases_GetConfigMongoDB(t *testing.T) { + setup() + defer teardown() + + var ( + dbSvc = client.Databases + dbID = "da4e0206-d019-41d7-b51f-deadbeefbb8f" + path = fmt.Sprintf("/v2/databases/%s/config", dbID) + + mongoDBConfigJSON = `{ + "config": { + "default_read_concern": "LOCAL", + "default_write_concern": "majority", + "transaction_lifetime_limit_seconds": 60, + "slow_op_threshold_ms": 100, + "verbosity": 0 + } +} +` + + mongoDBConfig = MongoDBConfig{ + DefaultReadConcern: PtrTo("LOCAL"), + DefaultWriteConcern: PtrTo("majority"), + TransactionLifetimeLimitSeconds: PtrTo(60), + SlowOpThresholdMs: PtrTo(100), + Verbosity: PtrTo(0), + } + ) + + mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, mongoDBConfigJSON) + }) + + got, _, err := dbSvc.GetMongoDBConfig(ctx, dbID) + require.NoError(t, err) + require.Equal(t, &mongoDBConfig, got) +} + +func TestDatabases_UpdateConfigMongoDB(t *testing.T) { + setup() + defer teardown() + + var ( + dbID = "deadbeef-dead-4aa5-beef-deadbeef347d" + path = fmt.Sprintf("/v2/databases/%s/config", dbID) + mongoDBConfig = &MongoDBConfig{ + DefaultReadConcern: PtrTo("AVAILABLE"), + DefaultWriteConcern: PtrTo(""), + SlowOpThresholdMs: PtrTo(0), + Verbosity: PtrTo(5), + } + ) + + mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPatch) + + var b databaseMongoDBConfigRoot + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(&b) + require.NoError(t, err) + + assert.Equal(t, b.Config, mongoDBConfig) + assert.Equal(t, "", *b.Config.DefaultWriteConcern, "pointers to zero value should be sent") + assert.Nil(t, b.Config.TransactionLifetimeLimitSeconds, "excluded value should not be sent") + + w.WriteHeader(http.StatusNoContent) + }) + + _, err := client.Databases.UpdateMongoDBConfig(ctx, dbID, mongoDBConfig) + require.NoError(t, err) +} + func TestDatabases_UpgradeMajorVersion(t *testing.T) { setup() defer teardown()