Skip to content

Commit e0a2e12

Browse files
committed
Add tests for database and distributed architecture
Signed-off-by: Dmitry Tantsur <[email protected]>
1 parent 38036a4 commit e0a2e12

File tree

3 files changed

+100
-26
lines changed

3 files changed

+100
-26
lines changed

.github/workflows/functional.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ jobs:
1414
- uses: helm/kind-action@v1
1515
with:
1616
cluster_name: kind
17-
- name: Prepare and run the tests
18-
run: NOCLEAN=1 ./test/functional.sh
19-
17+
- name: Prepare tests
18+
run: ./test/prepare.sh
19+
- name: Run tests
20+
run: cd test && go test -timeout 60m
21+
# TODO(dtantsur): turn this into a normal artifact collection
22+
- name: Show any local logs
23+
run: cat test/*.log
24+
if: always()
2025
- name: Show the deployment
2126
run: kubectl get -o yaml -n ironic-standalone-operator-system deployment/ironic-standalone-operator-controller-manager
2227
if: always()
Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,9 @@
11
#!/bin/bash
22

3-
set -x
3+
set -eux -o pipefail
44

55
IMG="${IMG:-controller:test}"
66

7-
clean_up() {
8-
cd "$(dirname $0)/.."
9-
if [[ -z "${NOCLEAN:-}" ]]; then
10-
make undeploy uninstall
11-
fi
12-
}
13-
14-
on_exit() {
15-
EXIT=$?
16-
set +e
17-
clean_up
18-
exit $EXIT
19-
}
20-
21-
clean_up
22-
trap on_exit EXIT
23-
24-
set -eu -o pipefail
25-
267
for image in ironic mariadb ironic-ipa-downloader; do
278
docker pull "quay.io/metal3-io/${image}"
289
kind load docker-image "quay.io/metal3-io/${image}"
@@ -34,4 +15,3 @@ make install deploy IMG="${IMG}"
3415

3516
kubectl wait --for=condition=Available --timeout=60s \
3617
-n ironic-standalone-operator-system deployment/ironic-standalone-operator-controller-manager
37-
cd test && go test -timeout 60m

test/suite_test.go

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package main
2020
import (
2121
"context"
2222
"fmt"
23+
"io"
2324
"math/rand"
2425
"os"
2526
"testing"
@@ -98,10 +99,34 @@ func WaitForIronic(name types.NamespacedName) *metal3api.Ironic {
9899
if cond != nil && cond.Status == metav1.ConditionTrue {
99100
return true
100101
}
102+
GinkgoWriter.Printf("Current status of Ironic: %+v\n", ironic.Status)
103+
104+
deployName := fmt.Sprintf("%s-service", name.Name)
105+
if ironic.Spec.Distributed {
106+
deploy, err := clientset.AppsV1().DaemonSets(name.Namespace).Get(ctx, deployName, metav1.GetOptions{})
107+
if err == nil {
108+
GinkgoWriter.Printf(".. status of daemon set: %+v\n", deploy.Status)
109+
} else if !k8serrors.IsNotFound(err) {
110+
Expect(err).NotTo(HaveOccurred())
111+
}
112+
} else {
113+
deploy, err := clientset.AppsV1().Deployments(name.Namespace).Get(ctx, deployName, metav1.GetOptions{})
114+
if err == nil {
115+
GinkgoWriter.Printf(".. status of deployment: %+v\n", deploy.Status)
116+
} else if !k8serrors.IsNotFound(err) {
117+
Expect(err).NotTo(HaveOccurred())
118+
}
119+
}
120+
121+
pods, err := clientset.CoreV1().Pods(name.Namespace).List(ctx, metav1.ListOptions{})
122+
Expect(err).NotTo(HaveOccurred())
123+
124+
for _, pod := range pods.Items {
125+
GinkgoWriter.Printf("... status of pod %s: %+v\n", pod.Name, pod.Status)
126+
}
101127

102-
GinkgoWriter.Printf("Current status of Ironic: %+v\n", ironic)
103128
return false
104-
}).WithTimeout(15 * time.Minute).WithPolling(10 * time.Second).Should(BeTrue())
129+
}).WithTimeout(5 * time.Minute).WithPolling(10 * time.Second).Should(BeTrue())
105130

106131
return ironic
107132
}
@@ -116,6 +141,30 @@ func VerifyIronic(ironic *metal3api.Ironic) {
116141
Expect(err).NotTo(HaveOccurred())
117142
}
118143

144+
func CollectLogs(namespace string) {
145+
GinkgoHelper()
146+
147+
pods, err := clientset.CoreV1().Pods(namespace).List(ctx, metav1.ListOptions{})
148+
Expect(err).NotTo(HaveOccurred())
149+
150+
for _, pod := range pods.Items {
151+
for _, cont := range pod.Spec.Containers {
152+
podLogOpts := corev1.PodLogOptions{Container: cont.Name}
153+
req := clientset.CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, &podLogOpts)
154+
podLogs, err := req.Stream(ctx)
155+
Expect(err).NotTo(HaveOccurred())
156+
defer podLogs.Close()
157+
158+
logFile, err := os.Create(fmt.Sprintf("%s.%s.%s.log", namespace, pod.Name, cont.Name))
159+
Expect(err).NotTo(HaveOccurred())
160+
defer logFile.Close()
161+
162+
_, err = io.Copy(logFile, podLogs)
163+
Expect(err).NotTo(HaveOccurred())
164+
}
165+
}
166+
}
167+
119168
func DeleteAndWait(ironic *metal3api.Ironic) {
120169
GinkgoHelper()
121170

@@ -177,6 +226,46 @@ var _ = Describe("Ironic object tests", func() {
177226
err := k8sClient.Create(ctx, ironic)
178227
Expect(err).NotTo(HaveOccurred())
179228
DeferCleanup(func() {
229+
CollectLogs(namespace)
230+
DeleteAndWait(ironic)
231+
})
232+
233+
ironic = WaitForIronic(name)
234+
VerifyIronic(ironic)
235+
})
236+
237+
It("creates distributed Ironic", func() {
238+
name := types.NamespacedName{
239+
Name: "test-ironic",
240+
Namespace: namespace,
241+
}
242+
243+
ironicDb := &metal3api.IronicDatabase{
244+
ObjectMeta: metav1.ObjectMeta{
245+
Name: fmt.Sprintf("%s-db", name.Name),
246+
Namespace: name.Namespace,
247+
},
248+
}
249+
250+
err := k8sClient.Create(ctx, ironicDb)
251+
Expect(err).NotTo(HaveOccurred())
252+
253+
ironic := &metal3api.Ironic{
254+
ObjectMeta: metav1.ObjectMeta{
255+
Name: name.Name,
256+
Namespace: name.Namespace,
257+
},
258+
Spec: metal3api.IronicSpec{
259+
DatabaseRef: corev1.LocalObjectReference{
260+
Name: ironicDb.Name,
261+
},
262+
Distributed: true,
263+
},
264+
}
265+
err = k8sClient.Create(ctx, ironic)
266+
Expect(err).NotTo(HaveOccurred())
267+
DeferCleanup(func() {
268+
CollectLogs(namespace)
180269
DeleteAndWait(ironic)
181270
})
182271

0 commit comments

Comments
 (0)