Repository: kumahq/kuma
Pull request #1035 (2020-09-20 18:04:43)

chore(*) reuse Helm 3 KindSorter
### Summary

Reuse the KindSorter from Helm 3 and drop the duplicated code.


Patch:
diff --git a/app/kumactl/cmd/install/install_control_plane.go b/app/kumactl/cmd/install/install_control_plane.go
index a18a648d4..fb695109b 100644
--- a/app/kumactl/cmd/install/install_control_plane.go
+++ b/app/kumactl/cmd/install/install_control_plane.go
@@ -114,7 +114,10 @@ func newInstallControlPlaneCmd(pctx *kumactl_cmd.RootContext) *cobra.Command {
 				return errors.Wrap(err, "Failed to render helm template files")
 			}
 
-			sortedResources := k8s.SortResourcesByKind(renderedFiles)
+			sortedResources, err := k8s.SortResourcesByKind(renderedFiles)
+			if err != nil {
+				return errors.Wrap(err, "Failed to sort resources by kind")
+			}
 
 			singleFile := data.JoinYAML(sortedResources)
 
diff --git a/app/kumactl/cmd/install/install_ingress.go b/app/kumactl/cmd/install/install_ingress.go
index 93719e615..f2416e7ae 100644
--- a/app/kumactl/cmd/install/install_ingress.go
+++ b/app/kumactl/cmd/install/install_ingress.go
@@ -53,7 +53,10 @@ func newInstallIngressCmd() *cobra.Command {
 				return errors.Wrap(err, "Failed to render template files")
 			}
 
-			sortedResources := k8s.SortResourcesByKind(renderedFiles)
+			sortedResources, err := k8s.SortResourcesByKind(renderedFiles)
+			if err != nil {
+				return errors.Wrap(err, "Failed to sort resources by kind")
+			}
 
 			singleFile := data.JoinYAML(sortedResources)
 
diff --git a/app/kumactl/cmd/install/install_logging.go b/app/kumactl/cmd/install/install_logging.go
index d5a6a46b4..7388cbd9b 100644
--- a/app/kumactl/cmd/install/install_logging.go
+++ b/app/kumactl/cmd/install/install_logging.go
@@ -39,7 +39,10 @@ func newInstallLogging() *cobra.Command {
 				return errors.Wrap(err, "Failed to render template files")
 			}
 
-			sortedResources := k8s.SortResourcesByKind(renderedFiles)
+			sortedResources, err := k8s.SortResourcesByKind(renderedFiles)
+			if err != nil {
+				return errors.Wrap(err, "Failed to sort resources by kind")
+			}
 
 			singleFile := data.JoinYAML(sortedResources)
 
diff --git a/app/kumactl/cmd/install/install_metrics.go b/app/kumactl/cmd/install/install_metrics.go
index 86fb95b22..3b862ea28 100644
--- a/app/kumactl/cmd/install/install_metrics.go
+++ b/app/kumactl/cmd/install/install_metrics.go
@@ -74,7 +74,10 @@ func newInstallMetrics() *cobra.Command {
 				return errors.Wrap(err, "Failed to render template files")
 			}
 
-			sortedResources := k8s.SortResourcesByKind(renderedFiles)
+			sortedResources, err := k8s.SortResourcesByKind(renderedFiles)
+			if err != nil {
+				return errors.Wrap(err, "Failed to sort resources by kind")
+			}
 
 			singleFile := data.JoinYAML(sortedResources)
 
diff --git a/app/kumactl/cmd/install/install_tracing.go b/app/kumactl/cmd/install/install_tracing.go
index 97cad3699..2fb1c107f 100644
--- a/app/kumactl/cmd/install/install_tracing.go
+++ b/app/kumactl/cmd/install/install_tracing.go
@@ -38,7 +38,10 @@ func newInstallTracing() *cobra.Command {
 				return errors.Wrap(err, "Failed to render template files")
 			}
 
-			sortedResources := k8s.SortResourcesByKind(renderedFiles)
+			sortedResources, err := k8s.SortResourcesByKind(renderedFiles)
+			if err != nil {
+				return errors.Wrap(err, "Failed to sort resources by kind")
+			}
 
 			singleFile := data.JoinYAML(sortedResources)
 
