From 3a1dc8ce5885ca7b008e73b847138eb96e8dff1b Mon Sep 17 00:00:00 2001 From: Husni Mansour Date: Fri, 21 Jun 2024 15:09:05 +0200 Subject: [PATCH] CLOUDP-252326: Replace Atlas dependency phase 2 --- opsmngr/checkpoints.go | 41 +++++++++-- opsmngr/checkpoints_test.go | 57 +++++++------- opsmngr/continuous_restore_jobs.go | 5 ++ opsmngr/continuous_snapshots.go | 70 ++++++++++++++++-- opsmngr/continuous_snapshots_test.go | 37 +++++----- opsmngr/diagnostics.go | 4 +- opsmngr/logs.go | 4 +- opsmngr/opsmngr.go | 29 +++++--- opsmngr/performance_advisor.go | 106 ++++++++++++++++++++++++--- opsmngr/performance_advisor_test.go | 31 ++++---- opsmngr/snapshot_schedule.go | 28 ++++--- 11 files changed, 289 insertions(+), 123 deletions(-) diff --git a/opsmngr/checkpoints.go b/opsmngr/checkpoints.go index cd3276f..2575e2a 100644 --- a/opsmngr/checkpoints.go +++ b/opsmngr/checkpoints.go @@ -18,20 +18,45 @@ import ( "context" "fmt" "net/http" - - atlas "go.mongodb.org/atlas/mongodbatlas" ) const ( checkpoints = "api/public/v1.0/groups/%s/clusters/%s/checkpoints" ) +// Checkpoint represents MongoDB Checkpoint. +type Checkpoint struct { + ClusterID string `json:"clusterId"` + Completed string `json:"completed,omitempty"` + GroupID string `json:"groupId"` + ID string `json:"id,omitempty"` // Unique identifier of the checkpoint. + Links []*Link `json:"links,omitempty"` // One or more links to sub-resources and/or related resources. + Parts []*Part `json:"parts,omitempty"` + Restorable bool `json:"restorable"` + Started string `json:"started"` + Timestamp string `json:"timestamp"` +} + +// CheckpointPart represents the individual parts that comprise the complete checkpoint. +type CheckpointPart struct { + ShardName string `json:"shardName"` + TokenDiscovered bool `json:"tokenDiscovered"` + TokenTimestamp SnapshotTimestamp `json:"tokenTimestamp"` +} + +// Checkpoints represents all the backup checkpoints related to a cluster. +type Checkpoints struct { + Results []*Checkpoint `json:"results,omitempty"` // Includes one Checkpoint object for each item detailed in the results array section. + Links []*Link `json:"links,omitempty"` // One or more links to sub-resources and/or related resources. + TotalCount int `json:"totalCount,omitempty"` // Count of the total number of items in the result set. It may be greater than the number of objects in the results array if the entire result set is paginated. +} + // CheckpointsService provides access to the backup related functions in the Ops Manager API. // // See more: https://docs.opsmanager.mongodb.com/current/reference/api/checkpoints/ type CheckpointsService interface { - List(context.Context, string, string, *ListOptions) (*atlas.Checkpoints, *Response, error) - Get(context.Context, string, string, string) (*atlas.Checkpoint, *Response, error) + List(context.Context, string, string, *ListOptions) (*Checkpoints, *Response, error) + Get(context.Context, string, string, string) (*Checkpoint, *Response, error) } // CheckpointsServiceOp provides an implementation of the CheckpointsService interface. @@ -42,7 +67,7 @@ var _ CheckpointsService = &CheckpointsServiceOp{} // List lists checkpoints. // // See https://docs.opsmanager.mongodb.com/current/reference/api/checkpoints/#get-all-checkpoints -func (s *CheckpointsServiceOp) List(ctx context.Context, groupID, clusterName string, listOptions *ListOptions) (*atlas.Checkpoints, *Response, error) { +func (s *CheckpointsServiceOp) List(ctx context.Context, groupID, clusterName string, listOptions *ListOptions) (*Checkpoints, *Response, error) { if groupID == "" { return nil, nil, NewArgError("groupId", "must be set") } @@ -61,7 +86,7 @@ func (s *CheckpointsServiceOp) List(ctx context.Context, groupID, clusterName st return nil, nil, err } - root := new(atlas.Checkpoints) + root := new(Checkpoints) resp, err := s.Client.Do(ctx, req, root) return root, resp, err @@ -70,7 +95,7 @@ func (s *CheckpointsServiceOp) List(ctx context.Context, groupID, clusterName st // Get gets a checkpoint. // // See https://docs.opsmanager.mongodb.com/current/reference/api/checkpoints/#get-one-checkpoint -func (s *CheckpointsServiceOp) Get(ctx context.Context, groupID, clusterID, checkpointID string) (*atlas.Checkpoint, *Response, error) { +func (s *CheckpointsServiceOp) Get(ctx context.Context, groupID, clusterID, checkpointID string) (*Checkpoint, *Response, error) { if groupID == "" { return nil, nil, NewArgError("groupId", "must be set") } @@ -89,7 +114,7 @@ func (s *CheckpointsServiceOp) Get(ctx context.Context, groupID, clusterID, chec return nil, nil, err } - root := new(atlas.Checkpoint) + root := new(Checkpoint) resp, err := s.Client.Do(ctx, req, root) return root, resp, err diff --git a/opsmngr/checkpoints_test.go b/opsmngr/checkpoints_test.go index b41fba9..8377a71 100644 --- a/opsmngr/checkpoints_test.go +++ b/opsmngr/checkpoints_test.go @@ -20,7 +20,6 @@ import ( "testing" "github.com/go-test/deep" - atlas "go.mongodb.org/atlas/mongodbatlas" ) const clusterID = "6b8cd61180eef547110159d9" //nolint:gosec // not a credential @@ -145,27 +144,27 @@ func TestCheckpoints_List(t *testing.T) { t.Fatalf("Checkpoints.List returned error: %v", err) } - expected := &atlas.Checkpoints{ - Results: []*atlas.Checkpoint{ + expected := &Checkpoints{ + Results: []*Checkpoint{ { ClusterID: clusterID, Completed: "2018-02-08T23:20:25Z", GroupID: projectID, ID: "5a7cdb3980eef53de5bffdcf", - Links: []*atlas.Link{ + Links: []*Link{ { Rel: "self", Href: "https://cloud.mongodb.com/api/public/v1.0/groups/5c8100bcf2a30b12ff88258f/clusters/Cluster0/checkpoints", }, }, - Parts: []*atlas.Part{ + Parts: []*Part{ { ReplicaSetName: "Cluster0-shard-1", TypeName: "REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ ShardName: "Cluster0-shard-1", TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-08T23:20:25Z", Increment: 1, }}, @@ -173,10 +172,10 @@ func TestCheckpoints_List(t *testing.T) { { ReplicaSetName: "Cluster0-shard-0", TypeName: "REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ ShardName: "Cluster0-shard-0", TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-08T23:20:25Z", Increment: 1, }}, @@ -184,9 +183,9 @@ func TestCheckpoints_List(t *testing.T) { { ReplicaSetName: "Cluster0-config-0", TypeName: "CONFIG_SERVER_REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-08T23:20:25Z", Increment: 2, }}, @@ -201,20 +200,20 @@ func TestCheckpoints_List(t *testing.T) { Completed: "2018-02-09T14:50:33Z", GroupID: projectID, ID: "5a7db53987d9d64fe298ff46", - Links: []*atlas.Link{ + Links: []*Link{ { Rel: "self", Href: "https://cloud.mongodb.com/api/public/v1.0/groups/5c8100bcf2a30b12ff88258f/clusters/Cluster0/checkpoints?pretty=true", }, }, - Parts: []*atlas.Part{ + Parts: []*Part{ { ReplicaSetName: "Cluster0-shard-1", TypeName: "REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ ShardName: "Cluster0-shard-1", TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-09T14:50:33Z", Increment: 1, }}, @@ -222,10 +221,10 @@ func TestCheckpoints_List(t *testing.T) { { ReplicaSetName: "Cluster0-shard-0", TypeName: "REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ ShardName: "Cluster0-shard-0", TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-09T14:50:33Z", Increment: 2, }}, @@ -233,9 +232,9 @@ func TestCheckpoints_List(t *testing.T) { { ReplicaSetName: "Cluster0-config-0", TypeName: "CONFIG_SERVER_REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-09T14:50:33Z", Increment: 4, }}, @@ -246,7 +245,7 @@ func TestCheckpoints_List(t *testing.T) { Timestamp: "2018-02-09T14:50:18Z", }, }, - Links: []*atlas.Link{ + Links: []*Link{ { Href: "https://cloud.mongodb.com/api/public/v1.0/groups/5c8100bcf2a30b12ff88258f/clusters/Cluster0/checkpoints?pageNum=1&itemsPerPage=100", Rel: "self", @@ -322,26 +321,26 @@ func TestCheckpoints_Get(t *testing.T) { t.Fatalf("Checkpoints.Get returned error: %v", err) } - expected := &atlas.Checkpoint{ + expected := &Checkpoint{ ClusterID: clusterID, Completed: "2018-02-08T23:20:25Z", GroupID: projectID, ID: "5a7cdb3980eef53de5bffdcf", - Links: []*atlas.Link{ + Links: []*Link{ { Rel: "self", Href: "https://cloud.mongodb.com/api/public/v1.0/groups/5c8100bcf2a30b12ff88258f/clusters/Cluster0/checkpoints", }, }, - Parts: []*atlas.Part{ + Parts: []*Part{ { ReplicaSetName: "Cluster0-shard-1", TypeName: "REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ ShardName: "Cluster0-shard-1", TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-08T23:20:25Z", Increment: 1, }, @@ -350,10 +349,10 @@ func TestCheckpoints_Get(t *testing.T) { { ReplicaSetName: "Cluster0-shard-0", TypeName: "REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ ShardName: "Cluster0-shard-0", TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-08T23:20:25Z", Increment: 1, }}, @@ -361,9 +360,9 @@ func TestCheckpoints_Get(t *testing.T) { { ReplicaSetName: "Cluster0-config-0", TypeName: "CONFIG_SERVER_REPLICA_SET", - CheckpointPart: atlas.CheckpointPart{ + CheckpointPart: CheckpointPart{ TokenDiscovered: true, - TokenTimestamp: atlas.SnapshotTimestamp{ + TokenTimestamp: SnapshotTimestamp{ Date: "2018-02-08T23:20:25Z", Increment: 2, }}, diff --git a/opsmngr/continuous_restore_jobs.go b/opsmngr/continuous_restore_jobs.go index dcb2d1a..2f625f3 100644 --- a/opsmngr/continuous_restore_jobs.go +++ b/opsmngr/continuous_restore_jobs.go @@ -34,6 +34,11 @@ type ( ContinuousJobRequest = atlas.ContinuousJobRequest ) +type SnapshotTimestamp struct { + Date string `json:"date"` + Increment int64 `json:"increment"` +} + var _ atlas.ContinuousRestoreJobsService = &ContinuousRestoreJobsServiceOp{} // List lists all continuous backup jobs in Atlas diff --git a/opsmngr/continuous_snapshots.go b/opsmngr/continuous_snapshots.go index 1ac5f77..eb4849e 100644 --- a/opsmngr/continuous_snapshots.go +++ b/opsmngr/continuous_snapshots.go @@ -18,24 +18,80 @@ import ( "context" "fmt" "net/http" - - atlas "go.mongodb.org/atlas/mongodbatlas" ) const ( continuousSnapshotsBasePath = "api/public/v1.0/groups/%s/clusters/%s/snapshots" ) +// ContinuousSnapshotsService is an interface for interfacing with the Continuous Snapshots. +type ContinuousSnapshotsService interface { + List(context.Context, string, string, *ListOptions) (*ContinuousSnapshots, *Response, error) + Get(context.Context, string, string, string) (*ContinuousSnapshot, *Response, error) + ChangeExpiry(context.Context, string, string, string, *ContinuousSnapshot) (*ContinuousSnapshot, *Response, error) + Delete(context.Context, string, string, string) (*Response, error) +} + // ContinuousSnapshotsServiceOp handles communication with the Continuous Snapshots related methods of the // MongoDB Ops Manager API. type ContinuousSnapshotsServiceOp service -var _ atlas.ContinuousSnapshotsService = &ContinuousSnapshotsServiceOp{} +// ContinuousSnapshot represents a cloud provider snapshot. +type ContinuousSnapshot struct { + ClusterID string `json:"clusterId,omitempty"` + Complete bool `json:"complete,omitempty"` + Created *SnapshotTimestamp `json:"created,omitempty"` + DoNotDelete *bool `json:"doNotDelete,omitempty"` + Expires string `json:"expires,omitempty"` + GroupID string `json:"groupId,omitempty"` + ID string `json:"id,omitempty"` // Unique identifier of the snapshot. + IsPossiblyInconsistent *bool `json:"isPossiblyInconsistent,omitempty"` + LastOplogAppliedTimestamp *SnapshotTimestamp `json:"lastOplogAppliedTimestamp,omitempty"` + Links []*Link `json:"links,omitempty"` // One or more links to sub-resources and/or related resources. + NamespaceFilterList *NamespaceFilter `json:"namespaceFilterList,omitempty"` + MissingShards []*MissingShard `json:"missingShards,omitempty"` + Parts []*Part `json:"parts,omitempty"` +} -type ( - ContinuousSnapshots = atlas.ContinuousSnapshots - ContinuousSnapshot = atlas.ContinuousSnapshot -) +// ContinuousSnapshots represents all cloud provider snapshots. +type ContinuousSnapshots struct { + Results []*ContinuousSnapshot `json:"results,omitempty"` // Includes one ContinuousSnapshots object for each item detailed in the results array section. + Links []*Link `json:"links,omitempty"` // One or more links to sub-resources and/or related resources. + TotalCount int `json:"totalCount,omitempty"` // Count of the total number of items in the result set. It may be greater than the number of objects in the results array if the entire result set is paginated. +} + +type Part struct { + ReplicaSetName string `json:"replicaSetName"` + TypeName string `json:"typeName"` + SnapshotPart + CheckpointPart +} + +type NamespaceFilter struct { + FilterList []string `json:"filterList"` + FilterType string `json:"filterType"` +} + +type MissingShard struct { + ID string `json:"id"` + GroupID string `json:"groupId"` + TypeName string `json:"typeName"` + ClusterName string `json:"clusterName,omitempty"` + ShardName string `json:"shardName,omitempty"` + ReplicaSetName string `json:"replicaSetName"` + LastHeartbeat string `json:"lastHeartbeat"` +} + +type SnapshotPart struct { + ClusterID string `json:"clusterId"` + CompressionSetting string `json:"compressionSetting"` + DataSizeBytes int64 `json:"dataSizeBytes"` + EncryptionEnabled bool `json:"encryptionEnabled"` + FileSizeBytes int64 `json:"fileSizeBytes"` + MasterKeyUUID string `json:"masterKeyUUID,omitempty"` //nolint:all + MongodVersion string `json:"mongodVersion"` + StorageSizeBytes int64 `json:"storageSizeBytes"` +} // List lists continuous snapshots for the given cluster // diff --git a/opsmngr/continuous_snapshots_test.go b/opsmngr/continuous_snapshots_test.go index 5f632df..50b12f9 100644 --- a/opsmngr/continuous_snapshots_test.go +++ b/opsmngr/continuous_snapshots_test.go @@ -21,7 +21,6 @@ import ( "testing" "github.com/go-test/deep" - atlas "go.mongodb.org/atlas/mongodbatlas" ) const ( @@ -83,7 +82,7 @@ func TestContinuousSnapshots_List(t *testing.T) { } expected := &ContinuousSnapshots{ - Links: []*atlas.Link{ + Links: []*Link{ { Href: "https://cloud.mongodb.com/api/atlas/v1.0/groups/6c7498dg87d9e6526801572b/clusters/Cluster0/snapshots?pageNum=1&itemsPerPage=100", Rel: "self", @@ -93,7 +92,7 @@ func TestContinuousSnapshots_List(t *testing.T) { { ClusterID: "7c2487d833e9e75286093696", Complete: true, - Created: &atlas.SnapshotTimestamp{ + Created: &SnapshotTimestamp{ Date: "2017-12-26T16:32:16Z", Increment: 1, }, @@ -101,21 +100,21 @@ func TestContinuousSnapshots_List(t *testing.T) { Expires: "2018-12-25T16:32:16Z", GroupID: "6c7498dg87d9e6526801572b", ID: "5a4279d4fcc178500596745a", - LastOplogAppliedTimestamp: &atlas.SnapshotTimestamp{ + LastOplogAppliedTimestamp: &SnapshotTimestamp{ Date: "2017-12-26T16:32:15Z", Increment: 1, }, - Links: []*atlas.Link{ + Links: []*Link{ { Href: "https://cloud.mongodb.com/api/atlas/v1.0/groups/6c7498dg87d9e6526801572b/clusters/Cluster0/snapshots/5a4279d4fcc178500596745a", Rel: "self", }, }, - Parts: []*atlas.Part{ + Parts: []*Part{ { ReplicaSetName: "Cluster0-shard-0", TypeName: "REPLICA_SET", - SnapshotPart: atlas.SnapshotPart{ + SnapshotPart: SnapshotPart{ ClusterID: "7c2487d833e9e75286093696", CompressionSetting: "GZIP", DataSizeBytes: 4502, @@ -184,7 +183,7 @@ func TestContinuousSnapshots_Get(t *testing.T) { expected := &ContinuousSnapshot{ ClusterID: "7c2487d833e9e75286093696", Complete: true, - Created: &atlas.SnapshotTimestamp{ + Created: &SnapshotTimestamp{ Date: "2017-12-26T16:32:16Z", Increment: 1, }, @@ -192,21 +191,21 @@ func TestContinuousSnapshots_Get(t *testing.T) { Expires: "2018-12-25T16:32:16Z", GroupID: "6c7498dg87d9e6526801572b", ID: "6b5380e6jvn128560506942b", - LastOplogAppliedTimestamp: &atlas.SnapshotTimestamp{ + LastOplogAppliedTimestamp: &SnapshotTimestamp{ Date: "2017-12-26T16:32:15Z", Increment: 1, }, - Links: []*atlas.Link{ + Links: []*Link{ { Href: "https://cloud.mongodb.com/api/atlas/v1.0/groups/6c7498dg87d9e6526801572b/clusters/Cluster0/snapshots/6b5380e6jvn128560506942b", Rel: "self", }, }, - Parts: []*atlas.Part{ + Parts: []*Part{ { ReplicaSetName: "Cluster0-shard-0", TypeName: "REPLICA_SET", - SnapshotPart: atlas.SnapshotPart{ + SnapshotPart: SnapshotPart{ ClusterID: "7c2487d833e9e75286093696", CompressionSetting: "GZIP", DataSizeBytes: 4502, @@ -227,7 +226,7 @@ func TestContinuousSnapshots_ChangeExpiry(t *testing.T) { client, mux, teardown := setup() defer teardown() - updateRequest := &atlas.ContinuousSnapshot{ + updateRequest := &ContinuousSnapshot{ Expires: "2018-12-01", } @@ -290,10 +289,10 @@ func TestContinuousSnapshots_ChangeExpiry(t *testing.T) { t.Fatalf("ContinuousSnapshots.ChangeExpiry returned error: %v", err) } - expected := &atlas.ContinuousSnapshot{ + expected := &ContinuousSnapshot{ ClusterID: "57c2487d833e9e75286093696", Complete: true, - Created: &atlas.SnapshotTimestamp{ + Created: &SnapshotTimestamp{ Date: "2017-12-26T16:32:16Z", Increment: 1, }, @@ -301,21 +300,21 @@ func TestContinuousSnapshots_ChangeExpiry(t *testing.T) { Expires: "2018-12-01T00:00:00Z", GroupID: "6c7498dg87d9e6526801572b", ID: "6b5380e6jvn128560506942b", - LastOplogAppliedTimestamp: &atlas.SnapshotTimestamp{ + LastOplogAppliedTimestamp: &SnapshotTimestamp{ Date: "2017-12-26T16:32:15Z", Increment: 1, }, - Links: []*atlas.Link{ + Links: []*Link{ { Href: "https://cloud.mongodb.com/api/atlas/v1.0/groups/6c7498dg87d9e6526801572b/clusters/Cluster0/snapshots/6b5380e6jvn128560506942b", Rel: "self", }, }, - Parts: []*atlas.Part{ + Parts: []*Part{ { ReplicaSetName: "Cluster0-shard-0", TypeName: "REPLICA_SET", - SnapshotPart: atlas.SnapshotPart{ + SnapshotPart: SnapshotPart{ ClusterID: "57c2487d833e9e75286093696", CompressionSetting: "GZIP", DataSizeBytes: 4502, diff --git a/opsmngr/diagnostics.go b/opsmngr/diagnostics.go index 95fa851..fcb4879 100644 --- a/opsmngr/diagnostics.go +++ b/opsmngr/diagnostics.go @@ -19,8 +19,6 @@ import ( "fmt" "io" "net/http" - - atlas "go.mongodb.org/atlas/mongodbatlas" ) const ( @@ -36,7 +34,7 @@ type DiagnosticsService interface { // DiagnosticsServiceOp provides an implementation of the DiagnosticsService interface. type DiagnosticsServiceOp struct { - Client atlas.GZipRequestDoer + Client GZipRequestDoer } // DiagnosticsListOpts query options for getting the archive. diff --git a/opsmngr/logs.go b/opsmngr/logs.go index f3eef22..0f70513 100644 --- a/opsmngr/logs.go +++ b/opsmngr/logs.go @@ -19,8 +19,6 @@ import ( "fmt" "io" "net/http" - - atlas "go.mongodb.org/atlas/mongodbatlas" ) const ( @@ -56,7 +54,7 @@ type LogsService interface { // LogsServiceOp handles communication with the Log Collection Jobs download method of the // MongoDB Ops Manager API. type LogsServiceOp struct { - Client atlas.GZipRequestDoer + Client GZipRequestDoer } var _ LogsService = &LogsServiceOp{} diff --git a/opsmngr/opsmngr.go b/opsmngr/opsmngr.go index 060ba38..5be262c 100644 --- a/opsmngr/opsmngr.go +++ b/opsmngr/opsmngr.go @@ -48,10 +48,6 @@ type ( APIKey = atlas.APIKey APIKeyInput = atlas.APIKeyInput AssignAPIKey = atlas.AssignAPIKey - Part = atlas.Part - Checkpoint = atlas.Checkpoint - Checkpoints = atlas.Checkpoints - SnapshotTimestamp = atlas.SnapshotTimestamp IndexOptions = atlas.IndexOptions CollationOptions = atlas.CollationOptions Team = atlas.Team @@ -62,12 +58,6 @@ type ( TeamRoles = atlas.TeamRoles Invitation = atlas.Invitation InvitationOptions = atlas.InvitationOptions - NamespaceOptions = atlas.NamespaceOptions - Namespaces = atlas.Namespaces - SlowQueryOptions = atlas.SlowQueryOptions - SlowQueries = atlas.SlowQueries - SuggestedIndexOptions = atlas.SuggestedIndexOptions - SuggestedIndexes = atlas.SuggestedIndexes Notification = atlas.Notification CurrentValue = atlas.CurrentValue MetricThreshold = atlas.MetricThreshold @@ -78,6 +68,23 @@ type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } +// Doer basic interface of a client to be able to do a request. +type Doer interface { + Do(context.Context, *http.Request, interface{}) (*Response, error) +} + +// Completer interface for clients with callback. +type Completer interface { + OnRequestCompleted(RequestCompletionCallback) +} + +// GZipRequestDoer minimum interface for any service of the client that should handle gzip downloads. +type GZipRequestDoer interface { + Doer + Completer + NewGZipRequest(context.Context, string, string) (*http.Request, error) +} + // Client manages communication with Ops Manager API. type Client struct { client HTTPClient @@ -95,7 +102,7 @@ type Client struct { UnauthUsers UnauthUsersService AlertConfigurations atlas.AlertConfigurationsService Alerts atlas.AlertsService - ContinuousSnapshots atlas.ContinuousSnapshotsService + ContinuousSnapshots ContinuousSnapshotsService ContinuousRestoreJobs atlas.ContinuousRestoreJobsService Events atlas.EventsService OrganizationAPIKeys atlas.APIKeysService diff --git a/opsmngr/performance_advisor.go b/opsmngr/performance_advisor.go index 844ffa8..5b2c2de 100644 --- a/opsmngr/performance_advisor.go +++ b/opsmngr/performance_advisor.go @@ -18,8 +18,6 @@ import ( "context" "fmt" "net/http" - - atlas "go.mongodb.org/atlas/mongodbatlas" ) const ( @@ -34,20 +32,104 @@ const ( // // See more: https://docs.opsmanager.mongodb.com/current/reference/api/performance-advisor/index.html type PerformanceAdvisorService interface { - GetNamespaces(context.Context, string, string, *atlas.NamespaceOptions) (*atlas.Namespaces, *Response, error) - GetSlowQueries(context.Context, string, string, *atlas.SlowQueryOptions) (*atlas.SlowQueries, *Response, error) - GetSuggestedIndexes(context.Context, string, string, *atlas.SuggestedIndexOptions) (*atlas.SuggestedIndexes, *Response, error) + GetNamespaces(context.Context, string, string, *NamespaceOptions) (*Namespaces, *Response, error) + GetSlowQueries(context.Context, string, string, *SlowQueryOptions) (*SlowQueries, *Response, error) + GetSuggestedIndexes(context.Context, string, string, *SuggestedIndexOptions) (*SuggestedIndexes, *Response, error) } -// PerformanceAdvisorServiceOp handles communication with the Performance Advisor related methods of the MongoDB Atlas API. +// PerformanceAdvisorServiceOp handles communication with the Performance Advisor related methods of the MongoDB OpsManager API. type PerformanceAdvisorServiceOp service var _ PerformanceAdvisorService = &PerformanceAdvisorServiceOp{} +// NamespaceOptions contains the request query parameters for the API request. +type NamespaceOptions struct { + Since int64 `url:"since,omitempty"` // Point in time, specified as milliseconds since the Unix Epoch, from which you want to receive results. + Duration int64 `url:"duration,omitempty"` // Length of time from the since parameter, in milliseconds, for which you want to receive results. +} + +// Namespace represents a Namespace. +type Namespace struct { + Namespace string `json:"namespace,omitempty"` // A namespace on the specified host. + Type string `json:"type,omitempty"` // The type of namespace. +} + +// Namespaces represents a list of Namespace. +type Namespaces struct { + Namespaces []*Namespace `json:"namespaces,omitempty"` +} + +// SlowQueryOptions contains the request query parameters for the API request. +type SlowQueryOptions struct { + Namespaces string `url:"namespaces,omitempty"` // Namespaces from which to retrieve slow query logs. A namespace consists of the database and collection resource separated by a ., such as .. + NLogs int64 `url:"nLogs,omitempty"` // Maximum number of log lines to return. Defaults to 20000. + NamespaceOptions +} + +// SlowQuery represents a slow query. +type SlowQuery struct { + Namespace string `json:"namespace,omitempty"` // The namespace in which the slow query ran. + Line string `json:"line,omitempty"` // The raw log line pertaining to the slow query. +} + +// SlowQueries represents a list of SlowQuery. +type SlowQueries struct { + SlowQuery []*SlowQuery `json:"slowQueries,omitempty"` //nolint:all // A list of documents with information about slow queries as detected by the Performance Advisor. +} + +// SuggestedIndexOptions contains the request query parameters for the API request. +type SuggestedIndexOptions struct { + Namespaces string `url:"namespaces,omitempty"` // Namespaces from which to retrieve slow query logs. A namespace consists of the database and collection resource separated by a ., such as .. + NIndexes int64 `url:"nIndexes,omitempty"` // Maximum number of indexes to suggest. Defaults to unlimited. + NExamples int64 `url:"NExamples,omitempty"` // Maximum number of examples queries to provide that will be improved by a suggested index. Defaults to 5. + NamespaceOptions +} + +// SuggestedIndexes represents an array of suggested indexes. +type SuggestedIndexes struct { + SuggestedIndexes []*SuggestedIndex `json:"suggestedIndexes,omitempty"` // Documents with information about the indexes suggested by the Performance Advisor. + Shapes []*Shape `json:"shapes,omitempty"` // Documents with information about the query shapes that are served by the suggested indexes. + +} + +// SuggestedIndex represents a suggested index. +type SuggestedIndex struct { + ID string `json:"id,omitempty"` // Unique id for this suggested index. + Impact []string `json:"impact,omitempty"` // List of unique identifiers which correspond the query shapes in this response which pertain to this suggested index. + Namespace string `json:"namespace,omitempty"` // Namespace of the suggested index. + Weight float64 `json:"weight,omitempty"` // Estimated percentage performance improvement that the suggested index would provide. + Index []map[string]int `json:"index,omitempty"` // Array of documents that specifies a key in the index and its sort order, ascending or descending. +} + +// Shape represents a document with information about the query shapes that are served by the suggested indexes. +type Shape struct { + AvgMs float64 `json:"avgMs,omitempty"` // Average duration in milliseconds for the queries examined that match this shape. + Count int64 `json:"count,omitempty"` // Number of queries examined that match this shape. + ID string `json:"id,omitempty"` // Unique id for this shape. Exists only for the duration of the API request. + InefficiencyScore int64 `json:"inefficiencyScore,omitempty"` // Average number of documents read for every document returned by the query. + Namespace string `json:"namespace,omitempty"` // The namespace in which the slow query ran. + Operations []*Operation `json:"operations,omitempty"` // It represents documents with specific information and log lines for individual queries. +} + +// Operation represents a document with specific information and log lines for individual queries. +type Operation struct { + Raw string `json:"raw,omitempty"` // Raw log line produced by the query. + Stats Stats `json:"stats,omitempty"` // Query statistics. + Predicates []map[string]interface{} `json:"predicates,omitempty"` // Documents containing the search criteria used by the query. +} + +// Stats represents query statistics. +type Stats struct { + MS float64 `json:"ms,omitempty"` // Duration in milliseconds of the query. + NReturned int64 `json:"nReturned,omitempty"` // Number of results returned by the query. + NScanned int64 `json:"nScanned,omitempty"` // Number of documents read by the query. + TS int64 `json:"ts,omitempty"` // Query timestamp, in seconds since epoch. +} + // GetNamespaces retrieves the namespaces for collections experiencing slow queries for a specified host. // // See more: https://docs.opsmanager.mongodb.com/current/reference/api/performance-advisor/pa-namespaces-get-all/ -func (s *PerformanceAdvisorServiceOp) GetNamespaces(ctx context.Context, groupID, processName string, opts *atlas.NamespaceOptions) (*atlas.Namespaces, *Response, error) { +func (s *PerformanceAdvisorServiceOp) GetNamespaces(ctx context.Context, groupID, processName string, opts *NamespaceOptions) (*Namespaces, *Response, error) { if groupID == "" { return nil, nil, NewArgError("groupID", "must be set") } @@ -67,7 +149,7 @@ func (s *PerformanceAdvisorServiceOp) GetNamespaces(ctx context.Context, groupID return nil, nil, err } - root := new(atlas.Namespaces) + root := new(Namespaces) resp, err := s.Client.Do(ctx, req, root) if err != nil { return nil, resp, err @@ -79,7 +161,7 @@ func (s *PerformanceAdvisorServiceOp) GetNamespaces(ctx context.Context, groupID // GetSlowQueries gets log lines for slow queries as determined by the Performance Advisor. // // See more: https://docs.opsmanager.mongodb.com/current/reference/api/performance-advisor/get-slow-queries/ -func (s *PerformanceAdvisorServiceOp) GetSlowQueries(ctx context.Context, groupID, processName string, opts *atlas.SlowQueryOptions) (*atlas.SlowQueries, *Response, error) { +func (s *PerformanceAdvisorServiceOp) GetSlowQueries(ctx context.Context, groupID, processName string, opts *SlowQueryOptions) (*SlowQueries, *Response, error) { if groupID == "" { return nil, nil, NewArgError("groupID", "must be set") } @@ -99,7 +181,7 @@ func (s *PerformanceAdvisorServiceOp) GetSlowQueries(ctx context.Context, groupI return nil, nil, err } - root := new(atlas.SlowQueries) + root := new(SlowQueries) resp, err := s.Client.Do(ctx, req, root) if err != nil { return nil, resp, err @@ -111,7 +193,7 @@ func (s *PerformanceAdvisorServiceOp) GetSlowQueries(ctx context.Context, groupI // GetSuggestedIndexes gets suggested indexes as determined by the Performance Advisor. // // See more: https://docs.opsmanager.mongodb.com/current/reference/api/performance-advisor/get-suggested-indexes/ -func (s *PerformanceAdvisorServiceOp) GetSuggestedIndexes(ctx context.Context, groupID, processName string, opts *atlas.SuggestedIndexOptions) (*atlas.SuggestedIndexes, *Response, error) { +func (s *PerformanceAdvisorServiceOp) GetSuggestedIndexes(ctx context.Context, groupID, processName string, opts *SuggestedIndexOptions) (*SuggestedIndexes, *Response, error) { if groupID == "" { return nil, nil, NewArgError("groupID", "must be set") } @@ -131,7 +213,7 @@ func (s *PerformanceAdvisorServiceOp) GetSuggestedIndexes(ctx context.Context, g return nil, nil, err } - root := new(atlas.SuggestedIndexes) + root := new(SuggestedIndexes) resp, err := s.Client.Do(ctx, req, root) if err != nil { return nil, resp, err diff --git a/opsmngr/performance_advisor_test.go b/opsmngr/performance_advisor_test.go index b8494fd..022613c 100644 --- a/opsmngr/performance_advisor_test.go +++ b/opsmngr/performance_advisor_test.go @@ -20,7 +20,6 @@ import ( "testing" "github.com/go-test/deep" - "go.mongodb.org/atlas/mongodbatlas" ) const processName = "test:27017" @@ -42,7 +41,7 @@ func TestPerformanceAdvisor_GetNamespaces(t *testing.T) { }`) }) - opts := &mongodbatlas.NamespaceOptions{ + opts := &NamespaceOptions{ Since: 2, Duration: 2, } @@ -52,8 +51,8 @@ func TestPerformanceAdvisor_GetNamespaces(t *testing.T) { t.Fatalf("PerformanceAdvisor.GetNamespaces returned error: %v", err) } - expected := &mongodbatlas.Namespaces{ - Namespaces: []*mongodbatlas.Namespace{ + expected := &Namespaces{ + Namespaces: []*Namespace{ { Namespace: "data.zips", Type: "COLLECTION", @@ -87,8 +86,8 @@ func TestPerformanceAdvisor_GetSlowQueries(t *testing.T) { }`) }) - opts := &mongodbatlas.SlowQueryOptions{ - NamespaceOptions: mongodbatlas.NamespaceOptions{Since: 2, Duration: 2}, + opts := &SlowQueryOptions{ + NamespaceOptions: NamespaceOptions{Since: 2, Duration: 2}, Namespaces: "test", NLogs: 2, } @@ -98,8 +97,8 @@ func TestPerformanceAdvisor_GetSlowQueries(t *testing.T) { t.Fatalf("PerformanceAdvisor.GetSlowQueries returned error: %v", err) } - expected := &mongodbatlas.SlowQueries{ - SlowQuery: []*mongodbatlas.SlowQuery{ + expected := &SlowQueries{ + SlowQuery: []*SlowQuery{ { Namespace: "myDb.users", Line: "2018-08-16T22:53:43.447+0000 I COMMAND [conn10614] command myDb.users appName: \"MongoDB Shell\" command: find { find: \"users\", filter: { emails: \"tocde@fijoow.to\" }, lsid: { id: UUID(\"832b4b0e-085a-480e-b470-16a0994dc7cb\") }, $clusterTime: { clusterTime: Timestamp(1534460016, 1)...", @@ -169,8 +168,8 @@ func TestPerformanceAdvisor_GetSuggestedIndexes(t *testing.T) { }`) }) - opts := &mongodbatlas.SuggestedIndexOptions{ - NamespaceOptions: mongodbatlas.NamespaceOptions{Since: 2, Duration: 2}, + opts := &SuggestedIndexOptions{ + NamespaceOptions: NamespaceOptions{Since: 2, Duration: 2}, Namespaces: "test", NIndexes: 55, NExamples: 4, @@ -181,8 +180,8 @@ func TestPerformanceAdvisor_GetSuggestedIndexes(t *testing.T) { t.Fatalf("PerformanceAdvisor.GetSuggestedIndexes returned error: %v", err) } - expected := &mongodbatlas.SuggestedIndexes{ - SuggestedIndexes: []*mongodbatlas.SuggestedIndex{ + expected := &SuggestedIndexes{ + SuggestedIndexes: []*SuggestedIndex{ { ID: "5b74689a80eef53f3388897f", Impact: []string{"5b74689a80eef53f3388897e"}, @@ -202,17 +201,17 @@ func TestPerformanceAdvisor_GetSuggestedIndexes(t *testing.T) { }, }, }, - Shapes: []*mongodbatlas.Shape{ + Shapes: []*Shape{ { AvgMs: 42, Count: 2, ID: "5b74689a80eef53f3388897e", InefficiencyScore: 50000, Namespace: "test.users", - Operations: []*mongodbatlas.Operation{ + Operations: []*Operation{ { Raw: "2018-08-15T17:14:11.115+0000 I COMMAND [conn4576] command test.users appName: \"MongoDB Shell\" command: find { find: \"users\", filter: { emails: \"la@sa.kp\" }, lsid: { id: UUID(\"1a4e71d3-9b67-4e9c-b078-9fdf3fae9091\") }, $clusterTime: { clusterTime: Timestamp(1534353241, 1), signature: { hash: BinData(0, AB91938B7CF7BC87994A2909A98D87F29101EFA0), keyId: 6589681559618453505 } }, $db: \"test\" } planSummary: COLLSCAN keysExamined:0 docsExamined:50000 cursorExhausted:1 numYields:391 nreturned:1 reslen:339 locks:{ Global: { acquireCount: { r: 784 } }, Database: { acquireCount: { r: 392 } }, Collection: { acquireCount: { r: 392 } } } protocol:op_msg 34ms", - Stats: mongodbatlas.Stats{ + Stats: Stats{ MS: 34, NReturned: 1, NScanned: 50000, @@ -224,7 +223,7 @@ func TestPerformanceAdvisor_GetSuggestedIndexes(t *testing.T) { }, { Raw: "2018-08-15T17:14:18.665+0000 I COMMAND [conn4576] command test.users appName: \"MongoDB Shell\" command: find { find: \"users\", filter: { emails: \"tocde@fijoow.to\" }, lsid: { id: UUID(\"1a4e71d3-9b67-4e9c-b078-9fdf3fae9091\") }, $clusterTime: { clusterTime: Timestamp(1534353241, 1), signature: { hash: BinData(0, AB91938B7CF7BC87994A2909A98D87F29101EFA0), keyId: 6589681559618453505 } }, $db: \"test\" } planSummary: COLLSCAN keysExamined:0 docsExamined:50000 cursorExhausted:1 numYields:390 nreturned:1 reslen:342 locks:{ Global: { acquireCount: { r: 782 } }, Database: { acquireCount: { r: 391 } }, Collection: { acquireCount: { r: 391 } } } protocol:op_msg 36ms", - Stats: mongodbatlas.Stats{ + Stats: Stats{ MS: 36, NReturned: 1, NScanned: 50000, diff --git a/opsmngr/snapshot_schedule.go b/opsmngr/snapshot_schedule.go index 0b3f412..f51ccd9 100644 --- a/opsmngr/snapshot_schedule.go +++ b/opsmngr/snapshot_schedule.go @@ -18,8 +18,6 @@ import ( "context" "fmt" "net/http" - - atlas "go.mongodb.org/atlas/mongodbatlas" ) const snapshotScheduleBasePath = "api/public/v1.0/groups/%s/backupConfigs/%s/snapshotSchedule" @@ -39,19 +37,19 @@ type SnapshotScheduleServiceOp service var _ SnapshotScheduleService = &SnapshotScheduleServiceOp{} type SnapshotSchedule struct { - ClusterID string `json:"clusterId"` - GroupID string `json:"groupId"` - ReferenceTimeZoneOffset string `json:"referenceTimeZoneOffset,omitempty"` - DailySnapshotRetentionDays *int `json:"dailySnapshotRetentionDays,omitempty"` - ClusterCheckpointIntervalMin int `json:"clusterCheckpointIntervalMin,omitempty"` - Links []*atlas.Link `json:"links,omitempty"` - MonthlySnapshotRetentionMonths *int `json:"monthlySnapshotRetentionMonths,omitempty"` - PointInTimeWindowHours *int `json:"pointInTimeWindowHours,omitempty"` - ReferenceHourOfDay *int `json:"referenceHourOfDay,omitempty"` - ReferenceMinuteOfHour *int `json:"referenceMinuteOfHour,omitempty"` - SnapshotIntervalHours int `json:"snapshotIntervalHours,omitempty"` - SnapshotRetentionDays int `json:"snapshotRetentionDays,omitempty"` - WeeklySnapshotRetentionWeeks *int `json:"weeklySnapshotRetentionWeeks,omitempty"` + ClusterID string `json:"clusterId"` + GroupID string `json:"groupId"` + ReferenceTimeZoneOffset string `json:"referenceTimeZoneOffset,omitempty"` + DailySnapshotRetentionDays *int `json:"dailySnapshotRetentionDays,omitempty"` + ClusterCheckpointIntervalMin int `json:"clusterCheckpointIntervalMin,omitempty"` + Links []*Link `json:"links,omitempty"` + MonthlySnapshotRetentionMonths *int `json:"monthlySnapshotRetentionMonths,omitempty"` + PointInTimeWindowHours *int `json:"pointInTimeWindowHours,omitempty"` + ReferenceHourOfDay *int `json:"referenceHourOfDay,omitempty"` + ReferenceMinuteOfHour *int `json:"referenceMinuteOfHour,omitempty"` + SnapshotIntervalHours int `json:"snapshotIntervalHours,omitempty"` + SnapshotRetentionDays int `json:"snapshotRetentionDays,omitempty"` + WeeklySnapshotRetentionWeeks *int `json:"weeklySnapshotRetentionWeeks,omitempty"` } // Get gets the snapshot schedule for an instance.