You are implementing Task B1 of the "DD Agent Logs via Vector" plan.

## Task Description

Capture the CURRENT (pre-change) rendered output of the DD Agent module's helm values template as a locked baseline. This locks in the "logs_intake_url = null = byte-identical to today" guarantee that Task B4 will rely on.

**Files to create:**
- `/Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh` (the test harness)
- `/Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/expected-direct.yaml` (the locked baseline render)

The harness will be used by Task B4 to assert that adding the `logs_intake_url` variable produces the same output as today when the variable is null. It will also assert the new env vars appear when the variable is set.

### Step 1: Create the directory

```
mkdir -p /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render
```

### Step 2: Generate the baseline using the CURRENT (unmodified) template

The current template (`values.yaml.tftpl`) does NOT have a `logs_intake_url` variable. To generate the baseline, render it with the existing required template vars only:

```
cd /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent
TMP="$(mktemp -d)"
ln -sf "$(pwd)/values.yaml.tftpl" "$TMP/values.yaml.tftpl"
cat > "$TMP/main.tf" <<'EOF'
output "rendered" {
  value = templatefile("${path.module}/values.yaml.tftpl", {
    cluster_name                    = "test-cluster"
    env                             = "nonprod"
    global_segment                  = "test"
    image_tag                       = "7.55.0"
    watch_namespace                 = "datadog"
    tags                            = ["env:test"]
    agents_priority_class_name      = "cloud-ops-system"
    apm_enabled                     = true
    container_exclude               = ""
    container_exclude_logs          = ""
    enable_mrds_monitoring          = false
    enable_nowrds_monitoring        = false
    enable_now_obfusicator_options  = false
    now_obfusicator_options         = { replace_digits = "true" }
    datadog_api_key_secret_name     = "datadog-api-key"
    cluster_agent_token_secret_name = "datadog-clusteragent-token"
    log_level                       = "ERROR"
  })
}
EOF
(cd "$TMP" && terraform init -backend=false -input=false >/dev/null && terraform apply -auto-approve -input=false >/dev/null)
(cd "$TMP" && terraform output -raw rendered) > tests/render/expected-direct.yaml
rm -rf "$TMP"
```

This produces `tests/render/expected-direct.yaml` containing the current rendered helm values. It MUST be generated against the unmodified template (i.e., before any future tasks touch values.yaml.tftpl).

After running, verify:
```
wc -l /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/expected-direct.yaml
head -5 /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/expected-direct.yaml
```
Expected: ~230 lines (the current template is 234 lines), starts with `targetSystem: "linux"`.

### Step 3: Create the harness runner

Create `/Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh`:

```
#!/usr/bin/env bash
# Renders values.yaml.tftpl under two input scenarios and diffs against the
# locked expected outputs. Catches accidental drift in the helm values output.
set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULE_DIR="$(cd "$DIR/../.." && pwd)"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

render() {
  local intake_url="$1"
  local out="$2"

  cat > "$TMP/main.tf" <<EOF
output "rendered" {
  value = templatefile("\${path.module}/values.yaml.tftpl", {
    cluster_name                    = "test-cluster"
    env                             = "nonprod"
    global_segment                  = "test"
    image_tag                       = "7.55.0"
    watch_namespace                 = "datadog"
    tags                            = ["env:test"]
    agents_priority_class_name      = "cloud-ops-system"
    apm_enabled                     = true
    container_exclude               = ""
    container_exclude_logs          = ""
    enable_mrds_monitoring          = false
    enable_nowrds_monitoring        = false
    enable_now_obfusicator_options  = false
    now_obfusicator_options         = { replace_digits = "true" }
    datadog_api_key_secret_name     = "datadog-api-key"
    cluster_agent_token_secret_name = "datadog-clusteragent-token"
    log_level                       = "ERROR"
    logs_intake_url                 = ${intake_url}
  })
}
EOF
  ln -sf "$MODULE_DIR/values.yaml.tftpl" "$TMP/values.yaml.tftpl"
  (cd "$TMP" && terraform init -backend=false -input=false >/dev/null && terraform apply -auto-approve -input=false >/dev/null)
  (cd "$TMP" && terraform output -raw rendered) > "$out"
  rm -rf "$TMP"/.terraform "$TMP"/terraform.tfstate*
}

render "null"                                                "$DIR/.actual-direct.yaml"
render '"http://vector.vector.svc.cluster.local:8282"'       "$DIR/.actual-via-vector.yaml"

diff -u "$DIR/expected-direct.yaml"     "$DIR/.actual-direct.yaml"
diff -u "$DIR/expected-via-vector.yaml" "$DIR/.actual-via-vector.yaml"

echo "datadog-agent values render OK"
```

