Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 39ceb70

Browse files
agneumanatolystansler
authored andcommitted
feat: allow choosing snapshot when creating a clone in CLI (#107)
1 parent 563d014 commit 39ceb70

File tree

12 files changed

+236
-127
lines changed

12 files changed

+236
-127
lines changed

api/swagger-spec/dblab_server_swagger.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ paths:
9797
schema:
9898
$ref: '#/definitions/CreateClone'
9999
responses:
100-
200:
100+
201:
101101
description: "Successful operation"
102102
schema:
103103
$ref: "#/definitions/Clone"
@@ -172,6 +172,10 @@ paths:
172172
schema:
173173
$ref: '#/definitions/UpdateClone'
174174
responses:
175+
200:
176+
description: "Successful operation"
177+
schema:
178+
$ref: "#/definitions/Clone"
175179
404:
176180
description: "Not found"
177181
schema:

cmd/cli/commands/clone/actions.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/urfave/cli/v2"
1313

1414
"gitlab.com/postgres-ai/database-lab/cmd/cli/commands"
15-
"gitlab.com/postgres-ai/database-lab/pkg/client/dblabapi"
15+
"gitlab.com/postgres-ai/database-lab/pkg/client/dblabapi/types"
1616
"gitlab.com/postgres-ai/database-lab/pkg/models"
1717
)
1818

@@ -48,16 +48,20 @@ func create() func(*cli.Context) error {
4848
return err
4949
}
5050

