Skip to content

Commit 0d491ab

Browse files
committed
juju_utils: fix assumptions about 'subordinate-to'
Few places in the code made assumption that for subordinate charms, the 'subordinate-to' list would contain only principal charms. However that is not the case. If a suboridnate charm is related to other subordinate charms, they show up in each other's 'subordinate-to' lists. This was especially problematic in the 'get_machines_for_application' function which would end up in an infinite loop. Signed-off-by: Martin Kalcok <martin.kalcok@canonical.com>
1 parent 1655161 commit 0d491ab

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

unit_tests/utilities/test_zaza_utilities_juju.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,39 @@ def fail_on_use():
7878
self.unit2_mock.data = {'machine-id': self.machine2}
7979

8080
self.application = "app"
81+
8182
self.subordinate_application = "subordinate_application"
8283
self.subordinate_application_unit = "subordinate_application/0"
8384
self.subordinate_application_data = {
8485
"subordinate-to": [self.application]}
86+
87+
# Second subordinate app is related both to the principal application
88+
# and to the first subordinate application
89+
self.second_subordinate_application = "second_subordinate"
90+
self.second_subordinate_application_unit = "second_subordinate/0"
91+
self.second_subordinate_application_data = {
92+
"subordinate-to": [self.subordinate_application, self.application]}
93+
# Update the suboridnate list on the first subordinate as well
94+
self.subordinate_application_data['subordinate-to'].insert(
95+
0,
96+
self.second_subordinate_application
97+
)
98+
8599
self.application_data = {
86100
"units": {self.unit1: self.unit1_data},
87-
"subordinates": {self.subordinate_application_unit: {}}}
101+
"subordinates": {
102+
self.subordinate_application_unit: {},
103+
self.second_subordinate_application_unit: {},
104+
}
105+
}
88106
self.juju_status = mock.MagicMock()
89107
self.juju_status.name = "juju_status_object"
90108
self.juju_status.applications = {
91109
self.application: self.application_data,
92-
self.subordinate_application: self.subordinate_application_data}
110+
self.subordinate_application: self.subordinate_application_data,
111+
self.second_subordinate_application:
112+
self.second_subordinate_application_data,
113+
}
93114
self.juju_status.machines = {
94115
self.machine0: self.machine0_mock,
95116
self.machine1: self.machine1_mock,

zaza/utilities/juju.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,12 @@ def get_principle_applications(application_name, application_status=None,
122122
status = application_status or get_application_status(
123123
application_name,
124124
model_name=model_name)
125-
return status.get("subordinate-to")
125+
# A subodrinate application can be related to other
126+
# subordinate applications, such that they both show up in
127+
# each other's 'subordinate-to' list. We need to filter them out
128+
# from the list that we are returning.
129+
return [app for app in status.get("subordinate-to")
130+
if not is_subordinate_application(app, model_name=model_name)]
126131

127132

128133
def get_machines_for_application(application, model_name=None):
@@ -142,8 +147,15 @@ def get_machines_for_application(application, model_name=None):
142147
# libjuju juju status no longer has units for subordinate charms
143148
# Use the application it is subordinate-to to find machines
144149
if is_subordinate_application(application, model_name=model_name):
150+
principal = get_principle_applications(application,
151+
model_name=model_name)
152+
if not principal:
153+
logging.warn(f"Suboridnate application {application} is not"
154+
" related to any principal application.")
155+
return
156+
145157
yield from get_machines_for_application(
146-
status.get("subordinate-to")[0],
158+
principal[0],
147159
model_name=model_name)
148160
else:
149161
for unit in status.get("units").keys():

0 commit comments

Comments
 (0)