pyinfra 2.9.2__py2.py3-none-any.whl → 3.0b1__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 +261 -255
- pyinfra/api/arguments_typed.py +77 -0
- pyinfra/api/command.py +66 -53
- pyinfra/api/config.py +27 -22
- pyinfra/api/connect.py +1 -1
- pyinfra/api/connectors.py +2 -24
- pyinfra/api/deploy.py +21 -52
- pyinfra/api/exceptions.py +33 -8
- pyinfra/api/facts.py +77 -113
- pyinfra/api/host.py +150 -82
- pyinfra/api/inventory.py +17 -25
- pyinfra/api/operation.py +232 -198
- pyinfra/api/operations.py +102 -148
- pyinfra/api/state.py +137 -79
- pyinfra/api/util.py +55 -70
- pyinfra/connectors/base.py +150 -0
- pyinfra/connectors/chroot.py +160 -169
- pyinfra/connectors/docker.py +227 -237
- pyinfra/connectors/dockerssh.py +231 -253
- pyinfra/connectors/local.py +195 -207
- pyinfra/connectors/ssh.py +528 -615
- pyinfra/connectors/ssh_util.py +114 -0
- pyinfra/connectors/sshuserclient/client.py +5 -3
- pyinfra/connectors/terraform.py +86 -65
- pyinfra/connectors/util.py +212 -137
- pyinfra/connectors/vagrant.py +55 -48
- pyinfra/context.py +3 -2
- pyinfra/facts/docker.py +1 -0
- pyinfra/facts/files.py +45 -32
- pyinfra/facts/git.py +3 -1
- pyinfra/facts/gpg.py +1 -1
- pyinfra/facts/hardware.py +4 -2
- pyinfra/facts/iptables.py +5 -3
- pyinfra/facts/mysql.py +1 -0
- pyinfra/facts/postgres.py +168 -0
- pyinfra/facts/postgresql.py +5 -161
- pyinfra/facts/selinux.py +3 -1
- pyinfra/facts/server.py +77 -30
- pyinfra/facts/systemd.py +29 -12
- pyinfra/facts/sysvinit.py +10 -10
- pyinfra/facts/util/packaging.py +4 -2
- pyinfra/local.py +4 -5
- pyinfra/operations/apk.py +3 -3
- pyinfra/operations/apt.py +25 -47
- pyinfra/operations/brew.py +7 -14
- pyinfra/operations/bsdinit.py +4 -4
- pyinfra/operations/cargo.py +1 -1
- pyinfra/operations/choco.py +1 -1
- pyinfra/operations/dnf.py +4 -4
- pyinfra/operations/files.py +108 -321
- pyinfra/operations/gem.py +1 -1
- pyinfra/operations/git.py +6 -37
- pyinfra/operations/iptables.py +2 -10
- pyinfra/operations/launchd.py +1 -1
- pyinfra/operations/lxd.py +1 -9
- pyinfra/operations/mysql.py +5 -28
- pyinfra/operations/npm.py +1 -1
- pyinfra/operations/openrc.py +1 -1
- pyinfra/operations/pacman.py +3 -3
- pyinfra/operations/pip.py +14 -15
- pyinfra/operations/pkg.py +1 -1
- pyinfra/operations/pkgin.py +3 -3
- pyinfra/operations/postgres.py +347 -0
- pyinfra/operations/postgresql.py +17 -380
- pyinfra/operations/python.py +2 -17
- pyinfra/operations/selinux.py +5 -28
- pyinfra/operations/server.py +59 -84
- pyinfra/operations/snap.py +1 -3
- pyinfra/operations/ssh.py +8 -23
- pyinfra/operations/systemd.py +7 -7
- pyinfra/operations/sysvinit.py +3 -12
- pyinfra/operations/upstart.py +4 -4
- pyinfra/operations/util/__init__.py +12 -0
- pyinfra/operations/util/files.py +2 -2
- pyinfra/operations/util/packaging.py +6 -24
- pyinfra/operations/util/service.py +18 -37
- pyinfra/operations/vzctl.py +2 -2
- pyinfra/operations/xbps.py +3 -3
- pyinfra/operations/yum.py +4 -4
- pyinfra/operations/zypper.py +4 -4
- {pyinfra-2.9.2.dist-info → pyinfra-3.0b1.dist-info}/METADATA +19 -22
- pyinfra-3.0b1.dist-info/RECORD +163 -0
- pyinfra-3.0b1.dist-info/entry_points.txt +11 -0
- pyinfra_cli/__main__.py +2 -0
- pyinfra_cli/commands.py +7 -2
- pyinfra_cli/exceptions.py +83 -42
- pyinfra_cli/inventory.py +19 -4
- pyinfra_cli/log.py +17 -3
- pyinfra_cli/main.py +133 -90
- pyinfra_cli/prints.py +93 -129
- pyinfra_cli/util.py +60 -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 +100 -200
- 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 +66 -107
- tests/test_connectors/test_terraform.py +9 -15
- tests/test_connectors/test_util.py +24 -46
- tests/test_connectors/test_vagrant.py +4 -4
- 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.2.dist-info/RECORD +0 -170
- pyinfra-2.9.2.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.2.dist-info → pyinfra-3.0b1.dist-info}/LICENSE.md +0 -0
- {pyinfra-2.9.2.dist-info → pyinfra-3.0b1.dist-info}/WHEEL +0 -0
- {pyinfra-2.9.2.dist-info → pyinfra-3.0b1.dist-info}/top_level.txt +0 -0
pyinfra/operations/gem.py
CHANGED
pyinfra/operations/git.py
CHANGED
|
@@ -13,9 +13,7 @@ from . import files, ssh
|
|
|
13
13
|
from .util.files import chown, unix_path_join
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
@operation(
|
|
17
|
-
pipeline_facts={"git_config": "repo"},
|
|
18
|
-
)
|
|
16
|
+
@operation()
|
|
19
17
|
def config(key, value, multi_value=False, repo=None):
|
|
20
18
|
"""
|
|
21
19
|
Manage git config for a repository or globally.
|
|
@@ -54,19 +52,15 @@ def config(key, value, multi_value=False, repo=None):
|
|
|
54
52
|
|
|
55
53
|
if not multi_value and existing_config.get(key) != [value]:
|
|
56
54
|
yield '{0} {1} "{2}"'.format(base_command, key, value)
|
|
57
|
-
existing_config[key] = [value]
|
|
58
55
|
|
|
59
56
|
elif multi_value and value not in existing_config.get(key, []):
|
|
60
57
|
yield '{0} --add {1} "{2}"'.format(base_command, key, value)
|
|
61
|
-
existing_config.setdefault(key, []).append(value)
|
|
62
58
|
|
|
63
59
|
else:
|
|
64
60
|
host.noop("git config {0} is set to {1}".format(key, value))
|
|
65
61
|
|
|
66
62
|
|
|
67
|
-
@operation(
|
|
68
|
-
pipeline_facts={"git_branch": "target"},
|
|
69
|
-
)
|
|
63
|
+
@operation()
|
|
70
64
|
def repo(
|
|
71
65
|
src,
|
|
72
66
|
dest,
|
|
@@ -105,7 +99,7 @@ def repo(
|
|
|
105
99
|
"""
|
|
106
100
|
|
|
107
101
|
# Ensure our target directory exists
|
|
108
|
-
yield from files.directory(dest)
|
|
102
|
+
yield from files.directory._inner(dest)
|
|
109
103
|
|
|
110
104
|
# Do we need to scan for the remote host key?
|
|
111
105
|
if ssh_keyscan:
|
|
@@ -113,7 +107,7 @@ def repo(
|
|
|
113
107
|
domain = re.match(r"^[a-zA-Z0-9]+@([0-9a-zA-Z\.\-]+)", src)
|
|
114
108
|
|
|
115
109
|
if domain:
|
|
116
|
-
yield from ssh.keyscan(domain.group(1))
|
|
110
|
+
yield from ssh.keyscan._inner(domain.group(1))
|
|
117
111
|
else:
|
|
118
112
|
raise OperationError(
|
|
119
113
|
"Could not parse domain (to SSH keyscan) from: {0}".format(src),
|
|
@@ -130,21 +124,11 @@ def repo(
|
|
|
130
124
|
git_commands.append("clone {0} --branch {1} .".format(src, branch))
|
|
131
125
|
else:
|
|
132
126
|
git_commands.append("clone {0} .".format(src))
|
|
133
|
-
|
|
134
|
-
host.create_fact(GitBranch, kwargs={"repo": dest}, data=branch)
|
|
135
|
-
host.create_fact(
|
|
136
|
-
Directory,
|
|
137
|
-
kwargs={"path": git_dir},
|
|
138
|
-
data={"user": user, "group": group},
|
|
139
|
-
)
|
|
140
|
-
|
|
141
127
|
# Ensuring existing repo
|
|
142
128
|
else:
|
|
143
129
|
if branch and host.get_fact(GitBranch, repo=dest) != branch:
|
|
144
130
|
git_commands.append("fetch") # fetch to ensure we have the branch locally
|
|
145
131
|
git_commands.append("checkout {0}".format(branch))
|
|
146
|
-
host.create_fact(GitBranch, kwargs={"repo": dest}, data=branch)
|
|
147
|
-
|
|
148
132
|
if pull:
|
|
149
133
|
if rebase:
|
|
150
134
|
git_commands.append("pull --rebase")
|
|
@@ -293,7 +277,6 @@ def worktree(
|
|
|
293
277
|
|
|
294
278
|
# Doesn't exist & we want it
|
|
295
279
|
if not host.get_fact(Directory, path=worktree) and present:
|
|
296
|
-
|
|
297
280
|
# be sure that `repo` is a GIT repository
|
|
298
281
|
if not assume_repo_exists and not host.get_fact(
|
|
299
282
|
Directory,
|
|
@@ -321,12 +304,8 @@ def worktree(
|
|
|
321
304
|
if user or group:
|
|
322
305
|
yield chown(worktree, user, group, recursive=True)
|
|
323
306
|
|
|
324
|
-
host.create_fact(Directory, kwargs={"path": worktree}, data={"user": user, "group": group})
|
|
325
|
-
host.create_fact(GitTrackingBranch, kwargs={"repo": worktree}, data=new_branch)
|
|
326
|
-
|
|
327
307
|
# It exists and we don't want it
|
|
328
308
|
elif host.get_fact(Directory, path=worktree) and not present:
|
|
329
|
-
|
|
330
309
|
command = "cd {0} && git worktree remove .".format(worktree)
|
|
331
310
|
|
|
332
311
|
if force:
|
|
@@ -334,12 +313,8 @@ def worktree(
|
|
|
334
313
|
|
|
335
314
|
yield command
|
|
336
315
|
|
|
337
|
-
host.delete_fact(Directory, kwargs={"path": worktree})
|
|
338
|
-
host.create_fact(GitTrackingBranch, kwargs={"repo": worktree})
|
|
339
|
-
|
|
340
316
|
# It exists and we still want it => pull/rebase it
|
|
341
317
|
elif host.get_fact(Directory, path=worktree) and present:
|
|
342
|
-
|
|
343
318
|
# pull the worktree only if it's already linked to a tracking branch or
|
|
344
319
|
# if a remote branch is set
|
|
345
320
|
if host.get_fact(GitTrackingBranch, repo=worktree) or from_remote_branch:
|
|
@@ -359,7 +334,7 @@ def worktree(
|
|
|
359
334
|
yield command
|
|
360
335
|
|
|
361
336
|
|
|
362
|
-
@operation
|
|
337
|
+
@operation()
|
|
363
338
|
def bare_repo(
|
|
364
339
|
path,
|
|
365
340
|
user=None,
|
|
@@ -384,7 +359,7 @@ def bare_repo(
|
|
|
384
359
|
)
|
|
385
360
|
"""
|
|
386
361
|
|
|
387
|
-
yield from files.directory(path, present=present)
|
|
362
|
+
yield from files.directory._inner(path, present=present)
|
|
388
363
|
|
|
389
364
|
if present:
|
|
390
365
|
head_filename = unix_path_join(path, "HEAD")
|
|
@@ -397,9 +372,3 @@ def bare_repo(
|
|
|
397
372
|
else:
|
|
398
373
|
if (user and head_file["user"] != user) or (group and head_file["group"] != group):
|
|
399
374
|
yield chown(path, user, group, recursive=True)
|
|
400
|
-
|
|
401
|
-
host.create_fact(
|
|
402
|
-
File,
|
|
403
|
-
kwargs={"path": head_filename},
|
|
404
|
-
data={"user": user, "group": group, "mode": None},
|
|
405
|
-
)
|
pyinfra/operations/iptables.py
CHANGED
|
@@ -8,7 +8,7 @@ from pyinfra.api.exceptions import OperationError
|
|
|
8
8
|
from pyinfra.facts.iptables import Ip6tablesChains, Ip6tablesRules, IptablesChains, IptablesRules
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
@operation
|
|
11
|
+
@operation()
|
|
12
12
|
def chain(
|
|
13
13
|
chain,
|
|
14
14
|
present=True,
|
|
@@ -41,7 +41,6 @@ def chain(
|
|
|
41
41
|
if not present:
|
|
42
42
|
if chain in chains:
|
|
43
43
|
yield "{0} -X {1}".format(command, chain)
|
|
44
|
-
chains.pop(chain)
|
|
45
44
|
else:
|
|
46
45
|
host.noop("iptables chain {0} does not exist".format(chain))
|
|
47
46
|
return
|
|
@@ -49,17 +48,15 @@ def chain(
|
|
|
49
48
|
if present:
|
|
50
49
|
if chain not in chains:
|
|
51
50
|
yield "{0} -N {1}".format(command, chain)
|
|
52
|
-
chains[chain] = None # policy will be set below
|
|
53
51
|
else:
|
|
54
52
|
host.noop("iptables chain {0} exists".format(chain))
|
|
55
53
|
|
|
56
54
|
if policy:
|
|
57
55
|
if chain not in chains or chains[chain] != policy:
|
|
58
56
|
yield "{0} -P {1} {2}".format(command, chain, policy)
|
|
59
|
-
chains[chain] = policy
|
|
60
57
|
|
|
61
58
|
|
|
62
|
-
@operation
|
|
59
|
+
@operation()
|
|
63
60
|
def rule(
|
|
64
61
|
chain,
|
|
65
62
|
jump,
|
|
@@ -310,8 +307,3 @@ def rule(
|
|
|
310
307
|
|
|
311
308
|
# Build the final iptables command
|
|
312
309
|
yield " ".join(args)
|
|
313
|
-
|
|
314
|
-
if action == "-D":
|
|
315
|
-
rules.remove(definition)
|
|
316
|
-
else:
|
|
317
|
-
rules.append(definition)
|
pyinfra/operations/launchd.py
CHANGED
pyinfra/operations/lxd.py
CHANGED
|
@@ -15,7 +15,7 @@ def get_container_named(name, containers):
|
|
|
15
15
|
return None
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
@operation
|
|
18
|
+
@operation()
|
|
19
19
|
def container(
|
|
20
20
|
id,
|
|
21
21
|
present=True,
|
|
@@ -53,8 +53,6 @@ def container(
|
|
|
53
53
|
|
|
54
54
|
# Command to remove the container:
|
|
55
55
|
yield "lxc delete {0}".format(id)
|
|
56
|
-
|
|
57
|
-
current_containers.remove(container)
|
|
58
56
|
else:
|
|
59
57
|
host.noop("container {0} does not exist".format(id))
|
|
60
58
|
|
|
@@ -63,11 +61,5 @@ def container(
|
|
|
63
61
|
if not container:
|
|
64
62
|
# Command to create the container:
|
|
65
63
|
yield "lxc launch {image} {id} < /dev/null".format(id=id, image=image)
|
|
66
|
-
current_containers.append(
|
|
67
|
-
{
|
|
68
|
-
"name": id,
|
|
69
|
-
"image": image,
|
|
70
|
-
},
|
|
71
|
-
)
|
|
72
64
|
else:
|
|
73
65
|
host.noop("container {0} exists".format(id))
|
pyinfra/operations/mysql.py
CHANGED
|
@@ -52,7 +52,7 @@ def sql(
|
|
|
52
52
|
)
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
@operation
|
|
55
|
+
@operation()
|
|
56
56
|
def user(
|
|
57
57
|
user,
|
|
58
58
|
present=True,
|
|
@@ -162,22 +162,10 @@ def user(
|
|
|
162
162
|
host=mysql_host,
|
|
163
163
|
port=mysql_port,
|
|
164
164
|
)
|
|
165
|
-
current_users.pop(user_host)
|
|
166
165
|
else:
|
|
167
166
|
host.noop("mysql user {0}@{1} does not exist".format(user, user_hostname))
|
|
168
167
|
return
|
|
169
168
|
|
|
170
|
-
new_or_updated_user_fact = {
|
|
171
|
-
"ssl_type": "ANY" if require == "SSL" else require,
|
|
172
|
-
"ssl_cipher": require_cipher,
|
|
173
|
-
"x509_issuer": require_issuer,
|
|
174
|
-
"x509_subject": require_subject,
|
|
175
|
-
"max_user_connections": max_connections,
|
|
176
|
-
"max_questions": max_queries_per_hour,
|
|
177
|
-
"max_updates": max_updates_per_hour,
|
|
178
|
-
"max_connections": max_connections_per_hour,
|
|
179
|
-
}
|
|
180
|
-
|
|
181
169
|
if present and not is_present:
|
|
182
170
|
sql_bits = ['CREATE USER "{0}"@"{1}"'.format(user, user_hostname)]
|
|
183
171
|
if password:
|
|
@@ -224,8 +212,6 @@ def user(
|
|
|
224
212
|
port=mysql_port,
|
|
225
213
|
)
|
|
226
214
|
|
|
227
|
-
current_users[user_host] = new_or_updated_user_fact
|
|
228
|
-
|
|
229
215
|
if present and is_present:
|
|
230
216
|
current_user = current_users.get(user_host)
|
|
231
217
|
|
|
@@ -277,14 +263,13 @@ def user(
|
|
|
277
263
|
host=mysql_host,
|
|
278
264
|
port=mysql_port,
|
|
279
265
|
)
|
|
280
|
-
current_user.update(new_or_updated_user_fact)
|
|
281
266
|
else:
|
|
282
267
|
host.noop("mysql user {0}@{1} exists".format(user, user_hostname))
|
|
283
268
|
|
|
284
269
|
# If we're here either the user exists or we just created them; either way
|
|
285
270
|
# now we can check any privileges are set.
|
|
286
271
|
if privileges:
|
|
287
|
-
yield from _privileges(
|
|
272
|
+
yield from _privileges._inner(
|
|
288
273
|
user,
|
|
289
274
|
privileges,
|
|
290
275
|
user_hostname=user_hostname,
|
|
@@ -295,7 +280,7 @@ def user(
|
|
|
295
280
|
)
|
|
296
281
|
|
|
297
282
|
|
|
298
|
-
@operation
|
|
283
|
+
@operation()
|
|
299
284
|
def database(
|
|
300
285
|
database,
|
|
301
286
|
# Desired database settings
|
|
@@ -359,7 +344,6 @@ def database(
|
|
|
359
344
|
host=mysql_host,
|
|
360
345
|
port=mysql_port,
|
|
361
346
|
)
|
|
362
|
-
current_databases.pop(database)
|
|
363
347
|
else:
|
|
364
348
|
host.noop("mysql database {0} does not exist".format(database))
|
|
365
349
|
return
|
|
@@ -381,16 +365,12 @@ def database(
|
|
|
381
365
|
host=mysql_host,
|
|
382
366
|
port=mysql_port,
|
|
383
367
|
)
|
|
384
|
-
current_databases[database] = {
|
|
385
|
-
"collate": collate,
|
|
386
|
-
"charset": charset,
|
|
387
|
-
}
|
|
388
368
|
else:
|
|
389
369
|
host.noop("mysql database {0} exists".format(database))
|
|
390
370
|
|
|
391
371
|
# Ensure any user privileges for this database
|
|
392
372
|
if user and user_privileges:
|
|
393
|
-
yield from privileges(
|
|
373
|
+
yield from privileges._inner(
|
|
394
374
|
user,
|
|
395
375
|
user_hostname=user_hostname,
|
|
396
376
|
privileges=user_privileges,
|
|
@@ -402,7 +382,7 @@ def database(
|
|
|
402
382
|
)
|
|
403
383
|
|
|
404
384
|
|
|
405
|
-
@operation
|
|
385
|
+
@operation()
|
|
406
386
|
def privileges(
|
|
407
387
|
user,
|
|
408
388
|
privileges,
|
|
@@ -504,9 +484,6 @@ def privileges(
|
|
|
504
484
|
# Find / grant any privileges that we want but do not exist
|
|
505
485
|
privileges_to_grant = privileges - existing_privileges
|
|
506
486
|
|
|
507
|
-
user_grants[database_table] -= privileges_to_revoke
|
|
508
|
-
user_grants[database_table].update(privileges_to_grant)
|
|
509
|
-
|
|
510
487
|
if privileges_to_grant:
|
|
511
488
|
# We will grant something on this table, no need to revoke "USAGE" as it will be overridden
|
|
512
489
|
privileges_to_revoke.discard("USAGE")
|
pyinfra/operations/npm.py
CHANGED
pyinfra/operations/openrc.py
CHANGED
pyinfra/operations/pacman.py
CHANGED
|
@@ -18,7 +18,7 @@ def upgrade():
|
|
|
18
18
|
yield "pacman --noconfirm -Su"
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
_upgrade = upgrade # noqa: E305
|
|
21
|
+
_upgrade = upgrade._inner # noqa: E305
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@operation(is_idempotent=False)
|
|
@@ -30,10 +30,10 @@ def update():
|
|
|
30
30
|
yield "pacman -Sy"
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
_update = update # noqa: E305
|
|
33
|
+
_update = update._inner # noqa: E305
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
@operation
|
|
36
|
+
@operation()
|
|
37
37
|
def packages(
|
|
38
38
|
packages=None,
|
|
39
39
|
present=True,
|
pyinfra/operations/pip.py
CHANGED
|
@@ -12,7 +12,7 @@ from . import files
|
|
|
12
12
|
from .util.packaging import ensure_packages
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
@operation
|
|
15
|
+
@operation()
|
|
16
16
|
def virtualenv(
|
|
17
17
|
path,
|
|
18
18
|
python=None,
|
|
@@ -46,7 +46,7 @@ def virtualenv(
|
|
|
46
46
|
|
|
47
47
|
if present is False:
|
|
48
48
|
if host.get_fact(File, path=activate_script_path):
|
|
49
|
-
yield from files.directory(path, present=False)
|
|
49
|
+
yield from files.directory._inner(path, present=False)
|
|
50
50
|
else:
|
|
51
51
|
host.noop("virtualenv {0} does not exist".format(path))
|
|
52
52
|
|
|
@@ -72,20 +72,14 @@ def virtualenv(
|
|
|
72
72
|
command.append(path)
|
|
73
73
|
|
|
74
74
|
yield " ".join(command)
|
|
75
|
-
|
|
76
|
-
host.create_fact(
|
|
77
|
-
File,
|
|
78
|
-
kwargs={"path": activate_script_path},
|
|
79
|
-
data={"user": None, "group": None},
|
|
80
|
-
)
|
|
81
75
|
else:
|
|
82
76
|
host.noop("virtualenv {0} exists".format(path))
|
|
83
77
|
|
|
84
78
|
|
|
85
|
-
_virtualenv = virtualenv # noqa
|
|
79
|
+
_virtualenv = virtualenv._inner # noqa
|
|
86
80
|
|
|
87
81
|
|
|
88
|
-
@operation
|
|
82
|
+
@operation()
|
|
89
83
|
def venv(
|
|
90
84
|
path,
|
|
91
85
|
python=None,
|
|
@@ -111,7 +105,7 @@ def venv(
|
|
|
111
105
|
)
|
|
112
106
|
"""
|
|
113
107
|
|
|
114
|
-
yield from
|
|
108
|
+
yield from _virtualenv(
|
|
115
109
|
venv=True,
|
|
116
110
|
path=path,
|
|
117
111
|
python=python,
|
|
@@ -121,7 +115,7 @@ def venv(
|
|
|
121
115
|
)
|
|
122
116
|
|
|
123
117
|
|
|
124
|
-
@operation
|
|
118
|
+
@operation()
|
|
125
119
|
def packages(
|
|
126
120
|
packages=None,
|
|
127
121
|
present=True,
|
|
@@ -173,10 +167,10 @@ def packages(
|
|
|
173
167
|
virtualenv = virtualenv.rstrip("/")
|
|
174
168
|
pip = "{0}/bin/{1}".format(virtualenv, pip)
|
|
175
169
|
|
|
176
|
-
|
|
170
|
+
install_command_args = [pip, "install"]
|
|
177
171
|
if extra_install_args:
|
|
178
|
-
|
|
179
|
-
install_command = " ".join(
|
|
172
|
+
install_command_args.append(extra_install_args)
|
|
173
|
+
install_command = " ".join(install_command_args)
|
|
180
174
|
|
|
181
175
|
uninstall_command = " ".join([pip, "uninstall", "--yes"])
|
|
182
176
|
|
|
@@ -191,6 +185,11 @@ def packages(
|
|
|
191
185
|
if packages:
|
|
192
186
|
current_packages = host.get_fact(PipPackages, pip=pip)
|
|
193
187
|
|
|
188
|
+
# PEP-0426 states that Python packages should be compared using lowercase, so lowercase both
|
|
189
|
+
# the input packages and the fact packages before comparison.
|
|
190
|
+
packages = [pkg.lower() for pkg in packages]
|
|
191
|
+
current_packages = {pkg.lower(): versions for pkg, versions in current_packages.items()}
|
|
192
|
+
|
|
194
193
|
yield from ensure_packages(
|
|
195
194
|
host,
|
|
196
195
|
packages,
|
pyinfra/operations/pkg.py
CHANGED
|
@@ -11,7 +11,7 @@ from pyinfra.facts.server import Arch, Os, OsVersion, Which
|
|
|
11
11
|
from .util.packaging import ensure_packages
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
@operation
|
|
14
|
+
@operation()
|
|
15
15
|
def packages(packages=None, present=True, pkg_path=None):
|
|
16
16
|
"""
|
|
17
17
|
Install/remove/update pkg packages. This will use ``pkg ...`` where available
|
pyinfra/operations/pkgin.py
CHANGED
|
@@ -18,7 +18,7 @@ def upgrade():
|
|
|
18
18
|
yield "pkgin -y upgrade"
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
_upgrade = upgrade # noqa: E305
|
|
21
|
+
_upgrade = upgrade._inner # noqa: E305
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@operation(is_idempotent=False)
|
|
@@ -30,10 +30,10 @@ def update():
|
|
|
30
30
|
yield "pkgin -y update"
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
_update = update # noqa: E305
|
|
33
|
+
_update = update._inner # noqa: E305
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
@operation
|
|
36
|
+
@operation()
|
|
37
37
|
def packages(
|
|
38
38
|
packages=None,
|
|
39
39
|
present=True,
|