pyinfra 3.2__py2.py3-none-any.whl → 3.3.1__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_typed.py +4 -5
- pyinfra/api/command.py +22 -3
- pyinfra/api/config.py +5 -2
- pyinfra/api/facts.py +3 -0
- pyinfra/api/host.py +10 -4
- pyinfra/api/operation.py +2 -1
- pyinfra/api/state.py +1 -1
- pyinfra/connectors/base.py +34 -8
- pyinfra/connectors/chroot.py +7 -2
- pyinfra/connectors/docker.py +7 -2
- pyinfra/connectors/dockerssh.py +7 -2
- pyinfra/connectors/local.py +7 -2
- pyinfra/connectors/ssh.py +9 -2
- pyinfra/connectors/sshuserclient/client.py +18 -2
- pyinfra/connectors/sshuserclient/config.py +2 -0
- pyinfra/connectors/terraform.py +1 -1
- pyinfra/connectors/util.py +13 -9
- pyinfra/context.py +9 -2
- pyinfra/facts/apk.py +5 -0
- pyinfra/facts/apt.py +9 -1
- pyinfra/facts/brew.py +13 -0
- pyinfra/facts/bsdinit.py +3 -0
- pyinfra/facts/cargo.py +5 -0
- pyinfra/facts/choco.py +6 -0
- pyinfra/facts/crontab.py +6 -1
- pyinfra/facts/deb.py +10 -0
- pyinfra/facts/dnf.py +5 -0
- pyinfra/facts/docker.py +10 -0
- pyinfra/facts/efibootmgr.py +5 -0
- pyinfra/facts/files.py +19 -1
- pyinfra/facts/flatpak.py +7 -0
- pyinfra/facts/freebsd.py +75 -0
- pyinfra/facts/gem.py +5 -0
- pyinfra/facts/git.py +9 -0
- pyinfra/facts/gpg.py +7 -0
- pyinfra/facts/hardware.py +13 -0
- pyinfra/facts/iptables.py +9 -1
- pyinfra/facts/launchd.py +5 -0
- pyinfra/facts/lxd.py +5 -0
- pyinfra/facts/mysql.py +8 -0
- pyinfra/facts/npm.py +5 -0
- pyinfra/facts/openrc.py +8 -0
- pyinfra/facts/opkg.py +12 -0
- pyinfra/facts/pacman.py +9 -1
- pyinfra/facts/pip.py +5 -0
- pyinfra/facts/pipx.py +8 -0
- pyinfra/facts/pkg.py +4 -0
- pyinfra/facts/pkgin.py +5 -0
- pyinfra/facts/podman.py +7 -0
- pyinfra/facts/postgres.py +8 -2
- pyinfra/facts/rpm.py +11 -0
- pyinfra/facts/runit.py +7 -0
- pyinfra/facts/selinux.py +16 -0
- pyinfra/facts/server.py +49 -3
- pyinfra/facts/snap.py +7 -0
- pyinfra/facts/systemd.py +5 -0
- pyinfra/facts/sysvinit.py +4 -0
- pyinfra/facts/upstart.py +5 -0
- pyinfra/facts/util/__init__.py +4 -1
- pyinfra/facts/vzctl.py +5 -0
- pyinfra/facts/xbps.py +6 -1
- pyinfra/facts/yum.py +5 -0
- pyinfra/facts/zfs.py +19 -2
- pyinfra/facts/zypper.py +5 -0
- pyinfra/operations/apt.py +10 -3
- pyinfra/operations/docker.py +48 -44
- pyinfra/operations/files.py +47 -1
- pyinfra/operations/freebsd/__init__.py +12 -0
- pyinfra/operations/freebsd/freebsd_update.py +70 -0
- pyinfra/operations/freebsd/pkg.py +219 -0
- pyinfra/operations/freebsd/service.py +116 -0
- pyinfra/operations/freebsd/sysrc.py +92 -0
- pyinfra/operations/opkg.py +5 -5
- pyinfra/operations/postgres.py +99 -16
- pyinfra/operations/server.py +6 -4
- pyinfra/operations/util/docker.py +44 -22
- {pyinfra-3.2.dist-info → pyinfra-3.3.1.dist-info}/LICENSE.md +1 -1
- {pyinfra-3.2.dist-info → pyinfra-3.3.1.dist-info}/METADATA +25 -24
- {pyinfra-3.2.dist-info → pyinfra-3.3.1.dist-info}/RECORD +89 -83
- pyinfra_cli/exceptions.py +5 -0
- pyinfra_cli/log.py +3 -0
- pyinfra_cli/main.py +9 -8
- pyinfra_cli/prints.py +1 -1
- pyinfra_cli/virtualenv.py +1 -1
- tests/test_connectors/test_ssh.py +302 -182
- tests/test_connectors/test_sshuserclient.py +10 -5
- {pyinfra-3.2.dist-info → pyinfra-3.3.1.dist-info}/WHEEL +0 -0
- {pyinfra-3.2.dist-info → pyinfra-3.3.1.dist-info}/entry_points.txt +0 -0
- {pyinfra-3.2.dist-info → pyinfra-3.3.1.dist-info}/top_level.txt +0 -0
pyinfra/facts/files.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
2
|
The files facts provide information about the filesystem and it's contents on the target host.
|
|
3
|
+
|
|
4
|
+
Facts need to be imported before use, eg
|
|
5
|
+
|
|
6
|
+
from pyinfra.facts.files import File
|
|
3
7
|
"""
|
|
4
8
|
|
|
5
9
|
from __future__ import annotations
|
|
@@ -10,7 +14,7 @@ import stat
|
|
|
10
14
|
from datetime import datetime
|
|
11
15
|
from typing import TYPE_CHECKING, List, Optional, Tuple, Union
|
|
12
16
|
|
|
13
|
-
from typing_extensions import Literal, NotRequired, TypedDict
|
|
17
|
+
from typing_extensions import Literal, NotRequired, TypedDict, override
|
|
14
18
|
|
|
15
19
|
from pyinfra.api import StringCommand
|
|
16
20
|
from pyinfra.api.command import QuoteString, make_formatted_string_command
|
|
@@ -111,6 +115,7 @@ class File(FactBase[Union[FileDict, Literal[False], None]]):
|
|
|
111
115
|
|
|
112
116
|
type = "file"
|
|
113
117
|
|
|
118
|
+
@override
|
|
114
119
|
def command(self, path):
|
|
115
120
|
if path.startswith("~/"):
|
|
116
121
|
# Do not quote leading tilde to ensure that it gets properly expanded by the shell
|
|
@@ -129,6 +134,7 @@ class File(FactBase[Union[FileDict, Literal[False], None]]):
|
|
|
129
134
|
bsd_stat_command=BSD_STAT_COMMAND,
|
|
130
135
|
)
|
|
131
136
|
|
|
137
|
+
@override
|
|
132
138
|
def process(self, output) -> Union[FileDict, Literal[False], None]:
|
|
133
139
|
match = re.match(STAT_REGEX, output[0])
|
|
134
140
|
if not match:
|
|
@@ -233,6 +239,7 @@ class HashFileFactBase(FactBaseOptionalStr):
|
|
|
233
239
|
_raw_cmd: str
|
|
234
240
|
_regexes: Tuple[str, str]
|
|
235
241
|
|
|
242
|
+
@override
|
|
236
243
|
def __init_subclass__(cls, digits: int, cmds: List[str], **kwargs) -> None:
|
|
237
244
|
super().__init_subclass__(**kwargs)
|
|
238
245
|
|
|
@@ -249,10 +256,12 @@ class HashFileFactBase(FactBaseOptionalStr):
|
|
|
249
256
|
r"^%s\s+\(%%s\)\s+=\s+([a-fA-F0-9]{%d})$" % (hash_name, digits),
|
|
250
257
|
)
|
|
251
258
|
|
|
259
|
+
@override
|
|
252
260
|
def command(self, path):
|
|
253
261
|
self.path = path
|
|
254
262
|
return make_formatted_string_command(self._raw_cmd, QuoteString(path))
|
|
255
263
|
|
|
264
|
+
@override
|
|
256
265
|
def process(self, output) -> Optional[str]:
|
|
257
266
|
output = output[0]
|
|
258
267
|
escaped_path = re.escape(self.path)
|
|
@@ -294,6 +303,7 @@ class FindInFile(FactBase):
|
|
|
294
303
|
lines if the file exists, and ``None`` if the file does not.
|
|
295
304
|
"""
|
|
296
305
|
|
|
306
|
+
@override
|
|
297
307
|
def command(self, path, pattern, interpolate_variables=False):
|
|
298
308
|
self.exists_flag = "__pyinfra_exists_{0}".format(path)
|
|
299
309
|
|
|
@@ -312,6 +322,7 @@ class FindInFile(FactBase):
|
|
|
312
322
|
QuoteString(self.exists_flag),
|
|
313
323
|
)
|
|
314
324
|
|
|
325
|
+
@override
|
|
315
326
|
def process(self, output):
|
|
316
327
|
# If output is the special string: no matches, so return an empty list;
|
|
317
328
|
# this allows us to differentiate between no matches in an existing file
|
|
@@ -327,9 +338,11 @@ class FindFilesBase(FactBase):
|
|
|
327
338
|
default = list
|
|
328
339
|
type_flag: str
|
|
329
340
|
|
|
341
|
+
@override
|
|
330
342
|
def process(self, output):
|
|
331
343
|
return output
|
|
332
344
|
|
|
345
|
+
@override
|
|
333
346
|
def command(
|
|
334
347
|
self,
|
|
335
348
|
path: str,
|
|
@@ -446,15 +459,18 @@ class Flags(FactBase):
|
|
|
446
459
|
Returns a list of the file flags set for the specified file or directory.
|
|
447
460
|
"""
|
|
448
461
|
|
|
462
|
+
@override
|
|
449
463
|
def requires_command(self, path) -> str:
|
|
450
464
|
return "chflags" # don't try to retrieve them if we can't set them
|
|
451
465
|
|
|
466
|
+
@override
|
|
452
467
|
def command(self, path):
|
|
453
468
|
return make_formatted_string_command(
|
|
454
469
|
"! test -e {0} || stat -f %Sf {0}",
|
|
455
470
|
QuoteString(path),
|
|
456
471
|
)
|
|
457
472
|
|
|
473
|
+
@override
|
|
458
474
|
def process(self, output):
|
|
459
475
|
return [flag for flag in output[0].split(",") if len(flag) > 0] if len(output) == 1 else []
|
|
460
476
|
|
|
@@ -490,6 +506,7 @@ class Block(FactBase):
|
|
|
490
506
|
# the list with a single empty string.
|
|
491
507
|
default = list
|
|
492
508
|
|
|
509
|
+
@override
|
|
493
510
|
def command(self, path, marker=None, begin=None, end=None):
|
|
494
511
|
self.path = path
|
|
495
512
|
start = (marker or MARKER_DEFAULT).format(mark=begin or MARKER_BEGIN_DEFAULT)
|
|
@@ -510,6 +527,7 @@ class Block(FactBase):
|
|
|
510
527
|
)
|
|
511
528
|
return cmd
|
|
512
529
|
|
|
530
|
+
@override
|
|
513
531
|
def process(self, output):
|
|
514
532
|
if output and (output[0] == f"{EXISTS}{self.path}"):
|
|
515
533
|
return []
|
pyinfra/facts/flatpak.py
CHANGED
|
@@ -2,12 +2,15 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
5
7
|
from pyinfra.api import FactBase
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class FlatpakBaseFact(FactBase):
|
|
9
11
|
abstract = True
|
|
10
12
|
|
|
13
|
+
@override
|
|
11
14
|
def requires_command(self, *args, **kwargs) -> str:
|
|
12
15
|
return "flatpak"
|
|
13
16
|
|
|
@@ -32,9 +35,11 @@ class FlatpakPackage(FlatpakBaseFact):
|
|
|
32
35
|
"version": r"^[ ]+Version:[ ]+([\w\d.-]+).*$",
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
@override
|
|
35
39
|
def command(self, package):
|
|
36
40
|
return f"flatpak info {package}"
|
|
37
41
|
|
|
42
|
+
@override
|
|
38
43
|
def process(self, output):
|
|
39
44
|
data = {}
|
|
40
45
|
for line in output:
|
|
@@ -63,8 +68,10 @@ class FlatpakPackages(FlatpakBaseFact):
|
|
|
63
68
|
|
|
64
69
|
default = list
|
|
65
70
|
|
|
71
|
+
@override
|
|
66
72
|
def command(self):
|
|
67
73
|
return "flatpak list --columns=application"
|
|
68
74
|
|
|
75
|
+
@override
|
|
69
76
|
def process(self, output):
|
|
70
77
|
return [flatpak for flatpak in output[1:]]
|
pyinfra/facts/freebsd.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing_extensions import Optional, override
|
|
4
|
+
|
|
5
|
+
from pyinfra.api import FactBase
|
|
6
|
+
from pyinfra.api.command import QuoteString, StringCommand, make_formatted_string_command
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ServiceScript(FactBase):
|
|
10
|
+
@override
|
|
11
|
+
def command(self, srvname: str, jail: Optional[str] = None) -> StringCommand:
|
|
12
|
+
if jail is None:
|
|
13
|
+
jail = ""
|
|
14
|
+
|
|
15
|
+
return make_formatted_string_command(
|
|
16
|
+
(
|
|
17
|
+
"for service in `service -j {0} -l`; do "
|
|
18
|
+
'if [ {1} = \\"$service\\" ]; '
|
|
19
|
+
'then echo \\"$service\\"; '
|
|
20
|
+
"fi; "
|
|
21
|
+
"done"
|
|
22
|
+
),
|
|
23
|
+
QuoteString(jail),
|
|
24
|
+
QuoteString(srvname),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ServiceStatus(FactBase):
|
|
29
|
+
@override
|
|
30
|
+
def command(self, srvname: str, jail: Optional[str] = None) -> StringCommand:
|
|
31
|
+
if jail is None:
|
|
32
|
+
jail = ""
|
|
33
|
+
|
|
34
|
+
return make_formatted_string_command(
|
|
35
|
+
(
|
|
36
|
+
"service -j {0} {1} status > /dev/null 2>&1; "
|
|
37
|
+
"if [ $? -eq 0 ]; then "
|
|
38
|
+
"echo running; "
|
|
39
|
+
"fi"
|
|
40
|
+
),
|
|
41
|
+
QuoteString(jail),
|
|
42
|
+
QuoteString(srvname),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Sysrc(FactBase):
|
|
47
|
+
@override
|
|
48
|
+
def command(self, parameter: str, jail: Optional[str] = None) -> StringCommand:
|
|
49
|
+
if jail is None:
|
|
50
|
+
command = make_formatted_string_command(
|
|
51
|
+
("sysrc -in -- {0} || true"), QuoteString(parameter)
|
|
52
|
+
)
|
|
53
|
+
else:
|
|
54
|
+
command = make_formatted_string_command(
|
|
55
|
+
("sysrc -j {0} -in -- {1} || true"), QuoteString(jail), QuoteString(parameter)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return command
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class PkgPackage(FactBase):
|
|
62
|
+
@override
|
|
63
|
+
def command(self, package: str, jail: Optional[str] = None) -> StringCommand:
|
|
64
|
+
if jail is None:
|
|
65
|
+
command = make_formatted_string_command(
|
|
66
|
+
("pkg info -E -- {0} 2> /dev/null || true"), QuoteString(package)
|
|
67
|
+
)
|
|
68
|
+
else:
|
|
69
|
+
command = make_formatted_string_command(
|
|
70
|
+
("pkg -j {0} info -E -- {1} 2> /dev/null || true"),
|
|
71
|
+
QuoteString(jail),
|
|
72
|
+
QuoteString(package),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
return command
|
pyinfra/facts/gem.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing_extensions import override
|
|
4
|
+
|
|
3
5
|
from pyinfra.api import FactBase
|
|
4
6
|
|
|
5
7
|
from .util.packaging import parse_packages
|
|
@@ -18,13 +20,16 @@ class GemPackages(FactBase):
|
|
|
18
20
|
}
|
|
19
21
|
"""
|
|
20
22
|
|
|
23
|
+
@override
|
|
21
24
|
def command(self) -> str:
|
|
22
25
|
return "gem list --local"
|
|
23
26
|
|
|
27
|
+
@override
|
|
24
28
|
def requires_command(self) -> str:
|
|
25
29
|
return "gem"
|
|
26
30
|
|
|
27
31
|
default = dict
|
|
28
32
|
|
|
33
|
+
@override
|
|
29
34
|
def process(self, output):
|
|
30
35
|
return parse_packages(GEM_REGEX, output)
|
pyinfra/facts/git.py
CHANGED
|
@@ -2,18 +2,23 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
5
7
|
from pyinfra.api.facts import FactBase
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class GitFactBase(FactBase):
|
|
11
|
+
@override
|
|
9
12
|
def requires_command(self, *args, **kwargs) -> str:
|
|
10
13
|
return "git"
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
class GitBranch(GitFactBase):
|
|
17
|
+
@override
|
|
14
18
|
def command(self, repo) -> str:
|
|
15
19
|
return "! test -d {0} || (cd {0} && git describe --all)".format(repo)
|
|
16
20
|
|
|
21
|
+
@override
|
|
17
22
|
def process(self, output):
|
|
18
23
|
return re.sub(r"(heads|tags)/", r"", "\n".join(output))
|
|
19
24
|
|
|
@@ -21,6 +26,7 @@ class GitBranch(GitFactBase):
|
|
|
21
26
|
class GitConfig(GitFactBase):
|
|
22
27
|
default = dict
|
|
23
28
|
|
|
29
|
+
@override
|
|
24
30
|
def command(self, repo=None, system=False) -> str:
|
|
25
31
|
if repo is None:
|
|
26
32
|
level = "--system" if system else "--global"
|
|
@@ -28,6 +34,7 @@ class GitConfig(GitFactBase):
|
|
|
28
34
|
|
|
29
35
|
return "! test -d {0} || (cd {0} && git config --local -l)".format(repo)
|
|
30
36
|
|
|
37
|
+
@override
|
|
31
38
|
def process(self, output):
|
|
32
39
|
items: dict[str, list[str]] = {}
|
|
33
40
|
|
|
@@ -39,9 +46,11 @@ class GitConfig(GitFactBase):
|
|
|
39
46
|
|
|
40
47
|
|
|
41
48
|
class GitTrackingBranch(GitFactBase):
|
|
49
|
+
@override
|
|
42
50
|
def command(self, repo) -> str:
|
|
43
51
|
return r"! test -d {0} || (cd {0} && git status --branch --porcelain)".format(repo)
|
|
44
52
|
|
|
53
|
+
@override
|
|
45
54
|
def process(self, output):
|
|
46
55
|
if not output:
|
|
47
56
|
return None
|
pyinfra/facts/gpg.py
CHANGED
|
@@ -2,18 +2,22 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from urllib.parse import urlparse
|
|
4
4
|
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
5
7
|
from pyinfra.api import FactBase
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class GpgFactBase(FactBase):
|
|
9
11
|
abstract = True
|
|
10
12
|
|
|
13
|
+
@override
|
|
11
14
|
def requires_command(self, *args, **kwargs) -> str:
|
|
12
15
|
return "gpg"
|
|
13
16
|
|
|
14
17
|
key_record_type = "pub"
|
|
15
18
|
subkey_record_type = "sub"
|
|
16
19
|
|
|
20
|
+
@override
|
|
17
21
|
def process(self, output):
|
|
18
22
|
# For details on the field values see:
|
|
19
23
|
# https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob_plain;f=doc/DETAILS
|
|
@@ -88,6 +92,7 @@ class GpgKey(GpgFactBase):
|
|
|
88
92
|
}
|
|
89
93
|
"""
|
|
90
94
|
|
|
95
|
+
@override
|
|
91
96
|
def command(self, src):
|
|
92
97
|
if urlparse(src).scheme:
|
|
93
98
|
return ("(wget -O - {0} || curl -sSLf {0}) | gpg --with-colons").format(src)
|
|
@@ -109,6 +114,7 @@ class GpgKeys(GpgFactBase):
|
|
|
109
114
|
}
|
|
110
115
|
"""
|
|
111
116
|
|
|
117
|
+
@override
|
|
112
118
|
def command(self, keyring=None):
|
|
113
119
|
if not keyring:
|
|
114
120
|
return "gpg --list-keys --with-colons"
|
|
@@ -134,6 +140,7 @@ class GpgSecretKeys(GpgFactBase):
|
|
|
134
140
|
key_record_type = "sec"
|
|
135
141
|
subkey_record_type = "ssb"
|
|
136
142
|
|
|
143
|
+
@override
|
|
137
144
|
def command(self, keyring=None):
|
|
138
145
|
if not keyring:
|
|
139
146
|
return "gpg --list-secret-keys --with-colons"
|
pyinfra/facts/hardware.py
CHANGED
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
5
7
|
from pyinfra.api import FactBase, ShortFactBase
|
|
6
8
|
|
|
7
9
|
|
|
@@ -10,9 +12,11 @@ class Cpus(FactBase[int]):
|
|
|
10
12
|
Returns the number of CPUs on this server.
|
|
11
13
|
"""
|
|
12
14
|
|
|
15
|
+
@override
|
|
13
16
|
def command(self) -> str:
|
|
14
17
|
return "getconf NPROCESSORS_ONLN 2> /dev/null || getconf _NPROCESSORS_ONLN"
|
|
15
18
|
|
|
19
|
+
@override
|
|
16
20
|
def process(self, output):
|
|
17
21
|
try:
|
|
18
22
|
return int(list(output)[0])
|
|
@@ -25,12 +29,15 @@ class Memory(FactBase):
|
|
|
25
29
|
Returns the memory installed in this server, in MB.
|
|
26
30
|
"""
|
|
27
31
|
|
|
32
|
+
@override
|
|
28
33
|
def requires_command(self) -> str:
|
|
29
34
|
return "vmstat"
|
|
30
35
|
|
|
36
|
+
@override
|
|
31
37
|
def command(self) -> str:
|
|
32
38
|
return "vmstat -s"
|
|
33
39
|
|
|
40
|
+
@override
|
|
34
41
|
def process(self, output):
|
|
35
42
|
data = {}
|
|
36
43
|
|
|
@@ -80,9 +87,11 @@ class BlockDevices(FactBase):
|
|
|
80
87
|
regex = r"([a-zA-Z0-9\/\-_]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]{1,3})%\s+([a-zA-Z\/0-9\-_]+)" # noqa: E501
|
|
81
88
|
default = dict
|
|
82
89
|
|
|
90
|
+
@override
|
|
83
91
|
def command(self) -> str:
|
|
84
92
|
return "df"
|
|
85
93
|
|
|
94
|
+
@override
|
|
86
95
|
def process(self, output):
|
|
87
96
|
devices = {}
|
|
88
97
|
|
|
@@ -177,11 +186,13 @@ class NetworkDevices(FactBase):
|
|
|
177
186
|
|
|
178
187
|
default = dict
|
|
179
188
|
|
|
189
|
+
@override
|
|
180
190
|
def command(self) -> str:
|
|
181
191
|
return "ip addr show 2> /dev/null || ifconfig -a"
|
|
182
192
|
|
|
183
193
|
# Definition of valid interface names for Linux:
|
|
184
194
|
# https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/net/core/dev.c?h=v5.1.3#n1020
|
|
195
|
+
@override
|
|
185
196
|
def process(self, output):
|
|
186
197
|
def mask(value):
|
|
187
198
|
try:
|
|
@@ -318,6 +329,7 @@ class Ipv4Addrs(ShortFactBase):
|
|
|
318
329
|
fact = NetworkDevices
|
|
319
330
|
ip_type = "ipv4"
|
|
320
331
|
|
|
332
|
+
@override
|
|
321
333
|
def process_data(self, data):
|
|
322
334
|
host_to_ips = {}
|
|
323
335
|
|
|
@@ -379,6 +391,7 @@ class Ipv4Addresses(ShortFactBase):
|
|
|
379
391
|
fact = NetworkDevices
|
|
380
392
|
ip_type = "ipv4"
|
|
381
393
|
|
|
394
|
+
@override
|
|
382
395
|
def process_data(self, data):
|
|
383
396
|
addresses = {}
|
|
384
397
|
|
pyinfra/facts/iptables.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing_extensions import override
|
|
4
|
+
|
|
3
5
|
from pyinfra.api import FactBase
|
|
4
6
|
|
|
5
7
|
# Mapping for iptables code arguments to variable names
|
|
@@ -35,7 +37,7 @@ def parse_iptables_rule(line):
|
|
|
35
37
|
args: list[str] = []
|
|
36
38
|
not_arg = False
|
|
37
39
|
|
|
38
|
-
def add_args():
|
|
40
|
+
def add_args() -> None:
|
|
39
41
|
arg_string = " ".join(args)
|
|
40
42
|
|
|
41
43
|
if key and key in IPTABLES_ARGS:
|
|
@@ -89,9 +91,11 @@ class IptablesRules(FactBase):
|
|
|
89
91
|
|
|
90
92
|
default = list
|
|
91
93
|
|
|
94
|
+
@override
|
|
92
95
|
def command(self, table="filter"):
|
|
93
96
|
return "iptables-save -t {0}".format(table)
|
|
94
97
|
|
|
98
|
+
@override
|
|
95
99
|
def process(self, output):
|
|
96
100
|
rules = []
|
|
97
101
|
|
|
@@ -116,6 +120,7 @@ class Ip6tablesRules(IptablesRules):
|
|
|
116
120
|
]
|
|
117
121
|
"""
|
|
118
122
|
|
|
123
|
+
@override
|
|
119
124
|
def command(self, table="filter"):
|
|
120
125
|
return "ip6tables-save -t {0}".format(table)
|
|
121
126
|
|
|
@@ -133,9 +138,11 @@ class IptablesChains(FactBase):
|
|
|
133
138
|
|
|
134
139
|
default = dict
|
|
135
140
|
|
|
141
|
+
@override
|
|
136
142
|
def command(self, table="filter"):
|
|
137
143
|
return "iptables-save -t {0}".format(table)
|
|
138
144
|
|
|
145
|
+
@override
|
|
139
146
|
def process(self, output):
|
|
140
147
|
chains = {}
|
|
141
148
|
|
|
@@ -160,5 +167,6 @@ class Ip6tablesChains(IptablesChains):
|
|
|
160
167
|
}
|
|
161
168
|
"""
|
|
162
169
|
|
|
170
|
+
@override
|
|
163
171
|
def command(self, table="filter"):
|
|
164
172
|
return "ip6tables-save -t {0}".format(table)
|
pyinfra/facts/launchd.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from typing_extensions import override
|
|
4
|
+
|
|
3
5
|
from pyinfra.api import FactBase
|
|
4
6
|
|
|
5
7
|
|
|
@@ -8,14 +10,17 @@ class LaunchdStatus(FactBase):
|
|
|
8
10
|
Returns a dict of name -> status for launchd managed services.
|
|
9
11
|
"""
|
|
10
12
|
|
|
13
|
+
@override
|
|
11
14
|
def command(self) -> str:
|
|
12
15
|
return "launchctl list"
|
|
13
16
|
|
|
17
|
+
@override
|
|
14
18
|
def requires_command(self) -> str:
|
|
15
19
|
return "launchctl"
|
|
16
20
|
|
|
17
21
|
default = dict
|
|
18
22
|
|
|
23
|
+
@override
|
|
19
24
|
def process(self, output):
|
|
20
25
|
services = {}
|
|
21
26
|
|
pyinfra/facts/lxd.py
CHANGED
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
5
7
|
from pyinfra.api import FactBase
|
|
6
8
|
|
|
7
9
|
|
|
@@ -10,14 +12,17 @@ class LxdContainers(FactBase):
|
|
|
10
12
|
Returns a list of running LXD containers
|
|
11
13
|
"""
|
|
12
14
|
|
|
15
|
+
@override
|
|
13
16
|
def command(self) -> str:
|
|
14
17
|
return "lxc list --format json --fast"
|
|
15
18
|
|
|
19
|
+
@override
|
|
16
20
|
def requires_command(self) -> str:
|
|
17
21
|
return "lxc"
|
|
18
22
|
|
|
19
23
|
default = list
|
|
20
24
|
|
|
25
|
+
@override
|
|
21
26
|
def process(self, output):
|
|
22
27
|
output = list(output)
|
|
23
28
|
assert len(output) == 1
|
pyinfra/facts/mysql.py
CHANGED
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import re
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
|
|
6
|
+
from typing_extensions import override
|
|
7
|
+
|
|
6
8
|
from pyinfra.api import FactBase, MaskString, QuoteString, StringCommand
|
|
7
9
|
from pyinfra.api.util import try_int
|
|
8
10
|
|
|
@@ -62,9 +64,11 @@ class MysqlFactBase(FactBase):
|
|
|
62
64
|
mysql_command: str
|
|
63
65
|
ignore_errors = False
|
|
64
66
|
|
|
67
|
+
@override
|
|
65
68
|
def requires_command(self, *args, **kwargs) -> str:
|
|
66
69
|
return "mysql"
|
|
67
70
|
|
|
71
|
+
@override
|
|
68
72
|
def command(
|
|
69
73
|
self,
|
|
70
74
|
# Details for speaking to MySQL via `mysql` CLI via `mysql` CLI
|
|
@@ -100,6 +104,7 @@ class MysqlDatabases(MysqlFactBase):
|
|
|
100
104
|
default = dict
|
|
101
105
|
mysql_command = "SELECT * FROM information_schema.SCHEMATA"
|
|
102
106
|
|
|
107
|
+
@override
|
|
103
108
|
def process(self, output):
|
|
104
109
|
rows = parse_columns_and_rows(
|
|
105
110
|
output,
|
|
@@ -136,6 +141,7 @@ class MysqlUsers(MysqlFactBase):
|
|
|
136
141
|
default = dict
|
|
137
142
|
mysql_command = "SELECT * FROM mysql.user"
|
|
138
143
|
|
|
144
|
+
@override
|
|
139
145
|
def process(self, output):
|
|
140
146
|
rows = parse_columns_and_rows(output, "\t")
|
|
141
147
|
|
|
@@ -195,6 +201,7 @@ class MysqlUserGrants(MysqlFactBase):
|
|
|
195
201
|
# Ignore errors as SHOW GRANTS will error if the user does not exist
|
|
196
202
|
ignore_errors = True
|
|
197
203
|
|
|
204
|
+
@override
|
|
198
205
|
def command( # type: ignore[override]
|
|
199
206
|
self,
|
|
200
207
|
user,
|
|
@@ -214,6 +221,7 @@ class MysqlUserGrants(MysqlFactBase):
|
|
|
214
221
|
mysql_port,
|
|
215
222
|
)
|
|
216
223
|
|
|
224
|
+
@override
|
|
217
225
|
def process(self, output):
|
|
218
226
|
database_table_privileges = defaultdict(set)
|
|
219
227
|
|
pyinfra/facts/npm.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# encoding: utf8
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
+
from typing_extensions import override
|
|
5
|
+
|
|
4
6
|
from pyinfra.api import FactBase
|
|
5
7
|
|
|
6
8
|
from .util.packaging import parse_packages
|
|
@@ -21,13 +23,16 @@ class NpmPackages(FactBase):
|
|
|
21
23
|
|
|
22
24
|
default = dict
|
|
23
25
|
|
|
26
|
+
@override
|
|
24
27
|
def requires_command(self, directory=None) -> str:
|
|
25
28
|
return "npm"
|
|
26
29
|
|
|
30
|
+
@override
|
|
27
31
|
def command(self, directory=None):
|
|
28
32
|
if directory:
|
|
29
33
|
return ("cd {0} && npm list -g --depth=0").format(directory)
|
|
30
34
|
return "npm list -g --depth=0"
|
|
31
35
|
|
|
36
|
+
@override
|
|
32
37
|
def process(self, output):
|
|
33
38
|
return parse_packages(NPM_REGEX, output)
|
pyinfra/facts/openrc.py
CHANGED
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
|
|
5
|
+
from typing_extensions import override
|
|
6
|
+
|
|
5
7
|
from pyinfra.api import FactBase
|
|
6
8
|
|
|
7
9
|
|
|
@@ -20,12 +22,15 @@ class OpenrcStatus(FactBase):
|
|
|
20
22
|
r"\s+\]"
|
|
21
23
|
)
|
|
22
24
|
|
|
25
|
+
@override
|
|
23
26
|
def requires_command(self, runlevel="default") -> str:
|
|
24
27
|
return "rc-status"
|
|
25
28
|
|
|
29
|
+
@override
|
|
26
30
|
def command(self, runlevel="default"):
|
|
27
31
|
return "rc-status {0}".format(runlevel)
|
|
28
32
|
|
|
33
|
+
@override
|
|
29
34
|
def process(self, output):
|
|
30
35
|
services = {}
|
|
31
36
|
|
|
@@ -44,13 +49,16 @@ class OpenrcEnabled(FactBase):
|
|
|
44
49
|
|
|
45
50
|
default = dict
|
|
46
51
|
|
|
52
|
+
@override
|
|
47
53
|
def requires_command(self, runlevel="default") -> str:
|
|
48
54
|
return "rc-update"
|
|
49
55
|
|
|
56
|
+
@override
|
|
50
57
|
def command(self, runlevel="default"):
|
|
51
58
|
self.runlevel = runlevel
|
|
52
59
|
return "rc-update show -v"
|
|
53
60
|
|
|
61
|
+
@override
|
|
54
62
|
def process(self, output):
|
|
55
63
|
services = {}
|
|
56
64
|
|