Skip to content

Commit 393f3c2

Browse files
committed
fix(e2e): unblock Chainsaw suite after replication fix
With the kubeconfig port fix, replication works and the suite advanced, exposing four pre-existing issues: - zones-and-records asserted status.domainRef.status.nameservers (real Cloudflare NS) which is populated by NSO; CI runs without NSO. Assert only operator-owned fields (conditions + DNSZoneClass nameservers). - display-annotations asserted a single-element conditions slice while the DNSZone carries two (Accepted+Programmed), failing on slice length. Use a JMESPath filter to assert the Accepted condition only. - alias/zones-and-records scripts used 'set -euo pipefail'; chainsaw runs scripts under dash, which rejects '-o pipefail'. Use 'set -eu'. - events.k8s.io/v1 Events require a non-empty reportingInstance, but POD_NAME was never injected, so every emitted Event was rejected. Inject POD_NAME via the downward API and add a hostname fallback in code. Refs #46
1 parent 8b999e2 commit 393f3c2

5 files changed

Lines changed: 47 additions & 15 deletions

File tree

config/manager/manager.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ spec:
6868
image: ghcr.io/datum-cloud/dns-operator:latest
6969
imagePullPolicy: IfNotPresent
7070
name: manager
71+
# POD_NAME is used as the reportingInstance on emitted events.k8s.io/v1
72+
# Events, which the API server requires to be non-empty.
73+
env:
74+
- name: POD_NAME
75+
valueFrom:
76+
fieldRef:
77+
fieldPath: metadata.name
7178
ports: []
7279
securityContext:
7380
readOnlyRootFilesystem: true

internal/controller/events.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,31 @@ func buildEvent(
247247
Note: note,
248248
Type: eventType,
249249
ReportingController: "dns.networking.miloapis.com/dns-operator",
250-
ReportingInstance: os.Getenv("POD_NAME"),
250+
ReportingInstance: reportingInstance(),
251251
}
252252
}
253253

254+
// reportingInstance returns a non-empty identifier for the reporting pod.
255+
// events.k8s.io/v1 requires reportingInstance to be set (1-128 chars), so we
256+
// fall back through POD_NAME -> hostname -> a constant when the downward-API
257+
// env var is unset (e.g. in tests or misconfigured deployments). The result is
258+
// truncated to the 128-character API limit.
259+
func reportingInstance() string {
260+
name := os.Getenv("POD_NAME")
261+
if name == "" {
262+
if h, err := os.Hostname(); err == nil {
263+
name = h
264+
}
265+
}
266+
if name == "" {
267+
name = "dns-operator"
268+
}
269+
if len(name) > 128 {
270+
name = name[:128]
271+
}
272+
return name
273+
}
274+
254275
// recordSetObjectRef builds a corev1.ObjectReference for a DNSRecordSet using
255276
// hardcoded GVK values (stable and known for this operator).
256277
func recordSetObjectRef(rs *dnsv1alpha1.DNSRecordSet) corev1.ObjectReference {

test/e2e/alias/chainsaw-test.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ spec:
163163
- script:
164164
cluster: upstream
165165
content: |
166-
set -euo pipefail
166+
set -eu
167167
for i in $(seq 1 30); do
168168
acc="$(kubectl -n "$NAMESPACE" get dnsrecordset example-test-alias-apex -o jsonpath='{.status.conditions[?(@.type=="Accepted")].status}' 2>/dev/null || true)"
169169
prog="$(kubectl -n "$NAMESPACE" get dnsrecordset example-test-alias-apex -o jsonpath='{.status.conditions[?(@.type=="Programmed")].status}' 2>/dev/null || true)"
@@ -208,12 +208,12 @@ spec:
208208
- script:
209209
cluster: downstream
210210
content: |
211-
set -euo pipefail
211+
set -eu
212212
kubectl wait --for=condition=Ready --timeout=120s -n default pod/dnsutils-alias
213213
# ALIAS is provider-internal; clients query A/AAAA for the owner name.
214214
# Validate expansion by comparing A answers to a public resolver (dynamic, no hard-coded IPs).
215215
kubectl -n default exec pod/dnsutils-alias -- sh -lc '
216-
set -euo pipefail
216+
set -eu
217217
expected="$(dig @1.1.1.1 example.com A +short +tries=1 +time=2 | sort -u)"
218218
[ -n "$expected" ] || { echo "expected A set is empty" >&2; exit 1; }
219219
got="$(dig @pdns-auth.dns-agent-system.svc.cluster.local example.test A +short +tries=2 +time=2 | sort -u)"

test/e2e/display-annotations/chainsaw-test.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,12 @@ spec:
100100
kind: DNSZone
101101
metadata:
102102
name: annotations-test-zone
103+
# The DNSZone carries both Accepted and Programmed conditions; assert
104+
# only that the Accepted condition is True without requiring the slice
105+
# to match exactly (a bare list would force a length match).
103106
status:
104-
conditions:
105-
- type: Accepted
106-
status: "True"
107+
(conditions[?type == 'Accepted']):
108+
- status: "True"
107109

108110
- name: Create DNSRecordSet upstream (A record)
109111
try:

test/e2e/zones-and-records/chainsaw-test.yaml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,14 @@ spec:
132132
kind: DNSZone
133133
metadata:
134134
name: example-com
135+
# NOTE: status.domainRef.status.nameservers is mirrored from the
136+
# upstream NSO Domain object's status, which is only populated when
137+
# the Network Services Operator is deployed and resolving real
138+
# external DNS. CI bootstraps without NSO (NSO_DEPLOY=false), so we
139+
# assert only the fields this operator owns: the Accepted/Programmed
140+
# conditions and (in the next step) the DNSZoneClass-derived
141+
# nameservers.
135142
status:
136-
domainRef:
137-
status:
138-
nameservers:
139-
- hostname: elliott.ns.cloudflare.com
140-
- hostname: hera.ns.cloudflare.com
141143
conditions:
142144
- type: Accepted
143145
status: "True"
@@ -255,7 +257,7 @@ spec:
255257
- script:
256258
cluster: downstream
257259
content: |
258-
set -euo pipefail
260+
set -eu
259261
# wait for pod ready condition
260262
kubectl wait --for=condition=Ready --timeout=120s -n default pod/dnsutils
261263
# Execute dig from inside the dnsutils pod (in-cluster DNS context)
@@ -287,7 +289,7 @@ spec:
287289
- script:
288290
cluster: upstream
289291
content: |
290-
set -euo pipefail
292+
set -eu
291293
# Confirm it no longer exists upstream
292294
if kubectl -n "$NAMESPACE" get dnsrecordset www-example-com >/dev/null 2>&1; then
293295
echo "upstream DNSRecordSet still exists" >&2
@@ -298,7 +300,7 @@ spec:
298300
- script:
299301
cluster: downstream
300302
content: |
301-
set -euo pipefail
303+
set -eu
302304
# verify A record no longer resolves
303305
kubectl -n default exec pod/dnsutils -- sh -lc '
304306
out=$(dig @pdns-auth.dns-agent-system.svc.cluster.local www.example.com A +short +tries=1 +time=1);

0 commit comments

Comments
 (0)