Then make it executable:
```
chmod +x /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh
```

### Step 4: Do NOT run run.sh yet

The harness expects two `expected-*.yaml` files. We only generate `expected-direct.yaml` in this task — `expected-via-vector.yaml` will be generated by Task B4 after the template change. **If you run run.sh now, it will fail with "expected-via-vector.yaml: No such file or directory" — that's expected.**

DO NOT run run.sh in this task. Only confirm:
- `tests/render/run.sh` exists, is executable, and contains the script above
- `tests/render/expected-direct.yaml` exists, is non-empty, ~230 lines, starts with `targetSystem: "linux"`

## Context

This baseline-locking pattern is borrowed from the Vector module's VRL test pattern. The point is to capture the CURRENT helm values output BEFORE making any changes. Task B4 will then assert byte-identical output when `logs_intake_url = null`, proving the change is non-disruptive for clusters that don't opt in.

The local terraform binary is v1.3.10. The DD Agent module's `main.tf` requires >= 1.3.0, so the harness should run cleanly. If `terraform init` complains about unsatisfied provider versions, the Step 2 baseline generation may need `terraform init -backend=false -input=false -upgrade` or similar — surface any environmental issue as DONE_WITH_CONCERNS.

## CRITICAL — No git operations

Do NOT run any git commands. Sir Charles handles git himself.

## Your Job

1. Run Step 1 (mkdir).
2. Run Step 2 (generate the baseline). Capture the output and verify it looks right.
3. Run Step 3 (create run.sh, chmod +x).
4. Self-review by listing the directory and confirming both files exist with the right content.
5. Report back.

## Report Format

- **Status:** DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_CONTEXT
- Files created (with line counts)
- First 5 lines of expected-direct.yaml (paste the actual content)
- Whether run.sh is executable
- Any concerns (e.g., environmental issues with terraform)


I'll work through this systematically, Sir Charles. Let me start by examining the existing module to understand what we're working with before generating the baseline.


Bash

List datadog-agent module directory


Check terraform binary version


.rw-r--r-- steve.briggs staff 494 B  Mon Feb  9 15:05:23 2026 output.tf
.rw-r--r-- steve.briggs staff 7.5 KB Mon Feb  9 16:48:12 2026 datadog-app.yaml
drwxr-xr-x steve.briggs staff 128 B  Thu Feb 12 17:09:38 2026 processing-rules
.rw-r--r-- steve.briggs staff 144 B  Thu Feb 26 11:23:08 2026 AGENTS.md
.rw-r--r-- steve.briggs staff  49 B  Thu Feb 26 12:26:57 2026 CLAUDE.MD
.rw-r--r-- steve.briggs staff 3.0 KB Thu Feb 26 12:43:41 2026 MEMORIES.md
.rw-r--r-- steve.briggs staff 2.0 KB Fri Mar  6 14:23:59 2026 netpols.tf
.rw-r--r-- steve.briggs staff 9.4 KB Fri Mar  6 15:26:08 2026 main.tf
.rw-r--r-- steve.briggs staff  70 B  Wed Apr 15 19:26:08 2026 .gitignore
.rw-r--r-- steve.briggs staff 6.1 KB Wed Apr 15 19:26:08 2026 README.md
.rw-r--r-- steve.briggs staff 3.3 KB Wed Apr 15 19:26:08 2026 variables.tf
drwxr-xr-x steve.briggs staff 320 B  Wed Apr 22 12:42:10 2026 .idea
drwxr-xr-x steve.briggs staff 224 B  Tue May  5 12:32:56 2026 ..
drwxr-xr-x steve.briggs staff 512 B  Wed May  6 10:56:28 2026 .
.rw-r--r-- steve.briggs staff 6.3 KB Wed May  6 10:56:28 2026 values.yaml.tftpl
drwxr-xr-x steve.briggs staff 448 B  Wed May  6 11:11:05 2026 .git


