Skip to content
Snippets Groups Projects
Commit bb5d9bf6 authored by Angus Lees's avatar Angus Lees Committed by GitHub
Browse files

Merge pull request #6 from anguslees/sort

Attempt to topologically sort resources before updating
parents f7cd5b14 fad478f6
No related branches found
No related tags found
No related merge requests found
......@@ -10,6 +10,8 @@ import (
"k8s.io/client-go/pkg/api/errors"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/diff"
"github.com/ksonnet/kubecfg/utils"
)
const (
......@@ -47,6 +49,8 @@ var updateCmd = &cobra.Command{
return err
}
utils.SortDepFirst(objs)
for _, obj := range objs {
desc := fmt.Sprintf("%s/%s", obj.GetKind(), fqName(obj))
glog.Info("Updating ", desc)
......
package utils
import (
"sort"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
var (
gkNamespace = unversioned.GroupKind{Group: "", Kind: "Namespace"}
gkTpr = unversioned.GroupKind{Group: "extensions", Kind: "ThirdPartyResource"}
gkStorageClass = unversioned.GroupKind{Group: "storage.k8s.io", Kind: "StorageClass"}
gkPod = unversioned.GroupKind{Group: "", Kind: "Pod"}
gkJob = unversioned.GroupKind{Group: "batch", Kind: "Job"}
gkDeployment = unversioned.GroupKind{Group: "extensions", Kind: "Deployment"}
gkDaemonSet = unversioned.GroupKind{Group: "extensions", Kind: "DaemonSet"}
gkStatefulSet = unversioned.GroupKind{Group: "apps", Kind: "StatefulSet"}
)
// These kinds all start pods.
// TODO: expand this list.
func isPodOrSimilar(gk unversioned.GroupKind) bool {
return gk == gkPod ||
gk == gkJob ||
gk == gkDeployment ||
gk == gkDaemonSet ||
gk == gkStatefulSet
}
// Arbitrary numbers used to do a simple topological sort of resources.
// TODO: expand this list.
func depTier(o *runtime.Unstructured) int {
gk := o.GroupVersionKind().GroupKind()
if gk == gkNamespace || gk == gkTpr || gk == gkStorageClass {
return 10
} else if isPodOrSimilar(gk) {
return 100
} else {
return 50
}
}
type dependentObjects []*runtime.Unstructured
func (l dependentObjects) Len() int { return len(l) }
func (l dependentObjects) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l dependentObjects) Less(i, j int) bool {
return depTier(l[i]) < depTier(l[j])
}
// SortDepFirst *best-effort* sorts the objects so that known
// dependencies appear earlier in the list. The idea is to prevent
// *some* of the "crash-restart" loops when creating inter-dependent
// resources.
func SortDepFirst(objs []*runtime.Unstructured) {
sort.Sort(dependentObjects(objs))
}
package utils
import (
"testing"
"k8s.io/client-go/pkg/runtime"
)
func newObj(apiVersion, kind string) *runtime.Unstructured {
return &runtime.Unstructured{
Object: map[string]interface{}{
"apiVersion": apiVersion,
"kind": kind,
},
}
}
func TestSort(t *testing.T) {
objs := []*runtime.Unstructured{
newObj("extensions/v1beta1", "Deployment"),
newObj("v1", "ConfigMap"),
newObj("v1", "Namespace"),
newObj("v1", "Service"),
}
SortDepFirst(objs)
if objs[0].GetKind() != "Namespace" {
t.Error("Namespace should be sorted first")
}
if objs[3].GetKind() != "Deployment" {
t.Error("Deployment should be sorted after other objects")
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment