Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hull tests for rancher-gatekeeper-crd chart #2625

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/rancher/charts/tests
go 1.19

require (
github.com/rancher/hull v0.0.0-20230329190516-51af9be6b929
github.com/rancher/hull v0.0.0-20230424152137-627ef5347afd
github.com/rancher/wrangler v1.1.1
github.com/stretchr/testify v1.8.2
k8s.io/api v0.26.2
Expand Down
4 changes: 2 additions & 2 deletions tests/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rancher/hull v0.0.0-20230329190516-51af9be6b929 h1:0tH29T8JSJzgB6gsbfkRZEtHlI7dnCIb2iaxwytpuuY=
github.com/rancher/hull v0.0.0-20230329190516-51af9be6b929/go.mod h1:zzX4GCX5B2QJT6B1cBE+JYaHRYK29eurtDZv2rNXJLU=
github.com/rancher/hull v0.0.0-20230424152137-627ef5347afd h1:IhBX+7apT16PSNV8lvu3LT6nXJ6VuxSoaP9iJ/kofbI=
github.com/rancher/hull v0.0.0-20230424152137-627ef5347afd/go.mod h1:zzX4GCX5B2QJT6B1cBE+JYaHRYK29eurtDZv2rNXJLU=
github.com/rancher/lasso v0.0.0-20221227210133-6ea88ca2fbcc h1:29VHrInLV4qSevvcvhBj5UhQWkPShxrxv4AahYg2Scw=
github.com/rancher/lasso v0.0.0-20221227210133-6ea88ca2fbcc/go.mod h1:dEfC9eFQigj95lv/JQ8K5e7+qQCacWs1aIA6nLxKzT8=
github.com/rancher/wrangler v1.1.1 h1:wmqUwqc2M7ADfXnBCJTFkTB5ZREWpD78rnZMzmxwMvM=
Expand Down
300 changes: 300 additions & 0 deletions tests/rancher-gatekeper-crd/rancher_gatekeeper_crd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
package rancher_gatekeeper_crd

import (
"github.com/rancher/charts/tests/common"
"github.com/rancher/hull/pkg/chart"
"github.com/rancher/hull/pkg/checker"
"github.com/rancher/hull/pkg/test"
"github.com/rancher/hull/pkg/utils"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
policyv1beta1 "k8s.io/api/policy/v1beta1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var ChartPath = utils.MustGetPathFromModuleRoot("../charts/rancher-gatekeeper-crd/102.0.0+up3.10.0")

const (
DefaultReleaseName = "rancher-gatekeeper-crd"
DefaultNamespace = "cattle-gatekeeper-system"
)

var suite = test.Suite{
ChartPath: ChartPath,

Cases: []test.Case{
{
Name: "Using Defaults",
TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace),
},

{
Name: "Set .Values.global.cattle.systemDefaultRegistry",
TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
SetValue(
"global.cattle.systemDefaultRegistry", "testRegistry",
),
},

{
Name: "Set .Values.tolerations",
TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set(
"tolerations", testTolerations,
),
},

{
Name: "Set .Values.nodeSelector",
TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set(
"nodeSelector", defaultNodeSelector,
),
},

{
Name: "Set .Values.global.cattle.psp.enabled to true",

TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set("global.cattle.psp.enabled", true),
},

{
Name: "Set .Values.global.cattle.psp.enabled to false",

TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set("global.cattle.psp.enabled", false),
},

{
Name: "Set .Values.image",

TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set("image", map[string]string{
"repository": "rancher/kubectl-test",
"tag": "v1.24.6",
}),
},

{
Name: "Set .Values.enableRuntimeDefaultSeccompProfile",

TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set("enableRuntimeDefaultSeccompProfile", true),
},

{
Name: "Set .Values.enableRuntimeDefaultSeccompProfile to false",

TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set("enableRuntimeDefaultSeccompProfile", false),
},

{
Name: "Set .Values.securityContext",

TemplateOptions: chart.NewTemplateOptions(DefaultReleaseName, DefaultNamespace).
Set("securityContext", testSecurityContext),
},
},

NamedChecks: []test.NamedCheck{
{
Name: "All Workloads Have Node Selectors and Tolerations",
Checks: common.AllWorkloadsHaveNodeSelectorsAndTolerationsForOS,
},

{
Name: "All Workload Container Should Have SystemDefaultRegistry",
Checks: common.AllContainerImagesShouldHaveSystemDefaultRegistryPrefix,
Covers: []string{
".Values.global.cattle.systemDefaultRegistry",
},
},

{
Name: "Check All Workload Have NodeSelector As Per Given Values",
Covers: []string{
".Values.nodeSelector",
},

Checks: test.Checks{
checker.PerWorkload(func(tc *checker.TestContext, obj metav1.Object, podTemplateSpec corev1.PodTemplateSpec) {
nodeselectorAddedByValues, _ := checker.RenderValue[map[string]string](tc, ".Values.nodeSelector")
expectedNodeSelector := map[string]string{}

for k, v := range nodeselectorAddedByValues {
expectedNodeSelector[k] = v
}

for k, v := range defaultNodeSelector {
expectedNodeSelector[k] = v
}

assert.Equal(tc.T, expectedNodeSelector, podTemplateSpec.Spec.NodeSelector,
"workload %s (type: %T) does not have correct nodeSelectors, expected: %v got: %v",
obj.GetName(), obj, expectedNodeSelector, podTemplateSpec.Spec.NodeSelector,
)
}),
},
},

{
Name: "Check All Workload Have Tolerations As Per Given Values",
Covers: []string{
".Values.tolerations",
},

Checks: test.Checks{
checker.PerWorkload(func(tc *checker.TestContext, obj metav1.Object, podTemplateSpec corev1.PodTemplateSpec) {
if obj.GetName() == "kiali" {
return
}

if obj.GetName() == "rancher-istio-tracing" {
return
}

tolerationsAddedByValues, _ := checker.RenderValue[[]corev1.Toleration](tc, ".Values.tolerations")

expectedTolerations := append(defaultTolerations, tolerationsAddedByValues...)
if len(expectedTolerations) == 0 {
expectedTolerations = nil
}

assert.Equal(tc.T, expectedTolerations, podTemplateSpec.Spec.Tolerations,
"workload %s (type: %T) does not have correct tolerations, expected: %v got: %v",
obj.GetName(), obj, expectedTolerations, podTemplateSpec.Spec.Tolerations,
)
}),
},
},

{ //Set PSPs
Name: "Set PSPs",

Covers: []string{
".Values.global.cattle.psp.enabled",
},

Checks: test.Checks{
checker.PerResource(func(tc *checker.TestContext, cr *rbacv1.ClusterRole) {
pspsEnabled, _ := checker.RenderValue[bool](tc, ".Values.global.cattle.psp.enabled")
pspsFound := false
for _, rule := range cr.Rules {
for _, resource := range rule.Resources {
if resource == "podsecuritypolicies" {
pspsFound = true
}
}
}
if !pspsEnabled {
assert.False(tc.T, pspsFound, "ClusterRole %s has incorrect PSP configuration", cr.Name)
}
}),
checker.OnResources(func(tc *checker.TestContext, psps []*policyv1beta1.PodSecurityPolicy) {
pspsEnabled, _ := checker.RenderValue[bool](tc, ".Values.global.cattle.psp.enabled")
if pspsEnabled {
assert.Equal(tc.T, 1, len(psps), "Missing PSPs")
} else {
assert.Equal(tc.T, 0, len(psps), "Missing PSPs")
}
}),
},
},

{
Name: "Check securityContext",
Covers: []string{
".Values.securityContext",
},

Checks: test.Checks{
checker.PerWorkload(func(tc *checker.TestContext, obj metav1.Object, podTemplateSpec corev1.PodTemplateSpec) {

if obj.GetName() != "rancher-gatekeeper-crd" {
return
}

securityContext, _ := checker.RenderValue[*corev1.SecurityContext](tc, ".Values.securityContext")

for _, container := range podTemplateSpec.Spec.Containers {
assert.Equal(tc.T, securityContext, container.SecurityContext,
"workload %s (type: %T) does not have correct securityContext, expected: %v got: %v",
obj.GetName(), obj, securityContext, container.SecurityContext,
)
}
}),
},
},

{
Name: "Check enableRuntimeDefaultSeccompProfile",
Covers: []string{
".Values.enableRuntimeDefaultSeccompProfile",
},

Checks: test.Checks{
checker.PerWorkload(func(tc *checker.TestContext, obj metav1.Object, podTemplateSpec corev1.PodTemplateSpec) {

if obj.GetName() != "rancher-gatekeeper-crd" {
return
}

enableRuntimeDefaultSeccompProfile, _ := checker.RenderValue[bool](tc, ".Values.enableRuntimeDefaultSeccompProfile")

for _, container := range podTemplateSpec.Spec.Containers {
assert.Equal(tc.T, enableRuntimeDefaultSeccompProfile, *container.SecurityContext.SeccompProfile,
"workload %s (type: %T) does not have correct enableRuntimeDefaultSeccompProfile, expected: %v got: %v",
obj.GetName(), obj, enableRuntimeDefaultSeccompProfile, *container.SecurityContext.SeccompProfile,
)
}

if !enableRuntimeDefaultSeccompProfile {
for _, container := range podTemplateSpec.Spec.InitContainers {
assert.Equal(tc.T, enableRuntimeDefaultSeccompProfile, *container.SecurityContext.SeccompProfile,
"workload %s (type: %T) does not have correct enableRuntimeDefaultSeccompProfile, expected: %v got: %v",
obj.GetName(), obj, enableRuntimeDefaultSeccompProfile, *container.SecurityContext.SeccompProfile,
)
}
}
}),
},
},

{
Name: "Check image and tag",
Covers: []string{
".Values.global.cattle.systemDefaultRegistry",
".Values.image.repository",
".Values.image.tag",
},

Checks: test.Checks{
checker.PerWorkload(func(tc *checker.TestContext, obj metav1.Object, podTemplateSpec corev1.PodTemplateSpec) {

if obj.GetName() != "rancher-gatekeeper-crd" {
return
}

systemDefaultRegistry, _ := checker.RenderValue[string](tc, ".Values.global.cattle.systemDefaultRegistry")
image, _ := checker.RenderValue[string](tc, ".Values.image.repository")
tag, _ := checker.RenderValue[string](tc, ".Values.image.tag")
expectedImage := image + ":" + tag

if systemDefaultRegistry != "" {
expectedImage = systemDefaultRegistry + "/" + expectedImage
}

for _, container := range podTemplateSpec.Spec.Containers {
assert.Equal(tc.T, expectedImage, container.Image,
"workload %s (type: %T) does not have correct image, expected: %v got: %v",
obj.GetName(), obj, expectedImage, container.Image,
)
}
}),
},
},
},
}
15 changes: 15 additions & 0 deletions tests/rancher-gatekeper-crd/rancher_gatekeeper_crd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package rancher_gatekeeper_crd

import (
"testing"

"github.com/rancher/hull/pkg/test"
)

func TestChart(t *testing.T) {
opts := test.GetRancherOptions()
opts.Coverage.IncludeSubcharts = false
opts.Coverage.Disabled = false
opts.YAMLLint.Enabled = false
suite.Run(t, opts)
}
48 changes: 48 additions & 0 deletions tests/rancher-gatekeper-crd/testdata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package rancher_gatekeeper_crd

import (
corev1 "k8s.io/api/core/v1"
)

// for Values.nodeSelector
var defaultNodeSelector = map[string]string{
"kubernetes.io/os": "linux",
}

// for Values.tolerations
var defaultTolerations = []corev1.Toleration{
{
Key: "cattle.io/os",
Operator: corev1.TolerationOpEqual,
Value: "linux",
Effect: corev1.TaintEffectNoSchedule,
},
}

var testTolerations = []corev1.Toleration{
{
Key: "test",
Operator: corev1.TolerationOpEqual,
Value: "test",
Effect: corev1.TaintEffectNoSchedule,
},
{
Key: "test1",
Operator: corev1.TolerationOpExists,
Value: "test1",
Effect: corev1.TaintEffectNoExecute,
},
}

var testSecurityContext = &corev1.SecurityContext{
AllowPrivilegeEscalation: func() *bool { b := true; return &b }(),
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{
"ALL",
},
},
Privileged: func() *bool { b := true; return &b }(),
ReadOnlyRootFilesystem: func() *bool { b := true; return &b }(),
RunAsNonRoot: func() *bool { b := true; return &b }(),
RunAsUser: func() *int64 { i := int64(100); return &i }(),
}