/Users/steve.briggs/.local/share/mise/installs/terraform/1.3.10/bin/terraform
Terraform v1.3.10
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v6.43.0
+ provider registry.terraform.io/hashicorp/external v2.3.5
+ provider registry.terraform.io/hashicorp/google v6.50.0
+ provider registry.terraform.io/hashicorp/helm v2.17.0
+ provider registry.terraform.io/hashicorp/kubernetes v2.38.0
+ provider registry.terraform.io/hashicorp/random v3.8.1
+ provider registry.terraform.io/hashicorp/vault v4.8.0

Your version of Terraform is out of date! The latest version
is 1.15.1. You can update by downloading from https://www.terraform.io/downloads.html


Good — terraform 1.3.10 is available. Now let me read the current template to understand its structure before generating the baseline.


1	targetSystem: "linux"
2	registry: public.ecr.aws/datadog
3	datadog:
4	  operator:
5	    enabled: false
6	  apiKeyExistingSecret: ${datadog_api_key_secret_name}
7	  clusterName: ${cluster_name}
8	  securityContext:
9	    seLinuxOptions:
10	      user: "system_u"
11	      role: "system_r"
12	      type: "spc_t"
13	      level: "s0"
14	  logLevel: ${log_level}
15	  containerExclude: "${container_exclude}"
16	  containerExcludeLogs: "${container_exclude_logs}"
17	  logs:
18	    enabled: true
19	    containerCollectAll: true
20	    autoMultiLineDetection: true
21	  criSocketPath: /run/containerd/containerd.sock
22	  dogstatsd:
23	    port: 8125
24	    useHostPort: true
25	    nonLocalTraffic: true
26	  otlp:
27	    receiver:
28	      protocols:
29	        grpc:
30	          enabled: true
31	          endpoint: 0.0.0.0:4317
32	        http:
33	          enabled: true
34	          endpoint: 0.0.0.0:4318
35	  apm:
36	    enabled: ${apm_enabled}
37	    instrumentation:
38	      skipKPITelemetry: true
39	  processAgent:
40	    enabled: false
41	  networkMonitoring:
42	    enabled: false
43	  tags:
44	    - "global_segment:${global_segment}"
45	%{ for tag in tags ~}
46	    - "${tag}"
47	%{ endfor ~}
48	  confd:
49	    journald_conf.yaml: |-
50	      logs:
51	        - type: journald
52	          path: /var/log/journal/
53	          start_position: beginning
54	          source: journald
55	          exclude_units:
56	            - kubelet.service
57	  env:
58	    - name: DD_AUTOCONFIG_INCLUDE_FEATURES
59	      value: "containerd"
60	    - name: DD_ENV
61	      value: ${env}
62	    - name: DD_KUBERNETES_NODE_LABELS_AS_TAGS
63	      value: '{"kubernetes.io/hostname":"node_name","kubernetes.io/os":"node_os","beta.kubernetes.io/instance-type":"node_instance_type","node.kubernetes.io/lifecycle":"node_lifecycle","failure-domain.beta.kubernetes.io/region":"node_region","failure-domain.beta.kubernetes.io/zone":"node_zone"}'
64	    - name: DD_LOGS_CONFIG_PROCESSING_RULES
65	      valueFrom:
66	        configMapKeyRef:
67	          name: rules-config
68	          key: logs
69	    - name: DD_APM_REPLACE_TAGS
70	      valueFrom:
71	        configMapKeyRef:
72	          name: rules-config
73	          key: apm
74	    - name: DD_CLOUD_PROVIDER_METADATA
75	      value: "aws"
76	    - name: CLUSTER_NAME
77	      value: "${cluster_name}"
78	    - name: DD_APM_PROBABILISTIC_SAMPLER_ENABLED
79	      value: true
80	    - name: DD_APM_PROBABILISTIC_SAMPLER_SAMPLING_PERCENTAGE
81	      value: 15
82	clusterAgent:
83	  env:
84	    - name: DD_ENV
85	      value: ${env}
86	    - name: DD_KUBERNETES_NODE_LABELS_AS_TAGS
87	      value: '{"kubernetes.io/hostname":"node_name","kubernetes.io/os":"node_os","beta.kubernetes.io/instance-type":"node_instance_type","node.kubernetes.io/lifecycle":"node_lifecycle","failure-domain.beta.kubernetes.io/region":"node_region","failure-domain.beta.kubernetes.io/zone":"node_zone"}'
88	    - name: DD_LOGS_CONFIG_PROCESSING_RULES
89	      valueFrom:
90	        configMapKeyRef:
91	          name: rules-config
92	          key: logs
93	    - name: DD_APM_REPLACE_TAGS
94	      valueFrom:
95	        configMapKeyRef:
96	          name: rules-config
97	          key: apm
98	    - name: DD_CLOUD_PROVIDER_METADATA
99	      value: "aws"
100	    - name: CLUSTER_NAME
101	      value: "${cluster_name}"
102	%{ if enable_mrds_monitoring ~}
103	    - name: MRDS_HOST
104	      valueFrom:
105	        secretKeyRef:
106	          name: datadog-env
107	          key: MRDS_HOST
108	    - name: MRDS_PORT
109	      valueFrom:
110	        secretKeyRef:
111	          name: datadog-env
112	          key: MRDS_PORT
113	    - name: MRDS_USERNAME
114	      valueFrom:
115	        secretKeyRef:
116	          name: datadog-env
117	          key: MRDS_USERNAME
118	    - name: MRDS_PASSWORD
119	      valueFrom:
120	        secretKeyRef:
121	          name: datadog-env
122	          key: MRDS_PASSWORD
123	    - name: MRDS_REGION
124	      valueFrom:
125	        secretKeyRef:
126	          name: datadog-env
127	          key: MRDS_REGION
128	    - name: MRDS_INSTANCE_NAME
129	      valueFrom:
130	        secretKeyRef:
131	          name: datadog-env
132	          key: MRDS_INSTANCE_NAME
133	%{ endif ~}
134	%{ if enable_nowrds_monitoring ~}
135	    - name: NOWRDS_HOST
136	      valueFrom:
137	        secretKeyRef:
138	          name: datadog-env
139	          key: NOWRDS_HOST
140	    - name: NOWRDS_PORT
141	      valueFrom:
142	        secretKeyRef:
143	          name: datadog-env
144	          key: NOWRDS_PORT
145	    - name: NOWRDS_USERNAME
146	      valueFrom:
147	        secretKeyRef:
148	          name: datadog-env
149	          key: NOWRDS_USERNAME
150	    - name: NOWRDS_PASSWORD
151	      valueFrom:
152	        secretKeyRef:
153	          name: datadog-env
154	          key: NOWRDS_PASSWORD
155	    - name: NOWRDS_INSTANCE_NAME
156	      valueFrom:
157	        secretKeyRef:
158	          name: datadog-env
159	          key: NOWRDS_INSTANCE_NAME
160	%{ endif ~}
161	  confd:
162	%{ if enable_mrds_monitoring || enable_nowrds_monitoring ~}
163	    postgres.yaml: |-
164	      cluster_check: true
165	      init_config:
166	      instances:
167	%{ if enable_mrds_monitoring ~}
168	        - dbm: true
169	          ssl: allow
170	          host: "%%env_MRDS_HOST%%"
171	          port: "%%env_MRDS_PORT%%"
172	          username: "%%env_MRDS_USERNAME%%"
173	          password: "%%env_MRDS_PASSWORD%%"
174	          collect_schemas:
175	            enabled: true
176	          database_autodiscovery:
177	            enabled: true
178	          tags:
179	            - "dbinstanceidentifier:%%env_MRDS_INSTANCE_NAME%%"
180	            - "env:%%env_DD_ENV%%"
181	%{ endif ~}
182	%{ if enable_nowrds_monitoring ~}
183	        - dbm: true
184	          ssl: allow
185	          host: "%%env_NOWRDS_HOST%%"
186	          port: "%%env_NOWRDS_PORT%%"
187	          username: "%%env_NOWRDS_USERNAME%%"
188	          password: "%%env_NOWRDS_PASSWORD%%"
189	          collect_schemas:
190	            enabled: true
191	          database_autodiscovery:
192	            enabled: true
193	%{ if enable_now_obfusicator_options ~}
194	          obfuscator_options:
195	%{ for key, option in now_obfusicator_options ~}
196	            ${key}: ${option}
197	%{ endfor ~}
198	%{ endif ~}
199	          tags:
200	            - "dbinstanceidentifier:%%env_NOWRDS_INSTANCE_NAME%%"
201	            - "env:%%env_DD_ENV%%"
202	%{ endif ~}
203	%{ endif ~}
204	  enabled: true
205	  image:
206	    tag: ${image_tag}
207	  priorityClassName: ${agents_priority_class_name}
208	  tokenExistingSecret: ${cluster_agent_token_secret_name}
209	  admissionController:
210	    enabled: true
211	    configMode: socket
212	agents:
213	  enabled: true
214	  image:
215	    tag: ${image_tag}
216	  priorityClassName: ${agents_priority_class_name}
217	  tolerations:
218	    - operator: Exists
219	  useHostNetwork: true
220	  volumes:
221	    - name: journald
222	      hostPath:
223	        path: "/var/log/journal"
224	    - name: machineid
225	      hostPath:
226	        path: "/etc/machine-id"
227	  volumeMounts:
228	    - name: journald
229	      mountPath: "/var/log/journal"
230	      readOnly: true
231	    - name: machineid
232	      mountPath: "/etc/machine-id"
233	      readOnly: true
234


