Merge lp:~sseman/juju-chaos-monkey/command-validation into lp:juju-chaos-monkey
- command-validation
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John George (community) | Approve | ||
Review via email: mp+259305@code.launchpad.net |
Commit message
Description of the change
This branch adds command validation.
To post a comment you must log in.
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 |
Thank you.