Skip to content

Commit

Permalink
Add minimal GKE Autopilot unit tests (#1717)
Browse files Browse the repository at this point in the history
* Add minimal GKE Autopilot unit tests

* Enable datadog chart unit tests in CI

* add required prometheus helm repo to gh job

* fix make target name

* assert expected volumeMounts

* fix container name
  • Loading branch information
fanny-jiang authored Feb 26, 2025
1 parent 67f2ed6 commit 19ce2bc
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 8 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/go-test-datadog.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Go Test Datadog
on:
push:
paths:
- 'test/datadog/**'
- 'charts/datadog/**'
pull_request:
paths:
- 'test/datadog/**'
- 'charts/datadog/**'

# Permission forced by repo-level setting; only elevate on job-level
permissions:
contents: read
# packages: read

env:
GO111MODULE: "on"
PROJECTNAME: "helm-charts"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@0caeaed6fd66a828038c2da3c0f662a42862658f # v1.1.3
with:
go-version: 1.21
id: go
- name: Set up Helm
uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0
with:
version: v3.14.0
- name: Add Datadog Helm repo
run: helm repo add datadog https://helm.datadoghq.com && helm repo update
- name: Add Prometheus Community Helm repo
run: helm repo add prometheus-community https://prometheus-community.github.io/helm-charts && helm repo update
- name: Check out code into the Go module directory
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1.2.0
- name: run Go tests
run: |
helm dependency build ./charts/datadog
make unit-test-datadog
File renamed without changes.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ vet:
unit-test:
go test -C test ./... -count=1

.PHONY: unit-test-datadog
unit-test-datadog:
go test -C test ./datadog -count=1

.PHONY: unit-test-operator
unit-test-operator:
go test -C test ./datadog-operator -count=1
Expand Down
18 changes: 18 additions & 0 deletions test/common/common.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package common

import (
appsv1 "k8s.io/api/apps/v1"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -99,3 +100,20 @@ func WriteToFile(t *testing.T, filepath, content string) {
err := os.WriteFile(filepath, []byte(content), 0644)
require.NoError(t, err, "can't update manifest", "path", filepath)
}

func GetVolumeNames(ds appsv1.DaemonSet) []string {
volumeNames := []string{}
for _, volume := range ds.Spec.Template.Spec.Volumes {
volumeNames = append(volumeNames, volume.Name)
}
return volumeNames
}

func Contains(str string, list []string) bool {
for _, s := range list {
if s == str {
return true
}
}
return false
}
102 changes: 102 additions & 0 deletions test/datadog/autopilot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package datadog

import (
"fmt"
"github.com/DataDog/helm-charts/test/common"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"testing"
)

var allowedAutopilotHostPaths = map[string]interface{}{
"/var/log/pods": nil,
"/var/log/containers": nil,
"/var/autopilot/addon/datadog/logs": nil,
"/var/lib/docker/containers": nil,
"/proc": nil,
"/sys/fs/cgroup": nil,
"/etc/passwd": nil,
"/var/run/containerd": nil,
}

func Test_autopilotConfigs(t *testing.T) {
tests := []struct {
name string
command common.HelmCommand
assertions func(t *testing.T, manifest string)
}{
{
name: "default",
command: common.HelmCommand{
ReleaseName: "datadog",
ChartPath: "../../charts/datadog",
ShowOnly: []string{"templates/daemonset.yaml"},
Values: []string{"../../charts/datadog/values.yaml"},
Overrides: map[string]string{
"datadog.apiKeyExistingSecret": "datadog-secret",
"datadog.appKeyExistingSecret": "datadog-secret",
"providers.gke.autopilot": "true",
},
},
assertions: verifyDaemonsetAutopilotMinimal,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
manifest, err := common.RenderChart(t, tt.command)
assert.Nil(t, err, "couldn't render template")
tt.assertions(t, manifest)
})
}
}

func verifyDaemonsetAutopilotMinimal(t *testing.T, manifest string) {
var ds appsv1.DaemonSet
common.Unmarshal(t, manifest, &ds)
agentContainer := &corev1.Container{}
processAgentContainer := &corev1.Container{}

assert.Equal(t, 2, len(ds.Spec.Template.Spec.Containers))

for _, container := range ds.Spec.Template.Spec.Containers {
if container.Name == "agent" {
agentContainer = &container
} else if container.Name == "process-agent" {
processAgentContainer = &container
}
}

assert.NotNil(t, agentContainer)
assert.NotNil(t, processAgentContainer)

var validHostPath = true
for _, volume := range ds.Spec.Template.Spec.Volumes {
if volume.HostPath != nil {
_, validHostPath = allowedAutopilotHostPaths[volume.HostPath.Path]
assert.True(t, validHostPath, fmt.Sprintf("DaemonSet has restricted hostPath mounted: %s ", volume.HostPath.Path))
}
}

volumeNames := common.GetVolumeNames(ds)
for _, container := range ds.Spec.Template.Spec.Containers {
for _, volumeMount := range container.VolumeMounts {
assert.True(t, common.Contains(volumeMount.Name, volumeNames),
fmt.Sprintf("Found unexpected volumeMount `%s` in container `%s`", volumeMount.Name, container.Name))
}
}

validPorts := true
for _, container := range ds.Spec.Template.Spec.Containers {
if container.Ports != nil {
for _, port := range container.Ports {
if port.HostPort > 0 {
validPorts = false
break
}
}
}
}
assert.True(t, validPorts, "Daemonset has restricted hostPort mounted.")
}
8 changes: 8 additions & 0 deletions test/datadog/gdc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ func verifyDaemonsetGDCMinimal(t *testing.T, manifest string) {
}
}

