Skip to content

Commit 468680f

Browse files
authored
Fix: deleting state failed (#178)
Signed-off-by: Daniel Hu <[email protected]>
1 parent 88383f4 commit 468680f

File tree

15 files changed

+178
-88
lines changed

15 files changed

+178
-88
lines changed

internal/pkg/configloader/config.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import (
55
"io/ioutil"
66
"runtime"
77

8-
"github.com/merico-dev/stream/internal/pkg/log"
9-
108
"gopkg.in/yaml.v3"
9+
10+
"github.com/merico-dev/stream/internal/pkg/log"
1111
)
1212

1313
var (
@@ -32,12 +32,6 @@ type Tool struct {
3232
Options map[string]interface{} `yaml:"options"`
3333
}
3434

35-
// Plugin is the struct for the plugin section of each tool of the DevStream configuration file.
36-
type Plugin struct {
37-
Kind string `mapstructure:"kind"`
38-
Version string `mapstructure:"version"`
39-
}
40-
4135
func (t *Tool) DeepCopy() *Tool {
4236
var retTool = Tool{
4337
Name: t.Name,
@@ -50,6 +44,12 @@ func (t *Tool) DeepCopy() *Tool {
5044
return &retTool
5145
}
5246

47+
// Plugin is the struct for the plugin section of each tool of the DevStream configuration file.
48+
type Plugin struct {
49+
Kind string `mapstructure:"kind"`
50+
Version string `mapstructure:"version"`
51+
}
52+
5353
// LoadConf reads an input file as a Config struct.
5454
func LoadConf(fname string) *Config {
5555
fileBytes, err := ioutil.ReadFile(fname)
@@ -59,6 +59,8 @@ func LoadConf(fname string) *Config {
5959
log.Fatal("See more help by running \"dtm help\"")
6060
}
6161

62+
log.Debugf("Config file: \n%s\n", string(fileBytes))
63+
6264
var config Config
6365
err = yaml.Unmarshal(fileBytes, &config)
6466
if err != nil {

internal/pkg/planmanager/change.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ type ChangeResult struct {
2121
Time string
2222
}
2323

24+
func (c *Change) String() string {
25+
return fmt.Sprintf("\n{\n ActionName: %s,\n Tool: {Name: %s, Plugin: {Kind: %s, Version: %s}}\n}",
26+
c.ActionName, c.Tool.Name, c.Tool.Plugin.Kind, c.Tool.Plugin.Version)
27+
}
28+
2429
func getStateKeyFromTool(t *configloader.Tool) string {
2530
return fmt.Sprintf("%s_%s", t.Name, t.Plugin.Kind)
2631
}

internal/pkg/planmanager/plan_apply.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ package planmanager
33
import (
44
"gopkg.in/yaml.v3"
55

6-
"github.com/merico-dev/stream/internal/pkg/log"
7-
86
"github.com/merico-dev/stream/internal/pkg/configloader"
7+
"github.com/merico-dev/stream/internal/pkg/log"
98
"github.com/merico-dev/stream/internal/pkg/statemanager"
109
)
1110

@@ -47,5 +46,11 @@ func NewPlan(smgr statemanager.Manager, cfg *configloader.Config) *Plan {
4746
tmpStates := smgr.GetStatesMap().DeepCopy()
4847
plan.generatePlanAccordingToConfig(tmpStates, cfg)
4948
plan.removeNoLongerNeededToolsFromPlan(tmpStates)
49+
50+
log.Debugf("Changes for the plan:")
51+
for _, c := range plan.Changes {
52+
log.Debugf(c.String())
53+
}
54+
5055
return plan
5156
}

internal/pkg/planmanager/plan_delete.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,11 @@ func NewDeletePlan(smgr statemanager.Manager, cfg *configloader.Config) *Plan {
4040
}
4141
tmpStates := smgr.GetStatesMap().DeepCopy()
4242
plan.generatePlanForDelete(tmpStates, cfg)
43+
44+
log.Debugf("Changes for the plan:")
45+
for _, c := range plan.Changes {
46+
log.Debugf(c.String())
47+
}
48+
4349
return plan
4450
}

internal/pkg/planmanager/plan_helper.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func (p *Plan) removeNoLongerNeededToolsFromPlan(statesMap *statemanager.StatesM
4343
statesMap.Range(func(key, value interface{}) bool {
4444
p.Changes = append(p.Changes, &Change{
4545
Tool: &configloader.Tool{
46-
Name: key.(string),
46+
Name: value.(*statemanager.State).Name,
4747
Plugin: value.(*statemanager.State).Plugin,
4848
Options: value.(*statemanager.State).Metadata,
4949
},

internal/pkg/planmanager/result.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ import (
1010

1111
// HandleResult is used to Write the latest StatesMap to the Backend.
1212
func (p *Plan) HandleResult(change *Change) error {
13+
log.Debugf("Start: \n%s", string(p.smgr.GetStatesMap().Format()))
14+
defer func() {
15+
log.Debugf("End:\n%s", string(p.smgr.GetStatesMap().Format()))
16+
}()
17+
1318
if !change.Result.Succeeded {
1419
log.Errorf("Plugin %s %s failed.", change.Tool.Name, change.ActionName)
1520
return fmt.Errorf("plugin %s %s failed", change.Tool.Name, change.ActionName)
1621
}
1722

1823
if change.ActionName == statemanager.ActionUninstall {
19-
p.smgr.DeleteState(getStateKeyFromTool(change.Tool))
24+
key := getStateKeyFromTool(change.Tool)
25+
log.Infof("Prepare to delete '%s' from States", key)
26+
p.smgr.DeleteState(key)
2027
log.Successf("Plugin %s uninstall done.", change.Tool.Name)
2128
return p.smgr.Write(p.smgr.GetStatesMap().Format())
2229
}

internal/pkg/pluginengine/delete.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ func Delete(fname string, continueDirectly bool) error {
3131
if err != nil {
3232
return err
3333
}
34+
3435
smgr := statemanager.NewManager(b)
3536

3637
p := planmanager.NewDeletePlan(smgr, cfg)

internal/pkg/statemanager/manager.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ func (m *manager) GetState(key string) *State {
5050
}
5151

5252
func (m *manager) AddState(state *State) {
53-
state_key := getStateKeyFromState(state)
54-
m.statesMap.Store(state_key, state)
53+
stateKey := getStateKeyFromState(state)
54+
m.statesMap.Store(stateKey, state)
5555
}
5656

5757
func (m *manager) UpdateState(state *State) {
58-
state_key := getStateKeyFromState(state)
59-
m.statesMap.Store(state_key, state)
58+
stateKey := getStateKeyFromState(state)
59+
m.statesMap.Store(stateKey, state)
6060
}
6161

6262
func (m *manager) DeleteState(key string) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package statemanager_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestPlanmanager(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Util Statemanager Suite")
13+
}
Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,74 @@
1-
package statemanager
1+
package statemanager_test
22

33
import (
44
"os"
5-
"reflect"
6-
"testing"
75

6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
88
"gopkg.in/yaml.v3"
99

1010
"github.com/merico-dev/stream/internal/pkg/backend"
1111
"github.com/merico-dev/stream/internal/pkg/backend/local"
1212
"github.com/merico-dev/stream/internal/pkg/configloader"
13+
"github.com/merico-dev/stream/internal/pkg/statemanager"
1314
)
1415

15-
var smgr Manager
16-
17-
// setup is used to initialize smgr.
18-
func setup(t *testing.T) {
19-
b, err := backend.GetBackend("local")
20-
if err != nil {
21-
t.Fatal("failed to get backend.")
22-
}
23-
24-
smgr = NewManager(b)
25-
}
26-
27-
func newState() *State {
28-
return NewState("argocd-prod", configloader.Plugin{Kind: "argocd", Version: "v0.0.1"}, nil, nil)
29-
}
30-
31-
func TestManager_State(t *testing.T) {
32-
setup(t)
33-
stateA := newState()
34-
smgr.AddState(stateA)
35-
36-
stateB := smgr.GetState("argocd-prod_argocd")
37-
38-
if !reflect.DeepEqual(stateA, stateB) {
39-
t.Errorf("expect stateB == stateA, but got stateA: %v and stateB: %v", stateA, stateB)
40-
}
41-
42-
smgr.DeleteState("argocd")
43-
if smgr.GetState("argocd") != nil {
44-
t.Error("DeleteState failed")
45-
}
46-
}
47-
48-
func TestManager_Write(t *testing.T) {
49-
setup(t)
50-
stateA := newState()
51-
smgr.AddState(stateA)
52-
if err := smgr.Write(smgr.GetStatesMap().Format()); err != nil {
53-
t.Error("Failed to Write StatesMap to disk")
54-
}
55-
}
56-
57-
func TestManager_Read(t *testing.T) {
58-
TestManager_Write(t)
59-
data, err := smgr.Read()
60-
if err != nil {
61-
t.Error(err)
62-
}
63-
64-
var oldSs = NewStatesMap()
65-
if err := yaml.Unmarshal(data, oldSs); err != nil {
66-
t.Error(err)
67-
}
68-
69-
smgr.SetStatesMap(oldSs)
70-
newSs := smgr.GetStatesMap()
71-
if !reflect.DeepEqual(smgr.GetStatesMap(), oldSs) {
72-
t.Errorf("expect old StatesMap == new StatesMap, but got oldSs: %v and newSs: %v", oldSs, newSs)
73-
}
74-
75-
teardown()
76-
}
77-
78-
func teardown() {
79-
_ = os.Remove(local.DefaultStateFile)
80-
}
16+
var _ = Describe("Statemanager", func() {
17+
var smgr statemanager.Manager
18+
19+
Context("States", func() {
20+
BeforeEach(func() {
21+
b, err := backend.GetBackend("local")
22+
Expect(err).NotTo(HaveOccurred())
23+
Expect(b).NotTo(BeNil())
24+
25+
smgr = statemanager.NewManager(b)
26+
Expect(smgr).NotTo(BeNil())
27+
})
28+
29+
It("Should get the state right", func() {
30+
stateA := statemanager.NewState("prod", configloader.Plugin{Kind: "argocd", Version: "v0.0.1"}, nil, nil)
31+
Expect(stateA).NotTo(BeNil())
32+
33+
smgr.AddState(stateA)
34+
35+
stateB := smgr.GetState("prod_argocd")
36+
Expect(stateA).To(Equal(stateB))
37+
38+
smgr.DeleteState("prod_argocd")
39+
stateC := smgr.GetState("prod_argocd")
40+
Expect(stateC).To(BeNil())
41+
})
42+
43+
It("Should Read/Write well", func() {
44+
// write
45+
stateA := statemanager.NewState("prod", configloader.Plugin{Kind: "argocd", Version: "v0.0.1"}, []string{}, map[string]interface{}{})
46+
smgr.AddState(stateA)
47+
err := smgr.Write(smgr.GetStatesMap().Format())
48+
Expect(err).NotTo(HaveOccurred())
49+
50+
// read
51+
data, err := smgr.Read()
52+
Expect(err).NotTo(HaveOccurred())
53+
Expect(len(data)).NotTo(BeZero())
54+
55+
tmpMap := make(map[string]*statemanager.State)
56+
err = yaml.Unmarshal(data, tmpMap)
57+
Expect(err).NotTo(HaveOccurred())
58+
59+
statesMap := statemanager.NewStatesMap()
60+
for k, v := range tmpMap {
61+
statesMap.Store(k, v)
62+
}
63+
64+
stateB, ok := statesMap.Load("prod_argocd")
65+
Expect(ok).To(BeTrue())
66+
Expect(*stateB.(*statemanager.State)).To(Equal(*stateA))
67+
})
68+
69+
AfterEach(func() {
70+
err := os.RemoveAll(local.DefaultStateFile)
71+
Expect(err).NotTo(HaveOccurred())
72+
})
73+
})
74+
})

0 commit comments

Comments
 (0)