Skip to content

Commit

Permalink
feat: ignore castware components labels for RBAC resources during Hel…
Browse files Browse the repository at this point in the history
…m upsert (#79)

* feat: ignore Castware components labels for RBAC resources during Helm upsert

---------

Co-authored-by: Narunas Kapocius <[email protected]>
  • Loading branch information
Narunas-K and Narunas Kapocius authored Sep 11, 2023
1 parent ec04738 commit 8489d83
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 58 deletions.
26 changes: 26 additions & 0 deletions helm/hook/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,38 @@ import (
var labelIgnoreResources = map[string]struct{}{
"rbac.authorization.k8s.io/v1/ClusterRole//castai-evictor": {},
"rbac.authorization.k8s.io/v1/ClusterRoleBinding//castai-evictor": {},
"rbac.authorization.k8s.io/v1/Role//castai-evictor": {},
"rbac.authorization.k8s.io/v1/RoleBinding//castai-evictor": {},

"rbac.authorization.k8s.io/v1/ClusterRole//castai-agent": {},
"rbac.authorization.k8s.io/v1/ClusterRoleBinding//castai-agent": {},
"rbac.authorization.k8s.io/v1/Role//castai-agent": {},
"rbac.authorization.k8s.io/v1/RoleBinding//castai-agent": {},

"rbac.authorization.k8s.io/v1/ClusterRole//castai-spot-handler": {},
"rbac.authorization.k8s.io/v1/ClusterRoleBinding//castai-spot-handler": {},
"rbac.authorization.k8s.io/v1/Role//castai-spot-handler": {},
"rbac.authorization.k8s.io/v1/RoleBinding//castai-spot-handler": {},

"rbac.authorization.k8s.io/v1/ClusterRole//castai-egressd": {},
"rbac.authorization.k8s.io/v1/ClusterRoleBinding//castai-egressd": {},
"rbac.authorization.k8s.io/v1/Role//castai-egressd": {},
"rbac.authorization.k8s.io/v1/RoleBinding//castai-egressd": {},

"rbac.authorization.k8s.io/v1/ClusterRole//castai-kvisor": {},
"rbac.authorization.k8s.io/v1/ClusterRoleBinding//castai-kvisor": {},
"rbac.authorization.k8s.io/v1/Role//castai-kvisor": {},
"rbac.authorization.k8s.io/v1/RoleBinding//castai-kvisor": {},

"rbac.authorization.k8s.io/v1/ClusterRole//castai-kvisor-runtime": {},
"rbac.authorization.k8s.io/v1/ClusterRoleBinding//castai-kvisor-runtime": {},
"rbac.authorization.k8s.io/v1/Role//castai-kvisor-runtime": {},
"rbac.authorization.k8s.io/v1/RoleBinding//castai-kvisor-runtime": {},

"rbac.authorization.k8s.io/v1/ClusterRole//castai-cluster-controller": {},
"rbac.authorization.k8s.io/v1/ClusterRoleBinding//castai-cluster-controller": {},
"rbac.authorization.k8s.io/v1/Role//castai-cluster-controller": {},
"rbac.authorization.k8s.io/v1/RoleBinding//castai-cluster-controller": {},
}

const (
Expand Down
160 changes: 102 additions & 58 deletions helm/hook/hook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package hook

import (
"bytes"
"fmt"
"testing"
"text/template"
"time"

"github.com/stretchr/testify/require"
Expand All @@ -12,61 +14,94 @@ import (
"github.com/castai/cluster-controller/helm/hook/mock"
)

func TestIgnoreHook(t *testing.T) {
r := require.New(t)
type componentVersions struct {
appVersion string
chartVersion string
newAppVersion string
newChartVersion string
}

oldManifests :=
`---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/instance: castai-evictor
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: castai-evictor
app.kubernetes.io/version: 0.5.1
helm.sh/chart: castai-evictor-0.10.0
name: castai-evictor
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/instance: castai-evictor
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: castai-evictor
app.kubernetes.io/version: 0.5.1
helm.sh/chart: castai-evictor-0.10.0
name: castai-evictor
namespace: castai-agent`

newManifests :=
`---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/instance: castai-evictor
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: castai-evictor
app.kubernetes.io/version: 0.6.0
helm.sh/chart: castai-evictor-0.11.0
name: castai-evictor
---
apiVersion: v1
kind: Service
type k8sObjectDetails struct {
apiVersion string
updateLabels bool
}

func renderManifestTemplate(apiVersion string, kind string, name string, appVersion string, chartVersion string) (string, error) {
vars := map[string]interface{}{
"ApiVersion": apiVersion,
"Kind": kind,
"Name": name,
"AppVersion": appVersion,
"ChartVersion": chartVersion,
}

manifestTemplate := `---
apiVersion: {{ .ApiVersion }}
kind: {{ .Kind}}
metadata:
labels:
app.kubernetes.io/instance: castai-evictor
app.kubernetes.io/instance: {{ .Name }}
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: castai-evictor
app.kubernetes.io/version: 0.6.0
helm.sh/chart: castai-evictor-0.11.0
name: castai-evictor
namespace: castai-agent`
app.kubernetes.io/name: {{ .Name }}
app.kubernetes.io/version: {{ .AppVersion }}
{{- if .ChartVersion }}
helm.sh/chart: {{ .Name }}-{{ .ChartVersion }}
{{- end }}
name: {{ .Name }}
`

tmpl, err := template.New("template").Parse(manifestTemplate)
if err != nil {
return "", fmt.Errorf("parsing manifest template: %w", err)
}

var renderedTemplate bytes.Buffer
if err := tmpl.Execute(&renderedTemplate, vars); err != nil {
return "", fmt.Errorf("rendering manifest template: %w", err)
}

return renderedTemplate.String(), nil

}

func TestIgnoreHook(t *testing.T) {
r := require.New(t)

components := map[string]componentVersions{
"castai-evictor": {"0.5.1", "0.10.0", "0.6.0", "0.11.0"},
"castai-agent": {"0.5.1", "0.10.0", "0.6.0", "0.11.0"},
"castai-spot-handler": {"0.5.1", "0.10.0", "0.6.0", "0.11.0"},
"castai-egressd": {"0.5.1", "0.10.0", "0.6.0", "0.11.0"},
"castai-kvisor": {"0.5.1", "0.10.0", "0.6.0", "0.11.0"},
"castai-kvisor-runtime": {"0.5.1", "0.10.0", "0.6.0", "0.11.0"},
"castai-cluster-controller": {"v0.37.0", "0.52.0", "v0.38.0", "0.53.0"},
}

k8sObjects := map[string]k8sObjectDetails{
"ClusterRoleBinding": {"rbac.authorization.k8s.io/v1", false},
"ClusterRole": {"rbac.authorization.k8s.io/v1", false},
"Role": {"rbac.authorization.k8s.io/v1", false},
"RoleBinding": {"rbac.authorization.k8s.io/v1", false},
"Service": {"v1", true},
}

// Generate old and new manifest strings.
var oldManifests, newManifests string
for name, c := range components {
for kind, d := range k8sObjects {
oldM, err := renderManifestTemplate(d.apiVersion, kind, name, c.appVersion, c.chartVersion)
if err != nil {
r.Error(err)
}
oldManifests += oldM

newM, err := renderManifestTemplate(d.apiVersion, kind, name, c.newAppVersion, c.newChartVersion)
if err != nil {
r.Error(err)
}
newManifests += newM
}
}

oldRelease := &release.Release{
Manifest: oldManifests,
Expand All @@ -87,17 +122,26 @@ metadata:
typed, err := cl.Build(fixedManifest, false)
r.NoError(err)

// Iterate through Helm generated k8s objects.
for _, res := range typed {
u := res.Object.(*unstructured.Unstructured)

if u.GetKind() == "Service" {
r.Equal("0.6.0", u.GetLabels()[k8sVersionLabel])
r.Equal("castai-evictor-0.11.0", u.GetLabels()[helmVersionLabel])
}

if u.GetKind() == "ClusterRoleBinding" {
r.Equal("0.5.1", u.GetLabels()[k8sVersionLabel])
r.Equal("castai-evictor-0.10.0", u.GetLabels()[helmVersionLabel])
// Assert all castai-components k8s resources pairs in one place.
for kind, d := range k8sObjects {
if u.GetKind() == kind {
if c, ok := components[u.GetName()]; ok {
// If labels should have been updated by post render hook - change them for correct assertion.
appVersion := c.appVersion
chartVersion := c.chartVersion
if d.updateLabels {
appVersion = c.newAppVersion
chartVersion = c.newChartVersion
}

r.Equal(appVersion, u.GetLabels()[k8sVersionLabel])
r.Equal(fmt.Sprintf("%s-%s", u.GetName(), chartVersion), u.GetLabels()[helmVersionLabel])
}
}
}
}

Expand Down

0 comments on commit 8489d83

Please sign in to comment.