diff --git a/app/kumactl/pkg/install/k8s/kind_sorter.go b/app/kumactl/pkg/install/k8s/kind_sorter.go
deleted file mode 100644
index a25f28b13..000000000
--- a/app/kumactl/pkg/install/k8s/kind_sorter.go
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-Copyright The Helm Authors.
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-    http://www.apache.org/licenses/LICENSE-2.0
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package k8s
-
-import (
-	"sort"
-
-	"k8s.io/helm/pkg/manifest"
-)
-
-// SortOrder is an ordering of Kinds.
-type SortOrder []string
-
-// InstallOrder is the order in which manifests should be installed (by Kind).
-//
-// Those occurring earlier in the list get installed before those occurring later in the list.
-var InstallOrder SortOrder = []string{
-	"Namespace",
-	"ResourceQuota",
-	"LimitRange",
-	"PodSecurityPolicy",
-	"PodDisruptionBudget",
-	"Secret",
-	"ConfigMap",
-	"StorageClass",
-	"PersistentVolume",
-	"PersistentVolumeClaim",
-	"ServiceAccount",
-	"CustomResourceDefinition",
-	"ClusterRole",
-	"ClusterRoleList",
-	"ClusterRoleBinding",
-	"ClusterRoleBindingList",
-	"Role",
-	"RoleList",
-	"RoleBinding",
-	"RoleBindingList",
-	"Service",
-	"DaemonSet",
-	"Pod",
-	"ReplicationController",
-	"ReplicaSet",
-	"Deployment",
-	"HorizontalPodAutoscaler",
-	"StatefulSet",
-	"Job",
-	"CronJob",
-	"Ingress",
-	"APIService",
-}
-
-// UninstallOrder is the order in which manifests should be uninstalled (by Kind).
-//
-// Those occurring earlier in the list get uninstalled before those occurring later in the list.
-var UninstallOrder SortOrder = []string{
-	"APIService",
-	"Ingress",
-	"Service",
-	"CronJob",
-	"Job",
-	"StatefulSet",
-	"HorizontalPodAutoscaler",
-	"Deployment",
-	"ReplicaSet",
-	"ReplicationController",
-	"Pod",
-	"DaemonSet",
-	"RoleBindingList",
-	"RoleBinding",
-	"RoleList",
-	"Role",
-	"ClusterRoleBindingList",
-	"ClusterRoleBinding",
-	"ClusterRoleList",
-	"ClusterRole",
-	"CustomResourceDefinition",
-	"ServiceAccount",
-	"PersistentVolumeClaim",
-	"PersistentVolume",
-	"StorageClass",
-	"ConfigMap",
-	"Secret",
-	"PodDisruptionBudget",
-	"PodSecurityPolicy",
-	"LimitRange",
-	"ResourceQuota",
-	"Namespace",
-}
-
-// sortByKind does an in-place sort of manifests by Kind.
-//
-// Results are sorted by 'ordering'
-
-type kindSorter struct {
-	ordering  map[string]int
-	manifests []manifest.Manifest
-}
-
-func newKindSorter(m []manifest.Manifest, s SortOrder) *kindSorter {
-	o := make(map[string]int, len(s))
-	for v, k := range s {
-		o[k] = v
-	}
-
-	return &kindSorter{
-		manifests: m,
-		ordering:  o,
-	}
-}
-
-func (k *kindSorter) Len() int { return len(k.manifests) }
-
-func (k *kindSorter) Swap(i, j int) { k.manifests[i], k.manifests[j] = k.manifests[j], k.manifests[i] }
-
-func (k *kindSorter) Less(i, j int) bool {
-	a := k.manifests[i]
-	b := k.manifests[j]
-	first, aok := k.ordering[a.Head.Kind]
-	second, bok := k.ordering[b.Head.Kind]
-
-	if !aok && !bok {
-		// if both are unknown then sort alphabetically by kind and name
-		if a.Head.Kind != b.Head.Kind {
-			return a.Head.Kind < b.Head.Kind
-		}
-		return a.Name < b.Name
-	}
-
-	// unknown kind is last
-	if !aok {
-		return false
-	}
-	if !bok {
-		return true
-	}
-
-	// if same kind sub sort alphanumeric
-	if first == second {
-		return a.Name < b.Name
-	}
-	// sort different kinds
-	return first < second
-}
-
-// SortByKind sorts manifests in InstallOrder
-func SortByKind(manifests []manifest.Manifest) []manifest.Manifest {
-	ordering := InstallOrder
-	ks := newKindSorter(manifests, ordering)
-	sort.Sort(ks)
-	return ks.manifests
-}
diff --git a/app/kumactl/pkg/install/k8s/sorter.go b/app/kumactl/pkg/install/k8s/sorter.go
index a555af65e..5a8a2e6a5 100644
--- a/app/kumactl/pkg/install/k8s/sorter.go
+++ b/app/kumactl/pkg/install/k8s/sorter.go
@@ -1,21 +1,29 @@
 package k8s
 
 import (
-	helm_manifest "k8s.io/helm/pkg/manifest"
-	helm_releaseutil "k8s.io/helm/pkg/releaseutil"
+	"helm.sh/helm/v3/pkg/chartutil"
+	"helm.sh/helm/v3/pkg/releaseutil"
 
 	"github.com/kumahq/kuma/app/kumactl/pkg/install/data"
 )
 
