Skip to content

Commit

Permalink
feat: use topological sort
Browse files Browse the repository at this point in the history
  • Loading branch information
dadav committed Sep 1, 2023
1 parent 302d2a1 commit d903908
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 26 deletions.
86 changes: 60 additions & 26 deletions cmd/helm-schema/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import (
"os"
"path/filepath"
"runtime"
"sort"
"strings"
"sync"

"github.com/dadav/helm-schema/pkg/chart"
"github.com/dadav/helm-schema/pkg/schema"
"github.com/dadav/helm-schema/pkg/util"
mapset "github.com/deckarep/golang-set/v2"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand Down Expand Up @@ -47,6 +47,53 @@ type Result struct {
Errors []error
}

// sortResults sorts the given Results via topology algorithm
// see: https://dnaeon.github.io/dependency-graph-resolution-algorithm-in-go/
func sortResults(results []*Result) ([]*Result, error) {
depNamesToResults := make(map[string]*Result)
depNamesToNames := make(map[string]mapset.Set[string])

for _, result := range results {
depNamesToResults[result.Chart.Name] = result
dependencySet := mapset.NewSet[string]()
for _, dep := range result.Chart.Dependencies {
dependencySet.Add(dep.Name)
}
depNamesToNames[result.Chart.Name] = dependencySet
}

var sorted []*Result

for len(depNamesToNames) != 0 {
readySet := mapset.NewSet[string]()
for name, deps := range depNamesToNames {
if deps.Cardinality() == 0 {
readySet.Add(name)
}
}

if readySet.Cardinality() == 0 {
var g []*Result
for name := range depNamesToNames {
g = append(g, depNamesToResults[name])
}

return g, errors.New("Circular dependency found")
}

for name := range readySet.Iter() {
delete(depNamesToNames, name)
sorted = append(sorted, depNamesToResults[name])
}

for name, deps := range depNamesToNames {
diff := deps.Difference(readySet)
depNamesToNames[name] = diff
}
}
return sorted, nil
}

func worker(
dryRun, keepFullComment bool,
valueFileNames []string,
Expand Down Expand Up @@ -141,7 +188,7 @@ func exec(cmd *cobra.Command, _ []string) error {
// 1. Start a producer that searches Chart.yaml and values.yaml files
queue := make(chan string)
resultsChan := make(chan Result)
results := []Result{}
results := []*Result{}
errs := make(chan error)
done := make(chan struct{})

Expand Down Expand Up @@ -176,39 +223,26 @@ loop:
case err := <-errs:
log.Error(err)
case res := <-resultsChan:
results = append(results, res)
results = append(results, &res)
case <-done:
break loop

}
}

// sort results with topology sort
results, err := sortResults(results)
if err != nil {
log.Errorf("Error while sorting results: %s", err)
return err
}

conditionsToPatch := make(map[string][]string)
// Sort results if dependencies should be processed
// Need to resolve the dependencies from deepest level to highest
if !noDeps {
sort.Slice(results, func(i, j int) bool {
first := results[i]
second := results[j]

// No dependencies
if len(first.Chart.Dependencies) == 0 {
return true
}
// First is dependency of second
for _, dep := range second.Chart.Dependencies {
if dep.Name != "" {
if dep.Name == first.Chart.Name {
return true
}
}
}

// first comes after second
return false
})

// Iterate over deps to find conditions we need to patch
if !noDeps {
// Iterate over deps to find conditions we need to patch (dependencies that have a condition)
for _, result := range results {
if len(result.Errors) > 0 {
continue
Expand All @@ -222,7 +256,7 @@ loop:
}
}

chartNameToResult := make(map[string]Result)
chartNameToResult := make(map[string]*Result)
foundErrors := false

// process results
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/dadav/helm-schema
go 1.21.0

require (
github.com/deckarep/golang-set/v2 v2.3.1
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/spf13/viper v1.16.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A=
github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down

0 comments on commit d903908

Please sign in to comment.