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.
Files changed (203) hide show
  1. pyinfra/__init__.py +9 -12
  2. pyinfra/__main__.py +4 -0
  3. pyinfra/api/__init__.py +18 -3
  4. pyinfra/api/arguments.py +406 -0
  5. pyinfra/api/arguments_typed.py +79 -0
  6. pyinfra/api/command.py +274 -0
  7. pyinfra/api/config.py +222 -28
  8. pyinfra/api/connect.py +33 -13
  9. pyinfra/api/connectors.py +27 -0
  10. pyinfra/api/deploy.py +65 -66
  11. pyinfra/api/exceptions.py +67 -18
  12. pyinfra/api/facts.py +253 -202
  13. pyinfra/api/host.py +413 -50
  14. pyinfra/api/inventory.py +121 -160
  15. pyinfra/api/operation.py +432 -262
  16. pyinfra/api/operations.py +273 -260
  17. pyinfra/api/state.py +302 -248
  18. pyinfra/api/util.py +291 -368
  19. pyinfra/connectors/base.py +173 -0
  20. pyinfra/connectors/chroot.py +212 -0
  21. pyinfra/connectors/docker.py +381 -0
  22. pyinfra/connectors/dockerssh.py +297 -0
  23. pyinfra/connectors/local.py +238 -0
  24. pyinfra/connectors/scp/__init__.py +1 -0
  25. pyinfra/connectors/scp/client.py +204 -0
  26. pyinfra/connectors/ssh.py +670 -0
  27. pyinfra/connectors/ssh_util.py +114 -0
  28. pyinfra/connectors/sshuserclient/client.py +309 -0
  29. pyinfra/connectors/sshuserclient/config.py +102 -0
  30. pyinfra/connectors/terraform.py +135 -0
  31. pyinfra/connectors/util.py +410 -0
  32. pyinfra/connectors/vagrant.py +183 -0
  33. pyinfra/context.py +145 -0
  34. pyinfra/facts/__init__.py +7 -6
  35. pyinfra/facts/apk.py +22 -7
  36. pyinfra/facts/apt.py +117 -60
  37. pyinfra/facts/brew.py +100 -15
  38. pyinfra/facts/bsdinit.py +23 -0
  39. pyinfra/facts/cargo.py +37 -0
  40. pyinfra/facts/choco.py +47 -0
  41. pyinfra/facts/crontab.py +195 -0
  42. pyinfra/facts/deb.py +94 -0
  43. pyinfra/facts/dnf.py +48 -0
  44. pyinfra/facts/docker.py +96 -23
  45. pyinfra/facts/efibootmgr.py +113 -0
  46. pyinfra/facts/files.py +630 -58
  47. pyinfra/facts/flatpak.py +77 -0
  48. pyinfra/facts/freebsd.py +70 -0
  49. pyinfra/facts/gem.py +19 -6
  50. pyinfra/facts/git.py +59 -14
  51. pyinfra/facts/gpg.py +150 -0
  52. pyinfra/facts/hardware.py +313 -167
  53. pyinfra/facts/iptables.py +72 -62
  54. pyinfra/facts/launchd.py +44 -0
  55. pyinfra/facts/lxd.py +17 -4
  56. pyinfra/facts/mysql.py +122 -86
  57. pyinfra/facts/npm.py +17 -9
  58. pyinfra/facts/openrc.py +71 -0
  59. pyinfra/facts/opkg.py +246 -0
  60. pyinfra/facts/pacman.py +50 -7
  61. pyinfra/facts/pip.py +24 -7
  62. pyinfra/facts/pipx.py +82 -0
  63. pyinfra/facts/pkg.py +15 -6
  64. pyinfra/facts/pkgin.py +35 -0
  65. pyinfra/facts/podman.py +54 -0
  66. pyinfra/facts/postgres.py +178 -0
  67. pyinfra/facts/postgresql.py +6 -147
  68. pyinfra/facts/rpm.py +105 -0
  69. pyinfra/facts/runit.py +77 -0
  70. pyinfra/facts/selinux.py +161 -0
  71. pyinfra/facts/server.py +746 -285
  72. pyinfra/facts/snap.py +88 -0
  73. pyinfra/facts/systemd.py +139 -0
  74. pyinfra/facts/sysvinit.py +59 -0
  75. pyinfra/facts/upstart.py +35 -0
  76. pyinfra/facts/util/__init__.py +17 -0
  77. pyinfra/facts/util/databases.py +4 -6
  78. pyinfra/facts/util/packaging.py +37 -6
  79. pyinfra/facts/util/units.py +30 -0
  80. pyinfra/facts/util/win_files.py +99 -0
  81. pyinfra/facts/vzctl.py +20 -13
  82. pyinfra/facts/xbps.py +35 -0
  83. pyinfra/facts/yum.py +34 -40
  84. pyinfra/facts/zfs.py +77 -0
  85. pyinfra/facts/zypper.py +42 -0
  86. pyinfra/local.py +45 -83
  87. pyinfra/operations/__init__.py +12 -0
  88. pyinfra/operations/apk.py +98 -0
  89. pyinfra/operations/apt.py +488 -0
  90. pyinfra/operations/brew.py +231 -0
  91. pyinfra/operations/bsdinit.py +59 -0
  92. pyinfra/operations/cargo.py +45 -0
  93. pyinfra/operations/choco.py +61 -0
  94. pyinfra/operations/crontab.py +191 -0
  95. pyinfra/operations/dnf.py +210 -0
  96. pyinfra/operations/docker.py +446 -0
  97. pyinfra/operations/files.py +1939 -0
  98. pyinfra/operations/flatpak.py +94 -0
  99. pyinfra/operations/freebsd/__init__.py +12 -0
  100. pyinfra/operations/freebsd/freebsd_update.py +70 -0
  101. pyinfra/operations/freebsd/pkg.py +219 -0
  102. pyinfra/operations/freebsd/service.py +116 -0
  103. pyinfra/operations/freebsd/sysrc.py +92 -0
  104. pyinfra/operations/gem.py +47 -0
  105. pyinfra/operations/git.py +419 -0
  106. pyinfra/operations/iptables.py +311 -0
  107. pyinfra/operations/launchd.py +45 -0
  108. pyinfra/operations/lxd.py +68 -0
  109. pyinfra/operations/mysql.py +609 -0
  110. pyinfra/operations/npm.py +57 -0
  111. pyinfra/operations/openrc.py +63 -0
  112. pyinfra/operations/opkg.py +88 -0
  113. pyinfra/operations/pacman.py +81 -0
  114. pyinfra/operations/pip.py +205 -0
  115. pyinfra/operations/pipx.py +102 -0
  116. pyinfra/operations/pkg.py +70 -0
  117. pyinfra/operations/pkgin.py +91 -0
  118. pyinfra/operations/postgres.py +436 -0
  119. pyinfra/operations/postgresql.py +30 -0
  120. pyinfra/operations/puppet.py +40 -0
  121. pyinfra/operations/python.py +72 -0
  122. pyinfra/operations/runit.py +184 -0
  123. pyinfra/operations/selinux.py +189 -0
  124. pyinfra/operations/server.py +1099 -0
  125. pyinfra/operations/snap.py +117 -0
  126. pyinfra/operations/ssh.py +216 -0
  127. pyinfra/operations/systemd.py +149 -0
  128. pyinfra/operations/sysvinit.py +141 -0
  129. pyinfra/operations/upstart.py +68 -0
  130. pyinfra/operations/util/__init__.py +12 -0
  131. pyinfra/operations/util/docker.py +251 -0
  132. pyinfra/operations/util/files.py +247 -0
  133. pyinfra/operations/util/packaging.py +336 -0
  134. pyinfra/operations/util/service.py +46 -0
  135. pyinfra/operations/vzctl.py +137 -0
  136. pyinfra/operations/xbps.py +77 -0
  137. pyinfra/operations/yum.py +210 -0
  138. pyinfra/operations/zfs.py +175 -0
  139. pyinfra/operations/zypper.py +192 -0
  140. pyinfra/progress.py +44 -32
  141. pyinfra/py.typed +0 -0
  142. pyinfra/version.py +9 -1
  143. pyinfra-3.5.1.dist-info/METADATA +141 -0
  144. pyinfra-3.5.1.dist-info/RECORD +159 -0
  145. {pyinfra-0.11.dev3.dist-info → pyinfra-3.5.1.dist-info}/WHEEL +1 -2
  146. pyinfra-3.5.1.dist-info/entry_points.txt +12 -0
  147. {pyinfra-0.11.dev3.dist-info → pyinfra-3.5.1.dist-info/licenses}/LICENSE.md +1 -1
  148. pyinfra_cli/__init__.py +1 -0
  149. pyinfra_cli/cli.py +780 -0
  150. pyinfra_cli/commands.py +66 -0
  151. pyinfra_cli/exceptions.py +155 -65
  152. pyinfra_cli/inventory.py +233 -89
  153. pyinfra_cli/log.py +39 -43
  154. pyinfra_cli/main.py +26 -495
  155. pyinfra_cli/prints.py +215 -156
  156. pyinfra_cli/util.py +172 -105
  157. pyinfra_cli/virtualenv.py +25 -20
  158. pyinfra/api/connectors/__init__.py +0 -21
  159. pyinfra/api/connectors/ansible.py +0 -99
  160. pyinfra/api/connectors/docker.py +0 -178
  161. pyinfra/api/connectors/local.py +0 -169
  162. pyinfra/api/connectors/ssh.py +0 -402
  163. pyinfra/api/connectors/sshuserclient/client.py +0 -105
  164. pyinfra/api/connectors/sshuserclient/config.py +0 -90
  165. pyinfra/api/connectors/util.py +0 -63
  166. pyinfra/api/connectors/vagrant.py +0 -155
  167. pyinfra/facts/init.py +0 -176
  168. pyinfra/facts/util/files.py +0 -102
  169. pyinfra/hook.py +0 -41
  170. pyinfra/modules/__init__.py +0 -11
  171. pyinfra/modules/apk.py +0 -64
  172. pyinfra/modules/apt.py +0 -272
  173. pyinfra/modules/brew.py +0 -122
  174. pyinfra/modules/files.py +0 -711
  175. pyinfra/modules/gem.py +0 -30
  176. pyinfra/modules/git.py +0 -115
  177. pyinfra/modules/init.py +0 -344
  178. pyinfra/modules/iptables.py +0 -271
  179. pyinfra/modules/lxd.py +0 -45
  180. pyinfra/modules/mysql.py +0 -347
  181. pyinfra/modules/npm.py +0 -47
  182. pyinfra/modules/pacman.py +0 -60
  183. pyinfra/modules/pip.py +0 -99
  184. pyinfra/modules/pkg.py +0 -43
  185. pyinfra/modules/postgresql.py +0 -245
  186. pyinfra/modules/puppet.py +0 -20
  187. pyinfra/modules/python.py +0 -37
  188. pyinfra/modules/server.py +0 -524
  189. pyinfra/modules/ssh.py +0 -150
  190. pyinfra/modules/util/files.py +0 -52
  191. pyinfra/modules/util/packaging.py +0 -118
  192. pyinfra/modules/vzctl.py +0 -133
  193. pyinfra/modules/yum.py +0 -171
  194. pyinfra/pseudo_modules.py +0 -64
  195. pyinfra-0.11.dev3.dist-info/.DS_Store +0 -0
  196. pyinfra-0.11.dev3.dist-info/METADATA +0 -135
  197. pyinfra-0.11.dev3.dist-info/RECORD +0 -95
  198. pyinfra-0.11.dev3.dist-info/entry_points.txt +0 -3
  199. pyinfra-0.11.dev3.dist-info/top_level.txt +0 -2
  200. pyinfra_cli/__main__.py +0 -40
  201. pyinfra_cli/config.py +0 -92
  202. /pyinfra/{modules/util → connectors}/__init__.py +0 -0
  203. /pyinfra/{api/connectors → connectors}/sshuserclient/__init__.py +0 -0
pyinfra_cli/main.py CHANGED
@@ -1,509 +1,40 @@
1
- import logging
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
- from pyinfra import (
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
- Documentation: pyinfra.readthedocs.io
9
+ from .cli import cli
127
10
 
128
- # INVENTORY
129
11
 
130
- \b
131
- + a file (inventory.py)
132
- + hostname (host.net)
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
- # OPERATIONS
16
+ # Don't write out deploy.pyc/config.pyc etc
17
+ sys.dont_write_bytecode = True
137
18
 
138
- \b
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
- \b
143
- # Run a single operation against the inventory
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
- \b
147
- # Execute an arbitrary command on the inventory
148
- pyinfra INVENTORY exec -- echo "hello world"
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
- \b
151
- # Run one or more facts on the inventory
152
- pyinfra INVENTORY fact linux_distribution [users]...
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
- _main(*args, **kwargs)
187
-
188
- except PyinfraError as e:
189
- # Re-raise any internal exceptions that aren't handled by click as
190
- # CliErrors which are.
191
- if not isinstance(e, click.ClickException):
192
- message = getattr(e, 'message', e.args[0])
193
- raise CliError(message)
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()