Allows ordering of Custom Resources

Signed-off-by: Niklas Wagner <n.wagner@finatix.de>
pull/9534/head
Niklas Wagner 5 years ago
parent d55c53df4e
commit 7e4bb365e6
No known key found for this signature in database
GPG Key ID: 8AED02178FD25987

@ -108,12 +108,12 @@ var UninstallOrder KindSortOrder = []string{
// sort manifests by kind.
//
// Results are sorted by 'ordering', keeping order of items with equal kind/priority
func sortManifestsByKind(manifests []Manifest, ordering KindSortOrder) []Manifest {
sort.SliceStable(manifests, func(i, j int) bool {
return lessByKind(manifests[i], manifests[j], manifests[i].Head.Kind, manifests[j].Head.Kind, ordering)
func sortManifestsByKind(m []Manifest, ordering KindSortOrder) []Manifest {
sort.SliceStable(m, func(i, j int) bool {
return lessByKind(m[i], m[j], m[i].Head.Kind, m[j].Head.Kind, m[i].InstallBefore, m[j].InstallBefore, ordering)
})
return manifests
return m
}
// sort hooks by kind, using an out-of-place sort to preserve the input parameters.
@ -122,20 +122,15 @@ func sortManifestsByKind(manifests []Manifest, ordering KindSortOrder) []Manifes
func sortHooksByKind(hooks []*release.Hook, ordering KindSortOrder) []*release.Hook {
h := hooks
sort.SliceStable(h, func(i, j int) bool {
return lessByKind(h[i], h[j], h[i].Kind, h[j].Kind, ordering)
return lessByKind(h[i], h[j], h[i].Kind, h[j].Kind, nil, nil, ordering)
})
return h
}
func lessByKind(a interface{}, b interface{}, kindA string, kindB string, o KindSortOrder) bool {
ordering := make(map[string]int, len(o))
for v, k := range o {
ordering[k] = v
}
first, aok := ordering[kindA]
second, bok := ordering[kindB]
func lessByKind(a interface{}, b interface{}, kindA string, kindB string, beforeA []string, beforeB []string, o KindSortOrder) bool {
first, aok := installOrderIndex(kindA, beforeA, o)
second, bok := installOrderIndex(kindB, beforeB, o)
if !aok && !bok {
// if both are unknown then sort alphabetically by kind, keep original order if same kind
@ -154,3 +149,28 @@ func lessByKind(a interface{}, b interface{}, kindA string, kindB string, o Kind
// sort different kinds, keep original order if same priority
return first < second
}
// installOrderIndex returns the lowest index number of all beforeKinds
func installOrderIndex(kind string, beforeKinds []string, o KindSortOrder) (int, bool) {
ordering := make(map[string]int, len(o))
for v, k := range o {
ordering[k] = v
}
orderIndex, foundIndex := ordering[kind]
// reset orderIndex for unknown resources
if !foundIndex {
orderIndex = len(o)
}
for _, kind := range beforeKinds {
i, ok := ordering[kind]
if ok && i < orderIndex {
foundIndex = true
// set orderIndex 1 BEFORE the actual index, so it get executed BEFORE it
orderIndex = i - 1
}
}
return orderIndex, foundIndex
}

@ -23,6 +23,9 @@ import (
"strings"
)
// InstallOrderAnnotation the annotation that allows manipulating the install order of custom resources
const InstallOrderAnnotation = "helm.sh/install-before"
// SimpleHead defines what the structure of the head of a manifest file
type SimpleHead struct {
Version string `json:"apiVersion"`

@ -35,6 +35,7 @@ type Manifest struct {
Name string
Content string
Head *SimpleHead
InstallBefore []string
}
// manifestFile represents a file that contains a manifest.
@ -155,6 +156,30 @@ func (file *manifestFile) sort(result *result) error {
continue
}
installBeforeKinds, ok := entry.Metadata.Annotations[InstallOrderAnnotation]
// InstallOrderAnnotation is only supported for unknown Kinds e.g. Custom Resources
if ok && isKnownKind(entry.Kind) {
log.Printf("info: %v annotation is not supported for Kind %v", InstallOrderAnnotation, entry.Kind)
} else if ok {
var installBefore []string
for _, kind := range strings.Split(installBeforeKinds, ",") {
kind = strings.TrimSpace(kind)
if isKnownKind(kind) {
installBefore = append(installBefore, kind)
} else {
log.Printf("info: skipping unknown install-before kind: %q", kind)
}
}
result.generic = append(result.generic, Manifest{
Name: file.path,
Content: m,
Head: &entry,
InstallBefore: installBefore,
})
continue
}
hookTypes, ok := entry.Metadata.Annotations[release.HookAnnotation]
if !ok {
result.generic = append(result.generic, Manifest{
@ -231,3 +256,15 @@ func operateAnnotationValues(entry SimpleHead, annotation string, operate func(p
}
}
}
// isKnownKind returns true if the given kind exists in the InstallOrder or UninstallOrder
func isKnownKind(kind string) bool {
knownKinds := append(InstallOrder, UninstallOrder...)
for _, kk := range knownKinds {
if kk == kind {
return true
}
}
return false
}

Loading…
Cancel
Save