Skip to content

Commit

Permalink
style: make state storages more tidy (#924)
Browse files Browse the repository at this point in the history
  • Loading branch information
healthjyk committed Mar 18, 2024
1 parent ad86ddd commit 564701e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 45 deletions.
60 changes: 34 additions & 26 deletions pkg/engine/state/storages/mysql.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package storages

import (
"errors"

"gopkg.in/yaml.v3"
"gorm.io/gorm"

Expand All @@ -23,95 +25,101 @@ func NewMysqlStorage(db *gorm.DB, project, stack, workspace string) *MysqlStorag
}

func (s *MysqlStorage) Get() (*v1.State, error) {
stateDO, err := getState(s.db, s.project, s.stack, s.workspace)
stateDO, err := getStateFromMysql(s.db, s.project, s.stack, s.workspace)
if err != nil {
return nil, err
}
if stateDO == nil {
return nil, nil
}
return convertFromDO(stateDO)
return convertFromMysqlDO(stateDO)
}

func (s *MysqlStorage) Apply(state *v1.State) error {
exist, err := isStateExist(s.db, s.project, s.stack, s.workspace)
exist, err := checkStateExistenceInMysql(s.db, s.project, s.stack, s.workspace)
if err != nil {
return err
}

stateDO, err := convertToDO(state)
stateDO, err := convertToMysqlDO(state)
if err != nil {
return err
}
if exist {
return updateState(s.db, stateDO)
return updateStateInMysql(s.db, stateDO)
} else {
return createState(s.db, stateDO)
return createStateInMysql(s.db, stateDO)
}
}

// State is the data object stored in the mysql db.
type State struct {
// StateMysqlDO is the data object stored in the mysql db.
type StateMysqlDO struct {
Project string
Stack string
Workspace string
Content string
}

func (s State) TableName() string {
func (s StateMysqlDO) TableName() string {
return stateTable
}

func getState(db *gorm.DB, project, stack, workspace string) (*State, error) {
q := &State{
func getStateFromMysql(db *gorm.DB, project, stack, workspace string) (*StateMysqlDO, error) {
q := &StateMysqlDO{
Project: project,
Stack: stack,
Workspace: workspace,
}
s := &State{}
s := &StateMysqlDO{}
result := db.Where(q).First(s)
// if no record, return nil
if *s == (State{}) {
s = nil
// if no record, return nil state and nil error
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return s, result.Error
}

func isStateExist(db *gorm.DB, project, stack, workspace string) (bool, error) {
s, err := getState(db, project, stack, workspace)
if err != nil {
return false, err
func checkStateExistenceInMysql(db *gorm.DB, project, stack, workspace string) (bool, error) {
q := &StateMysqlDO{
Project: project,
Stack: stack,
Workspace: workspace,
}
s := &StateMysqlDO{}
result := db.Select("project").Where(q).First(s)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false, nil
}
return s != nil, err
return result.Error == nil, result.Error
}

func createState(db *gorm.DB, s *State) error {
func createStateInMysql(db *gorm.DB, s *StateMysqlDO) error {
return db.Create(s).Error
}

func updateState(db *gorm.DB, s *State) error {
q := &State{
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
}

func convertToDO(state *v1.State) (*State, error) {
func convertToMysqlDO(state *v1.State) (*StateMysqlDO, error) {
content, err := yaml.Marshal(state)
if err != nil {
return nil, err
}
return &State{
return &StateMysqlDO{
Project: state.Project,
Stack: state.Stack,
Workspace: state.Workspace,
Content: string(content),
}, nil
}

func convertFromDO(s *State) (*v1.State, error) {
func convertFromMysqlDO(s *StateMysqlDO) (*v1.State, error) {
state := &v1.State{}
if err := yaml.Unmarshal([]byte(s.Content), state); err != nil {
return nil, err
Expand Down
21 changes: 11 additions & 10 deletions pkg/engine/state/storages/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
v1 "kusionstack.io/kusion/pkg/apis/core/v1"
)

func mockStateDO() *State {
return &State{
func mockStateMysqlDO() *StateMysqlDO {
return &StateMysqlDO{
Project: "wordpress",
Stack: "dev",
Workspace: "dev",
Expand All @@ -27,13 +27,13 @@ func TestMysqlStorage_Get(t *testing.T) {
testcases := []struct {
name string
success bool
stateDO *State
stateDO *StateMysqlDO
state *v1.State
}{
{
name: "get mysql state successfully",
success: true,
stateDO: mockStateDO(),
stateDO: mockStateMysqlDO(),
state: mockState(),
},
{
Expand All @@ -46,7 +46,7 @@ func TestMysqlStorage_Get(t *testing.T) {
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
mockey.PatchConvey("mock mysql get", t, func() {
mockey.Mock(getState).Return(tc.stateDO, nil).Build()
mockey.Mock(getStateFromMysql).Return(tc.stateDO, nil).Build()
state, err := mockMysqlStorage().Get()
assert.Equal(t, tc.success, err == nil)
assert.Equal(t, tc.state, state)
Expand All @@ -59,13 +59,13 @@ func TestMysqlStorage_Apply(t *testing.T) {
testcases := []struct {
name string
success bool
lastStateDO *State
lastStateDO *StateMysqlDO
state *v1.State
}{
{
name: "update mysql state successfully",
success: true,
lastStateDO: mockStateDO(),
lastStateDO: mockStateMysqlDO(),
state: mockState(),
},
{
Expand All @@ -78,9 +78,10 @@ func TestMysqlStorage_Apply(t *testing.T) {
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
mockey.PatchConvey("mock mysql create and update", t, func() {
mockey.Mock(getState).Return(tc.lastStateDO, nil).Build()
mockey.Mock(createState).Return(nil).Build()
mockey.Mock(updateState).Return(nil).Build()
mockey.Mock(getStateFromMysql).Return(tc.lastStateDO, nil).Build()
mockey.Mock(checkStateExistenceInMysql).Return(tc.lastStateDO != nil, nil).Build()
mockey.Mock(createStateInMysql).Return(nil).Build()
mockey.Mock(updateStateInMysql).Return(nil).Build()
err := mockMysqlStorage().Apply(tc.state)
assert.Equal(t, tc.success, err == nil)
})
Expand Down
6 changes: 1 addition & 5 deletions pkg/engine/state/storages/oss.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,5 @@ func (s *OssStorage) Apply(state *v1.State) error {
return err
}

err = s.bucket.PutObject(s.key, bytes.NewReader(content))
if err != nil {
return err
}
return nil
return s.bucket.PutObject(s.key, bytes.NewReader(content))
}
4 changes: 0 additions & 4 deletions pkg/engine/state/storages/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,10 @@ func (s *S3Storage) Get() (*v1.State, error) {
Key: &s.key,
}
output, err := s.s3.GetObject(input)
var notExist bool
if err != nil {
awsErr, ok := err.(awserr.Error)
// if no kusion state file, return nil state
if ok && awsErr.Code() == s3.ErrCodeNoSuchKey {
notExist = true
}
if notExist {
return nil, nil
}
return nil, err
Expand Down

0 comments on commit 564701e

Please sign in to comment.