Skip to content

fix: workspace update and delete API #1375

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions api/openapispec/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5433,10 +5433,6 @@ const docTemplate = `{
"id"
],
"properties": {
"backendID": {
"description": "BackendID is the configuration backend id associated with the workspace.",
"type": "integer"
},
"description": {
"description": "Description is a human-readable description of the workspace.",
"type": "string"
Expand Down
4 changes: 0 additions & 4 deletions api/openapispec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -5422,10 +5422,6 @@
"id"
],
"properties": {
"backendID": {
"description": "BackendID is the configuration backend id associated with the workspace.",
"type": "integer"
},
"description": {
"description": "Description is a human-readable description of the workspace.",
"type": "string"
Expand Down
4 changes: 0 additions & 4 deletions api/openapispec/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1218,10 +1218,6 @@ definitions:
type: object
request.UpdateWorkspaceRequest:
properties:
backendID:
description: BackendID is the configuration backend id associated with the
workspace.
type: integer
description:
description: Description is a human-readable description of the workspace.
type: string
Expand Down
4 changes: 4 additions & 0 deletions pkg/cmd/release/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ func (f *fakeWorkspaceStorage) SetCurrent(name string) error {
return nil
}

func (f *fakeWorkspaceStorage) RenameWorkspace(oldName, newName string) error {
return nil
}

type fakeStorageForList struct {
revisions []uint64
releases map[uint64]*v1.Release
Expand Down
8 changes: 6 additions & 2 deletions pkg/cmd/workspace/update/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ func NewCmd() *cobra.Command {
kusion workspace update dev -f dev.yaml --current

# Update a specified workspace in a specified backend
kusion workspace update prod -f prod.yaml --backend oss-prod`)
kusion workspace update prod -f prod.yaml --backend oss-prod

