Skip to content

Commit

Permalink
feat(kubernetes): sort objects (#244)
Browse files Browse the repository at this point in the history
* Sort kubernetes objects before applying.

Instead of just applying namespces before everything else, let's sort
all the objects. There's more inter-dependences between various kinds,
e.g. CRDs need to be applied before the actual custom resources,
StorageClasses before the PVCs, ... .

Signed-off-by: Milan Plzik <milan.plzik@grafana.com>

* Move object sorting to the Reconcile phase.

As suggested in
#244 (comment) ,
`Reconcile()` might be a better place for sorting, since we're already
doing sort-of (pun intended) similar thing there.

Signed-off-by: Milan Plzik <milan.plzik@grafana.com>

* Fix review comments.

Signed-off-by: Milan Plzik <milan.plzik@grafana.com>
  • Loading branch information
mplzik authored Mar 31, 2020
1 parent a3aaf4d commit 40a9e45
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 20 deletions.
20 changes: 0 additions & 20 deletions pkg/kubernetes/client/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,11 @@ import (
"os"
"strings"

funk "github.com/thoas/go-funk"

"github.com/grafana/tanka/pkg/kubernetes/manifest"
)

// Apply applies the given yaml to the cluster
func (k Kubectl) Apply(data manifest.List, opts ApplyOpts) error {
// create namespaces first to succeed first try
ns := filterNamespace(data)
if len(ns) > 0 {
if err := k.apply(ns, opts); err != nil {
return err
}
}

return k.apply(data, opts)
}

func (k Kubectl) apply(data manifest.List, opts ApplyOpts) error {
argv := []string{"-f", "-"}
if opts.Force {
argv = append(argv, "--force")
Expand All @@ -40,9 +26,3 @@ func (k Kubectl) apply(data manifest.List, opts ApplyOpts) error {

return cmd.Run()
}

func filterNamespace(in manifest.List) manifest.List {
return manifest.List(funk.Filter(in, func(i manifest.Manifest) bool {
return strings.ToLower(i.Kind()) == "namespace"
}).([]manifest.Manifest))
}
62 changes: 62 additions & 0 deletions pkg/kubernetes/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,44 @@ import (
"github.com/grafana/tanka/pkg/spec/v1alpha1"
)

// Order in which install different kinds of Kubernetes objects.
// Inspired by https://github.com/helm/helm/blob/8c84a0bc0376650bc3d7334eef0c46356c22fa36/pkg/releaseutil/kind_sorter.go
var kindOrder = []string{
"Namespace",
"NetworkPolicy",
"ResourceQuota",
"LimitRange",
"PodSecurityPolicy",
"PodDisruptionBudget",
"ServiceAccount",
"Secret",
"ConfigMap",
"StorageClass",
"PersistentVolume",
"PersistentVolumeClaim",
"CustomResourceDefinition",
"ClusterRole",
"ClusterRoleList",
"ClusterRoleBinding",
"ClusterRoleBindingList",
"Role",
"RoleList",
"RoleBinding",
"RoleBindingList",
"Service",
"DaemonSet",
"Pod",
"ReplicationController",
"ReplicaSet",
"Deployment",
"HorizontalPodAutoscaler",
"StatefulSet",
"Job",
"CronJob",
"Ingress",
"APIService",
}

// Reconcile extracts kubernetes Manifests from raw evaluated jsonnet <kind>/<name>,
// provided the manifests match the given regular expressions. It finds each manifest by
// recursively walking the jsonnet structure.
Expand Down Expand Up @@ -49,9 +87,33 @@ func Reconcile(raw map[string]interface{}, spec v1alpha1.Spec, targets []*regexp

// Stable output order
sort.SliceStable(out, func(i int, j int) bool {
var io, jo int

// anything that is not in kindOrder will get to the end of the install list.
for io = 0; io < len(kindOrder); io++ {
if out[i].Kind() == kindOrder[io] {
break
}
}

for jo = 0; jo < len(kindOrder); jo++ {
if out[j].Kind() == kindOrder[jo] {
break
}
}

// If Kind of both objects are at different indexes of kindOrder, sort by them
if io != jo {
return io < jo
}

// If the Kinds themselves are different (e.g. both of the Kinds are not in
// the kindOrder), order alphabetically.
if out[i].Kind() != out[j].Kind() {
return out[i].Kind() < out[j].Kind()
}

// Otherwise, order the objects by name.
return out[i].Metadata().Name() < out[j].Metadata().Name()
})

Expand Down

0 comments on commit 40a9e45

Please sign in to comment.