Merge lp:~wgrant/juju-deployer/slaughter-suboordinate-slumber into lp:juju-deployer

Proposed by William Grant
Status: Merged
Merged at revision: 201
Proposed branch: lp:~wgrant/juju-deployer/slaughter-suboordinate-slumber
Merge into: lp:juju-deployer
Diff against target: 189 lines (+17/-69)
4 files modified
deployer/action/importer.py (+7/-21)
deployer/tests/base.py (+1/-36)
deployer/tests/test_guiserver.py (+3/-7)
deployer/tests/test_importer.py (+6/-5)
To merge this branch: bzr merge lp:~wgrant/juju-deployer/slaughter-suboordinate-slumber
Reviewer Review Type Date Requested Status
Tim Van Steenburgh (community) Approve
Review via email: mp+309912@code.launchpad.net

Commit message

Refactor subordinate 60-second sleep away.

Description of the change

Refactor subordinate 60-second sleep away.

r146 caused add_units to wait 60 seconds for every subordinate service.
This was to avoid a crash when it attempted to retrieve the number of
units of the service before Juju had had a chance to include the service
in status output yet. But add_units just skips any subordinate service
anyway, so a much less slow fix is to just move the subordinate check to
the top of the loop.

I also cleaned up some tests which patched the mock environment to skip
the formerly dreadfully slow bits of add_units.

To post a comment you must log in.
Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

This is great, thanks William. I left one inline comment for your review.

review: Needs Fixing
Revision history for this message
William Grant (wgrant) :
Revision history for this message
William Grant (wgrant) :
201. By William Grant

Fix potential crash if units is None.

Revision history for this message
Tim Van Steenburgh (tvansteenburgh) wrote :

