Merge lp:~ack/landscape-client/refactor-prompt-functions into lp:~landscape/landscape-client/trunk
- refactor-prompt-functions
- Merge into trunk
Proposed by
Alberto Donato
Status: | Merged |
---|---|
Approved by: | Alberto Donato |
Approved revision: | 943 |
Merged at revision: | 938 |
Proposed branch: | lp:~ack/landscape-client/refactor-prompt-functions |
Merge into: | lp:~landscape/landscape-client/trunk |
Diff against target: |
807 lines (+190/-168) 2 files modified
landscape/configuration.py (+52/-47) landscape/tests/test_configuration.py (+138/-121) |
To merge this branch: | bzr merge lp:~ack/landscape-client/refactor-prompt-functions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Bogdana Vereha (community) | Approve | ||
Free Ekanayaka (community) | Approve | ||
🤖 Landscape Builder | test results | Approve | |
Review via email: mp+318905@code.launchpad.net |
Commit message
Purely refactoring branch, it moves prompt_yes_no and show_help functions out of the script class, and reuse prompt_yes_no instead of duplicated code.
Description of the change
Purely refactoring branch, it moves prompt_yes_no and show_help functions out of the script class, and reuse prompt_yes_no instead of duplicated code.
Diff is big because of mock changes in tests.
Testing instructions:
run unittests
To post a comment you must log in.
Revision history for this message
🤖 Landscape Builder (landscape-builder) : | # |
review:
Abstain
(executing tests)
Revision history for this message
🤖 Landscape Builder (landscape-builder) wrote : | # |
review:
Approve
(test results)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'landscape/configuration.py' | |||
2 | --- landscape/configuration.py 2017-02-24 09:38:26 +0000 | |||
3 | +++ landscape/configuration.py 2017-03-03 12:43:19 +0000 | |||
4 | @@ -22,10 +22,13 @@ | |||
5 | 22 | from landscape.lib.twisted_util import gather_results | 22 | from landscape.lib.twisted_util import gather_results |
6 | 23 | from landscape.lib.fetch import fetch, FetchError | 23 | from landscape.lib.fetch import fetch, FetchError |
7 | 24 | from landscape.lib.bootstrap import BootstrapList, BootstrapDirectory | 24 | from landscape.lib.bootstrap import BootstrapList, BootstrapDirectory |
8 | 25 | from landscape.lib.persist import Persist | ||
9 | 25 | from landscape.reactor import LandscapeReactor | 26 | from landscape.reactor import LandscapeReactor |
10 | 26 | from landscape.broker.registration import RegistrationError | 27 | from landscape.broker.registration import RegistrationError |
11 | 27 | from landscape.broker.config import BrokerConfiguration | 28 | from landscape.broker.config import BrokerConfiguration |
12 | 28 | from landscape.broker.amp import RemoteBrokerConnector | 29 | from landscape.broker.amp import RemoteBrokerConnector |
13 | 30 | from landscape.broker.registration import Identity | ||
14 | 31 | from landscape.broker.service import BrokerService | ||
15 | 29 | 32 | ||
16 | 30 | 33 | ||
17 | 31 | class ConfigurationError(Exception): | 34 | class ConfigurationError(Exception): |
18 | @@ -47,6 +50,27 @@ | |||
19 | 47 | stream.flush() | 50 | stream.flush() |
20 | 48 | 51 | ||
21 | 49 | 52 | ||
22 | 53 | def show_help(text): | ||
23 | 54 | """Display help text.""" | ||
24 | 55 | lines = text.strip().splitlines() | ||
25 | 56 | print_text("\n" + "".join([line.strip() + "\n" for line in lines])) | ||
26 | 57 | |||
27 | 58 | |||
28 | 59 | def prompt_yes_no(message, default=True): | ||
29 | 60 | """Prompt for a yes/no question and return the answer as bool.""" | ||
30 | 61 | default_msg = "[Y/n]" if default else "[y/N]" | ||
31 | 62 | while True: | ||
32 | 63 | value = raw_input("{} {}: ".format(message, default_msg)).lower() | ||
33 | 64 | if value: | ||
34 | 65 | if value.startswith("n"): | ||
35 | 66 | return False | ||
36 | 67 | if value.startswith("y"): | ||
37 | 68 | return True | ||
38 | 69 | show_help("Invalid input.") | ||
39 | 70 | else: | ||
40 | 71 | return default | ||
41 | 72 | |||
42 | 73 | |||
43 | 50 | def get_invalid_users(users): | 74 | def get_invalid_users(users): |
44 | 51 | """ | 75 | """ |
45 | 52 | Process a string with a list of comma separated usernames, this returns | 76 | Process a string with a list of comma separated usernames, this returns |
46 | @@ -183,10 +207,6 @@ | |||
47 | 183 | def __init__(self, config): | 207 | def __init__(self, config): |
48 | 184 | self.config = config | 208 | self.config = config |
49 | 185 | 209 | ||
50 | 186 | def show_help(self, text): | ||
51 | 187 | lines = text.strip().splitlines() | ||
52 | 188 | print_text("\n" + "".join([line.strip() + "\n" for line in lines])) | ||
53 | 189 | |||
54 | 190 | def prompt_get_input(self, msg, required): | 210 | def prompt_get_input(self, msg, required): |
55 | 191 | """Prompt the user on the terminal for a value | 211 | """Prompt the user on the terminal for a value |
56 | 192 | 212 | ||
57 | @@ -199,7 +219,7 @@ | |||
58 | 199 | return value | 219 | return value |
59 | 200 | elif not required: | 220 | elif not required: |
60 | 201 | break | 221 | break |
62 | 202 | self.show_help("This option is required to configure Landscape.") | 222 | show_help("This option is required to configure Landscape.") |
63 | 203 | 223 | ||
64 | 204 | def prompt(self, option, msg, required=False): | 224 | def prompt(self, option, msg, required=False): |
65 | 205 | """Prompt the user on the terminal for a value. | 225 | """Prompt the user on the terminal for a value. |
66 | @@ -239,37 +259,20 @@ | |||
67 | 239 | value2 = getpass.getpass("Please confirm: ") | 259 | value2 = getpass.getpass("Please confirm: ") |
68 | 240 | if value: | 260 | if value: |
69 | 241 | if value != value2: | 261 | if value != value2: |
71 | 242 | self.show_help("Keys must match.") | 262 | show_help("Keys must match.") |
72 | 243 | else: | 263 | else: |
73 | 244 | setattr(self.config, option, value) | 264 | setattr(self.config, option, value) |
74 | 245 | break | 265 | break |
75 | 246 | elif default or not required: | 266 | elif default or not required: |
76 | 247 | break | 267 | break |
77 | 248 | else: | 268 | else: |
96 | 249 | self.show_help("This option is required to configure " | 269 | show_help("This option is required to configure Landscape.") |
79 | 250 | "Landscape.") | ||
80 | 251 | |||
81 | 252 | def prompt_yes_no(self, message, default=True): | ||
82 | 253 | if default: | ||
83 | 254 | default_msg = " [Y/n]" | ||
84 | 255 | else: | ||
85 | 256 | default_msg = " [y/N]" | ||
86 | 257 | while True: | ||
87 | 258 | value = raw_input(message + default_msg).lower() | ||
88 | 259 | if value: | ||
89 | 260 | if value.startswith("n"): | ||
90 | 261 | return False | ||
91 | 262 | if value.startswith("y"): | ||
92 | 263 | return True | ||
93 | 264 | self.show_help("Invalid input.") | ||
94 | 265 | else: | ||
95 | 266 | return default | ||
97 | 267 | 270 | ||
98 | 268 | def query_computer_title(self): | 271 | def query_computer_title(self): |
99 | 269 | if "computer_title" in self.config.get_command_line_options(): | 272 | if "computer_title" in self.config.get_command_line_options(): |
100 | 270 | return | 273 | return |
101 | 271 | 274 | ||
103 | 272 | self.show_help( | 275 | show_help( |
104 | 273 | """ | 276 | """ |
105 | 274 | The computer title you provide will be used to represent this | 277 | The computer title you provide will be used to represent this |
106 | 275 | computer in the Landscape user interface. It's important to use | 278 | computer in the Landscape user interface. It's important to use |
107 | @@ -283,7 +286,7 @@ | |||
108 | 283 | if "account_name" in self.config.get_command_line_options(): | 286 | if "account_name" in self.config.get_command_line_options(): |
109 | 284 | return | 287 | return |
110 | 285 | 288 | ||
112 | 286 | self.show_help( | 289 | show_help( |
113 | 287 | """ | 290 | """ |
114 | 288 | You must now specify the name of the Landscape account you | 291 | You must now specify the name of the Landscape account you |
115 | 289 | want to register this computer with. Your account name is shown | 292 | want to register this computer with. Your account name is shown |
116 | @@ -297,7 +300,7 @@ | |||
117 | 297 | if "registration_key" in command_line_options: | 300 | if "registration_key" in command_line_options: |
118 | 298 | return | 301 | return |
119 | 299 | 302 | ||
121 | 300 | self.show_help( | 303 | show_help( |
122 | 301 | """ | 304 | """ |
123 | 302 | A registration key may be associated with your Landscape | 305 | A registration key may be associated with your Landscape |
124 | 303 | account to prevent unauthorized registration attempts. This | 306 | account to prevent unauthorized registration attempts. This |
125 | @@ -316,7 +319,7 @@ | |||
126 | 316 | if "http_proxy" in options and "https_proxy" in options: | 319 | if "http_proxy" in options and "https_proxy" in options: |
127 | 317 | return | 320 | return |
128 | 318 | 321 | ||
130 | 319 | self.show_help( | 322 | show_help( |
131 | 320 | """ | 323 | """ |
132 | 321 | The Landscape client communicates with the server over HTTP and | 324 | The Landscape client communicates with the server over HTTP and |
133 | 322 | HTTPS. If your network requires you to use a proxy to access HTTP | 325 | HTTPS. If your network requires you to use a proxy to access HTTP |
134 | @@ -337,7 +340,7 @@ | |||
135 | 337 | raise ConfigurationError("Unknown system users: %s" % | 340 | raise ConfigurationError("Unknown system users: %s" % |
136 | 338 | ", ".join(invalid_users)) | 341 | ", ".join(invalid_users)) |
137 | 339 | return | 342 | return |
139 | 340 | self.show_help( | 343 | show_help( |
140 | 341 | """ | 344 | """ |
141 | 342 | Landscape has a feature which enables administrators to run | 345 | Landscape has a feature which enables administrators to run |
142 | 343 | arbitrary scripts on machines under their control. By default this | 346 | arbitrary scripts on machines under their control. By default this |
143 | @@ -351,10 +354,10 @@ | |||
144 | 351 | if included_plugins == [""]: | 354 | if included_plugins == [""]: |
145 | 352 | included_plugins = [] | 355 | included_plugins = [] |
146 | 353 | default = "ScriptExecution" in included_plugins | 356 | default = "ScriptExecution" in included_plugins |
148 | 354 | if self.prompt_yes_no(msg, default=default): | 357 | if prompt_yes_no(msg, default=default): |
149 | 355 | if "ScriptExecution" not in included_plugins: | 358 | if "ScriptExecution" not in included_plugins: |
150 | 356 | included_plugins.append("ScriptExecution") | 359 | included_plugins.append("ScriptExecution") |
152 | 357 | self.show_help( | 360 | show_help( |
153 | 358 | """ | 361 | """ |
154 | 359 | By default, scripts are restricted to the 'landscape' and | 362 | By default, scripts are restricted to the 'landscape' and |
155 | 360 | 'nobody' users. Please enter a comma-delimited list of users | 363 | 'nobody' users. Please enter a comma-delimited list of users |
156 | @@ -368,8 +371,8 @@ | |||
157 | 368 | if not invalid_users: | 371 | if not invalid_users: |
158 | 369 | break | 372 | break |
159 | 370 | else: | 373 | else: |
162 | 371 | self.show_help("Unknown system users: %s" % | 374 | show_help("Unknown system users: {}".format( |
163 | 372 | ",".join(invalid_users)) | 375 | ",".join(invalid_users))) |
164 | 373 | self.config.script_users = None | 376 | self.config.script_users = None |
165 | 374 | else: | 377 | else: |
166 | 375 | if "ScriptExecution" in included_plugins: | 378 | if "ScriptExecution" in included_plugins: |
167 | @@ -382,8 +385,9 @@ | |||
168 | 382 | if "access_group" in options: | 385 | if "access_group" in options: |
169 | 383 | return # an access group is already provided, don't ask for one | 386 | return # an access group is already provided, don't ask for one |
170 | 384 | 387 | ||
173 | 385 | self.show_help("You may provide an access group for this computer " | 388 | show_help( |
174 | 386 | "e.g. webservers.") | 389 | "You may provide an access group for this computer " |
175 | 390 | "e.g. webservers.") | ||
176 | 387 | self.prompt("access_group", "Access group", False) | 391 | self.prompt("access_group", "Access group", False) |
177 | 388 | 392 | ||
178 | 389 | def _get_invalid_tags(self, tagnames): | 393 | def _get_invalid_tags(self, tagnames): |
179 | @@ -407,19 +411,19 @@ | |||
180 | 407 | ", ".join(invalid_tags)) | 411 | ", ".join(invalid_tags)) |
181 | 408 | return | 412 | return |
182 | 409 | 413 | ||
185 | 410 | self.show_help("You may provide tags for this computer e.g. " | 414 | show_help( |
186 | 411 | "server,precise.") | 415 | "You may provide tags for this computer e.g. server,precise.") |
187 | 412 | while True: | 416 | while True: |
188 | 413 | self.prompt("tags", "Tags", False) | 417 | self.prompt("tags", "Tags", False) |
189 | 414 | if self._get_invalid_tags(self.config.tags): | 418 | if self._get_invalid_tags(self.config.tags): |
192 | 415 | self.show_help("Tag names may only contain alphanumeric " | 419 | show_help( |
193 | 416 | "characters.") | 420 | "Tag names may only contain alphanumeric characters.") |
194 | 417 | self.config.tags = None # Reset for the next prompt | 421 | self.config.tags = None # Reset for the next prompt |
195 | 418 | else: | 422 | else: |
196 | 419 | break | 423 | break |
197 | 420 | 424 | ||
198 | 421 | def show_header(self): | 425 | def show_header(self): |
200 | 422 | self.show_help( | 426 | show_help( |
201 | 423 | """ | 427 | """ |
202 | 424 | This script will interactively set up the Landscape client. It will | 428 | This script will interactively set up the Landscape client. It will |
203 | 425 | ask you a few questions about this computer and your Landscape | 429 | ask you a few questions about this computer and your Landscape |
204 | @@ -526,10 +530,11 @@ | |||
205 | 526 | if config.silent: | 530 | if config.silent: |
206 | 527 | setup_init_script_and_start_client() | 531 | setup_init_script_and_start_client() |
207 | 528 | elif not sysvconfig.is_configured_to_run(): | 532 | elif not sysvconfig.is_configured_to_run(): |
212 | 529 | answer = raw_input("\nThe Landscape client must be started " | 533 | answer = prompt_yes_no( |
213 | 530 | "on boot to operate correctly.\n\n" | 534 | "\nThe Landscape client must be started " |
214 | 531 | "Start Landscape client on boot? (Y/n): ") | 535 | "on boot to operate correctly.\n\n" |
215 | 532 | if not answer.upper().startswith("N"): | 536 | "Start Landscape client on boot?") |
216 | 537 | if answer: | ||
217 | 533 | setup_init_script_and_start_client() | 538 | setup_init_script_and_start_client() |
218 | 534 | else: | 539 | else: |
219 | 535 | sys.exit("Aborting Landscape configuration") | 540 | sys.exit("Aborting Landscape configuration") |
220 | @@ -774,9 +779,9 @@ | |||
221 | 774 | report_registration_outcome(result, print=print) | 779 | report_registration_outcome(result, print=print) |
222 | 775 | sys.exit(determine_exit_code(result)) | 780 | sys.exit(determine_exit_code(result)) |
223 | 776 | else: | 781 | else: |
227 | 777 | answer = raw_input("\nRequest a new registration for " | 782 | answer = prompt_yes_no( |
228 | 778 | "this computer now? (Y/n): ") | 783 | "\nRequest a new registration for this computer now?") |
229 | 779 | if not answer.upper().startswith("N"): | 784 | if answer: |
230 | 780 | result = register(config, reactor) | 785 | result = register(config, reactor) |
231 | 781 | report_registration_outcome(result, print=print) | 786 | report_registration_outcome(result, print=print) |
232 | 782 | sys.exit(determine_exit_code(result)) | 787 | sys.exit(determine_exit_code(result)) |
233 | 783 | 788 | ||
234 | === modified file 'landscape/tests/test_configuration.py' | |||
235 | --- landscape/tests/test_configuration.py 2017-02-24 10:09:22 +0000 | |||
236 | +++ landscape/tests/test_configuration.py 2017-03-03 12:43:19 +0000 | |||
237 | @@ -15,7 +15,7 @@ | |||
238 | 15 | from landscape.configuration import ( | 15 | from landscape.configuration import ( |
239 | 16 | print_text, LandscapeSetupScript, LandscapeSetupConfiguration, | 16 | print_text, LandscapeSetupScript, LandscapeSetupConfiguration, |
240 | 17 | register, setup, main, setup_init_script_and_start_client, | 17 | register, setup, main, setup_init_script_and_start_client, |
242 | 18 | ConfigurationError, | 18 | ConfigurationError, prompt_yes_no, show_help, |
243 | 19 | ImportOptionError, store_public_key_data, | 19 | ImportOptionError, store_public_key_data, |
244 | 20 | bootstrap_tree, got_connection, success, failure, exchange_failure, | 20 | bootstrap_tree, got_connection, success, failure, exchange_failure, |
245 | 21 | handle_registration_errors, done, got_error, report_registration_outcome, | 21 | handle_registration_errors, done, got_error, report_registration_outcome, |
246 | @@ -217,6 +217,50 @@ | |||
247 | 217 | self.assertEqual("Hi!END", stdout.getvalue()) | 217 | self.assertEqual("Hi!END", stdout.getvalue()) |
248 | 218 | 218 | ||
249 | 219 | 219 | ||
250 | 220 | class PromptYesNoTest(unittest.TestCase): | ||
251 | 221 | |||
252 | 222 | def test_prompt_yes_no(self): | ||
253 | 223 | """ | ||
254 | 224 | prompt_yes_no prompts a question and returns a boolean with the answer. | ||
255 | 225 | """ | ||
256 | 226 | comparisons = [("Y", True), | ||
257 | 227 | ("y", True), | ||
258 | 228 | ("yEs", True), | ||
259 | 229 | ("YES", True), | ||
260 | 230 | ("n", False), | ||
261 | 231 | ("N", False), | ||
262 | 232 | ("No", False), | ||
263 | 233 | ("no", False), | ||
264 | 234 | ("", True)] | ||
265 | 235 | |||
266 | 236 | for input_string, result in comparisons: | ||
267 | 237 | with mock.patch("__builtin__.raw_input", | ||
268 | 238 | return_value=input_string) as mock_raw_input: | ||
269 | 239 | prompt_yes_no("Foo") | ||
270 | 240 | mock_raw_input.assert_called_once_with("Foo [Y/n]: ") | ||
271 | 241 | |||
272 | 242 | @mock.patch("__builtin__.raw_input", return_value="") | ||
273 | 243 | def test_prompt_yes_no_default(self, mock_raw_input): | ||
274 | 244 | self.assertFalse(prompt_yes_no("Foo", default=False)) | ||
275 | 245 | mock_raw_input.assert_called_once_with("Foo [y/N]: ") | ||
276 | 246 | |||
277 | 247 | @mock.patch("__builtin__.raw_input", side_effect=("x", "n")) | ||
278 | 248 | @mock.patch("landscape.configuration.show_help") | ||
279 | 249 | def test_prompt_yes_no_invalid(self, mock_show_help, mock_raw_input): | ||
280 | 250 | self.assertFalse(prompt_yes_no("Foo")) | ||
281 | 251 | mock_show_help.assert_called_once_with("Invalid input.") | ||
282 | 252 | calls = [mock.call("Foo [Y/n]: "), mock.call("Foo [Y/n]: ")] | ||
283 | 253 | mock_raw_input.assert_has_calls(calls) | ||
284 | 254 | |||
285 | 255 | |||
286 | 256 | class ShowHelpTest(unittest.TestCase): | ||
287 | 257 | |||
288 | 258 | @mock.patch("landscape.configuration.print_text") | ||
289 | 259 | def test_show_help(self, mock_print_text): | ||
290 | 260 | show_help("\n\n \n Hello \n \n world! \n \n\n") | ||
291 | 261 | mock_print_text.assert_called_once_with("\nHello\n\nworld!\n") | ||
292 | 262 | |||
293 | 263 | |||
294 | 220 | class LandscapeSetupScriptTest(LandscapeTest): | 264 | class LandscapeSetupScriptTest(LandscapeTest): |
295 | 221 | 265 | ||
296 | 222 | def setUp(self): | 266 | def setUp(self): |
297 | @@ -228,11 +272,6 @@ | |||
298 | 228 | self.config = MyLandscapeSetupConfiguration() | 272 | self.config = MyLandscapeSetupConfiguration() |
299 | 229 | self.script = LandscapeSetupScript(self.config) | 273 | self.script = LandscapeSetupScript(self.config) |
300 | 230 | 274 | ||
301 | 231 | @mock.patch("landscape.configuration.print_text") | ||
302 | 232 | def test_show_help(self, mock_print_text): | ||
303 | 233 | self.script.show_help("\n\n \n Hello \n \n world! \n \n\n") | ||
304 | 234 | mock_print_text.assert_called_once_with("\nHello\n\nworld!\n") | ||
305 | 235 | |||
306 | 236 | @mock.patch("__builtin__.raw_input", return_value="Desktop") | 275 | @mock.patch("__builtin__.raw_input", return_value="Desktop") |
307 | 237 | def test_prompt_simple(self, mock_raw_input): | 276 | def test_prompt_simple(self, mock_raw_input): |
308 | 238 | self.script.prompt("computer_title", "Message") | 277 | self.script.prompt("computer_title", "Message") |
309 | @@ -248,10 +287,10 @@ | |||
310 | 248 | self.assertEqual(self.config.computer_title, "default") | 287 | self.assertEqual(self.config.computer_title, "default") |
311 | 249 | 288 | ||
312 | 250 | @mock.patch("__builtin__.raw_input", side_effect=("", "Desktop")) | 289 | @mock.patch("__builtin__.raw_input", side_effect=("", "Desktop")) |
315 | 251 | def test_prompt_with_required(self, mock_raw_input): | 290 | @mock.patch("landscape.configuration.show_help") |
316 | 252 | self.script.show_help = mock.Mock() | 291 | def test_prompt_with_required(self, mock_show_help, mock_raw_input): |
317 | 253 | self.script.prompt("computer_title", "Message", True) | 292 | self.script.prompt("computer_title", "Message", True) |
319 | 254 | self.script.show_help.assert_called_once_with( | 293 | mock_show_help.assert_called_once_with( |
320 | 255 | "This option is required to configure Landscape.") | 294 | "This option is required to configure Landscape.") |
321 | 256 | 295 | ||
322 | 257 | calls = [mock.call("Message: "), mock.call("Message: ")] | 296 | calls = [mock.call("Message: "), mock.call("Message: ")] |
323 | @@ -286,71 +325,41 @@ | |||
324 | 286 | mock_getpass.assert_has_calls(calls) | 325 | mock_getpass.assert_has_calls(calls) |
325 | 287 | self.assertEqual(self.config.registration_key, "password") | 326 | self.assertEqual(self.config.registration_key, "password") |
326 | 288 | 327 | ||
327 | 328 | @mock.patch("landscape.configuration.show_help") | ||
328 | 289 | @mock.patch("landscape.configuration.getpass.getpass", | 329 | @mock.patch("landscape.configuration.getpass.getpass", |
329 | 290 | side_effect=("password", "", "password", "password")) | 330 | side_effect=("password", "", "password", "password")) |
333 | 291 | def test_password_prompt_simple_non_matching(self, mock_getpass): | 331 | def test_password_prompt_simple_non_matching(self, mock_getpass, |
334 | 292 | self.script.show_help = mock.Mock() | 332 | mock_show_help): |
332 | 293 | |||
335 | 294 | self.script.password_prompt("registration_key", "Password") | 333 | self.script.password_prompt("registration_key", "Password") |
336 | 295 | 334 | ||
337 | 296 | calls = [mock.call("Password: "), mock.call("Please confirm: "), | 335 | calls = [mock.call("Password: "), mock.call("Please confirm: "), |
338 | 297 | mock.call("Password: "), mock.call("Please confirm: ")] | 336 | mock.call("Password: "), mock.call("Please confirm: ")] |
339 | 298 | mock_getpass.assert_has_calls(calls) | 337 | mock_getpass.assert_has_calls(calls) |
341 | 299 | self.script.show_help.assert_called_once_with("Keys must match.") | 338 | mock_show_help.assert_called_once_with("Keys must match.") |
342 | 300 | self.assertEqual(self.config.registration_key, "password") | 339 | self.assertEqual(self.config.registration_key, "password") |
343 | 301 | 340 | ||
344 | 341 | @mock.patch("landscape.configuration.show_help") | ||
345 | 302 | @mock.patch("landscape.configuration.getpass.getpass", | 342 | @mock.patch("landscape.configuration.getpass.getpass", |
346 | 303 | side_effect=("", "password", "password")) | 343 | side_effect=("", "password", "password")) |
350 | 304 | def test_password_prompt_simple_matching_required(self, mock_getpass): | 344 | def test_password_prompt_simple_matching_required(self, mock_getpass, |
351 | 305 | self.script.show_help = mock.Mock() | 345 | mock_show_help): |
349 | 306 | |||
352 | 307 | self.script.password_prompt("registration_key", "Password", True) | 346 | self.script.password_prompt("registration_key", "Password", True) |
353 | 308 | 347 | ||
354 | 309 | calls = [mock.call("Password: "), mock.call("Password: "), | 348 | calls = [mock.call("Password: "), mock.call("Password: "), |
355 | 310 | mock.call("Please confirm: ")] | 349 | mock.call("Please confirm: ")] |
356 | 311 | mock_getpass.assert_has_calls(calls) | 350 | mock_getpass.assert_has_calls(calls) |
358 | 312 | self.script.show_help.assert_called_once_with( | 351 | mock_show_help.assert_called_once_with( |
359 | 313 | "This option is required to configure Landscape.") | 352 | "This option is required to configure Landscape.") |
360 | 314 | self.assertEqual(self.config.registration_key, "password") | 353 | self.assertEqual(self.config.registration_key, "password") |
361 | 315 | 354 | ||
393 | 316 | def test_prompt_yes_no(self): | 355 | @mock.patch("landscape.configuration.show_help") |
394 | 317 | comparisons = [("Y", True), | 356 | def test_query_computer_title(self, mock_show_help): |
364 | 318 | ("y", True), | ||
365 | 319 | ("yEs", True), | ||
366 | 320 | ("YES", True), | ||
367 | 321 | ("n", False), | ||
368 | 322 | ("N", False), | ||
369 | 323 | ("No", False), | ||
370 | 324 | ("no", False), | ||
371 | 325 | ("", True)] | ||
372 | 326 | |||
373 | 327 | for input_string, result in comparisons: | ||
374 | 328 | with mock.patch("__builtin__.raw_input", | ||
375 | 329 | return_value=input_string) as mock_raw_input: | ||
376 | 330 | self.script.prompt_yes_no("Foo") | ||
377 | 331 | mock_raw_input.assert_called_once_with("Foo [Y/n]") | ||
378 | 332 | |||
379 | 333 | @mock.patch("__builtin__.raw_input", return_value="") | ||
380 | 334 | def test_prompt_yes_no_default(self, mock_raw_input): | ||
381 | 335 | self.assertFalse(self.script.prompt_yes_no("Foo", default=False)) | ||
382 | 336 | mock_raw_input.assert_called_once_with("Foo [y/N]") | ||
383 | 337 | |||
384 | 338 | @mock.patch("__builtin__.raw_input", side_effect=("x", "n")) | ||
385 | 339 | def test_prompt_yes_no_invalid(self, mock_raw_input): | ||
386 | 340 | self.script.show_help = mock.Mock() | ||
387 | 341 | self.assertFalse(self.script.prompt_yes_no("Foo")) | ||
388 | 342 | self.script.show_help.assert_called_once_with("Invalid input.") | ||
389 | 343 | calls = [mock.call("Foo [Y/n]"), mock.call("Foo [Y/n]")] | ||
390 | 344 | mock_raw_input.assert_has_calls(calls) | ||
391 | 345 | |||
392 | 346 | def test_query_computer_title(self): | ||
395 | 347 | help_snippet = "The computer title you" | 357 | help_snippet = "The computer title you" |
396 | 348 | self.script.show_help = mock.Mock() | ||
397 | 349 | self.script.prompt = mock.Mock() | 358 | self.script.prompt = mock.Mock() |
398 | 350 | self.script.query_computer_title() | 359 | self.script.query_computer_title() |
399 | 351 | self.script.prompt.assert_called_once_with( | 360 | self.script.prompt.assert_called_once_with( |
400 | 352 | "computer_title", "This computer's title", True) | 361 | "computer_title", "This computer's title", True) |
402 | 353 | [call] = self.script.show_help.mock_calls | 362 | [call] = mock_show_help.mock_calls |
403 | 354 | self.assertTrue(call.strip().startswith(help_snippet)) | 363 | self.assertTrue(call.strip().startswith(help_snippet)) |
404 | 355 | 364 | ||
405 | 356 | @mock.patch("__builtin__.raw_input") | 365 | @mock.patch("__builtin__.raw_input") |
406 | @@ -360,14 +369,14 @@ | |||
407 | 360 | self.script.query_computer_title() | 369 | self.script.query_computer_title() |
408 | 361 | mock_raw_input.assert_not_called() | 370 | mock_raw_input.assert_not_called() |
409 | 362 | 371 | ||
411 | 363 | def test_query_account_name(self): | 372 | @mock.patch("landscape.configuration.show_help") |
412 | 373 | def test_query_account_name(self, mock_show_help): | ||
413 | 364 | help_snippet = "You must now specify the name of the Landscape account" | 374 | help_snippet = "You must now specify the name of the Landscape account" |
414 | 365 | self.script.show_help = mock.Mock() | ||
415 | 366 | self.script.prompt = mock.Mock() | 375 | self.script.prompt = mock.Mock() |
416 | 367 | self.script.query_account_name() | 376 | self.script.query_account_name() |
417 | 368 | self.script.prompt.assert_called_once_with( | 377 | self.script.prompt.assert_called_once_with( |
418 | 369 | "account_name", "Account name", True) | 378 | "account_name", "Account name", True) |
420 | 370 | [call] = self.script.show_help.mock_calls | 379 | [call] = mock_show_help.mock_calls |
421 | 371 | self.assertTrue(call.strip().startswith(help_snippet)) | 380 | self.assertTrue(call.strip().startswith(help_snippet)) |
422 | 372 | 381 | ||
423 | 373 | self.script.query_account_name() | 382 | self.script.query_account_name() |
424 | @@ -378,14 +387,14 @@ | |||
425 | 378 | self.script.query_account_name() | 387 | self.script.query_account_name() |
426 | 379 | mock_raw_input.assert_not_called() | 388 | mock_raw_input.assert_not_called() |
427 | 380 | 389 | ||
429 | 381 | def test_query_registration_key(self): | 390 | @mock.patch("landscape.configuration.show_help") |
430 | 391 | def test_query_registration_key(self, mock_show_help): | ||
431 | 382 | help_snippet = "A registration key may be" | 392 | help_snippet = "A registration key may be" |
432 | 383 | self.script.show_help = mock.Mock() | ||
433 | 384 | self.script.password_prompt = mock.Mock() | 393 | self.script.password_prompt = mock.Mock() |
434 | 385 | self.script.query_registration_key() | 394 | self.script.query_registration_key() |
435 | 386 | self.script.password_prompt.assert_called_once_with( | 395 | self.script.password_prompt.assert_called_once_with( |
436 | 387 | "registration_key", "Account registration key") | 396 | "registration_key", "Account registration key") |
438 | 388 | [call] = self.script.show_help.mock_calls | 397 | [call] = mock_show_help.mock_calls |
439 | 389 | self.assertTrue(call.strip().startswith(help_snippet)) | 398 | self.assertTrue(call.strip().startswith(help_snippet)) |
440 | 390 | 399 | ||
441 | 391 | @mock.patch("landscape.configuration.getpass.getpass") | 400 | @mock.patch("landscape.configuration.getpass.getpass") |
442 | @@ -395,16 +404,16 @@ | |||
443 | 395 | self.script.query_registration_key() | 404 | self.script.query_registration_key() |
444 | 396 | mock_getpass.assert_not_called() | 405 | mock_getpass.assert_not_called() |
445 | 397 | 406 | ||
447 | 398 | def test_query_proxies(self): | 407 | @mock.patch("landscape.configuration.show_help") |
448 | 408 | def test_query_proxies(self, mock_show_help): | ||
449 | 399 | help_snippet = "The Landscape client communicates" | 409 | help_snippet = "The Landscape client communicates" |
450 | 400 | self.script.show_help = mock.Mock() | ||
451 | 401 | self.script.prompt = mock.Mock() | 410 | self.script.prompt = mock.Mock() |
452 | 402 | 411 | ||
453 | 403 | self.script.query_proxies() | 412 | self.script.query_proxies() |
454 | 404 | calls = [mock.call("http_proxy", "HTTP proxy URL"), | 413 | calls = [mock.call("http_proxy", "HTTP proxy URL"), |
455 | 405 | mock.call("https_proxy", "HTTPS proxy URL")] | 414 | mock.call("https_proxy", "HTTPS proxy URL")] |
456 | 406 | self.script.prompt.assert_has_calls(calls) | 415 | self.script.prompt.assert_has_calls(calls) |
458 | 407 | [call] = self.script.show_help.mock_calls | 416 | [call] = mock_show_help.mock_calls |
459 | 408 | self.assertTrue(call.strip().startswith(help_snippet)) | 417 | self.assertTrue(call.strip().startswith(help_snippet)) |
460 | 409 | 418 | ||
461 | 410 | @mock.patch("__builtin__.raw_input") | 419 | @mock.patch("__builtin__.raw_input") |
462 | @@ -414,53 +423,53 @@ | |||
463 | 414 | self.script.query_proxies() | 423 | self.script.query_proxies() |
464 | 415 | mock_raw_input.assert_not_called() | 424 | mock_raw_input.assert_not_called() |
465 | 416 | 425 | ||
467 | 417 | def test_query_http_proxy_defined_on_command_line(self): | 426 | @mock.patch("landscape.configuration.show_help") |
468 | 427 | def test_query_http_proxy_defined_on_command_line(self, mock_show_help): | ||
469 | 418 | help_snippet = "The Landscape client communicates" | 428 | help_snippet = "The Landscape client communicates" |
470 | 419 | self.script.show_help = mock.Mock() | ||
471 | 420 | self.script.prompt = mock.Mock() | 429 | self.script.prompt = mock.Mock() |
472 | 421 | 430 | ||
473 | 422 | self.config.load_command_line(["--http-proxy", "localhost:8080"]) | 431 | self.config.load_command_line(["--http-proxy", "localhost:8080"]) |
474 | 423 | self.script.query_proxies() | 432 | self.script.query_proxies() |
476 | 424 | [call] = self.script.show_help.mock_calls | 433 | [call] = mock_show_help.mock_calls |
477 | 425 | self.assertTrue(call.strip().startswith(help_snippet)) | 434 | self.assertTrue(call.strip().startswith(help_snippet)) |
478 | 426 | 435 | ||
480 | 427 | def test_query_https_proxy_defined_on_command_line(self): | 436 | @mock.patch("landscape.configuration.show_help") |
481 | 437 | def test_query_https_proxy_defined_on_command_line(self, mock_show_help): | ||
482 | 428 | help_snippet = "The Landscape client communicates" | 438 | help_snippet = "The Landscape client communicates" |
483 | 429 | self.script.show_help = mock.Mock() | ||
484 | 430 | self.script.prompt = mock.Mock() | 439 | self.script.prompt = mock.Mock() |
485 | 431 | self.config.load_command_line(["--https-proxy", "localhost:8443"]) | 440 | self.config.load_command_line(["--https-proxy", "localhost:8443"]) |
486 | 432 | self.script.query_proxies() | 441 | self.script.query_proxies() |
487 | 433 | self.script.prompt.assert_called_once_with( | 442 | self.script.prompt.assert_called_once_with( |
488 | 434 | "http_proxy", "HTTP proxy URL") | 443 | "http_proxy", "HTTP proxy URL") |
490 | 435 | [call] = self.script.show_help.mock_calls | 444 | [call] = mock_show_help.mock_calls |
491 | 436 | self.assertTrue(call.strip().startswith(help_snippet)) | 445 | self.assertTrue(call.strip().startswith(help_snippet)) |
492 | 437 | 446 | ||
494 | 438 | def test_query_script_plugin_no(self): | 447 | @mock.patch("landscape.configuration.show_help") |
495 | 448 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=False) | ||
496 | 449 | def test_query_script_plugin_no(self, mock_prompt_yes_no, mock_show_help): | ||
497 | 439 | help_snippet = "Landscape has a feature which enables administrators" | 450 | help_snippet = "Landscape has a feature which enables administrators" |
498 | 440 | self.script.show_help = mock.Mock() | ||
499 | 441 | self.script.prompt_yes_no = mock.Mock(return_value=False) | ||
500 | 442 | 451 | ||
501 | 443 | self.script.query_script_plugin() | 452 | self.script.query_script_plugin() |
502 | 444 | self.assertEqual(self.config.include_manager_plugins, "") | 453 | self.assertEqual(self.config.include_manager_plugins, "") |
504 | 445 | self.script.prompt_yes_no.assert_called_once_with( | 454 | mock_prompt_yes_no.assert_called_once_with( |
505 | 446 | "Enable script execution?", default=False) | 455 | "Enable script execution?", default=False) |
507 | 447 | [call] = self.script.show_help.mock_calls | 456 | [call] = mock_show_help.mock_calls |
508 | 448 | self.assertTrue(call.strip().startswith(help_snippet)) | 457 | self.assertTrue(call.strip().startswith(help_snippet)) |
509 | 449 | 458 | ||
511 | 450 | def test_query_script_plugin_yes(self): | 459 | @mock.patch("landscape.configuration.show_help") |
512 | 460 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=True) | ||
513 | 461 | def test_query_script_plugin_yes(self, mock_prompt_yes_no, mock_show_help): | ||
514 | 451 | """ | 462 | """ |
515 | 452 | If the user *does* want script execution, then the script asks which | 463 | If the user *does* want script execution, then the script asks which |
516 | 453 | users to enable it for. | 464 | users to enable it for. |
517 | 454 | """ | 465 | """ |
518 | 455 | help_snippet = "Landscape has a feature which enables administrators" | 466 | help_snippet = "Landscape has a feature which enables administrators" |
519 | 456 | self.script.show_help = mock.Mock() | ||
520 | 457 | self.script.prompt_yes_no = mock.Mock(return_value=True) | ||
521 | 458 | self.script.prompt = mock.Mock() | 467 | self.script.prompt = mock.Mock() |
522 | 459 | 468 | ||
523 | 460 | self.script.query_script_plugin() | 469 | self.script.query_script_plugin() |
525 | 461 | self.script.prompt_yes_no.assert_called_once_with( | 470 | mock_prompt_yes_no.assert_called_once_with( |
526 | 462 | "Enable script execution?", default=False) | 471 | "Enable script execution?", default=False) |
528 | 463 | first_call, second_call = self.script.show_help.mock_calls | 472 | first_call, second_call = mock_show_help.mock_calls |
529 | 464 | self.assertTrue(first_call.strip().startswith(help_snippet)) | 473 | self.assertTrue(first_call.strip().startswith(help_snippet)) |
530 | 465 | self.assertTrue(second_call.strip().startswith( | 474 | self.assertTrue(second_call.strip().startswith( |
531 | 466 | "By default, scripts are restricted")) | 475 | "By default, scripts are restricted")) |
532 | @@ -470,56 +479,58 @@ | |||
533 | 470 | self.assertEqual(self.config.include_manager_plugins, | 479 | self.assertEqual(self.config.include_manager_plugins, |
534 | 471 | "ScriptExecution") | 480 | "ScriptExecution") |
535 | 472 | 481 | ||
537 | 473 | def test_disable_script_plugin(self): | 482 | @mock.patch("landscape.configuration.show_help") |
538 | 483 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=False) | ||
539 | 484 | def test_disable_script_plugin(self, mock_prompt_yes_no, mock_show_help): | ||
540 | 474 | """ | 485 | """ |
541 | 475 | Answering NO to enabling the script plugin while it's already enabled | 486 | Answering NO to enabling the script plugin while it's already enabled |
542 | 476 | will disable it. | 487 | will disable it. |
543 | 477 | """ | 488 | """ |
544 | 478 | self.config.include_manager_plugins = "ScriptExecution" | 489 | self.config.include_manager_plugins = "ScriptExecution" |
545 | 479 | help_snippet = "Landscape has a feature which enables administrators" | 490 | help_snippet = "Landscape has a feature which enables administrators" |
546 | 480 | self.script.show_help = mock.Mock() | ||
547 | 481 | self.script.prompt_yes_no = mock.Mock(return_value=False) | ||
548 | 482 | 491 | ||
549 | 483 | self.script.query_script_plugin() | 492 | self.script.query_script_plugin() |
551 | 484 | self.script.prompt_yes_no.assert_called_once_with( | 493 | mock_prompt_yes_no.assert_called_once_with( |
552 | 485 | "Enable script execution?", default=True) | 494 | "Enable script execution?", default=True) |
553 | 486 | self.assertEqual(self.config.include_manager_plugins, "") | 495 | self.assertEqual(self.config.include_manager_plugins, "") |
555 | 487 | [call] = self.script.show_help.mock_calls | 496 | [call] = mock_show_help.mock_calls |
556 | 488 | self.assertTrue(call.strip().startswith(help_snippet)) | 497 | self.assertTrue(call.strip().startswith(help_snippet)) |
557 | 489 | 498 | ||
559 | 490 | def test_disabling_script_plugin_leaves_existing_inclusions(self): | 499 | @mock.patch("landscape.configuration.show_help") |
560 | 500 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=False) | ||
561 | 501 | def test_disabling_script_plugin_leaves_existing_inclusions( | ||
562 | 502 | self, mock_prompt_yes_no, mock_show_help): | ||
563 | 491 | """ | 503 | """ |
564 | 492 | Disabling the script execution plugin doesn't remove other included | 504 | Disabling the script execution plugin doesn't remove other included |
565 | 493 | plugins. | 505 | plugins. |
566 | 494 | """ | 506 | """ |
567 | 495 | self.config.include_manager_plugins = "FooPlugin, ScriptExecution" | 507 | self.config.include_manager_plugins = "FooPlugin, ScriptExecution" |
568 | 496 | self.script.show_help = mock.Mock() | ||
569 | 497 | self.script.prompt_yes_no = mock.Mock(return_value=False) | ||
570 | 498 | 508 | ||
571 | 499 | self.script.query_script_plugin() | 509 | self.script.query_script_plugin() |
573 | 500 | self.script.prompt_yes_no.assert_called_once_with( | 510 | mock_prompt_yes_no.assert_called_once_with( |
574 | 501 | "Enable script execution?", default=True) | 511 | "Enable script execution?", default=True) |
575 | 502 | self.assertEqual(self.config.include_manager_plugins, "FooPlugin") | 512 | self.assertEqual(self.config.include_manager_plugins, "FooPlugin") |
577 | 503 | self.script.show_help.assert_called_once_with(mock.ANY) | 513 | mock_show_help.assert_called_once_with(mock.ANY) |
578 | 504 | 514 | ||
580 | 505 | def test_enabling_script_plugin_leaves_existing_inclusions(self): | 515 | @mock.patch("landscape.configuration.show_help") |
581 | 516 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=True) | ||
582 | 517 | def test_enabling_script_plugin_leaves_existing_inclusions( | ||
583 | 518 | self, mock_prompt_yes_no, mock_show_help): | ||
584 | 506 | """ | 519 | """ |
585 | 507 | Enabling the script execution plugin doesn't remove other included | 520 | Enabling the script execution plugin doesn't remove other included |
586 | 508 | plugins. | 521 | plugins. |
587 | 509 | """ | 522 | """ |
588 | 510 | self.config.include_manager_plugins = "FooPlugin" | 523 | self.config.include_manager_plugins = "FooPlugin" |
589 | 511 | 524 | ||
590 | 512 | self.script.show_help = mock.Mock() | ||
591 | 513 | self.script.prompt_yes_no = mock.Mock(return_value=True) | ||
592 | 514 | self.script.prompt = mock.Mock() | 525 | self.script.prompt = mock.Mock() |
593 | 515 | 526 | ||
594 | 516 | self.script.query_script_plugin() | 527 | self.script.query_script_plugin() |
596 | 517 | self.script.prompt_yes_no.assert_called_once_with( | 528 | mock_prompt_yes_no.assert_called_once_with( |
597 | 518 | "Enable script execution?", default=False) | 529 | "Enable script execution?", default=False) |
598 | 519 | 530 | ||
599 | 520 | self.script.prompt.assert_called_once_with( | 531 | self.script.prompt.assert_called_once_with( |
600 | 521 | "script_users", "Script users") | 532 | "script_users", "Script users") |
602 | 522 | self.assertEqual(2, self.script.show_help.call_count) | 533 | self.assertEqual(2, mock_show_help.call_count) |
603 | 523 | self.assertEqual(self.config.include_manager_plugins, | 534 | self.assertEqual(self.config.include_manager_plugins, |
604 | 524 | "FooPlugin, ScriptExecution") | 535 | "FooPlugin, ScriptExecution") |
605 | 525 | 536 | ||
606 | @@ -534,9 +545,10 @@ | |||
607 | 534 | "ScriptExecution") | 545 | "ScriptExecution") |
608 | 535 | self.assertEqual(self.config.script_users, "root, nobody") | 546 | self.assertEqual(self.config.script_users, "root, nobody") |
609 | 536 | 547 | ||
613 | 537 | def test_query_script_manager_plugins_defined_on_command_line(self): | 548 | @mock.patch("landscape.configuration.show_help") |
614 | 538 | self.script.show_help = mock.Mock() | 549 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=True) |
615 | 539 | self.script.prompt_yes_no = mock.Mock(return_value=True) | 550 | def test_query_script_manager_plugins_defined_on_command_line( |
616 | 551 | self, mock_prompt_yes_no, mock_show_help): | ||
617 | 540 | self.script.prompt = mock.Mock() | 552 | self.script.prompt = mock.Mock() |
618 | 541 | 553 | ||
619 | 542 | self.config.load_command_line( | 554 | self.config.load_command_line( |
620 | @@ -544,17 +556,19 @@ | |||
621 | 544 | self.script.query_script_plugin() | 556 | self.script.query_script_plugin() |
622 | 545 | self.script.prompt.assert_called_once_with( | 557 | self.script.prompt.assert_called_once_with( |
623 | 546 | "script_users", "Script users") | 558 | "script_users", "Script users") |
625 | 547 | self.assertEqual(2, self.script.show_help.call_count) | 559 | self.assertEqual(2, mock_show_help.call_count) |
626 | 548 | self.assertEqual(self.config.include_manager_plugins, | 560 | self.assertEqual(self.config.include_manager_plugins, |
627 | 549 | "FooPlugin, ScriptExecution") | 561 | "FooPlugin, ScriptExecution") |
628 | 550 | 562 | ||
629 | 563 | @mock.patch("landscape.configuration.show_help") | ||
630 | 564 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=True) | ||
631 | 551 | @mock.patch("landscape.configuration.pwd.getpwnam", return_value=None) | 565 | @mock.patch("landscape.configuration.pwd.getpwnam", return_value=None) |
633 | 552 | def test_query_script_users_defined_on_command_line(self, mock_getpwnam): | 566 | def test_query_script_users_defined_on_command_line(self, mock_getpwnam, |
634 | 567 | mock_prompt_yes_no, | ||
635 | 568 | mock_show_help): | ||
636 | 553 | """ | 569 | """ |
637 | 554 | Confirm with the user for users specified for the ScriptPlugin. | 570 | Confirm with the user for users specified for the ScriptPlugin. |
638 | 555 | """ | 571 | """ |
639 | 556 | self.script.show_help = mock.Mock() | ||
640 | 557 | self.script.prompt_yes_no = mock.Mock(return_value=True) | ||
641 | 558 | self.script.prompt_get_input = mock.Mock(return_value=None) | 572 | self.script.prompt_get_input = mock.Mock(return_value=None) |
642 | 559 | 573 | ||
643 | 560 | self.config.include_manager_plugins = "FooPlugin" | 574 | self.config.include_manager_plugins = "FooPlugin" |
644 | @@ -564,11 +578,11 @@ | |||
645 | 564 | self.script.query_script_plugin() | 578 | self.script.query_script_plugin() |
646 | 565 | 579 | ||
647 | 566 | mock_getpwnam.assert_called_with("landscape") | 580 | mock_getpwnam.assert_called_with("landscape") |
649 | 567 | self.script.prompt_yes_no.assert_called_once_with( | 581 | mock_prompt_yes_no.assert_called_once_with( |
650 | 568 | "Enable script execution?", default=False) | 582 | "Enable script execution?", default=False) |
651 | 569 | self.script.prompt_get_input.assert_called_once_with( | 583 | self.script.prompt_get_input.assert_called_once_with( |
652 | 570 | "Script users [root, nobody, landscape]: ", False) | 584 | "Script users [root, nobody, landscape]: ", False) |
654 | 571 | self.assertEqual(2, self.script.show_help.call_count) | 585 | self.assertEqual(2, mock_show_help.call_count) |
655 | 572 | self.assertEqual(self.config.script_users, | 586 | self.assertEqual(self.config.script_users, |
656 | 573 | "root, nobody, landscape") | 587 | "root, nobody, landscape") |
657 | 574 | 588 | ||
658 | @@ -617,53 +631,56 @@ | |||
659 | 617 | "--include-manager-plugins", "ScriptPlugin"]) | 631 | "--include-manager-plugins", "ScriptPlugin"]) |
660 | 618 | self.assertRaises(ConfigurationError, self.script.query_script_plugin) | 632 | self.assertRaises(ConfigurationError, self.script.query_script_plugin) |
661 | 619 | 633 | ||
663 | 620 | def test_invalid_user_entered_by_user(self): | 634 | @mock.patch("landscape.configuration.show_help") |
664 | 635 | @mock.patch("landscape.configuration.prompt_yes_no", return_value=True) | ||
665 | 636 | def test_invalid_user_entered_by_user(self, mock_prompt_yes_no, | ||
666 | 637 | mock_show_help): | ||
667 | 621 | """ | 638 | """ |
668 | 622 | If an invalid user is entered on the command line the user should be | 639 | If an invalid user is entered on the command line the user should be |
669 | 623 | informed and prompted again. | 640 | informed and prompted again. |
670 | 624 | """ | 641 | """ |
671 | 625 | help_snippet = "Landscape has a feature which enables administrators" | 642 | help_snippet = "Landscape has a feature which enables administrators" |
672 | 626 | self.script.show_help = mock.Mock() | ||
673 | 627 | self.script.prompt_yes_no = mock.Mock(return_value=True) | ||
674 | 628 | self.script.prompt_get_input = mock.Mock( | 643 | self.script.prompt_get_input = mock.Mock( |
675 | 629 | side_effect=(u"nonexistent", u"root")) | 644 | side_effect=(u"nonexistent", u"root")) |
676 | 630 | 645 | ||
677 | 631 | self.script.query_script_plugin() | 646 | self.script.query_script_plugin() |
678 | 632 | self.assertEqual(self.config.script_users, "root") | 647 | self.assertEqual(self.config.script_users, "root") |
680 | 633 | first_call, second_call, third_call = self.script.show_help.mock_calls | 648 | first_call, second_call, third_call = mock_show_help.mock_calls |
681 | 634 | self.assertTrue(first_call.strip().startswith(help_snippet)) | 649 | self.assertTrue(first_call.strip().startswith(help_snippet)) |
682 | 635 | self.assertTrue(second_call.strip().startswith( | 650 | self.assertTrue(second_call.strip().startswith( |
683 | 636 | "By default, scripts are restricted")) | 651 | "By default, scripts are restricted")) |
684 | 637 | self.assertTrue(third_call.strip().startswith( | 652 | self.assertTrue(third_call.strip().startswith( |
685 | 638 | "Unknown system users: nonexistsent")) | 653 | "Unknown system users: nonexistsent")) |
686 | 639 | 654 | ||
688 | 640 | def test_tags_not_defined_on_command_line(self): | 655 | @mock.patch("landscape.configuration.show_help") |
689 | 656 | def test_tags_not_defined_on_command_line(self, mock_show_help): | ||
690 | 641 | """ | 657 | """ |
691 | 642 | If tags are not provided, the user should be prompted for them. | 658 | If tags are not provided, the user should be prompted for them. |
692 | 643 | """ | 659 | """ |
693 | 644 | help_snippet = ("You may provide tags for this computer e.g. " | 660 | help_snippet = ("You may provide tags for this computer e.g. " |
694 | 645 | "server,precise.") | 661 | "server,precise.") |
695 | 646 | self.script.show_help = mock.Mock() | ||
696 | 647 | self.script.prompt = mock.Mock() | 662 | self.script.prompt = mock.Mock() |
697 | 648 | 663 | ||
698 | 649 | self.script.query_tags() | 664 | self.script.query_tags() |
699 | 650 | self.script.prompt.assert_called_once_with( | 665 | self.script.prompt.assert_called_once_with( |
700 | 651 | "tags", "Tags", False) | 666 | "tags", "Tags", False) |
702 | 652 | [call] = self.script.show_help.mock_calls | 667 | [call] = mock_show_help.mock_calls |
703 | 653 | self.assertTrue(call.strip().startswith(help_snippet)) | 668 | self.assertTrue(call.strip().startswith(help_snippet)) |
704 | 654 | 669 | ||
706 | 655 | def test_invalid_tags_entered_by_user(self): | 670 | @mock.patch("landscape.configuration.show_help") |
707 | 671 | @mock.patch("landscape.configuration.prompt_yes_no") | ||
708 | 672 | def test_invalid_tags_entered_by_user(self, mock_prompt_yes_no, | ||
709 | 673 | mock_show_help): | ||
710 | 656 | """ | 674 | """ |
711 | 657 | If tags are not provided, the user should be prompted for them, and | 675 | If tags are not provided, the user should be prompted for them, and |
712 | 658 | they should be valid tags, if not the user should be prompted for them | 676 | they should be valid tags, if not the user should be prompted for them |
713 | 659 | again. | 677 | again. |
714 | 660 | """ | 678 | """ |
715 | 661 | self.script.show_help = mock.Mock() | ||
716 | 662 | self.script.prompt_get_input = mock.Mock( | 679 | self.script.prompt_get_input = mock.Mock( |
717 | 663 | side_effect=(u"<script>alert();</script>", u"london")) | 680 | side_effect=(u"<script>alert();</script>", u"london")) |
718 | 664 | 681 | ||
719 | 665 | self.script.query_tags() | 682 | self.script.query_tags() |
721 | 666 | first_call, second_call = self.script.show_help.mock_calls | 683 | first_call, second_call = mock_show_help.mock_calls |
722 | 667 | self.assertTrue( | 684 | self.assertTrue( |
723 | 668 | first_call.strip().startswith("You may provide tags for this " | 685 | first_call.strip().startswith("You may provide tags for this " |
724 | 669 | "computer e.g. server,precise.")) | 686 | "computer e.g. server,precise.")) |
725 | @@ -693,16 +710,16 @@ | |||
726 | 693 | self.assertRaises(ConfigurationError, self.script.query_tags) | 710 | self.assertRaises(ConfigurationError, self.script.query_tags) |
727 | 694 | mock_raw_input.assert_not_called() | 711 | mock_raw_input.assert_not_called() |
728 | 695 | 712 | ||
730 | 696 | def test_access_group_not_defined_on_command_line(self): | 713 | @mock.patch("landscape.configuration.show_help") |
731 | 714 | def test_access_group_not_defined_on_command_line(self, mock_show_help): | ||
732 | 697 | """ | 715 | """ |
733 | 698 | If an access group is not provided, the user should be prompted for it. | 716 | If an access group is not provided, the user should be prompted for it. |
734 | 699 | """ | 717 | """ |
735 | 700 | help_snippet = ("You may provide an access group for this computer " | 718 | help_snippet = ("You may provide an access group for this computer " |
736 | 701 | "e.g. webservers.") | 719 | "e.g. webservers.") |
737 | 702 | self.script.show_help = mock.Mock() | ||
738 | 703 | self.script.prompt = mock.Mock() | 720 | self.script.prompt = mock.Mock() |
739 | 704 | self.script.query_access_group() | 721 | self.script.query_access_group() |
741 | 705 | [call] = self.script.show_help.mock_calls | 722 | [call] = mock_show_help.mock_calls |
742 | 706 | self.assertTrue(call.strip().startswith(help_snippet)) | 723 | self.assertTrue(call.strip().startswith(help_snippet)) |
743 | 707 | 724 | ||
744 | 708 | @mock.patch("__builtin__.raw_input") | 725 | @mock.patch("__builtin__.raw_input") |
745 | @@ -716,11 +733,11 @@ | |||
746 | 716 | self.assertEqual(self.config.access_group, u"webservers") | 733 | self.assertEqual(self.config.access_group, u"webservers") |
747 | 717 | mock_raw_input.assert_not_called() | 734 | mock_raw_input.assert_not_called() |
748 | 718 | 735 | ||
750 | 719 | def test_show_header(self): | 736 | @mock.patch("landscape.configuration.show_help") |
751 | 737 | def test_show_header(self, mock_show_help): | ||
752 | 720 | help_snippet = "This script will" | 738 | help_snippet = "This script will" |
753 | 721 | self.script.show_help = mock.Mock() | ||
754 | 722 | self.script.show_header() | 739 | self.script.show_header() |
756 | 723 | [call] = self.script.show_help.mock_calls | 740 | [call] = mock_show_help.mock_calls |
757 | 724 | self.assertTrue(call.strip().startswith(help_snippet)) | 741 | self.assertTrue(call.strip().startswith(help_snippet)) |
758 | 725 | 742 | ||
759 | 726 | def test_run(self): | 743 | def test_run(self): |
760 | @@ -1095,7 +1112,7 @@ | |||
761 | 1095 | main(["-c", self.make_working_config()], print=noop_print) | 1112 | main(["-c", self.make_working_config()], print=noop_print) |
762 | 1096 | mock_register.assert_not_called() | 1113 | mock_register.assert_not_called() |
763 | 1097 | mock_raw_input.assert_called_once_with( | 1114 | mock_raw_input.assert_called_once_with( |
765 | 1098 | "\nRequest a new registration for this computer now? (Y/n): ") | 1115 | "\nRequest a new registration for this computer now? [Y/n]: ") |
766 | 1099 | 1116 | ||
767 | 1100 | @mock.patch("landscape.configuration.register", return_value="success") | 1117 | @mock.patch("landscape.configuration.register", return_value="success") |
768 | 1101 | @mock.patch("landscape.configuration.setup") | 1118 | @mock.patch("landscape.configuration.setup") |
769 | @@ -1136,7 +1153,7 @@ | |||
770 | 1136 | mock_setup.assert_called_once_with(mock.ANY) | 1153 | mock_setup.assert_called_once_with(mock.ANY) |
771 | 1137 | mock_register.assert_called_once_with(mock.ANY, mock.ANY) | 1154 | mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
772 | 1138 | mock_raw_input.assert_called_once_with( | 1155 | mock_raw_input.assert_called_once_with( |
774 | 1139 | "\nRequest a new registration for this computer now? (Y/n): ") | 1156 | "\nRequest a new registration for this computer now? [Y/n]: ") |
775 | 1140 | self.assertEqual( | 1157 | self.assertEqual( |
776 | 1141 | [("Please wait...", sys.stdout), | 1158 | [("Please wait...", sys.stdout), |
777 | 1142 | ("System successfully registered.", sys.stdout)], | 1159 | ("System successfully registered.", sys.stdout)], |
778 | @@ -1161,7 +1178,7 @@ | |||
779 | 1161 | mock_setup.assert_called_once_with(mock.ANY) | 1178 | mock_setup.assert_called_once_with(mock.ANY) |
780 | 1162 | mock_register.assert_called_once_with(mock.ANY, mock.ANY) | 1179 | mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
781 | 1163 | mock_raw_input.assert_called_once_with( | 1180 | mock_raw_input.assert_called_once_with( |
783 | 1164 | "\nRequest a new registration for this computer now? (Y/n): ") | 1181 | "\nRequest a new registration for this computer now? [Y/n]: ") |
784 | 1165 | 1182 | ||
785 | 1166 | # Note that the error is output via sys.stderr. | 1183 | # Note that the error is output via sys.stderr. |
786 | 1167 | self.assertEqual( | 1184 | self.assertEqual( |
787 | @@ -1249,9 +1266,9 @@ | |||
788 | 1249 | mock_raw_input.assert_any_call( | 1266 | mock_raw_input.assert_any_call( |
789 | 1250 | "\nThe Landscape client must be started " | 1267 | "\nThe Landscape client must be started " |
790 | 1251 | "on boot to operate correctly.\n\n" | 1268 | "on boot to operate correctly.\n\n" |
792 | 1252 | "Start Landscape client on boot? (Y/n): ") | 1269 | "Start Landscape client on boot? [Y/n]: ") |
793 | 1253 | mock_raw_input.assert_called_with( | 1270 | mock_raw_input.assert_called_with( |
795 | 1254 | "\nRequest a new registration for this computer now? (Y/n): ") | 1271 | "\nRequest a new registration for this computer now? [Y/n]: ") |
796 | 1255 | 1272 | ||
797 | 1256 | @mock.patch("landscape.configuration.print_text") | 1273 | @mock.patch("landscape.configuration.print_text") |
798 | 1257 | @mock.patch("landscape.configuration.SysVConfig") | 1274 | @mock.patch("landscape.configuration.SysVConfig") |
799 | @@ -1307,7 +1324,7 @@ | |||
800 | 1307 | mock_setup.assert_called_once_with(mock.ANY) | 1324 | mock_setup.assert_called_once_with(mock.ANY) |
801 | 1308 | mock_register.assert_called_once_with(mock.ANY, mock.ANY) | 1325 | mock_register.assert_called_once_with(mock.ANY, mock.ANY) |
802 | 1309 | mock_raw_input.assert_called_once_with( | 1326 | mock_raw_input.assert_called_once_with( |
804 | 1310 | "\nRequest a new registration for this computer now? (Y/n): ") | 1327 | "\nRequest a new registration for this computer now? [Y/n]: ") |
805 | 1311 | 1328 | ||
806 | 1312 | @mock.patch("landscape.configuration.SysVConfig") | 1329 | @mock.patch("landscape.configuration.SysVConfig") |
807 | 1313 | def test_setup_init_script_and_start_client( | 1330 | def test_setup_init_script_and_start_client( |
Command: TRIAL_ARGS=-j4 make check /ci.lscape. net/job/ latch-test- precise/ 870/
Result: Success
Revno: 943
Branch: lp:~ack/landscape-client/refactor-prompt-functions
Jenkins: https:/