add support for weighted manifests

Signed-off-by: Chris Randles <randles.chris@gmail.com>
pull/12541/head
Chris Randles 8 months ago
parent f3099cdb67
commit c8d3349c7b

@ -18,6 +18,7 @@ package releaseutil
import (
"sort"
"strconv"
"helm.sh/helm/v3/pkg/release"
)
@ -109,11 +110,40 @@ var UninstallOrder KindSortOrder = []string{
"PriorityClass",
}
// OrderWeightAnnotation is the label name for configuring the sorted weight of a manifest
const OrderWeightAnnotation = "helm.sh/order-weight"
// sort manifests by kind.
//
// Results are sorted by 'ordering', keeping order of items with equal kind/priority
//
// If a manifest defines a `helm.sh/order-weight` annotation, its value is used in addition to the kind's priority value.
func sortManifestsByKind(manifests []Manifest, ordering KindSortOrder) []Manifest {
sort.SliceStable(manifests, func(i, j int) bool {
var err error
iPriority := 0
if metadata := manifests[i].Head.Metadata; metadata != nil {
iPriority, err = strconv.Atoi(metadata.Annotations[OrderWeightAnnotation])
if err != nil {
iPriority = 0
}
}
jPriority := 0
if metadata := manifests[j].Head.Metadata; metadata != nil {
jPriority, err = strconv.Atoi(metadata.Annotations[OrderWeightAnnotation])
if err != nil {
jPriority = 0
}
}
if iPriority < jPriority {
return true
} else if iPriority > jPriority {
return false
}
// if the resolved priorities match, default to the legacy lessByKind logic for final sorting
return lessByKind(manifests[i], manifests[j], manifests[i].Head.Kind, manifests[j].Head.Kind, ordering)
})

@ -18,9 +18,11 @@ package releaseutil
import (
"bytes"
"fmt"
"testing"
"helm.sh/helm/v3/pkg/release"
"sigs.k8s.io/yaml"
)
func TestKindSorter(t *testing.T) {
@ -287,6 +289,102 @@ func TestKindSorterNamespaceAgainstUnknown(t *testing.T) {
}
}
func TestKindSorterOrderWeight(t *testing.T) {
for _, test := range []struct {
description string
input string
expected []string
}{
{
description: "no weights",
input: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: a
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: b
`,
expected: []string{"rbac.authorization.k8s.io/v1:ClusterRole:a", "rbac.authorization.k8s.io/v1:ClusterRole:b"},
},
{
description: "one weighted object",
input: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: a
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: b
annotations:
"helm.sh/order-weight": 1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: c
`,
expected: []string{"rbac.authorization.k8s.io/v1:ClusterRole:a", "rbac.authorization.k8s.io/v1:ClusterRole:c", "rbac.authorization.k8s.io/v1:ClusterRole:b"},
},
{
description: "negative weight",
input: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: a
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: b
annotations:
"helm.sh/order-weight": -1
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: c
`,
expected: []string{"rbac.authorization.k8s.io/v1:ClusterRole:b", "rbac.authorization.k8s.io/v1:ClusterRole:a", "rbac.authorization.k8s.io/v1:ClusterRole:c"},
},
} {
t.Run(test.description, func(t *testing.T) {
objects := SplitManifests(test.input)
manifests := []Manifest{}
for _, m := range objects {
var sh SimpleHead
if err := yaml.Unmarshal([]byte(m), &sh); err != nil {
t.Log(err)
continue
}
name := sh.Metadata.Name
content := m
manifests = append(manifests, Manifest{Name: name, Content: content, Head: &sh})
}
manifests = sortManifestsByKind(manifests, InstallOrder)
if got := len(manifests); got != len(test.expected) {
t.Errorf("Expected %d, got %d", len(test.expected), got)
} else {
for i, manifest := range manifests {
got := fmt.Sprintf("%s:%s:%s", manifest.Head.Version, manifest.Head.Kind, manifest.Name)
if test.expected[i] != got {
t.Errorf("Expected %s, got %s", test.expected[i], got)
}
}
}
})
}
}
// test hook sorting with a small subset of kinds, since it uses the same algorithm as sortManifestsByKind
func TestKindSorterForHooks(t *testing.T) {
hooks := []*release.Hook{

Loading…
Cancel
Save