Skip to content

Commit

Permalink
Sort kubernetes objects before applying.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mplzik committed Mar 20, 2020
1 parent a3aaf4d commit ba2f62f
Showing 1 changed file with 56 additions and 14 deletions.
70 changes: 56 additions & 14 deletions pkg/kubernetes/client/apply.go
Expand Up @@ -2,23 +2,71 @@ package client

import (
"os"
"sort"
"strings"

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

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

// 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",
}

// 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
// sort the manifests into a sane install order
sort.SliceStable(data, func(i, 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 data[i].Kind() == kindOrder[io] {
break
}
}
}

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

return io < jo
})
return k.apply(data, opts)
}

Expand All @@ -40,9 +88,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))
}

0 comments on commit ba2f62f

Please sign in to comment.