51-
cloneRequest := dblabapi.CreateRequest{
51+
cloneRequest := types.CloneCreateRequest{
5252
ID: cliCtx.String("id"),
5353
Project: cliCtx.String("project"),
5454
Protected: cliCtx.Bool("protected"),
55-
DB: &dblabapi.DatabaseRequest{
55+
DB: &types.DatabaseRequest{
5656
Username: cliCtx.String("username"),
5757
Password: cliCtx.String("password"),
5858
},
5959
}
6060

61+
if cliCtx.IsSet("snapshot-id") {
62+
cloneRequest.Snapshot = &types.SnapshotCloneFieldRequest{ID: cliCtx.String("snapshot-id")}
63+
}
64+
6165
var clone *models.Clone
6266

6367
if cliCtx.Bool("async") {
@@ -113,7 +117,7 @@ func update() func(*cli.Context) error {
113117
return err
114118
}
115119

116-
updateRequest := dblabapi.UpdateRequest{
120+
updateRequest := types.CloneUpdateRequest{
117121
Protected: cliCtx.Bool("protected"),
118122
}
119123

cmd/cli/commands/clone/command_list.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ func CommandList() []*cli.Command {
4747
Name: "id",
4848
Usage: "clone ID (optional)",
4949
},
50+
&cli.StringFlag{
51+
Name: "snapshot-id",
52+
Usage: "snapshot ID (optional)",
53+
},
5054
&cli.StringFlag{
5155
Name: "project",
5256
Usage: "project name (optional)",

cmd/cli/commands/initialization/command_list.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func GlobalList() []*cli.Command {
1919
CustomHelpTemplate: templates.CustomCommandHelpTemplate + templates.SupportProjectTemplate,
2020
Flags: []cli.Flag{
2121
&cli.StringFlag{
22-
Name: "environment_id",
22+
Name: "environment-id",
2323
Usage: "environment ID of Database Lab instance's API",
2424
Required: true,
2525
},

pkg/client/dblabapi/clone.go

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/pkg/errors"
1616

17+
"gitlab.com/postgres-ai/database-lab/pkg/client/dblabapi/types"
1718
"gitlab.com/postgres-ai/database-lab/pkg/models"
1819
)
1920

@@ -67,27 +68,13 @@ func (c *Client) GetClone(ctx context.Context, cloneID string) (*models.Clone, e
6768
return &clone, nil
6869
}
6970

70-
// CreateRequest represents clone params of a create request.
71-
type CreateRequest struct {
72-
ID string `json:"id"`
73-
Project string `json:"project"`
74-
Protected bool `json:"protected"`
75-
DB *DatabaseRequest `json:"db"`
76-
}
77-
78-
// DatabaseRequest represents database params of a clone request.
79-
type DatabaseRequest struct {
80-
Username string `json:"username"`
81-
Password string `json:"password"`
82-
}
83-
8471
// CreateClone creates a new Database Lab clone.
85-
func (c *Client) CreateClone(ctx context.Context, cloneRequest CreateRequest) (*models.Clone, error) {
72+
func (c *Client) CreateClone(ctx context.Context, cloneRequest types.CloneCreateRequest) (*models.Clone, error) {
8673
u := c.URL("/clone")
8774

8875
body := bytes.NewBuffer(nil)
8976
if err := json.NewEncoder(body).Encode(cloneRequest); err != nil {
90-
return nil, errors.Wrap(err, "failed to encode CreateRequest")
77+
return nil, errors.Wrap(err, "failed to encode CloneCreateRequest")
9178
}
9279

9380
request, err := http.NewRequest(http.MethodPost, u.String(), body)
@@ -161,12 +148,12 @@ func (c *Client) watchCloneStatus(ctx context.Context, cloneID string, initialSt
161148
}
162149

163150
// CreateCloneAsync asynchronously creates a new Database Lab clone.
164-
func (c *Client) CreateCloneAsync(ctx context.Context, cloneRequest CreateRequest) (*models.Clone, error) {
151+
func (c *Client) CreateCloneAsync(ctx context.Context, cloneRequest types.CloneCreateRequest) (*models.Clone, error) {
165152
u := c.URL("/clone")
166153

167154
body := bytes.NewBuffer(nil)
168155
if err := json.NewEncoder(body).Encode(cloneRequest); err != nil {
169-
return nil, errors.Wrap(err, "failed to encode CreateRequest")
156+
return nil, errors.Wrap(err, "failed to encode CloneCreateRequest")
170157
}
171158

172159
request, err := http.NewRequest(http.MethodPost, u.String(), body)
@@ -190,18 +177,13 @@ func (c *Client) CreateCloneAsync(ctx context.Context, cloneRequest CreateReques
190177
return &clone, nil
191178
}
192179

193-
// UpdateRequest represents params of an update request.
194-
type UpdateRequest struct {
195-
Protected bool `json:"protected"`
196-
}
197-
198180
// UpdateClone updates an existing Database Lab clone.
199-
func (c *Client) UpdateClone(ctx context.Context, cloneID string, updateRequest UpdateRequest) (*models.Clone, error) {
181+
func (c *Client) UpdateClone(ctx context.Context, cloneID string, updateRequest types.CloneUpdateRequest) (*models.Clone, error) {
200182
u := c.URL(fmt.Sprintf("/clone/%s", cloneID))
201183

202184
body := bytes.NewBuffer(nil)
203185
if err := json.NewEncoder(body).Encode(updateRequest); err != nil {
204-
return nil, errors.Wrap(err, "failed to encode UpdateRequest")
186+
return nil, errors.Wrap(err, "failed to encode CloneUpdateRequest")
205187
}
206188

207189
request, err := http.NewRequest(http.MethodPatch, u.String(), body)

pkg/client/dblabapi/clone_test.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/stretchr/testify/assert"
1414
"github.com/stretchr/testify/require"
1515

16+
"gitlab.com/postgres-ai/database-lab/pkg/client/dblabapi/types"
1617
"gitlab.com/postgres-ai/database-lab/pkg/models"
1718
)
1819

@@ -122,7 +123,7 @@ func TestClientCreateClone(t *testing.T) {
122123
require.NoError(t, err)
123124
defer func() { _ = r.Body.Close() }()
124125

125-
cloneRequest := CreateRequest{}
126+
cloneRequest := types.CloneCreateRequest{}
126127
err = json.Unmarshal(requestBody, &cloneRequest)
127128
require.NoError(t, err)
128129
clone = expectedClone
@@ -156,11 +157,11 @@ func TestClientCreateClone(t *testing.T) {
156157
defer cancel()
157158

158159
// Send a request.
159-
newClone, err := c.CreateClone(ctx, CreateRequest{
160+
newClone, err := c.CreateClone(ctx, types.CloneCreateRequest{
160161
ID: "testCloneID",
161162
Project: "testProject",
162163
Protected: true,
163-
DB: &DatabaseRequest{
164+
DB: &types.DatabaseRequest{
164165
Username: "john",
165166
Password: "doe",
166167
},
@@ -198,7 +199,7 @@ func TestClientCreateCloneAsync(t *testing.T) {
198199
require.NoError(t, err)
199200
defer func() { _ = r.Body.Close() }()
200201

201-
cloneRequest := CreateRequest{}
202+
cloneRequest := types.CloneCreateRequest{}
202203
err = json.Unmarshal(requestBody, &cloneRequest)
203204
require.NoError(t, err)
204205

@@ -226,11 +227,11 @@ func TestClientCreateCloneAsync(t *testing.T) {
226227
defer cancel()
227228

228229
// Send a request.
229-
newClone, err := c.CreateCloneAsync(ctx, CreateRequest{
230+
newClone, err := c.CreateCloneAsync(ctx, types.CloneCreateRequest{
230231
ID: "testCloneID",
231232
Project: "testProject",
232233
Protected: true,
233-
DB: &DatabaseRequest{
234+
DB: &types.DatabaseRequest{
234235
Username: "john",
235236
Password: "doe",
236237
},
@@ -258,7 +259,7 @@ func TestClientCreateCloneWithFailedRequest(t *testing.T) {
258259

259260
c.client = mockClient
260261

261-
clone, err := c.CreateClone(context.Background(), CreateRequest{})
262+
clone, err := c.CreateClone(context.Background(), types.CloneCreateRequest{})
262263
require.EqualError(t, err, "failed to decode a response body: EOF")
263264
require.Nil(t, clone)
264265
}
@@ -365,7 +366,7 @@ func TestClientUpdateClone(t *testing.T) {
365366
require.NoError(t, err)
366367
defer func() { _ = r.Body.Close() }()
367368

368-
updateRequest := UpdateRequest{}
369+
updateRequest := types.CloneUpdateRequest{}
369370
err = json.Unmarshal(requestBody, &updateRequest)
370371
require.NoError(t, err)
371372

@@ -392,7 +393,7 @@ func TestClientUpdateClone(t *testing.T) {
392393
c.client = mockClient
393394

394395
// Send a request.
395-
newClone, err := c.UpdateClone(context.Background(), cloneModel.ID, UpdateRequest{
396+
newClone, err := c.UpdateClone(context.Background(), cloneModel.ID, types.CloneUpdateRequest{
396397
Protected: false,
397398
})
398399
require.NoError(t, err)
@@ -429,7 +430,7 @@ func TestClientUpdateCloneWithFailedRequest(t *testing.T) {
429430

430431
c.client = mockClient
431432

432-
clone, err := c.UpdateClone(context.Background(), "testCloneID", UpdateRequest{})
433+
clone, err := c.UpdateClone(context.Background(), "testCloneID", types.CloneUpdateRequest{})
433434
require.EqualError(t, err, `failed to get response: Code "BAD_REQUEST". Message: Wrong request format. Detail: Clone not found. Hint: Check request params.`)
434435
require.Nil(t, clone)
435436
}

pkg/client/dblabapi/types/clone.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
2020 © Postgres.ai
3+
*/
4+
5+
// Package types provides request structures for Database Lab HTTP API.
6+
package types
7+
8+
// CloneCreateRequest represents clone params of a create request.
9+
type CloneCreateRequest struct {
10+
ID string `json:"id"`
11+
Project string `json:"project"`
12+
Protected bool `json:"protected"`
13+
DB *DatabaseRequest `json:"db"`
14+
Snapshot *SnapshotCloneFieldRequest `json:"snapshot"`
15+
}
16+
17+
// CloneUpdateRequest represents params of an update request.
18+
type CloneUpdateRequest struct {
19+
Protected bool `json:"protected"`
20+
}
21+
22+
// DatabaseRequest represents database params of a clone request.
23+
type DatabaseRequest struct {
24+
Username string `json:"username"`
25+
Password string `json:"password"`
26+
}
27+
28+
// SnapshotCloneFieldRequest represents snapshot params of a create request.
29+
type SnapshotCloneFieldRequest struct {
30+
ID string `json:"id"`
31+
}

pkg/services/cloning/cloning.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/pkg/errors"
1313

14+
"gitlab.com/postgres-ai/database-lab/pkg/client/dblabapi/types"
1415
"gitlab.com/postgres-ai/database-lab/pkg/log"
1516
"gitlab.com/postgres-ai/database-lab/pkg/models"
1617
"gitlab.com/postgres-ai/database-lab/pkg/services/provision"
@@ -43,10 +44,10 @@ type cloning struct {
4344
type Cloning interface {
4445
Run(ctx context.Context) error
4546

46-
CreateClone(*models.Clone) error
47+
CreateClone(*types.CloneCreateRequest) (*models.Clone, error)
4748
DestroyClone(string) error
4849
GetClone(string) (*models.Clone, error)
49-
UpdateClone(string, *models.Clone) error
50+
UpdateClone(string, *types.CloneUpdateRequest) (*models.Clone, error)
5051
ResetClone(string) error
5152

5253
GetInstanceState() (*models.InstanceStatus, error)

0 commit comments

Comments
 (0)