pyinfra 3.0b4__py2.py3-none-any.whl → 3.0.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/facts.py +7 -50
- pyinfra/api/util.py +1 -1
- pyinfra/connectors/ssh.py +3 -3
- pyinfra/connectors/sshuserclient/client.py +1 -1
- pyinfra/facts/apk.py +5 -2
- pyinfra/facts/apt.py +13 -7
- pyinfra/facts/brew.py +26 -13
- pyinfra/facts/bsdinit.py +7 -6
- pyinfra/facts/cargo.py +4 -3
- pyinfra/facts/choco.py +6 -4
- pyinfra/facts/deb.py +12 -5
- pyinfra/facts/dnf.py +9 -6
- pyinfra/facts/docker.py +13 -6
- pyinfra/facts/files.py +3 -3
- pyinfra/facts/gem.py +5 -2
- pyinfra/facts/git.py +14 -21
- pyinfra/facts/gpg.py +2 -1
- pyinfra/facts/hardware.py +17 -11
- pyinfra/facts/launchd.py +5 -2
- pyinfra/facts/lxd.py +6 -2
- pyinfra/facts/mysql.py +7 -6
- pyinfra/facts/npm.py +2 -1
- pyinfra/facts/openrc.py +6 -2
- pyinfra/facts/pacman.py +7 -3
- pyinfra/facts/pkg.py +3 -1
- pyinfra/facts/pkgin.py +5 -2
- pyinfra/facts/postgres.py +3 -1
- pyinfra/facts/rpm.py +12 -9
- pyinfra/facts/runit.py +4 -2
- pyinfra/facts/selinux.py +12 -4
- pyinfra/facts/server.py +80 -51
- pyinfra/facts/snap.py +6 -2
- pyinfra/facts/systemd.py +10 -5
- pyinfra/facts/sysvinit.py +2 -1
- pyinfra/facts/upstart.py +5 -2
- pyinfra/facts/vzctl.py +6 -4
- pyinfra/facts/xbps.py +5 -2
- pyinfra/facts/yum.py +8 -5
- pyinfra/facts/zypper.py +7 -4
- pyinfra/operations/apt.py +5 -0
- pyinfra/operations/selinux.py +1 -1
- pyinfra/operations/server.py +1 -1
- {pyinfra-3.0b4.dist-info → pyinfra-3.0.1.dist-info}/METADATA +1 -5
- {pyinfra-3.0b4.dist-info → pyinfra-3.0.1.dist-info}/RECORD +54 -53
- pyinfra_cli/__main__.py +2 -3
- pyinfra_cli/inventory.py +13 -11
- pyinfra_cli/main.py +10 -9
- tests/test_api/test_api_facts.py +2 -2
- tests/test_cli/test_cli.py +0 -1
- tests/test_cli/test_cli_inventory.py +66 -0
- {pyinfra-3.0b4.dist-info → pyinfra-3.0.1.dist-info}/LICENSE.md +0 -0
- {pyinfra-3.0b4.dist-info → pyinfra-3.0.1.dist-info}/WHEEL +0 -0
- {pyinfra-3.0b4.dist-info → pyinfra-3.0.1.dist-info}/entry_points.txt +0 -0
- {pyinfra-3.0b4.dist-info → pyinfra-3.0.1.dist-info}/top_level.txt +0 -0
pyinfra/facts/mysql.py
CHANGED
|
@@ -60,9 +60,11 @@ class MysqlFactBase(FactBase):
|
|
|
60
60
|
abstract = True
|
|
61
61
|
|
|
62
62
|
mysql_command: str
|
|
63
|
-
requires_command = "mysql"
|
|
64
63
|
ignore_errors = False
|
|
65
64
|
|
|
65
|
+
def requires_command(self, *args, **kwargs) -> str:
|
|
66
|
+
return "mysql"
|
|
67
|
+
|
|
66
68
|
def command(
|
|
67
69
|
self,
|
|
68
70
|
# Details for speaking to MySQL via `mysql` CLI via `mysql` CLI
|
|
@@ -70,7 +72,7 @@ class MysqlFactBase(FactBase):
|
|
|
70
72
|
mysql_password=None,
|
|
71
73
|
mysql_host=None,
|
|
72
74
|
mysql_port=None,
|
|
73
|
-
):
|
|
75
|
+
) -> StringCommand:
|
|
74
76
|
return make_execute_mysql_command(
|
|
75
77
|
self.mysql_command,
|
|
76
78
|
ignore_errors=self.ignore_errors,
|
|
@@ -134,8 +136,7 @@ class MysqlUsers(MysqlFactBase):
|
|
|
134
136
|
default = dict
|
|
135
137
|
mysql_command = "SELECT * FROM mysql.user"
|
|
136
138
|
|
|
137
|
-
|
|
138
|
-
def process(output):
|
|
139
|
+
def process(self, output):
|
|
139
140
|
rows = parse_columns_and_rows(output, "\t")
|
|
140
141
|
|
|
141
142
|
users = {}
|
|
@@ -194,7 +195,7 @@ class MysqlUserGrants(MysqlFactBase):
|
|
|
194
195
|
# Ignore errors as SHOW GRANTS will error if the user does not exist
|
|
195
196
|
ignore_errors = True
|
|
196
197
|
|
|
197
|
-
def command(
|
|
198
|
+
def command( # type: ignore[override]
|
|
198
199
|
self,
|
|
199
200
|
user,
|
|
200
201
|
hostname="localhost",
|
|
@@ -203,7 +204,7 @@ class MysqlUserGrants(MysqlFactBase):
|
|
|
203
204
|
mysql_password=None,
|
|
204
205
|
mysql_host=None,
|
|
205
206
|
mysql_port=None,
|
|
206
|
-
):
|
|
207
|
+
) -> StringCommand:
|
|
207
208
|
self.mysql_command = 'SHOW GRANTS FOR "{0}"@"{1}"'.format(user, hostname)
|
|
208
209
|
|
|
209
210
|
return super().command(
|
pyinfra/facts/npm.py
CHANGED
pyinfra/facts/openrc.py
CHANGED
|
@@ -11,7 +11,6 @@ class OpenrcStatus(FactBase):
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
default = dict
|
|
14
|
-
requires_command = "rc-status"
|
|
15
14
|
regex = (
|
|
16
15
|
r"\s+([a-zA-Z0-9\-_]+)"
|
|
17
16
|
r"\s+\[\s+"
|
|
@@ -21,6 +20,9 @@ class OpenrcStatus(FactBase):
|
|
|
21
20
|
r"\s+\]"
|
|
22
21
|
)
|
|
23
22
|
|
|
23
|
+
def requires_command(self, runlevel="default") -> str:
|
|
24
|
+
return "rc-status"
|
|
25
|
+
|
|
24
26
|
def command(self, runlevel="default"):
|
|
25
27
|
return "rc-status {0}".format(runlevel)
|
|
26
28
|
|
|
@@ -41,7 +43,9 @@ class OpenrcEnabled(FactBase):
|
|
|
41
43
|
"""
|
|
42
44
|
|
|
43
45
|
default = dict
|
|
44
|
-
|
|
46
|
+
|
|
47
|
+
def requires_command(self, runlevel="default") -> str:
|
|
48
|
+
return "rc-update"
|
|
45
49
|
|
|
46
50
|
def command(self, runlevel="default"):
|
|
47
51
|
self.runlevel = runlevel
|
pyinfra/facts/pacman.py
CHANGED
|
@@ -21,7 +21,8 @@ class PacmanUnpackGroup(FactBase):
|
|
|
21
21
|
]
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
requires_command
|
|
24
|
+
def requires_command(self, *args, **kwargs) -> str:
|
|
25
|
+
return "pacman"
|
|
25
26
|
|
|
26
27
|
default = list
|
|
27
28
|
|
|
@@ -44,8 +45,11 @@ class PacmanPackages(FactBase):
|
|
|
44
45
|
}
|
|
45
46
|
"""
|
|
46
47
|
|
|
47
|
-
command
|
|
48
|
-
|
|
48
|
+
def command(self) -> str:
|
|
49
|
+
return "pacman -Q"
|
|
50
|
+
|
|
51
|
+
def requires_command(self, *args, **kwargs) -> str:
|
|
52
|
+
return "pacman"
|
|
49
53
|
|
|
50
54
|
default = dict
|
|
51
55
|
|
pyinfra/facts/pkg.py
CHANGED
|
@@ -16,9 +16,11 @@ class PkgPackages(FactBase):
|
|
|
16
16
|
}
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
-
command = "pkg info || pkg_info || true"
|
|
20
19
|
regex = r"^([a-zA-Z0-9_\-\+]+)\-([0-9a-z\.]+)"
|
|
21
20
|
default = dict
|
|
22
21
|
|
|
22
|
+
def command(self) -> str:
|
|
23
|
+
return "pkg info || pkg_info || true"
|
|
24
|
+
|
|
23
25
|
def process(self, output):
|
|
24
26
|
return parse_packages(self.regex, output)
|
pyinfra/facts/pkgin.py
CHANGED
pyinfra/facts/postgres.py
CHANGED
pyinfra/facts/rpm.py
CHANGED
|
@@ -22,8 +22,11 @@ class RpmPackages(FactBase):
|
|
|
22
22
|
}
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
command
|
|
26
|
-
|
|
25
|
+
def command(self) -> str:
|
|
26
|
+
return "rpm --queryformat {0} -qa".format(shlex.quote(rpm_query_format))
|
|
27
|
+
|
|
28
|
+
def requires_command(self) -> str:
|
|
29
|
+
return "rpm"
|
|
27
30
|
|
|
28
31
|
default = dict
|
|
29
32
|
|
|
@@ -43,9 +46,10 @@ class RpmPackage(FactBase):
|
|
|
43
46
|
}
|
|
44
47
|
"""
|
|
45
48
|
|
|
46
|
-
requires_command
|
|
49
|
+
def requires_command(self, package) -> str:
|
|
50
|
+
return "rpm"
|
|
47
51
|
|
|
48
|
-
def command(self, package):
|
|
52
|
+
def command(self, package) -> str:
|
|
49
53
|
return (
|
|
50
54
|
"rpm --queryformat {0} -q {1} || "
|
|
51
55
|
"! test -e {1} || "
|
|
@@ -69,18 +73,17 @@ class RpmPackageProvides(FactBase):
|
|
|
69
73
|
|
|
70
74
|
default = list
|
|
71
75
|
|
|
72
|
-
requires_command
|
|
76
|
+
def requires_command(self, *args, **kwargs) -> str:
|
|
77
|
+
return "repoquery"
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
def command(package):
|
|
79
|
+
def command(self, package):
|
|
76
80
|
# Accept failure here (|| true) for invalid/unknown packages
|
|
77
81
|
return "repoquery --queryformat {0} --whatprovides {1} || true".format(
|
|
78
82
|
shlex.quote(rpm_query_format),
|
|
79
83
|
shlex.quote(package),
|
|
80
84
|
)
|
|
81
85
|
|
|
82
|
-
|
|
83
|
-
def process(output):
|
|
86
|
+
def process(self, output):
|
|
84
87
|
packages = []
|
|
85
88
|
|
|
86
89
|
for line in output:
|
pyinfra/facts/runit.py
CHANGED
|
@@ -18,10 +18,12 @@ class RunitStatus(FactBase):
|
|
|
18
18
|
}
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
requires_command = "sv"
|
|
22
21
|
default = dict
|
|
23
22
|
|
|
24
|
-
def
|
|
23
|
+
def requires_command(self, *args, **kwargs) -> str:
|
|
24
|
+
return "sv"
|
|
25
|
+
|
|
26
|
+
def command(self, service=None, svdir="/var/service") -> str:
|
|
25
27
|
if service is None:
|
|
26
28
|
return (
|
|
27
29
|
'export SVDIR="{0}" && '
|
pyinfra/facts/selinux.py
CHANGED
|
@@ -14,7 +14,9 @@ class SEBoolean(FactBase):
|
|
|
14
14
|
If ``boolean`` does not exist, ``SEBoolean`` returns the empty string.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
-
requires_command
|
|
17
|
+
def requires_command(self, boolean) -> str:
|
|
18
|
+
return "getsebool"
|
|
19
|
+
|
|
18
20
|
default = str
|
|
19
21
|
|
|
20
22
|
def command(self, boolean):
|
|
@@ -60,9 +62,11 @@ class FileContextMapping(FactBase):
|
|
|
60
62
|
Note: This fact requires root privileges.
|
|
61
63
|
"""
|
|
62
64
|
|
|
63
|
-
requires_command = "semanage"
|
|
64
65
|
default = dict
|
|
65
66
|
|
|
67
|
+
def requires_command(self, target) -> str:
|
|
68
|
+
return "semanage"
|
|
69
|
+
|
|
66
70
|
def command(self, target):
|
|
67
71
|
return "set -o pipefail && semanage fcontext -n -l | (grep '^{0}' || true)".format(target)
|
|
68
72
|
|
|
@@ -87,11 +91,13 @@ class SEPorts(FactBase):
|
|
|
87
91
|
}
|
|
88
92
|
"""
|
|
89
93
|
|
|
90
|
-
requires_command = "semanage"
|
|
91
94
|
default = dict
|
|
92
95
|
# example output: amqp_port_t tcp 15672, 5671-5672 # noqa: SC100
|
|
93
96
|
_regex = re.compile(r"^([\w_]+)\s+(\w+)\s+([\w\-,\s]+)$")
|
|
94
97
|
|
|
98
|
+
def requires_command(self) -> str:
|
|
99
|
+
return "semanage"
|
|
100
|
+
|
|
95
101
|
def command(self):
|
|
96
102
|
return "semanage port -ln"
|
|
97
103
|
|
|
@@ -122,9 +128,11 @@ class SEPort(FactBase):
|
|
|
122
128
|
Note: ``policycoreutils-dev`` must be installed for this to work.
|
|
123
129
|
"""
|
|
124
130
|
|
|
125
|
-
requires_command = "sepolicy"
|
|
126
131
|
default = str
|
|
127
132
|
|
|
133
|
+
def requires_command(self, protocol, port) -> str:
|
|
134
|
+
return "sepolicy"
|
|
135
|
+
|
|
128
136
|
def command(self, protocol, port):
|
|
129
137
|
return "(sepolicy network -p {0} 2>/dev/null || true) | grep {1}".format(port, protocol)
|
|
130
138
|
|
pyinfra/facts/server.py
CHANGED
|
@@ -22,7 +22,8 @@ class User(FactBase):
|
|
|
22
22
|
Returns the name of the current user.
|
|
23
23
|
"""
|
|
24
24
|
|
|
25
|
-
command
|
|
25
|
+
def command(self):
|
|
26
|
+
return "echo $USER"
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
class Home(FactBase[Optional[str]]):
|
|
@@ -40,7 +41,8 @@ class Path(FactBase):
|
|
|
40
41
|
Returns the path environment variable of the current user.
|
|
41
42
|
"""
|
|
42
43
|
|
|
43
|
-
command
|
|
44
|
+
def command(self):
|
|
45
|
+
return "echo $PATH"
|
|
44
46
|
|
|
45
47
|
|
|
46
48
|
class TmpDir(FactBase):
|
|
@@ -48,7 +50,8 @@ class TmpDir(FactBase):
|
|
|
48
50
|
Returns the temporary directory of the current server, if configured.
|
|
49
51
|
"""
|
|
50
52
|
|
|
51
|
-
command
|
|
53
|
+
def command(self):
|
|
54
|
+
return "echo $TMPDIR"
|
|
52
55
|
|
|
53
56
|
|
|
54
57
|
class Hostname(FactBase):
|
|
@@ -56,7 +59,8 @@ class Hostname(FactBase):
|
|
|
56
59
|
Returns the current hostname of the server.
|
|
57
60
|
"""
|
|
58
61
|
|
|
59
|
-
command
|
|
62
|
+
def command(self):
|
|
63
|
+
return "uname -n"
|
|
60
64
|
|
|
61
65
|
|
|
62
66
|
class Kernel(FactBase):
|
|
@@ -64,7 +68,8 @@ class Kernel(FactBase):
|
|
|
64
68
|
Returns the kernel name according to ``uname``.
|
|
65
69
|
"""
|
|
66
70
|
|
|
67
|
-
command
|
|
71
|
+
def command(self):
|
|
72
|
+
return "uname -s"
|
|
68
73
|
|
|
69
74
|
|
|
70
75
|
class KernelVersion(FactBase):
|
|
@@ -72,7 +77,8 @@ class KernelVersion(FactBase):
|
|
|
72
77
|
Returns the kernel version according to ``uname``.
|
|
73
78
|
"""
|
|
74
79
|
|
|
75
|
-
command
|
|
80
|
+
def command(self):
|
|
81
|
+
return "uname -r"
|
|
76
82
|
|
|
77
83
|
|
|
78
84
|
# Deprecated/renamed -> Kernel
|
|
@@ -84,7 +90,8 @@ class Os(FactBase[str]):
|
|
|
84
90
|
This fact is deprecated/renamed, please use the ``server.Kernel`` fact.
|
|
85
91
|
"""
|
|
86
92
|
|
|
87
|
-
command
|
|
93
|
+
def command(self):
|
|
94
|
+
return "uname -s"
|
|
88
95
|
|
|
89
96
|
|
|
90
97
|
# Deprecated/renamed -> KernelVersion
|
|
@@ -96,7 +103,8 @@ class OsVersion(FactBase[str]):
|
|
|
96
103
|
This fact is deprecated/renamed, please use the ``server.KernelVersion`` fact.
|
|
97
104
|
"""
|
|
98
105
|
|
|
99
|
-
command
|
|
106
|
+
def command(self):
|
|
107
|
+
return "uname -r"
|
|
100
108
|
|
|
101
109
|
|
|
102
110
|
class Arch(FactBase[str]):
|
|
@@ -106,7 +114,8 @@ class Arch(FactBase[str]):
|
|
|
106
114
|
|
|
107
115
|
# ``uname -p`` is not portable and returns ``unknown`` on Debian.
|
|
108
116
|
# ``uname -m`` works on most Linux and BSD systems.
|
|
109
|
-
command
|
|
117
|
+
def command(self):
|
|
118
|
+
return "uname -m"
|
|
110
119
|
|
|
111
120
|
|
|
112
121
|
class Command(FactBase[str]):
|
|
@@ -121,12 +130,12 @@ class Command(FactBase[str]):
|
|
|
121
130
|
|
|
122
131
|
class Which(FactBase[Optional[str]]):
|
|
123
132
|
"""
|
|
124
|
-
Returns the path of a given command
|
|
133
|
+
Returns the path of a given command according to `command -v`, if available.
|
|
125
134
|
"""
|
|
126
135
|
|
|
127
136
|
@staticmethod
|
|
128
137
|
def command(command):
|
|
129
|
-
return "
|
|
138
|
+
return "command -v {0} || true".format(command)
|
|
130
139
|
|
|
131
140
|
|
|
132
141
|
class Date(FactBase[datetime]):
|
|
@@ -134,12 +143,13 @@ class Date(FactBase[datetime]):
|
|
|
134
143
|
Returns the current datetime on the server.
|
|
135
144
|
"""
|
|
136
145
|
|
|
137
|
-
command = f"date +'{ISO_DATE_FORMAT}'"
|
|
138
146
|
default = datetime.now
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
148
|
+
def command(self):
|
|
149
|
+
return f"date +'{ISO_DATE_FORMAT}'"
|
|
150
|
+
|
|
151
|
+
def process(self, output) -> datetime:
|
|
152
|
+
return datetime.strptime(list(output)[0], ISO_DATE_FORMAT)
|
|
143
153
|
|
|
144
154
|
|
|
145
155
|
class MacosVersion(FactBase[str]):
|
|
@@ -147,8 +157,11 @@ class MacosVersion(FactBase[str]):
|
|
|
147
157
|
Returns the installed MacOS version.
|
|
148
158
|
"""
|
|
149
159
|
|
|
150
|
-
|
|
151
|
-
|
|
160
|
+
def requires_command(self) -> str:
|
|
161
|
+
return "sw_vers"
|
|
162
|
+
|
|
163
|
+
def command(self):
|
|
164
|
+
return "sw_vers -productVersion"
|
|
152
165
|
|
|
153
166
|
|
|
154
167
|
class MountsDict(TypedDict):
|
|
@@ -175,11 +188,12 @@ class Mounts(FactBase[Dict[str, MountsDict]]):
|
|
|
175
188
|
}
|
|
176
189
|
"""
|
|
177
190
|
|
|
178
|
-
command = "mount"
|
|
179
191
|
default = dict
|
|
180
192
|
|
|
181
|
-
|
|
182
|
-
|
|
193
|
+
def command(self):
|
|
194
|
+
return "mount"
|
|
195
|
+
|
|
196
|
+
def process(self, output) -> dict[str, MountsDict]:
|
|
183
197
|
devices: dict[str, MountsDict] = {}
|
|
184
198
|
|
|
185
199
|
for line in output:
|
|
@@ -224,11 +238,12 @@ class KernelModules(FactBase):
|
|
|
224
238
|
}
|
|
225
239
|
"""
|
|
226
240
|
|
|
227
|
-
command
|
|
241
|
+
def command(self):
|
|
242
|
+
return "! test -f /proc/modules || cat /proc/modules"
|
|
243
|
+
|
|
228
244
|
default = dict
|
|
229
245
|
|
|
230
|
-
|
|
231
|
-
def process(output):
|
|
246
|
+
def process(self, output):
|
|
232
247
|
modules = {}
|
|
233
248
|
|
|
234
249
|
for line in output:
|
|
@@ -264,11 +279,13 @@ class LsbRelease(FactBase):
|
|
|
264
279
|
}
|
|
265
280
|
"""
|
|
266
281
|
|
|
267
|
-
command
|
|
268
|
-
|
|
282
|
+
def command(self):
|
|
283
|
+
return "lsb_release -ca"
|
|
269
284
|
|
|
270
|
-
|
|
271
|
-
|
|
285
|
+
def requires_command(self):
|
|
286
|
+
return "lsb_release"
|
|
287
|
+
|
|
288
|
+
def process(self, output):
|
|
272
289
|
items = {}
|
|
273
290
|
|
|
274
291
|
for line in output:
|
|
@@ -307,14 +324,12 @@ class Sysctl(FactBase):
|
|
|
307
324
|
|
|
308
325
|
default = dict
|
|
309
326
|
|
|
310
|
-
|
|
311
|
-
def command(keys=None):
|
|
327
|
+
def command(self, keys=None):
|
|
312
328
|
if keys is None:
|
|
313
329
|
return "sysctl -a"
|
|
314
330
|
return f"sysctl {' '.join(keys)}"
|
|
315
331
|
|
|
316
|
-
|
|
317
|
-
def process(output):
|
|
332
|
+
def process(self, output):
|
|
318
333
|
sysctls = {}
|
|
319
334
|
|
|
320
335
|
for line in output:
|
|
@@ -347,7 +362,9 @@ class Groups(FactBase[List[str]]):
|
|
|
347
362
|
Returns a list of groups on the system.
|
|
348
363
|
"""
|
|
349
364
|
|
|
350
|
-
command
|
|
365
|
+
def command(self):
|
|
366
|
+
return "cat /etc/group"
|
|
367
|
+
|
|
351
368
|
default = list
|
|
352
369
|
|
|
353
370
|
def process(self, output) -> list[str]:
|
|
@@ -392,10 +409,10 @@ class Crontab(FactBase[Dict[str, CrontabDict]]):
|
|
|
392
409
|
|
|
393
410
|
default = dict
|
|
394
411
|
|
|
395
|
-
requires_command =
|
|
412
|
+
def requires_command(self, user=None) -> str:
|
|
413
|
+
return "crontab"
|
|
396
414
|
|
|
397
|
-
|
|
398
|
-
def command(user=None):
|
|
415
|
+
def command(self, user=None):
|
|
399
416
|
if user:
|
|
400
417
|
return "crontab -l -u {0} || true".format(user)
|
|
401
418
|
return "crontab -l || true"
|
|
@@ -455,7 +472,9 @@ class Users(FactBase):
|
|
|
455
472
|
}
|
|
456
473
|
"""
|
|
457
474
|
|
|
458
|
-
command
|
|
475
|
+
def command(self):
|
|
476
|
+
return """
|
|
477
|
+
|
|
459
478
|
for i in `cat /etc/passwd | cut -d: -f1`; do
|
|
460
479
|
ENTRY=`grep ^$i: /etc/passwd`;
|
|
461
480
|
LASTLOG_RAW=`(lastlog -u $i 2> /dev/null || lastlogin $i 2> /dev/null)`;
|
|
@@ -538,11 +557,12 @@ class LinuxDistribution(FactBase[LinuxDistributionDict]):
|
|
|
538
557
|
}
|
|
539
558
|
"""
|
|
540
559
|
|
|
541
|
-
command
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
560
|
+
def command(self) -> str:
|
|
561
|
+
return (
|
|
562
|
+
"cd /etc/ && for file in $(ls -pdL *-release | grep -v /); "
|
|
563
|
+
'do echo "/etc/${file}"; cat "/etc/${file}"; echo ---; '
|
|
564
|
+
"done"
|
|
565
|
+
)
|
|
546
566
|
|
|
547
567
|
name_to_pretty_name = {
|
|
548
568
|
"alpine": "Alpine",
|
|
@@ -626,8 +646,7 @@ class LinuxName(ShortFactBase[str]):
|
|
|
626
646
|
|
|
627
647
|
fact = LinuxDistribution
|
|
628
648
|
|
|
629
|
-
|
|
630
|
-
def process_data(data):
|
|
649
|
+
def process_data(self, data) -> str:
|
|
631
650
|
return data["name"]
|
|
632
651
|
|
|
633
652
|
|
|
@@ -646,8 +665,11 @@ class Selinux(FactBase[SelinuxDict]):
|
|
|
646
665
|
}
|
|
647
666
|
"""
|
|
648
667
|
|
|
649
|
-
command
|
|
650
|
-
|
|
668
|
+
def command(self):
|
|
669
|
+
return "sestatus"
|
|
670
|
+
|
|
671
|
+
def requires_command(self) -> str:
|
|
672
|
+
return "sestatus"
|
|
651
673
|
|
|
652
674
|
@staticmethod
|
|
653
675
|
def default() -> SelinuxDict:
|
|
@@ -673,7 +695,9 @@ class LinuxGui(FactBase[List[str]]):
|
|
|
673
695
|
Returns a list of available Linux GUIs.
|
|
674
696
|
"""
|
|
675
697
|
|
|
676
|
-
command
|
|
698
|
+
def command(self):
|
|
699
|
+
return "ls /usr/bin/*session || true"
|
|
700
|
+
|
|
677
701
|
default = list
|
|
678
702
|
|
|
679
703
|
known_gui_binaries = {
|
|
@@ -702,8 +726,7 @@ class HasGui(ShortFactBase[bool]):
|
|
|
702
726
|
|
|
703
727
|
fact = LinuxGui
|
|
704
728
|
|
|
705
|
-
|
|
706
|
-
def process_data(data) -> bool:
|
|
729
|
+
def process_data(self, data) -> bool:
|
|
707
730
|
return len(data) > 0
|
|
708
731
|
|
|
709
732
|
|
|
@@ -716,8 +739,12 @@ class Locales(FactBase[List[str]]):
|
|
|
716
739
|
["C.UTF-8", "en_US.UTF-8"]
|
|
717
740
|
"""
|
|
718
741
|
|
|
719
|
-
command
|
|
720
|
-
|
|
742
|
+
def command(self) -> str:
|
|
743
|
+
return "locale -a"
|
|
744
|
+
|
|
745
|
+
def requires_command(self) -> str:
|
|
746
|
+
return "locale"
|
|
747
|
+
|
|
721
748
|
default = list
|
|
722
749
|
|
|
723
750
|
def process(self, output) -> list[str]:
|
|
@@ -784,7 +811,9 @@ class SecurityLimits(FactBase):
|
|
|
784
811
|
]
|
|
785
812
|
"""
|
|
786
813
|
|
|
787
|
-
command
|
|
814
|
+
def command(self):
|
|
815
|
+
return "cat /etc/security/limits.conf"
|
|
816
|
+
|
|
788
817
|
default = list
|
|
789
818
|
|
|
790
819
|
def process(self, output):
|
pyinfra/facts/snap.py
CHANGED
|
@@ -7,7 +7,9 @@ from pyinfra.api import FactBase
|
|
|
7
7
|
|
|
8
8
|
class SnapBaseFact(FactBase):
|
|
9
9
|
abstract = True
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
def requires_command(self, *args, **kwargs) -> str:
|
|
12
|
+
return "snap"
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class SnapPackage(SnapBaseFact):
|
|
@@ -64,7 +66,9 @@ class SnapPackages(SnapBaseFact):
|
|
|
64
66
|
"""
|
|
65
67
|
|
|
66
68
|
default = list
|
|
67
|
-
|
|
69
|
+
|
|
70
|
+
def command(self) -> str:
|
|
71
|
+
return "snap list"
|
|
68
72
|
|
|
69
73
|
def process(self, output):
|
|
70
74
|
# Discard header output line from snap list command
|
pyinfra/facts/systemd.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import re
|
|
4
4
|
from typing import Dict, Iterable
|
|
5
5
|
|
|
6
|
-
from pyinfra.api import FactBase,
|
|
6
|
+
from pyinfra.api import FactBase, QuoteString, StringCommand
|
|
7
7
|
|
|
8
8
|
# Valid unit names consist of a "name prefix" and a dot and a suffix specifying the unit type.
|
|
9
9
|
# The "unit prefix" must consist of one or more valid characters
|
|
@@ -52,14 +52,21 @@ class SystemdStatus(FactBase[Dict[str, bool]]):
|
|
|
52
52
|
}
|
|
53
53
|
"""
|
|
54
54
|
|
|
55
|
-
requires_command
|
|
55
|
+
def requires_command(self, *args, **kwargs) -> str:
|
|
56
|
+
return "systemctl"
|
|
56
57
|
|
|
57
58
|
default = dict
|
|
58
59
|
|
|
59
60
|
state_key = "SubState"
|
|
60
61
|
state_values = ["running", "waiting", "exited"]
|
|
61
62
|
|
|
62
|
-
def command(
|
|
63
|
+
def command(
|
|
64
|
+
self,
|
|
65
|
+
user_mode: bool = False,
|
|
66
|
+
machine: str | None = None,
|
|
67
|
+
user_name: str | None = None,
|
|
68
|
+
services: str | list[str] | None = None,
|
|
69
|
+
) -> StringCommand:
|
|
63
70
|
fact_cmd = _make_systemctl_cmd(
|
|
64
71
|
user_mode=user_mode,
|
|
65
72
|
machine=machine,
|
|
@@ -72,8 +79,6 @@ class SystemdStatus(FactBase[Dict[str, bool]]):
|
|
|
72
79
|
service_strs = [QuoteString(services)]
|
|
73
80
|
elif isinstance(services, Iterable):
|
|
74
81
|
service_strs = [QuoteString(s) for s in services]
|
|
75
|
-
else:
|
|
76
|
-
raise FactTypeError(f"Invalid type passed for services argument: {type(services)}")
|
|
77
82
|
|
|
78
83
|
return StringCommand(
|
|
79
84
|
fact_cmd,
|
pyinfra/facts/sysvinit.py
CHANGED
|
@@ -18,7 +18,8 @@ class InitdStatus(FactBase):
|
|
|
18
18
|
http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
-
command
|
|
21
|
+
def command(self) -> str:
|
|
22
|
+
return """
|
|
22
23
|
for SERVICE in `ls /etc/init.d/`; do
|
|
23
24
|
_=`cat /etc/init.d/$SERVICE | grep "### BEGIN INIT INFO"`
|
|
24
25
|
|
pyinfra/facts/upstart.py
CHANGED
|
@@ -10,12 +10,15 @@ class UpstartStatus(FactBase):
|
|
|
10
10
|
Returns a dict of name -> status for upstart managed services.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
def requires_command(self) -> str:
|
|
14
|
+
return "initctl"
|
|
15
15
|
|
|
16
16
|
regex = r"^([a-z\-]+) [a-z]+\/([a-z]+)"
|
|
17
17
|
default = dict
|
|
18
18
|
|
|
19
|
+
def command(self):
|
|
20
|
+
return "initctl list"
|
|
21
|
+
|
|
19
22
|
def process(self, output):
|
|
20
23
|
services = {}
|
|
21
24
|
|