Good — I can see the template. It has 234 lines and does NOT yet contain `logs_intake_url`. Now let me proceed with the steps.


mkdir -p /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render && echo "Directory created"

Create the tests/render directory


Directory created


Now generate the baseline. Since the template does NOT have `logs_intake_url`, I need to use only the existing variables:


MODULE_DIR="/Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent"
TMP="$(mktemp -d)"
ln -sf "$MODULE_DIR/values.yaml.tftpl" "$TMP/values.yaml.tftpl"

cat > "$TMP/main.tf" <<'EOF'
output "rendered" {
  value = templatefile("${path.module}/values.yaml.tftpl", {
    cluster_name                    = "test-cluster"
    env                             = "nonprod"
    global_segment                  = "test"
    image_tag                       = "7.55.0"
    watch_namespace                 = "datadog"
    tags                            = ["env:test"]
    agents_priority_class_name      = "cloud-ops-system"
    apm_enabled                     = true
    container_exclude               = ""
    container_exclude_logs          = ""
    enable_mrds_monitoring          = false
    enable_nowrds_monitoring        = false
    enable_now_obfusicator_options  = false
    now_obfusicator_options         = { replace_digits = "true" }
    datadog_api_key_secret_name     = "datadog-api-key"
    cluster_agent_token_secret_name = "datadog-clusteragent-token"
    log_level                       = "ERROR"
  })
}
EOF

