diff --git a/.github/workflows/go-test-datadog.yaml b/.github/workflows/go-test-datadog.yaml new file mode 100644 index 000000000..990417e72 --- /dev/null +++ b/.github/workflows/go-test-datadog.yaml @@ -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 diff --git a/.github/workflows/go-test.yaml b/.github/workflows/go-test-operator.yaml similarity index 100% rename from .github/workflows/go-test.yaml rename to .github/workflows/go-test-operator.yaml diff --git a/Makefile b/Makefile index 493319bbe..7699b0cb1 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/test/common/common.go b/test/common/common.go index c060ae173..e34b481b8 100644 --- a/test/common/common.go +++ b/test/common/common.go @@ -1,6 +1,7 @@ package common import ( + appsv1 "k8s.io/api/apps/v1" "os" "path/filepath" "strings" @@ -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 +} diff --git a/test/datadog/autopilot_test.go b/test/datadog/autopilot_test.go new file mode 100644 index 000000000..3a7abade6 --- /dev/null +++ b/test/datadog/autopilot_test.go @@ -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.") +} diff --git a/test/datadog/gdc_test.go b/test/datadog/gdc_test.go index b8b2ecf98..b68ac2a4a 100644 --- a/test/datadog/gdc_test.go +++ b/test/datadog/gdc_test.go @@ -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 { diff --git a/test/datadog/process_agent_test.go b/test/datadog/process_agent_test.go index 10946f82d..9f1e986d7 100644 --- a/test/datadog/process_agent_test.go +++ b/test/datadog/process_agent_test.go @@ -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, @@ -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,