-func SortResourcesByKind(files []data.File) []data.File {
+func SortResourcesByKind(files []data.File) ([]data.File, error) {
 	singleFile := data.JoinYAML(files)
-	resources := helm_releaseutil.SplitManifests(string(singleFile.Data))
-	manifests := helm_manifest.SplitManifests(resources)
-	SortByKind(manifests)
+	resources := releaseutil.SplitManifests(string(singleFile.Data))
 
-	result := make([]data.File, len(manifests))
+	hooks, manifests, err := releaseutil.SortManifests(resources, chartutil.VersionSet{"v1", "v1beta1", "v1alpha1"}, releaseutil.InstallOrder)
+	if err != nil {
+		return nil, err
+	}
+
+	result := make([]data.File, len(manifests)+len(hooks))
 	for i, manifest := range manifests {
 		result[i].Data = []byte(manifest.Content)
 	}
-	return result
+
+	baseIdx := len(manifests) - 1
+	for i, hook := range hooks {
+		result[baseIdx+i].Data = []byte(hook.Manifest)
+	}
+	return result, nil
 }
diff --git a/go.mod b/go.mod
index cfd4315cd..6faa1f1da 100644
--- a/go.mod
+++ b/go.mod
@@ -51,11 +51,10 @@ require (
 	gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
 	gopkg.in/fsnotify.v1 v1.4.9 // indirect
 	gopkg.in/yaml.v2 v2.3.0
-	helm.sh/helm/v3 v3.3.1
+	helm.sh/helm/v3 v3.3.4
 	k8s.io/api v0.18.8
 	k8s.io/apimachinery v0.18.8
 	k8s.io/client-go v10.0.0+incompatible
-	k8s.io/helm v2.14.3+incompatible
 	sigs.k8s.io/controller-runtime v0.6.0
 	sigs.k8s.io/testing_frameworks v0.1.1
 )
diff --git a/go.sum b/go.sum
index 411af65f4..9cbb13f83 100644
--- a/go.sum
+++ b/go.sum
@@ -1229,8 +1229,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
-helm.sh/helm/v3 v3.3.1 h1:uc+ZUthJnWNSwqyIv1KCdQm0ewi0eAf6oRaWG2X1oo0=
-helm.sh/helm/v3 v3.3.1/go.mod h1:CyCGQa53/k1JFxXvXveGwtfJ4cuB9zkaBSGa5rnAiHU=
+helm.sh/helm/v3 v3.3.4 h1:tbad6WQVMxEw1HlVBvI2rQqOblmI5lgXOrWAMwJ198M=
+helm.sh/helm/v3 v3.3.4/go.mod h1:CyCGQa53/k1JFxXvXveGwtfJ4cuB9zkaBSGa5rnAiHU=
 honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1270,8 +1270,6 @@ k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQks
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
-k8s.io/helm v2.14.3+incompatible h1:uzotTcZXa/b2SWVoUzM1xiCXVjI38TuxMujS/1s+3Gw=
-k8s.io/helm v2.14.3+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI=
 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=


Test patch:
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml
index b90d7b444..816f2d728 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.cni-enabled.golden.yaml
@@ -8,6 +8,26 @@ metadata:
     kuma.io/system-namespace: "true"
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kuma-cni
+  namespace: kube-system
+  labels:
+
+    app: kuma-cni
+    app.kubernetes.io/name: kuma
+    app.kubernetes.io/instance: kuma
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kuma-control-plane
+  namespace: kuma-system
+  labels:
+    app.kubernetes.io/name: kuma
+    app.kubernetes.io/instance: kuma
+---
+apiVersion: v1
 kind: Secret
 type: kubernetes.io/tls
 metadata:
@@ -59,26 +79,6 @@ data:
     #
     # see conf/kuma-cp.conf.yml for available settings
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: kuma-cni
-  namespace: kube-system
-  labels:
-
-    app: kuma-cni
-    app.kubernetes.io/name: kuma
-    app.kubernetes.io/instance: kuma
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: kuma-control-plane
-  namespace: kuma-system
-  labels:
-    app.kubernetes.io/name: kuma
-    app.kubernetes.io/instance: kuma
----
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml
index 11f2bc154..fd96877d2 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml
@@ -8,6 +8,15 @@ metadata:
     kuma.io/system-namespace: "true"
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kuma-control-plane
+  namespace: kuma-system
+  labels:
+    app.kubernetes.io/name: kuma
+    app.kubernetes.io/instance: kuma
+---
+apiVersion: v1
 kind: Secret
 type: kubernetes.io/tls
 metadata:
@@ -34,15 +43,6 @@ data:
     #
     # see conf/kuma-cp.conf.yml for available settings
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: kuma-control-plane
-  namespace: kuma-system
-  labels:
-    app.kubernetes.io/name: kuma
-    app.kubernetes.io/instance: kuma
----
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml
index b7dcc7f63..8e356ba38 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.global.golden.yaml
@@ -8,6 +8,15 @@ metadata:
     kuma.io/system-namespace: "true"
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kuma-control-plane
+  namespace: kuma-system
+  labels:
+    app.kubernetes.io/name: kuma
+    app.kubernetes.io/instance: kuma
+---
+apiVersion: v1
 kind: Secret
 type: kubernetes.io/tls
 metadata:
@@ -34,15 +43,6 @@ data:
     #
     # see conf/kuma-cp.conf.yml for available settings
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: kuma-control-plane
-  namespace: kuma-system
-  labels:
-    app.kubernetes.io/name: kuma
-    app.kubernetes.io/instance: kuma
----
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml
index 853a13ac3..dfab7e034 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.overrides.golden.yaml
@@ -8,6 +8,15 @@ metadata:
     kuma.io/system-namespace: "true"
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kuma-control-plane
+  namespace: kuma
+  labels:
+    app.kubernetes.io/name: kuma
+    app.kubernetes.io/instance: kuma
+---
+apiVersion: v1
 kind: Secret
 type: kubernetes.io/tls
 metadata:
@@ -34,15 +43,6 @@ data:
     #
     # see conf/kuma-cp.conf.yml for available settings
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: kuma-control-plane
-  namespace: kuma
-  labels:
-    app.kubernetes.io/name: kuma
-    app.kubernetes.io/instance: kuma
----
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.remote.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.remote.golden.yaml
index 913cb1fd8..329add995 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.remote.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.remote.golden.yaml
@@ -8,6 +8,15 @@ metadata:
     kuma.io/system-namespace: "true"
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: kuma-control-plane
+  namespace: kuma-system
+  labels:
+    app.kubernetes.io/name: kuma
+    app.kubernetes.io/instance: kuma
+---
+apiVersion: v1
 kind: Secret
 type: kubernetes.io/tls
 metadata:
@@ -34,15 +43,6 @@ data:
     #
     # see conf/kuma-cp.conf.yml for available settings
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  name: kuma-control-plane
-  namespace: kuma-system
-  labels:
-    app.kubernetes.io/name: kuma
-    app.kubernetes.io/instance: kuma
----
 apiVersion: apiextensions.k8s.io/v1beta1
 kind: CustomResourceDefinition
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-logging.defaults.golden.yaml b/app/kumactl/cmd/install/testdata/install-logging.defaults.golden.yaml
index 708fc6efe..dc5c9fdb0 100644
--- a/app/kumactl/cmd/install/testdata/install-logging.defaults.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-logging.defaults.golden.yaml
@@ -78,6 +78,26 @@ spec:
     - ALL
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: loki
+    release: loki
+  annotations:
+    {}
+  name: loki
+  namespace: kuma-logging
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: promtail
+    release: loki
+  name: loki-promtail
+  namespace: kuma-logging
+---
+apiVersion: v1
 kind: Secret
 metadata:
   name: loki
@@ -361,26 +381,6 @@ data:
         - __meta_kubernetes_pod_container_name
         target_label: __path__
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    app: loki
-    release: loki
-  annotations:
-    {}
-  name: loki
-  namespace: kuma-logging
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    app: promtail
-    release: loki
-  name: loki-promtail
-  namespace: kuma-logging
----
 kind: ClusterRole
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-logging.overrides.golden.yaml b/app/kumactl/cmd/install/testdata/install-logging.overrides.golden.yaml
index f369ade4c..bb168a7df 100644
--- a/app/kumactl/cmd/install/testdata/install-logging.overrides.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-logging.overrides.golden.yaml
@@ -78,6 +78,26 @@ spec:
     - ALL
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: loki
+    release: loki
+  annotations:
+    {}
+  name: loki
+  namespace: kuma
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: promtail
+    release: loki
+  name: loki-promtail
+  namespace: kuma
+---
+apiVersion: v1
 kind: Secret
 metadata:
   name: loki
@@ -361,26 +381,6 @@ data:
         - __meta_kubernetes_pod_container_name
         target_label: __path__
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    app: loki
-    release: loki
-  annotations:
-    {}
-  name: loki
-  namespace: kuma
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    app: promtail
-    release: loki
-  name: loki-promtail
-  namespace: kuma
----
 kind: ClusterRole
 apiVersion: rbac.authorization.k8s.io/v1
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-metrics.defaults.golden.yaml b/app/kumactl/cmd/install/testdata/install-metrics.defaults.golden.yaml
index 4263946ef..02f276e14 100644
--- a/app/kumactl/cmd/install/testdata/install-metrics.defaults.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-metrics.defaults.golden.yaml
@@ -57,6 +57,59 @@ spec:
   readOnlyRootFilesystem: false
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "alertmanager"
+    app: prometheus
+  name: prometheus-alertmanager
+  namespace: kuma-metrics
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "kube-state-metrics"
+    app: prometheus
+  name: prometheus-kube-state-metrics
+  namespace: kuma-metrics
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "node-exporter"
+    app: prometheus
+  name: prometheus-node-exporter
+  namespace: kuma-metrics
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "pushgateway"
+    app: prometheus
+  name: prometheus-pushgateway
+  namespace: kuma-metrics
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "server"
+    app: prometheus
+  name: prometheus-server
+  namespace: kuma-metrics
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: grafana
+  name: grafana
+  namespace: kuma-metrics
+---
+apiVersion: v1
 kind: ConfigMap
 metadata:
   name: grafana
@@ -8345,59 +8398,6 @@ spec:
     requests:
       storage: "8Gi"
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "alertmanager"
-    app: prometheus
-  name: prometheus-alertmanager
-  namespace: kuma-metrics
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "kube-state-metrics"
-    app: prometheus
-  name: prometheus-kube-state-metrics
-  namespace: kuma-metrics
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "node-exporter"
-    app: prometheus
-  name: prometheus-node-exporter
-  namespace: kuma-metrics
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "pushgateway"
-    app: prometheus
-  name: prometheus-pushgateway
-  namespace: kuma-metrics
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "server"
-    app: prometheus
-  name: prometheus-server
-  namespace: kuma-metrics
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    app: grafana
-  name: grafana
-  namespace: kuma-metrics
----
 apiVersion: rbac.authorization.k8s.io/v1beta1
 kind: ClusterRole
 metadata:
diff --git a/app/kumactl/cmd/install/testdata/install-metrics.overrides.golden.yaml b/app/kumactl/cmd/install/testdata/install-metrics.overrides.golden.yaml
index 4503e34d9..729081613 100644
--- a/app/kumactl/cmd/install/testdata/install-metrics.overrides.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-metrics.overrides.golden.yaml
@@ -57,6 +57,59 @@ spec:
   readOnlyRootFilesystem: false
 ---
 apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "alertmanager"
+    app: prometheus
+  name: prometheus-alertmanager
+  namespace: kuma
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "kube-state-metrics"
+    app: prometheus
+  name: prometheus-kube-state-metrics
+  namespace: kuma
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "node-exporter"
+    app: prometheus
+  name: prometheus-node-exporter
+  namespace: kuma
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "pushgateway"
+    app: prometheus
+  name: prometheus-pushgateway
+  namespace: kuma
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    component: "server"
+    app: prometheus
+  name: prometheus-server
+  namespace: kuma
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: grafana
+  name: grafana
+  namespace: kuma
+---
+apiVersion: v1
 kind: ConfigMap
 metadata:
   name: grafana
@@ -8345,59 +8398,6 @@ spec:
     requests:
       storage: "8Gi"
 ---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "alertmanager"
-    app: prometheus
-  name: prometheus-alertmanager
-  namespace: kuma
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "kube-state-metrics"
-    app: prometheus
-  name: prometheus-kube-state-metrics
-  namespace: kuma
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "node-exporter"
-    app: prometheus
-  name: prometheus-node-exporter
-  namespace: kuma
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "pushgateway"
-    app: prometheus
-  name: prometheus-pushgateway
-  namespace: kuma
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    component: "server"
-    app: prometheus
-  name: prometheus-server
-  namespace: kuma
----
-apiVersion: v1
-kind: ServiceAccount
-metadata:
-  labels:
-    app: grafana
-  name: grafana
-  namespace: kuma
----
 apiVersion: rbac.authorization.k8s.io/v1beta1
 kind: ClusterRole
 metadata: