Merge lp:~sseman/juju-chaos-monkey/command-validation into lp:juju-chaos-monkey

Proposed by Seman
Status: Merged
Merged at revision: 15
Proposed branch: lp:~sseman/juju-chaos-monkey/command-validation
Merge into: lp:juju-chaos-monkey
Diff against target: 291 lines (+138/-25)
5 files modified
chaos_monkey.py (+8/-0)
runner.py (+35/-16)
tests/test_chaos_monkey.py (+15/-4)
tests/test_runner.py (+78/-5)
utility.py (+2/-0)
To merge this branch: bzr merge lp:~sseman/juju-chaos-monkey/command-validation
Reviewer Review Type Date Requested Status
John George (community) Approve
Review via email: mp+259305@code.launchpad.net

Description of the change

This branch adds command validation.

To post a comment you must log in.
16. By Seman

Added command validation.

17. By Seman

Used exception rather than returning errors.

18. By Seman

Updated exception error messages.

Revision history for this message
John George (jog) wrote :

Thank you.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'chaos_monkey.py'
2--- chaos_monkey.py 2015-05-13 17:01:50 +0000
3+++ chaos_monkey.py 2015-05-19 00:17:54 +0000
4@@ -57,6 +57,14 @@
5 self.chaos.remove(group)
6
7 @staticmethod
8+ def get_all_groups():
9+ return list(set(c.group for c in ChaosMonkey.get_all_chaos()[0]))
10+
11+ @staticmethod
12+ def get_all_commands():
13+ return [c.command_str for c in ChaosMonkey.get_all_chaos()[0]]
14+
15+ @staticmethod
16 def get_groups(groups, chaos):
17 ret_groups = []
18 for group in groups:
19
20=== modified file 'runner.py'
21--- runner.py 2015-05-14 06:46:36 +0000
22+++ runner.py 2015-05-19 00:17:54 +0000
23@@ -81,10 +81,9 @@
24 if enablement_timeout < 0:
25 raise BadRequest("Invalid value for enablement timeout")
26
27- self.filter_commands(include_group=include_group,
28- exclude_group=exclude_group,
29- include_command=include_command,
30- exclude_command=exclude_command)
31+ self.filter_commands(
32+ include_group=include_group, exclude_group=exclude_group,
33+ include_command=include_command, exclude_command=exclude_command)
34 expire_time = time() + run_timeout
35 while time() < expire_time:
36 if self.stop_chaos or self.dry_run:
37@@ -106,23 +105,37 @@
38
39 def filter_commands(self, include_group=None, exclude_group=None,
40 include_command=None, exclude_command=None):
41+ all_groups = ChaosMonkey.get_all_groups()
42+ all_commands = ChaosMonkey.get_all_commands()
43+
44 # If any groups and any commands are not included, assume the intent
45 # is to include all groups and all commands.
46 if not include_group and not include_command:
47 self.chaos_monkey.include_group('all')
48 if include_group:
49- include_group = split_arg_string(include_group)
50+ include_group = self._validate(include_group, all_groups)
51 self.chaos_monkey.include_group(include_group)
52 if exclude_group:
53- exclude_group = split_arg_string(exclude_group)
54+ exclude_group = self._validate(exclude_group, all_groups)
55 self.chaos_monkey.exclude_group(exclude_group)
56 if include_command:
57- include_command = split_arg_string(include_command)
58+ include_command = self._validate(
59+ include_command, all_commands)
60 self.chaos_monkey.include_command(include_command)
61 if exclude_command:
62- exclude_command = split_arg_string(exclude_command)
63+ exclude_command = self._validate(
64+ exclude_command, all_commands)
65 self.chaos_monkey.exclude_command(exclude_command)
66
67+ @staticmethod
68+ def _validate(sub_string, all_list):
69+ sub_list = split_arg_string(sub_string)
70+ for item in sub_list:
71+ if item not in all_list:
72+ raise BadRequest(
73+ 'Invalid value given on command line: {}'.format(item))
74+ return sub_list
75+
76 def sig_handler(self, sig_num, frame):
77 """Set the stop_chaos flag, to request a safe exit."""
78 logging.info('Caught signal {}: Waiting for graceful exit.\n'.format(
79@@ -144,7 +157,7 @@
80 'path',
81 help='An existing directory, to be used as a workspace.')
82 parser.add_argument(
83- '-pt', '--enablement-timeout', default=10, type=int,
84+ '-et', '--enablement-timeout', default=10, type=int,
85 help="Enablement timeout in seconds")
86 parser.add_argument(
87 '-tt', '--total-timeout', default=60, type=int,
88@@ -174,10 +187,16 @@
89 runner.acquire_lock()
90 logging.info('Chaos monkey started in {}'.format(args.path))
91 logging.debug('Dry run is set to {}'.format(args.dry_run))
92- runner.random_chaos(run_timeout=args.total_timeout,
93- enablement_timeout=args.enablement_timeout,
94- include_group=args.include_group,
95- exclude_group=args.exclude_group,
96- include_command=args.include_command,
97- exclude_command=args.exclude_command)
98- runner.cleanup()
99+ try:
100+ runner.random_chaos(
101+ run_timeout=args.total_timeout,
102+ enablement_timeout=args.enablement_timeout,
103+ include_group=args.include_group,
104+ exclude_group=args.exclude_group,
105+ include_command=args.include_command,
106+ exclude_command=args.exclude_command)
107+ except Exception as e:
108+ logging.error('{} ({})'.format(e, type(e).__name__))
109+ sys.exit(1)
110+ finally:
111+ runner.cleanup()
112
113=== modified file 'tests/test_chaos_monkey.py'
114--- tests/test_chaos_monkey.py 2015-05-15 00:05:59 +0000
115+++ tests/test_chaos_monkey.py 2015-05-19 00:17:54 +0000
116@@ -26,7 +26,7 @@
117 cm = ChaosMonkey.factory()
118 all_chaos, all_factory_obj = cm.get_all_chaos()
119 self.assertItemsEqual(
120- self._get_all_command_str(all_chaos), self._command_strings())
121+ self._get_command_str(all_chaos), self._get_all_command_strings())
122
123 def test_run_random_chaos(self):
124 cm = ChaosMonkey.factory()
125@@ -249,7 +249,7 @@
126
127 def test_include_group_and_exclude_commands(self):
128 groups = ['net']
129- commands = ['deny-all', 'deny-ssh']
130+ commands = ['deny-all', 'deny-incoming']
131 cm = ChaosMonkey.factory()
132 cm.include_group(groups)
133 self.assertGreaterEqual(len(cm.chaos), 1)
134@@ -299,8 +299,19 @@
135 self.assertTrue(any(c.group == 'net' for c in group))
136 self.assertTrue(any(c.group == 'kill' for c in group))
137
138- def _get_all_command_str(self, chaos):
139+ def test_get_all_commands(self):
140+ all_commands = ChaosMonkey.get_all_commands()
141+ self.assertItemsEqual(all_commands, self._get_all_command_strings())
142+
143+ def test_get_all_groups(self):
144+ all_groups = ChaosMonkey.get_all_groups()
145+ self.assertItemsEqual(all_groups, self._get_all_groups())
146+
147+ def _get_command_str(self, chaos):
148 return [c.command_str for c in chaos]
149
150- def _command_strings(self):
151+ def _get_all_command_strings(self):
152 return get_all_net_commands() + get_all_kill_commands()
153+
154+ def _get_all_groups(self):
155+ return ['net', 'kill']
156
157=== modified file 'tests/test_runner.py'
158--- tests/test_runner.py 2015-05-14 06:46:36 +0000
159+++ tests/test_runner.py 2015-05-19 00:17:54 +0000
160@@ -370,7 +370,7 @@
161
162 def test_filter_commands_include_group_and_exclude_commands(self):
163 include_group = 'net'
164- exclude_command = 'deny-all,deny-ssh'
165+ exclude_command = 'deny-all,deny-incoming'
166 with temp_dir() as directory:
167 runner = Runner(directory, ChaosMonkey.factory())
168 runner.filter_commands(include_group=include_group,
169@@ -380,7 +380,7 @@
170 for c in runner.chaos_monkey.chaos))
171 self.assertTrue(all(c.command_str != 'deny-all'
172 for c in runner.chaos_monkey.chaos))
173- self.assertTrue(all(c.command_str != 'deny-ssh'
174+ self.assertTrue(all(c.command_str != 'deny-incoming'
175 for c in runner.chaos_monkey.chaos))
176
177 def test_filter_commands_exclude_group_and_exclude_commands(self):
178@@ -422,7 +422,7 @@
179 include_group = 'net,kill'
180 exclude_group = 'kill'
181 include_command = 'jujud'
182- exclude_command = 'deny-all,monogd'
183+ exclude_command = 'deny-all,mongod'
184 with temp_dir() as directory:
185 runner = Runner(directory, ChaosMonkey.factory())
186 runner.filter_commands(include_group=include_group,
187@@ -454,11 +454,11 @@
188 include_group='net,kill',
189 exclude_group='kill',
190 include_command='deny-all',
191- exclude_command='deny-ssh')
192+ exclude_command='deny-incoming')
193 expected = {'include_group': 'net,kill',
194 'exclude_group': 'kill',
195 'include_command': 'deny-all',
196- 'exclude_command': 'deny-ssh'}
197+ 'exclude_command': 'deny-incoming'}
198 call_params = f_mock.call_args_list[0][1:]
199 for k, v in call_params[0].items():
200 self.assertEqual(expected[k], v)
201@@ -469,6 +469,79 @@
202 arg = split_arg_string('net')
203 self.assertItemsEqual(arg, ['net'])
204
205+ def test_validate_group(self):
206+ groups = "net"
207+ all_groups = ChaosMonkey.get_all_groups()
208+ groups = Runner._validate(groups, all_groups)
209+ self.assertItemsEqual(groups, ['net'])
210+
211+ def test_validate_groups(self):
212+ groups = "net,kill"
213+ all_groups = ChaosMonkey.get_all_groups()
214+ groups = Runner._validate(groups, all_groups)
215+ self.assertItemsEqual(groups, ['net', 'kill'])
216+
217+ def test_validate_incorrect_group(self):
218+ groups = "net,killl"
219+ all_groups = ChaosMonkey.get_all_groups()
220+ with self.assertRaisesRegexp(
221+ BadRequest, "Invalid value given on command line: killl"):
222+ Runner._validate(groups, all_groups)
223+
224+ def test_validate_command(self):
225+ commands = "deny-all"
226+ all_commands = ChaosMonkey.get_all_commands()
227+ commands = Runner._validate(commands, all_commands)
228+ self.assertItemsEqual(commands, ['deny-all'])
229+
230+ def test_validate_commands(self):
231+ commands = "deny-all,jujud,deny-api-server"
232+ all_commands = ChaosMonkey.get_all_commands()
233+ commands = Runner._validate(commands, all_commands)
234+ self.assertItemsEqual(
235+ commands, ['deny-all', 'jujud', 'deny-api-server'])
236+
237+ def test_validate_incorrect_command(self):
238+ commands = "deny-all,monogd,deny-api-server"
239+ all_commands = ChaosMonkey.get_all_commands()
240+ with self.assertRaisesRegexp(
241+ BadRequest, "Invalid value given on command line: monogd"):
242+ Runner._validate(commands, all_commands)
243+
244+ def test_filter_commands_include_incorrect_group(self):
245+ include_group = 'net,killl'
246+ with temp_dir() as directory:
247+ runner = Runner(directory, ChaosMonkey.factory())
248+ with self.assertRaisesRegexp(
249+ BadRequest, "Invalid value given on command line: killl"):
250+ runner.filter_commands(include_group=include_group)
251+
252+ def test_filter_commands_exclude_incorrect_group(self):
253+ exclude_group = 'net,killl'
254+ with temp_dir() as directory:
255+ runner = Runner(directory, ChaosMonkey.factory())
256+ with self.assertRaisesRegexp(
257+ BadRequest, "Invalid value given on command line: killl"):
258+ runner.filter_commands(exclude_group=exclude_group)
259+
260+ def test_filter_command_include_incorrect_command(self):
261+ include_command = 'deny-all,deny-net'
262+ with temp_dir() as directory:
263+ runner = Runner(directory, ChaosMonkey.factory())
264+ with self.assertRaisesRegexp(
265+ BadRequest,
266+ "Invalid value given on command line: deny-net"):
267+ runner.filter_commands(include_command=include_command)
268+
269+ def test_filter_command_exclude_incorrect_command(self):
270+ exclude_command = 'deny-all,deny-net,jujud'
271+ with temp_dir() as directory:
272+ runner = Runner(directory, ChaosMonkey.factory())
273+ with self.assertRaisesRegexp(
274+ BadRequest,
275+ "Invalid value given on command line: deny-net"):
276+ runner.filter_commands(exclude_command=exclude_command)
277+
278
279 def add_fake_group(chaos_monkey):
280 chaos = Chaos(None, None, 'fake_group', 'fake_command_str', 'description')
281
282=== modified file 'utility.py'
283--- utility.py 2015-05-13 16:49:07 +0000
284+++ utility.py 2015-05-19 00:17:54 +0000
285@@ -50,6 +50,8 @@
286
287
288 def split_arg_string(arg_string):
289+ if not arg_string:
290+ return []
291 return arg_string.split(',') if ',' in arg_string else [arg_string]
292
293

Subscribers

People subscribed via source and target branches