echo "=== Running terraform init ==="
(cd "$TMP" && terraform init -backend=false -input=false 2>&1)

echo "=== Running terraform apply ==="
(cd "$TMP" && terraform apply -auto-approve -input=false 2>&1)

echo "=== Capturing output ==="
(cd "$TMP" && terraform output -raw rendered) > /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/expected-direct.yaml

rm -rf "$TMP"
echo "=== Done ==="

Generate the baseline expected-direct.yaml from the current unmodified template


=== Running terraform init ===

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
=== Running terraform apply ===

Changes to Outputs:
  + rendered = <<-EOT
        targetSystem: "linux"
        registry: public.ecr.aws/datadog
        datadog:
          operator:
            enabled: false
          apiKeyExistingSecret: datadog-api-key
          clusterName: test-cluster
          securityContext:
            seLinuxOptions:
              user: "system_u"
              role: "system_r"
              type: "spc_t"
              level: "s0"
          logLevel: ERROR
          containerExclude: ""
          containerExcludeLogs: ""
          logs:
            enabled: true
            containerCollectAll: true
            autoMultiLineDetection: true
          criSocketPath: /run/containerd/containerd.sock
          dogstatsd:
            port: 8125
            useHostPort: true
            nonLocalTraffic: true
          otlp:
            receiver:
              protocols:
                grpc:
                  enabled: true
                  endpoint: 0.0.0.0:4317
                http:
                  enabled: true
                  endpoint: 0.0.0.0:4318
          apm:
            enabled: true
            instrumentation:
              skipKPITelemetry: true
          processAgent:
            enabled: false
          networkMonitoring:
            enabled: false
          tags:
            - "global_segment:test"
            - "env:test"
          confd:
            journald_conf.yaml: |-
              logs:
                - type: journald
                  path: /var/log/journal/
                  start_position: beginning
                  source: journald
                  exclude_units:
                    - kubelet.service
          env:
            - name: DD_AUTOCONFIG_INCLUDE_FEATURES
              value: "containerd"
            - name: DD_ENV
              value: nonprod
            - name: DD_KUBERNETES_NODE_LABELS_AS_TAGS
              value: '{"kubernetes.io/hostname":"node_name","kubernetes.io/os":"node_os","beta.kubernetes.io/instance-type":"node_instance_type","node.kubernetes.io/lifecycle":"node_lifecycle","failure-domain.beta.kubernetes.io/region":"node_region","failure-domain.beta.kubernetes.io/zone":"node_zone"}'
            - name: DD_LOGS_CONFIG_PROCESSING_RULES
              valueFrom:
                configMapKeyRef:
                  name: rules-config
                  key: logs
            - name: DD_APM_REPLACE_TAGS
              valueFrom:
                configMapKeyRef:
                  name: rules-config
                  key: apm
            - name: DD_CLOUD_PROVIDER_METADATA
              value: "aws"
            - name: CLUSTER_NAME
              value: "test-cluster"
            - name: DD_APM_PROBABILISTIC_SAMPLER_ENABLED
              value: true
            - name: DD_APM_PROBABILISTIC_SAMPLER_SAMPLING_PERCENTAGE
              value: 15
        clusterAgent:
          env:
            - name: DD_ENV
              value: nonprod
            - name: DD_KUBERNETES_NODE_LABELS_AS_TAGS
              value: '{"kubernetes.io/hostname":"node_name","kubernetes.io/os":"node_os","beta.kubernetes.io/instance-type":"node_instance_type","node.kubernetes.io/lifecycle":"node_lifecycle","failure-domain.beta.kubernetes.io/region":"node_region","failure-domain.beta.kubernetes.io/zone":"node_zone"}'
            - name: DD_LOGS_CONFIG_PROCESSING_RULES
              valueFrom:
                configMapKeyRef:
                  name: rules-config
                  key: logs
            - name: DD_APM_REPLACE_TAGS
              valueFrom:
                configMapKeyRef:
                  name: rules-config
                  key: apm
            - name: DD_CLOUD_PROVIDER_METADATA
              value: "aws"
            - name: CLUSTER_NAME
              value: "test-cluster"
          confd:
          enabled: true
          image:
            tag: 7.55.0
          priorityClassName: cloud-ops-system
          tokenExistingSecret: datadog-clusteragent-token
          admissionController:
            enabled: true
            configMode: socket
        agents:
          enabled: true
          image:
            tag: 7.55.0
          priorityClassName: cloud-ops-system
          tolerations:
            - operator: Exists
          useHostNetwork: true
          volumes:
            - name: journald
              hostPath:
                path: "/var/log/journal"
            - name: machineid
              hostPath:
                path: "/etc/machine-id"
          volumeMounts:
            - name: journald
              mountPath: "/var/log/journal"
              readOnly: true
            - name: machineid
              mountPath: "/etc/machine-id"
              readOnly: true
    EOT

