Skip to content

Commit 2103f06

Browse files
authored
fix: workspace update and delete API (#1375)
1 parent e59a896 commit 2103f06

File tree

26 files changed

+614
-72
lines changed

26 files changed

+614
-72
lines changed

api/openapispec/docs.go

-4
Original file line numberDiff line numberDiff line change
@@ -5433,10 +5433,6 @@ const docTemplate = `{
54335433
"id"
54345434
],
54355435
"properties": {
5436-
"backendID": {
5437-
"description": "BackendID is the configuration backend id associated with the workspace.",
5438-
"type": "integer"
5439-
},
54405436
"description": {
54415437
"description": "Description is a human-readable description of the workspace.",
54425438
"type": "string"

api/openapispec/swagger.json

-4
Original file line numberDiff line numberDiff line change
@@ -5422,10 +5422,6 @@
54225422
"id"
54235423
],
54245424
"properties": {
5425-
"backendID": {
5426-
"description": "BackendID is the configuration backend id associated with the workspace.",
5427-
"type": "integer"
5428-
},
54295425
"description": {
54305426
"description": "Description is a human-readable description of the workspace.",
54315427
"type": "string"

api/openapispec/swagger.yaml

-4
Original file line numberDiff line numberDiff line change
@@ -1218,10 +1218,6 @@ definitions:
12181218
type: object
12191219
request.UpdateWorkspaceRequest:
12201220
properties:
1221-
backendID:
1222-
description: BackendID is the configuration backend id associated with the
1223-
workspace.
1224-
type: integer
12251221
description:
12261222
description: Description is a human-readable description of the workspace.
12271223
type: string

pkg/cmd/release/list_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ func (f *fakeWorkspaceStorage) SetCurrent(name string) error {
102102
return nil
103103
}
104104

105+
func (f *fakeWorkspaceStorage) RenameWorkspace(oldName, newName string) error {
106+
return nil
107+
}
108+
105109
type fakeStorageForList struct {
106110
revisions []uint64
107111
releases map[uint64]*v1.Release

pkg/cmd/workspace/update/cmd.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ func NewCmd() *cobra.Command {
2323
kusion workspace update dev -f dev.yaml --current
2424
2525
# Update a specified workspace in a specified backend
26-
kusion workspace update prod -f prod.yaml --backend oss-prod`)
26+
kusion workspace update prod -f prod.yaml --backend oss-prod
27+
28+
# Update a specified workspace with a specified name
29+
kusion workspace update dev --rename dev-test`)
2730
)
2831

2932
o := NewOptions()
@@ -43,7 +46,8 @@ func NewCmd() *cobra.Command {
4346
}
4447

4548
cmd.Flags().StringVarP(&o.FilePath, "file", "f", "", i18n.T("the path of workspace configuration file"))
46-
cmd.Flags().StringVarP(&o.Backend, "backend", "", "", i18n.T("the backend name"))
49+
cmd.Flags().StringVarP(&o.Backend, "backend", "b", "", i18n.T("the backend name"))
50+
cmd.Flags().StringVarP(&o.NewName, "rename", "r", "", i18n.T("the new name of the workspace"))
4751
cmd.Flags().BoolVarP(&o.Current, "current", "", false, i18n.T("set the creating workspace as current"))
4852
return cmd
4953
}

pkg/cmd/workspace/update/options.go

+27-8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type Options struct {
1212
FilePath string
1313
Backend string
1414
Current bool
15+
NewName string
1516
}
1617

1718
func NewOptions() *Options {
@@ -28,8 +29,13 @@ func (o *Options) Complete(args []string) error {
2829
}
2930

3031
func (o *Options) Validate() error {
31-
if err := util.ValidateFilePath(o.FilePath); err != nil {
32-
return err
32+
if o.NewName != "" {
33+
if err := util.ValidateNotDefaultName(o.NewName); err != nil {
34+
return err
35+
}
36+
if err := util.ValidateNotDefaultName(o.Name); err != nil {
37+
return err
38+
}
3339
}
3440
return nil
3541
}
@@ -53,12 +59,25 @@ func (o *Options) Run() error {
5359
return err
5460
}
5561
}
56-
ws, err := util.GetValidWorkspaceFromFile(o.FilePath, o.Name)
57-
if err != nil {
58-
return err
62+
63+
if o.NewName == "" && o.FilePath == "" {
64+
return fmt.Errorf("new name or file path is required")
5965
}
60-
if err = storage.Update(ws); err != nil {
61-
return err
66+
67+
if o.NewName != "" {
68+
if err = storage.RenameWorkspace(o.Name, o.NewName); err != nil {
69+
return err
70+
}
71+
}
72+
73+
if o.FilePath != "" {
74+
ws, err := util.GetValidWorkspaceFromFile(o.FilePath, o.Name)
75+
if err != nil {
76+
return err
77+
}
78+
if err = storage.Update(ws); err != nil {
79+
return err
80+
}
6281
}
6382

6483
if o.Current && o.Name != "" {
@@ -67,6 +86,6 @@ func (o *Options) Run() error {
6786
}
6887
}
6988

70-
fmt.Printf("update workspace %s successfully\n", ws.Name)
89+
fmt.Printf("update workspace %s successfully\n", o.Name)
7190
return nil
7291
}

pkg/cmd/workspace/update/options_test.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,16 @@ func TestOptions_Validate(t *testing.T) {
5555
{
5656
name: "valid options",
5757
opts: &Options{
58-
Name: "dev",
59-
FilePath: "dev.yaml",
58+
Name: "dev",
59+
NewName: "dev-test",
6060
},
6161
success: true,
6262
},
6363
{
64-
name: "invalid options empty file path",
64+
name: "invalid options invalid new name",
6565
opts: &Options{
66-
Name: "dev",
66+
Name: "dev",
67+
NewName: "default",
6768
},
6869
success: false,
6970
},

pkg/cmd/workspace/util/util.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
var (
1616
ErrMoreThanOneArgs = errors.New("more than one args are not accepted")
1717
ErrEmptyName = errors.New("empty workspace name")
18-
ErrInvalidDefault = errors.New("invalid default workspace")
18+
ErrInvalidDefault = errors.New("default workspace cannot be modified")
1919
ErrEmptyFilePath = errors.New("empty configuration file path")
2020
)
2121

pkg/domain/constant/workspace.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ package constant
33
import "errors"
44

55
var (
6-
ErrEmptyWorkspaceName = errors.New("workspace must have a name")
7-
ErrInvalidWorkspaceName = errors.New("workspace name can only have alphanumeric characters and underscores with [a-zA-Z0-9_]")
8-
ErrEmptyOwners = errors.New("workspace must have at least one owner")
9-
ErrEmptyBackendID = errors.New("workspace must have a backend id")
6+
ErrEmptyWorkspaceName = errors.New("workspace must have a name")
7+
ErrInvalidWorkspaceName = errors.New("workspace name can only have alphanumeric characters and underscores with [a-zA-Z0-9_]")
8+
ErrEmptyOwners = errors.New("workspace must have at least one owner")
9+
ErrEmptyBackendID = errors.New("workspace must have a backend id")
10+
ErrInvalidDefaultWorkspaceName = errors.New("workspace name cannot be \"default\"")
1011
)

pkg/domain/request/workspace_request.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ type UpdateWorkspaceRequest struct {
3535
Labels map[string]string `json:"labels"`
3636
// Owners is a list of owners for the workspace.
3737
Owners []string `json:"owners"`
38-
// BackendID is the configuration backend id associated with the workspace.
39-
BackendID uint `json:"backendID"`
4038
}
4139

4240
type WorkspaceCredentials struct {
@@ -59,6 +57,10 @@ func (payload *CreateWorkspaceRequest) Validate() error {
5957
return constant.ErrEmptyWorkspaceName
6058
}
6159

60+
if payload.Name == constant.DefaultWorkspace {
61+
return constant.ErrInvalidDefaultWorkspaceName
62+
}
63+
6264
if validName(payload.Name) {
6365
return constant.ErrInvalidWorkspaceName
6466
}
@@ -75,6 +77,10 @@ func (payload *CreateWorkspaceRequest) Validate() error {
7577
}
7678

7779
func (payload *UpdateWorkspaceRequest) Validate() error {
80+
if payload.Name == constant.DefaultWorkspace {
81+
return constant.ErrInvalidDefaultWorkspaceName
82+
}
83+
7884
if payload.Name != "" && validName(payload.Name) {
7985
return constant.ErrInvalidWorkspaceName
8086
}

pkg/server/handler/workspace/handler_test.go

+16-9
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,8 @@ func TestWorkspaceHandler(t *testing.T) {
167167

168168
// Set request body
169169
requestPayload := request.UpdateWorkspaceRequest{
170-
ID: 1,
171-
Name: wsNameUpdated,
172-
BackendID: 1,
170+
ID: 1,
171+
Name: wsNameUpdated,
173172
}
174173
reqBody, err := json.Marshal(requestPayload)
175174
assert.NoError(t, err)
@@ -212,10 +211,16 @@ func TestWorkspaceHandler(t *testing.T) {
212211
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
213212

214213
// Mock the Delete method of the workspace repository
214+
sqlMock.ExpectQuery("SELECT").
215+
WillReturnRows(sqlmock.NewRows([]string{"id", "name", "Backend__id"}).
216+
AddRow(1, "test-ws", 1))
217+
sqlMock.ExpectQuery("SELECT").
218+
WillReturnRows(sqlmock.NewRows([]string{"id", "backend_config"}).
219+
AddRow(1, "{\"type\":\"local\"}"))
215220
sqlMock.ExpectBegin()
216221
sqlMock.ExpectQuery("SELECT").
217-
WillReturnRows(sqlmock.NewRows([]string{"id"}).
218-
AddRow(1))
222+
WillReturnRows(sqlmock.NewRows([]string{"id", "name", "Backend__id"}).
223+
AddRow(1, "test-ws", 1))
219224
sqlMock.ExpectExec("DELETE").WillReturnResult(sqlmock.NewResult(1, 0))
220225
sqlMock.ExpectCommit()
221226

@@ -246,7 +251,6 @@ func TestWorkspaceHandler(t *testing.T) {
246251
rctx.URLParams.Add("workspaceID", "1")
247252
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
248253

249-
sqlMock.ExpectBegin()
250254
sqlMock.ExpectQuery("SELECT").
251255
WillReturnRows(sqlmock.NewRows([]string{"id"}))
252256

@@ -280,9 +284,8 @@ func TestWorkspaceHandler(t *testing.T) {
280284
// Set request body
281285
requestPayload := request.UpdateWorkspaceRequest{
282286
// Set your request payload fields here
283-
ID: 1,
284-
Name: "test-ws-updated",
285-
BackendID: 1,
287+
ID: 1,
288+
Name: "test-ws-updated",
286289
}
287290
reqBody, err := json.Marshal(requestPayload)
288291
assert.NoError(t, err)
@@ -380,3 +383,7 @@ func (m *mockStorage) GetCurrent() (string, error) {
380383
func (m *mockStorage) SetCurrent(name string) error {
381384
return nil
382385
}
386+
387+
func (m *mockStorage) RenameWorkspace(oldName, newName string) error {
388+
return nil
389+
}

0 commit comments

Comments
 (0)