From a2ab18f0421ef8c6a0ed898a04a77c742db0659d Mon Sep 17 00:00:00 2001 From: healthjyk Date: Tue, 16 Apr 2024 20:54:20 +0800 Subject: [PATCH] feat: update state storage which is identified by project and workspace --- pkg/backend/backend.go | 2 +- pkg/backend/storages/local.go | 4 ++-- pkg/backend/storages/local_test.go | 13 ++++++------- pkg/backend/storages/mysql.go | 4 ++-- pkg/backend/storages/mysql_test.go | 12 +++++------- pkg/backend/storages/oss.go | 4 ++-- pkg/backend/storages/oss_test.go | 13 ++++++------- pkg/backend/storages/s3.go | 4 ++-- pkg/backend/storages/s3_test.go | 13 ++++++------- pkg/cmd/apply/apply.go | 2 +- pkg/cmd/destroy/destroy.go | 2 +- pkg/cmd/destroy/destroy_test.go | 6 +++--- pkg/cmd/preview/preview.go | 2 +- pkg/engine/state/storages/mysql.go | 20 +++++++------------- pkg/engine/state/storages/mysql_test.go | 1 - pkg/engine/state/storages/util.go | 8 ++++---- 16 files changed, 49 insertions(+), 61 deletions(-) diff --git a/pkg/backend/backend.go b/pkg/backend/backend.go index 55ebd7c8..b3f55fa5 100644 --- a/pkg/backend/backend.go +++ b/pkg/backend/backend.go @@ -16,7 +16,7 @@ type Backend interface { WorkspaceStorage() (workspace.Storage, error) // StateStorage returns the state storage. - StateStorage(project, stack, workspace string) state.Storage + StateStorage(project, workspace string) state.Storage } // NewBackend creates the Backend with the configuration set in the Kusion configuration file, where the input diff --git a/pkg/backend/storages/local.go b/pkg/backend/storages/local.go index 3fcfef00..95352bc5 100644 --- a/pkg/backend/storages/local.go +++ b/pkg/backend/storages/local.go @@ -19,8 +19,8 @@ func NewLocalStorage(config *v1.BackendLocalConfig) *LocalStorage { return &LocalStorage{path: config.Path} } -func (s *LocalStorage) StateStorage(project, stack, workspace string) state.Storage { - return statestorages.NewLocalStorage(statestorages.GenStateFilePath(s.path, project, stack, workspace)) +func (s *LocalStorage) StateStorage(project, workspace string) state.Storage { + return statestorages.NewLocalStorage(statestorages.GenStateFilePath(s.path, project, workspace)) } func (s *LocalStorage) WorkspaceStorage() (workspace.Storage, error) { diff --git a/pkg/backend/storages/local_test.go b/pkg/backend/storages/local_test.go index e77bb054..f67a6114 100644 --- a/pkg/backend/storages/local_test.go +++ b/pkg/backend/storages/local_test.go @@ -37,10 +37,10 @@ func TestNewLocalStorage(t *testing.T) { func TestLocalStorage_StateStorage(t *testing.T) { testcases := []struct { - name string - localStorage *LocalStorage - project, stack, workspace string - stateStorage state.Storage + name string + localStorage *LocalStorage + project, workspace string + stateStorage state.Storage }{ { name: "state storage from local backend", @@ -48,17 +48,16 @@ func TestLocalStorage_StateStorage(t *testing.T) { path: "kusion", }, project: "wordpress", - stack: "dev", workspace: "dev", stateStorage: statestorages.NewLocalStorage( - filepath.Join("kusion", "states", "wordpress", "dev", "dev", "state.yaml"), + filepath.Join("kusion", "states", "wordpress", "dev", "state.yaml"), ), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - stateStorage := tc.localStorage.StateStorage(tc.project, tc.stack, tc.workspace) + stateStorage := tc.localStorage.StateStorage(tc.project, tc.workspace) assert.Equal(t, tc.stateStorage, stateStorage) }) } diff --git a/pkg/backend/storages/mysql.go b/pkg/backend/storages/mysql.go index ade0dd9f..a261434a 100644 --- a/pkg/backend/storages/mysql.go +++ b/pkg/backend/storages/mysql.go @@ -40,8 +40,8 @@ func NewMysqlStorage(config *v1.BackendMysqlConfig) (*MysqlStorage, error) { return &MysqlStorage{db: db}, nil } -func (s *MysqlStorage) StateStorage(project, stack, workspace string) state.Storage { - return statestorages.NewMysqlStorage(s.db, project, stack, workspace) +func (s *MysqlStorage) StateStorage(project, workspace string) state.Storage { + return statestorages.NewMysqlStorage(s.db, project, workspace) } func (s *MysqlStorage) WorkspaceStorage() (workspace.Storage, error) { diff --git a/pkg/backend/storages/mysql_test.go b/pkg/backend/storages/mysql_test.go index 5cc25c78..2d76fb04 100644 --- a/pkg/backend/storages/mysql_test.go +++ b/pkg/backend/storages/mysql_test.go @@ -44,10 +44,10 @@ func TestNewMysqlStorage(t *testing.T) { func TestMysqlStorage_StateStorage(t *testing.T) { testcases := []struct { - name string - mysqlStorage *MysqlStorage - project, stack, workspace string - stateStorage state.Storage + name string + mysqlStorage *MysqlStorage + project, workspace string + stateStorage state.Storage }{ { name: "state storage from mysql", @@ -55,20 +55,18 @@ func TestMysqlStorage_StateStorage(t *testing.T) { db: &gorm.DB{}, }, project: "wordpress", - stack: "dev", workspace: "dev", stateStorage: statestorages.NewMysqlStorage( &gorm.DB{}, "wordpress", "dev", - "dev", ), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - stateStorage := tc.mysqlStorage.StateStorage(tc.project, tc.stack, tc.workspace) + stateStorage := tc.mysqlStorage.StateStorage(tc.project, tc.workspace) assert.Equal(t, tc.stateStorage, stateStorage) }) } diff --git a/pkg/backend/storages/oss.go b/pkg/backend/storages/oss.go index d815cf76..e772afbc 100644 --- a/pkg/backend/storages/oss.go +++ b/pkg/backend/storages/oss.go @@ -31,8 +31,8 @@ func NewOssStorage(config *v1.BackendOssConfig) (*OssStorage, error) { return &OssStorage{bucket: bucket, prefix: config.Prefix}, nil } -func (s *OssStorage) StateStorage(project, stack, workspace string) state.Storage { - return statestorages.NewOssStorage(s.bucket, statestorages.GenGenericOssStateFileKey(s.prefix, project, stack, workspace)) +func (s *OssStorage) StateStorage(project, workspace string) state.Storage { + return statestorages.NewOssStorage(s.bucket, statestorages.GenGenericOssStateFileKey(s.prefix, project, workspace)) } func (s *OssStorage) WorkspaceStorage() (workspace.Storage, error) { diff --git a/pkg/backend/storages/oss_test.go b/pkg/backend/storages/oss_test.go index dcda949a..195103dc 100644 --- a/pkg/backend/storages/oss_test.go +++ b/pkg/backend/storages/oss_test.go @@ -46,10 +46,10 @@ func TestNewOssStorage(t *testing.T) { func TestOssStorage_StateStorage(t *testing.T) { testcases := []struct { - name string - ossStorage *OssStorage - project, stack, workspace string - stateStorage state.Storage + name string + ossStorage *OssStorage + project, workspace string + stateStorage state.Storage }{ { name: "state storage from oss backend", @@ -58,18 +58,17 @@ func TestOssStorage_StateStorage(t *testing.T) { prefix: "kusion", }, project: "wordpress", - stack: "dev", workspace: "dev", stateStorage: statestorages.NewOssStorage( &oss.Bucket{}, - "kusion/states/wordpress/dev/dev/state.yaml", + "kusion/states/wordpress/dev/state.yaml", ), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - stateStorage := tc.ossStorage.StateStorage(tc.project, tc.stack, tc.workspace) + stateStorage := tc.ossStorage.StateStorage(tc.project, tc.workspace) assert.Equal(t, tc.stateStorage, stateStorage) }) } diff --git a/pkg/backend/storages/s3.go b/pkg/backend/storages/s3.go index 77e9fe27..1f688861 100644 --- a/pkg/backend/storages/s3.go +++ b/pkg/backend/storages/s3.go @@ -44,8 +44,8 @@ func NewS3Storage(config *v1.BackendS3Config) (*S3Storage, error) { }, nil } -func (s *S3Storage) StateStorage(project, stack, workspace string) state.Storage { - return statestorages.NewS3Storage(s.s3, s.bucket, statestorages.GenGenericOssStateFileKey(s.prefix, project, stack, workspace)) +func (s *S3Storage) StateStorage(project, workspace string) state.Storage { + return statestorages.NewS3Storage(s.s3, s.bucket, statestorages.GenGenericOssStateFileKey(s.prefix, project, workspace)) } func (s *S3Storage) WorkspaceStorage() (workspace.Storage, error) { diff --git a/pkg/backend/storages/s3_test.go b/pkg/backend/storages/s3_test.go index 6e73445c..96cba6ad 100644 --- a/pkg/backend/storages/s3_test.go +++ b/pkg/backend/storages/s3_test.go @@ -48,10 +48,10 @@ func TestNewS3Storage(t *testing.T) { func TestS3Storage_StateStorage(t *testing.T) { testcases := []struct { - name string - s3Storage *S3Storage - project, stack, workspace string - stateStorage state.Storage + name string + s3Storage *S3Storage + project, workspace string + stateStorage state.Storage }{ { name: "state storage from s3 backend", @@ -61,19 +61,18 @@ func TestS3Storage_StateStorage(t *testing.T) { prefix: "kusion", }, project: "wordpress", - stack: "dev", workspace: "dev", stateStorage: statestorages.NewS3Storage( &s3.S3{}, "infra", - "kusion/states/wordpress/dev/dev/state.yaml", + "kusion/states/wordpress/dev/state.yaml", ), }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - stateStorage := tc.s3Storage.StateStorage(tc.project, tc.stack, tc.workspace) + stateStorage := tc.s3Storage.StateStorage(tc.project, tc.workspace) assert.Equal(t, tc.stateStorage, stateStorage) }) } diff --git a/pkg/cmd/apply/apply.go b/pkg/cmd/apply/apply.go index 3c30300a..0c801cc2 100644 --- a/pkg/cmd/apply/apply.go +++ b/pkg/cmd/apply/apply.go @@ -177,7 +177,7 @@ func (o *ApplyOptions) Run() error { } // compute changes for preview - storage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefStack.Name, o.RefWorkspace.Name) + storage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefWorkspace.Name) changes, err := preview.Preview(o.PreviewOptions, storage, spec, o.RefProject, o.RefStack) if err != nil { return err diff --git a/pkg/cmd/destroy/destroy.go b/pkg/cmd/destroy/destroy.go index dfecce7e..5bdd60cc 100644 --- a/pkg/cmd/destroy/destroy.go +++ b/pkg/cmd/destroy/destroy.go @@ -154,7 +154,7 @@ func (o *DeleteOptions) Run() error { signals.HandleInterrupt() // only destroy resources we managed - storage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefStack.Name, o.RefWorkspace.Name) + storage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefWorkspace.Name) priorState, err := storage.Get() if err != nil || priorState == nil { return fmt.Errorf("can not find DeprecatedState in this stack") diff --git a/pkg/cmd/destroy/destroy_test.go b/pkg/cmd/destroy/destroy_test.go index 1238df68..2d6970d4 100644 --- a/pkg/cmd/destroy/destroy_test.go +++ b/pkg/cmd/destroy/destroy_test.go @@ -132,7 +132,7 @@ func TestPreview(t *testing.T) { mockOperationPreview() o := NewDeleteOptions() - stateStorage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefStack.Name, o.RefWorkspace.Name) + stateStorage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefWorkspace.Name) _, err := o.preview(&apiv1.Spec{Resources: []apiv1.Resource{sa1}}, proj, stack, stateStorage) assert.Nil(t, err) }) @@ -249,7 +249,7 @@ func TestDestroy(t *testing.T) { } changes := models.NewChanges(proj, stack, order) - stateStorage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefStack.Name, o.RefWorkspace.Name) + stateStorage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefWorkspace.Name) err := o.destroy(planResources, changes, stateStorage) assert.Nil(t, err) }) @@ -271,7 +271,7 @@ func TestDestroy(t *testing.T) { } changes := models.NewChanges(proj, stack, order) - stateStorage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefStack.Name, o.RefWorkspace.Name) + stateStorage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefWorkspace.Name) err := o.destroy(planResources, changes, stateStorage) assert.NotNil(t, err) }) diff --git a/pkg/cmd/preview/preview.go b/pkg/cmd/preview/preview.go index 75b7c924..3b8332a6 100644 --- a/pkg/cmd/preview/preview.go +++ b/pkg/cmd/preview/preview.go @@ -193,7 +193,7 @@ func (o *PreviewOptions) Run() error { } // compute changes for preview - storage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefStack.Name, o.RefWorkspace.Name) + storage := o.StorageBackend.StateStorage(o.RefProject.Name, o.RefWorkspace.Name) changes, err := Preview(o, storage, spec, o.RefProject, o.RefStack) if err != nil { return err diff --git a/pkg/engine/state/storages/mysql.go b/pkg/engine/state/storages/mysql.go index b9125b57..6d3d70b8 100644 --- a/pkg/engine/state/storages/mysql.go +++ b/pkg/engine/state/storages/mysql.go @@ -11,21 +11,20 @@ import ( // MysqlStorage is an implementation of state.Storage which uses mysql as storage. type MysqlStorage struct { - db *gorm.DB - project, stack, workspace string + db *gorm.DB + project, workspace string } -func NewMysqlStorage(db *gorm.DB, project, stack, workspace string) *MysqlStorage { +func NewMysqlStorage(db *gorm.DB, project, workspace string) *MysqlStorage { return &MysqlStorage{ db: db, project: project, - stack: stack, workspace: workspace, } } func (s *MysqlStorage) Get() (*v1.DeprecatedState, error) { - stateDO, err := getStateFromMysql(s.db, s.project, s.stack, s.workspace) + stateDO, err := getStateFromMysql(s.db, s.project, s.workspace) if err != nil { return nil, err } @@ -36,7 +35,7 @@ func (s *MysqlStorage) Get() (*v1.DeprecatedState, error) { } func (s *MysqlStorage) Apply(state *v1.DeprecatedState) error { - exist, err := checkStateExistenceInMysql(s.db, s.project, s.stack, s.workspace) + exist, err := checkStateExistenceInMysql(s.db, s.project, s.workspace) if err != nil { return err } @@ -55,7 +54,6 @@ func (s *MysqlStorage) Apply(state *v1.DeprecatedState) error { // StateMysqlDO is the data object stored in the mysql db. type StateMysqlDO struct { Project string - Stack string Workspace string Content string } @@ -64,10 +62,9 @@ func (s StateMysqlDO) TableName() string { return stateTable } -func getStateFromMysql(db *gorm.DB, project, stack, workspace string) (*StateMysqlDO, error) { +func getStateFromMysql(db *gorm.DB, project, workspace string) (*StateMysqlDO, error) { q := &StateMysqlDO{ Project: project, - Stack: stack, Workspace: workspace, } s := &StateMysqlDO{} @@ -79,10 +76,9 @@ func getStateFromMysql(db *gorm.DB, project, stack, workspace string) (*StateMys return s, result.Error } -func checkStateExistenceInMysql(db *gorm.DB, project, stack, workspace string) (bool, error) { +func checkStateExistenceInMysql(db *gorm.DB, project, workspace string) (bool, error) { q := &StateMysqlDO{ Project: project, - Stack: stack, Workspace: workspace, } s := &StateMysqlDO{} @@ -100,7 +96,6 @@ func createStateInMysql(db *gorm.DB, s *StateMysqlDO) error { func updateStateInMysql(db *gorm.DB, s *StateMysqlDO) error { q := &StateMysqlDO{ Project: s.Project, - Stack: s.Stack, Workspace: s.Workspace, } return db.Where(q).Updates(s).Error @@ -113,7 +108,6 @@ func convertToMysqlDO(state *v1.DeprecatedState) (*StateMysqlDO, error) { } return &StateMysqlDO{ Project: state.Project, - Stack: state.Stack, Workspace: state.Workspace, Content: string(content), }, nil diff --git a/pkg/engine/state/storages/mysql_test.go b/pkg/engine/state/storages/mysql_test.go index fde543b7..dbd99f1c 100644 --- a/pkg/engine/state/storages/mysql_test.go +++ b/pkg/engine/state/storages/mysql_test.go @@ -13,7 +13,6 @@ import ( func mockStateMysqlDO() *StateMysqlDO { return &StateMysqlDO{ Project: "wordpress", - Stack: "dev", Workspace: "dev", Content: mockStateContent(), } diff --git a/pkg/engine/state/storages/util.go b/pkg/engine/state/storages/util.go index a79fa43d..d170e35f 100644 --- a/pkg/engine/state/storages/util.go +++ b/pkg/engine/state/storages/util.go @@ -13,15 +13,15 @@ const ( ) // GenStateFilePath generates the state file path, which is used for LocalStorage. -func GenStateFilePath(dir, project, stack, workspace string) string { - return filepath.Join(dir, statesPrefix, project, stack, workspace, stateFile) +func GenStateFilePath(dir, project, workspace string) string { + return filepath.Join(dir, statesPrefix, project, workspace, stateFile) } // GenGenericOssStateFileKey generates generic oss state file key, which is use for OssStorage and S3Storage. -func GenGenericOssStateFileKey(prefix, project, stack, workspace string) string { +func GenGenericOssStateFileKey(prefix, project, workspace string) string { prefix = strings.TrimPrefix(prefix, "/") if prefix != "" { prefix += "/" } - return fmt.Sprintf("%s%s/%s/%s/%s/%s", prefix, statesPrefix, project, stack, workspace, stateFile) + return fmt.Sprintf("%s%s/%s/%s/%s", prefix, statesPrefix, project, workspace, stateFile) }