mirror of https://github.com/helm/helm.git
ref(kind_sorter): use an in-place sort for sortManifestsByKind, reduce code duplication
Signed-off-by: Matthew Fisher <matt.fisher@microsoft.com>
This commit is contained in:
parent
9a2ff7802f
commit
671ceb5514
|
|
@ -103,84 +103,42 @@ var UninstallOrder KindSortOrder = []string{
|
||||||
"Namespace",
|
"Namespace",
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort manifests by kind (out of place sort)
|
// sort manifests by kind.
|
||||||
//
|
//
|
||||||
// Results are sorted by 'ordering', keeping order of items with equal kind/priority
|
// Results are sorted by 'ordering', keeping order of items with equal kind/priority
|
||||||
func manifestsSortedByKind(manifests []Manifest, ordering KindSortOrder) []Manifest {
|
func sortManifestsByKind(manifests []Manifest, ordering KindSortOrder) []Manifest {
|
||||||
k := make([]string, len(manifests))
|
sort.SliceStable(manifests, func(i, j int) bool {
|
||||||
for i, h := range manifests {
|
return lessByKind(manifests[i], manifests[j], manifests[i].Head.Kind, manifests[j].Head.Kind, ordering)
|
||||||
k[i] = h.Head.Kind
|
})
|
||||||
}
|
|
||||||
ks := newKindSorter(k, ordering)
|
|
||||||
sort.Stable(ks)
|
|
||||||
|
|
||||||
// apply permutation
|
return manifests
|
||||||
sorted := make([]Manifest, len(manifests))
|
|
||||||
for i, p := range ks.permutation {
|
|
||||||
sorted[i] = manifests[p]
|
|
||||||
}
|
|
||||||
return sorted
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort hooks by kind (out of place sort)
|
// sort hooks by kind, using an out-of-place sort to preserve the input parameters.
|
||||||
//
|
//
|
||||||
// Results are sorted by 'ordering', keeping order of items with equal kind/priority
|
// Results are sorted by 'ordering', keeping order of items with equal kind/priority
|
||||||
func hooksSortedByKind(hooks []*release.Hook, ordering KindSortOrder) []*release.Hook {
|
func sortHooksByKind(hooks []*release.Hook, ordering KindSortOrder) []*release.Hook {
|
||||||
k := make([]string, len(hooks))
|
h := hooks
|
||||||
for i, h := range hooks {
|
sort.SliceStable(h, func(i, j int) bool {
|
||||||
k[i] = h.Kind
|
return lessByKind(h[i], h[j], h[i].Kind, h[j].Kind, ordering)
|
||||||
}
|
})
|
||||||
|
|
||||||
ks := newKindSorter(k, ordering)
|
return h
|
||||||
sort.Stable(ks)
|
|
||||||
|
|
||||||
// apply permutation
|
|
||||||
sorted := make([]*release.Hook, len(hooks))
|
|
||||||
for i, p := range ks.permutation {
|
|
||||||
sorted[i] = hooks[p]
|
|
||||||
}
|
|
||||||
return sorted
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type kindSorter struct {
|
func lessByKind(a interface{}, b interface{}, kindA string, kindB string, o KindSortOrder) bool {
|
||||||
permutation []int
|
ordering := make(map[string]int, len(o))
|
||||||
ordering map[string]int
|
for v, k := range o {
|
||||||
kinds []string
|
ordering[k] = v
|
||||||
}
|
|
||||||
|
|
||||||
func newKindSorter(kinds []string, s KindSortOrder) *kindSorter {
|
|
||||||
o := make(map[string]int, len(s))
|
|
||||||
for v, k := range s {
|
|
||||||
o[k] = v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p := make([]int, len(kinds))
|
first, aok := ordering[kindA]
|
||||||
for i := range p {
|
second, bok := ordering[kindB]
|
||||||
p[i] = i
|
|
||||||
}
|
|
||||||
return &kindSorter{
|
|
||||||
permutation: p,
|
|
||||||
kinds: kinds,
|
|
||||||
ordering: o,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *kindSorter) Len() int { return len(k.kinds) }
|
|
||||||
|
|
||||||
func (k *kindSorter) Swap(i, j int) {
|
|
||||||
k.permutation[i], k.permutation[j] = k.permutation[j], k.permutation[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *kindSorter) Less(i, j int) bool {
|
|
||||||
a := k.kinds[k.permutation[i]]
|
|
||||||
b := k.kinds[k.permutation[j]]
|
|
||||||
first, aok := k.ordering[a]
|
|
||||||
second, bok := k.ordering[b]
|
|
||||||
|
|
||||||
if !aok && !bok {
|
if !aok && !bok {
|
||||||
// if both are unknown then sort alphabetically by kind, keep original order if same kind
|
// if both are unknown then sort alphabetically by kind, keep original order if same kind
|
||||||
if a != b {
|
if kindA != kindB {
|
||||||
return a < b
|
return kindA < kindB
|
||||||
}
|
}
|
||||||
return first < second
|
return first < second
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,12 +177,18 @@ func TestKindSorter(t *testing.T) {
|
||||||
t.Fatalf("Expected %d names in order, got %d", want, got)
|
t.Fatalf("Expected %d names in order, got %d", want, got)
|
||||||
}
|
}
|
||||||
defer buf.Reset()
|
defer buf.Reset()
|
||||||
for _, r := range manifestsSortedByKind(manifests, test.order) {
|
orig := manifests
|
||||||
|
for _, r := range sortManifestsByKind(manifests, test.order) {
|
||||||
buf.WriteString(r.Name)
|
buf.WriteString(r.Name)
|
||||||
}
|
}
|
||||||
if got := buf.String(); got != test.expected {
|
if got := buf.String(); got != test.expected {
|
||||||
t.Errorf("Expected %q, got %q", test.expected, got)
|
t.Errorf("Expected %q, got %q", test.expected, got)
|
||||||
}
|
}
|
||||||
|
for i, manifest := range orig {
|
||||||
|
if manifest != manifests[i] {
|
||||||
|
t.Fatal("Expected input to sortManifestsByKind to stay the same")
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +244,7 @@ func TestKindSorterKeepOriginalOrder(t *testing.T) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
t.Run(test.description, func(t *testing.T) {
|
t.Run(test.description, func(t *testing.T) {
|
||||||
defer buf.Reset()
|
defer buf.Reset()
|
||||||
for _, r := range manifestsSortedByKind(manifests, test.order) {
|
for _, r := range sortManifestsByKind(manifests, test.order) {
|
||||||
buf.WriteString(r.Name)
|
buf.WriteString(r.Name)
|
||||||
}
|
}
|
||||||
if got := buf.String(); got != test.expected {
|
if got := buf.String(); got != test.expected {
|
||||||
|
|
@ -259,7 +265,7 @@ func TestKindSorterNamespaceAgainstUnknown(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
manifests := []Manifest{unknown, namespace}
|
manifests := []Manifest{unknown, namespace}
|
||||||
manifests = manifestsSortedByKind(manifests, InstallOrder)
|
manifests = sortManifestsByKind(manifests, InstallOrder)
|
||||||
|
|
||||||
expectedOrder := []Manifest{namespace, unknown}
|
expectedOrder := []Manifest{namespace, unknown}
|
||||||
for i, manifest := range manifests {
|
for i, manifest := range manifests {
|
||||||
|
|
@ -269,7 +275,7 @@ func TestKindSorterNamespaceAgainstUnknown(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test hook sorting with a small subset of kinds, since it uses the same algorithm as manifestsSortedByKind
|
// test hook sorting with a small subset of kinds, since it uses the same algorithm as sortManifestsByKind
|
||||||
func TestKindSorterForHooks(t *testing.T) {
|
func TestKindSorterForHooks(t *testing.T) {
|
||||||
hooks := []*release.Hook{
|
hooks := []*release.Hook{
|
||||||
{
|
{
|
||||||
|
|
@ -304,9 +310,15 @@ func TestKindSorterForHooks(t *testing.T) {
|
||||||
t.Fatalf("Expected %d names in order, got %d", want, got)
|
t.Fatalf("Expected %d names in order, got %d", want, got)
|
||||||
}
|
}
|
||||||
defer buf.Reset()
|
defer buf.Reset()
|
||||||
for _, r := range hooksSortedByKind(hooks, test.order) {
|
orig := hooks
|
||||||
|
for _, r := range sortHooksByKind(hooks, test.order) {
|
||||||
buf.WriteString(r.Name)
|
buf.WriteString(r.Name)
|
||||||
}
|
}
|
||||||
|
for i, hook := range orig {
|
||||||
|
if hook != hooks[i] {
|
||||||
|
t.Fatal("Expected input to sortHooksByKind to stay the same")
|
||||||
|
}
|
||||||
|
}
|
||||||
if got := buf.String(); got != test.expected {
|
if got := buf.String(); got != test.expected {
|
||||||
t.Errorf("Expected %q, got %q", test.expected, got)
|
t.Errorf("Expected %q, got %q", test.expected, got)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ func SortManifests(files map[string]string, apis chartutil.VersionSet, ordering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hooksSortedByKind(result.hooks, ordering), manifestsSortedByKind(result.generic, ordering), nil
|
return sortHooksByKind(result.hooks, ordering), sortManifestsByKind(result.generic, ordering), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort takes a manifestFile object which may contain multiple resource definition
|
// sort takes a manifestFile object which may contain multiple resource definition
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ metadata:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sorted = manifestsSortedByKind(sorted, InstallOrder)
|
sorted = sortManifestsByKind(sorted, InstallOrder)
|
||||||
for i, m := range generic {
|
for i, m := range generic {
|
||||||
if m.Content != sorted[i].Content {
|
if m.Content != sorted[i].Content {
|
||||||
t.Errorf("Expected %q, got %q", m.Content, sorted[i].Content)
|
t.Errorf("Expected %q, got %q", m.Content, sorted[i].Content)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue