Skip to content

Commit 62f31c9

Browse files
committed
actions: Add actions to deploy & test our chart
Those actions have been vibe generated, although still heavily based on what we currently have on kata-containers / confidential-containers' oeprator. Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
1 parent 1bb7d13 commit 62f31c9

File tree

3 files changed

+474
-0
lines changed

3 files changed

+474
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
name: Install Helm Chart
2+
description: Install the Confidential Containers Helm chart with various configurations
3+
4+
inputs:
5+
release-name:
6+
description: 'Helm release name'
7+
required: false
8+
default: 'coco'
9+
namespace:
10+
description: 'Kubernetes namespace'
11+
required: false
12+
default: 'kube-system'
13+
extra-args:
14+
description: 'Extra Helm install arguments (e.g., --set flags)'
15+
required: false
16+
default: ''
17+
values-file:
18+
description: 'Path to values file (optional)'
19+
required: false
20+
default: ''
21+
wait-timeout:
22+
description: 'Timeout for helm install --wait'
23+
required: false
24+
default: '15m'
25+
26+
outputs:
27+
installed:
28+
description: 'Whether installation succeeded'
29+
value: ${{ steps.install.outputs.result }}
30+
31+
runs:
32+
using: composite
33+
steps:
34+
- name: Update Helm dependencies
35+
shell: bash
36+
run: |
37+
echo "📦 Updating Helm dependencies..."
38+
helm dependency update
39+
echo "✅ Dependencies updated"
40+
41+
- name: Validate chart
42+
shell: bash
43+
run: |
44+
echo "🔍 Validating chart..."
45+
helm lint .
46+
echo "✅ Chart is valid"
47+
48+
- name: Install chart
49+
id: install
50+
shell: bash
51+
run: |
52+
echo "🚀 Installing chart: ${{ inputs.release-name }}"
53+
echo " Namespace: ${{ inputs.namespace }}"
54+
echo " Extra args: ${{ inputs.extra-args }}"
55+
if [ -n "${{ inputs.values-file }}" ]; then
56+
echo " Values file: ${{ inputs.values-file }}"
57+
fi
58+
59+
INSTALL_CMD="helm install ${{ inputs.release-name }} . \
60+
--namespace ${{ inputs.namespace }} \
61+
--create-namespace \
62+
--debug"
63+
64+
if [ -n "${{ inputs.values-file }}" ]; then
65+
INSTALL_CMD="$INSTALL_CMD -f ${{ inputs.values-file }}"
66+
fi
67+
68+
if [ -n "${{ inputs.extra-args }}" ]; then
69+
INSTALL_CMD="$INSTALL_CMD ${{ inputs.extra-args }}"
70+
fi
71+
72+
echo "Running: $INSTALL_CMD"
73+
74+
if eval $INSTALL_CMD; then
75+
echo "✅ Chart installed successfully"
76+
echo "result=success" >> $GITHUB_OUTPUT
77+
else
78+
echo "❌ Chart installation failed"
79+
echo "result=failed" >> $GITHUB_OUTPUT
80+
exit 1
81+
fi
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
name: Run Test Pod
2+
description: Deploy and verify a test pod using Kata runtime
3+
4+
inputs:
5+
runtime-class:
6+
description: 'RuntimeClass to use for the test pod'
7+
required: true
8+
namespace:
9+
description: 'Kubernetes namespace for test pod'
10+
required: false
11+
default: 'default'
12+
pod-name:
13+
description: 'Name of the test pod'
14+
required: false
15+
default: 'kata-test-pod'
16+
timeout:
17+
description: 'Timeout for pod to become ready'
18+
required: false
19+
default: '5m'
20+
21+
outputs:
22+
pod-status:
23+
description: 'Final status of the test pod'
24+
value: ${{ steps.check-status.outputs.status }}
25+
26+
runs:
27+
using: composite
28+
steps:
29+
- name: Verify cluster health
30+
shell: bash
31+
run: |
32+
set -e # Exit on any error
33+
echo "🏥 Checking cluster health before running test pod..."
34+
35+
# Retry kubectl cluster-info with exponential backoff
36+
MAX_RETRIES=5
37+
RETRY_DELAY=2
38+
39+
for attempt in $(seq 1 $MAX_RETRIES); do
40+
echo " Attempt $attempt/$MAX_RETRIES: Checking API server..."
41+
42+
if kubectl cluster-info 2>&1 | grep -q "is running"; then
43+
echo "✅ Kubernetes API server is responding"
44+
break
45+
else
46+
if [ $attempt -eq $MAX_RETRIES ]; then
47+
echo "❌ Kubernetes API server is not responding after $MAX_RETRIES attempts"
48+
echo ""
49+
echo "Cluster info:"
50+
kubectl cluster-info dump --output-directory=/tmp/cluster-info --namespaces=kube-system 2>&1 || true
51+
echo ""
52+
echo "System pods:"
53+
kubectl get pods -n kube-system 2>&1 || echo "Failed to get pods"
54+
echo ""
55+
echo "Nodes:"
56+
kubectl get nodes 2>&1 || echo "Failed to get nodes"
57+
exit 1
58+
fi
59+
echo " API server not ready, waiting ${RETRY_DELAY}s..."
60+
sleep $RETRY_DELAY
61+
RETRY_DELAY=$((RETRY_DELAY * 2))
62+
fi
63+
done
64+
65+
# Check nodes are ready
66+
echo ""
67+
echo "📋 Node status:"
68+
kubectl get nodes
69+
70+
NOT_READY_NODES=$(kubectl get nodes --no-headers 2>/dev/null | grep -v " Ready " | wc -l || echo "0")
71+
if [ "$NOT_READY_NODES" -gt 0 ]; then
72+
echo "⚠️ Warning: Some nodes are not ready"
73+
kubectl get nodes
74+
fi
75+
76+
echo ""
77+
echo "📋 System pods status:"
78+
kubectl get pods -n kube-system
79+
80+
echo "✅ Cluster health check passed"
81+
82+
- name: Create test pod
83+
shell: bash
84+
run: |
85+
set -e # Exit on any error
86+
echo "🚀 Creating test pod with RuntimeClass: ${{ inputs.runtime-class }}"
87+
88+
cat > /tmp/test-pod.yaml <<EOF
89+
apiVersion: v1
90+
kind: Pod
91+
metadata:
92+
name: ${{ inputs.pod-name }}
93+
namespace: ${{ inputs.namespace }}
94+
labels:
95+
app: kata-test
96+
spec:
97+
runtimeClassName: ${{ inputs.runtime-class }}
98+
containers:
99+
- name: test
100+
image: docker.io/library/busybox:latest
101+
command: ['sh', '-c', 'echo "Hello from Kata Containers!" && sleep 30']
102+
restartPolicy: Never
103+
EOF
104+
105+
# Retry kubectl apply with exponential backoff
106+
MAX_RETRIES=3
107+
RETRY_DELAY=5
108+
109+
for attempt in $(seq 1 $MAX_RETRIES); do
110+
echo " Attempt $attempt/$MAX_RETRIES: Applying pod manifest..."
111+
112+
if kubectl apply -f /tmp/test-pod.yaml 2>&1; then
113+
echo "✅ Test pod created successfully"
114+
break
115+
else
116+
if [ $attempt -eq $MAX_RETRIES ]; then
117+
echo "❌ Failed to create test pod after $MAX_RETRIES attempts"
118+
echo ""
119+
echo "Checking API server:"
120+
kubectl cluster-info || true
121+
exit 1
122+
fi
123+
echo " Failed to create pod, waiting ${RETRY_DELAY}s before retry..."
124+
sleep $RETRY_DELAY
125+
RETRY_DELAY=$((RETRY_DELAY * 2))
126+
fi
127+
done
128+
129+
- name: Wait for pod
130+
shell: bash
131+
run: |
132+
set -e # Exit on any error
133+
echo "⏳ Waiting for pod to start (timeout: ${{ inputs.timeout }})..."
134+
135+
# Wait for pod to be scheduled
136+
SUCCESS=false
137+
for i in {1..30}; do
138+
POD_PHASE=$(kubectl get pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }} -o jsonpath='{.status.phase}' 2>/dev/null || echo "NotFound")
139+
echo " Attempt $i/30: Pod phase is: $POD_PHASE"
140+
141+
if [ "$POD_PHASE" = "Running" ] || [ "$POD_PHASE" = "Succeeded" ]; then
142+
echo "✅ Pod is in $POD_PHASE state"
143+
SUCCESS=true
144+
break
145+
elif [ "$POD_PHASE" = "Failed" ]; then
146+
echo "❌ Pod failed"
147+
kubectl describe pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }}
148+
exit 1
149+
fi
150+
151+
sleep 10
152+
done
153+
154+
if [ "$SUCCESS" = "false" ]; then
155+
echo "❌ Timeout: Pod did not reach Running/Succeeded state"
156+
kubectl describe pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }}
157+
exit 1
158+
fi
159+
160+
- name: Check pod status
161+
id: check-status
162+
shell: bash
163+
run: |
164+
set -e # Exit on any error
165+
echo "🔍 Checking final pod status..."
166+
167+
kubectl get pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }}
168+
169+
POD_PHASE=$(kubectl get pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }} -o jsonpath='{.status.phase}')
170+
171+
echo ""
172+
echo "Pod phase: $POD_PHASE"
173+
174+
if [ "$POD_PHASE" = "Running" ] || [ "$POD_PHASE" = "Succeeded" ]; then
175+
echo "✅ Pod reached $POD_PHASE state successfully"
176+
echo "status=success" >> $GITHUB_OUTPUT
177+
else
178+
echo "❌ Pod did not reach Running/Succeeded state (current: $POD_PHASE)"
179+
echo "status=failed" >> $GITHUB_OUTPUT
180+
kubectl describe pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }}
181+
exit 1
182+
fi
183+
184+
- name: Show pod details
185+
shell: bash
186+
run: |
187+
echo "📋 Pod details:"
188+
kubectl describe pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }}
189+
190+
- name: Show pod logs
191+
shell: bash
192+
run: |
193+
echo "📋 Pod logs:"
194+
kubectl logs ${{ inputs.pod-name }} -n ${{ inputs.namespace }} || echo "No logs available yet"
195+
196+
- name: Verify Kata runtime is used
197+
shell: bash
198+
run: |
199+
set -e # Exit on any error
200+
echo "🔍 Verifying Kata runtime is actually being used..."
201+
202+
# Get the node the pod is running on
203+
NODE=$(kubectl get pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }} -o jsonpath='{.spec.nodeName}')
204+
if [ -z "$NODE" ]; then
205+
echo "❌ Failed to get node name for pod"
206+
exit 1
207+
fi
208+
echo "Pod is running on node: $NODE"
209+
210+
# In kind, we can check the container runtime via docker
211+
if command -v docker &> /dev/null; then
212+
echo ""
213+
echo "Container processes on the node:"
214+
docker exec ${NODE} ps aux | grep -E "containerd|qemu" | head -10 || true
215+
fi
216+
217+
# Check RuntimeClass in pod spec
218+
RUNTIME_CLASS=$(kubectl get pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }} -o jsonpath='{.spec.runtimeClassName}')
219+
echo ""
220+
echo "Pod RuntimeClass: $RUNTIME_CLASS"
221+
echo "Expected RuntimeClass: ${{ inputs.runtime-class }}"
222+
223+
if [ "$RUNTIME_CLASS" = "${{ inputs.runtime-class }}" ]; then
224+
echo "✅ Pod is using the correct RuntimeClass"
225+
else
226+
echo "❌ Pod RuntimeClass mismatch!"
227+
echo " Expected: ${{ inputs.runtime-class }}"
228+
echo " Got: $RUNTIME_CLASS"
229+
kubectl describe pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }}
230+
exit 1
231+
fi
232+
233+
- name: Cleanup test pod
234+
if: always()
235+
shell: bash
236+
run: |
237+
echo "🗑️ Cleaning up test pod..."
238+
kubectl delete pod ${{ inputs.pod-name }} -n ${{ inputs.namespace }} --ignore-not-found=true
239+
echo "✅ Test pod cleaned up"

0 commit comments

Comments
 (0)