pyinfra 2.9.2__py2.py3-none-any.whl → 3.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyinfra/api/__init__.py +3 -0
- pyinfra/api/arguments.py +265 -253
- pyinfra/api/arguments_typed.py +80 -0
- pyinfra/api/command.py +68 -53
- pyinfra/api/config.py +139 -32
- pyinfra/api/connect.py +1 -1
- pyinfra/api/connectors.py +7 -26
- pyinfra/api/deploy.py +21 -52
- pyinfra/api/exceptions.py +33 -8
- pyinfra/api/facts.py +102 -137
- pyinfra/api/host.py +150 -82
- pyinfra/api/inventory.py +21 -25
- pyinfra/api/operation.py +240 -198
- pyinfra/api/operations.py +102 -148
- pyinfra/api/state.py +137 -79
- pyinfra/api/util.py +79 -86
- pyinfra/connectors/base.py +147 -0
- pyinfra/connectors/chroot.py +160 -169
- pyinfra/connectors/docker.py +220 -237
- pyinfra/connectors/dockerssh.py +231 -253
- pyinfra/connectors/local.py +196 -208
- pyinfra/connectors/ssh.py +530 -613
- pyinfra/connectors/ssh_util.py +114 -0
- pyinfra/connectors/sshuserclient/client.py +5 -3
- pyinfra/connectors/terraform.py +86 -65
- pyinfra/connectors/util.py +211 -137
- pyinfra/connectors/vagrant.py +60 -53
- pyinfra/context.py +4 -2
- pyinfra/facts/apk.py +2 -0
- pyinfra/facts/apt.py +2 -0
- pyinfra/facts/brew.py +2 -0
- pyinfra/facts/bsdinit.py +2 -0
- pyinfra/facts/cargo.py +2 -0
- pyinfra/facts/choco.py +2 -0
- pyinfra/facts/deb.py +7 -2
- pyinfra/facts/dnf.py +2 -0
- pyinfra/facts/docker.py +19 -0
- pyinfra/facts/files.py +47 -32
- pyinfra/facts/gem.py +2 -0
- pyinfra/facts/git.py +3 -1
- pyinfra/facts/gpg.py +3 -1
- pyinfra/facts/hardware.py +34 -24
- pyinfra/facts/iptables.py +5 -3
- pyinfra/facts/launchd.py +2 -0
- pyinfra/facts/lxd.py +2 -0
- pyinfra/facts/mysql.py +13 -6
- pyinfra/facts/npm.py +1 -0
- pyinfra/facts/openrc.py +2 -0
- pyinfra/facts/pacman.py +6 -2
- pyinfra/facts/pip.py +2 -0
- pyinfra/facts/pkg.py +2 -0
- pyinfra/facts/pkgin.py +2 -0
- pyinfra/facts/postgres.py +168 -0
- pyinfra/facts/postgresql.py +6 -160
- pyinfra/facts/rpm.py +12 -9
- pyinfra/facts/runit.py +68 -0
- pyinfra/facts/selinux.py +3 -1
- pyinfra/facts/server.py +80 -36
- pyinfra/facts/snap.py +2 -0
- pyinfra/facts/systemd.py +31 -12
- pyinfra/facts/sysvinit.py +10 -10
- pyinfra/facts/upstart.py +2 -0
- pyinfra/facts/util/packaging.py +7 -4
- pyinfra/facts/vzctl.py +2 -0
- pyinfra/facts/xbps.py +2 -0
- pyinfra/facts/yum.py +2 -0
- pyinfra/facts/zypper.py +2 -0
- pyinfra/local.py +4 -5
- pyinfra/operations/apk.py +6 -4
- pyinfra/operations/apt.py +46 -65
- pyinfra/operations/brew.py +17 -22
- pyinfra/operations/bsdinit.py +9 -7
- pyinfra/operations/cargo.py +4 -2
- pyinfra/operations/choco.py +4 -2
- pyinfra/operations/dnf.py +19 -23
- pyinfra/operations/docker.py +339 -0
- pyinfra/operations/files.py +188 -386
- pyinfra/operations/gem.py +4 -2
- pyinfra/operations/git.py +24 -53
- pyinfra/operations/iptables.py +29 -35
- pyinfra/operations/launchd.py +6 -7
- pyinfra/operations/lxd.py +8 -13
- pyinfra/operations/mysql.py +62 -81
- pyinfra/operations/npm.py +9 -2
- pyinfra/operations/openrc.py +6 -4
- pyinfra/operations/pacman.py +7 -8
- pyinfra/operations/pip.py +25 -24
- pyinfra/operations/pkg.py +4 -2
- pyinfra/operations/pkgin.py +6 -4
- pyinfra/operations/postgres.py +349 -0
- pyinfra/operations/postgresql.py +18 -379
- pyinfra/operations/puppet.py +3 -1
- pyinfra/operations/python.py +8 -19
- pyinfra/operations/runit.py +182 -0
- pyinfra/operations/selinux.py +47 -44
- pyinfra/operations/server.py +111 -127
- pyinfra/operations/snap.py +4 -4
- pyinfra/operations/ssh.py +20 -33
- pyinfra/operations/systemd.py +19 -15
- pyinfra/operations/sysvinit.py +9 -16
- pyinfra/operations/upstart.py +9 -7
- pyinfra/operations/util/__init__.py +12 -0
- pyinfra/operations/util/docker.py +177 -0
- pyinfra/operations/util/files.py +24 -16
- pyinfra/operations/util/packaging.py +55 -57
- pyinfra/operations/util/service.py +39 -51
- pyinfra/operations/vzctl.py +12 -10
- pyinfra/operations/xbps.py +6 -4
- pyinfra/operations/yum.py +18 -22
- pyinfra/operations/zypper.py +12 -13
- pyinfra/version.py +5 -2
- {pyinfra-2.9.2.dist-info → pyinfra-3.0.dist-info}/METADATA +40 -41
- pyinfra-3.0.dist-info/RECORD +167 -0
- {pyinfra-2.9.2.dist-info → pyinfra-3.0.dist-info}/WHEEL +1 -1
- pyinfra-3.0.dist-info/entry_points.txt +11 -0
- pyinfra_cli/__main__.py +4 -3
- pyinfra_cli/commands.py +7 -2
- pyinfra_cli/exceptions.py +78 -42
- pyinfra_cli/inventory.py +40 -6
- pyinfra_cli/log.py +17 -3
- pyinfra_cli/main.py +133 -90
- pyinfra_cli/prints.py +95 -127
- pyinfra_cli/util.py +62 -29
- tests/test_api/test_api.py +2 -0
- tests/test_api/test_api_arguments.py +13 -13
- tests/test_api/test_api_deploys.py +28 -29
- tests/test_api/test_api_facts.py +60 -98
- tests/test_api/test_api_operations.py +101 -201
- tests/test_cli/test_cli.py +18 -49
- tests/test_cli/test_cli_deploy.py +11 -37
- tests/test_cli/test_cli_exceptions.py +50 -19
- tests/test_cli/util.py +1 -1
- tests/test_connectors/test_chroot.py +6 -6
- tests/test_connectors/test_docker.py +4 -4
- tests/test_connectors/test_dockerssh.py +38 -50
- tests/test_connectors/test_local.py +11 -12
- tests/test_connectors/test_ssh.py +105 -93
- tests/test_connectors/test_terraform.py +9 -15
- tests/test_connectors/test_util.py +24 -46
- tests/test_connectors/test_vagrant.py +7 -7
- pyinfra/api/operation.pyi +0 -117
- pyinfra/connectors/ansible.py +0 -171
- pyinfra/connectors/mech.py +0 -186
- pyinfra/connectors/pyinfrawinrmsession/__init__.py +0 -28
- pyinfra/connectors/winrm.py +0 -320
- pyinfra/facts/windows.py +0 -366
- pyinfra/facts/windows_files.py +0 -90
- pyinfra/operations/windows.py +0 -59
- pyinfra/operations/windows_files.py +0 -551
- pyinfra-2.9.2.dist-info/RECORD +0 -170
- pyinfra-2.9.2.dist-info/entry_points.txt +0 -14
- tests/test_connectors/test_ansible.py +0 -64
- tests/test_connectors/test_mech.py +0 -126
- tests/test_connectors/test_winrm.py +0 -76
- {pyinfra-2.9.2.dist-info → pyinfra-3.0.dist-info}/LICENSE.md +0 -0
- {pyinfra-2.9.2.dist-info → pyinfra-3.0.dist-info}/top_level.txt +0 -0
pyinfra_cli/log.py
CHANGED
|
@@ -2,7 +2,8 @@ import logging
|
|
|
2
2
|
|
|
3
3
|
import click
|
|
4
4
|
|
|
5
|
-
from pyinfra import logger
|
|
5
|
+
from pyinfra import logger, state
|
|
6
|
+
from pyinfra.context import ctx_state
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class LogHandler(logging.Handler):
|
|
@@ -15,6 +16,8 @@ class LogHandler(logging.Handler):
|
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class LogFormatter(logging.Formatter):
|
|
19
|
+
previous_was_header = True
|
|
20
|
+
|
|
18
21
|
level_to_format = {
|
|
19
22
|
logging.DEBUG: lambda s: click.style(s, "green"),
|
|
20
23
|
logging.WARNING: lambda s: click.style(s, "yellow"),
|
|
@@ -39,21 +42,32 @@ class LogFormatter(logging.Formatter):
|
|
|
39
42
|
|
|
40
43
|
# We only handle strings here
|
|
41
44
|
if isinstance(message, str):
|
|
42
|
-
if
|
|
45
|
+
if ctx_state.isset() and record.levelno is logging.WARNING:
|
|
46
|
+
state.increment_warning_counter()
|
|
47
|
+
|
|
48
|
+
if "-->" in message:
|
|
49
|
+
if not self.previous_was_header:
|
|
50
|
+
click.echo(err=True)
|
|
51
|
+
else:
|
|
43
52
|
message = " {0}".format(message)
|
|
44
53
|
|
|
45
54
|
if record.levelno in self.level_to_format:
|
|
46
55
|
message = self.level_to_format[record.levelno](message)
|
|
47
56
|
|
|
57
|
+
self.previous_was_header = "-->" in message
|
|
48
58
|
return message
|
|
49
59
|
|
|
50
60
|
# If not a string, pass to standard Formatter
|
|
51
61
|
return super().format(record)
|
|
52
62
|
|
|
53
63
|
|
|
54
|
-
def setup_logging(log_level):
|
|
64
|
+
def setup_logging(log_level, other_log_level=None):
|
|
65
|
+
if other_log_level:
|
|
66
|
+
logging.basicConfig(level=other_log_level)
|
|
67
|
+
|
|
55
68
|
logger.setLevel(log_level)
|
|
56
69
|
handler = LogHandler()
|
|
57
70
|
formatter = LogFormatter()
|
|
58
71
|
handler.setFormatter(formatter)
|
|
59
72
|
logger.addHandler(handler)
|
|
73
|
+
logger.propagate = False
|
pyinfra_cli/main.py
CHANGED
|
@@ -13,12 +13,13 @@ from pyinfra.api.connect import connect_all, disconnect_all
|
|
|
13
13
|
from pyinfra.api.exceptions import NoGroupError, PyinfraError
|
|
14
14
|
from pyinfra.api.facts import get_facts
|
|
15
15
|
from pyinfra.api.operations import run_ops
|
|
16
|
+
from pyinfra.api.state import StateStage
|
|
16
17
|
from pyinfra.api.util import get_kwargs_str
|
|
17
18
|
from pyinfra.context import ctx_config, ctx_inventory, ctx_state
|
|
18
19
|
from pyinfra.operations import server
|
|
19
20
|
|
|
20
21
|
from .commands import get_facts_and_args, get_func_and_args
|
|
21
|
-
from .exceptions import CliError, UnexpectedExternalError, UnexpectedInternalError
|
|
22
|
+
from .exceptions import CliError, UnexpectedExternalError, UnexpectedInternalError, WrappedError
|
|
22
23
|
from .inventory import make_inventory
|
|
23
24
|
from .log import setup_logging
|
|
24
25
|
from .prints import (
|
|
@@ -26,7 +27,6 @@ from .prints import (
|
|
|
26
27
|
print_inventory,
|
|
27
28
|
print_meta,
|
|
28
29
|
print_results,
|
|
29
|
-
print_state_facts,
|
|
30
30
|
print_state_operations,
|
|
31
31
|
print_support_info,
|
|
32
32
|
)
|
|
@@ -44,7 +44,7 @@ def _print_support(ctx, param, value):
|
|
|
44
44
|
if not value:
|
|
45
45
|
return
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
logger.info("--> Support information:")
|
|
48
48
|
print_support_info()
|
|
49
49
|
ctx.exit()
|
|
50
50
|
|
|
@@ -64,6 +64,15 @@ def _print_support(ctx, param, value):
|
|
|
64
64
|
default=False,
|
|
65
65
|
help="Don't execute operations on the target hosts.",
|
|
66
66
|
)
|
|
67
|
+
@click.option(
|
|
68
|
+
"-y",
|
|
69
|
+
"--yes",
|
|
70
|
+
is_flag=True,
|
|
71
|
+
default=False,
|
|
72
|
+
help="Execute operations immediately on hosts without prompt or checking for changes.",
|
|
73
|
+
envvar="PYINFRA_YES",
|
|
74
|
+
show_envvar=True,
|
|
75
|
+
)
|
|
67
76
|
@click.option(
|
|
68
77
|
"--limit",
|
|
69
78
|
help="Restrict the target hosts by name and group name.",
|
|
@@ -132,11 +141,6 @@ def _print_support(ctx, param, value):
|
|
|
132
141
|
help="SSH Private key password.",
|
|
133
142
|
)
|
|
134
143
|
@click.option("--ssh-password", "--password", "ssh_password", help="SSH password.")
|
|
135
|
-
# WinRM connector args
|
|
136
|
-
@click.option("--winrm-username", help="WINRM user to connect as.")
|
|
137
|
-
@click.option("--winrm-password", help="WINRM password.")
|
|
138
|
-
@click.option("--winrm-port", help="WINRM port to connect to.")
|
|
139
|
-
@click.option("--winrm-transport", help="WINRM transport for use.")
|
|
140
144
|
# Eager commands (pyinfra --support)
|
|
141
145
|
@click.option(
|
|
142
146
|
"--support",
|
|
@@ -156,7 +160,13 @@ def _print_support(ctx, param, value):
|
|
|
156
160
|
"--debug",
|
|
157
161
|
is_flag=True,
|
|
158
162
|
default=False,
|
|
159
|
-
help="Print debug
|
|
163
|
+
help="Print debug logs from pyinfra.",
|
|
164
|
+
)
|
|
165
|
+
@click.option(
|
|
166
|
+
"--debug-all",
|
|
167
|
+
is_flag=True,
|
|
168
|
+
default=False,
|
|
169
|
+
help="Print debug logs from all packages including pyinfra.",
|
|
160
170
|
)
|
|
161
171
|
@click.option(
|
|
162
172
|
"--debug-facts",
|
|
@@ -216,26 +226,17 @@ def cli(*args, **kwargs):
|
|
|
216
226
|
|
|
217
227
|
try:
|
|
218
228
|
_main(*args, **kwargs)
|
|
219
|
-
|
|
220
|
-
except PyinfraError as e:
|
|
221
|
-
# Re-raise any internal exceptions that aren't handled by click as
|
|
222
|
-
# CliErrors which are.
|
|
223
|
-
if not isinstance(e, click.ClickException):
|
|
224
|
-
message = getattr(e, "message", e.args[0])
|
|
225
|
-
raise CliError(message)
|
|
226
|
-
|
|
227
|
-
raise
|
|
228
|
-
|
|
229
|
-
except UnexpectedExternalError:
|
|
230
|
-
# Pass unexpected external exceptions through as-is
|
|
229
|
+
except (CliError, UnexpectedExternalError):
|
|
231
230
|
raise
|
|
232
|
-
|
|
231
|
+
except PyinfraError as e:
|
|
232
|
+
# Re-raise "expected" pyinfra exceptions with our click exception wrapper
|
|
233
|
+
raise WrappedError(e)
|
|
233
234
|
except Exception as e:
|
|
234
235
|
# Re-raise any unexpected internal exceptions as UnexpectedInternalError
|
|
235
236
|
raise UnexpectedInternalError(e)
|
|
236
|
-
|
|
237
237
|
finally:
|
|
238
238
|
if ctx_state.isset() and state.initialised:
|
|
239
|
+
logger.info("--> Disconnecting from hosts...")
|
|
239
240
|
# Triggers any executor disconnect requirements
|
|
240
241
|
disconnect_all(state)
|
|
241
242
|
|
|
@@ -258,10 +259,6 @@ def _main(
|
|
|
258
259
|
ssh_key,
|
|
259
260
|
ssh_key_password: str,
|
|
260
261
|
ssh_password: str,
|
|
261
|
-
winrm_username: str,
|
|
262
|
-
winrm_password: str,
|
|
263
|
-
winrm_port,
|
|
264
|
-
winrm_transport,
|
|
265
262
|
shell_executable,
|
|
266
263
|
sudo: bool,
|
|
267
264
|
sudo_user: str,
|
|
@@ -273,14 +270,16 @@ def _main(
|
|
|
273
270
|
group_data,
|
|
274
271
|
config_filename: str,
|
|
275
272
|
dry: bool,
|
|
273
|
+
yes: bool,
|
|
276
274
|
limit: Iterable,
|
|
277
275
|
no_wait: bool,
|
|
278
276
|
serial: bool,
|
|
279
277
|
quiet: bool,
|
|
280
278
|
debug: bool,
|
|
279
|
+
debug_all: bool,
|
|
281
280
|
debug_facts: bool,
|
|
282
281
|
debug_operations: bool,
|
|
283
|
-
support: bool =
|
|
282
|
+
support: bool = False,
|
|
284
283
|
):
|
|
285
284
|
# Setup working directory
|
|
286
285
|
#
|
|
@@ -289,7 +288,7 @@ def _main(
|
|
|
289
288
|
|
|
290
289
|
# Setup logging & Bootstrap/Venv
|
|
291
290
|
#
|
|
292
|
-
_setup_log_level(debug,
|
|
291
|
+
_setup_log_level(debug, debug_all)
|
|
293
292
|
init_virtualenv()
|
|
294
293
|
|
|
295
294
|
# Check operations are valid and setup commands
|
|
@@ -298,7 +297,7 @@ def _main(
|
|
|
298
297
|
|
|
299
298
|
# Setup state, config & inventory
|
|
300
299
|
#
|
|
301
|
-
state = _setup_state(verbosity, quiet)
|
|
300
|
+
state = _setup_state(verbosity, quiet, yes)
|
|
302
301
|
config = Config()
|
|
303
302
|
ctx_config.set(config)
|
|
304
303
|
|
|
@@ -314,7 +313,7 @@ def _main(
|
|
|
314
313
|
parallel,
|
|
315
314
|
shell_executable,
|
|
316
315
|
fail_percent,
|
|
317
|
-
|
|
316
|
+
yes,
|
|
318
317
|
)
|
|
319
318
|
override_data = _set_override_data(
|
|
320
319
|
data,
|
|
@@ -323,15 +322,14 @@ def _main(
|
|
|
323
322
|
ssh_key_password,
|
|
324
323
|
ssh_port,
|
|
325
324
|
ssh_password,
|
|
326
|
-
winrm_username,
|
|
327
|
-
winrm_password,
|
|
328
|
-
winrm_port,
|
|
329
|
-
winrm_transport,
|
|
330
325
|
)
|
|
331
326
|
|
|
327
|
+
if yes is False:
|
|
328
|
+
_set_fail_prompts(state, config)
|
|
329
|
+
|
|
332
330
|
# Load up the inventory from the filesystem
|
|
333
331
|
#
|
|
334
|
-
|
|
332
|
+
logger.info("--> Loading inventory...")
|
|
335
333
|
inventory = make_inventory(
|
|
336
334
|
inventory,
|
|
337
335
|
cwd=state.cwd,
|
|
@@ -352,20 +350,27 @@ def _main(
|
|
|
352
350
|
|
|
353
351
|
# Connect to the hosts & start handling the user commands
|
|
354
352
|
#
|
|
355
|
-
|
|
353
|
+
logger.info("--> Connecting to hosts...")
|
|
354
|
+
state.set_stage(StateStage.Connect)
|
|
356
355
|
connect_all(state)
|
|
357
|
-
|
|
356
|
+
|
|
357
|
+
logger.info("--> Preparing operations...")
|
|
358
|
+
state.set_stage(StateStage.Prepare)
|
|
359
|
+
can_diff, state, config = _handle_commands(
|
|
360
|
+
state, config, command, original_operations, operations
|
|
361
|
+
)
|
|
358
362
|
|
|
359
363
|
# Print proposed changes, execute unless --dry, and exit
|
|
360
364
|
#
|
|
361
|
-
|
|
362
|
-
|
|
365
|
+
if can_diff:
|
|
366
|
+
if yes:
|
|
367
|
+
logger.info("--> Skipping change detection")
|
|
368
|
+
else:
|
|
369
|
+
logger.info("--> Detected changes:")
|
|
370
|
+
print_meta(state)
|
|
363
371
|
|
|
364
372
|
# If --debug-facts or --debug-operations, print and exit
|
|
365
373
|
if debug_facts or debug_operations:
|
|
366
|
-
if debug_facts:
|
|
367
|
-
print_state_facts(state)
|
|
368
|
-
|
|
369
374
|
if debug_operations:
|
|
370
375
|
print_state_operations(state)
|
|
371
376
|
|
|
@@ -374,33 +379,67 @@ def _main(
|
|
|
374
379
|
if dry:
|
|
375
380
|
_exit()
|
|
376
381
|
|
|
377
|
-
|
|
378
|
-
|
|
382
|
+
if (
|
|
383
|
+
can_diff
|
|
384
|
+
and not yes
|
|
385
|
+
and not _do_confirm("Detected changes displayed above, skip this step with -y")
|
|
386
|
+
):
|
|
387
|
+
_exit()
|
|
379
388
|
|
|
389
|
+
logger.info("--> Beginning operation run...")
|
|
390
|
+
state.set_stage(StateStage.Execute)
|
|
380
391
|
run_ops(state, serial=serial, no_wait=no_wait)
|
|
381
392
|
|
|
382
|
-
|
|
393
|
+
logger.info("--> Results:")
|
|
394
|
+
state.set_stage(StateStage.Disconnect)
|
|
383
395
|
print_results(state)
|
|
384
396
|
_exit()
|
|
385
397
|
|
|
386
398
|
|
|
399
|
+
def _do_confirm(msg: str) -> bool:
|
|
400
|
+
click.echo(err=True)
|
|
401
|
+
click.echo(f" {msg}", err=True)
|
|
402
|
+
warning_count = state.get_warning_counter()
|
|
403
|
+
if warning_count > 0:
|
|
404
|
+
click.secho(
|
|
405
|
+
f" {warning_count} warnings shown during change detection, see above",
|
|
406
|
+
fg="yellow",
|
|
407
|
+
err=True,
|
|
408
|
+
)
|
|
409
|
+
confirm_msg = " Press enter to execute..."
|
|
410
|
+
click.echo(confirm_msg, err=True, nl=False)
|
|
411
|
+
v = input()
|
|
412
|
+
if v:
|
|
413
|
+
click.echo(f" Unexpected user input: {v}", err=True)
|
|
414
|
+
return False
|
|
415
|
+
# Go up, clear the line, go up again - as if the confirmation statement was never here!
|
|
416
|
+
click.echo(
|
|
417
|
+
"\033[1A{0}\033[1A".format("".join(" " for _ in range(len(confirm_msg)))),
|
|
418
|
+
err=True,
|
|
419
|
+
nl=False,
|
|
420
|
+
)
|
|
421
|
+
click.echo(err=True)
|
|
422
|
+
return True
|
|
423
|
+
|
|
424
|
+
|
|
387
425
|
# Setup
|
|
388
426
|
#
|
|
389
|
-
def _setup_log_level(debug,
|
|
427
|
+
def _setup_log_level(debug, debug_all):
|
|
390
428
|
if not debug and not sys.warnoptions:
|
|
391
429
|
warnings.simplefilter("ignore")
|
|
392
430
|
|
|
393
431
|
log_level = logging.INFO
|
|
394
|
-
if debug:
|
|
432
|
+
if debug or debug_all:
|
|
395
433
|
log_level = logging.DEBUG
|
|
396
|
-
elif quiet:
|
|
397
|
-
log_level = logging.WARNING
|
|
398
434
|
|
|
399
|
-
|
|
435
|
+
other_log_level = None
|
|
436
|
+
if debug_all:
|
|
437
|
+
other_log_level = logging.DEBUG
|
|
400
438
|
|
|
439
|
+
setup_logging(log_level, other_log_level)
|
|
401
440
|
|
|
402
|
-
def _validate_operations(operations, chdir):
|
|
403
441
|
|
|
442
|
+
def _validate_operations(operations, chdir):
|
|
404
443
|
# Make a copy before we overwrite
|
|
405
444
|
original_operations = operations
|
|
406
445
|
|
|
@@ -467,7 +506,7 @@ def _validate_operations(operations, chdir):
|
|
|
467
506
|
return original_operations, operations, command, chdir
|
|
468
507
|
|
|
469
508
|
|
|
470
|
-
def _set_verbosity(state, verbosity
|
|
509
|
+
def _set_verbosity(state, verbosity):
|
|
471
510
|
if verbosity > 0:
|
|
472
511
|
state.print_fact_info = True
|
|
473
512
|
state.print_noop_info = True
|
|
@@ -481,16 +520,16 @@ def _set_verbosity(state, verbosity, quiet):
|
|
|
481
520
|
return state
|
|
482
521
|
|
|
483
522
|
|
|
484
|
-
def _setup_state(verbosity, quiet):
|
|
523
|
+
def _setup_state(verbosity, quiet, yes):
|
|
485
524
|
cwd = getcwd()
|
|
486
525
|
if cwd not in sys.path: # ensure cwd is present in sys.path
|
|
487
526
|
sys.path.append(cwd)
|
|
488
527
|
|
|
489
|
-
state = State()
|
|
528
|
+
state = State(check_for_changes=not yes)
|
|
490
529
|
state.cwd = cwd
|
|
491
530
|
ctx_state.set(state)
|
|
492
531
|
|
|
493
|
-
state = _set_verbosity(state, verbosity
|
|
532
|
+
state = _set_verbosity(state, verbosity)
|
|
494
533
|
return state
|
|
495
534
|
|
|
496
535
|
|
|
@@ -504,12 +543,13 @@ def _set_config(
|
|
|
504
543
|
parallel,
|
|
505
544
|
shell_executable,
|
|
506
545
|
fail_percent,
|
|
507
|
-
|
|
546
|
+
yes,
|
|
508
547
|
):
|
|
509
|
-
|
|
548
|
+
logger.info("--> Loading config...")
|
|
510
549
|
|
|
511
550
|
# Load up any config.py from the filesystem
|
|
512
|
-
|
|
551
|
+
if state.cwd:
|
|
552
|
+
config_filename = path.join(state.cwd, config_filename)
|
|
513
553
|
if path.exists(config_filename):
|
|
514
554
|
exec_file(config_filename)
|
|
515
555
|
|
|
@@ -548,10 +588,6 @@ def _set_override_data(
|
|
|
548
588
|
ssh_key_password,
|
|
549
589
|
ssh_port,
|
|
550
590
|
ssh_password,
|
|
551
|
-
winrm_username,
|
|
552
|
-
winrm_password,
|
|
553
|
-
winrm_port,
|
|
554
|
-
winrm_transport,
|
|
555
591
|
):
|
|
556
592
|
override_data = {}
|
|
557
593
|
|
|
@@ -567,10 +603,6 @@ def _set_override_data(
|
|
|
567
603
|
("ssh_key_password", ssh_key_password),
|
|
568
604
|
("ssh_port", ssh_port),
|
|
569
605
|
("ssh_password", ssh_password),
|
|
570
|
-
("winrm_username", winrm_username),
|
|
571
|
-
("winrm_password", winrm_password),
|
|
572
|
-
("winrm_port", winrm_port),
|
|
573
|
-
("winrm_transport", winrm_transport),
|
|
574
606
|
):
|
|
575
607
|
if value:
|
|
576
608
|
override_data[key] = value
|
|
@@ -578,6 +610,19 @@ def _set_override_data(
|
|
|
578
610
|
return override_data
|
|
579
611
|
|
|
580
612
|
|
|
613
|
+
def _set_fail_prompts(state: State, config: Config) -> None:
|
|
614
|
+
# Set fail percent to zero, meaning we'll raise an exception for any fail,
|
|
615
|
+
# and we can capture + prompt the user to continue/exit.
|
|
616
|
+
config.FAIL_PERCENT = 0
|
|
617
|
+
|
|
618
|
+
def should_raise_failed_hosts(state: State) -> bool:
|
|
619
|
+
if state.current_stage == StateStage.Connect:
|
|
620
|
+
return not _do_confirm("One of more hosts failed to connect, continue?")
|
|
621
|
+
return not _do_confirm("One of more hosts failed, continue?")
|
|
622
|
+
|
|
623
|
+
state.should_raise_failed_hosts = should_raise_failed_hosts
|
|
624
|
+
|
|
625
|
+
|
|
581
626
|
def _apply_inventory_limit(inventory, limit):
|
|
582
627
|
initial_limit = None
|
|
583
628
|
if limit:
|
|
@@ -600,27 +645,34 @@ def _apply_inventory_limit(inventory, limit):
|
|
|
600
645
|
|
|
601
646
|
# Operations Execution
|
|
602
647
|
#
|
|
603
|
-
def _handle_commands(state, config, command, original_operations, operations
|
|
604
|
-
|
|
648
|
+
def _handle_commands(state, config, command, original_operations, operations):
|
|
605
649
|
if command is CliCommands.FACT:
|
|
606
|
-
state, fact_data = _run_fact_operations(state, config, operations
|
|
650
|
+
state, fact_data = _run_fact_operations(state, config, operations)
|
|
607
651
|
print_facts(fact_data)
|
|
608
652
|
_exit()
|
|
609
653
|
|
|
654
|
+
can_diff = True
|
|
655
|
+
|
|
610
656
|
if command == CliCommands.SHELL:
|
|
611
|
-
state =
|
|
657
|
+
state = _prepare_exec_operations(state, config, operations)
|
|
658
|
+
can_diff = False
|
|
612
659
|
|
|
613
660
|
elif command == CliCommands.DEPLOY_FILES:
|
|
614
|
-
state, config, operations =
|
|
661
|
+
state, config, operations = _prepare_deploy_operations(state, config, operations)
|
|
615
662
|
|
|
616
663
|
elif command == CliCommands.FUNC:
|
|
617
|
-
state, kwargs =
|
|
664
|
+
state, kwargs = _prepare_func_operations(
|
|
665
|
+
state,
|
|
666
|
+
config,
|
|
667
|
+
operations,
|
|
668
|
+
original_operations,
|
|
669
|
+
)
|
|
618
670
|
|
|
619
|
-
return state, config
|
|
671
|
+
return can_diff, state, config
|
|
620
672
|
|
|
621
673
|
|
|
622
|
-
def _run_fact_operations(state, config, operations
|
|
623
|
-
|
|
674
|
+
def _run_fact_operations(state, config, operations):
|
|
675
|
+
logger.info("--> Gathering facts...")
|
|
624
676
|
|
|
625
677
|
state.print_fact_info = True
|
|
626
678
|
fact_data = {}
|
|
@@ -648,7 +700,7 @@ def _run_fact_operations(state, config, operations, quiet):
|
|
|
648
700
|
return state, fact_data
|
|
649
701
|
|
|
650
702
|
|
|
651
|
-
def
|
|
703
|
+
def _prepare_exec_operations(state, config, operations):
|
|
652
704
|
state.print_output = True
|
|
653
705
|
load_func(
|
|
654
706
|
state,
|
|
@@ -658,8 +710,8 @@ def _run_exec_operations(state, config, operations, quiet):
|
|
|
658
710
|
return state
|
|
659
711
|
|
|
660
712
|
|
|
661
|
-
def
|
|
662
|
-
|
|
713
|
+
def _prepare_deploy_operations(state, config, operations):
|
|
714
|
+
logger.info("--> Preparing Operations...")
|
|
663
715
|
|
|
664
716
|
# Number of "steps" to make = number of files * number of hosts
|
|
665
717
|
for i, filename in enumerate(operations):
|
|
@@ -675,8 +727,8 @@ def _run_deploy_operations(state, config, operations, quiet):
|
|
|
675
727
|
return state, config, operations
|
|
676
728
|
|
|
677
729
|
|
|
678
|
-
def
|
|
679
|
-
|
|
730
|
+
def _prepare_func_operations(state, config, operations, original_operations):
|
|
731
|
+
logger.info("--> Preparing operation...")
|
|
680
732
|
|
|
681
733
|
op, args = operations
|
|
682
734
|
args, kwargs = args
|
|
@@ -684,12 +736,3 @@ def _run_func_operations(state, config, operations, original_operations, quiet):
|
|
|
684
736
|
load_func(state, op, *args, **kwargs)
|
|
685
737
|
|
|
686
738
|
return state, kwargs
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
# Utils
|
|
690
|
-
#
|
|
691
|
-
def echo_msg(msg=None, quiet=None):
|
|
692
|
-
if not quiet:
|
|
693
|
-
click.echo(err=True)
|
|
694
|
-
if msg:
|
|
695
|
-
click.echo(msg, err=True)
|