You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

rendered = <<EOT
targetSystem: "linux"
registry: public.ecr.aws/datadog
datadog:
  operator:
    enabled: false
  apiKeyExistingSecret: datadog-api-key
  clusterName: test-cluster
  securityContext:
    seLinuxOptions:
      user: "system_u"
      role: "system_r"
      type: "spc_t"
      level: "s0"
  logLevel: ERROR
  containerExclude: ""
  containerExcludeLogs: ""
  logs:
    enabled: true
    containerCollectAll: true
    autoMultiLineDetection: true
  criSocketPath: /run/containerd/containerd.sock
  dogstatsd:
    port: 8125
    useHostPort: true
    nonLocalTraffic: true
  otlp:
    receiver:
      protocols:
        grpc:
          enabled: true
          endpoint: 0.0.0.0:4317
        http:
          enabled: true
          endpoint: 0.0.0.0:4318
  apm:
    enabled: true
    instrumentation:
      skipKPITelemetry: true
  processAgent:
    enabled: false
  networkMonitoring:
    enabled: false
  tags:
    - "global_segment:test"
    - "env:test"
  confd:
    journald_conf.yaml: |-
      logs:
        - type: journald
          path: /var/log/journal/
          start_position: beginning
          source: journald
          exclude_units:
            - kubelet.service
  env:
    - name: DD_AUTOCONFIG_INCLUDE_FEATURES
      value: "containerd"
    - name: DD_ENV
      value: nonprod
    - name: DD_KUBERNETES_NODE_LABELS_AS_TAGS
      value: '{"kubernetes.io/hostname":"node_name","kubernetes.io/os":"node_os","beta.kubernetes.io/instance-type":"node_instance_type","node.kubernetes.io/lifecycle":"node_lifecycle","failure-domain.beta.kubernetes.io/region":"node_region","failure-domain.beta.kubernetes.io/zone":"node_zone"}'
    - name: DD_LOGS_CONFIG_PROCESSING_RULES
      valueFrom:
        configMapKeyRef:
          name: rules-config
          key: logs
    - name: DD_APM_REPLACE_TAGS
      valueFrom:
        configMapKeyRef:
          name: rules-config
          key: apm
    - name: DD_CLOUD_PROVIDER_METADATA
      value: "aws"
    - name: CLUSTER_NAME
      value: "test-cluster"
    - name: DD_APM_PROBABILISTIC_SAMPLER_ENABLED
      value: true
    - name: DD_APM_PROBABILISTIC_SAMPLER_SAMPLING_PERCENTAGE
      value: 15
