pyinfra 0.11.dev3__py3-none-any.whl → 3.6__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 (204) hide show
  1. pyinfra/__init__.py +9 -12
  2. pyinfra/__main__.py +4 -0
  3. pyinfra/api/__init__.py +19 -3
  4. pyinfra/api/arguments.py +413 -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 +73 -18
  12. pyinfra/api/facts.py +267 -200
  13. pyinfra/api/host.py +416 -50
  14. pyinfra/api/inventory.py +121 -160
  15. pyinfra/api/metadata.py +69 -0
  16. pyinfra/api/operation.py +432 -262
  17. pyinfra/api/operations.py +273 -260
  18. pyinfra/api/state.py +302 -248
  19. pyinfra/api/util.py +309 -369
  20. pyinfra/connectors/base.py +173 -0
  21. pyinfra/connectors/chroot.py +212 -0
  22. pyinfra/connectors/docker.py +405 -0
  23. pyinfra/connectors/dockerssh.py +297 -0
  24. pyinfra/connectors/local.py +238 -0
  25. pyinfra/connectors/scp/__init__.py +1 -0
  26. pyinfra/connectors/scp/client.py +204 -0
  27. pyinfra/connectors/ssh.py +727 -0
  28. pyinfra/connectors/ssh_util.py +114 -0
  29. pyinfra/connectors/sshuserclient/client.py +309 -0
  30. pyinfra/connectors/sshuserclient/config.py +102 -0
  31. pyinfra/connectors/terraform.py +135 -0
  32. pyinfra/connectors/util.py +417 -0
  33. pyinfra/connectors/vagrant.py +183 -0
  34. pyinfra/context.py +145 -0
  35. pyinfra/facts/__init__.py +7 -6
  36. pyinfra/facts/apk.py +22 -7
  37. pyinfra/facts/apt.py +117 -60
  38. pyinfra/facts/brew.py +100 -15
  39. pyinfra/facts/bsdinit.py +23 -0
  40. pyinfra/facts/cargo.py +37 -0
  41. pyinfra/facts/choco.py +47 -0
  42. pyinfra/facts/crontab.py +195 -0
  43. pyinfra/facts/deb.py +94 -0
  44. pyinfra/facts/dnf.py +48 -0
  45. pyinfra/facts/docker.py +96 -23
  46. pyinfra/facts/efibootmgr.py +113 -0
  47. pyinfra/facts/files.py +629 -58
  48. pyinfra/facts/flatpak.py +77 -0
  49. pyinfra/facts/freebsd.py +70 -0
  50. pyinfra/facts/gem.py +19 -6
  51. pyinfra/facts/git.py +59 -14
  52. pyinfra/facts/gpg.py +150 -0
  53. pyinfra/facts/hardware.py +313 -167
  54. pyinfra/facts/iptables.py +72 -62
  55. pyinfra/facts/launchd.py +44 -0
  56. pyinfra/facts/lxd.py +17 -4
  57. pyinfra/facts/mysql.py +122 -86
  58. pyinfra/facts/npm.py +17 -9
  59. pyinfra/facts/openrc.py +71 -0
  60. pyinfra/facts/opkg.py +246 -0
  61. pyinfra/facts/pacman.py +50 -7
  62. pyinfra/facts/pip.py +24 -7
  63. pyinfra/facts/pipx.py +82 -0
  64. pyinfra/facts/pkg.py +15 -6
  65. pyinfra/facts/pkgin.py +35 -0
  66. pyinfra/facts/podman.py +54 -0
  67. pyinfra/facts/postgres.py +178 -0
  68. pyinfra/facts/postgresql.py +6 -147
  69. pyinfra/facts/rpm.py +105 -0
  70. pyinfra/facts/runit.py +77 -0
  71. pyinfra/facts/selinux.py +161 -0
  72. pyinfra/facts/server.py +762 -285
  73. pyinfra/facts/snap.py +88 -0
  74. pyinfra/facts/systemd.py +139 -0
  75. pyinfra/facts/sysvinit.py +59 -0
  76. pyinfra/facts/upstart.py +35 -0
  77. pyinfra/facts/util/__init__.py +17 -0
  78. pyinfra/facts/util/databases.py +4 -6
  79. pyinfra/facts/util/packaging.py +37 -6
  80. pyinfra/facts/util/units.py +30 -0
  81. pyinfra/facts/util/win_files.py +99 -0
  82. pyinfra/facts/vzctl.py +20 -13
  83. pyinfra/facts/xbps.py +35 -0
  84. pyinfra/facts/yum.py +34 -40
  85. pyinfra/facts/zfs.py +77 -0
  86. pyinfra/facts/zypper.py +42 -0
  87. pyinfra/local.py +45 -83
  88. pyinfra/operations/__init__.py +12 -0
  89. pyinfra/operations/apk.py +99 -0
  90. pyinfra/operations/apt.py +496 -0
  91. pyinfra/operations/brew.py +232 -0
  92. pyinfra/operations/bsdinit.py +59 -0
  93. pyinfra/operations/cargo.py +45 -0
  94. pyinfra/operations/choco.py +61 -0
  95. pyinfra/operations/crontab.py +194 -0
  96. pyinfra/operations/dnf.py +213 -0
  97. pyinfra/operations/docker.py +492 -0
  98. pyinfra/operations/files.py +2014 -0
  99. pyinfra/operations/flatpak.py +95 -0
  100. pyinfra/operations/freebsd/__init__.py +12 -0
  101. pyinfra/operations/freebsd/freebsd_update.py +70 -0
  102. pyinfra/operations/freebsd/pkg.py +219 -0
  103. pyinfra/operations/freebsd/service.py +116 -0
  104. pyinfra/operations/freebsd/sysrc.py +92 -0
  105. pyinfra/operations/gem.py +48 -0
  106. pyinfra/operations/git.py +420 -0
  107. pyinfra/operations/iptables.py +312 -0
  108. pyinfra/operations/launchd.py +45 -0
  109. pyinfra/operations/lxd.py +69 -0
  110. pyinfra/operations/mysql.py +610 -0
  111. pyinfra/operations/npm.py +57 -0
  112. pyinfra/operations/openrc.py +63 -0
  113. pyinfra/operations/opkg.py +89 -0
  114. pyinfra/operations/pacman.py +82 -0
  115. pyinfra/operations/pip.py +206 -0
  116. pyinfra/operations/pipx.py +103 -0
  117. pyinfra/operations/pkg.py +71 -0
  118. pyinfra/operations/pkgin.py +92 -0
  119. pyinfra/operations/postgres.py +437 -0
  120. pyinfra/operations/postgresql.py +30 -0
  121. pyinfra/operations/puppet.py +41 -0
  122. pyinfra/operations/python.py +73 -0
  123. pyinfra/operations/runit.py +184 -0
  124. pyinfra/operations/selinux.py +190 -0
  125. pyinfra/operations/server.py +1100 -0
  126. pyinfra/operations/snap.py +118 -0
  127. pyinfra/operations/ssh.py +217 -0
  128. pyinfra/operations/systemd.py +150 -0
  129. pyinfra/operations/sysvinit.py +142 -0
  130. pyinfra/operations/upstart.py +68 -0
  131. pyinfra/operations/util/__init__.py +12 -0
  132. pyinfra/operations/util/docker.py +407 -0
  133. pyinfra/operations/util/files.py +247 -0
  134. pyinfra/operations/util/packaging.py +338 -0
  135. pyinfra/operations/util/service.py +46 -0
  136. pyinfra/operations/vzctl.py +137 -0
  137. pyinfra/operations/xbps.py +78 -0
  138. pyinfra/operations/yum.py +213 -0
  139. pyinfra/operations/zfs.py +176 -0
  140. pyinfra/operations/zypper.py +193 -0
  141. pyinfra/progress.py +44 -32
  142. pyinfra/py.typed +0 -0
  143. pyinfra/version.py +9 -1
  144. pyinfra-3.6.dist-info/METADATA +142 -0
  145. pyinfra-3.6.dist-info/RECORD +160 -0
  146. {pyinfra-0.11.dev3.dist-info → pyinfra-3.6.dist-info}/WHEEL +1 -2
  147. pyinfra-3.6.dist-info/entry_points.txt +12 -0
  148. {pyinfra-0.11.dev3.dist-info → pyinfra-3.6.dist-info/licenses}/LICENSE.md +1 -1
  149. pyinfra_cli/__init__.py +1 -0
  150. pyinfra_cli/cli.py +793 -0
  151. pyinfra_cli/commands.py +66 -0
  152. pyinfra_cli/exceptions.py +155 -65
  153. pyinfra_cli/inventory.py +233 -89
  154. pyinfra_cli/log.py +39 -43
  155. pyinfra_cli/main.py +26 -495
  156. pyinfra_cli/prints.py +215 -156
  157. pyinfra_cli/util.py +172 -105
  158. pyinfra_cli/virtualenv.py +25 -20
  159. pyinfra/api/connectors/__init__.py +0 -21
  160. pyinfra/api/connectors/ansible.py +0 -99
  161. pyinfra/api/connectors/docker.py +0 -178
  162. pyinfra/api/connectors/local.py +0 -169
  163. pyinfra/api/connectors/ssh.py +0 -402
  164. pyinfra/api/connectors/sshuserclient/client.py +0 -105
  165. pyinfra/api/connectors/sshuserclient/config.py +0 -90
  166. pyinfra/api/connectors/util.py +0 -63
  167. pyinfra/api/connectors/vagrant.py +0 -155
  168. pyinfra/facts/init.py +0 -176
  169. pyinfra/facts/util/files.py +0 -102
  170. pyinfra/hook.py +0 -41
  171. pyinfra/modules/__init__.py +0 -11
  172. pyinfra/modules/apk.py +0 -64
  173. pyinfra/modules/apt.py +0 -272
  174. pyinfra/modules/brew.py +0 -122
  175. pyinfra/modules/files.py +0 -711
  176. pyinfra/modules/gem.py +0 -30
  177. pyinfra/modules/git.py +0 -115
  178. pyinfra/modules/init.py +0 -344
  179. pyinfra/modules/iptables.py +0 -271
  180. pyinfra/modules/lxd.py +0 -45
  181. pyinfra/modules/mysql.py +0 -347
  182. pyinfra/modules/npm.py +0 -47
  183. pyinfra/modules/pacman.py +0 -60
  184. pyinfra/modules/pip.py +0 -99
  185. pyinfra/modules/pkg.py +0 -43
  186. pyinfra/modules/postgresql.py +0 -245
  187. pyinfra/modules/puppet.py +0 -20
  188. pyinfra/modules/python.py +0 -37
  189. pyinfra/modules/server.py +0 -524
  190. pyinfra/modules/ssh.py +0 -150
  191. pyinfra/modules/util/files.py +0 -52
  192. pyinfra/modules/util/packaging.py +0 -118
  193. pyinfra/modules/vzctl.py +0 -133
  194. pyinfra/modules/yum.py +0 -171
  195. pyinfra/pseudo_modules.py +0 -64
  196. pyinfra-0.11.dev3.dist-info/.DS_Store +0 -0
  197. pyinfra-0.11.dev3.dist-info/METADATA +0 -135
  198. pyinfra-0.11.dev3.dist-info/RECORD +0 -95
  199. pyinfra-0.11.dev3.dist-info/entry_points.txt +0 -3
  200. pyinfra-0.11.dev3.dist-info/top_level.txt +0 -2
  201. pyinfra_cli/__main__.py +0 -40
  202. pyinfra_cli/config.py +0 -92
  203. /pyinfra/{modules/util → connectors}/__init__.py +0 -0
  204. /pyinfra/{api/connectors → connectors}/sshuserclient/__init__.py +0 -0
