Skip to content

Commit daded9c

Browse files
authored
INTMDB-299: Added snapshot export bucket support (#276)
1 parent 89c5571 commit daded9c

6 files changed

+485
-60
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Copyright 2022 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package mongodbatlas
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"net/http"
21+
)
22+
23+
const (
24+
cloudProviderSnapshotExportBucketsPath = "api/atlas/v1.0/groups/%s/backup/exportBuckets"
25+
)
26+
27+
// CloudProviderSnapshotExportBucketsService is an interface for interfacing with the Cloud Provider Snapshots Export Buckets
28+
// endpoints of the MongoDB Atlas API.
29+
type CloudProviderSnapshotExportBucketsService interface {
30+
List(context.Context, string, *ListOptions) (*CloudProviderSnapshotExportBuckets, *Response, error)
31+
Get(context.Context, string, string) (*CloudProviderSnapshotExportBucket, *Response, error)
32+
Create(context.Context, string, *CloudProviderSnapshotExportBucket) (*CloudProviderSnapshotExportBucket, *Response, error)
33+
Delete(context.Context, string, string) (*Response, error)
34+
}
35+
36+
// CloudProviderSnapshotExportBucketsServiceOp handles communication with the CloudProviderSnapshotExportBucketsService related methods of the
37+
// MongoDB Atlas API.
38+
type CloudProviderSnapshotExportBucketsServiceOp service
39+
40+
// List Retrieve all the buckets for the specified project.
41+
//
42+
// See more: https://docs.atlas.mongodb.com/reference/api/cloud-backup/export/get-all-export-buckets/
43+
func (c CloudProviderSnapshotExportBucketsServiceOp) List(ctx context.Context, projectID string, options *ListOptions) (*CloudProviderSnapshotExportBuckets, *Response, error) {
44+
if projectID == "" {
45+
return nil, nil, NewArgError("projectID", "must be set")
46+
}
47+
48+
path := fmt.Sprintf(cloudProviderSnapshotExportBucketsPath, projectID)
49+
50+
path, err := setListOptions(path, options)
51+
if err != nil {
52+
return nil, nil, err
53+
}
54+
55+
req, err := c.Client.NewRequest(ctx, http.MethodGet, path, nil)
56+
if err != nil {
57+
return nil, nil, err
58+
}
59+
60+
root := new(CloudProviderSnapshotExportBuckets)
61+
resp, err := c.Client.Do(ctx, req, root)
62+
if err != nil {
63+
return nil, resp, err
64+
}
65+
66+
if l := root.Links; l != nil {
67+
resp.Links = l
68+
}
69+
70+
return root, resp, nil
71+
}
72+
73+
// Get Allows you to retrieve one bucket specified by the bucket ID.
74+
//
75+
// See more: https://docs.atlas.mongodb.com/reference/api/cloud-backup/export/get-one-export-bucket/
76+
func (c CloudProviderSnapshotExportBucketsServiceOp) Get(ctx context.Context, projectID, bucketID string) (*CloudProviderSnapshotExportBucket, *Response, error) {
77+
if projectID == "" {
78+
return nil, nil, NewArgError("projectID", "must be set")
79+
}
80+
if bucketID == "" {
81+
return nil, nil, NewArgError("bucketID", "must be set")
82+
}
83+
84+
path := fmt.Sprintf("api/atlas/v1.0/groups/%s/backup/exportBuckets/%s", projectID, bucketID)
85+
86+
req, err := c.Client.NewRequest(ctx, http.MethodGet, path, nil)
87+
if err != nil {
88+
return nil, nil, err
89+
}
90+
91+
root := new(CloudProviderSnapshotExportBucket)
92+
resp, err := c.Client.Do(ctx, req, root)
93+
if err != nil {
94+
return nil, resp, err
95+
}
96+
97+
return root, resp, err
98+
}
99+
100+
// Create Allows you to grant Atlas access to the specified bucket for exporting backup snapshots.
101+
//
102+
// See more: https://docs.atlas.mongodb.com/reference/api/cloud-backup/export/create-one-export-bucket/
103+
func (c CloudProviderSnapshotExportBucketsServiceOp) Create(ctx context.Context, projectID string, bucket *CloudProviderSnapshotExportBucket) (*CloudProviderSnapshotExportBucket, *Response, error) {
104+
if projectID == "" {
105+
return nil, nil, NewArgError("projectID", "must be set")
106+
}
107+
108+
path := fmt.Sprintf(cloudProviderSnapshotExportBucketsPath, projectID)
109+
110+
req, err := c.Client.NewRequest(ctx, http.MethodPost, path, bucket)
111+
if err != nil {
112+
return nil, nil, err
113+
}
114+
115+
root := new(CloudProviderSnapshotExportBucket)
116+
resp, err := c.Client.Do(ctx, req, root)
117+
if err != nil {
118+
return nil, resp, err
119+
}
120+
121+
return root, resp, err
122+
}
123+
124+
// Delete Allows you to remove one bucket specified by the bucket ID.
125+
//
126+
// See more: https://docs.atlas.mongodb.com/reference/api/cloud-backup/export/delete-one-export-bucket/
127+
func (c CloudProviderSnapshotExportBucketsServiceOp) Delete(ctx context.Context, projectID, bucketID string) (*Response, error) {
128+
if projectID == "" {
129+
return nil, NewArgError("projectID", "must be set")
130+
}
131+
if bucketID == "" {
132+
return nil, NewArgError("bucketID", "must be set")
133+
}
134+
135+
path := fmt.Sprintf("api/atlas/v1.0/groups/%s/backup/exportBuckets/%s", projectID, bucketID)
136+
137+
req, err := c.Client.NewRequest(ctx, http.MethodDelete, path, nil)
138+
if err != nil {
139+
return nil, err
140+
}
141+
142+
resp, err := c.Client.Do(ctx, req, nil)
143+
144+
return resp, err
145+
}
146+
147+
var _ CloudProviderSnapshotExportBucketsService = &CloudProviderSnapshotExportBucketsServiceOp{}
148+
149+
// CloudProviderSnapshotExportBuckets represents all cloud provider snapshot export buckets.
150+
type CloudProviderSnapshotExportBuckets struct {
151+
Results []*CloudProviderSnapshotExportBucket `json:"results,omitempty"` // Includes one CloudProviderSnapshotExportBucket object for each item detailed in the results array section.
152+
Links []*Link `json:"links,omitempty"` // One or more links to sub-resources and/or related resources.
153+
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.
154+
}
155+
156+
// CloudProviderSnapshotExportBucket represents one cloud provider snapshot export buckets.
157+
type CloudProviderSnapshotExportBucket struct {
158+
ID string `json:"_id,omitempty"` // Unique identifier of the S3 bucket.
159+
BucketName string `json:"bucketName,omitempty"` // Name of the bucket that the role ID is authorized to access.
160+
CloudProvider string `json:"cloudProvider,omitempty"` // Name of the provider of the cloud service where Atlas can access the S3 bucket. Atlas only supports AWS.
161+
IAMRoleID string `json:"iamRoleId,omitempty"` // Unique identifier of the role that Atlas can use to access the bucket. If necessary, use the UI or API to retrieve the role ID. You must also specify the bucketName.
162+
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// Copyright 2021 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package mongodbatlas
16+
17+
import (
18+
"encoding/json"
19+
"fmt"
20+
"net/http"
21+
"testing"
22+
23+
"github.com/go-test/deep"
24+
)
25+
26+
func TestCloudProviderSnapshotExportBuckets_List(t *testing.T) {
27+
client, mux, teardown := setup()
28+
defer teardown()
29+
30+
projectID := "test-project-id"
31+
32+
path := fmt.Sprintf("/api/atlas/v1.0/groups/%s/backup/exportBuckets", projectID)
33+
34+
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
35+
testMethod(t, r, http.MethodGet)
36+
fmt.Fprint(w, `{
37+
"links": [
38+
{
39+
"href": "https://cloud.mongodb.com/api/atlas/v1.0/groups/{GROUP-ID}/backup/exportBuckets?pageNum=1&itemsPerPage=100",
40+
"rel": "self"
41+
}
42+
],
43+
"results": [
44+
{
45+
"_id": "{BUCKET-ID}",
46+
"bucketName": "example-bucket",
47+
"cloudProvider": "AWS",
48+
"iamRoleId": "12345678f901a234dbdb00ca"
49+
}
50+
],
51+
"totalCount": 1
52+
}`)
53+
})
54+
55+
cloudProviderSnapshots, _, err := client.CloudProviderSnapshotExportBuckets.List(ctx, projectID, nil)
56+
if err != nil {
57+
t.Fatalf("CloudProviderSnapshotExportBuckets.List returned error: %v", err)
58+
}
59+
60+
expected := &CloudProviderSnapshotExportBuckets{
61+
Links: []*Link{
62+
{
63+
Href: "https://cloud.mongodb.com/api/atlas/v1.0/groups/{GROUP-ID}/backup/exportBuckets?pageNum=1&itemsPerPage=100",
64+
Rel: "self",
65+
},
66+
},
67+
Results: []*CloudProviderSnapshotExportBucket{
68+
{
69+
ID: "{BUCKET-ID}",
70+
BucketName: "example-bucket",
71+
CloudProvider: "AWS",
72+
IAMRoleID: "12345678f901a234dbdb00ca",
73+
},
74+
},
75+
TotalCount: 1,
76+
}
77+
78+
if diff := deep.Equal(cloudProviderSnapshots, expected); diff != nil {
79+
t.Error(diff)
80+
}
81+
}
82+
83+
func TestCloudProviderSnapshotExportBuckets_Get(t *testing.T) {
84+
client, mux, teardown := setup()
85+
defer teardown()
86+
87+
projectID := "test-project-id"
88+
bucketID := "bucket-id-test"
89+
90+
path := fmt.Sprintf("/api/atlas/v1.0/groups/%s/backup/exportBuckets/%s", projectID, bucketID)
91+
92+
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
93+
testMethod(t, r, http.MethodGet)
94+
fmt.Fprint(w, `{
95+
"_id": "{BUCKET-ID}",
96+
"bucketName": "example-bucket",
97+
"cloudProvider": "AWS",
98+
"iamRoleId": "12345678f901a234dbdb00ca"
99+
}`)
100+
})
101+
102+
cloudProviderSnapshotBucket, _, err := client.CloudProviderSnapshotExportBuckets.Get(ctx, projectID, bucketID)
103+
if err != nil {
104+
t.Fatalf("CloudProviderSnapshotExportBuckets.Get returned error: %v", err)
105+
}
106+
107+
expected := &CloudProviderSnapshotExportBucket{
108+
ID: "{BUCKET-ID}",
109+
BucketName: "example-bucket",
110+
CloudProvider: "AWS",
111+
IAMRoleID: "12345678f901a234dbdb00ca",
112+
}
113+
114+
if diff := deep.Equal(cloudProviderSnapshotBucket, expected); diff != nil {
115+
t.Error(diff)
116+
}
117+
}
118+
119+
func TestCloudProviderSnapshotExportBuckets_Create(t *testing.T) {
120+
client, mux, teardown := setup()
121+
defer teardown()
122+
123+
projectID := "test-project-id"
124+
125+
createRequest := &CloudProviderSnapshotExportBucket{
126+
ID: "{BUCKET-ID}",
127+
BucketName: "example-bucket",
128+
CloudProvider: "AWS",
129+
IAMRoleID: "12345678f901a234dbdb00ca",
130+
}
131+
132+
path := fmt.Sprintf("/api/atlas/v1.0/groups/%s/backup/exportBuckets", projectID)
133+
134+
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
135+
expected := map[string]interface{}{
136+
"_id": "{BUCKET-ID}",
137+
"bucketName": "example-bucket",
138+
"cloudProvider": "AWS",
139+
"iamRoleId": "12345678f901a234dbdb00ca",
140+
}
141+
142+
var v map[string]interface{}
143+
err := json.NewDecoder(r.Body).Decode(&v)
144+
if err != nil {
145+
t.Fatalf("Decode json: %v", err)
146+
}
147+
148+
if diff := deep.Equal(v, expected); diff != nil {
149+
t.Error(diff)
150+
}
151+
152+
fmt.Fprint(w, `{
153+
"_id": "{BUCKET-ID}",
154+
"bucketName": "example-bucket",
155+
"cloudProvider": "AWS",
156+
"iamRoleId": "12345678f901a234dbdb00ca"
157+
}`)
158+
})
159+
160+
cloudProviderSnapshot, _, err := client.CloudProviderSnapshotExportBuckets.Create(ctx, projectID, createRequest)
161+
if err != nil {
162+
t.Fatalf("CloudProviderSnapshotExportBuckets.Create returned error: %v", err)
163+
}
164+
165+
expected := &CloudProviderSnapshotExportBucket{
166+
ID: "{BUCKET-ID}",
167+
BucketName: "example-bucket",
168+
CloudProvider: "AWS",
169+
IAMRoleID: "12345678f901a234dbdb00ca",
170+
}
171+
172+
if diff := deep.Equal(cloudProviderSnapshot, expected); diff != nil {
173+
t.Error(diff)
174+
}
175+
}
176+
177+
func TestCloudProviderSnapshotExportBuckets_Delete(t *testing.T) {
178+
client, mux, teardown := setup()
179+
defer teardown()
180+
181+
projectID := "project-id"
182+
bucketID := "bucket-id"
183+
184+
path := fmt.Sprintf("/api/atlas/v1.0/groups/%s/backup/exportBuckets/%s", projectID, bucketID)
185+
186+
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
187+
testMethod(t, r, http.MethodDelete)
188+
})
189+
190+
_, err := client.CloudProviderSnapshotExportBuckets.Delete(ctx, projectID, bucketID)
191+
if err != nil {
192+
t.Fatalf("CloudProviderSnapshotExportBuckets.Delete returned error: %v", err)
193+
}
194+
}

mongodbatlas/cloud_provider_snapshot_restore_jobs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func (s *CloudProviderSnapshotRestoreJobsServiceOp) Get(ctx context.Context, req
123123
return nil, nil, NewArgError("clusterName", "must be set")
124124
}
125125
if requestParameters.JobID == "" {
126-
return nil, nil, NewArgError("jobId", "must be set")
126+
return nil, nil, NewArgError("JobID", "must be set")
127127
}
128128

129129
path := fmt.Sprintf("%s/%s/clusters/%s/backup/restoreJobs/%s", cloudProviderSnapshotsBasePath, requestParameters.GroupID, requestParameters.ClusterName, requestParameters.JobID)

0 commit comments

Comments
 (0)