clusterAgent:
  env:
    - name: DD_ENV
      value: nonprod
    - name: DD_KUBERNETES_NODE_LABELS_AS_TAGS
      value: '{"kubernetes.io/hostname":"node_name","kubernetes.io/os":"node_os","beta.kubernetes.io/instance-type":"node_instance_type","node.kubernetes.io/lifecycle":"node_lifecycle","failure-domain.beta.kubernetes.io/region":"node_region","failure-domain.beta.kubernetes.io/zone":"node_zone"}'
    - name: DD_LOGS_CONFIG_PROCESSING_RULES
      valueFrom:
        configMapKeyRef:
          name: rules-config
          key: logs
    - name: DD_APM_REPLACE_TAGS
      valueFrom:
        configMapKeyRef:
          name: rules-config
          key: apm
    - name: DD_CLOUD_PROVIDER_METADATA
      value: "aws"
    - name: CLUSTER_NAME
      value: "test-cluster"
  confd:
  enabled: true
  image:
    tag: 7.55.0
  priorityClassName: cloud-ops-system
  tokenExistingSecret: datadog-clusteragent-token
  admissionController:
    enabled: true
    configMode: socket
agents:
  enabled: true
  image:
    tag: 7.55.0
  priorityClassName: cloud-ops-system
  tolerations:
    - operator: Exists
  useHostNetwork: true
  volumes:
    - name: journald
      hostPath:
        path: "/var/log/journal"
    - name: machineid
      hostPath:
        path: "/etc/machine-id"
  volumeMounts:
    - name: journald
      mountPath: "/var/log/journal"
      readOnly: true
    - name: machineid
      mountPath: "/etc/machine-id"
      readOnly: true

EOT
=== Capturing output ===
=== Done ===


The baseline rendered cleanly. Now let me verify the output file and then create `run.sh`:


Count lines in the baseline file


130 /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/expected-direct.yaml


1	targetSystem: "linux"
2	registry: public.ecr.aws/datadog
3	datadog:
4	  operator:
5	    enabled: false
6	  apiKeyExistingSecret: datadog-api-key
7	  clusterName: test-cluster
8	  securityContext:
9	    seLinuxOptions:
10	      user: "system_u"


Good — starts with `targetSystem: "linux"` as expected. The 130 lines vs the expected ~230 is because `terraform output -raw` strips the EOT wrapper and the template collapses conditional blocks (the `enable_mrds_monitoring`/`enable_nowrds_monitoring` blocks are all false, so they render to nothing). This is the correct output. Now create `run.sh`:


Write

#!/usr/bin/env bash
# Renders values.yaml.tftpl under two input scenarios and diffs against the
# locked expected outputs. Catches accidental drift in the helm values output.
set -euo pipefail

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODULE_DIR="$(cd "$DIR/../.." && pwd)"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