@@ -1,271 +0,0 @@
1
- '''
2
- The iptables modules handles iptables rules
3
- '''
4
-
5
- from pyinfra.api import operation
6
- from pyinfra.api.exceptions import OperationError
7
-
8
-
9
- @operation
10
- def chain(
11
- state, host, name, present=True,
12
- table='filter', policy=None, version=4,
13
- ):
14
- '''
15
- Add/remove/update iptables chains.
16
-
17
- + name: the name of the chain
18
- + present: whether the chain should exist
19
- + table: the iptables table this chain should belong to
20
- + policy: the policy this table should have
21
- + version: whether to target iptables or ip6tables
22
-
23
- Policy:
24
- These can only be applied to system chains (FORWARD, INPUT, OUTPUT, etc).
25
- '''
26
-
27
- chains = (
28
- host.fact.iptables_chains(table)
29
- if version == 4
30
- else host.fact.ip6tables_chains(table)
31
- )
32
-
33
- command = 'iptables' if version == 4 else 'ip6tables'
34
- command = '{0} -t {1}'.format(command, table)
35
-
36
- # Doesn't exist but we want it?
37
- if present and name not in chains:
38
- yield '{0} -N {1}'.format(command, name)
39
-
40
- if policy:
41
- yield '{0} -P {1} {2}'.format(command, name, policy)
42
-
43
- # Exists and we don't want it?
44
- if not present and name in chains:
45
- yield '{0} -X {1}'.format(command, name)
46
-
47
- # Exists, we want it, but the policies don't match?
48
- if present and name in chains and policy and chains[name] != policy:
49
- yield '{0} -P {1} {2}'.format(command, name, policy)
50
-
51
-
52
- @operation
53
- def rule(
54
- state, host, chain, jump, present=True,
55
- table='filter', append=True, version=4,
56
- # Core iptables filter arguments
57
- protocol=None, not_protocol=None,
58
- source=None, not_source=None,
59
- destination=None, not_destination=None,
60
- in_interface=None, not_in_interface=None,
61
- out_interface=None, not_out_interface=None,
62
- # After-rule arguments
63
- to_destination=None, to_source=None, to_ports=None, log_prefix=None,
64
- # Extras and extra shortcuts
65
- destination_port=None, source_port=None, extras='',
66
- ):
67
- '''
68
- Add/remove iptables rules.
69
-
70
- + chain: the chain this rule should live in
71
- + jump: the target of the rule
72
- + table: the iptables table this rule should belong to
73
- + append: whether to append or insert the rule (if not present)
74
- + version: whether to target iptables or ip6tables
75
-
76
- Iptables args:
77
-
78
- + protocol/not_protocol: filter by protocol (tcp or udp)
79
- + source/not_source: filter by source IPs
80
- + destination/not_destination: filter by destination IPs
81
- + in_interface/not_in_interface: filter by incoming interface
82
- + out_interface/not_out_interface: filter by outgoing interface
83
- + to_destination: where to route to when jump=DNAT
84
- + to_source: where to route to when jump=SNAT
85
- + to_ports: where to route to when jump=REDIRECT
86
- + log_prefix: prefix for the log of this rule when jump=LOG
87
-
88
- Extras:
89
-
90
- + extras: a place to define iptables extension arguments (eg --limit, --physdev)
91
- + destination_port: destination port (requires protocol)
92
- + source_port: source port (requires protocol)
93
-
94
- Examples:
95
-
96
- .. code:: python
97
-
98
- # Block SSH traffic
99
-
100
- iptables.rule(
101
- 'INPUT', 'DROP',
102
- destination_port=22
103
- )
104
-
105
-
106
- # NAT traffic on from 8.8.8.8:53 to 8.8.4.4:8080
107
-
108
- iptables.rule(
109
- 'PREROUTING', 'DNAT', table='nat',
110
- source='8.8.8.8', destination_port=53,
111
- to_destination='8.8.4.4:8080'
112
- )
113
- '''
114
-
115
- # These are only shortcuts for extras
116
- if destination_port:
117
- extras = '{0} --dport {1}'.format(extras, destination_port)
118
-
119
- if source_port:
120
- extras = '{0} --sport {1}'.format(extras, source_port)
121
-
122
- # Convert the extras string into a set to enable comparison with the fact
123
- extras_set = set(extras.split())
124
-
125
- # When protocol is set, the extension is automagically added by iptables (which shows
126
- # in iptables-save): http://ipset.netfilter.org/iptables-extensions.man.html
127
- if protocol:
128
- extras_set.add('-m')
129
- extras_set.add(protocol)
130
-
131
- # --dport and --sport do not work without a protocol (because they need -m [tcp|udp]
132
- elif destination_port or source_port:
133
- raise OperationError(
134
- 'iptables cannot filter by destination_port/source_port without a protocol',
135
- )
136
-
137
- # Verify NAT arguments, --to-destination only w/table=nat, jump=DNAT
138
- if to_destination and (table != 'nat' or jump != 'DNAT'):
139
- raise OperationError(
140
- 'iptables only supports to_destination on the nat table and the DNAT jump '
141
- '(table={0}, jump={1})'.format(table, jump),
142
- )
143
-
144
- # As above, --to-source only w/table=nat, jump=SNAT
145
- if to_source and (table != 'nat' or jump != 'SNAT'):
146
- raise OperationError(
147
- 'iptables only supports to_source on the nat table and the SNAT jump '
148
- '(table={0}, jump={1})'.format(table, jump),
149
- )
150
-
151
- # As above, --to-ports only w/table=nat, jump=REDIRECT
152
- if to_ports and (table != 'nat' or jump != 'REDIRECT'):
153
- raise OperationError(
154
- 'iptables only supports to_ports on the nat table and the REDIRECT jump '
155
- '(table={0}, jump={1})'.format(table, jump),
156
- )
157
-
158
- # --log-prefix is only supported with jump=LOG
159
- if log_prefix and jump != 'LOG':
160
- raise OperationError(
161
- 'iptables only supports log_prefix with the LOG jump '
162
- '(jump={0})'.format(jump),
163
- )
164
-
165
- definition = {
166
- 'chain': chain,
167
- 'jump': jump,
168
-
169
- 'protocol': protocol,
170
- 'source': source,
171
- 'destination': destination,
172
- 'in_interface': in_interface,
173
- 'out_interface': out_interface,
174
-
175
- 'not_protocol': not_protocol,
176
- 'not_source': not_source,
177
- 'not_destination': not_destination,
178
- 'not_in_interface': not_in_interface,
179
- 'not_out_interface': not_out_interface,
180
-
181
- # These go *after* the jump argument
182
- 'log_prefix': log_prefix,
183
- 'to_destination': to_destination,
184
- 'to_source': to_source,
185
- 'to_ports': to_ports,
186
- 'extras': extras_set,
187
- }
188
-
189
- definition = {
190
- key: (
191
- '{0}/32'.format(value)
192
- if (
193
- '/' not in value
194
- and key in ('source', 'not_source', 'destination', 'not_destination')
195
- )
196
- else value
197
- )
198
- for key, value in definition.items()
199
- if value
200
- }
201
-
202
- rules = (
203
- host.fact.iptables_rules(table)
204
- if version == 4
205
- else host.fact.ip6tables_rules(table)
206
- )
207
-
208
- action = None
209
-
210
- # Definition doesn't exist and we want it
211
- if present and definition not in rules:
212
- action = '-A' if append else '-I'
213
-
214
- # Definition exists and we don't want it
215
- if not present and definition in rules:
216
- action = '-D'
217
-
218
- # Are we adding/removing a rule? Lets build it
219
- if action:
220
- args = [
221
- 'iptables' if version == 4 else 'ip6tables',
222
- # Add the table
223
- '-t', table,
224
- # Add the action and target chain
225
- action, chain,
226
- ]
227
-
228
- if protocol:
229
- args.extend(('-p', protocol))
230
-
231
- if source:
232
- args.extend(('-s', source))
233
-
234
- if in_interface:
235
- args.extend(('-i', in_interface))
236
-
237
- if out_interface:
238
- args.extend(('-o', out_interface))
239
-
240
- if not_protocol:
241
- args.extend(('!', '-p', not_protocol))
242
-
243
- if not_source:
244
- args.extend(('!', '-s', not_source))
245
-
246
- if not_in_interface:
247
- args.extend(('!', '-i', not_in_interface))
248
-
249
- if not_out_interface:
250
- args.extend(('!', '-o', not_out_interface))
251
-
252
- if extras:
253
- args.append(extras.strip())
254
-
255
- # Add the jump
256
- args.extend(('-j', jump))
257
-
258
- if log_prefix:
259
- args.extend(('--log-prefix', log_prefix))
260
-
261
- if to_destination:
262
- args.extend(('--to-destination', to_destination))
263
-
264
- if to_source:
265
- args.extend(('--to-source', to_source))
266
-
267
- if to_ports:
268
- args.extend(('--to-ports', to_ports))
269
-
270
- # Build the final iptables command
271
- yield ' '.join(args)
pyinfra/modules/lxd.py DELETED
@@ -1,45 +0,0 @@
1
- '''
2
- The LXD modules manage LXD containers
3
- '''
4
-
5
- from pyinfra.api import operation
6
-
7
-
8
- def get_container_named(name, containers):
9
- for container in containers:
10
- if container['name'] == name:
11
- return container
12
- else:
13
- return None
14
-
15
-
16
- @operation
17
- def container(
18
- state, host, name,
19
- present=True, image='ubuntu:16.04',
20
- ):
21
- '''
22
- Add/remove LXD containers.
23
-
24
- Note: does not check if an existing container is based on the specified
25
- image.
26
-
27
- + name: name of the container
28
- + image: image to base the container on
29
- + present: whether the container should be present or absent
30
- '''
31
-
32
- container = get_container_named(name, host.fact.lxd_containers)
33
-
34
- # Container exists and we don't want it
35
- if container and not present:
36
- if container['status'] == 'Running':
37
- yield 'lxc stop {0}'.format(name)
38
-
39
- # Command to remove the container:
40
- yield 'lxc delete {0}'.format(name)
41
-
42
- # Container doesn't exist and we want it
43
- if not container and present:
44
- # Command to create the container:
45
- yield 'lxc launch {image} {name}'.format(name=name, image=image)
pyinfra/modules/mysql.py DELETED
@@ -1,347 +0,0 @@
1
- '''
2
- Manage MySQL databases, users and privileges.
3
-
4
- Requires the ``mysql`` CLI executable on the target host(s).
5
-
6
- All operations in this module take four optional global arguments:
7
- + ``mysql_user``: the username to connect to mysql to
8
- + ``mysql_password``: the password for the connecting user
9
- + ``mysql_host``: the hostname of the server to connect to
10
- + ``mysql_port``: the port of the server to connect to
11
- '''
12
-
13
- from pyinfra.api import operation, OperationError
14
- from pyinfra.facts.mysql import make_execute_mysql_command, make_mysql_command
15
-
16
-
17
- @operation
18
- def sql(
19
- state, host, sql,
20
- database=None,
21
- # Details for speaking to MySQL via `mysql` CLI
22
- mysql_user=None, mysql_password=None,
23
- mysql_host=None, mysql_port=None,
24
- ):
25
- '''
26
- Execute arbitrary SQL against MySQL.
27
-
28
- + sql: SQL command(s) to execute
29
- + database: optional database to open the connection with
30
- + mysql_*: global module arguments, see above
31
- '''
32
-
33
- yield make_execute_mysql_command(
34
- sql,
35
- database=database,
36
- user=mysql_user,
37
- password=mysql_password,
38
- host=mysql_host,
39
- port=mysql_port,
40
- )
41
-
42
-
43
- @operation
44
- def user(
45
- state, host, name,
46
- # Desired user settings
47
- present=True,
48
- user_hostname='localhost', password=None, privileges=None,
49
- # Details for speaking to MySQL via `mysql` CLI via `mysql` CLI
50
- mysql_user=None, mysql_password=None,
51
- mysql_host=None, mysql_port=None,
52
- ):
53
- '''
54
- Add/remove/update MySQL users.
55
-
56
- + name: the name of the user
57
- + present: whether the user should exist or not
58
- + user_hostname: the hostname of the user
59
- + password: the password of the user (if created)
60
- + privileges: the global privileges for this user
61
- + mysql_*: global module arguments, see above
62
-
63
- Hostname:
64
- this + ``name`` makes the username - so changing this will create a new
65
- user, rather than update users with the same ``name``.
66
-
67
- Password:
68
- will only be applied if the user does not exist - ie pyinfra cannot
69
- detect if the current password doesn't match the one provided, so won't
70
- attempt to change it.
71
- '''
72
-
73
- current_users = host.fact.mysql_users(
74
- mysql_user, mysql_password, mysql_host, mysql_port,
75
- )
76
-
77
- user_host = '{0}@{1}'.format(name, user_hostname)
78
- is_present = user_host in current_users
79
-
80
- # User not wanted?
81
- if not present:
82
- if is_present:
83
- yield make_execute_mysql_command(
84
- 'DROP USER "{0}"@"{1}"'.format(name, user_hostname),
85
- user=mysql_user,
86
- password=mysql_password,
87
- host=mysql_host,
88
- port=mysql_port,
89
- )
90
- return
91
-
92
- # If we want the user and they don't exist
93
- if present and not is_present:
94
- sql_bits = ['CREATE USER "{0}"@"{1}"'.format(name, user_hostname)]
95
- if password:
96
- sql_bits.append('IDENTIFIED BY "{0}"'.format(password))
97
-
98
- yield make_execute_mysql_command(
99
- ' '.join(sql_bits),
100
- user=mysql_user,
101
- password=mysql_password,
102
- host=mysql_host,
103
- port=mysql_port,
104
- )
105
-
106
- # If we're here either the user exists or we just created them; either way
107
- # now we can check any privileges are set.
108
- if privileges:
109
- yield _privileges(
110
- state, host, name, privileges,
111
- user_hostname=user_hostname,
112
- mysql_user=mysql_user, mysql_password=mysql_password,
113
- mysql_host=mysql_host, mysql_port=mysql_port,
114
- )
115
-
116
-
117
- @operation
118
- def database(
119
- state, host, name,
120
- # Desired database settings
121
- present=True,
122
- collate=None, charset=None,
123
- user=None, user_hostname='localhost', user_privileges='ALL',
124
- # Details for speaking to MySQL via `mysql` CLI
125
- mysql_user=None, mysql_password=None,
126
- mysql_host=None, mysql_port=None,
127
- ):
128
- '''
129
- Add/remove MySQL databases.
130
-
131
- + name: the name of the database
132
- + present: whether the database should exist or not
133
- + collate: the collate to use when creating the database
134
- + charset: the charset to use when creating the database
135
- + user: MySQL user to grant privileges on this database to
136
- + user_hostname: the hostname of the MySQL user to grant
137
- + user_privileges: privileges to grant to any specified user
138
- + mysql_*: global module arguments, see above
139
-
140
- Collate/charset:
141
- these will only be applied if the database does not exist - ie pyinfra
142
- will not attempt to alter the existing databases collate/character sets.
143
- '''
144
-
145
- current_databases = host.fact.mysql_databases(
146
- mysql_user, mysql_password,
147
- mysql_host, mysql_port,
148
- )
149
-
150
- is_present = name in current_databases
151
-
152
- if not present:
153
- if is_present:
154
- yield make_execute_mysql_command(
155
- 'DROP DATABASE {0}'.format(name),
156
- user=mysql_user,
157
- password=mysql_password,
158
- host=mysql_host,
159
- port=mysql_port,
160
- )
161
- return
162
-
163
- # We want the database but it doesn't exist
164
- if present and not is_present:
165
- sql_bits = ['CREATE DATABASE {0}'.format(name)]
166
-
167
- if collate:
168
- sql_bits.append('COLLATE {0}'.format(collate))
169
-
170
- if charset:
171
- sql_bits.append('CHARSET {0}'.format(charset))
172
-
173
- yield make_execute_mysql_command(
174
- ' '.join(sql_bits),
175
- user=mysql_user,
176
- password=mysql_password,
177
- host=mysql_host,
178
- port=mysql_port,
179
- )
180
-
181
- # Ensure any user privileges for this database
182
- if user and user_privileges:
183
- yield privileges(
184
- state, host, user,
185
- user_hostname=user_hostname,
186
- privileges=user_privileges,
187
- database=name,
188
- )
189
-
190
-
191
- @operation
192
- def privileges(
193
- state, host,
194
- user, privileges,
195
- user_hostname='localhost',
196
- database='*', table='*',
197
- present=True,
198
- flush=True,
199
- # Details for speaking to MySQL via `mysql` CLI
200
- mysql_user=None, mysql_password=None,
201
- mysql_host=None, mysql_port=None,
202
- ):
203
- '''
204
- Add/remove MySQL privileges for a user, either global, database or table specific.
205
-
206
- + user: name of the user to manage privileges for
207
- + privileges: list of privileges the user should have
208
- + user_hostname: the hostname of the user
209
- + database: name of the database to grant privileges to (defaults to all)
210
- + table: name of the table to grant privileges to (defaults to all)
211
- + present: whether these privileges should exist (False to ``REVOKE)
212
- + flush: whether to flush (and update) the privileges table after any changes
213
- + mysql_*: global module arguments, see above
214
- '''
215
-
216
- # Ensure we have a list
217
- if isinstance(privileges, str):
218
- privileges = [privileges]
219
-
220
- if database != '*':
221
- database = '`{0}`'.format(database)
222
-
223
- if table != '*':
224
- table = '`{0}`'.format(table)
225
-
226
- # We can't set privileges on *.tablename as MySQL won't allow it
227
- if database == '*':
228
- raise OperationError((
229
- 'Cannot apply MySQL privileges on {0}.{1}, no database provided'
230
- ).format(database, table))
231
-
232
- database_table = '{0}.{1}'.format(database, table)
233
- user_grants = host.fact.mysql_user_grants(
234
- user, user_hostname,
235
- mysql_user, mysql_password,
236
- mysql_host, mysql_port,
237
- )
238
-
239
- has_privileges = False
240
-
241
- if database_table in user_grants:
242
- existing_privileges = [
243
- 'ALL' if privilege == 'ALL PRIVILEGES' else privilege
244
- for privilege in user_grants[database_table]['privileges']
245
- ]
246
-
247
- has_privileges = (
248
- database_table in user_grants
249
- and all(
250
- privilege in existing_privileges
251
- for privilege in privileges
252
- )
253
- )
254
-
255
- target = action = None
256
-
257
- # No privilege and we want it
258
- if not has_privileges and present:
259
- action = 'GRANT'
260
- target = 'TO'
261
-
262
- # Permission we don't want
263
- elif has_privileges and not present:
264
- action = 'REVOKE'
265
- target = 'FROM'
266
-
267
- if target and action:
268
- command = (
269
- '{action} {privileges} '
270
- 'ON {database}.{table} '
271
- '{target} "{user}"@"{user_hostname}"'
272
- ).format(
273
- privileges=', '.join(privileges),
274
- action=action, target=target,
275
- database=database, table=table,
276
- user=user, user_hostname=user_hostname,
277
- ).replace('`', r'\`')
278
-
279
- yield make_execute_mysql_command(
280
- command,
281
- user=mysql_user,
282
- password=mysql_password,
283
- host=mysql_host,
284
- port=mysql_port,
285
- )
286
-
287
- if flush:
288
- yield make_execute_mysql_command(
289
- 'FLUSH PRIVILEGES',
290
- user=mysql_user,
291
- password=mysql_password,
292
- host=mysql_host,
293
- port=mysql_port,
294
- )
295
-
296
- _privileges = privileges # noqa: E305 (for use where kwarg is the same)
297
-
298
-
299
- @operation
300
- def dump(
301
- state, host,
302
- remote_filename, database=None,
303
- # Details for speaking to MySQL via `mysql` CLI
304
- mysql_user=None, mysql_password=None,
305
- mysql_host=None, mysql_port=None,
306
- ):
307
- '''
308
- Dump a MySQL database into a ``.sql`` file. Requires ``mysqldump``.
309
-
310
- + database: name of the database to dump
311
- + remote_filename: name of the file to dump the SQL to
312
- + mysql_*: global module arguments, see above
313
- '''
314
-
315
- yield '{0} > {1}'.format(make_mysql_command(
316
- executable='mysqldump',
317
- database=database,
318
- user=mysql_user,
319
- password=mysql_password,
320
- host=mysql_host,
321
- port=mysql_port,
322
- ), remote_filename)
323
-
324
-
325
- @operation
326
- def load(
327
- state, host,
328
- remote_filename, database=None,
329
- # Details for speaking to MySQL via `mysql` CLI
330
- mysql_user=None, mysql_password=None,
331
- mysql_host=None, mysql_port=None,
332
- ):
333
- '''
334
- Load ``.sql`` file into a database.
335
-
336
- + database: name of the database to import into
337
- + remote_filename: the filename to read from
338
- + mysql_*: global module arguments, see above
339
- '''
340
-
341
- yield '{0} < {1}'.format(make_mysql_command(
342
- database=database,
343
- user=mysql_user,
344
- password=mysql_password,
345
- host=mysql_host,
346
- port=mysql_port,
347
- ), remote_filename)
pyinfra/modules/npm.py DELETED
@@ -1,47 +0,0 @@
1
- from pyinfra.api import operation
2
-
3
- from .util.packaging import ensure_packages
4
-
5
-
6
- @operation
7
- def packages(state, host, packages=None, present=True, latest=False, directory=None):
8
- '''
9
- Install/remove/update npm packages.
10
-
11
- + packages: list of packages to ensure
12
- + present: whether the packages should be present
13
- + latest: whether to upgrade packages without a specified version
14
- + directory: directory to manage packages for, defaults to global
15
-
16
- Versions:
17
- Package versions can be pinned like npm: ``<pkg>@<version>``.
18
- '''
19
-
20
- current_packages = host.fact.npm_packages(directory)
21
-
22
- install_command = (
23
- 'npm install -g'
24
- if directory is None
25
- else 'cd {0} && npm install'.format(directory)
26
- )
27
-
28
- uninstall_command = (
29
- 'npm uninstall -g'
30
- if directory is None
31
- else 'cd {0} && npm uninstall'.format(directory)
32
- )
33
-
34
- upgrade_command = (
35
- 'npm update -g'
36
- if directory is None
37
- else 'cd {0} && npm update'.format(directory)
38
- )
39
-
40
- yield ensure_packages(
41
- packages, current_packages, present,
42
- install_command=install_command,
43
- uninstall_command=uninstall_command,
44
- upgrade_command=upgrade_command,
45
- version_join='@',
46
- latest=latest,
47
- )