pyinfra 3.0.dev0__py2.py3-none-any.whl → 3.0.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.
Files changed (148) hide show
  1. pyinfra/api/__init__.py +3 -0
  2. pyinfra/api/arguments.py +115 -97
  3. pyinfra/api/arguments_typed.py +80 -0
  4. pyinfra/api/command.py +5 -3
  5. pyinfra/api/config.py +139 -39
  6. pyinfra/api/connectors.py +5 -2
  7. pyinfra/api/deploy.py +19 -19
  8. pyinfra/api/exceptions.py +35 -4
  9. pyinfra/api/facts.py +62 -86
  10. pyinfra/api/host.py +102 -15
  11. pyinfra/api/inventory.py +4 -0
  12. pyinfra/api/operation.py +188 -120
  13. pyinfra/api/operations.py +66 -113
  14. pyinfra/api/state.py +53 -34
  15. pyinfra/api/util.py +64 -33
  16. pyinfra/connectors/base.py +65 -20
  17. pyinfra/connectors/chroot.py +15 -13
  18. pyinfra/connectors/docker.py +62 -72
  19. pyinfra/connectors/dockerssh.py +20 -19
  20. pyinfra/connectors/local.py +32 -22
  21. pyinfra/connectors/ssh.py +162 -86
  22. pyinfra/connectors/sshuserclient/client.py +1 -1
  23. pyinfra/connectors/terraform.py +57 -39
  24. pyinfra/connectors/util.py +26 -27
  25. pyinfra/connectors/vagrant.py +27 -26
  26. pyinfra/context.py +1 -0
  27. pyinfra/facts/apk.py +7 -2
  28. pyinfra/facts/apt.py +15 -7
  29. pyinfra/facts/brew.py +28 -13
  30. pyinfra/facts/bsdinit.py +9 -6
  31. pyinfra/facts/cargo.py +6 -3
  32. pyinfra/facts/choco.py +8 -4
  33. pyinfra/facts/deb.py +21 -9
  34. pyinfra/facts/dnf.py +11 -6
  35. pyinfra/facts/docker.py +30 -5
  36. pyinfra/facts/files.py +49 -33
  37. pyinfra/facts/gem.py +7 -2
  38. pyinfra/facts/git.py +14 -21
  39. pyinfra/facts/gpg.py +4 -1
  40. pyinfra/facts/hardware.py +186 -138
  41. pyinfra/facts/launchd.py +7 -2
  42. pyinfra/facts/lxd.py +8 -2
  43. pyinfra/facts/mysql.py +19 -12
  44. pyinfra/facts/npm.py +3 -1
  45. pyinfra/facts/openrc.py +8 -2
  46. pyinfra/facts/pacman.py +13 -5
  47. pyinfra/facts/pip.py +2 -0
  48. pyinfra/facts/pkg.py +5 -1
  49. pyinfra/facts/pkgin.py +7 -2
  50. pyinfra/facts/postgres.py +170 -0
  51. pyinfra/facts/postgresql.py +5 -162
  52. pyinfra/facts/rpm.py +21 -15
  53. pyinfra/facts/runit.py +70 -0
  54. pyinfra/facts/selinux.py +12 -4
  55. pyinfra/facts/server.py +240 -82
  56. pyinfra/facts/snap.py +8 -2
  57. pyinfra/facts/systemd.py +37 -13
  58. pyinfra/facts/sysvinit.py +7 -4
  59. pyinfra/facts/upstart.py +7 -2
  60. pyinfra/facts/util/packaging.py +3 -2
  61. pyinfra/facts/vzctl.py +8 -4
  62. pyinfra/facts/xbps.py +7 -2
  63. pyinfra/facts/yum.py +10 -5
  64. pyinfra/facts/zypper.py +9 -4
  65. pyinfra/operations/apk.py +5 -3
  66. pyinfra/operations/apt.py +28 -25
  67. pyinfra/operations/brew.py +60 -29
  68. pyinfra/operations/bsdinit.py +6 -4
  69. pyinfra/operations/cargo.py +3 -1
  70. pyinfra/operations/choco.py +3 -1
  71. pyinfra/operations/dnf.py +16 -20
  72. pyinfra/operations/docker.py +339 -0
  73. pyinfra/operations/files.py +187 -168
  74. pyinfra/operations/gem.py +3 -1
  75. pyinfra/operations/git.py +23 -25
  76. pyinfra/operations/iptables.py +33 -25
  77. pyinfra/operations/launchd.py +5 -6
  78. pyinfra/operations/lxd.py +7 -4
  79. pyinfra/operations/mysql.py +59 -55
  80. pyinfra/operations/npm.py +8 -1
  81. pyinfra/operations/openrc.py +5 -3
  82. pyinfra/operations/pacman.py +6 -7
  83. pyinfra/operations/pip.py +19 -12
  84. pyinfra/operations/pkg.py +3 -1
  85. pyinfra/operations/pkgin.py +5 -3
  86. pyinfra/operations/postgres.py +349 -0
  87. pyinfra/operations/postgresql.py +18 -335
  88. pyinfra/operations/puppet.py +3 -1
  89. pyinfra/operations/python.py +8 -19
  90. pyinfra/operations/runit.py +182 -0
  91. pyinfra/operations/selinux.py +47 -29
  92. pyinfra/operations/server.py +138 -67
  93. pyinfra/operations/snap.py +3 -1
  94. pyinfra/operations/ssh.py +18 -16
  95. pyinfra/operations/systemd.py +18 -12
  96. pyinfra/operations/sysvinit.py +7 -5
  97. pyinfra/operations/upstart.py +7 -5
  98. pyinfra/operations/util/__init__.py +12 -0
  99. pyinfra/operations/util/docker.py +177 -0
  100. pyinfra/operations/util/files.py +24 -16
  101. pyinfra/operations/util/packaging.py +54 -38
  102. pyinfra/operations/util/service.py +39 -47
  103. pyinfra/operations/vzctl.py +12 -10
  104. pyinfra/operations/xbps.py +5 -3
  105. pyinfra/operations/yum.py +15 -19
  106. pyinfra/operations/zypper.py +9 -10
  107. pyinfra/version.py +5 -2
  108. {pyinfra-3.0.dev0.dist-info → pyinfra-3.0.2.dist-info}/METADATA +51 -58
  109. pyinfra-3.0.2.dist-info/RECORD +168 -0
  110. {pyinfra-3.0.dev0.dist-info → pyinfra-3.0.2.dist-info}/WHEEL +1 -1
  111. {pyinfra-3.0.dev0.dist-info → pyinfra-3.0.2.dist-info}/entry_points.txt +0 -3
  112. pyinfra_cli/__main__.py +4 -3
  113. pyinfra_cli/commands.py +3 -2
  114. pyinfra_cli/exceptions.py +75 -43
  115. pyinfra_cli/inventory.py +52 -31
  116. pyinfra_cli/log.py +10 -2
  117. pyinfra_cli/main.py +88 -65
  118. pyinfra_cli/prints.py +37 -109
  119. pyinfra_cli/util.py +15 -10
  120. tests/test_api/test_api.py +2 -0
  121. tests/test_api/test_api_arguments.py +9 -9
  122. tests/test_api/test_api_deploys.py +15 -19
  123. tests/test_api/test_api_facts.py +4 -5
  124. tests/test_api/test_api_operations.py +18 -20
  125. tests/test_api/test_api_util.py +41 -2
  126. tests/test_cli/test_cli.py +14 -50
  127. tests/test_cli/test_cli_deploy.py +17 -14
  128. tests/test_cli/test_cli_exceptions.py +50 -19
  129. tests/test_cli/test_cli_inventory.py +66 -0
  130. tests/test_cli/util.py +1 -1
  131. tests/test_connectors/test_dockerssh.py +11 -8
  132. tests/test_connectors/test_ssh.py +88 -23
  133. tests/test_connectors/test_sshuserclient.py +1 -1
  134. tests/test_connectors/test_terraform.py +11 -8
  135. tests/test_connectors/test_vagrant.py +6 -6
  136. pyinfra/connectors/ansible.py +0 -175
  137. pyinfra/connectors/mech.py +0 -189
  138. pyinfra/connectors/pyinfrawinrmsession/__init__.py +0 -28
  139. pyinfra/connectors/winrm.py +0 -312
  140. pyinfra/facts/windows.py +0 -366
  141. pyinfra/facts/windows_files.py +0 -90
  142. pyinfra/operations/windows.py +0 -59
  143. pyinfra/operations/windows_files.py +0 -538
  144. pyinfra-3.0.dev0.dist-info/RECORD +0 -170
  145. tests/test_connectors/test_ansible.py +0 -64
  146. tests/test_connectors/test_mech.py +0 -126
  147. {pyinfra-3.0.dev0.dist-info → pyinfra-3.0.2.dist-info}/LICENSE.md +0 -0
  148. {pyinfra-3.0.dev0.dist-info → pyinfra-3.0.2.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,8 @@
2
2
  Manage ``choco`` (Chocolatey) packages (https://chocolatey.org).
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  from pyinfra import host
6
8
  from pyinfra.api import operation
7
9
  from pyinfra.facts.choco import ChocoPackages
@@ -10,7 +12,7 @@ from .util.packaging import ensure_packages
10
12
 
11
13
 
12
14
  @operation()
13
- def packages(packages=None, present=True, latest=False):
15
+ def packages(packages: str | list[str] | None = None, present=True, latest=False):
14
16
  """
15
17
  Add/remove/update ``choco`` packages.
16
18
 
pyinfra/operations/dnf.py CHANGED
@@ -2,16 +2,17 @@
2
2
  Manage dnf packages and repositories. Note that dnf package names are case-sensitive.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  from pyinfra import host, state
6
8
  from pyinfra.api import operation
7
9
  from pyinfra.facts.rpm import RpmPackageProvides, RpmPackages
8
10
 
9
- from . import files
10
11
  from .util.packaging import ensure_packages, ensure_rpm, ensure_yum_repo
11
12
 
12
13
 
13
14
  @operation(is_idempotent=False)
14
- def key(src):
15
+ def key(src: str):
15
16
  """
16
17
  Add dnf gpg keys with ``rpm``.
17
18
 
@@ -37,19 +38,19 @@ def key(src):
37
38
 
38
39
  @operation()
39
40
  def repo(
40
- src,
41
+ src: str,
41
42
  present=True,
42
- baseurl=None,
43
- description=None,
43
+ baseurl: str | None = None,
44
+ description: str | None = None,
44
45
  enabled=True,
45
46
  gpgcheck=True,
46
- gpgkey=None,
47
+ gpgkey: str | None = None,
47
48
  ):
48
49
  # NOTE: if updating this docstring also update `yum.repo`
49
50
  """
50
51
  Add/remove/update dnf repositories.
51
52
 
52
- + name: URL or name for the ``.repo`` file
53
+ + src: URL or name for the ``.repo`` file
53
54
  + present: whether the ``.repo`` file should be present
54
55
  + baseurl: the baseurl of the repo (if ``name`` is not a URL)
55
56
  + description: optional verbose description
@@ -81,9 +82,7 @@ def repo(
81
82
  """
82
83
 
83
84
  yield from ensure_yum_repo(
84
- state,
85
85
  host,
86
- files,
87
86
  src,
88
87
  baseurl,
89
88
  present,
@@ -95,7 +94,7 @@ def repo(
95
94
 
96
95
 
97
96
  @operation()
98
- def rpm(src, present=True):
97
+ def rpm(src: str, present=True):
99
98
  # NOTE: if updating this docstring also update `yum.rpm`
100
99
  """
101
100
  Add/remove ``.rpm`` file packages.
@@ -118,7 +117,7 @@ def rpm(src, present=True):
118
117
  )
119
118
  """
120
119
 
121
- yield from ensure_rpm(state, host, files, src, present, "dnf")
120
+ yield from ensure_rpm(state, host, src, present, "dnf")
122
121
 
123
122
 
124
123
  @operation(is_idempotent=False)
@@ -130,24 +129,24 @@ def update():
130
129
  yield "dnf update -y"
131
130
 
132
131
 
133
- _update = update # noqa: E305 (for use below where update is a kwarg)
132
+ _update = update._inner # noqa: E305 (for use below where update is a kwarg)
134
133
 
135
134
 
136
135
  @operation()
137
136
  def packages(
138
- packages=None,
137
+ packages: str | list[str] | None = None,
139
138
  present=True,
140
139
  latest=False,
141
140
  update=False,
142
141
  clean=False,
143
142
  nobest=False,
144
- extra_install_args=None,
145
- extra_uninstall_args=None,
143
+ extra_install_args: str | None = None,
144
+ extra_uninstall_args: str | None = None,
146
145
  ):
147
146
  """
148
147
  Install/remove/update dnf packages & updates.
149
148
 
150
- + packages: list of packages to ensure
149
+ + packages: packages to ensure
151
150
  + present: whether the packages should be installed
152
151
  + latest: whether to upgrade packages without a specified version
153
152
  + update: run ``dnf update`` before installing packages
@@ -207,8 +206,5 @@ def packages(
207
206
  upgrade_command="dnf update -y",
208
207
  version_join="=",
209
208
  latest=latest,
210
- expand_package_fact=lambda package: host.get_fact(
211
- RpmPackageProvides,
212
- name=package,
213
- ),
209
+ expand_package_fact=lambda package: host.get_fact(RpmPackageProvides, package=package),
214
210
  )
@@ -0,0 +1,339 @@
1
+ """
2
+ Manager Docker Containers, Volumes and Networks
3
+ """
4
+
5
+ from pyinfra import host
6
+ from pyinfra.api import operation
7
+ from pyinfra.facts.docker import DockerContainers, DockerNetworks, DockerVolumes
8
+
9
+ from .util.docker import handle_docker
10
+
11
+
12
+ @operation()
13
+ def container(
14
+ container,
15
+ image="",
16
+ ports=None,
17
+ networks=None,
18
+ volumes=None,
19
+ env_vars=None,
20
+ pull_always=False,
21
+ present=True,
22
+ force=False,
23
+ start=True,
24
+ ):
25
+ """
26
+ Manage Docker containers
27
+
28
+ + container: name to identify the container
29
+ + image: container image and tag ex: nginx:alpine
30
+ + networks: network list to attach on container
31
+ + ports: port list to expose
32
+ + volumes: volume list to map on container
33
+ + env_vars: environment varible list to inject on container
34
+ + pull_always: force image pull
35
+ + force: remove a contaner with same name and create a new one
36
+ + present: whether the container should be up and running
37
+ + start: start or stop the container
38
+
39
+ **Examples:**
40
+
41
+ .. code:: python
42
+
43
+ # Run a container
44
+ docker.container(
45
+ name="Deploy Nginx container",
46
+ container="nginx",
47
+ image="nginx:alpine",
48
+ ports=["80:80"],
49
+ present=True,
50
+ force=True,
51
+ networks=["proxy", "services"],
52
+ volumes=["nginx_data:/usr/share/nginx/html"],
53
+ pull_always=True,
54
+ )
55
+
56
+ # Stop a container
57
+ docker.container(
58
+ name="Stop Nginx container",
59
+ container="nginx",
60
+ start=False,
61
+ )
62
+
63
+ # Start a container
64
+ docker.container(
65
+ name="Start Nginx container",
66
+ container="nginx",
67
+ start=True,
68
+ )
69
+ """
70
+
71
+ existent_container = [c for c in host.get_fact(DockerContainers) if container in c["Name"]]
72
+
73
+ if force:
74
+ if existent_container:
75
+ yield handle_docker(
76
+ resource="container",
77
+ command="remove",
78
+ container=container,
79
+ )
80
+
81
+ if present:
82
+ if not existent_container or force:
83
+ yield handle_docker(
84
+ resource="container",
85
+ command="create",
86
+ container=container,
87
+ image=image,
88
+ ports=ports,
89
+ networks=networks,
90
+ volumes=volumes,
91
+ env_vars=env_vars,
92
+ pull_always=pull_always,
93
+ present=present,
94
+ force=force,
95
+ start=start,
96
+ )
97
+
98
+ if existent_container and start:
99
+ if existent_container[0]["State"]["Status"] != "running":
100
+ yield handle_docker(
101
+ resource="container",
102
+ command="start",
103
+ container=container,
104
+ )
105
+
106
+ if existent_container and not start:
107
+ if existent_container[0]["State"]["Status"] == "running":
108
+ yield handle_docker(
109
+ resource="container",
110
+ command="stop",
111
+ container=container,
112
+ )
113
+
114
+ if existent_container and not present:
115
+ yield handle_docker(
116
+ resource="container",
117
+ command="remove",
118
+ container=container,
119
+ )
120
+
121
+
122
+ @operation(is_idempotent=False)
123
+ def image(image, present=True):
124
+ """
125
+ Manage Docker images
126
+
127
+ + image: Image and tag ex: nginx:alpine
128
+ + present: whether the Docker image should be exist
129
+
130
+ **Examples:**
131
+
132
+ .. code:: python
133
+
134
+ # Pull a Docker image
135
+ docker.image(
136
+ name="Pull nginx image",
137
+ image="nginx:alpine",
138
+ present=True,
139
+ )
140
+
141
+ # Remove a Docker image
142
+ docker.image(
143
+ name="Remove nginx image",
144
+ image:"nginx:image",
145
+ present=False,
146
+ )
147
+ """
148
+
149
+ if present:
150
+ yield handle_docker(
151
+ resource="image",
152
+ command="pull",
153
+ image=image,
154
+ )
155
+
156
+ else:
157
+ yield handle_docker(
158
+ resource="image",
159
+ command="remove",
160
+ image=image,
161
+ )
162
+
163
+
164
+ @operation()
165
+ def volume(volume, driver="", labels=None, present=True):
166
+ """
167
+ Manage Docker volumes
168
+
169
+ + volume: Volume name
170
+ + driver: Docker volume storage driver
171
+ + labels: Label list to attach in the volume
172
+ + present: whether the Docker volume should exist
173
+
174
+ **Examples:**
175
+
176
+ .. code:: python
177
+
178
+ # Create a Docker volume
179
+ docker.volume(
180
+ name="Create nginx volume",
181
+ volume="nginx_data",
182
+ present=True
183
+ )
184
+ """
185
+
186
+ existent_volume = [v for v in host.get_fact(DockerVolumes) if v["Name"] == volume]
187
+
188
+ if present:
189
+
190
+ if existent_volume:
191
+ host.noop("Volume alredy exist!")
192
+ return
193
+
194
+ yield handle_docker(
195
+ resource="volume",
196
+ command="create",
197
+ volume=volume,
198
+ driver=driver,
199
+ labels=labels,
200
+ present=present,
201
+ )
202
+
203
+ else:
204
+ if existent_volume is None:
205
+ host.noop("There is no {0} volume!".format(volume))
206
+ return
207
+
208
+ yield handle_docker(
209
+ resource="volume",
210
+ command="remove",
211
+ volume=volume,
212
+ )
213
+
214
+
215
+ @operation()
216
+ def network(
217
+ network,
218
+ driver="",
219
+ gateway="",
220
+ ip_range="",
221
+ ipam_driver="",
222
+ subnet="",
223
+ scope="",
224
+ opts=None,
225
+ ipam_opts=None,
226
+ labels=None,
227
+ ingress=False,
228
+ attachable=False,
229
+ present=True,
230
+ ):
231
+ """
232
+ Manage docker networks
233
+
234
+ + network_name: Image name
235
+ + driver: Container image and tag ex: nginx:alpine
236
+ + gateway: IPv4 or IPv6 Gateway for the master subnet
237
+ + ip_range: Allocate container ip from a sub-range
238
+ + ipam_driver: IP Address Management Driver
239
+ + subnet: Subnet in CIDR format that represents a network segment
240
+ + scope: Control the network's scope
241
+ + opts: Set driver specific options
242
+ + ipam_opts: Set IPAM driver specific options
243
+ + labels: Label list to attach in the network
244
+ + ingress: Create swarm routing-mesh network
245
+ + attachable: Enable manual container attachment
246
+ + present: whether the Docker network should exist
247
+
248
+ **Examples:**
249
+
250
+ .. code:: python
251
+
252
+ # Create Docker network
253
+ docker.network(
254
+ name="Create nginx network",
255
+ network_name="nginx",
256
+ attachable=True,
257
+ present=True,
258
+ )
259
+ """
260
+ existent_network = [n for n in host.get_fact(DockerNetworks) if n["Name"] == network]
261
+
262
+ if present:
263
+ if existent_network:
264
+ host.noop("Alredy exist a network with {0} name!".format(network))
265
+ return
266
+
267
+ yield handle_docker(
268
+ resource="network",
269
+ command="create",
270
+ network=network,
271
+ driver=driver,
272
+ gateway=gateway,
273
+ ip_range=ip_range,
274
+ ipam_driver=ipam_driver,
275
+ subnet=subnet,
276
+ scope=scope,
277
+ opts=opts,
278
+ ipam_opts=ipam_opts,
279
+ labels=labels,
280
+ ingress=ingress,
281
+ attachable=attachable,
282
+ present=present,
283
+ )
284
+
285
+ else:
286
+ if existent_network is None:
287
+ host.noop("Ther is not network with {0} name!".format(network))
288
+ return
289
+
290
+ yield handle_docker(
291
+ resource="network",
292
+ command="create",
293
+ network=network,
294
+ )
295
+
296
+
297
+ @operation(is_idempotent=False)
298
+ def prune(
299
+ all=False,
300
+ volume=False,
301
+ filter="",
302
+ ):
303
+ """
304
+ Execute a docker system prune.
305
+
306
+ + all: Remove all unused images not just dangling ones
307
+ + volumes: Prune anonymous volumes
308
+ + filter: Provide filter values (e.g. "label=<key>=<value>" or "until=24h")
309
+
310
+ **Examples:**
311
+
312
+ .. code:: python
313
+
314
+ # Remove dangling images
315
+ docker.prune(
316
+ name="remove dangling images",
317
+ )
318
+
319
+ # Remove all images and volumes
320
+ docker.prune(
321
+ name="Remove all images and volumes",
322
+ all=True,
323
+ volumes=True,
324
+ )
325
+
326
+ # Remove images older than 90 days
327
+ docker.prune(
328
+ name="Remove unused older than 90 days",
329
+ filter="until=2160h"
330
+ )
331
+ """
332
+
333
+ yield handle_docker(
334
+ resource="system",
335
+ command="prune",
336
+ all=all,
337
+ volume=volume,
338
+ filter=filter,
339
+ )