diff --git a/databases.go b/databases.go index 14d5a04..952663e 100644 --- a/databases.go +++ b/databases.go @@ -34,6 +34,7 @@ const ( databasePromoteReplicaToPrimaryPath = databaseReplicaPath + "/promote" databaseTopicPath = databaseBasePath + "/%s/topics/%s" databaseTopicsPath = databaseBasePath + "/%s/topics" + databaseMetricsCredentialsPath = databaseBasePath + "/metrics/credentials" ) // SQL Mode constants allow for MySQL-specific SQL flavor configuration. @@ -154,6 +155,8 @@ type DatabasesService interface { GetTopic(context.Context, string, string) (*DatabaseTopic, *Response, error) DeleteTopic(context.Context, string, string) (*Response, error) UpdateTopic(context.Context, string, string, *DatabaseUpdateTopicRequest) (*Response, error) + GetMetricsCredentials(context.Context) (*DatabaseMetricsCredentials, *Response, error) + UpdateMetricsCredentials(context.Context, *DatabaseUpdateMetricsCredentialsRequest) (*Response, error) } // DatabasesServiceOp handles communication with the Databases related methods @@ -190,6 +193,7 @@ type Database struct { Tags []string `json:"tags,omitempty"` ProjectID string `json:"project_id,omitempty"` StorageSizeMib uint64 `json:"storage_size_mib,omitempty"` + MetricsEndpoints []*ServiceAddress `json:"metrics_endpoints,omitempty"` } // DatabaseCA represents a database ca. @@ -210,6 +214,12 @@ type DatabaseConnection struct { ApplicationPorts map[string]uint32 `json:"application_ports,omitempty"` } +// ServiceAddress represents a host:port for a generic service (e.g. metrics endpoint) +type ServiceAddress struct { + Host string `json:"host"` + Port int `json:"port"` +} + // DatabaseUser represents a user in the database type DatabaseUser struct { Name string `json:"name,omitempty"` @@ -666,6 +676,19 @@ type databaseTopicsRoot struct { Topics []DatabaseTopic `json:"topics"` } +type databaseMetricsCredentialsRoot struct { + Credentials *DatabaseMetricsCredentials `json:"credentials"` +} + +type DatabaseMetricsCredentials struct { + BasicAuthUsername string `json:"basic_auth_username"` + BasicAuthPassword string `json:"basic_auth_password"` +} + +type DatabaseUpdateMetricsCredentialsRequest struct { + Credentials *DatabaseMetricsCredentials `json:"credentials"` +} + // DatabaseOptions represents the available database engines type DatabaseOptions struct { MongoDBOptions DatabaseEngineOptions `json:"mongodb"` @@ -1466,3 +1489,31 @@ func (svc *DatabasesServiceOp) DeleteTopic(ctx context.Context, databaseID, name } return resp, nil } + +// GetMetricsCredentials gets the credentials required to access a user's metrics endpoints +func (svc *DatabasesServiceOp) GetMetricsCredentials(ctx context.Context) (*DatabaseMetricsCredentials, *Response, error) { + req, err := svc.client.NewRequest(ctx, http.MethodGet, databaseMetricsCredentialsPath, nil) + if err != nil { + return nil, nil, err + } + + root := new(databaseMetricsCredentialsRoot) + resp, err := svc.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Credentials, resp, nil +} + +// UpdateMetricsAuth updates the credentials required to access a user's metrics endpoints +func (svc *DatabasesServiceOp) UpdateMetricsCredentials(ctx context.Context, updateCreds *DatabaseUpdateMetricsCredentialsRequest) (*Response, error) { + req, err := svc.client.NewRequest(ctx, http.MethodPut, databaseMetricsCredentialsPath, updateCreds) + if err != nil { + return nil, err + } + resp, err := svc.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} diff --git a/databases_test.go b/databases_test.go index bd34803..e95db8a 100644 --- a/databases_test.go +++ b/databases_test.go @@ -79,6 +79,16 @@ var db = Database{ Tags: []string{"production", "staging"}, ProjectID: "6d0f9073-0a24-4f1b-9065-7dc5c8bad3e2", StorageSizeMib: 61440, + MetricsEndpoints: []*ServiceAddress{ + { + Host: "dbtest-do-user-3342561-0.db.ondigitalocean.com", + Port: 9273, + }, + { + Host: "replica-dbtest-do-user-3342561-0.db.ondigitalocean.com", + Port: 9273, + }, + }, } var dbJSON = ` @@ -147,7 +157,17 @@ var dbJSON = ` "private_network_uuid": "da4e0206-d019-41d7-b51f-deadbeefbb8f", "tags": ["production", "staging"], "project_id": "6d0f9073-0a24-4f1b-9065-7dc5c8bad3e2", - "storage_size_mib": 61440 + "storage_size_mib": 61440, + "metrics_endpoints": [ + { + "host": "dbtest-do-user-3342561-0.db.ondigitalocean.com", + "port": 9273 + }, + { + "host": "replica-dbtest-do-user-3342561-0.db.ondigitalocean.com", + "port": 9273 + } + ] } ` @@ -3063,3 +3083,48 @@ func TestDatabases_ListTopics(t *testing.T) { require.NoError(t, err) require.Equal(t, want, got) } + +func TestDatabases_GetMetricsCredentials(t *testing.T) { + setup() + defer teardown() + + want := &DatabaseMetricsCredentials{ + BasicAuthUsername: "username_for_http_basic_auth", + BasicAuthPassword: "password_for_http_basic_auth", + } + + body := `{ + "credentials": { + "basic_auth_username": "username_for_http_basic_auth", + "basic_auth_password": "password_for_http_basic_auth" + } + }` + + mux.HandleFunc("/v2/databases/metrics/credentials", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, body) + }) + + got, _, err := client.Databases.GetMetricsCredentials(ctx) + require.NoError(t, err) + require.Equal(t, want, got) +} + +func TestDatabases_UpdateMetricsCredentials(t *testing.T) { + setup() + defer teardown() + + updateRequest := &DatabaseUpdateMetricsCredentialsRequest{ + Credentials: &DatabaseMetricsCredentials{ + BasicAuthUsername: "username_for_http_basic_auth", + BasicAuthPassword: "password_for_http_basic_auth", + }, + } + + mux.HandleFunc("/v2/databases/metrics/credentials", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPut) + }) + + _, err := client.Databases.UpdateMetricsCredentials(ctx, updateRequest) + require.NoError(t, err) +}