pyinfra 3.1__py2.py3-none-any.whl → 3.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyinfra/api/arguments.py +10 -3
- pyinfra/api/deploy.py +12 -2
- pyinfra/api/host.py +7 -4
- pyinfra/connectors/chroot.py +1 -1
- pyinfra/connectors/docker.py +17 -6
- pyinfra/connectors/local.py +1 -1
- pyinfra/connectors/ssh.py +3 -0
- pyinfra/connectors/sshuserclient/client.py +26 -14
- pyinfra/facts/apk.py +3 -1
- pyinfra/facts/apt.py +62 -2
- pyinfra/facts/crontab.py +190 -0
- pyinfra/facts/docker.py +6 -0
- pyinfra/facts/efibootmgr.py +108 -0
- pyinfra/facts/files.py +93 -6
- pyinfra/facts/git.py +3 -2
- pyinfra/facts/hardware.py +1 -0
- pyinfra/facts/mysql.py +1 -2
- pyinfra/facts/opkg.py +233 -0
- pyinfra/facts/pipx.py +74 -0
- pyinfra/facts/podman.py +47 -0
- pyinfra/facts/postgres.py +2 -0
- pyinfra/facts/selinux.py +3 -1
- pyinfra/facts/server.py +39 -77
- pyinfra/facts/util/units.py +30 -0
- pyinfra/facts/zfs.py +22 -19
- pyinfra/local.py +3 -2
- pyinfra/operations/apt.py +29 -21
- pyinfra/operations/crontab.py +189 -0
- pyinfra/operations/docker.py +13 -12
- pyinfra/operations/files.py +20 -2
- pyinfra/operations/git.py +48 -9
- pyinfra/operations/opkg.py +88 -0
- pyinfra/operations/pip.py +3 -2
- pyinfra/operations/pipx.py +90 -0
- pyinfra/operations/postgres.py +15 -11
- pyinfra/operations/runit.py +2 -0
- pyinfra/operations/server.py +4 -178
- pyinfra/operations/zfs.py +14 -14
- {pyinfra-3.1.dist-info → pyinfra-3.2.dist-info}/METADATA +11 -12
- {pyinfra-3.1.dist-info → pyinfra-3.2.dist-info}/RECORD +52 -43
- pyinfra_cli/inventory.py +26 -9
- pyinfra_cli/prints.py +18 -3
- pyinfra_cli/util.py +5 -2
- tests/test_cli/test_cli_deploy.py +15 -13
- tests/test_cli/test_cli_exceptions.py +2 -2
- tests/test_cli/test_cli_inventory.py +53 -0
- tests/test_cli/test_cli_util.py +2 -4
- tests/test_connectors/test_sshuserclient.py +68 -1
- {pyinfra-3.1.dist-info → pyinfra-3.2.dist-info}/LICENSE.md +0 -0
- {pyinfra-3.1.dist-info → pyinfra-3.2.dist-info}/WHEEL +0 -0
- {pyinfra-3.1.dist-info → pyinfra-3.2.dist-info}/entry_points.txt +0 -0
- {pyinfra-3.1.dist-info → pyinfra-3.2.dist-info}/top_level.txt +0 -0
pyinfra/operations/files.py
CHANGED
|
@@ -51,6 +51,7 @@ from pyinfra.facts.files import (
|
|
|
51
51
|
Md5File,
|
|
52
52
|
Sha1File,
|
|
53
53
|
Sha256File,
|
|
54
|
+
Sha384File,
|
|
54
55
|
)
|
|
55
56
|
from pyinfra.facts.server import Date, Which
|
|
56
57
|
|
|
@@ -67,6 +68,7 @@ def download(
|
|
|
67
68
|
mode: str | None = None,
|
|
68
69
|
cache_time: int | None = None,
|
|
69
70
|
force=False,
|
|
71
|
+
sha384sum: str | None = None,
|
|
70
72
|
sha256sum: str | None = None,
|
|
71
73
|
sha1sum: str | None = None,
|
|
72
74
|
md5sum: str | None = None,
|
|
@@ -84,6 +86,7 @@ def download(
|
|
|
84
86
|
+ mode: permissions of the files
|
|
85
87
|
+ cache_time: if the file exists already, re-download after this time (in seconds)
|
|
86
88
|
+ force: always download the file, even if it already exists
|
|
89
|
+
+ sha384sum: sha384 hash to checksum the downloaded file against
|
|
87
90
|
+ sha256sum: sha256 hash to checksum the downloaded file against
|
|
88
91
|
+ sha1sum: sha1 hash to checksum the downloaded file against
|
|
89
92
|
+ md5sum: md5 hash to checksum the downloaded file against
|
|
@@ -135,6 +138,10 @@ def download(
|
|
|
135
138
|
if sha256sum != host.get_fact(Sha256File, path=dest):
|
|
136
139
|
download = True
|
|
137
140
|
|
|
141
|
+
if sha384sum:
|
|
142
|
+
if sha384sum != host.get_fact(Sha384File, path=dest):
|
|
143
|
+
download = True
|
|
144
|
+
|
|
138
145
|
if md5sum:
|
|
139
146
|
if md5sum != host.get_fact(Md5File, path=dest):
|
|
140
147
|
download = True
|
|
@@ -211,6 +218,17 @@ def download(
|
|
|
211
218
|
QuoteString("SHA256 did not match!"),
|
|
212
219
|
)
|
|
213
220
|
|
|
221
|
+
if sha384sum:
|
|
222
|
+
yield make_formatted_string_command(
|
|
223
|
+
(
|
|
224
|
+
"(( sha384sum {0} 2> /dev/null || shasum -a 384 {0} ) "
|
|
225
|
+
"| grep {1}) || ( echo {2} && exit 1 )"
|
|
226
|
+
),
|
|
227
|
+
QuoteString(dest),
|
|
228
|
+
sha384sum,
|
|
229
|
+
QuoteString("SHA384 did not match!"),
|
|
230
|
+
)
|
|
231
|
+
|
|
214
232
|
if md5sum:
|
|
215
233
|
yield make_formatted_string_command(
|
|
216
234
|
(
|
|
@@ -256,7 +274,7 @@ def line(
|
|
|
256
274
|
change bits of lines, see ``files.replace``.
|
|
257
275
|
|
|
258
276
|
Regex line escaping:
|
|
259
|
-
If matching special characters (eg a crontab line containing
|
|
277
|
+
If matching special characters (eg a crontab line containing ``*``), remember to escape
|
|
260
278
|
it first using Python's ``re.escape``.
|
|
261
279
|
|
|
262
280
|
Backup:
|
|
@@ -523,7 +541,7 @@ def sync(
|
|
|
523
541
|
+ mode: permissions of the files
|
|
524
542
|
+ dir_mode: permissions of the directories
|
|
525
543
|
+ delete: delete remote files not present locally
|
|
526
|
-
+ exclude: string or list/tuple of strings to match & exclude files (eg
|
|
544
|
+
+ exclude: string or list/tuple of strings to match & exclude files (eg ``*.pyc``)
|
|
527
545
|
+ exclude_dir: string or list/tuple of strings to match & exclude directories (eg node_modules)
|
|
528
546
|
+ add_deploy_dir: interpret src as relative to deploy directory instead of current directory
|
|
529
547
|
|
pyinfra/operations/git.py
CHANGED
|
@@ -16,24 +16,40 @@ from .util.files import chown, unix_path_join
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
@operation()
|
|
19
|
-
def config(key: str, value: str, multi_value=False, repo: str | None = None):
|
|
19
|
+
def config(key: str, value: str, multi_value=False, repo: str | None = None, system=False):
|
|
20
20
|
"""
|
|
21
|
-
Manage git config
|
|
21
|
+
Manage git config at repository, user or system level.
|
|
22
22
|
|
|
23
23
|
+ key: the key of the config to ensure
|
|
24
24
|
+ value: the value this key should have
|
|
25
25
|
+ multi_value: Add the value rather than set it for settings that can have multiple values
|
|
26
26
|
+ repo: specify the git repo path to edit local config (defaults to global)
|
|
27
|
+
+ system: whether, when ``repo`` is unspecified, to work at system level (or default to global)
|
|
27
28
|
|
|
28
|
-
**
|
|
29
|
+
**Examples:**
|
|
29
30
|
|
|
30
31
|
.. code:: python
|
|
31
32
|
|
|
32
33
|
git.config(
|
|
33
|
-
name="
|
|
34
|
+
name="Always prune specified repo",
|
|
35
|
+
key="fetch.prune",
|
|
36
|
+
value="true",
|
|
37
|
+
repo="/usr/local/src/pyinfra",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
git.config(
|
|
41
|
+
name="Ensure user name is set for all repos of specified user",
|
|
34
42
|
key="user.name",
|
|
35
43
|
value="Anon E. Mouse",
|
|
36
|
-
|
|
44
|
+
_sudo=True,
|
|
45
|
+
_sudo_user="anon"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
git.config(
|
|
49
|
+
name="Ensure same date format for all users",
|
|
50
|
+
key="log.date",
|
|
51
|
+
value="iso",
|
|
52
|
+
system=True
|
|
37
53
|
)
|
|
38
54
|
|
|
39
55
|
"""
|
|
@@ -41,14 +57,14 @@ def config(key: str, value: str, multi_value=False, repo: str | None = None):
|
|
|
41
57
|
existing_config = {}
|
|
42
58
|
|
|
43
59
|
if not repo:
|
|
44
|
-
existing_config = host.get_fact(GitConfig)
|
|
60
|
+
existing_config = host.get_fact(GitConfig, system=system)
|
|
45
61
|
|
|
46
62
|
# Only get the config if the repo exists at this stage
|
|
47
63
|
elif host.get_fact(Directory, path=unix_path_join(repo, ".git")):
|
|
48
64
|
existing_config = host.get_fact(GitConfig, repo=repo)
|
|
49
65
|
|
|
50
66
|
if repo is None:
|
|
51
|
-
base_command = "git config --global"
|
|
67
|
+
base_command = "git config" + (" --system" if system else " --global")
|
|
52
68
|
else:
|
|
53
69
|
base_command = "cd {0} && git config --local".format(repo)
|
|
54
70
|
|
|
@@ -184,7 +200,7 @@ def worktree(
|
|
|
184
200
|
+ from_remote_branch: a 2-tuple ``(remote, branch)`` that identifies a remote branch
|
|
185
201
|
+ present: whether the working tree should exist
|
|
186
202
|
+ assume_repo_exists: whether to assume the main repo exists
|
|
187
|
-
+ force:
|
|
203
|
+
+ force: whether to use ``--force`` when adding/removing worktrees
|
|
188
204
|
+ user: chown files to this user after
|
|
189
205
|
+ group: chown files to this group after
|
|
190
206
|
|
|
@@ -205,6 +221,14 @@ def worktree(
|
|
|
205
221
|
commitish="4e091aa0"
|
|
206
222
|
)
|
|
207
223
|
|
|
224
|
+
git.worktree(
|
|
225
|
+
name="Create a worktree from the tag `4e091aa0`, even if already registered",
|
|
226
|
+
repo="/usr/local/src/pyinfra/master",
|
|
227
|
+
worktree="/usr/local/src/pyinfra/2.x",
|
|
228
|
+
commitish="2.x",
|
|
229
|
+
force=True
|
|
230
|
+
)
|
|
231
|
+
|
|
208
232
|
git.worktree(
|
|
209
233
|
name="Create a worktree with a new local branch `v1.0`",
|
|
210
234
|
repo="/usr/local/src/pyinfra/master",
|
|
@@ -250,6 +274,15 @@ def worktree(
|
|
|
250
274
|
commitish="v1.0"
|
|
251
275
|
)
|
|
252
276
|
|
|
277
|
+
git.worktree(
|
|
278
|
+
name="Idempotent worktree creation, never pulls",
|
|
279
|
+
repo="/usr/local/src/pyinfra/master",
|
|
280
|
+
worktree="/usr/local/src/pyinfra/hotfix",
|
|
281
|
+
new_branch="v1.0",
|
|
282
|
+
commitish="v1.0",
|
|
283
|
+
pull=False
|
|
284
|
+
)
|
|
285
|
+
|
|
253
286
|
git.worktree(
|
|
254
287
|
name="Pull an existing worktree already linked to a tracking branch",
|
|
255
288
|
repo="/usr/local/src/pyinfra/master",
|
|
@@ -295,6 +328,9 @@ def worktree(
|
|
|
295
328
|
elif detached:
|
|
296
329
|
command_parts.append("--detach")
|
|
297
330
|
|
|
331
|
+
if force:
|
|
332
|
+
command_parts.append("--force")
|
|
333
|
+
|
|
298
334
|
command_parts.append(worktree)
|
|
299
335
|
|
|
300
336
|
if commitish:
|
|
@@ -317,9 +353,12 @@ def worktree(
|
|
|
317
353
|
|
|
318
354
|
# It exists and we still want it => pull/rebase it
|
|
319
355
|
elif host.get_fact(Directory, path=worktree) and present:
|
|
356
|
+
if not pull:
|
|
357
|
+
host.noop("Pull is disabled")
|
|
358
|
+
|
|
320
359
|
# pull the worktree only if it's already linked to a tracking branch or
|
|
321
360
|
# if a remote branch is set
|
|
322
|
-
|
|
361
|
+
elif host.get_fact(GitTrackingBranch, repo=worktree) or from_remote_branch:
|
|
323
362
|
command = "cd {0} && git pull".format(worktree)
|
|
324
363
|
|
|
325
364
|
if rebase:
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Manage packages on OpenWrt using opkg
|
|
3
|
+
+ ``update`` - update local copy of package information
|
|
4
|
+
+ ``packages`` - install and remove packages
|
|
5
|
+
|
|
6
|
+
see https://openwrt.org/docs/guide-user/additional-software/opkg
|
|
7
|
+
OpenWrt recommends against upgrading all packages thus there is no ``opkg.upgrade`` function
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import List, Union
|
|
11
|
+
|
|
12
|
+
from pyinfra import host
|
|
13
|
+
from pyinfra.api import StringCommand, operation
|
|
14
|
+
from pyinfra.facts.opkg import OpkgPackages
|
|
15
|
+
from pyinfra.operations.util.packaging import ensure_packages
|
|
16
|
+
|
|
17
|
+
EQUALS = "="
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@operation(is_idempotent=False)
|
|
21
|
+
def update():
|
|
22
|
+
"""
|
|
23
|
+
Update the local opkg information.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
yield StringCommand("opkg update")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
_update = update
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@operation()
|
|
33
|
+
def packages(
|
|
34
|
+
packages: Union[str, List[str]] = "",
|
|
35
|
+
present: bool = True,
|
|
36
|
+
latest: bool = False,
|
|
37
|
+
update: bool = True,
|
|
38
|
+
):
|
|
39
|
+
"""
|
|
40
|
+
Add/remove/update opkg packages.
|
|
41
|
+
|
|
42
|
+
+ packages: package or list of packages to that must/must not be present
|
|
43
|
+
+ present: whether the package(s) should be installed (default True) or removed
|
|
44
|
+
+ latest: whether to attempt to upgrade the specified package(s) (default False)
|
|
45
|
+
+ update: run ``opkg update`` before installing packages (default True)
|
|
46
|
+
|
|
47
|
+
Not Supported:
|
|
48
|
+
Opkg does not support version pinning, i.e. ``<pkg>=<version>`` is not allowed
|
|
49
|
+
and will cause an exception.
|
|
50
|
+
|
|
51
|
+
**Examples:**
|
|
52
|
+
|
|
53
|
+
.. code:: python
|
|
54
|
+
|
|
55
|
+
# Ensure packages are installed∂ (will not force package upgrade)
|
|
56
|
+
opkg.packages(['asterisk', 'vim'], name="Install Asterisk and Vim")
|
|
57
|
+
|
|
58
|
+
# Install the latest versions of packages (always check)
|
|
59
|
+
opkg.packages(
|
|
60
|
+
'vim',
|
|
61
|
+
latest=True,
|
|
62
|
+
name="Ensure we have the latest version of Vim"
|
|
63
|
+
)
|
|
64
|
+
"""
|
|
65
|
+
if str(packages) == "" or (
|
|
66
|
+
isinstance(packages, list) and (len(packages) < 1 or all(len(p) < 1 for p in packages))
|
|
67
|
+
):
|
|
68
|
+
host.noop("empty or invalid package list provided to opkg.packages")
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
pkg_list = packages if isinstance(packages, list) else [packages]
|
|
72
|
+
have_equals = ",".join([pkg.split(EQUALS)[0] for pkg in pkg_list if EQUALS in pkg])
|
|
73
|
+
if len(have_equals) > 0:
|
|
74
|
+
raise ValueError(f"opkg does not support version pinning but found for: '{have_equals}'")
|
|
75
|
+
|
|
76
|
+
if update:
|
|
77
|
+
yield from _update._inner()
|
|
78
|
+
|
|
79
|
+
yield from ensure_packages(
|
|
80
|
+
host,
|
|
81
|
+
pkg_list,
|
|
82
|
+
host.get_fact(OpkgPackages),
|
|
83
|
+
present,
|
|
84
|
+
install_command="opkg install",
|
|
85
|
+
upgrade_command="opkg upgrade",
|
|
86
|
+
uninstall_command="opkg remove",
|
|
87
|
+
latest=latest,
|
|
88
|
+
)
|
pyinfra/operations/pip.py
CHANGED
|
@@ -174,12 +174,13 @@ def packages(
|
|
|
174
174
|
install_command_args.append(extra_install_args)
|
|
175
175
|
install_command = " ".join(install_command_args)
|
|
176
176
|
|
|
177
|
+
upgrade_command = "{0} --upgrade".format(install_command)
|
|
177
178
|
uninstall_command = " ".join([pip, "uninstall", "--yes"])
|
|
178
179
|
|
|
179
180
|
# (un)Install requirements
|
|
180
181
|
if requirements is not None:
|
|
181
182
|
if present:
|
|
182
|
-
yield "{0} -r {1}".format(install_command, requirements)
|
|
183
|
+
yield "{0} -r {1}".format(upgrade_command if latest else install_command, requirements)
|
|
183
184
|
else:
|
|
184
185
|
yield "{0} -r {1}".format(uninstall_command, requirements)
|
|
185
186
|
|
|
@@ -199,7 +200,7 @@ def packages(
|
|
|
199
200
|
present,
|
|
200
201
|
install_command=install_command,
|
|
201
202
|
uninstall_command=uninstall_command,
|
|
202
|
-
upgrade_command=
|
|
203
|
+
upgrade_command=upgrade_command,
|
|
203
204
|
version_join="==",
|
|
204
205
|
latest=latest,
|
|
205
206
|
)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Manage pipx (python) applications.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from pyinfra import host
|
|
6
|
+
from pyinfra.api import operation
|
|
7
|
+
from pyinfra.facts.pipx import PipxEnvironment, PipxPackages
|
|
8
|
+
from pyinfra.facts.server import Path
|
|
9
|
+
|
|
10
|
+
from .util.packaging import ensure_packages
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@operation()
|
|
14
|
+
def packages(
|
|
15
|
+
packages=None,
|
|
16
|
+
present=True,
|
|
17
|
+
latest=False,
|
|
18
|
+
extra_args=None,
|
|
19
|
+
):
|
|
20
|
+
"""
|
|
21
|
+
Install/remove/update pipx packages.
|
|
22
|
+
|
|
23
|
+
+ packages: list of packages to ensure
|
|
24
|
+
+ present: whether the packages should be installed
|
|
25
|
+
+ latest: whether to upgrade packages without a specified version
|
|
26
|
+
+ extra_args: additional arguments to the pipx command
|
|
27
|
+
|
|
28
|
+
Versions:
|
|
29
|
+
Package versions can be pinned like pip: ``<pkg>==<version>``.
|
|
30
|
+
|
|
31
|
+
**Example:**
|
|
32
|
+
|
|
33
|
+
.. code:: python
|
|
34
|
+
|
|
35
|
+
pipx.packages(
|
|
36
|
+
name="Install ",
|
|
37
|
+
packages=["pyinfra"],
|
|
38
|
+
)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
prep_install_command = ["pipx", "install"]
|
|
42
|
+
|
|
43
|
+
if extra_args:
|
|
44
|
+
prep_install_command.append(extra_args)
|
|
45
|
+
install_command = " ".join(prep_install_command)
|
|
46
|
+
|
|
47
|
+
uninstall_command = "pipx uninstall"
|
|
48
|
+
upgrade_command = "pipx upgrade"
|
|
49
|
+
|
|
50
|
+
current_packages = host.get_fact(PipxPackages)
|
|
51
|
+
|
|
52
|
+
# pipx support only one package name at a time
|
|
53
|
+
for package in packages:
|
|
54
|
+
yield from ensure_packages(
|
|
55
|
+
host,
|
|
56
|
+
[package],
|
|
57
|
+
current_packages,
|
|
58
|
+
present,
|
|
59
|
+
install_command=install_command,
|
|
60
|
+
uninstall_command=uninstall_command,
|
|
61
|
+
upgrade_command=upgrade_command,
|
|
62
|
+
version_join="==",
|
|
63
|
+
latest=latest,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@operation()
|
|
68
|
+
def upgrade_all():
|
|
69
|
+
"""
|
|
70
|
+
Upgrade all pipx packages.
|
|
71
|
+
"""
|
|
72
|
+
yield "pipx upgrade-all"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@operation()
|
|
76
|
+
def ensure_path():
|
|
77
|
+
"""
|
|
78
|
+
Ensure pipx bin dir is in the PATH.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
# Fetch the current user's PATH
|
|
82
|
+
path = host.get_fact(Path)
|
|
83
|
+
# Fetch the pipx environment variables
|
|
84
|
+
pipx_env = host.get_fact(PipxEnvironment)
|
|
85
|
+
|
|
86
|
+
# If the pipx bin dir is already in the user's PATH, we're done
|
|
87
|
+
if "PIPX_BIN_DIR" in pipx_env and pipx_env["PIPX_BIN_DIR"] in path.split(":"):
|
|
88
|
+
host.noop("pipx bin dir is already in the PATH")
|
|
89
|
+
else:
|
|
90
|
+
yield "pipx ensurepath"
|
pyinfra/operations/postgres.py
CHANGED
|
@@ -8,6 +8,7 @@ All operations in this module take four optional arguments:
|
|
|
8
8
|
+ ``psql_password``: the password for the connecting user
|
|
9
9
|
+ ``psql_host``: the hostname of the server to connect to
|
|
10
10
|
+ ``psql_port``: the port of the server to connect to
|
|
11
|
+
+ ``psql_database``: the database on the server to connect to
|
|
11
12
|
|
|
12
13
|
See example/postgresql.py for detailed example
|
|
13
14
|
|
|
@@ -28,28 +29,27 @@ from pyinfra.facts.postgres import (
|
|
|
28
29
|
@operation(is_idempotent=False)
|
|
29
30
|
def sql(
|
|
30
31
|
sql: str,
|
|
31
|
-
database: str | None = None,
|
|
32
32
|
# Details for speaking to PostgreSQL via `psql` CLI
|
|
33
33
|
psql_user: str | None = None,
|
|
34
34
|
psql_password: str | None = None,
|
|
35
35
|
psql_host: str | None = None,
|
|
36
36
|
psql_port: int | None = None,
|
|
37
|
+
psql_database: str | None = None,
|
|
37
38
|
):
|
|
38
39
|
"""
|
|
39
40
|
Execute arbitrary SQL against PostgreSQL.
|
|
40
41
|
|
|
41
42
|
+ sql: SQL command(s) to execute
|
|
42
|
-
+ database: optional database to execute against
|
|
43
43
|
+ psql_*: global module arguments, see above
|
|
44
44
|
"""
|
|
45
45
|
|
|
46
46
|
yield make_execute_psql_command(
|
|
47
47
|
sql,
|
|
48
|
-
database=database,
|
|
49
48
|
user=psql_user,
|
|
50
49
|
password=psql_password,
|
|
51
50
|
host=psql_host,
|
|
52
51
|
port=psql_port,
|
|
52
|
+
database=psql_database,
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
|
|
@@ -70,6 +70,7 @@ def role(
|
|
|
70
70
|
psql_password: str | None = None,
|
|
71
71
|
psql_host: str | None = None,
|
|
72
72
|
psql_port: int | None = None,
|
|
73
|
+
psql_database: str | None = None,
|
|
73
74
|
):
|
|
74
75
|
"""
|
|
75
76
|
Add/remove PostgreSQL roles.
|
|
@@ -112,6 +113,7 @@ def role(
|
|
|
112
113
|
psql_password=psql_password,
|
|
113
114
|
psql_host=psql_host,
|
|
114
115
|
psql_port=psql_port,
|
|
116
|
+
psql_database=psql_database,
|
|
115
117
|
)
|
|
116
118
|
|
|
117
119
|
is_present = role in roles
|
|
@@ -125,6 +127,7 @@ def role(
|
|
|
125
127
|
password=psql_password,
|
|
126
128
|
host=psql_host,
|
|
127
129
|
port=psql_port,
|
|
130
|
+
database=psql_database,
|
|
128
131
|
)
|
|
129
132
|
else:
|
|
130
133
|
host.noop("postgresql role {0} does not exist".format(role))
|
|
@@ -157,6 +160,7 @@ def role(
|
|
|
157
160
|
password=psql_password,
|
|
158
161
|
host=psql_host,
|
|
159
162
|
port=psql_port,
|
|
163
|
+
database=psql_database,
|
|
160
164
|
)
|
|
161
165
|
else:
|
|
162
166
|
host.noop("postgresql role {0} exists".format(role))
|
|
@@ -178,6 +182,7 @@ def database(
|
|
|
178
182
|
psql_password: str | None = None,
|
|
179
183
|
psql_host: str | None = None,
|
|
180
184
|
psql_port: int | None = None,
|
|
185
|
+
psql_database: str | None = None,
|
|
181
186
|
):
|
|
182
187
|
"""
|
|
183
188
|
Add/remove PostgreSQL databases.
|
|
@@ -218,6 +223,7 @@ def database(
|
|
|
218
223
|
psql_password=psql_password,
|
|
219
224
|
psql_host=psql_host,
|
|
220
225
|
psql_port=psql_port,
|
|
226
|
+
psql_database=psql_database,
|
|
221
227
|
)
|
|
222
228
|
|
|
223
229
|
is_present = database in current_databases
|
|
@@ -230,6 +236,7 @@ def database(
|
|
|
230
236
|
password=psql_password,
|
|
231
237
|
host=psql_host,
|
|
232
238
|
port=psql_port,
|
|
239
|
+
database=psql_database,
|
|
233
240
|
)
|
|
234
241
|
else:
|
|
235
242
|
host.noop("postgresql database {0} does not exist".format(database))
|
|
@@ -257,6 +264,7 @@ def database(
|
|
|
257
264
|
password=psql_password,
|
|
258
265
|
host=psql_host,
|
|
259
266
|
port=psql_port,
|
|
267
|
+
database=psql_database,
|
|
260
268
|
)
|
|
261
269
|
else:
|
|
262
270
|
host.noop("postgresql database {0} exists".format(database))
|
|
@@ -265,18 +273,17 @@ def database(
|
|
|
265
273
|
@operation(is_idempotent=False)
|
|
266
274
|
def dump(
|
|
267
275
|
dest: str,
|
|
268
|
-
database: str | None = None,
|
|
269
276
|
# Details for speaking to PostgreSQL via `psql` CLI
|
|
270
277
|
psql_user: str | None = None,
|
|
271
278
|
psql_password: str | None = None,
|
|
272
279
|
psql_host: str | None = None,
|
|
273
280
|
psql_port: int | None = None,
|
|
281
|
+
psql_database: str | None = None,
|
|
274
282
|
):
|
|
275
283
|
"""
|
|
276
284
|
Dump a PostgreSQL database into a ``.sql`` file. Requires ``pg_dump``.
|
|
277
285
|
|
|
278
286
|
+ dest: name of the file to dump the SQL to
|
|
279
|
-
+ database: name of the database to dump
|
|
280
287
|
+ psql_*: global module arguments, see above
|
|
281
288
|
|
|
282
289
|
**Example:**
|
|
@@ -286,7 +293,6 @@ def dump(
|
|
|
286
293
|
postgresql.dump(
|
|
287
294
|
name="Dump the pyinfra_stuff database",
|
|
288
295
|
dest="/tmp/pyinfra_stuff.dump",
|
|
289
|
-
database="pyinfra_stuff",
|
|
290
296
|
sudo_user="postgres",
|
|
291
297
|
)
|
|
292
298
|
|
|
@@ -295,11 +301,11 @@ def dump(
|
|
|
295
301
|
yield StringCommand(
|
|
296
302
|
make_psql_command(
|
|
297
303
|
executable="pg_dump",
|
|
298
|
-
database=database,
|
|
299
304
|
user=psql_user,
|
|
300
305
|
password=psql_password,
|
|
301
306
|
host=psql_host,
|
|
302
307
|
port=psql_port,
|
|
308
|
+
database=psql_database,
|
|
303
309
|
),
|
|
304
310
|
">",
|
|
305
311
|
QuoteString(dest),
|
|
@@ -309,18 +315,17 @@ def dump(
|
|
|
309
315
|
@operation(is_idempotent=False)
|
|
310
316
|
def load(
|
|
311
317
|
src: str,
|
|
312
|
-
database: str | None = None,
|
|
313
318
|
# Details for speaking to PostgreSQL via `psql` CLI
|
|
314
319
|
psql_user: str | None = None,
|
|
315
320
|
psql_password: str | None = None,
|
|
316
321
|
psql_host: str | None = None,
|
|
317
322
|
psql_port: int | None = None,
|
|
323
|
+
psql_database: str | None = None,
|
|
318
324
|
):
|
|
319
325
|
"""
|
|
320
326
|
Load ``.sql`` file into a database.
|
|
321
327
|
|
|
322
328
|
+ src: the filename to read from
|
|
323
|
-
+ database: name of the database to import into
|
|
324
329
|
+ psql_*: global module arguments, see above
|
|
325
330
|
|
|
326
331
|
**Example:**
|
|
@@ -330,7 +335,6 @@ def load(
|
|
|
330
335
|
postgresql.load(
|
|
331
336
|
name="Import the pyinfra_stuff dump into pyinfra_stuff_copy",
|
|
332
337
|
src="/tmp/pyinfra_stuff.dump",
|
|
333
|
-
database="pyinfra_stuff_copy",
|
|
334
338
|
sudo_user="postgres",
|
|
335
339
|
)
|
|
336
340
|
|
|
@@ -338,11 +342,11 @@ def load(
|
|
|
338
342
|
|
|
339
343
|
yield StringCommand(
|
|
340
344
|
make_psql_command(
|
|
341
|
-
database=database,
|
|
342
345
|
user=psql_user,
|
|
343
346
|
password=psql_password,
|
|
344
347
|
host=psql_host,
|
|
345
348
|
port=psql_port,
|
|
349
|
+
database=psql_database,
|
|
346
350
|
),
|
|
347
351
|
"<",
|
|
348
352
|
QuoteString(src),
|