Skip to content

Commit baaf73e

Browse files
michaeljguarinotest
andauthored
Use polly's topsort implementation (#253)
* Use polly's topsort implementation don't use the legacy toposort which is better designed and more modern * fix broken test * use FilterMap where appropriate Co-authored-by: test <test@plural.com>
1 parent 98c6e0f commit baaf73e

14 files changed

Lines changed: 130 additions & 349 deletions

File tree

cmd/plural/api.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package main
33
import (
44
"github.com/pluralsh/plural/pkg/api"
55
"github.com/pluralsh/plural/pkg/utils"
6-
"github.com/pluralsh/plural/pkg/utils/containers"
6+
"github.com/pluralsh/polly/algorithms"
77
"github.com/urfave/cli"
88
)
99

@@ -81,7 +81,7 @@ func (p *Plural) handleInstallations(c *cli.Context) error {
8181
return err
8282
}
8383

84-
installations = containers.Filter(installations, func(v *api.Installation) bool {
84+
installations = algorithms.Filter(installations, func(v *api.Installation) bool {
8585
return v.Repository != nil
8686
})
8787

@@ -143,7 +143,7 @@ func (p *Plural) handleChartInstallations(c *cli.Context) error {
143143
return err
144144
}
145145

146-
cis := containers.Filter(chartInstallations, func(ci *api.ChartInstallation) bool {
146+
cis := algorithms.Filter(chartInstallations, func(ci *api.ChartInstallation) bool {
147147
return ci.Chart != nil && ci.Version != nil
148148
})
149149

@@ -161,7 +161,7 @@ func (p *Plural) handleTerraformInstallations(c *cli.Context) error {
161161
return err
162162
}
163163

164-
tis := containers.Filter(terraformInstallations, func(ti *api.TerraformInstallation) bool {
164+
tis := algorithms.Filter(terraformInstallations, func(ti *api.TerraformInstallation) bool {
165165
return ti != nil
166166
})
167167

cmd/plural/dependencies_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ func TestTopSort(t *testing.T) {
2424
{
2525
name: `test "topsort"`,
2626
args: []string{plural.ApplicationName, "topsort"},
27-
installations: []*api.Installation{{
28-
Id: "abc",
29-
Repository: &api.Repository{
30-
Id: "abc",
31-
Name: "abc",
27+
installations: []*api.Installation{
28+
{
29+
Id: "abc",
30+
Repository: &api.Repository{
31+
Id: "abc",
32+
Name: "abc",
33+
},
3234
},
33-
},
3435
{
3536
Id: "cde",
3637
Repository: &api.Repository{
@@ -54,7 +55,6 @@ func TestTopSort(t *testing.T) {
5455
os.Args = test.args
5556
res, err := captureStdout(app, os.Args)
5657
assert.NoError(t, err)
57-
5858
assert.Equal(t, test.expectedResponse, res)
5959
})
6060
}

cmd/plural/deploy.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919
"github.com/pluralsh/plural/pkg/utils/git"
2020
"github.com/pluralsh/plural/pkg/utils/pathing"
2121
"github.com/pluralsh/plural/pkg/wkspace"
22+
"github.com/pluralsh/polly/algorithms"
23+
"github.com/pluralsh/polly/containers"
2224
"github.com/urfave/cli"
2325
)
2426

@@ -63,19 +65,8 @@ func getSortedNames(filter bool) ([]string, error) {
6365
}
6466

6567
if filter {
66-
result := make([]string, 0)
67-
isRepo := map[string]bool{}
68-
for _, repo := range diffed {
69-
isRepo[repo] = true
70-
}
71-
72-
for _, repo := range sorted {
73-
if isRepo[repo] {
74-
result = append(result, repo)
75-
}
76-
}
77-
78-
return result, nil
68+
repos := containers.ToSet(diffed)
69+
return algorithms.Filter(sorted, repos.Has), nil
7970
}
8071

8172
return sorted, nil

cmd/plural/deploy_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ func TestValidate(t *testing.T) {
152152
os.Args = test.args
153153
resp, err := captureStdout(app, os.Args)
154154
assert.NoError(t, err)
155-
assert.Equal(t, resp, test.expectedResponse)
155+
assert.Equal(t, test.expectedResponse, resp)
156156
})
157157
}
158158
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ require (
4040
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
4141
github.com/pluralsh/gqlclient v1.1.11
4242
github.com/pluralsh/plural-operator v0.5.3
43+
github.com/pluralsh/polly v0.0.3
4344
github.com/rodaine/hclencoder v0.0.1
4445
github.com/thoas/go-funk v0.9.2
4546
github.com/urfave/cli v1.22.10
@@ -89,8 +90,10 @@ require (
8990
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
9091
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
9192
github.com/pluralsh/controller-reconcile-helper v0.0.4 // indirect
93+
github.com/samber/lo v1.33.0 // indirect
9294
github.com/stretchr/objx v0.5.0 // indirect
9395
github.com/vektah/gqlparser/v2 v2.5.0 // indirect
96+
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
9497
gopkg.in/yaml.v3 v3.0.1 // indirect
9598
)
9699

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,10 @@ github.com/pluralsh/oauth v0.9.1-0.20220520000222-d76c0e7a0db9 h1:bMkXXUksi9ym+e
935935
github.com/pluralsh/oauth v0.9.1-0.20220520000222-d76c0e7a0db9/go.mod h1:aTUw/75rzcsbvW+/TLvWtHVDXFIdtFrDtUncOq9vHyM=
936936
github.com/pluralsh/plural-operator v0.5.3 h1:GaPL3LgimfzKZNHt7zXzqYZpb0hgyW9noHYnkA+rqNs=
937937
github.com/pluralsh/plural-operator v0.5.3/go.mod h1:WIXiz26/WDcUn0FA7Q1jPxmfsm98U1/JL8YpIdKVLX0=
938+
github.com/pluralsh/polly v0.0.2 h1:KBfpxlo6ssI2Ha1Iu6hWVY8Pt3v1Po/ixwwE788QUnY=
939+
github.com/pluralsh/polly v0.0.2/go.mod h1:GX6PeRDTRBLXNq3AgXfgJUEtfDssB7bm/JUjxDnjQ1U=
940+
github.com/pluralsh/polly v0.0.3 h1:0wN7MXGyDKCoZepO2+ryIb5T4a01IQd0r9IGDf6bo90=
941+
github.com/pluralsh/polly v0.0.3/go.mod h1:GX6PeRDTRBLXNq3AgXfgJUEtfDssB7bm/JUjxDnjQ1U=
938942
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
939943
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
940944
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -994,6 +998,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
994998
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
995999
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
9961000
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
1001+
github.com/samber/lo v1.33.0 h1:2aKucr+rQV6gHpY3bpeZu69uYoQOzVhGT3J22Op6Cjk=
1002+
github.com/samber/lo v1.33.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8=
9971003
github.com/schollz/progressbar/v3 v3.8.6 h1:QruMUdzZ1TbEP++S1m73OqRJk20ON11m6Wqv4EoGg8c=
9981004
github.com/schollz/progressbar/v3 v3.8.6/go.mod h1:W5IEwbJecncFGBvuEh4A7HT1nZZ6WNIL2i3qbnI0WKY=
9991005
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@@ -1198,6 +1204,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
11981204
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
11991205
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
12001206
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
1207+
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
1208+
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
12011209
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
12021210
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
12031211
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=

pkg/diff/builder.go

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"github.com/pluralsh/plural/pkg/utils"
1212
"github.com/pluralsh/plural/pkg/utils/git"
1313
"github.com/pluralsh/plural/pkg/utils/pathing"
14+
"github.com/pluralsh/polly/algorithms"
15+
"github.com/pluralsh/polly/containers"
1416
"github.com/rodaine/hclencoder"
1517
)
1618

@@ -93,41 +95,8 @@ func (e *Diff) IgnoreFile(root string) ([]string, error) {
9395
}
9496

9597
func DefaultDiff(path string, prev *Diff) (e *Diff) {
96-
byName := make(map[string]*executor.Step)
97-
steps := []*executor.Step{
98-
{
99-
Name: "terraform-init",
100-
Wkdir: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
101-
Target: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
102-
Command: "terraform",
103-
Args: []string{"init"},
104-
Sha: "",
105-
},
106-
{
107-
Name: "terraform",
108-
Wkdir: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
109-
Target: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
110-
Command: "plural",
111-
Args: []string{"wkspace", "terraform-diff", path},
112-
Sha: "",
113-
},
114-
{
115-
Name: "kube-init",
116-
Wkdir: path,
117-
Target: pluralfile(path, "NONCE"),
118-
Command: "plural",
119-
Args: []string{"wkspace", "kube-init", path},
120-
Sha: "",
121-
},
122-
{
123-
Name: "helm",
124-
Wkdir: pathing.SanitizeFilepath(filepath.Join(path, "helm")),
125-
Target: pathing.SanitizeFilepath(filepath.Join(path, "helm")),
126-
Command: "plural",
127-
Args: []string{"wkspace", "helm-diff", path},
128-
Sha: "",
129-
},
130-
}
98+
byName := map[string]*executor.Step{}
99+
steps := defaultDiff(path)
131100

132101
for _, step := range prev.Steps {
133102
byName[step.Name] = step
@@ -142,11 +111,7 @@ func DefaultDiff(path string, prev *Diff) (e *Diff) {
142111
}
143112

144113
// set up a topsort between the two orders of operations
145-
graph := utils.Graph(len(byName))
146-
for k := range byName {
147-
graph.AddNode(k)
148-
}
149-
114+
graph := containers.NewGraph[string]()
150115
for i := 0; i < len(steps)-1; i++ {
151116
graph.AddEdge(steps[i].Name, steps[i+1].Name)
152117
}
@@ -155,17 +120,8 @@ func DefaultDiff(path string, prev *Diff) (e *Diff) {
155120
graph.AddEdge(steps[i].Name, steps[i+1].Name)
156121
}
157122

158-
finalizedSteps := []*executor.Step{}
159-
sorted, ok := graph.Topsort()
160-
if !ok {
161-
panic("deployfile cycle detected")
162-
}
163-
164-
// dump the topsort to a list and use that from now on
165-
for _, name := range sorted {
166-
finalizedSteps = append(finalizedSteps, byName[name])
167-
}
168-
123+
sorted, _ := algorithms.TopsortGraph(graph)
124+
finalizedSteps := algorithms.Map(sorted, func(s string) *executor.Step { return byName[s] })
169125
return &Diff{
170126
Metadata: Metadata{Path: path, Name: "diff"},
171127
Steps: finalizedSteps,

pkg/diff/default.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package diff
2+
3+
import (
4+
"path/filepath"
5+
6+
"github.com/pluralsh/plural/pkg/executor"
7+
"github.com/pluralsh/plural/pkg/utils/pathing"
8+
)
9+
10+
func defaultDiff(path string) []*executor.Step {
11+
return []*executor.Step{
12+
{
13+
Name: "terraform-init",
14+
Wkdir: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
15+
Target: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
16+
Command: "terraform",
17+
Args: []string{"init"},
18+
Sha: "",
19+
},
20+
{
21+
Name: "terraform",
22+
Wkdir: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
23+
Target: pathing.SanitizeFilepath(filepath.Join(path, "terraform")),
24+
Command: "plural",
25+
Args: []string{"wkspace", "terraform-diff", path},
26+
Sha: "",
27+
},
28+
{
29+
Name: "kube-init",
30+
Wkdir: path,
31+
Target: pluralfile(path, "NONCE"),
32+
Command: "plural",
33+
Args: []string{"wkspace", "kube-init", path},
34+
Sha: "",
35+
},
36+
{
37+
Name: "helm",
38+
Wkdir: pathing.SanitizeFilepath(filepath.Join(path, "helm")),
39+
Target: pathing.SanitizeFilepath(filepath.Join(path, "helm")),
40+
Command: "plural",
41+
Args: []string{"wkspace", "helm-diff", path},
42+
Sha: "",
43+
},
44+
}
45+
}

pkg/executor/execution.go

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import (
77
"strings"
88

99
"github.com/hashicorp/hcl"
10-
"github.com/pluralsh/plural/pkg/utils"
1110
"github.com/pluralsh/plural/pkg/utils/git"
1211
"github.com/pluralsh/plural/pkg/utils/pathing"
12+
"github.com/pluralsh/polly/algorithms"
13+
"github.com/pluralsh/polly/containers"
1314
"github.com/rodaine/hclencoder"
1415
)
1516

@@ -118,11 +119,7 @@ func DefaultExecution(path string, prev *Execution) (e *Execution) {
118119
}
119120

120121
// set up a topsort between the two orders of operations
121-
graph := utils.Graph(len(byName))
122-
for k := range byName {
123-
graph.AddNode(k)
124-
}
125-
122+
graph := containers.NewGraph[string]()
126123
for i := 0; i < len(steps)-1; i++ {
127124
graph.AddEdge(steps[i].Name, steps[i+1].Name)
128125
}
@@ -131,17 +128,8 @@ func DefaultExecution(path string, prev *Execution) (e *Execution) {
131128
graph.AddEdge(prev.Steps[i].Name, prev.Steps[i+1].Name)
132129
}
133130

134-
finalizedSteps := []*Step{}
135-
sorted, ok := graph.Topsort()
136-
if !ok {
137-
panic("deployfile cycle detected")
138-
}
139-
140-
// dump the topsort to a list and use that from now on
141-
for _, name := range sorted {
142-
finalizedSteps = append(finalizedSteps, byName[name])
143-
}
144-
131+
sorted, _ := algorithms.TopsortGraph(graph)
132+
finalizedSteps := algorithms.Map(sorted, func(s string) *Step { return byName[s] })
145133
return &Execution{
146134
Metadata: Metadata{Path: path, Name: "deploy"},
147135
Steps: finalizedSteps,

pkg/scaffold/scaffold.go

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ import (
55
"path/filepath"
66

77
"github.com/pluralsh/plural/pkg/executor"
8-
"github.com/pluralsh/plural/pkg/utils"
98
"github.com/pluralsh/plural/pkg/utils/git"
109
"github.com/pluralsh/plural/pkg/utils/pathing"
1110
"github.com/pluralsh/plural/pkg/wkspace"
11+
"github.com/pluralsh/polly/algorithms"
12+
"github.com/pluralsh/polly/containers"
1213
"github.com/rodaine/hclencoder"
1314
)
1415

@@ -56,7 +57,6 @@ func Scaffolds(wk *wkspace.Workspace) (*Build, error) {
5657

5758
func merge(build *Build, base *Build) *Build {
5859
byName := make(map[string]*Scaffold)
59-
6060
for _, scaffold := range build.Scaffolds {
6161
byName[scaffold.Name] = scaffold
6262
}
@@ -70,12 +70,7 @@ func merge(build *Build, base *Build) *Build {
7070
// to handle helm v3 transition
7171
delete(byName, "add-repo")
7272

73-
graph := utils.Graph(len(byName))
74-
75-
for key := range byName {
76-
graph.AddNode(key)
77-
}
78-
73+
graph := containers.NewGraph[string]()
7974
for i := 0; i < len(build.Scaffolds)-1; i++ {
8075
graph.AddEdge(build.Scaffolds[i].Name, build.Scaffolds[i+1].Name)
8176
}
@@ -84,17 +79,8 @@ func merge(build *Build, base *Build) *Build {
8479
graph.AddEdge(base.Scaffolds[i].Name, base.Scaffolds[i+1].Name)
8580
}
8681

87-
sorted, ok := graph.Topsort()
88-
if !ok {
89-
panic("scaffold cycle created")
90-
}
91-
92-
scaffolds := []*Scaffold{}
93-
for _, name := range sorted {
94-
scaffolds = append(scaffolds, byName[name])
95-
}
96-
build.Scaffolds = scaffolds
97-
82+
sorted, _ := algorithms.TopsortGraph(graph)
83+
build.Scaffolds = algorithms.Map(sorted, func(n string) *Scaffold { return byName[n] })
9884
return build
9985
}
10086

0 commit comments

Comments
 (0)