Skip to content

Commit

Permalink
feat: update state storage which is identified by project and workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
healthjyk committed Apr 16, 2024
1 parent f41bf84 commit 24ad361
Show file tree
Hide file tree
Showing 15 changed files with 49 additions and 60 deletions.
2 changes: 1 addition & 1 deletion pkg/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pkg/backend/storages/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
13 changes: 6 additions & 7 deletions pkg/backend/storages/local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,27 @@ 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",
localStorage: &LocalStorage{
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)
})
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/backend/storages/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
12 changes: 5 additions & 7 deletions pkg/backend/storages/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,29 @@ 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",
mysqlStorage: &MysqlStorage{
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)
})
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/backend/storages/oss.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
13 changes: 6 additions & 7 deletions pkg/backend/storages/oss_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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)
})
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/backend/storages/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
13 changes: 6 additions & 7 deletions pkg/backend/storages/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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)
})
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/destroy/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
6 changes: 3 additions & 3 deletions pkg/cmd/destroy/destroy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
Expand Down Expand Up @@ -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)
})
Expand All @@ -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)
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/preview/preview.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 7 additions & 13 deletions pkg/engine/state/storages/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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
}
Expand All @@ -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
}
Expand All @@ -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{}
Expand All @@ -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{}
Expand All @@ -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
Expand All @@ -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
Expand Down
8 changes: 4 additions & 4 deletions pkg/engine/state/storages/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

0 comments on commit 24ad361

Please sign in to comment.