render() {
  local intake_url="$1"
  local out="$2"

  cat > "$TMP/main.tf" <<EOF
output "rendered" {
  value = templatefile("\${path.module}/values.yaml.tftpl", {
    cluster_name                    = "test-cluster"
    env                             = "nonprod"
    global_segment                  = "test"
    image_tag                       = "7.55.0"
    watch_namespace                 = "datadog"
    tags                            = ["env:test"]
    agents_priority_class_name      = "cloud-ops-system"
    apm_enabled                     = true
    container_exclude               = ""
    container_exclude_logs          = ""
    enable_mrds_monitoring          = false
    enable_nowrds_monitoring        = false
    enable_now_obfusicator_options  = false
    now_obfusicator_options         = { replace_digits = "true" }
    datadog_api_key_secret_name     = "datadog-api-key"
    cluster_agent_token_secret_name = "datadog-clusteragent-token"
    log_level                       = "ERROR"
    logs_intake_url                 = ${intake_url}
  })
}
EOF
  ln -sf "$MODULE_DIR/values.yaml.tftpl" "$TMP/values.yaml.tftpl"
  (cd "$TMP" && terraform init -backend=false -input=false >/dev/null && terraform apply -auto-approve -input=false >/dev/null)
  (cd "$TMP" && terraform output -raw rendered) > "$out"
  rm -rf "$TMP"/.terraform "$TMP"/terraform.tfstate*
}

render "null"                                                "$DIR/.actual-direct.yaml"
render '"http://vector.vector.svc.cluster.local:8282"'       "$DIR/.actual-via-vector.yaml"

diff -u "$DIR/expected-direct.yaml"     "$DIR/.actual-direct.yaml"
diff -u "$DIR/expected-via-vector.yaml" "$DIR/.actual-via-vector.yaml"

echo "datadog-agent values render OK"


File created successfully at: /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh (file state is current in your context — no need to Read it back)


Bash

chmod +x /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh && echo "chmod done"

Make run.sh executable


chmod done


Now the self-review — list the directory and verify both files:


List the tests/render directory to confirm both files exist


drwxr-xr-x steve.briggs staff  96 B  Wed May  6 12:49:11 2026 ..
.rw-r--r-- steve.briggs staff 3.5 KB Wed May  6 12:49:26 2026 expected-direct.yaml
.rwxr-xr-x steve.briggs staff 2.0 KB Wed May  6 12:55:25 2026 run.sh
drwxr-xr-x steve.briggs staff 128 B  Wed May  6 12:55:25 2026 .


Verify run.sh line count and type


      51 /Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh
/Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh: Bourne-Again shell script text executable, ASCII text


Both files are confirmed. Let me do a final content check of the first 5 lines of the baseline:


1	targetSystem: "linux"
2	registry: public.ecr.aws/datadog
3	datadog:
4	  operator:
5	    enabled: false


Everything looks correct. One brief note on the line count discrepancy to include in the report.

---

**Status:** DONE_WITH_CONCERNS (minor — see line count note)

**Files created:**

- `/Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/expected-direct.yaml` — **130 lines**
- `/Users/steve.briggs/projects/IAC/terraform/internal-modules/kubernetes/monitoring/datadog-agent/tests/render/run.sh` — **51 lines**, executable (`-rwxr-xr-x`)

**First 5 lines of expected-direct.yaml (actual content):**
```
targetSystem: "linux"
registry: public.ecr.aws/datadog
datadog:
  operator:
    enabled: false
```

**run.sh executable:** Yes — confirmed `Bourne-Again shell script text executable`.

**Concern — line count is 130, not ~230:**

The task description predicted ~230 lines, but the actual rendered output is 130 lines. This is correct and expected behavior — `terraform output -raw rendered` strips terraform's EOT wrapper, and all the conditional blocks (`enable_mrds_monitoring`, `enable_nowrds_monitoring`, `enable_now_obfusicator_options`) render to nothing because they're all `false`. The source template is 234 lines with ~100 lines inside conditional blocks that collapse away. The 130-line output accurately represents the rendered YAML for the test fixture inputs. Task B4's `null` comparison will be byte-for-byte against this same 130-line output, which is what matters.

**No environmental issues** — terraform 1.3.10 initialized without providers (no `required_providers` block in the temp harness), applied cleanly, and `terraform output -raw` produced clean YAML with no trailing newline issues.