Skip to content

Commit 3656e90

Browse files
committed
Adds tests for notification bus
1 parent 0c86fcc commit 3656e90

7 files changed

Lines changed: 352 additions & 1 deletion

test/functional/base_test.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ func NovaConductorConditionGetter(name types.NamespacedName) condition.Condition
218218

219219
func CreateNovaMessageBusSecret(cell CellNames) *corev1.Secret {
220220
s := th.CreateSecret(
221-
types.NamespacedName{Namespace: cell.CellCRName.Namespace, Name: fmt.Sprintf("%s-secret", cell.TransportURLName.Name)},
221+
types.NamespacedName{
222+
Namespace: cell.CellCRName.Namespace,
223+
Name: fmt.Sprintf("%s-secret", cell.TransportURLName.Name)},
222224
map[string][]byte{
223225
"transport_url": []byte(fmt.Sprintf("rabbit://%s/fake", cell.CellName)),
224226
},
@@ -227,6 +229,19 @@ func CreateNovaMessageBusSecret(cell CellNames) *corev1.Secret {
227229
return s
228230
}
229231

232+
func CreateNotificiationTransportURLSecret(notificationsBus NotificationsBusNames) *corev1.Secret {
233+
s := th.CreateSecret(
234+
types.NamespacedName{
235+
Namespace: novaNames.NovaName.Namespace,
236+
Name: fmt.Sprintf("%s-secret", notificationsBus.BusName)},
237+
map[string][]byte{
238+
"transport_url": []byte(fmt.Sprintf("rabbit://%s/fake", notificationsBus.TransportURLName.Name)),
239+
},
240+
)
241+
logger.Info("Secret created", "name", s.Name)
242+
return s
243+
}
244+
230245
func GetDefaultNovaCellSpec(cell CellNames) map[string]interface{} {
231246
return map[string]interface{}{
232247
"cellName": cell.CellName,
@@ -474,6 +489,20 @@ func GetCellNames(novaName types.NamespacedName, cell string) CellNames {
474489
return c
475490
}
476491

492+
type NotificationsBusNames struct {
493+
BusName string
494+
TransportURLName types.NamespacedName
495+
}
496+
497+
func GetNotificationsBusNames(novaName types.NamespacedName) NotificationsBusNames {
498+
return NotificationsBusNames{
499+
BusName: "rabbitmq-broadcaster",
500+
TransportURLName: types.NamespacedName{
501+
Namespace: novaName.Namespace,
502+
Name: novaName.Name + "-notification-transport"},
503+
}
504+
}
505+
477506
type NovaNames struct {
478507
Namespace string
479508
NovaName types.NamespacedName
@@ -916,3 +945,39 @@ func GetSampleTopologySpec(label string) (map[string]interface{}, []corev1.Topol
916945
}
917946
return topologySpec, topologySpecObj
918947
}
948+
949+
func AssertNotHaveNotificationTransportURL(configData string) {
950+
951+
Expect(configData).ToNot(
952+
ContainSubstring("[notifications]"))
953+
954+
Expect(configData).To(
955+
ContainSubstring("[oslo_messaging_notifications]\ndriver = noop"))
956+
957+
}
958+
959+
func AssertHaveNotificationTransportURL(configData string, notificationsTransportURLName string) {
960+
961+
expectedConf1 := "[notifications]\nnotify_on_state_change = vm_and_task_state\nnotification_format=both"
962+
963+
expectedConf2 := fmt.Sprintf(
964+
"[oslo_messaging_notifications]\ntransport_url = rabbit://%s/fake\ndriver = messagingv2",
965+
notificationsTransportURLName)
966+
967+
Expect(configData).To(
968+
ContainSubstring(expectedConf1))
969+
970+
Expect(configData).To(
971+
ContainSubstring(expectedConf2))
972+
973+
}
974+
975+
func AssertHaveMockedNotificationTransportURL(configData string) {
976+
977+
expectedConf1 := "[notifications]\nnotify_on_state_change = vm_and_task_state\nnotification_format=both"
978+
expectedConf2 := "[oslo_messaging_notifications]\ntransport_url = rabbit://notifications/fake\ndriver = messagingv2"
979+
980+
Expect(configData).To(ContainSubstring(expectedConf1))
981+
Expect(configData).To(ContainSubstring(expectedConf2))
982+
983+
}

test/functional/nova_compute_ironic_controller_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,45 @@ var _ = Describe("NovaCompute controller", func() {
139139

140140
})
141141

142+
When("the Secret is created but notification fields is missing", func() {
143+
BeforeEach(func() {
144+
secret := &corev1.Secret{
145+
ObjectMeta: metav1.ObjectMeta{
146+
Name: cell1.InternalCellSecretName.Name,
147+
Namespace: cell1.InternalCellSecretName.Namespace,
148+
},
149+
Data: map[string][]byte{
150+
"ServicePassword": []byte("12345678"),
151+
"transport_url": []byte("rabbit://cell1/fake"),
152+
// notification_transport_url is missing
153+
},
154+
}
155+
Expect(k8sClient.Create(ctx, secret)).Should(Succeed())
156+
DeferCleanup(k8sClient.Delete, ctx, secret)
157+
})
158+
159+
It("is not Ready", func() {
160+
th.ExpectCondition(
161+
cell1.NovaComputeName,
162+
ConditionGetterFunc(NovaComputeConditionGetter),
163+
condition.ReadyCondition,
164+
corev1.ConditionFalse,
165+
)
166+
})
167+
168+
It("reports that the inputs are not ready", func() {
169+
th.ExpectConditionWithDetails(
170+
cell1.NovaComputeName,
171+
ConditionGetterFunc(NovaComputeConditionGetter),
172+
condition.InputReadyCondition,
173+
corev1.ConditionFalse,
174+
condition.ErrorReason,
175+
fmt.Sprintf("Input data error occurred field not found in Secret: 'notification_transport_url' not found in secret/%s", cell1.InternalCellSecretName.Name),
176+
)
177+
})
178+
179+
})
180+
142181
When("the Secret is created with all the expected fields", func() {
143182
BeforeEach(func() {
144183
DeferCleanup(
@@ -165,6 +204,8 @@ var _ = Describe("NovaCompute controller", func() {
165204
Expect(configDataMap).ShouldNot(BeNil())
166205
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
167206
configData := string(configDataMap.Data["01-nova.conf"])
207+
AssertHaveMockedNotificationTransportURL(configData)
208+
168209
Expect(configData).Should(
169210
ContainSubstring("transport_url=rabbit://cell1/fake"))
170211
Expect(configData).Should(

test/functional/nova_controller_test.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,125 @@ import (
3838
"github.com/openstack-k8s-operators/nova-operator/controllers"
3939
)
4040

41+
var _ = Describe("Nova controller - notifications", func() {
42+
43+
When("Nova CR instance is created", func() {
44+
BeforeEach(func() {
45+
DeferCleanup(
46+
k8sClient.Delete, ctx, CreateNovaSecret(novaNames.NovaName.Namespace, SecretName))
47+
DeferCleanup(
48+
k8sClient.Delete, ctx, CreateNovaMessageBusSecret(cell0))
49+
DeferCleanup(
50+
mariadb.DeleteDBService,
51+
mariadb.CreateDBService(
52+
novaNames.NovaName.Namespace,
53+
"openstack",
54+
corev1.ServiceSpec{
55+
Ports: []corev1.ServicePort{{Port: 3306}},
56+
},
57+
),
58+
)
59+
memcachedSpec := infra.GetDefaultMemcachedSpec()
60+
61+
DeferCleanup(infra.DeleteMemcached, infra.CreateMemcached(novaNames.NovaName.Namespace, MemcachedInstance, memcachedSpec))
62+
infra.SimulateMemcachedReady(novaNames.MemcachedNamespace)
63+
64+
DeferCleanup(keystone.DeleteKeystoneAPI, keystone.CreateKeystoneAPI(novaNames.NovaName.Namespace))
65+
66+
DeferCleanup(th.DeleteInstance, CreateNovaWithCell0(novaNames.NovaName))
67+
68+
keystone.SimulateKeystoneServiceReady(novaNames.KeystoneServiceName)
69+
mariadb.SimulateMariaDBDatabaseCompleted(novaNames.APIMariaDBDatabaseName)
70+
mariadb.SimulateMariaDBAccountCompleted(novaNames.APIMariaDBDatabaseAccount)
71+
mariadb.SimulateMariaDBDatabaseCompleted(cell0.MariaDBDatabaseName)
72+
mariadb.SimulateMariaDBAccountCompleted(cell0.MariaDBAccountName)
73+
infra.SimulateTransportURLReady(cell0.TransportURLName)
74+
SimulateReadyOfNovaTopServices()
75+
})
76+
It("notification transport url is not set", func() {
77+
78+
// assert that a the top level internal internal secret is created
79+
// with the proper data
80+
internalTopLevelSecret := th.GetSecret(novaNames.InternalTopLevelSecretName)
81+
// verify if nova secret has notification-transport-url
82+
Expect(internalTopLevelSecret.Data).To(HaveKey("notification_transport_url"))
83+
Expect(internalTopLevelSecret.Data).To(
84+
HaveKeyWithValue("notification_transport_url", []byte("")))
85+
86+
// verify if confs are updated with notification-transport-url under oslo_messaging_notifications
87+
// assert in nova-api conf
88+
configDataMap := th.GetSecret(novaNames.APIConfigDataName)
89+
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
90+
configData := string(configDataMap.Data["01-nova.conf"])
91+
AssertNotHaveNotificationTransportURL(configData)
92+
93+
// assert in sch conf
94+
configDataMap = th.GetSecret(novaNames.SchedulerConfigDataName)
95+
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
96+
configData = string(configDataMap.Data["01-nova.conf"])
97+
AssertNotHaveNotificationTransportURL(configData)
98+
99+
// assert in cell0-conductor conf
100+
configDataMap = th.GetSecret(cell0.ConductorConfigDataName)
101+
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
102+
configData = string(configDataMap.Data["01-nova.conf"])
103+
AssertNotHaveNotificationTransportURL(configData)
104+
105+
})
106+
107+
It("notification transport url is set with new rabbit", func() {
108+
109+
// add new-rabbit in Nova CR
110+
notificationsBus := GetNotificationsBusNames(novaNames.NovaName)
111+
DeferCleanup(k8sClient.Delete, ctx, CreateNotificiationTransportURLSecret(notificationsBus))
112+
113+
Eventually(func(g Gomega) {
114+
nova := GetNova(novaNames.NovaName)
115+
nova.Spec.NotificationsBusInstance = &notificationsBus.BusName
116+
g.Expect(k8sClient.Update(ctx, nova)).Should(Succeed())
117+
}, timeout, interval).Should(Succeed())
118+
119+
// as new-rabbit already exists in cluster, infra operator will create transporturl for it
120+
// simulating same
121+
infra.SimulateTransportURLReady(notificationsBus.TransportURLName)
122+
transportURLName := infra.GetTransportURL(notificationsBus.TransportURLName)
123+
Expect(transportURLName.Spec.RabbitmqClusterName).To(Equal(notificationsBus.BusName))
124+
125+
th.ExpectCondition(
126+
novaNames.NovaName,
127+
ConditionGetterFunc(NovaConditionGetter),
128+
novav1.NovaNotificationMQReadyCondition,
129+
corev1.ConditionTrue,
130+
)
131+
132+
// the nova secret(i.e top level secret) should have notification_transport_url value set
133+
internalTopLevelSecret := th.GetSecret(novaNames.InternalTopLevelSecretName)
134+
Expect(internalTopLevelSecret.Data).To(HaveKey("notification_transport_url"))
135+
Expect(internalTopLevelSecret.Data["notification_transport_url"]).ShouldNot(BeEmpty())
136+
137+
// assert in nova-api conf
138+
configDataMap := th.GetSecret(novaNames.APIConfigDataName)
139+
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
140+
configData := string(configDataMap.Data["01-nova.conf"])
141+
AssertHaveNotificationTransportURL(configData, notificationsBus.TransportURLName.Name)
142+
143+
// assert in sch conf
144+
configDataMap = th.GetSecret(novaNames.SchedulerConfigDataName)
145+
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
146+
configData = string(configDataMap.Data["01-nova.conf"])
147+
AssertHaveNotificationTransportURL(configData, notificationsBus.TransportURLName.Name)
148+
149+
// assert in cell0-conductor conf
150+
configDataMap = th.GetSecret(cell0.ConductorConfigDataName)
151+
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
152+
configData = string(configDataMap.Data["01-nova.conf"])
153+
AssertHaveNotificationTransportURL(configData, notificationsBus.TransportURLName.Name)
154+
155+
})
156+
})
157+
158+
})
159+
41160
var _ = Describe("Nova controller", func() {
42161
When("Nova CR instance is created without a proper secret", func() {
43162
BeforeEach(func() {
@@ -265,6 +384,8 @@ var _ = Describe("Nova controller", func() {
265384
HaveKeyWithValue(controllers.ServicePasswordSelector, []byte("service-password")))
266385
Expect(internalCellSecret.Data).To(
267386
HaveKeyWithValue("transport_url", []byte("rabbit://cell0/fake")))
387+
Expect(internalCellSecret.Data).To(
388+
HaveKeyWithValue("notification_transport_url", []byte("")))
268389

269390
Expect(cell.Spec.Secret).To(Equal(cell0.InternalCellSecretName.Name))
270391
Expect(conductor.Spec.Secret).To(Equal(cell0.InternalCellSecretName.Name))
@@ -381,6 +502,8 @@ var _ = Describe("Nova controller", func() {
381502
HaveKeyWithValue(controllers.MetadataSecretSelector, []byte("metadata-secret")))
382503
Expect(internalTopLevelSecret.Data).To(
383504
HaveKeyWithValue("transport_url", []byte("rabbit://cell0/fake")))
505+
Expect(internalTopLevelSecret.Data).To(
506+
HaveKeyWithValue("notification_transport_url", []byte("")))
384507
})
385508

386509
It("creates NovaAPI", func() {

test/functional/nova_scheduler_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,44 @@ var _ = Describe("NovaScheduler controller", func() {
163163
})
164164
})
165165

166+
When("the Secret is created but notification fields is missing", func() {
167+
BeforeEach(func() {
168+
secret := &corev1.Secret{
169+
ObjectMeta: metav1.ObjectMeta{
170+
Name: novaNames.InternalTopLevelSecretName.Name,
171+
Namespace: novaNames.InternalTopLevelSecretName.Namespace,
172+
},
173+
Data: map[string][]byte{
174+
"ServicePassword": []byte("12345678"),
175+
"transport_url": []byte("rabbit://api/fake"),
176+
// notification_transport_url is missing
177+
},
178+
}
179+
Expect(k8sClient.Create(ctx, secret)).Should(Succeed())
180+
DeferCleanup(k8sClient.Delete, ctx, secret)
181+
})
182+
183+
It("is not Ready", func() {
184+
th.ExpectCondition(
185+
novaNames.SchedulerName,
186+
ConditionGetterFunc(NovaSchedulerConditionGetter),
187+
condition.ReadyCondition,
188+
corev1.ConditionFalse,
189+
)
190+
})
191+
192+
It("reports that the inputs are not ready", func() {
193+
th.ExpectConditionWithDetails(
194+
novaNames.SchedulerName,
195+
ConditionGetterFunc(NovaSchedulerConditionGetter),
196+
condition.InputReadyCondition,
197+
corev1.ConditionFalse,
198+
condition.ErrorReason,
199+
fmt.Sprintf("Input data error occurred field not found in Secret: 'notification_transport_url' not found in secret/%s", novaNames.InternalTopLevelSecretName.Name),
200+
)
201+
})
202+
})
203+
166204
When("the Secret is created with all the expected fields", func() {
167205
BeforeEach(func() {
168206
DeferCleanup(
@@ -192,6 +230,8 @@ var _ = Describe("NovaScheduler controller", func() {
192230
Expect(configDataMap).ShouldNot(BeNil())
193231
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
194232
configData := string(configDataMap.Data["01-nova.conf"])
233+
AssertHaveMockedNotificationTransportURL(configData)
234+
195235
Expect(configData).To(ContainSubstring("transport_url=rabbit://api/fake"))
196236
Expect(configData).To(ContainSubstring("password = service-password"))
197237
memcacheInstance := infra.GetMemcached(novaNames.MemcachedNamespace)

test/functional/novaapi_controller_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,44 @@ var _ = Describe("NovaAPI controller", func() {
162162
})
163163
})
164164

165+
When("the Secret is created but notification_transport_url field is missing", func() {
166+
BeforeEach(func() {
167+
secret := &corev1.Secret{
168+
ObjectMeta: metav1.ObjectMeta{
169+
Name: novaNames.InternalTopLevelSecretName.Name,
170+
Namespace: novaNames.InternalTopLevelSecretName.Namespace,
171+
},
172+
Data: map[string][]byte{
173+
"ServicePassword": []byte("12345678"),
174+
"transport_url": []byte("rabbit://api/fake"),
175+
// notification_transport_url is missing
176+
},
177+
}
178+
Expect(k8sClient.Create(ctx, secret)).Should(Succeed())
179+
DeferCleanup(k8sClient.Delete, ctx, secret)
180+
})
181+
182+
It("is not Ready", func() {
183+
th.ExpectCondition(
184+
novaNames.APIName,
185+
ConditionGetterFunc(NovaAPIConditionGetter),
186+
condition.ReadyCondition,
187+
corev1.ConditionFalse,
188+
)
189+
})
190+
191+
It("reports that the inputs are not ready", func() {
192+
th.ExpectConditionWithDetails(
193+
novaNames.APIName,
194+
ConditionGetterFunc(NovaAPIConditionGetter),
195+
condition.InputReadyCondition,
196+
corev1.ConditionFalse,
197+
condition.ErrorReason,
198+
fmt.Sprintf("Input data error occurred field not found in Secret: 'notification_transport_url' not found in secret/%s", novaNames.InternalTopLevelSecretName.Name),
199+
)
200+
})
201+
})
202+
165203
When("the Secret is created with all the expected fields", func() {
166204
BeforeEach(func() {
167205
DeferCleanup(
@@ -192,6 +230,8 @@ var _ = Describe("NovaAPI controller", func() {
192230
Expect(configDataMap).ShouldNot(BeNil())
193231
Expect(configDataMap.Data).Should(HaveKey("01-nova.conf"))
194232
configData := string(configDataMap.Data["01-nova.conf"])
233+
AssertHaveMockedNotificationTransportURL(configData)
234+
195235
Expect(configData).Should(ContainSubstring("transport_url=rabbit://api/fake"))
196236
// as of I3629b84d3255a8fe9d8a7cea8c6131d7c40899e8 nova now requires
197237
// service_user configuration to work to address Bug: #2004555

0 commit comments

Comments
 (0)