Skip to content

Commit 10c5214

Browse files
committed
Add more envTests to increase coverage
The last PR regarding adding envTests added simple envTests for all controllers. This PR adds more specific tests and aims to increase test coverage and inlude more scenarios.
1 parent 9cc6562 commit 10c5214

5 files changed

Lines changed: 298 additions & 21 deletions

File tree

test/functional/ansibletest_controller_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,28 @@ var _ = Describe("AnsibleTest controller", func() {
3737
}
3838
})
3939

40+
DescribeTable("Missing Openstack resources should set InputReady to false",
41+
func(createResource func()) {
42+
createResource()
43+
DeferCleanup(th.DeleteInstance, CreateAnsibleTest(ansibleTestName, GetDefaultAnsibleTestSpec()))
44+
45+
th.ExpectCondition(
46+
ansibleTestName,
47+
ConditionGetterFunc(AnsibleTestConditionGetter),
48+
condition.InputReadyCondition,
49+
corev1.ConditionFalse,
50+
)
51+
},
52+
Entry("when config map is missing", func() {
53+
_, secret := CreateCommonOpenstackResources(namespace)
54+
Expect(k8sClient.Create(ctx, secret)).Should(Succeed())
55+
}),
56+
Entry("when secret is missing", func() {
57+
cm, _ := CreateCommonOpenstackResources(namespace)
58+
Expect(k8sClient.Create(ctx, cm)).Should(Succeed())
59+
}),
60+
)
61+
4062
When("An AnsibleTest instance is created", func() {
4163
BeforeEach(func() {
4264
openstackConfigMap, openstackSecret := CreateCommonOpenstackResources(namespace)

test/functional/base_test.go

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
)
3131

3232
const (
33+
TestOperatorConfig = "test-operator-config"
3334
OpenStackConfigMapName = "openstack-config"
3435
OpenStackConfigSecretName = "openstack-config-secret" // #nosec G101
3536
DefaultStorageClass = "local-storage"
@@ -54,7 +55,7 @@ func CreateCommonOpenstackResources(namespace string) (*corev1.ConfigMap, *corev
5455
Namespace: namespace,
5556
},
5657
Data: map[string]string{
57-
"clouds.yaml": "clouds:\n default:\n auth: {}",
58+
"clouds.yaml": "clouds:\n default:\n auth:\n username: admin",
5859
},
5960
}
6061

@@ -64,13 +65,72 @@ func CreateCommonOpenstackResources(namespace string) (*corev1.ConfigMap, *corev
6465
Namespace: namespace,
6566
},
6667
StringData: map[string]string{
67-
"secure.yaml": "clouds:\n default:\n auth: {}",
68+
"secure.yaml": "clouds:\n default:\n auth:\n password: '12345678'",
6869
},
6970
}
7071

7172
return cm, secret
7273
}
7374

75+
func CreateTestOperatorConfigMap(namespace string) *corev1.ConfigMap {
76+
return &corev1.ConfigMap{
77+
ObjectMeta: metav1.ObjectMeta{
78+
Name: TestOperatorConfig,
79+
Namespace: namespace,
80+
},
81+
Data: map[string]string{
82+
"tobiko-image": "quay.io/podified-antelope-centos9/openstack-tobiko:current-podified",
83+
"tempest-image": "quay.io/podified-antelope-centos9/openstack-tempest:current-podified",
84+
"horizontest-image": "quay.io/podified-antelope-centos9/openstack-horizontest:current-podified",
85+
"ansibletest-image": "quay.io/podified-antelope-centos9/openstack-ansibletest:current-podified",
86+
},
87+
}
88+
}
89+
90+
func GetTestOperatorPVC(namespace string, instanceName string) *corev1.PersistentVolumeClaim {
91+
var pvc corev1.PersistentVolumeClaim
92+
Eventually(func(g Gomega) {
93+
pvcList := &corev1.PersistentVolumeClaimList{}
94+
listOpts := []client.ListOption{
95+
client.InNamespace(namespace),
96+
client.MatchingLabels{
97+
"instanceName": instanceName,
98+
"operator": "test-operator",
99+
},
100+
}
101+
g.Expect(k8sClient.List(ctx, pvcList, listOpts...)).Should(Succeed())
102+
g.Expect(pvcList.Items).ToNot(BeEmpty())
103+
pvc = pvcList.Items[0]
104+
}, timeout*2, interval).Should(Succeed())
105+
return &pvc
106+
}
107+
108+
func GetTestOperatorPod(namespace string, instanceName string) *corev1.Pod {
109+
var pod corev1.Pod
110+
Eventually(func(g Gomega) {
111+
podList := &corev1.PodList{}
112+
listOpts := []client.ListOption{
113+
client.InNamespace(namespace),
114+
client.MatchingLabels{
115+
"instanceName": instanceName,
116+
"operator": "test-operator",
117+
},
118+
}
119+
g.Expect(k8sClient.List(ctx, podList, listOpts...)).Should(Succeed())
120+
g.Expect(podList.Items).To(HaveLen(1))
121+
pod = podList.Items[0]
122+
}, timeout*3, interval).Should(Succeed())
123+
return &pod
124+
}
125+
126+
func SimulatePodSucceeded(podName types.NamespacedName) {
127+
Eventually(func(g Gomega) {
128+
pod := th.GetPod(podName)
129+
pod.Status.Phase = corev1.PodSucceeded
130+
g.Expect(k8sClient.Status().Update(ctx, pod)).Should(Succeed())
131+
}, timeout*3, interval).Should(Succeed())
132+
}
133+
74134
// AnsibleTest helpers
75135
func CreateAnsibleTest(name types.NamespacedName, spec map[string]any) client.Object {
76136
raw := map[string]any{
@@ -95,11 +155,9 @@ func GetAnsibleTest(name types.NamespacedName) *testv1.AnsibleTest {
95155

96156
func GetDefaultAnsibleTestSpec() map[string]any {
97157
return map[string]any{
98-
"storageClass": "local-storage",
99-
"openStackConfigMap": "openstack-config",
100-
"openStackConfigSecret": "openstack-config-secret",
101-
"ansibleGitRepo": "https://github.com/example/test-repo",
102-
"ansiblePlaybookPath": "tests/playbook.yaml",
158+
"storageClass": DefaultStorageClass,
159+
"ansibleGitRepo": "https://github.com/example/test-repo",
160+
"ansiblePlaybookPath": "tests/playbook.yaml",
103161
}
104162
}
105163

@@ -132,7 +190,7 @@ func GetHorizonTest(name types.NamespacedName) *testv1.HorizonTest {
132190

133191
func GetDefaultHorizonTestSpec() map[string]any {
134192
return map[string]any{
135-
"storageClass": "local-storage",
193+
"storageClass": DefaultStorageClass,
136194
"adminUsername": "admin",
137195
"adminPassword": "password",
138196
"dashboardUrl": "http://horizon.example.com",
@@ -169,9 +227,7 @@ func GetTempest(name types.NamespacedName) *testv1.Tempest {
169227

170228
func GetDefaultTempestSpec() map[string]any {
171229
return map[string]any{
172-
"storageClass": "local-storage",
173-
"openStackConfigMap": "openstack-config",
174-
"openStackConfigSecret": "openstack-config-secret",
230+
"storageClass": DefaultStorageClass,
175231
"tempestRun": map[string]any{
176232
"includeList": "tempest.api.identity.v3",
177233
},
@@ -207,7 +263,7 @@ func GetTobiko(name types.NamespacedName) *testv1.Tobiko {
207263

208264
func GetDefaultTobikoSpec() map[string]any {
209265
return map[string]any{
210-
"storageClass": "local-storage",
266+
"storageClass": DefaultStorageClass,
211267
"testenv": "sanity",
212268
}
213269
}

test/functional/horizontest_controller_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,28 @@ var _ = Describe("HorizonTest controller", func() {
3737
}
3838
})
3939

40+
DescribeTable("Missing Openstack resources should set InputReady to false",
41+
func(createResource func()) {
42+
createResource()
43+
DeferCleanup(th.DeleteInstance, CreateHorizonTest(horizonTestName, GetDefaultHorizonTestSpec()))
44+
45+
th.ExpectCondition(
46+
horizonTestName,
47+
ConditionGetterFunc(HorizonTestConditionGetter),
48+
condition.InputReadyCondition,
49+
corev1.ConditionFalse,
50+
)
51+
},
52+
Entry("when config map is missing", func() {
53+
_, secret := CreateCommonOpenstackResources(namespace)
54+
Expect(k8sClient.Create(ctx, secret)).Should(Succeed())
55+
}),
56+
Entry("when secret is missing", func() {
57+
cm, _ := CreateCommonOpenstackResources(namespace)
58+
Expect(k8sClient.Create(ctx, cm)).Should(Succeed())
59+
}),
60+
)
61+
4062
When("A HorizonTest instance is created", func() {
4163
BeforeEach(func() {
4264
openstackConfigMap, openstackSecret := CreateCommonOpenstackResources(namespace)

test/functional/tempest_controller_test.go

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package functional_test
1818

1919
import (
20+
"fmt"
21+
2022
. "github.com/onsi/ginkgo/v2" //revive:disable:dot-imports
2123
. "github.com/onsi/gomega" //revive:disable:dot-imports
2224

@@ -32,12 +34,34 @@ var _ = Describe("Tempest controller", func() {
3234

3335
BeforeEach(func() {
3436
tempestName = types.NamespacedName{
35-
Name: "tempest",
37+
Name: "tempest-tests",
3638
Namespace: namespace,
3739
}
3840
})
3941

40-
When("A Tempest intance is created", func() {
42+
DescribeTable("Missing Openstack resources should set InputReady to false",
43+
func(createResource func()) {
44+
createResource()
45+
DeferCleanup(th.DeleteInstance, CreateTempest(tempestName, GetDefaultTempestSpec()))
46+
47+
th.ExpectCondition(
48+
tempestName,
49+
ConditionGetterFunc(TempestConditionGetter),
50+
condition.InputReadyCondition,
51+
corev1.ConditionFalse,
52+
)
53+
},
54+
Entry("when config map is missing", func() {
55+
_, secret := CreateCommonOpenstackResources(namespace)
56+
Expect(k8sClient.Create(ctx, secret)).Should(Succeed())
57+
}),
58+
Entry("when secret is missing", func() {
59+
cm, _ := CreateCommonOpenstackResources(namespace)
60+
Expect(k8sClient.Create(ctx, cm)).Should(Succeed())
61+
}),
62+
)
63+
64+
When("A Tempest instance is created", func() {
4165
BeforeEach(func() {
4266
openstackConfigMap, openstackSecret := CreateCommonOpenstackResources(namespace)
4367
Expect(k8sClient.Create(ctx, openstackConfigMap)).Should(Succeed())
@@ -52,13 +76,18 @@ var _ = Describe("Tempest controller", func() {
5276
}, timeout*2, interval).Should(Succeed())
5377
})
5478

55-
It("is not ready", func() {
56-
th.ExpectCondition(
57-
tempestName,
58-
ConditionGetterFunc(TempestConditionGetter),
59-
condition.ReadyCondition,
60-
corev1.ConditionUnknown,
61-
)
79+
It("should have the Spec fields initialized", func() {
80+
tempest := GetTempest(tempestName)
81+
Expect(tempest.Spec.StorageClass).Should(Equal(DefaultStorageClass))
82+
Expect(tempest.Spec.OpenStackConfigMap).Should(Equal(OpenStackConfigMapName))
83+
Expect(tempest.Spec.OpenStackConfigSecret).Should(Equal(OpenStackConfigSecretName))
84+
Expect(tempest.Spec.TempestRun.IncludeList).ShouldNot(BeEmpty())
85+
})
86+
87+
It("should have empty Status fields", func() {
88+
tempest := GetTempest(tempestName)
89+
Expect(tempest.Status.Hash).To(BeEmpty())
90+
Expect(tempest.Status.NetworkAttachments).To(BeEmpty())
6291
})
6392

6493
It("should have a finalizer", func() {
@@ -69,4 +98,75 @@ var _ = Describe("Tempest controller", func() {
6998
}, timeout, interval).Should(ContainElement("openstack.org/tempest"))
7099
})
71100
})
101+
102+
When("All dependencies are ready", func() {
103+
var customDataConfigMapName string
104+
var envVarsConfigMapName string
105+
106+
BeforeEach(func() {
107+
openstackConfigMap, openstackSecret := CreateCommonOpenstackResources(namespace)
108+
Expect(k8sClient.Create(ctx, openstackConfigMap)).Should(Succeed())
109+
Expect(k8sClient.Create(ctx, openstackSecret)).Should(Succeed())
110+
DeferCleanup(th.DeleteInstance, CreateTempest(tempestName, GetDefaultTempestSpec()))
111+
112+
customDataConfigMapName = fmt.Sprintf("%s-custom-data-s0", tempestName.Name)
113+
envVarsConfigMapName = fmt.Sprintf("%s-env-vars-s0", tempestName.Name)
114+
})
115+
116+
It("should have InputReady condition true", func() {
117+
th.ExpectCondition(
118+
tempestName,
119+
ConditionGetterFunc(TempestConditionGetter),
120+
condition.InputReadyCondition,
121+
corev1.ConditionTrue,
122+
)
123+
})
124+
125+
It("should create a PVC for logs", func() {
126+
pvc := GetTestOperatorPVC(namespace, tempestName.Name)
127+
Expect(pvc.Name).ToNot(BeEmpty())
128+
Expect(*pvc.Spec.StorageClassName).To(Equal(DefaultStorageClass))
129+
Expect(pvc.Spec.AccessModes).To(ContainElement(corev1.ReadWriteOnce))
130+
})
131+
132+
It("should create required ConfigMaps", func() {
133+
customDataCM := th.GetConfigMap(types.NamespacedName{
134+
Namespace: namespace,
135+
Name: customDataConfigMapName,
136+
})
137+
Expect(customDataCM.Data).To(HaveKey("include.txt"))
138+
139+
envVarsCM := th.GetConfigMap(types.NamespacedName{
140+
Namespace: namespace,
141+
Name: envVarsConfigMapName,
142+
})
143+
Expect(envVarsCM.Data).NotTo(BeEmpty())
144+
})
145+
146+
It("should create a pod", func() {
147+
pod := GetTestOperatorPod(namespace, tempestName.Name)
148+
Expect(pod.Name).ToNot(BeEmpty())
149+
})
150+
151+
It("should become Ready when pod succeeds", func() {
152+
pod := GetTestOperatorPod(namespace, tempestName.Name)
153+
SimulatePodSucceeded(types.NamespacedName{
154+
Namespace: namespace,
155+
Name: pod.Name,
156+
})
157+
158+
th.ExpectCondition(
159+
tempestName,
160+
ConditionGetterFunc(TempestConditionGetter),
161+
condition.DeploymentReadyCondition,
162+
corev1.ConditionTrue,
163+
)
164+
th.ExpectCondition(
165+
tempestName,
166+
ConditionGetterFunc(TempestConditionGetter),
167+
condition.ReadyCondition,
168+
corev1.ConditionTrue,
169+
)
170+
})
171+
})
72172
})

0 commit comments

Comments
 (0)