pyinfra 0.11.dev3__py3-none-any.whl → 3.5.1__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/__init__.py +9 -12
- pyinfra/__main__.py +4 -0
- pyinfra/api/__init__.py +18 -3
- pyinfra/api/arguments.py +406 -0
- pyinfra/api/arguments_typed.py +79 -0
- pyinfra/api/command.py +274 -0
- pyinfra/api/config.py +222 -28
- pyinfra/api/connect.py +33 -13
- pyinfra/api/connectors.py +27 -0
- pyinfra/api/deploy.py +65 -66
- pyinfra/api/exceptions.py +67 -18
- pyinfra/api/facts.py +253 -202
- pyinfra/api/host.py +413 -50
- pyinfra/api/inventory.py +121 -160
- pyinfra/api/operation.py +432 -262
- pyinfra/api/operations.py +273 -260
- pyinfra/api/state.py +302 -248
- pyinfra/api/util.py +291 -368
- pyinfra/connectors/base.py +173 -0
- pyinfra/connectors/chroot.py +212 -0
- pyinfra/connectors/docker.py +381 -0
- pyinfra/connectors/dockerssh.py +297 -0
- pyinfra/connectors/local.py +238 -0
- pyinfra/connectors/scp/__init__.py +1 -0
- pyinfra/connectors/scp/client.py +204 -0
- pyinfra/connectors/ssh.py +670 -0
- pyinfra/connectors/ssh_util.py +114 -0
- pyinfra/connectors/sshuserclient/client.py +309 -0
- pyinfra/connectors/sshuserclient/config.py +102 -0
- pyinfra/connectors/terraform.py +135 -0
- pyinfra/connectors/util.py +410 -0
- pyinfra/connectors/vagrant.py +183 -0
- pyinfra/context.py +145 -0
- pyinfra/facts/__init__.py +7 -6
- pyinfra/facts/apk.py +22 -7
- pyinfra/facts/apt.py +117 -60
- pyinfra/facts/brew.py +100 -15
- pyinfra/facts/bsdinit.py +23 -0
- pyinfra/facts/cargo.py +37 -0
- pyinfra/facts/choco.py +47 -0
- pyinfra/facts/crontab.py +195 -0
- pyinfra/facts/deb.py +94 -0
- pyinfra/facts/dnf.py +48 -0
- pyinfra/facts/docker.py +96 -23
- pyinfra/facts/efibootmgr.py +113 -0
- pyinfra/facts/files.py +630 -58
- pyinfra/facts/flatpak.py +77 -0
- pyinfra/facts/freebsd.py +70 -0
- pyinfra/facts/gem.py +19 -6
- pyinfra/facts/git.py +59 -14
- pyinfra/facts/gpg.py +150 -0
- pyinfra/facts/hardware.py +313 -167
- pyinfra/facts/iptables.py +72 -62
- pyinfra/facts/launchd.py +44 -0
- pyinfra/facts/lxd.py +17 -4
- pyinfra/facts/mysql.py +122 -86
- pyinfra/facts/npm.py +17 -9
- pyinfra/facts/openrc.py +71 -0
- pyinfra/facts/opkg.py +246 -0
- pyinfra/facts/pacman.py +50 -7
- pyinfra/facts/pip.py +24 -7
- pyinfra/facts/pipx.py +82 -0
- pyinfra/facts/pkg.py +15 -6
- pyinfra/facts/pkgin.py +35 -0
- pyinfra/facts/podman.py +54 -0
- pyinfra/facts/postgres.py +178 -0
- pyinfra/facts/postgresql.py +6 -147
- pyinfra/facts/rpm.py +105 -0
- pyinfra/facts/runit.py +77 -0
- pyinfra/facts/selinux.py +161 -0
- pyinfra/facts/server.py +746 -285
- pyinfra/facts/snap.py +88 -0
- pyinfra/facts/systemd.py +139 -0
- pyinfra/facts/sysvinit.py +59 -0
- pyinfra/facts/upstart.py +35 -0
- pyinfra/facts/util/__init__.py +17 -0
- pyinfra/facts/util/databases.py +4 -6
- pyinfra/facts/util/packaging.py +37 -6
- pyinfra/facts/util/units.py +30 -0
- pyinfra/facts/util/win_files.py +99 -0
- pyinfra/facts/vzctl.py +20 -13
- pyinfra/facts/xbps.py +35 -0
- pyinfra/facts/yum.py +34 -40
- pyinfra/facts/zfs.py +77 -0
- pyinfra/facts/zypper.py +42 -0
- pyinfra/local.py +45 -83
- pyinfra/operations/__init__.py +12 -0
- pyinfra/operations/apk.py +98 -0
- pyinfra/operations/apt.py +488 -0
- pyinfra/operations/brew.py +231 -0
- pyinfra/operations/bsdinit.py +59 -0
- pyinfra/operations/cargo.py +45 -0
- pyinfra/operations/choco.py +61 -0
- pyinfra/operations/crontab.py +191 -0
- pyinfra/operations/dnf.py +210 -0
- pyinfra/operations/docker.py +446 -0
- pyinfra/operations/files.py +1939 -0
- pyinfra/operations/flatpak.py +94 -0
- pyinfra/operations/freebsd/__init__.py +12 -0
- pyinfra/operations/freebsd/freebsd_update.py +70 -0
- pyinfra/operations/freebsd/pkg.py +219 -0
- pyinfra/operations/freebsd/service.py +116 -0
- pyinfra/operations/freebsd/sysrc.py +92 -0
- pyinfra/operations/gem.py +47 -0
- pyinfra/operations/git.py +419 -0
- pyinfra/operations/iptables.py +311 -0
- pyinfra/operations/launchd.py +45 -0
- pyinfra/operations/lxd.py +68 -0
- pyinfra/operations/mysql.py +609 -0
- pyinfra/operations/npm.py +57 -0
- pyinfra/operations/openrc.py +63 -0
- pyinfra/operations/opkg.py +88 -0
- pyinfra/operations/pacman.py +81 -0
- pyinfra/operations/pip.py +205 -0
- pyinfra/operations/pipx.py +102 -0
- pyinfra/operations/pkg.py +70 -0
- pyinfra/operations/pkgin.py +91 -0
- pyinfra/operations/postgres.py +436 -0
- pyinfra/operations/postgresql.py +30 -0
- pyinfra/operations/puppet.py +40 -0
- pyinfra/operations/python.py +72 -0
- pyinfra/operations/runit.py +184 -0
- pyinfra/operations/selinux.py +189 -0
- pyinfra/operations/server.py +1099 -0
- pyinfra/operations/snap.py +117 -0
- pyinfra/operations/ssh.py +216 -0
- pyinfra/operations/systemd.py +149 -0
- pyinfra/operations/sysvinit.py +141 -0
- pyinfra/operations/upstart.py +68 -0
- pyinfra/operations/util/__init__.py +12 -0
- pyinfra/operations/util/docker.py +251 -0
- pyinfra/operations/util/files.py +247 -0
- pyinfra/operations/util/packaging.py +336 -0
- pyinfra/operations/util/service.py +46 -0
- pyinfra/operations/vzctl.py +137 -0
- pyinfra/operations/xbps.py +77 -0
- pyinfra/operations/yum.py +210 -0
- pyinfra/operations/zfs.py +175 -0
- pyinfra/operations/zypper.py +192 -0
- pyinfra/progress.py +44 -32
- pyinfra/py.typed +0 -0
- pyinfra/version.py +9 -1
- pyinfra-3.5.1.dist-info/METADATA +141 -0
- pyinfra-3.5.1.dist-info/RECORD +159 -0
- {pyinfra-0.11.dev3.dist-info → pyinfra-3.5.1.dist-info}/WHEEL +1 -2
- pyinfra-3.5.1.dist-info/entry_points.txt +12 -0
- {pyinfra-0.11.dev3.dist-info → pyinfra-3.5.1.dist-info/licenses}/LICENSE.md +1 -1
- pyinfra_cli/__init__.py +1 -0
- pyinfra_cli/cli.py +780 -0
- pyinfra_cli/commands.py +66 -0
- pyinfra_cli/exceptions.py +155 -65
- pyinfra_cli/inventory.py +233 -89
- pyinfra_cli/log.py +39 -43
- pyinfra_cli/main.py +26 -495
- pyinfra_cli/prints.py +215 -156
- pyinfra_cli/util.py +172 -105
- pyinfra_cli/virtualenv.py +25 -20
- pyinfra/api/connectors/__init__.py +0 -21
- pyinfra/api/connectors/ansible.py +0 -99
- pyinfra/api/connectors/docker.py +0 -178
- pyinfra/api/connectors/local.py +0 -169
- pyinfra/api/connectors/ssh.py +0 -402
- pyinfra/api/connectors/sshuserclient/client.py +0 -105
- pyinfra/api/connectors/sshuserclient/config.py +0 -90
- pyinfra/api/connectors/util.py +0 -63
- pyinfra/api/connectors/vagrant.py +0 -155
- pyinfra/facts/init.py +0 -176
- pyinfra/facts/util/files.py +0 -102
- pyinfra/hook.py +0 -41
- pyinfra/modules/__init__.py +0 -11
- pyinfra/modules/apk.py +0 -64
- pyinfra/modules/apt.py +0 -272
- pyinfra/modules/brew.py +0 -122
- pyinfra/modules/files.py +0 -711
- pyinfra/modules/gem.py +0 -30
- pyinfra/modules/git.py +0 -115
- pyinfra/modules/init.py +0 -344
- pyinfra/modules/iptables.py +0 -271
- pyinfra/modules/lxd.py +0 -45
- pyinfra/modules/mysql.py +0 -347
- pyinfra/modules/npm.py +0 -47
- pyinfra/modules/pacman.py +0 -60
- pyinfra/modules/pip.py +0 -99
- pyinfra/modules/pkg.py +0 -43
- pyinfra/modules/postgresql.py +0 -245
- pyinfra/modules/puppet.py +0 -20
- pyinfra/modules/python.py +0 -37
- pyinfra/modules/server.py +0 -524
- pyinfra/modules/ssh.py +0 -150
- pyinfra/modules/util/files.py +0 -52
- pyinfra/modules/util/packaging.py +0 -118
- pyinfra/modules/vzctl.py +0 -133
- pyinfra/modules/yum.py +0 -171
- pyinfra/pseudo_modules.py +0 -64
- pyinfra-0.11.dev3.dist-info/.DS_Store +0 -0
- pyinfra-0.11.dev3.dist-info/METADATA +0 -135
- pyinfra-0.11.dev3.dist-info/RECORD +0 -95
- pyinfra-0.11.dev3.dist-info/entry_points.txt +0 -3
- pyinfra-0.11.dev3.dist-info/top_level.txt +0 -2
- pyinfra_cli/__main__.py +0 -40
- pyinfra_cli/config.py +0 -92
- /pyinfra/{modules/util → connectors}/__init__.py +0 -0
- /pyinfra/{api/connectors → connectors}/sshuserclient/__init__.py +0 -0
pyinfra_cli/main.py
CHANGED
|
@@ -1,509 +1,40 @@
|
|
|
1
|
-
import
|
|
1
|
+
import signal
|
|
2
2
|
import sys
|
|
3
|
-
import warnings
|
|
4
|
-
|
|
5
|
-
from fnmatch import fnmatch
|
|
6
|
-
from os import getcwd, path
|
|
7
3
|
|
|
8
4
|
import click
|
|
5
|
+
import gevent
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
__version__,
|
|
12
|
-
logger,
|
|
13
|
-
pseudo_inventory,
|
|
14
|
-
pseudo_state,
|
|
15
|
-
)
|
|
16
|
-
from pyinfra.api import State
|
|
17
|
-
from pyinfra.api.connect import connect_all, disconnect_all
|
|
18
|
-
from pyinfra.api.exceptions import NoGroupError, PyinfraError
|
|
19
|
-
from pyinfra.api.facts import get_facts, is_fact
|
|
20
|
-
from pyinfra.api.operation import add_op
|
|
21
|
-
from pyinfra.api.operations import run_ops
|
|
22
|
-
from pyinfra.api.util import FallbackDict
|
|
23
|
-
from pyinfra.modules import server
|
|
24
|
-
|
|
25
|
-
from .config import load_config, load_deploy_config
|
|
26
|
-
from .exceptions import CliError, UnexpectedError
|
|
27
|
-
from .inventory import make_inventory
|
|
28
|
-
from .log import setup_logging
|
|
29
|
-
from .prints import (
|
|
30
|
-
print_facts,
|
|
31
|
-
print_facts_list,
|
|
32
|
-
print_inventory,
|
|
33
|
-
print_meta,
|
|
34
|
-
print_operations_list,
|
|
35
|
-
print_results,
|
|
36
|
-
print_state_facts,
|
|
37
|
-
print_state_operations,
|
|
38
|
-
)
|
|
39
|
-
from .util import (
|
|
40
|
-
get_operation_and_args,
|
|
41
|
-
load_deploy_file,
|
|
42
|
-
run_hook,
|
|
43
|
-
)
|
|
44
|
-
from .virtualenv import init_virtualenv
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
# Exit handler
|
|
48
|
-
def _exit():
|
|
49
|
-
sys.exit(0)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def _print_facts(ctx, param, value):
|
|
53
|
-
if not value:
|
|
54
|
-
return
|
|
55
|
-
|
|
56
|
-
print('--> Available facts:')
|
|
57
|
-
print_facts_list()
|
|
58
|
-
ctx.exit()
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def _print_operations(ctx, param, value):
|
|
62
|
-
if not value:
|
|
63
|
-
return
|
|
64
|
-
|
|
65
|
-
print('--> Available operations:')
|
|
66
|
-
print_operations_list()
|
|
67
|
-
ctx.exit()
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@click.command()
|
|
71
|
-
@click.argument('inventory', nargs=1)
|
|
72
|
-
@click.argument('operations', nargs=-1, required=True)
|
|
73
|
-
@click.option(
|
|
74
|
-
'verbosity', '-v',
|
|
75
|
-
count=True,
|
|
76
|
-
help='Print std[out|err] from operations/facts.',
|
|
77
|
-
)
|
|
78
|
-
@click.option('--user', help='SSH user to connect as.')
|
|
79
|
-
@click.option('--port', type=int, help='SSH port to connect to.')
|
|
80
|
-
@click.option('--key', type=click.Path(), help='Private key filename.')
|
|
81
|
-
@click.option('--key-password', help='Privte key password.')
|
|
82
|
-
@click.option('--password', help='SSH password.')
|
|
83
|
-
@click.option(
|
|
84
|
-
'--sudo', is_flag=True, default=False,
|
|
85
|
-
help='Whether to execute operations with sudo.',
|
|
86
|
-
)
|
|
87
|
-
@click.option('--sudo-user', help='Which user to sudo when sudoing.')
|
|
88
|
-
@click.option('--su-user', help='Which user to su to.')
|
|
89
|
-
@click.option('--parallel', type=int, help='Number of operations to run in parallel.')
|
|
90
|
-
@click.option('--fail-percent', type=int, help='% of hosts allowed to fail.')
|
|
91
|
-
@click.option(
|
|
92
|
-
'--dry', is_flag=True, default=False,
|
|
93
|
-
help="Don't execute operations on the target hosts.",
|
|
94
|
-
)
|
|
95
|
-
@click.option(
|
|
96
|
-
'--limit',
|
|
97
|
-
help='Restrict the target hosts by name and group name.',
|
|
98
|
-
)
|
|
99
|
-
@click.option(
|
|
100
|
-
'--no-wait', is_flag=True, default=False,
|
|
101
|
-
help="Don't wait between operations for hosts to complete.",
|
|
102
|
-
)
|
|
103
|
-
@click.option(
|
|
104
|
-
'--serial', is_flag=True, default=False,
|
|
105
|
-
help='Run operations in serial, host by host.',
|
|
106
|
-
)
|
|
107
|
-
# Eager commands (pyinfra [--facts | --operations | --version])
|
|
108
|
-
@click.option(
|
|
109
|
-
'--facts', is_flag=True, is_eager=True, callback=_print_facts,
|
|
110
|
-
help='Print available facts list and exit.',
|
|
111
|
-
)
|
|
112
|
-
@click.option(
|
|
113
|
-
'print_operations', '--operations', is_flag=True, is_eager=True, callback=_print_operations,
|
|
114
|
-
help='Print available operations list and exit.',
|
|
115
|
-
)
|
|
116
|
-
@click.version_option(
|
|
117
|
-
version=__version__,
|
|
118
|
-
prog_name='pyinfra',
|
|
119
|
-
message='%(prog)s: v%(version)s\nExecutable: {0}'.format(sys.argv[0]),
|
|
120
|
-
)
|
|
121
|
-
def cli(*args, **kwargs):
|
|
122
|
-
'''
|
|
123
|
-
pyinfra manages the state of one or more servers. It can be used for
|
|
124
|
-
app/service deployment, config management and ad-hoc command execution.
|
|
7
|
+
import pyinfra
|
|
125
8
|
|
|
126
|
-
|
|
9
|
+
from .cli import cli
|
|
127
10
|
|
|
128
|
-
# INVENTORY
|
|
129
11
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
+ Comma separated hostnames:
|
|
134
|
-
host-1.net,host-2.net,@local
|
|
12
|
+
def main():
|
|
13
|
+
# Set CLI mode
|
|
14
|
+
pyinfra.is_cli = True
|
|
135
15
|
|
|
136
|
-
#
|
|
16
|
+
# Don't write out deploy.pyc/config.pyc etc
|
|
17
|
+
sys.dont_write_bytecode = True
|
|
137
18
|
|
|
138
|
-
|
|
139
|
-
# Run one or more deploys against the inventory
|
|
140
|
-
pyinfra INVENTORY deploy_web.py [deploy_db.py]...
|
|
19
|
+
sys.path.append(".")
|
|
141
20
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
pyinfra INVENTORY server.user pyinfra home=/home/pyinfra
|
|
21
|
+
# Shut it click
|
|
22
|
+
click.disable_unicode_literals_warning = True # type: ignore
|
|
145
23
|
|
|
146
|
-
|
|
147
|
-
#
|
|
148
|
-
|
|
24
|
+
# Force line buffering
|
|
25
|
+
sys.stdout.reconfigure(line_buffering=True) # type: ignore
|
|
26
|
+
sys.stderr.reconfigure(line_buffering=True) # type: ignore
|
|
149
27
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
'''
|
|
28
|
+
def _handle_interrupt(signum, frame):
|
|
29
|
+
click.echo("Exiting upon user request!")
|
|
30
|
+
sys.exit(0)
|
|
154
31
|
|
|
155
|
-
main(*args, **kwargs)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
# This is a hack around Click 7 not being released (like, forever) which has the
|
|
159
|
-
# magical click.option(hidden=True) capability.
|
|
160
|
-
if '--help' not in sys.argv:
|
|
161
|
-
extra_options = (
|
|
162
|
-
click.option(
|
|
163
|
-
'--debug', is_flag=True, default=False,
|
|
164
|
-
help='Print debug info.',
|
|
165
|
-
),
|
|
166
|
-
click.option(
|
|
167
|
-
'--debug-data', is_flag=True, default=False,
|
|
168
|
-
help='Print host/group data before connecting and exit.',
|
|
169
|
-
),
|
|
170
|
-
click.option(
|
|
171
|
-
'--debug-facts', is_flag=True, default=False,
|
|
172
|
-
help='Print facts after generating operations and exit.',
|
|
173
|
-
),
|
|
174
|
-
click.option(
|
|
175
|
-
'--debug-operations', is_flag=True, default=False,
|
|
176
|
-
help='Print operations after generating and exit.',
|
|
177
|
-
),
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
for decorator in extra_options:
|
|
181
|
-
cli = decorator(cli)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
def main(*args, **kwargs):
|
|
185
32
|
try:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
except
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
raise
|
|
196
|
-
|
|
197
|
-
except Exception as e:
|
|
198
|
-
# Attach the tracback to the exception before returning as state (Py2
|
|
199
|
-
# does not have `Exception.__traceback__`).
|
|
200
|
-
_, _, traceback = sys.exc_info()
|
|
201
|
-
e._traceback = traceback
|
|
202
|
-
|
|
203
|
-
# Re-raise any unexpected exceptions as UnexpectedError
|
|
204
|
-
raise UnexpectedError(e)
|
|
205
|
-
|
|
206
|
-
finally:
|
|
207
|
-
if pseudo_state.isset() and pseudo_state.initialised:
|
|
208
|
-
# Triggers any executor disconnect requirements
|
|
209
|
-
disconnect_all(pseudo_state)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
def _main(
|
|
213
|
-
inventory, operations, verbosity,
|
|
214
|
-
user, port, key, key_password, password,
|
|
215
|
-
sudo, sudo_user, su_user,
|
|
216
|
-
parallel, fail_percent,
|
|
217
|
-
dry, limit, no_wait, serial,
|
|
218
|
-
debug, debug_data, debug_facts, debug_operations,
|
|
219
|
-
facts=None, print_operations=None,
|
|
220
|
-
):
|
|
221
|
-
if not debug and not sys.warnoptions:
|
|
222
|
-
warnings.simplefilter('ignore')
|
|
223
|
-
|
|
224
|
-
# Setup logging
|
|
225
|
-
log_level = logging.DEBUG if debug else logging.INFO
|
|
226
|
-
setup_logging(log_level)
|
|
227
|
-
|
|
228
|
-
# Bootstrap any virtualenv
|
|
229
|
-
init_virtualenv()
|
|
230
|
-
|
|
231
|
-
deploy_dir = getcwd()
|
|
232
|
-
potential_deploy_dirs = []
|
|
233
|
-
|
|
234
|
-
# This is the most common case: we have a deploy file so use it's
|
|
235
|
-
# pathname - we only look at the first file as we can't have multiple
|
|
236
|
-
# deploy directories.
|
|
237
|
-
if operations[0].endswith('.py'):
|
|
238
|
-
deploy_file_dir, _ = path.split(operations[0])
|
|
239
|
-
above_deploy_file_dir, _ = path.split(deploy_file_dir)
|
|
240
|
-
|
|
241
|
-
deploy_dir = deploy_file_dir
|
|
242
|
-
|
|
243
|
-
potential_deploy_dirs.extend((
|
|
244
|
-
deploy_file_dir, above_deploy_file_dir,
|
|
245
|
-
))
|
|
246
|
-
|
|
247
|
-
# If we have a valid inventory, look in it's path and it's parent for
|
|
248
|
-
# group_data or config.py to indicate deploy_dir (--fact, --run).
|
|
249
|
-
if inventory.endswith('.py') and path.isfile(inventory):
|
|
250
|
-
inventory_dir, _ = path.split(inventory)
|
|
251
|
-
above_inventory_dir, _ = path.split(inventory_dir)
|
|
252
|
-
|
|
253
|
-
potential_deploy_dirs.extend((
|
|
254
|
-
inventory_dir, above_inventory_dir,
|
|
255
|
-
))
|
|
256
|
-
|
|
257
|
-
for potential_deploy_dir in potential_deploy_dirs:
|
|
258
|
-
logger.debug('Checking potential directory: {0}'.format(
|
|
259
|
-
potential_deploy_dir,
|
|
260
|
-
))
|
|
261
|
-
|
|
262
|
-
if any((
|
|
263
|
-
path.isdir(path.join(potential_deploy_dir, 'group_data')),
|
|
264
|
-
path.isfile(path.join(potential_deploy_dir, 'config.py')),
|
|
265
|
-
)):
|
|
266
|
-
logger.debug('Setting directory to: {0}'.format(potential_deploy_dir))
|
|
267
|
-
deploy_dir = potential_deploy_dir
|
|
268
|
-
break
|
|
269
|
-
|
|
270
|
-
# List facts
|
|
271
|
-
if operations[0] == 'fact':
|
|
272
|
-
command = 'fact'
|
|
273
|
-
|
|
274
|
-
fact_names = operations[1:]
|
|
275
|
-
facts = []
|
|
276
|
-
|
|
277
|
-
for name in fact_names:
|
|
278
|
-
args = None
|
|
279
|
-
|
|
280
|
-
if ':' in name:
|
|
281
|
-
name, args = name.split(':', 1)
|
|
282
|
-
args = args.split(',')
|
|
283
|
-
|
|
284
|
-
if not is_fact(name):
|
|
285
|
-
raise CliError('No fact: {0}'.format(name))
|
|
286
|
-
|
|
287
|
-
facts.append((name, args))
|
|
288
|
-
|
|
289
|
-
operations = facts
|
|
290
|
-
|
|
291
|
-
# Execute a raw command with server.shell
|
|
292
|
-
elif operations[0] == 'exec':
|
|
293
|
-
command = 'exec'
|
|
294
|
-
operations = operations[1:]
|
|
295
|
-
|
|
296
|
-
# Deploy files(s)
|
|
297
|
-
elif all(cmd.endswith('.py') for cmd in operations):
|
|
298
|
-
command = 'deploy'
|
|
299
|
-
operations = operations[0:]
|
|
300
|
-
|
|
301
|
-
# Check each file exists
|
|
302
|
-
for file in operations:
|
|
303
|
-
if not path.exists(file):
|
|
304
|
-
raise CliError('No deploy file: {0}'.format(file))
|
|
305
|
-
|
|
306
|
-
# Operation w/optional args (<module>.<op> ARG1 ARG2 ...)
|
|
307
|
-
elif len(operations[0].split('.')) == 2:
|
|
308
|
-
command = 'op'
|
|
309
|
-
operations = get_operation_and_args(operations)
|
|
310
|
-
|
|
311
|
-
else:
|
|
312
|
-
raise CliError('''Invalid operations: {0}
|
|
313
|
-
|
|
314
|
-
Operation usage:
|
|
315
|
-
pyinfra INVENTORY deploy_web.py [deploy_db.py]...
|
|
316
|
-
pyinfra INVENTORY server.user pyinfra home=/home/pyinfra
|
|
317
|
-
pyinfra INVENTORY exec -- echo "hello world"
|
|
318
|
-
pyinfra INVENTORY fact os [users]...'''.format(operations))
|
|
319
|
-
|
|
320
|
-
# Create an empty/unitialised state object
|
|
321
|
-
state = State()
|
|
322
|
-
pseudo_state.set(state)
|
|
323
|
-
|
|
324
|
-
# Setup printing on the new state
|
|
325
|
-
print_output = verbosity > 0
|
|
326
|
-
print_fact_output = verbosity > 1
|
|
327
|
-
|
|
328
|
-
state.print_output = print_output # -v
|
|
329
|
-
state.print_fact_info = print_output # -v
|
|
330
|
-
state.print_fact_output = print_fact_output # -vv
|
|
331
|
-
|
|
332
|
-
print('--> Loading config...')
|
|
333
|
-
|
|
334
|
-
# Load up any config.py from the filesystem
|
|
335
|
-
config = load_config(deploy_dir)
|
|
336
|
-
|
|
337
|
-
# Load any hooks/config from the deploy file
|
|
338
|
-
if command == 'deploy':
|
|
339
|
-
load_deploy_config(operations[0], config)
|
|
340
|
-
|
|
341
|
-
# Arg based config overrides
|
|
342
|
-
if sudo:
|
|
343
|
-
config.SUDO = True
|
|
344
|
-
if sudo_user:
|
|
345
|
-
config.SUDO_USER = sudo_user
|
|
346
|
-
|
|
347
|
-
if su_user:
|
|
348
|
-
config.SU_USER = su_user
|
|
349
|
-
|
|
350
|
-
if parallel:
|
|
351
|
-
config.PARALLEL = parallel
|
|
352
|
-
|
|
353
|
-
if fail_percent is not None:
|
|
354
|
-
config.FAIL_PERCENT = fail_percent
|
|
355
|
-
|
|
356
|
-
print('--> Loading inventory...')
|
|
357
|
-
|
|
358
|
-
# Load up the inventory from the filesystem
|
|
359
|
-
inventory, inventory_group = make_inventory(
|
|
360
|
-
inventory,
|
|
361
|
-
deploy_dir=deploy_dir,
|
|
362
|
-
ssh_port=port,
|
|
363
|
-
ssh_user=user,
|
|
364
|
-
ssh_key=key,
|
|
365
|
-
ssh_key_password=key_password,
|
|
366
|
-
ssh_password=password,
|
|
367
|
-
)
|
|
368
|
-
|
|
369
|
-
# Apply any --limit to the inventory
|
|
370
|
-
limit_hosts = None
|
|
371
|
-
|
|
372
|
-
if limit:
|
|
373
|
-
try:
|
|
374
|
-
limit_hosts = inventory.get_group(limit)
|
|
375
|
-
except NoGroupError:
|
|
376
|
-
limits = limit.split(',')
|
|
377
|
-
|
|
378
|
-
limit_hosts = [
|
|
379
|
-
host for host in inventory
|
|
380
|
-
if any(fnmatch(host.name, limit) for limit in limits)
|
|
381
|
-
]
|
|
382
|
-
|
|
383
|
-
# Attach to pseudo inventory
|
|
384
|
-
pseudo_inventory.set(inventory)
|
|
385
|
-
|
|
386
|
-
# Initialise the state, passing any initial --limit
|
|
387
|
-
state.init(inventory, config, initial_limit=limit_hosts)
|
|
388
|
-
|
|
389
|
-
# If --debug-data dump & exit
|
|
390
|
-
if debug_data:
|
|
391
|
-
print_inventory(state)
|
|
392
|
-
_exit()
|
|
393
|
-
|
|
394
|
-
# Set the deploy directory
|
|
395
|
-
state.deploy_dir = deploy_dir
|
|
396
|
-
|
|
397
|
-
# Setup the data to be passed to config hooks
|
|
398
|
-
hook_data = FallbackDict(
|
|
399
|
-
state.inventory.get_override_data(),
|
|
400
|
-
state.inventory.get_group_data(inventory_group),
|
|
401
|
-
state.inventory.get_data(),
|
|
402
|
-
)
|
|
403
|
-
|
|
404
|
-
# Run the before_connect hook if provided
|
|
405
|
-
run_hook(state, 'before_connect', hook_data)
|
|
406
|
-
|
|
407
|
-
# Connect to all the servers
|
|
408
|
-
print()
|
|
409
|
-
print('--> Connecting to hosts...')
|
|
410
|
-
connect_all(state)
|
|
411
|
-
|
|
412
|
-
# Run the before_connect hook if provided
|
|
413
|
-
run_hook(state, 'before_facts', hook_data)
|
|
414
|
-
|
|
415
|
-
# Just getting a fact?
|
|
416
|
-
#
|
|
417
|
-
|
|
418
|
-
if command == 'fact':
|
|
419
|
-
print()
|
|
420
|
-
print('--> Gathering facts...')
|
|
421
|
-
|
|
422
|
-
# Print facts as we get them
|
|
423
|
-
state.print_fact_info = True
|
|
424
|
-
|
|
425
|
-
# Print fact output with -v
|
|
426
|
-
state.print_fact_output = print_output
|
|
427
|
-
|
|
428
|
-
fact_data = {}
|
|
429
|
-
|
|
430
|
-
for i, command in enumerate(operations):
|
|
431
|
-
name, args = command
|
|
432
|
-
fact_data[name] = get_facts(
|
|
433
|
-
state, name,
|
|
434
|
-
args=args,
|
|
435
|
-
)
|
|
436
|
-
|
|
437
|
-
print_facts(fact_data)
|
|
438
|
-
_exit()
|
|
439
|
-
|
|
440
|
-
# Prepare the deploy!
|
|
441
|
-
#
|
|
442
|
-
|
|
443
|
-
# Execute a raw command with server.shell
|
|
444
|
-
if command == 'exec':
|
|
445
|
-
# Print the output of the command
|
|
446
|
-
state.print_output = True
|
|
447
|
-
|
|
448
|
-
add_op(
|
|
449
|
-
state, server.shell,
|
|
450
|
-
' '.join(operations),
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
# Deploy files(s)
|
|
454
|
-
elif command == 'deploy':
|
|
455
|
-
print()
|
|
456
|
-
print('--> Preparing operations...')
|
|
457
|
-
|
|
458
|
-
# Number of "steps" to make = number of files * number of hosts
|
|
459
|
-
for i, filename in enumerate(operations):
|
|
460
|
-
logger.info('Loading: {0}'.format(click.style(filename, bold=True)))
|
|
461
|
-
state.current_op_file = i
|
|
462
|
-
load_deploy_file(state, filename)
|
|
463
|
-
|
|
464
|
-
# Operation w/optional args
|
|
465
|
-
elif command == 'op':
|
|
466
|
-
print()
|
|
467
|
-
print('--> Preparing operation...')
|
|
468
|
-
|
|
469
|
-
op, args = operations
|
|
470
|
-
|
|
471
|
-
add_op(
|
|
472
|
-
state, op,
|
|
473
|
-
*args[0], **args[1]
|
|
474
|
-
)
|
|
475
|
-
|
|
476
|
-
# Always show meta output
|
|
477
|
-
print()
|
|
478
|
-
print('--> Proposed changes:')
|
|
479
|
-
print_meta(state)
|
|
480
|
-
|
|
481
|
-
# If --debug-facts or --debug-operations, print and exit
|
|
482
|
-
if debug_facts or debug_operations:
|
|
483
|
-
if debug_facts:
|
|
484
|
-
print_state_facts(state)
|
|
485
|
-
|
|
486
|
-
if debug_operations:
|
|
487
|
-
print_state_operations(state)
|
|
488
|
-
|
|
489
|
-
_exit()
|
|
490
|
-
|
|
491
|
-
# Run the operations we generated with the deploy file
|
|
492
|
-
if dry:
|
|
493
|
-
_exit()
|
|
494
|
-
|
|
495
|
-
print()
|
|
496
|
-
|
|
497
|
-
# Run the before_deploy hook if provided
|
|
498
|
-
run_hook(state, 'before_deploy', hook_data)
|
|
499
|
-
|
|
500
|
-
print('--> Beginning operation run...')
|
|
501
|
-
run_ops(state, serial=serial, no_wait=no_wait)
|
|
502
|
-
|
|
503
|
-
# Run the after_deploy hook if provided
|
|
504
|
-
run_hook(state, 'after_deploy', hook_data)
|
|
505
|
-
|
|
506
|
-
print('--> Results:')
|
|
507
|
-
print_results(state)
|
|
508
|
-
|
|
509
|
-
_exit()
|
|
33
|
+
# Kill any greenlets on ctrl+c
|
|
34
|
+
gevent.signal_handler(signal.SIGINT, gevent.kill)
|
|
35
|
+
except AttributeError:
|
|
36
|
+
# Legacy (gevent <1.2) support
|
|
37
|
+
gevent.signal(signal.SIGINT, gevent.kill)
|
|
38
|
+
|
|
39
|
+
signal.signal(signal.SIGINT, _handle_interrupt) # print the message and exit main
|
|
40
|
+
cli()
|