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
@@ -0,0 +1,437 @@
1
+ """
2
+ The PostgreSQL modules manage PostgreSQL databases, users and privileges.
3
+
4
+ Requires the ``psql`` CLI executable on the target host(s).
5
+
6
+ All operations in this module take four optional arguments:
7
+ + ``psql_user``: the username to connect to postgresql to
8
+ + ``psql_password``: the password for the connecting user
9
+ + ``psql_host``: the hostname of the server to connect to
10
+ + ``psql_port``: the port of the server to connect to
11
+ + ``psql_database``: the database on the server to connect to
12
+
13
+ See example/postgresql.py for detailed example
14
+
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from pyinfra import host
20
+ from pyinfra.api import MaskString, QuoteString, StringCommand, operation
21
+ from pyinfra.facts.postgres import (
22
+ PostgresDatabases,
23
+ PostgresRoles,
24
+ make_execute_psql_command,
25
+ make_psql_command,
26
+ )
27
+
28
+
29
+ @operation(is_idempotent=False)
30
+ def sql(
31
+ sql: str,
32
+ # Details for speaking to PostgreSQL via `psql` CLI
33
+ psql_user: str | None = None,
34
+ psql_password: str | None = None,
35
+ psql_host: str | None = None,
36
+ psql_port: int | None = None,
37
+ psql_database: str | None = None,
38
+ ):
39
+ """
40
+ Execute arbitrary SQL against PostgreSQL.
41
+
42
+ + sql: SQL command(s) to execute
43
+ + psql_*: global module arguments, see above
44
+ """
45
+
46
+ yield make_execute_psql_command(
47
+ sql,
48
+ user=psql_user,
49
+ password=psql_password,
50
+ host=psql_host,
51
+ port=psql_port,
52
+ database=psql_database,
53
+ )
54
+
55
+
56
+ @operation()
57
+ def role(
58
+ role: str,
59
+ present: bool = True,
60
+ password: str | None = None,
61
+ login: bool = True,
62
+ superuser: bool = False,
63
+ inherit: bool = False,
64
+ createdb: bool = False,
65
+ createrole: bool = False,
66
+ replication: bool = False,
67
+ connection_limit: int | None = None,
68
+ # Details for speaking to PostgreSQL via `psql` CLI
69
+ psql_user: str | None = None,
70
+ psql_password: str | None = None,
71
+ psql_host: str | None = None,
72
+ psql_port: int | None = None,
73
+ psql_database: str | None = None,
74
+ ):
75
+ """
76
+ Add/remove PostgreSQL roles.
77
+
78
+ + role: name of the role
79
+ + present: whether the role should be present or absent
80
+ + password: the password for the role
81
+ + login: whether the role can login
82
+ + superuser: whether role will be a superuser
83
+ + inherit: whether the role inherits from other roles
84
+ + createdb: whether the role is allowed to create databases
85
+ + createrole: whether the role is allowed to create new roles
86
+ + replication: whether this role is allowed to replicate
87
+ + connection_limit: the connection limit for the role
88
+ + psql_*: global module arguments, see above
89
+
90
+ Updates:
91
+ pyinfra will not attempt to change existing roles - it will either
92
+ create or drop roles, but not alter them (if the role exists this
93
+ operation will make no changes).
94
+
95
+ **Example:**
96
+
97
+ .. code:: python
98
+
99
+ from pyinfra.operations import postgresql
100
+ postgresql.role(
101
+ name="Create the pyinfra PostgreSQL role",
102
+ role="pyinfra",
103
+ password="somepassword",
104
+ superuser=True,
105
+ login=True,
106
+ _sudo_user="postgres",
107
+ )
108
+
109
+ """
110
+
111
+ roles = host.get_fact(
112
+ PostgresRoles,
113
+ psql_user=psql_user,
114
+ psql_password=psql_password,
115
+ psql_host=psql_host,
116
+ psql_port=psql_port,
117
+ psql_database=psql_database,
118
+ )
119
+
120
+ is_present = role in roles
121
+
122
+ # User not wanted?
123
+ if not present:
124
+ if is_present:
125
+ yield make_execute_psql_command(
126
+ 'DROP ROLE "{0}"'.format(role),
127
+ user=psql_user,
128
+ password=psql_password,
129
+ host=psql_host,
130
+ port=psql_port,
131
+ database=psql_database,
132
+ )
133
+ else:
134
+ host.noop("postgresql role {0} does not exist".format(role))
135
+ return
136
+
137
+ # If we want the user and they don't exist
138
+ if not is_present:
139
+ sql_bits = ['CREATE ROLE "{0}"'.format(role)]
140
+
141
+ for key, value in (
142
+ ("LOGIN", login),
143
+ ("SUPERUSER", superuser),
144
+ ("INHERIT", inherit),
145
+ ("CREATEDB", createdb),
146
+ ("CREATEROLE", createrole),
147
+ ("REPLICATION", replication),
148
+ ):
149
+ if value:
150
+ sql_bits.append(key)
151
+
152
+ if connection_limit:
153
+ sql_bits.append("CONNECTION LIMIT {0}".format(connection_limit))
154
+
155
+ if password:
156
+ sql_bits.append(MaskString("PASSWORD '{0}'".format(password)))
157
+
158
+ yield make_execute_psql_command(
159
+ StringCommand(*sql_bits),
160
+ user=psql_user,
161
+ password=psql_password,
162
+ host=psql_host,
163
+ port=psql_port,
164
+ database=psql_database,
165
+ )
166
+ else:
167
+ # Check if any attributes need updating
168
+ current_role = roles[role]
169
+ should_execute = False
170
+ sql_bits = ['ALTER ROLE "{0}"'.format(role)]
171
+ if login and "login" in current_role and current_role["login"] != login:
172
+ sql_bits.append("LOGIN")
173
+ should_execute = True
174
+ if superuser and "superuser" in current_role and current_role["superuser"] != superuser:
175
+ sql_bits.append("SUPERUSER")
176
+ should_execute = True
177
+ if inherit and "inherit" in current_role and current_role["inherit"] != inherit:
178
+ sql_bits.append("INHERIT")
179
+ should_execute = True
180
+ if createdb and "createdb" in current_role and current_role["createdb"] != createdb:
181
+ sql_bits.append("CREATEDB")
182
+ should_execute = True
183
+ if createrole and "createrole" in current_role and current_role["createrole"] != createrole:
184
+ sql_bits.append("CREATEROLE")
185
+ should_execute = True
186
+ if (
187
+ connection_limit
188
+ and "connection_limit" in current_role
189
+ and roles[role]["connection_limit"] != connection_limit
190
+ ):
191
+ sql_bits.append("CONNECTION LIMIT {0}".format(connection_limit))
192
+ should_execute = True
193
+ if password:
194
+ sql_bits.append(MaskString("PASSWORD '{0}'".format(password)))
195
+ should_execute = True
196
+
197
+ if should_execute:
198
+ yield make_execute_psql_command(
199
+ StringCommand(*sql_bits),
200
+ user=psql_user,
201
+ password=psql_password,
202
+ host=psql_host,
203
+ port=psql_port,
204
+ database=psql_database,
205
+ )
206
+ else:
207
+ host.noop("postgresql role {0} exists and does not need updates".format(role))
208
+
209
+
210
+ @operation()
211
+ def database(
212
+ database: str,
213
+ present=True,
214
+ owner: str | None = None,
215
+ template: str | None = None,
216
+ encoding: str | None = None,
217
+ lc_collate: str | None = None,
218
+ lc_ctype: str | None = None,
219
+ tablespace: str | None = None,
220
+ connection_limit: int | None = None,
221
+ # Details for speaking to PostgreSQL via `psql` CLI
222
+ psql_user: str | None = None,
223
+ psql_password: str | None = None,
224
+ psql_host: str | None = None,
225
+ psql_port: int | None = None,
226
+ psql_database: str | None = None,
227
+ ):
228
+ """
229
+ Add/remove PostgreSQL databases.
230
+
231
+ + name: name of the database
232
+ + present: whether the database should exist or not
233
+ + owner: the PostgreSQL role that owns the database
234
+ + template: name of the PostgreSQL template to use
235
+ + encoding: encoding of the database
236
+ + lc_collate: lc_collate of the database
237
+ + lc_ctype: lc_ctype of the database
238
+ + tablespace: the tablespace to use for the template
239
+ + connection_limit: the connection limit to apply to the database
240
+ + psql_*: global module arguments, see above
241
+
242
+ Updates:
243
+ pyinfra will change existing databases - but some parameters are not
244
+ changeable (template, encoding, lc_collate and lc_ctype).
245
+
246
+ **Example:**
247
+
248
+ .. code:: python
249
+
250
+ postgresql.database(
251
+ name="Create the pyinfra_stuff database",
252
+ database="pyinfra_stuff",
253
+ owner="pyinfra",
254
+ encoding="UTF8",
255
+ _sudo_user="postgres",
256
+ )
257
+
258
+ """
259
+
260
+ current_databases = host.get_fact(
261
+ PostgresDatabases,
262
+ psql_user=psql_user,
263
+ psql_password=psql_password,
264
+ psql_host=psql_host,
265
+ psql_port=psql_port,
266
+ psql_database=psql_database,
267
+ )
268
+
269
+ is_present = database in current_databases
270
+
271
+ if not present:
272
+ if is_present:
273
+ yield make_execute_psql_command(
274
+ 'DROP DATABASE "{0}"'.format(database),
275
+ user=psql_user,
276
+ password=psql_password,
277
+ host=psql_host,
278
+ port=psql_port,
279
+ database=psql_database,
280
+ )
281
+ else:
282
+ host.noop("postgresql database {0} does not exist".format(database))
283
+ return
284
+
285
+ # We want the database but it doesn't exist
286
+ if present and not is_present:
287
+ sql_bits = ['CREATE DATABASE "{0}"'.format(database)]
288
+
289
+ for key, value in (
290
+ ("OWNER", '"{0}"'.format(owner) if owner else owner),
291
+ ("TEMPLATE", template),
292
+ ("ENCODING", encoding),
293
+ ("LC_COLLATE", "'{0}'".format(lc_collate) if lc_collate else lc_collate),
294
+ ("LC_CTYPE", "'{0}'".format(lc_ctype) if lc_ctype else lc_ctype),
295
+ ("TABLESPACE", tablespace),
296
+ ("CONNECTION LIMIT", connection_limit),
297
+ ):
298
+ if value:
299
+ sql_bits.append("{0} {1}".format(key, value))
300
+
301
+ yield make_execute_psql_command(
302
+ StringCommand(*sql_bits),
303
+ user=psql_user,
304
+ password=psql_password,
305
+ host=psql_host,
306
+ port=psql_port,
307
+ database=psql_database,
308
+ )
309
+ else:
310
+ current_db = current_databases[database]
311
+
312
+ for key, value, current_value in (
313
+ ("TEMPLATE", template, current_db.get("istemplate")),
314
+ ("ENCODING", encoding, current_db.get("encoding")),
315
+ ("LC_COLLATE", lc_collate, None),
316
+ ("LC_CTYPE", lc_ctype, None),
317
+ ):
318
+ if value and (current_value is None or current_value != value):
319
+ host.noop(
320
+ "postgresql database {0} already exists, skipping {1}".format(database, key)
321
+ )
322
+
323
+ sql_bits = []
324
+
325
+ if owner and "owner" in current_db and current_db["owner"] != owner:
326
+ sql_bits.append('ALTER DATABASE "{0}" OWNER TO "{1}";'.format(database, owner))
327
+
328
+ if tablespace and "tablespace" in current_db and current_db["tablespace"] != tablespace:
329
+ sql_bits.append(
330
+ 'ALTER DATABASE "{0}" SET TABLESPACE "{1}";'.format(database, tablespace)
331
+ )
332
+
333
+ if (
334
+ connection_limit
335
+ and "connlimit" in current_db
336
+ and current_db["connlimit"] != connection_limit
337
+ ):
338
+ sql_bits.append(
339
+ 'ALTER DATABASE "{0}" CONNECTION LIMIT {1};'.format(database, connection_limit)
340
+ )
341
+
342
+ if len(sql_bits) > 0:
343
+ yield make_execute_psql_command(
344
+ StringCommand(*sql_bits),
345
+ user=psql_user,
346
+ password=psql_password,
347
+ host=psql_host,
348
+ port=psql_port,
349
+ database=psql_database,
350
+ )
351
+ else:
352
+ host.noop(
353
+ "postgresql database {0} already exists with the same parameters".format(database)
354
+ )
355
+
356
+
357
+ @operation(is_idempotent=False)
358
+ def dump(
359
+ dest: str,
360
+ # Details for speaking to PostgreSQL via `psql` CLI
361
+ psql_user: str | None = None,
362
+ psql_password: str | None = None,
363
+ psql_host: str | None = None,
364
+ psql_port: int | None = None,
365
+ psql_database: str | None = None,
366
+ ):
367
+ """
368
+ Dump a PostgreSQL database into a ``.sql`` file. Requires ``pg_dump``.
369
+
370
+ + dest: name of the file to dump the SQL to
371
+ + psql_*: global module arguments, see above
372
+
373
+ **Example:**
374
+
375
+ .. code:: python
376
+
377
+ postgresql.dump(
378
+ name="Dump the pyinfra_stuff database",
379
+ dest="/tmp/pyinfra_stuff.dump",
380
+ sudo_user="postgres",
381
+ )
382
+
383
+ """
384
+
385
+ yield StringCommand(
386
+ make_psql_command(
387
+ executable="pg_dump",
388
+ user=psql_user,
389
+ password=psql_password,
390
+ host=psql_host,
391
+ port=psql_port,
392
+ database=psql_database,
393
+ ),
394
+ ">",
395
+ QuoteString(dest),
396
+ )
397
+
398
+
399
+ @operation(is_idempotent=False)
400
+ def load(
401
+ src: str,
402
+ # Details for speaking to PostgreSQL via `psql` CLI
403
+ psql_user: str | None = None,
404
+ psql_password: str | None = None,
405
+ psql_host: str | None = None,
406
+ psql_port: int | None = None,
407
+ psql_database: str | None = None,
408
+ ):
409
+ """
410
+ Load ``.sql`` file into a database.
411
+
412
+ + src: the filename to read from
413
+ + psql_*: global module arguments, see above
414
+
415
+ **Example:**
416
+
417
+ .. code:: python
418
+
419
+ postgresql.load(
420
+ name="Import the pyinfra_stuff dump into pyinfra_stuff_copy",
421
+ src="/tmp/pyinfra_stuff.dump",
422
+ sudo_user="postgres",
423
+ )
424
+
425
+ """
426
+
427
+ yield StringCommand(
428
+ make_psql_command(
429
+ user=psql_user,
430
+ password=psql_password,
431
+ host=psql_host,
432
+ port=psql_port,
433
+ database=psql_database,
434
+ ),
435
+ "<",
436
+ QuoteString(src),
437
+ )
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ from pyinfra.api import operation
4
+
5
+ from . import postgres
6
+
7
+
8
+ @operation(is_idempotent=False, is_deprecated=True, deprecated_for="postgres.sql")
9
+ def sql(*args, **kwargs):
10
+ yield from postgres.sql._inner(*args, **kwargs)
11
+
12
+
13
+ @operation(is_idempotent=False, is_deprecated=True, deprecated_for="postgres.role")
14
+ def role(*args, **kwargs):
15
+ yield from postgres.role._inner(*args, **kwargs)
16
+
17
+
18
+ @operation(is_idempotent=False, is_deprecated=True)
19
+ def database(*args, **kwargs):
20
+ yield from postgres.database._inner(*args, **kwargs)
21
+
22
+
23
+ @operation(is_idempotent=False, is_deprecated=True)
24
+ def dump(*args, **kwargs):
25
+ yield from postgres.dump._inner(*args, **kwargs)
26
+
27
+
28
+ @operation(is_idempotent=False, is_deprecated=True)
29
+ def load(*args, **kwargs):
30
+ yield from postgres.load._inner(*args, **kwargs)
@@ -0,0 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ from pyinfra.api import operation
4
+
5
+
6
+ @operation(is_idempotent=False)
7
+ def agent(server: str | None = None, port: int | None = None):
8
+ """
9
+ Run puppet agent
10
+
11
+ + server: master server URL
12
+ + port: puppet master port
13
+
14
+ Note: Either 'USE_SUDO_LOGIN=True' or 'USE_SU_LOGIN=True'
15
+ for puppet.agent() as `puppet` is added to the path in
16
+ the .bash_profile.
17
+
18
+ **Example:**
19
+
20
+ .. code:: python
21
+
22
+ from pyinfra.operations import puppet
23
+ puppet.agent()
24
+
25
+ # We also expect a return code of:
26
+ # 0=no changes or 2=changes applied
27
+ puppet.agent(
28
+ name="Run the puppet agent",
29
+ success_exit_codes=[0, 2],
30
+ )
31
+
32
+ """
33
+
34
+ args = []
35
+
36
+ if server:
37
+ args.append("--server=%s" % server)
38
+ if port:
39
+ args.append("--masterport=%s" % port)
40
+
41
+ yield "puppet agent -t %s" % " ".join(args)
@@ -0,0 +1,73 @@
1
+ """
2
+ The Python module allows you to execute Python code within the context of a deploy.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import Callable
8
+
9
+ from pyinfra.api import FunctionCommand, operation
10
+
11
+
12
+ @operation(is_idempotent=False, _set_in_op=False)
13
+ def call(function: Callable, *args, **kwargs):
14
+ """
15
+ Execute a Python function within a deploy.
16
+
17
+ + function: the function to execute
18
+ + args: arguments to pass to the function
19
+ + kwargs: keyword arguments to pass to the function
20
+
21
+ **Example:**
22
+
23
+ .. code:: python
24
+
25
+ from pyinfra.operations import python
26
+ def my_callback(hello=None):
27
+ command = 'echo hello'
28
+ if hello:
29
+ command = command + ' ' + hello
30
+
31
+ status, stdout, stderr = host.run_shell_command(command=command, sudo=SUDO)
32
+ assert status is True # ensure the command executed OK
33
+
34
+ if 'hello ' not in '\\n'.join(stdout): # stdout/stderr is a *list* of lines
35
+ raise Exception(
36
+ f'`{command}` problem with callback stdout:{stdout} stderr:{stderr}',
37
+ )
38
+
39
+ python.call(
40
+ name="Run my_callback function",
41
+ function=my_callback,
42
+ hello="world",
43
+ )
44
+
45
+ """
46
+
47
+ yield FunctionCommand(function, args, kwargs)
48
+
49
+
50
+ @operation(is_idempotent=False, _set_in_op=False)
51
+ def raise_exception(exception: Exception, *args, **kwargs):
52
+ """
53
+ Raise a Python exception within a deploy.
54
+
55
+ + exception: the exception class to raise
56
+ + args: arguments passed to the exception creation
57
+ + kwargs: keyword arguments passed to the exception creation
58
+
59
+ **Example**:
60
+
61
+ .. code:: python
62
+
63
+ python.raise_exception(
64
+ name="Raise NotImplementedError exception",
65
+ exception=NotImplementedError,
66
+ message="This is not implemented",
67
+ )
68
+ """
69
+
70
+ def raise_exc(*args, **kwargs): # pragma: no cover
71
+ raise exception(*args, **kwargs) # type: ignore[operator]
72
+
73
+ yield FunctionCommand(raise_exc, args, kwargs)