LGTM. Bonus points for the alliterate branch name.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'deployer/action/importer.py'
2--- deployer/action/importer.py 2016-09-22 14:10:50 +0000
3+++ deployer/action/importer.py 2016-11-03 12:52:41 +0000
4@@ -23,22 +23,15 @@
5 # Add units to existing services that don't match count.
6 env_status = self.env.status()
7
8- # Workaround an issue where watch output doesn't include subordinate
9- # services right away, and add_unit would fail while attempting to add
10- # units to a non-existant service. See lp:1421315 for details.
11- cur_units = 0
12 for svc in self.deployment.get_services():
13- delay = time.time() + 60
14- while delay > time.time():
15- if svc.name in env_status['services']:
16- cur_units = len(
17- (env_status['services'][svc.name].get('units') or ())
18- )
19- if cur_units > 0:
20- break
21- time.sleep(5)
22- env_status = self.env.status()
23+ charm = self.deployment.get_charm_for(svc.name)
24+ if charm.is_subordinate():
25+ self.log.warning(
26+ "Config specifies num units for subordinate: %s",
27+ svc.name)
28+ continue
29
30+ cur_units = len(env_status['services'][svc.name].get('units') or ())
31 delta = (svc.num_units - cur_units)
32
33 if delta <= 0:
34@@ -47,13 +40,6 @@
35 svc.name)
36 continue
37
38- charm = self.deployment.get_charm_for(svc.name)
39- if charm.is_subordinate():
40- self.log.warning(
41- "Config specifies num units for subordinate: %s",
42- svc.name)
43- continue
44-
45 self.log.info(
46 "Adding %d more units to %s" % (abs(delta), svc.name))
47 if svc.unit_placement:
48
49=== modified file 'deployer/tests/base.py'
50--- deployer/tests/base.py 2016-05-07 23:48:30 +0000
51+++ deployer/tests/base.py 2016-11-03 12:52:41 +0000
52@@ -1,13 +1,12 @@
53 from __future__ import absolute_import
54 import inspect
55+import itertools
56 import logging
57 import os
58 import unittest
59 import shutil
60 import tempfile
61
62-import mock
63-
64 import deployer
65 from deployer.config import ConfigStack
66
67@@ -82,37 +81,3 @@
68 os.environ.update(original_environ)
69
70 os.environ.update(kw)
71-
72-
73-def patch_env_status(env, services, machines=()):
74- """Simulate that the given mock env has the status described in services.
75-
76- This function is used so that tests do not have to wait minutes for
77- service units presence when the importer is used with the given env.
78-
79- The services argument is a dict mapping service names with the number of
80- their units. This will be reflected by the status returned when the
81- importer adds the units (see "deployer.action.importer.Importer.add_unit").
82-
83- The machines argument can be used to simulate that the given machines are
84- present in the Juju environment.
85- """
86- services_status = dict(
87- (k, {'units': dict((i, {}) for i in range(v))})
88- for k, v in services.items()
89- )
90- machines_status = dict((i, {}) for i in machines)
91- env.status.side_effect = [
92- # There are no services initially.
93- {'services': {}, 'machines': machines_status},
94- {'services': {}, 'machines': machines_status},
95- # This is the workaround check for subordinate charms presence:
96- # see lp:1421315 for details.
97- {'services': services_status, 'machines': machines_status},
98- {'services': services_status, 'machines': machines_status},
99- # After we exited the workaround loop, we can just mock further
100- # status results.
101- mock.MagicMock(),
102- mock.MagicMock(),
103- mock.MagicMock(),
104- ]
105
106=== modified file 'deployer/tests/test_guiserver.py'
107--- deployer/tests/test_guiserver.py 2016-07-12 02:29:52 +0000
108+++ deployer/tests/test_guiserver.py 2016-11-03 12:52:41 +0000
109@@ -12,10 +12,7 @@
110
111 from deployer import guiserver
112 from deployer.feedback import Feedback
113-from deployer.tests.base import (
114- patch_env_status,
115- skip_if_offline,
116-)
117+from deployer.tests.base import skip_if_offline
118
119
120 class TestGetDefaultGuiserverOptions(unittest.TestCase):
121@@ -274,8 +271,6 @@
122 def test_importer_behavior(self, mock_sleep, mock_environment):
123 # The importer executes the expected environment calls.
124 self.addCleanup(self.cleanup_series_path)
125- patch_env_status(mock_environment(), {'mysql': 1, 'wordpress': 1})
126- mock_environment.reset_mock()
127 with self.patch_juju_home():
128 self.import_bundle(version=3)
129 mock_sleep.assert_has_calls([mock.call(5.1), mock.call(60)])
130@@ -298,7 +293,8 @@
131 None, 1, None, 'precise'),
132 mock.call.set_annotation(
133 'wordpress', {'gui-y': '414.547', 'gui-x': '425.347'}),
134- mock.call.add_units('mysql', 1),
135+ mock.call.add_units('mysql', 2),
136+ mock.call.add_units('wordpress', 1),
137 mock.call.add_relation('mysql:db', 'wordpress:db'),
138 mock.call.close(),
139 ], any_order=True)
140
141=== modified file 'deployer/tests/test_importer.py'
142--- deployer/tests/test_importer.py 2016-05-07 23:48:30 +0000
143+++ deployer/tests/test_importer.py 2016-11-03 12:52:41 +0000
144@@ -8,7 +8,6 @@
145
146 from .base import (
147 Base,
148- patch_env_status,
149 skip_if_offline,
150 )
151
152@@ -56,7 +55,6 @@
153 stack = ConfigStack(self.options.configs)
154 deploy = stack.get('wiki')
155 env = mock.MagicMock()
156- patch_env_status(env, {'wiki': 1, 'db': 1})
157 importer = Importer(env, deploy, self.options)
158 importer.run()
159
160@@ -76,7 +74,6 @@
161 stack = ConfigStack(self.options.configs)
162 deploy = stack.get('wiki')
163 env = mock.MagicMock()
164- patch_env_status(env, {'wiki': 1, 'db': 1})
165 importer = Importer(env, deploy, self.options)
166 importer.run()
167 self.assertFalse(env.add_relation.called)
168@@ -90,7 +87,6 @@
169 stack = ConfigStack(self.options.configs)
170 deploy = stack.get(self.options.configs[0])
171 env = mock.MagicMock()
172- patch_env_status(env, {'mediawiki': 1, 'mysql': 1})
173 importer = Importer(env, deploy, self.options)
174 importer.run()
175
176@@ -110,7 +106,12 @@
177 stack = ConfigStack(self.options.configs)
178 deploy = stack.get(self.options.configs[0])
179 env = mock.MagicMock()
180- patch_env_status(env, {'mediawiki': 1, 'mysql': 1}, machines=[1])
181+
182+ config = {'status.return_value.get.return_value': {
183+ 1: {}
184+ }}
185+
186+ env.configure_mock(**config)
187
188 importer = Importer(env, deploy, self.options)
189 importer.run()

Subscribers

People subscribed via source and target branches