# Update a specified workspace with a specified name
kusion workspace update dev --rename dev-test`)
)

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

cmd.Flags().StringVarP(&o.FilePath, "file", "f", "", i18n.T("the path of workspace configuration file"))
cmd.Flags().StringVarP(&o.Backend, "backend", "", "", i18n.T("the backend name"))
cmd.Flags().StringVarP(&o.Backend, "backend", "b", "", i18n.T("the backend name"))
cmd.Flags().StringVarP(&o.NewName, "rename", "r", "", i18n.T("the new name of the workspace"))
cmd.Flags().BoolVarP(&o.Current, "current", "", false, i18n.T("set the creating workspace as current"))
return cmd
}
35 changes: 27 additions & 8 deletions pkg/cmd/workspace/update/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Options struct {
FilePath string
Backend string
Current bool
NewName string
}

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

func (o *Options) Validate() error {
if err := util.ValidateFilePath(o.FilePath); err != nil {
return err
if o.NewName != "" {
if err := util.ValidateNotDefaultName(o.NewName); err != nil {
return err
}
if err := util.ValidateNotDefaultName(o.Name); err != nil {
return err
}
}
return nil
}
Expand All @@ -53,12 +59,25 @@ func (o *Options) Run() error {
return err
}
}
ws, err := util.GetValidWorkspaceFromFile(o.FilePath, o.Name)
if err != nil {
return err

if o.NewName == "" && o.FilePath == "" {
return fmt.Errorf("new name or file path is required")
}
if err = storage.Update(ws); err != nil {
return err

if o.NewName != "" {
if err = storage.RenameWorkspace(o.Name, o.NewName); err != nil {
return err
}
}

if o.FilePath != "" {
ws, err := util.GetValidWorkspaceFromFile(o.FilePath, o.Name)
if err != nil {
return err
}
if err = storage.Update(ws); err != nil {
return err
}
}

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

fmt.Printf("update workspace %s successfully\n", ws.Name)
fmt.Printf("update workspace %s successfully\n", o.Name)
return nil
}
9 changes: 5 additions & 4 deletions pkg/cmd/workspace/update/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,16 @@ func TestOptions_Validate(t *testing.T) {
{
name: "valid options",
opts: &Options{
Name: "dev",
FilePath: "dev.yaml",
Name: "dev",
NewName: "dev-test",
},
success: true,
},
{
name: "invalid options empty file path",
name: "invalid options invalid new name",
opts: &Options{
Name: "dev",
Name: "dev",
NewName: "default",
},
success: false,
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/workspace/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
var (
ErrMoreThanOneArgs = errors.New("more than one args are not accepted")
ErrEmptyName = errors.New("empty workspace name")
ErrInvalidDefault = errors.New("invalid default workspace")
ErrInvalidDefault = errors.New("default workspace cannot be modified")
ErrEmptyFilePath = errors.New("empty configuration file path")
)

Expand Down
9 changes: 5 additions & 4 deletions pkg/domain/constant/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package constant
import "errors"

var (
ErrEmptyWorkspaceName = errors.New("workspace must have a name")
ErrInvalidWorkspaceName = errors.New("workspace name can only have alphanumeric characters and underscores with [a-zA-Z0-9_]")
ErrEmptyOwners = errors.New("workspace must have at least one owner")
ErrEmptyBackendID = errors.New("workspace must have a backend id")
ErrEmptyWorkspaceName = errors.New("workspace must have a name")
ErrInvalidWorkspaceName = errors.New("workspace name can only have alphanumeric characters and underscores with [a-zA-Z0-9_]")
ErrEmptyOwners = errors.New("workspace must have at least one owner")
ErrEmptyBackendID = errors.New("workspace must have a backend id")
ErrInvalidDefaultWorkspaceName = errors.New("workspace name cannot be \"default\"")
)
10 changes: 8 additions & 2 deletions pkg/domain/request/workspace_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ type UpdateWorkspaceRequest struct {
Labels map[string]string `json:"labels"`
// Owners is a list of owners for the workspace.
Owners []string `json:"owners"`
// BackendID is the configuration backend id associated with the workspace.
BackendID uint `json:"backendID"`
}

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

if payload.Name == constant.DefaultWorkspace {
return constant.ErrInvalidDefaultWorkspaceName
}

if validName(payload.Name) {
return constant.ErrInvalidWorkspaceName
}
Expand All @@ -75,6 +77,10 @@ func (payload *CreateWorkspaceRequest) Validate() error {
}

func (payload *UpdateWorkspaceRequest) Validate() error {
if payload.Name == constant.DefaultWorkspace {
return constant.ErrInvalidDefaultWorkspaceName
}

if payload.Name != "" && validName(payload.Name) {
return constant.ErrInvalidWorkspaceName
}
Expand Down
25 changes: 16 additions & 9 deletions pkg/server/handler/workspace/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,8 @@ func TestWorkspaceHandler(t *testing.T) {

// Set request body
requestPayload := request.UpdateWorkspaceRequest{
ID: 1,
Name: wsNameUpdated,
BackendID: 1,
ID: 1,
Name: wsNameUpdated,
}
reqBody, err := json.Marshal(requestPayload)
assert.NoError(t, err)
Expand Down Expand Up @@ -212,10 +211,16 @@ func TestWorkspaceHandler(t *testing.T) {
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))

// Mock the Delete method of the workspace repository
sqlMock.ExpectQuery("SELECT").
WillReturnRows(sqlmock.NewRows([]string{"id", "name", "Backend__id"}).
AddRow(1, "test-ws", 1))
sqlMock.ExpectQuery("SELECT").
WillReturnRows(sqlmock.NewRows([]string{"id", "backend_config"}).
AddRow(1, "{\"type\":\"local\"}"))
sqlMock.ExpectBegin()
sqlMock.ExpectQuery("SELECT").
WillReturnRows(sqlmock.NewRows([]string{"id"}).
AddRow(1))
WillReturnRows(sqlmock.NewRows([]string{"id", "name", "Backend__id"}).
AddRow(1, "test-ws", 1))
sqlMock.ExpectExec("DELETE").WillReturnResult(sqlmock.NewResult(1, 0))
sqlMock.ExpectCommit()

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

sqlMock.ExpectBegin()
sqlMock.ExpectQuery("SELECT").
WillReturnRows(sqlmock.NewRows([]string{"id"}))

Expand Down Expand Up @@ -280,9 +284,8 @@ func TestWorkspaceHandler(t *testing.T) {
// Set request body
requestPayload := request.UpdateWorkspaceRequest{
// Set your request payload fields here
ID: 1,
Name: "test-ws-updated",
BackendID: 1,
ID: 1,
Name: "test-ws-updated",
}
reqBody, err := json.Marshal(requestPayload)
assert.NoError(t, err)
Expand Down Expand Up @@ -380,3 +383,7 @@ func (m *mockStorage) GetCurrent() (string, error) {
func (m *mockStorage) SetCurrent(name string) error {
return nil
}

func (m *mockStorage) RenameWorkspace(oldName, newName string) error {
return nil
}
Loading
Loading