pyinfra 2.9.1__py2.py3-none-any.whl → 3.0__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/__init__.py +3 -0
- pyinfra/api/arguments.py +265 -253
- pyinfra/api/arguments_typed.py +80 -0
- pyinfra/api/command.py +68 -53
- pyinfra/api/config.py +139 -32
- pyinfra/api/connect.py +1 -1
- pyinfra/api/connectors.py +7 -26
- pyinfra/api/deploy.py +21 -52
- pyinfra/api/exceptions.py +33 -8
- pyinfra/api/facts.py +102 -137
- pyinfra/api/host.py +150 -82
- pyinfra/api/inventory.py +21 -25
- pyinfra/api/operation.py +240 -198
- pyinfra/api/operations.py +102 -148
- pyinfra/api/state.py +137 -79
- pyinfra/api/util.py +79 -86
- pyinfra/connectors/base.py +147 -0
- pyinfra/connectors/chroot.py +160 -169
- pyinfra/connectors/docker.py +220 -237
- pyinfra/connectors/dockerssh.py +231 -253
- pyinfra/connectors/local.py +196 -208
- pyinfra/connectors/ssh.py +530 -613
- pyinfra/connectors/ssh_util.py +114 -0
- pyinfra/connectors/sshuserclient/client.py +5 -3
- pyinfra/connectors/terraform.py +86 -65
- pyinfra/connectors/util.py +211 -137
- pyinfra/connectors/vagrant.py +60 -53
- pyinfra/context.py +4 -2
- pyinfra/facts/apk.py +2 -0
- pyinfra/facts/apt.py +2 -0
- pyinfra/facts/brew.py +2 -0
- pyinfra/facts/bsdinit.py +2 -0
- pyinfra/facts/cargo.py +2 -0
- pyinfra/facts/choco.py +2 -0
- pyinfra/facts/deb.py +7 -2
- pyinfra/facts/dnf.py +2 -0
- pyinfra/facts/docker.py +19 -0
- pyinfra/facts/files.py +47 -32
- pyinfra/facts/gem.py +2 -0
- pyinfra/facts/git.py +3 -1
- pyinfra/facts/gpg.py +3 -1
- pyinfra/facts/hardware.py +34 -24
- pyinfra/facts/iptables.py +5 -3
- pyinfra/facts/launchd.py +2 -0
- pyinfra/facts/lxd.py +2 -0
- pyinfra/facts/mysql.py +13 -6
- pyinfra/facts/npm.py +1 -0
- pyinfra/facts/openrc.py +2 -0
- pyinfra/facts/pacman.py +6 -2
- pyinfra/facts/pip.py +2 -0
- pyinfra/facts/pkg.py +2 -0
- pyinfra/facts/pkgin.py +2 -0
- pyinfra/facts/postgres.py +168 -0
- pyinfra/facts/postgresql.py +6 -160
- pyinfra/facts/rpm.py +12 -9
- pyinfra/facts/runit.py +68 -0
- pyinfra/facts/selinux.py +3 -1
- pyinfra/facts/server.py +80 -36
- pyinfra/facts/snap.py +2 -0
- pyinfra/facts/systemd.py +31 -12
- pyinfra/facts/sysvinit.py +10 -10
- pyinfra/facts/upstart.py +2 -0
- pyinfra/facts/util/packaging.py +7 -4
- pyinfra/facts/vzctl.py +2 -0
- pyinfra/facts/xbps.py +2 -0
- pyinfra/facts/yum.py +2 -0
- pyinfra/facts/zypper.py +2 -0
- pyinfra/local.py +4 -5
- pyinfra/operations/apk.py +6 -4
- pyinfra/operations/apt.py +46 -65
- pyinfra/operations/brew.py +17 -22
- pyinfra/operations/bsdinit.py +9 -7
- pyinfra/operations/cargo.py +4 -2
- pyinfra/operations/choco.py +4 -2
- pyinfra/operations/dnf.py +19 -23
- pyinfra/operations/docker.py +339 -0
- pyinfra/operations/files.py +188 -386
- pyinfra/operations/gem.py +4 -2
- pyinfra/operations/git.py +24 -53
- pyinfra/operations/iptables.py +29 -35
- pyinfra/operations/launchd.py +6 -7
- pyinfra/operations/lxd.py +8 -13
- pyinfra/operations/mysql.py +62 -81
- pyinfra/operations/npm.py +9 -2
- pyinfra/operations/openrc.py +6 -4
- pyinfra/operations/pacman.py +7 -8
- pyinfra/operations/pip.py +25 -24
- pyinfra/operations/pkg.py +4 -2
- pyinfra/operations/pkgin.py +6 -4
- pyinfra/operations/postgres.py +349 -0
- pyinfra/operations/postgresql.py +18 -379
- pyinfra/operations/puppet.py +3 -1
- pyinfra/operations/python.py +8 -19
- pyinfra/operations/runit.py +182 -0
- pyinfra/operations/selinux.py +47 -44
- pyinfra/operations/server.py +111 -127
- pyinfra/operations/snap.py +4 -4
- pyinfra/operations/ssh.py +20 -33
- pyinfra/operations/systemd.py +19 -15
- pyinfra/operations/sysvinit.py +9 -16
- pyinfra/operations/upstart.py +9 -7
- pyinfra/operations/util/__init__.py +12 -0
- pyinfra/operations/util/docker.py +177 -0
- pyinfra/operations/util/files.py +24 -16
- pyinfra/operations/util/packaging.py +55 -57
- pyinfra/operations/util/service.py +39 -51
- pyinfra/operations/vzctl.py +12 -10
- pyinfra/operations/xbps.py +6 -4
- pyinfra/operations/yum.py +18 -22
- pyinfra/operations/zypper.py +12 -13
- pyinfra/version.py +5 -2
- {pyinfra-2.9.1.dist-info → pyinfra-3.0.dist-info}/METADATA +40 -41
- pyinfra-3.0.dist-info/RECORD +167 -0
- {pyinfra-2.9.1.dist-info → pyinfra-3.0.dist-info}/WHEEL +1 -1
- pyinfra-3.0.dist-info/entry_points.txt +11 -0
- pyinfra_cli/__main__.py +4 -3
- pyinfra_cli/commands.py +7 -2
- pyinfra_cli/exceptions.py +78 -42
- pyinfra_cli/inventory.py +40 -6
- pyinfra_cli/log.py +17 -3
- pyinfra_cli/main.py +133 -90
- pyinfra_cli/prints.py +95 -127
- pyinfra_cli/util.py +62 -29
- tests/test_api/test_api.py +2 -0
- tests/test_api/test_api_arguments.py +13 -13
- tests/test_api/test_api_deploys.py +28 -29
- tests/test_api/test_api_facts.py +60 -98
- tests/test_api/test_api_operations.py +101 -201
- tests/test_cli/test_cli.py +18 -49
- tests/test_cli/test_cli_deploy.py +11 -37
- tests/test_cli/test_cli_exceptions.py +50 -19
- tests/test_cli/util.py +1 -1
- tests/test_connectors/test_chroot.py +6 -6
- tests/test_connectors/test_docker.py +4 -4
- tests/test_connectors/test_dockerssh.py +38 -50
- tests/test_connectors/test_local.py +11 -12
- tests/test_connectors/test_ssh.py +105 -93
- tests/test_connectors/test_terraform.py +9 -15
- tests/test_connectors/test_util.py +24 -46
- tests/test_connectors/test_vagrant.py +7 -7
- pyinfra/api/operation.pyi +0 -117
- pyinfra/connectors/ansible.py +0 -171
- pyinfra/connectors/mech.py +0 -186
- pyinfra/connectors/pyinfrawinrmsession/__init__.py +0 -28
- pyinfra/connectors/winrm.py +0 -320
- pyinfra/facts/windows.py +0 -366
- pyinfra/facts/windows_files.py +0 -90
- pyinfra/operations/windows.py +0 -59
- pyinfra/operations/windows_files.py +0 -551
- pyinfra-2.9.1.dist-info/RECORD +0 -170
- pyinfra-2.9.1.dist-info/entry_points.txt +0 -14
- tests/test_connectors/test_ansible.py +0 -64
- tests/test_connectors/test_mech.py +0 -126
- tests/test_connectors/test_winrm.py +0 -76
- {pyinfra-2.9.1.dist-info → pyinfra-3.0.dist-info}/LICENSE.md +0 -0
- {pyinfra-2.9.1.dist-info → pyinfra-3.0.dist-info}/top_level.txt +0 -0
pyinfra/api/exceptions.py
CHANGED
|
@@ -4,15 +4,28 @@ class PyinfraError(Exception):
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
class
|
|
7
|
+
class ConnectError(PyinfraError):
|
|
8
8
|
"""
|
|
9
|
-
Exception raised when
|
|
9
|
+
Exception raised when connecting fails.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class FactError(PyinfraError):
|
|
14
14
|
"""
|
|
15
|
-
Exception raised
|
|
15
|
+
Exception raised during fact gathering staging if a fact is unable to
|
|
16
|
+
generate output/change state.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class FactTypeError(FactError, TypeError):
|
|
21
|
+
"""
|
|
22
|
+
Exception raised when a fact is passed invalid argument types.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class FactValueError(FactError, ValueError):
|
|
27
|
+
"""
|
|
28
|
+
Exception raised when a fact is passed invalid argument values.
|
|
16
29
|
"""
|
|
17
30
|
|
|
18
31
|
|
|
@@ -47,19 +60,31 @@ class InventoryError(PyinfraError):
|
|
|
47
60
|
"""
|
|
48
61
|
|
|
49
62
|
|
|
50
|
-
class NoConnectorError(PyinfraError,
|
|
63
|
+
class NoConnectorError(PyinfraError, ValueError):
|
|
51
64
|
"""
|
|
52
65
|
Raised when a requested connector is missing.
|
|
53
66
|
"""
|
|
54
67
|
|
|
55
68
|
|
|
56
|
-
class NoHostError(PyinfraError,
|
|
69
|
+
class NoHostError(PyinfraError, KeyError):
|
|
57
70
|
"""
|
|
58
71
|
Raised when an inventory is missing a host.
|
|
59
72
|
"""
|
|
60
73
|
|
|
61
74
|
|
|
62
|
-
class NoGroupError(PyinfraError,
|
|
75
|
+
class NoGroupError(PyinfraError, KeyError):
|
|
76
|
+
"""
|
|
77
|
+
Raised when an inventory is missing a group.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class ConnectorDataTypeError(PyinfraError, TypeError):
|
|
82
|
+
"""
|
|
83
|
+
Raised when host connector data has invalid types.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ArgumentTypeError(PyinfraError, TypeError):
|
|
63
88
|
"""
|
|
64
|
-
|
|
89
|
+
Raised when global arguments are passed with invalid types.
|
|
65
90
|
"""
|
pyinfra/api/facts.py
CHANGED
|
@@ -8,10 +8,24 @@ it's possible to call facts on hosts out of context (ie give me the IP of this
|
|
|
8
8
|
other host B while I operate on this host A).
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import inspect
|
|
11
14
|
import re
|
|
12
15
|
from inspect import getcallargs
|
|
13
16
|
from socket import error as socket_error, timeout as timeout_error
|
|
14
|
-
from typing import
|
|
17
|
+
from typing import (
|
|
18
|
+
TYPE_CHECKING,
|
|
19
|
+
Any,
|
|
20
|
+
Callable,
|
|
21
|
+
Generic,
|
|
22
|
+
Iterable,
|
|
23
|
+
Optional,
|
|
24
|
+
Type,
|
|
25
|
+
TypeVar,
|
|
26
|
+
Union,
|
|
27
|
+
cast,
|
|
28
|
+
)
|
|
15
29
|
|
|
16
30
|
import click
|
|
17
31
|
import gevent
|
|
@@ -19,7 +33,7 @@ from paramiko import SSHException
|
|
|
19
33
|
|
|
20
34
|
from pyinfra import logger
|
|
21
35
|
from pyinfra.api import StringCommand
|
|
22
|
-
from pyinfra.api.arguments import pop_global_arguments
|
|
36
|
+
from pyinfra.api.arguments import all_global_arguments, pop_global_arguments
|
|
23
37
|
from pyinfra.api.util import (
|
|
24
38
|
get_kwargs_str,
|
|
25
39
|
log_error_or_warning,
|
|
@@ -27,11 +41,11 @@ from pyinfra.api.util import (
|
|
|
27
41
|
make_hash,
|
|
28
42
|
print_host_combined_output,
|
|
29
43
|
)
|
|
30
|
-
from pyinfra.connectors.util import
|
|
44
|
+
from pyinfra.connectors.util import CommandOutput
|
|
31
45
|
from pyinfra.context import ctx_host, ctx_state
|
|
32
46
|
from pyinfra.progress import progress_spinner
|
|
33
47
|
|
|
34
|
-
from .arguments import
|
|
48
|
+
from .arguments import CONNECTOR_ARGUMENT_KEYS
|
|
35
49
|
|
|
36
50
|
if TYPE_CHECKING:
|
|
37
51
|
from pyinfra.api.host import Host
|
|
@@ -44,14 +58,10 @@ SU_REGEXES = (
|
|
|
44
58
|
)
|
|
45
59
|
|
|
46
60
|
|
|
47
|
-
|
|
48
|
-
def __init__(cls, name: str, bases, attrs, **kwargs):
|
|
49
|
-
super().__init__(name, bases, attrs, **kwargs)
|
|
50
|
-
module_name = cls.__module__.replace("pyinfra.facts.", "")
|
|
51
|
-
cls.name = f"{module_name}.{cls.__name__}"
|
|
61
|
+
T = TypeVar("T")
|
|
52
62
|
|
|
53
63
|
|
|
54
|
-
class FactBase(
|
|
64
|
+
class FactBase(Generic[T]):
|
|
55
65
|
name: str
|
|
56
66
|
|
|
57
67
|
abstract: bool = True
|
|
@@ -62,23 +72,47 @@ class FactBase(metaclass=FactNameMeta):
|
|
|
62
72
|
|
|
63
73
|
command: Union[str, Callable]
|
|
64
74
|
|
|
75
|
+
def __init_subclass__(cls) -> None:
|
|
76
|
+
super().__init_subclass__()
|
|
77
|
+
module_name = cls.__module__.replace("pyinfra.facts.", "")
|
|
78
|
+
cls.name = f"{module_name}.{cls.__name__}"
|
|
79
|
+
|
|
80
|
+
# Check that fact's `command` method does not inadvertently take a global
|
|
81
|
+
# argument, most commonly `name`.
|
|
82
|
+
if hasattr(cls, "command") and callable(cls.command):
|
|
83
|
+
command_args = set(inspect.signature(cls.command).parameters.keys())
|
|
84
|
+
global_args = set([name for name, _ in all_global_arguments()])
|
|
85
|
+
command_global_args = command_args & global_args
|
|
86
|
+
|
|
87
|
+
if len(command_global_args) > 0:
|
|
88
|
+
names = ", ".join(command_global_args)
|
|
89
|
+
raise TypeError(f"{cls.name}'s arguments {names} are reserved for global arguments")
|
|
90
|
+
|
|
65
91
|
@staticmethod
|
|
66
|
-
def default():
|
|
92
|
+
def default() -> T:
|
|
67
93
|
"""
|
|
68
94
|
Set the default attribute to be a type (eg list/dict).
|
|
69
95
|
"""
|
|
70
96
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
97
|
+
return cast(T, None)
|
|
98
|
+
|
|
99
|
+
def process(self, output: Iterable[str]) -> T:
|
|
100
|
+
# NOTE: TypeVar does not support a default, so we have to cast this str -> T
|
|
101
|
+
return cast(T, "\n".join(output))
|
|
74
102
|
|
|
75
103
|
def process_pipeline(self, args, output):
|
|
76
104
|
return {arg: self.process([output[i]]) for i, arg in enumerate(args)}
|
|
77
105
|
|
|
78
106
|
|
|
79
|
-
class ShortFactBase(
|
|
107
|
+
class ShortFactBase(Generic[T]):
|
|
108
|
+
name: str
|
|
80
109
|
fact: Type[FactBase]
|
|
81
110
|
|
|
111
|
+
def __init_subclass__(cls) -> None:
|
|
112
|
+
super().__init_subclass__()
|
|
113
|
+
module_name = cls.__module__.replace("pyinfra.facts.", "")
|
|
114
|
+
cls.name = f"{module_name}.{cls.__name__}"
|
|
115
|
+
|
|
82
116
|
@staticmethod
|
|
83
117
|
def process_data(data):
|
|
84
118
|
return data
|
|
@@ -99,8 +133,8 @@ def _make_command(command_attribute, host_args):
|
|
|
99
133
|
def _get_executor_kwargs(
|
|
100
134
|
state: "State",
|
|
101
135
|
host: "Host",
|
|
102
|
-
override_kwargs: Optional[
|
|
103
|
-
override_kwarg_keys: Optional[
|
|
136
|
+
override_kwargs: Optional[dict[str, Any]] = None,
|
|
137
|
+
override_kwarg_keys: Optional[list[str]] = None,
|
|
104
138
|
):
|
|
105
139
|
if override_kwargs is None:
|
|
106
140
|
override_kwargs = {}
|
|
@@ -108,7 +142,7 @@ def _get_executor_kwargs(
|
|
|
108
142
|
override_kwarg_keys = []
|
|
109
143
|
|
|
110
144
|
# Use the current operation global kwargs, or generate defaults
|
|
111
|
-
global_kwargs = host.
|
|
145
|
+
global_kwargs = host.current_op_global_arguments
|
|
112
146
|
if not global_kwargs:
|
|
113
147
|
global_kwargs, _ = pop_global_arguments({}, state, host)
|
|
114
148
|
|
|
@@ -117,43 +151,32 @@ def _get_executor_kwargs(
|
|
|
117
151
|
{key: value for key, value in global_kwargs.items() if key not in override_kwarg_keys},
|
|
118
152
|
)
|
|
119
153
|
|
|
120
|
-
return {
|
|
121
|
-
key: value for key, value in override_kwargs.items() if key in get_executor_kwarg_keys()
|
|
122
|
-
}
|
|
154
|
+
return {key: value for key, value in override_kwargs.items() if key in CONNECTOR_ARGUMENT_KEYS}
|
|
123
155
|
|
|
124
156
|
|
|
125
157
|
def _handle_fact_kwargs(state, host, cls, args, kwargs):
|
|
126
158
|
args = args or []
|
|
127
159
|
kwargs = kwargs or {}
|
|
128
160
|
|
|
129
|
-
#
|
|
130
|
-
|
|
131
|
-
|
|
161
|
+
# Start with a (shallow) copy of current operation kwargs if any
|
|
162
|
+
ctx_kwargs = (host.current_op_global_arguments or {}).copy()
|
|
163
|
+
# Update with the input kwargs (overrides)
|
|
164
|
+
ctx_kwargs.update(kwargs)
|
|
132
165
|
|
|
133
|
-
#
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
kwargs,
|
|
166
|
+
# Pop executor kwargs, pass remaining
|
|
167
|
+
global_kwargs, _ = pop_global_arguments(
|
|
168
|
+
ctx_kwargs,
|
|
137
169
|
state=state,
|
|
138
170
|
host=host,
|
|
139
|
-
keys_to_check=get_executor_kwarg_keys(),
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
executor_kwargs = _get_executor_kwargs(
|
|
143
|
-
state,
|
|
144
|
-
host,
|
|
145
|
-
override_kwargs=override_kwargs,
|
|
146
|
-
override_kwarg_keys=override_kwarg_keys,
|
|
147
171
|
)
|
|
148
172
|
|
|
149
|
-
fact_kwargs = {}
|
|
173
|
+
fact_kwargs = {key: value for key, value in kwargs.items() if key not in global_kwargs}
|
|
150
174
|
|
|
151
|
-
if args or
|
|
152
|
-
assert not isinstance(cls.command, str)
|
|
175
|
+
if args or fact_kwargs:
|
|
153
176
|
# Merges args & kwargs into a single kwargs dictionary
|
|
154
|
-
fact_kwargs = getcallargs(cls().command, *args, **
|
|
177
|
+
fact_kwargs = getcallargs(cls().command, *args, **fact_kwargs)
|
|
155
178
|
|
|
156
|
-
return fact_kwargs,
|
|
179
|
+
return fact_kwargs, global_kwargs
|
|
157
180
|
|
|
158
181
|
|
|
159
182
|
def get_facts(state: "State", *args, **kwargs):
|
|
@@ -181,14 +204,12 @@ def get_facts(state: "State", *args, **kwargs):
|
|
|
181
204
|
def get_fact(
|
|
182
205
|
state: "State",
|
|
183
206
|
host: "Host",
|
|
184
|
-
cls:
|
|
207
|
+
cls: type[FactBase],
|
|
185
208
|
args: Optional[Any] = None,
|
|
186
209
|
kwargs: Optional[Any] = None,
|
|
187
210
|
ensure_hosts: Optional[Any] = None,
|
|
188
211
|
apply_failed_hosts: bool = True,
|
|
189
|
-
|
|
190
|
-
use_cache: bool = True,
|
|
191
|
-
):
|
|
212
|
+
) -> Any:
|
|
192
213
|
if issubclass(cls, ShortFactBase):
|
|
193
214
|
return get_short_facts(
|
|
194
215
|
state,
|
|
@@ -198,40 +219,32 @@ def get_fact(
|
|
|
198
219
|
kwargs=kwargs,
|
|
199
220
|
ensure_hosts=ensure_hosts,
|
|
200
221
|
apply_failed_hosts=apply_failed_hosts,
|
|
201
|
-
fact_hash=fact_hash,
|
|
202
|
-
use_cache=use_cache,
|
|
203
222
|
)
|
|
204
223
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
kwargs,
|
|
215
|
-
ensure_hosts,
|
|
216
|
-
apply_failed_hosts,
|
|
217
|
-
fact_hash,
|
|
218
|
-
)
|
|
224
|
+
return _get_fact(
|
|
225
|
+
state,
|
|
226
|
+
host,
|
|
227
|
+
cls,
|
|
228
|
+
args,
|
|
229
|
+
kwargs,
|
|
230
|
+
ensure_hosts,
|
|
231
|
+
apply_failed_hosts,
|
|
232
|
+
)
|
|
219
233
|
|
|
220
234
|
|
|
221
235
|
def _get_fact(
|
|
222
236
|
state: "State",
|
|
223
237
|
host: "Host",
|
|
224
|
-
cls:
|
|
225
|
-
args: Optional[
|
|
226
|
-
kwargs: Optional[
|
|
238
|
+
cls: type[FactBase],
|
|
239
|
+
args: Optional[list] = None,
|
|
240
|
+
kwargs: Optional[dict] = None,
|
|
227
241
|
ensure_hosts: Optional[Any] = None,
|
|
228
242
|
apply_failed_hosts: bool = True,
|
|
229
|
-
|
|
230
|
-
):
|
|
243
|
+
) -> Any:
|
|
231
244
|
fact = cls()
|
|
232
245
|
name = fact.name
|
|
233
246
|
|
|
234
|
-
fact_kwargs,
|
|
247
|
+
fact_kwargs, global_kwargs = _handle_fact_kwargs(state, host, cls, args, kwargs)
|
|
235
248
|
|
|
236
249
|
kwargs_str = get_kwargs_str(fact_kwargs)
|
|
237
250
|
logger.debug(
|
|
@@ -247,14 +260,9 @@ def _get_fact(
|
|
|
247
260
|
raise_exceptions=True,
|
|
248
261
|
)
|
|
249
262
|
|
|
250
|
-
ignore_errors = (host.current_op_global_kwargs or {}).get(
|
|
251
|
-
"ignore_errors",
|
|
252
|
-
state.config.IGNORE_ERRORS,
|
|
253
|
-
)
|
|
254
|
-
|
|
255
263
|
# Facts can override the shell (winrm powershell vs cmd support)
|
|
256
264
|
if fact.shell_executable:
|
|
257
|
-
|
|
265
|
+
global_kwargs["_shell_executable"] = fact.shell_executable
|
|
258
266
|
|
|
259
267
|
command = _make_command(fact.command, fact_kwargs)
|
|
260
268
|
requires_command = _make_command(fact.requires_command, fact_kwargs)
|
|
@@ -271,40 +279,42 @@ def _get_fact(
|
|
|
271
279
|
)
|
|
272
280
|
|
|
273
281
|
status = False
|
|
274
|
-
|
|
275
|
-
|
|
282
|
+
output = CommandOutput([])
|
|
283
|
+
|
|
284
|
+
executor_kwargs = {
|
|
285
|
+
key: value for key, value in global_kwargs.items() if key in CONNECTOR_ARGUMENT_KEYS
|
|
286
|
+
}
|
|
276
287
|
|
|
277
288
|
try:
|
|
278
|
-
status,
|
|
289
|
+
status, output = host.run_shell_command(
|
|
279
290
|
command,
|
|
280
291
|
print_output=state.print_fact_output,
|
|
281
292
|
print_input=state.print_fact_input,
|
|
282
|
-
return_combined_output=True,
|
|
283
293
|
**executor_kwargs,
|
|
284
294
|
)
|
|
285
295
|
except (timeout_error, socket_error, SSHException) as e:
|
|
286
296
|
log_host_command_error(
|
|
287
297
|
host,
|
|
288
298
|
e,
|
|
289
|
-
timeout=
|
|
299
|
+
timeout=global_kwargs["_timeout"],
|
|
290
300
|
)
|
|
291
301
|
|
|
292
|
-
|
|
302
|
+
stdout_lines, stderr_lines = output.stdout_lines, output.stderr_lines
|
|
293
303
|
|
|
294
304
|
data = fact.default()
|
|
295
305
|
|
|
296
306
|
if status:
|
|
297
|
-
if
|
|
298
|
-
data = fact.process(
|
|
299
|
-
elif
|
|
307
|
+
if stdout_lines:
|
|
308
|
+
data = fact.process(stdout_lines)
|
|
309
|
+
elif stderr_lines:
|
|
300
310
|
# If we have error output and that error is sudo or su stating the user
|
|
301
311
|
# does not exist, do not fail but instead return the default fact value.
|
|
302
312
|
# This allows for users that don't currently but may be created during
|
|
303
313
|
# other operations.
|
|
304
|
-
first_line =
|
|
305
|
-
if executor_kwargs["
|
|
314
|
+
first_line = stderr_lines[0]
|
|
315
|
+
if executor_kwargs["_sudo_user"] and re.match(SUDO_REGEX, first_line):
|
|
306
316
|
status = True
|
|
307
|
-
if executor_kwargs["
|
|
317
|
+
if executor_kwargs["_su_user"] and any(re.match(regex, first_line) for regex in SU_REGEXES):
|
|
308
318
|
status = True
|
|
309
319
|
|
|
310
320
|
if status:
|
|
@@ -321,20 +331,18 @@ def _get_fact(
|
|
|
321
331
|
logger.debug(log_message)
|
|
322
332
|
else:
|
|
323
333
|
if not state.print_fact_output:
|
|
324
|
-
print_host_combined_output(host,
|
|
334
|
+
print_host_combined_output(host, output)
|
|
325
335
|
|
|
326
336
|
log_error_or_warning(
|
|
327
337
|
host,
|
|
328
|
-
|
|
338
|
+
global_kwargs["_ignore_errors"],
|
|
329
339
|
description=("could not load fact: {0} {1}").format(name, get_kwargs_str(fact_kwargs)),
|
|
330
340
|
)
|
|
331
341
|
|
|
332
342
|
# Check we've not failed
|
|
333
|
-
if not status and not
|
|
343
|
+
if apply_failed_hosts and not status and not global_kwargs["_ignore_errors"]:
|
|
334
344
|
state.fail_hosts({host})
|
|
335
345
|
|
|
336
|
-
if fact_hash:
|
|
337
|
-
host.facts[fact_hash] = data
|
|
338
346
|
return data
|
|
339
347
|
|
|
340
348
|
|
|
@@ -349,50 +357,7 @@ def get_host_fact(
|
|
|
349
357
|
state: "State",
|
|
350
358
|
host: "Host",
|
|
351
359
|
cls,
|
|
352
|
-
args: Optional[
|
|
353
|
-
kwargs: Optional[
|
|
354
|
-
):
|
|
355
|
-
|
|
356
|
-
return get_fact(state, host, cls, args=args, kwargs=kwargs, fact_hash=fact_hash)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
def reload_host_fact(
|
|
360
|
-
state: "State",
|
|
361
|
-
host: "Host",
|
|
362
|
-
cls,
|
|
363
|
-
args: Optional[List] = None,
|
|
364
|
-
kwargs: Optional[Dict] = None,
|
|
365
|
-
):
|
|
366
|
-
fact_hash = _get_fact_hash(state, host, cls, args, kwargs)
|
|
367
|
-
return get_fact(
|
|
368
|
-
state,
|
|
369
|
-
host,
|
|
370
|
-
cls,
|
|
371
|
-
args=args,
|
|
372
|
-
kwargs=kwargs,
|
|
373
|
-
fact_hash=fact_hash,
|
|
374
|
-
use_cache=False,
|
|
375
|
-
)
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
def create_host_fact(
|
|
379
|
-
state: "State",
|
|
380
|
-
host: "Host",
|
|
381
|
-
cls,
|
|
382
|
-
data,
|
|
383
|
-
args: Optional[List] = None,
|
|
384
|
-
kwargs: Optional[Dict] = None,
|
|
385
|
-
):
|
|
386
|
-
fact_hash = _get_fact_hash(state, host, cls, args, kwargs)
|
|
387
|
-
host.facts[fact_hash] = data
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
def delete_host_fact(
|
|
391
|
-
state: "State",
|
|
392
|
-
host: "Host",
|
|
393
|
-
cls,
|
|
394
|
-
args: Optional[List] = None,
|
|
395
|
-
kwargs: Optional[Dict] = None,
|
|
396
|
-
):
|
|
397
|
-
fact_hash = _get_fact_hash(state, host, cls, args, kwargs)
|
|
398
|
-
host.facts.pop(fact_hash, None)
|
|
360
|
+
args: Optional[Iterable] = None,
|
|
361
|
+
kwargs: Optional[dict] = None,
|
|
362
|
+
) -> Any:
|
|
363
|
+
return get_fact(state, host, cls, args=args, kwargs=kwargs)
|