Skip to content

Commit e4c308f

Browse files
scotwellsclaude
andcommitted
test(e2e): federation delivery suites (full-federation, projection, writeback, PP lifecycle, deletion-cascade)
Carved out of the federation foundation PR so the controller change reviews without ~900 lines of chainsaw YAML inline. These suites exercise the federation behaviour end-to-end against the shared test/e2e/env harness (which stays with the foundation). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent cfc79cb commit e4c308f

20 files changed

Lines changed: 906 additions & 0 deletions
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Assert the WorkloadDeployment is present in the Karmada API server.
2+
# Used both to confirm federation succeeded and as the target for the error: check.
3+
apiVersion: compute.datumapis.com/v1alpha
4+
kind: WorkloadDeployment
5+
metadata:
6+
namespace: ($downstreamNS)
7+
name: test-cascade-wd
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha1
2+
kind: Test
3+
metadata:
4+
name: deletion-cascade
5+
spec:
6+
description: |
7+
Verifies that deleting a WorkloadDeployment from the project namespace causes
8+
the federator to remove the corresponding WorkloadDeployment from Karmada.
9+
10+
The WorkloadDeploymentFederator adds a finalizer
11+
(compute.datumapis.com/federator) to every project WD it manages. When the
12+
project WD is deleted:
13+
1. The finalizer's Finalize method runs (blocking deletion until complete).
14+
2. It deletes the Karmada-side WorkloadDeployment.
15+
3. It removes the PropagationPolicy if no other WDs for the city remain.
16+
4. It removes the finalizer, allowing the project WD to be garbage-collected.
17+
18+
This test validates: project WD deletion → Karmada WD deletion.
19+
20+
template: true
21+
22+
steps:
23+
- name: create-wd
24+
description: Create a WorkloadDeployment on the control-plane cluster.
25+
try:
26+
- apply:
27+
file: workload-deployment.yaml
28+
29+
- name: wait-for-federation
30+
description: Wait for the WorkloadDeployment to appear in Karmada.
31+
cluster: downstream
32+
try:
33+
- script:
34+
content: |
35+
kubectl --kubeconfig=../../../tmp/e2e/kubeconfigs/control-plane.yaml \
36+
get namespace "$NAMESPACE" \
37+
-o template='{{printf "ns-%s" .metadata.uid}}'
38+
outputs:
39+
- name: downstreamNS
40+
value: ($stdout)
41+
- assert:
42+
timeout: 30s
43+
resource:
44+
apiVersion: compute.datumapis.com/v1alpha
45+
kind: WorkloadDeployment
46+
metadata:
47+
namespace: ($downstreamNS)
48+
name: test-cascade-wd
49+
50+
- name: delete-wd
51+
description: Delete the WorkloadDeployment from the control-plane cluster.
52+
try:
53+
- delete:
54+
ref:
55+
apiVersion: compute.datumapis.com/v1alpha
56+
kind: WorkloadDeployment
57+
namespace: ($namespace)
58+
name: test-cascade-wd
59+
60+
- name: assert-downstream-wd-deleted
61+
description: Confirm the Karmada copy is removed by the finalizer.
62+
cluster: downstream
63+
try:
64+
- script:
65+
content: |
66+
kubectl --kubeconfig=../../../tmp/e2e/kubeconfigs/control-plane.yaml \
67+
get namespace "$NAMESPACE" \
68+
-o template='{{printf "ns-%s" .metadata.uid}}'
69+
outputs:
70+
- name: downstreamNS
71+
value: ($stdout)
72+
- wait:
73+
apiVersion: compute.datumapis.com/v1alpha
74+
kind: WorkloadDeployment
75+
namespace: ($downstreamNS)
76+
name: test-cascade-wd
77+
timeout: 30s
78+
for:
79+
deletion: {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: compute.datumapis.com/v1alpha
2+
kind: WorkloadDeployment
3+
metadata:
4+
name: test-cascade-wd
5+
spec:
6+
cityCode: dfw
7+
placementName: default
8+
workloadRef:
9+
name: test-workload
10+
uid: "00000000-0000-0000-0000-000000000001"
11+
template:
12+
spec:
13+
runtime:
14+
resources:
15+
instanceType: datumcloud/d1-standard-2
16+
networkInterfaces:
17+
- network:
18+
name: test-network
19+
20+
scaleSettings:
21+
minReplicas: 1
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
apiVersion: chainsaw.kyverno.io/v1alpha1
2+
kind: Test
3+
metadata:
4+
name: full-federation
5+
spec:
6+
description: |
7+
End-to-end federation chain test.
8+
9+
Exercises the complete path from WorkloadDeployment creation through to
10+
Instance projection on the control-plane cluster:
11+
12+
1. Create WorkloadDeployment on control-plane.
13+
2. WorkloadDeploymentFederator replicates it to Karmada (ns-<uid> namespace).
14+
3. Karmada PropagationPolicy routes the WD to pop-dfw.
15+
4. WorkloadDeploymentReconciler on pop-dfw creates Instance test-full-fed-wd-0.
16+
5. InstanceReconciler on pop-dfw writes Instance back to Karmada with
17+
label meta.datumapis.com/upstream-cluster-name: cluster-single.
18+
6. InstanceProjector on control-plane creates a projection of the Instance
19+
in the project namespace.
20+
21+
Prerequisites: both operator instances must be running (task e2e:operator:start).
22+
23+
template: true
24+
25+
steps:
26+
- name: create-workload-deployment
27+
description: Create the WorkloadDeployment on the control-plane cluster.
28+
try:
29+
- apply:
30+
file: workload-deployment.yaml
31+
32+
- name: assert-wd-in-downstream
33+
description: Assert WorkloadDeploymentFederator replicated the WD to Karmada and status is synced back.
34+
cluster: downstream
35+
try:
36+
- script:
37+
content: |
38+
kubectl --kubeconfig=../../../tmp/e2e/kubeconfigs/control-plane.yaml \
39+
get namespace "$NAMESPACE" \
40+
-o template='{{printf "ns-%s" .metadata.uid}}'
41+
outputs:
42+
- name: downstreamNS
43+
value: ($stdout)
44+
- assert:
45+
timeout: 30s
46+
resource:
47+
apiVersion: compute.datumapis.com/v1alpha
48+
kind: WorkloadDeployment
49+
metadata:
50+
namespace: ($downstreamNS)
51+
name: test-full-fed-wd
52+
- assert:
53+
# Wait for the cell operator to write status back to the Karmada WD.
54+
timeout: 60s
55+
resource:
56+
apiVersion: compute.datumapis.com/v1alpha
57+
kind: WorkloadDeployment
58+
metadata:
59+
namespace: ($downstreamNS)
60+
name: test-full-fed-wd
61+
status:
62+
replicas: 1
63+
desiredReplicas: 1
64+
65+
- name: assert-wd-on-pop-dfw
66+
description: Assert Karmada propagated the WD to pop-dfw and the cell reconciler set status.
67+
cluster: pop-dfw
68+
try:
69+
- script:
70+
content: |
71+
kubectl --kubeconfig=../../../tmp/e2e/kubeconfigs/control-plane.yaml \
72+
get namespace "$NAMESPACE" \
73+
-o template='{{printf "ns-%s" .metadata.uid}}'
74+
outputs:
75+
- name: downstreamNS
76+
value: ($stdout)
77+
- assert:
78+
# Karmada propagation can take longer than a local apply.
79+
timeout: 60s
80+
resource:
81+
apiVersion: compute.datumapis.com/v1alpha
82+
kind: WorkloadDeployment
83+
metadata:
84+
namespace: ($downstreamNS)
85+
name: test-full-fed-wd
86+
status:
87+
replicas: 1
88+
desiredReplicas: 1
89+
90+
- name: assert-instance-on-pop-dfw
91+
description: Assert WorkloadDeploymentReconciler created an Instance on pop-dfw with a Ready condition.
92+
cluster: pop-dfw
93+
try:
94+
- script:
95+
content: |
96+
kubectl --kubeconfig=../../../tmp/e2e/kubeconfigs/control-plane.yaml \
97+
get namespace "$NAMESPACE" \
98+
-o template='{{printf "ns-%s" .metadata.uid}}'
99+
outputs:
100+
- name: downstreamNS
101+
value: ($stdout)
102+
- assert:
103+
timeout: 30s
104+
resource:
105+
apiVersion: compute.datumapis.com/v1alpha
106+
kind: Instance
107+
metadata:
108+
namespace: ($downstreamNS)
109+
name: test-full-fed-wd-0
110+
(status.conditions[?type == 'Ready'] | [0]):
111+
status: "Unknown"
112+
113+
- name: assert-instance-writeback-in-downstream
114+
description: Assert InstanceReconciler wrote the Instance back to Karmada.
115+
cluster: downstream
116+
try:
117+
- script:
118+
content: |
119+
kubectl --kubeconfig=../../../tmp/e2e/kubeconfigs/control-plane.yaml \
120+
get namespace "$NAMESPACE" \
121+
-o template='{{printf "ns-%s" .metadata.uid}}'
122+
outputs:
123+
- name: downstreamNS
124+
value: ($stdout)
125+
- assert:
126+
timeout: 30s
127+
resource:
128+
apiVersion: compute.datumapis.com/v1alpha
129+
kind: Instance
130+
metadata:
131+
namespace: ($downstreamNS)
132+
name: test-full-fed-wd-0
133+
labels:
134+
meta.datumapis.com/upstream-cluster-name: cluster-single
135+
136+
- name: assert-instance-projected-to-control-plane
137+
description: Assert InstanceProjector created a projection with status on the control-plane.
138+
try:
139+
- assert:
140+
timeout: 30s
141+
resource:
142+
apiVersion: compute.datumapis.com/v1alpha
143+
kind: Instance
144+
metadata:
145+
namespace: ($namespace)
146+
name: test-full-fed-wd-0
147+
labels:
148+
meta.datumapis.com/upstream-cluster-name: cluster-single
149+
(status.conditions[?type == 'Ready'] | [0]):
150+
status: "Unknown"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: compute.datumapis.com/v1alpha
2+
kind: WorkloadDeployment
3+
metadata:
4+
name: test-full-fed-wd
5+
# namespace is injected by Chainsaw from ($namespace)
6+
spec:
7+
cityCode: dfw
8+
placementName: default
9+
workloadRef:
10+
name: test-workload
11+
uid: "00000000-0000-0000-0000-000000000001"
12+
template:
13+
spec:
14+
runtime:
15+
resources:
16+
instanceType: datumcloud/d1-standard-2
17+
networkInterfaces:
18+
- network:
19+
name: test-network
20+
scaleSettings:
21+
minReplicas: 1
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Assert the WorkloadDeployment is federated to Karmada (and the Karmada namespace created).
2+
apiVersion: compute.datumapis.com/v1alpha
3+
kind: WorkloadDeployment
4+
metadata:
5+
namespace: ($downstreamNS)
6+
name: test-projector-wd
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Assert the InstanceProjector created a projection in the project namespace.
2+
#
3+
# The InstanceProjector (internal/controller/instance_projector.go):
4+
# - Watches Instances in Karmada that carry upstreamClusterNameLabel
5+
# - Strips "cluster-" prefix to get the cluster name ("single" in single-provider mode)
6+
# - Finds the project namespace by matching ns-<uid> to namespace UIDs
7+
# - Creates/updates the Instance projection in the project namespace
8+
# - Sets an owner reference to the WorkloadDeployment for cascading deletion
9+
apiVersion: compute.datumapis.com/v1alpha
10+
kind: Instance
11+
metadata:
12+
# namespace is the Chainsaw test namespace (the project namespace on control-plane)
13+
name: test-projected-instance
14+
labels:
15+
meta.datumapis.com/upstream-cluster-name: cluster-single
16+
ownerReferences:
17+
- apiVersion: compute.datumapis.com/v1alpha
18+
kind: WorkloadDeployment
19+
name: test-projector-wd

0 commit comments

Comments
 (0)