volumeNames := common.GetVolumeNames(ds)
for _, container := range ds.Spec.Template.Spec.Containers {
for _, volumeMount := range container.VolumeMounts {
assert.True(t, common.Contains(volumeMount.Name, volumeNames),
fmt.Sprintf("Found unexpected volumeMount `%s` in container `%s`", volumeMount.Name, container.Name))
}
}

validPorts := true
for _, container := range ds.Spec.Template.Spec.Containers {
if container.Ports != nil {
Expand Down
16 changes: 8 additions & 8 deletions test/datadog/process_agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ func Test_processAgentConfigs(t *testing.T) {
ShowOnly: []string{"templates/daemonset.yaml"},
Values: []string{"../../charts/datadog/values.yaml"},
Overrides: map[string]string{
"datadog.apiKeyExistingSecret": "datadog-secret",
"datadog.appKeyExistingSecret": "datadog-secret",
"datadog.processAgent.runInCoreAgent": "true",
"agents.image.tag": "7.52.0",
"datadog.apiKeyExistingSecret": "datadog-secret",
"datadog.appKeyExistingSecret": "datadog-secret",
"datadog.processAgent.runInCoreAgent": "true",
"agents.image.tag": "7.52.0",
},
},
assertions: verifyLinuxRunInCoreAgentOld,
Expand All @@ -195,10 +195,10 @@ func Test_processAgentConfigs(t *testing.T) {
ShowOnly: []string{"templates/daemonset.yaml"},
Values: []string{"../../charts/datadog/values.yaml"},
Overrides: map[string]string{
"datadog.apiKeyExistingSecret": "datadog-secret",
"datadog.appKeyExistingSecret": "datadog-secret",
"datadog.processAgent.runInCoreAgent": "true",
"agents.image.doNotCheckTag": "true",
"datadog.apiKeyExistingSecret": "datadog-secret",
"datadog.appKeyExistingSecret": "datadog-secret",
"datadog.processAgent.runInCoreAgent": "true",
"agents.image.doNotCheckTag": "true",
},
},
assertions: verifyLinuxRunInCoreAgentOld,
Expand Down

0 comments on commit 19ce2bc

Please sign in to comment.