ansible-vars 1.0.16__py3-none-any.whl → 1.0.18__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.
- ansible_vars/cli.py +4 -4
- ansible_vars/constants.py +5 -0
- ansible_vars/util.py +2 -3
- ansible_vars/vault.py +16 -9
- {ansible_vars-1.0.16.dist-info → ansible_vars-1.0.18.dist-info}/METADATA +1 -1
- ansible_vars-1.0.18.dist-info/RECORD +13 -0
- ansible_vars-1.0.16.dist-info/RECORD +0 -13
- {ansible_vars-1.0.16.dist-info → ansible_vars-1.0.18.dist-info}/WHEEL +0 -0
- {ansible_vars-1.0.16.dist-info → ansible_vars-1.0.18.dist-info}/entry_points.txt +0 -0
- {ansible_vars-1.0.16.dist-info → ansible_vars-1.0.18.dist-info}/licenses/LICENSE +0 -0
ansible_vars/cli.py
CHANGED
@@ -33,7 +33,7 @@ from pygments.formatters import TerminalFormatter, Terminal256Formatter, Termina
|
|
33
33
|
from .vault import VaultFile, EncryptedVar, ProtoEncryptedVar
|
34
34
|
from .vault_crypt import VaultKey, VaultKeyring
|
35
35
|
from .util import DiffFileLogger, VaultDaemon
|
36
|
-
from .constants import Unset, MatchLocation, SENTINEL_KEY
|
36
|
+
from .constants import Unset, MatchLocation, SENTINEL_KEY, APPEND_SENTINEL
|
37
37
|
from .errors import YAMLFormatError, UnsupportedGenericFileOperation
|
38
38
|
|
39
39
|
## CLI argument parsing
|
@@ -183,13 +183,13 @@ The value will be shown in (recursively) decrypted form.
|
|
183
183
|
JSON mode formatting:
|
184
184
|
- [ ... ] or { ... } for lists/dictionaries, "<value>" for strings, <value> for numbers
|
185
185
|
''',
|
186
|
-
'cmd_set':
|
186
|
+
'cmd_set': f"""
|
187
187
|
Creates or updates a node in a vault with a YAML value, optionally encrypting the value('s string leaves) first using the configured encryption key.
|
188
|
-
|
188
|
+
Any unknown keys along the given path will be created as dictionaries. You can append an element to a list by using the special key '{ APPEND_SENTINEL }'.
|
189
189
|
The value is interpreted as YAML code.
|
190
190
|
|
191
191
|
[!] Creating new nodes or changing non-leaf nodes may break/remove trailing comments and Jinja2 blocks.
|
192
|
-
|
192
|
+
""",
|
193
193
|
'cmd_del': '''
|
194
194
|
Deletes a node from a vault if it exists.
|
195
195
|
|
ansible_vars/constants.py
CHANGED
@@ -45,6 +45,11 @@ EDIT_MODE_HEADER: str = f"""
|
|
45
45
|
|
46
46
|
""".lstrip('\n')
|
47
47
|
|
48
|
+
# Special codes
|
49
|
+
|
50
|
+
# Marks that a new element should be appended to a list in a `Vault.set` call
|
51
|
+
APPEND_SENTINEL: str = '+'
|
52
|
+
|
48
53
|
# Diff log filenames
|
49
54
|
|
50
55
|
# Default filename for a plaintext vault log
|
ansible_vars/util.py
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
# Standard library imports
|
4
4
|
import os, atexit
|
5
5
|
from glob import glob
|
6
|
-
from pathlib import Path
|
7
6
|
from functools import wraps
|
8
7
|
from datetime import datetime
|
9
8
|
from typing import Callable
|
@@ -38,7 +37,7 @@ class DiffLogger():
|
|
38
37
|
You can specify an optional comment string which will be included.
|
39
38
|
'''
|
40
39
|
# Check if any changes happened
|
41
|
-
diff:
|
40
|
+
diff: str | None = curr_vault.diff(prev_vault, context_lines=0, show_filenames=True)
|
42
41
|
if not force and not diff:
|
43
42
|
return None
|
44
43
|
# Build entry
|
@@ -55,7 +54,7 @@ class DiffLogger():
|
|
55
54
|
# Diff
|
56
55
|
lines.append('DIFF')
|
57
56
|
if diff:
|
58
|
-
lines += diff
|
57
|
+
lines += diff.split('\n')
|
59
58
|
else:
|
60
59
|
lines.append('No changes.')
|
61
60
|
#lines.append(OUTER_SEP)
|
ansible_vars/vault.py
CHANGED
@@ -15,7 +15,8 @@ from ruamel.yaml.constructor import Constructor
|
|
15
15
|
from ruamel.yaml.comments import CommentedMap
|
16
16
|
|
17
17
|
# Internal module imports
|
18
|
-
from .constants import ThrowError, octal, Indexable, ChangeList, MatchLocation,
|
18
|
+
from .constants import ThrowError, octal, Indexable, ChangeList, MatchLocation, \
|
19
|
+
SENTINEL_KEY, EDIT_MODE_HEADER, ENCRYPTED_VAR_TAG, APPEND_SENTINEL
|
19
20
|
from .vault_crypt import VaultKey, VaultKeyring
|
20
21
|
from .errors import KeyExistsError, NoVaultKeysError, YAMLFormatError
|
21
22
|
|
@@ -242,11 +243,12 @@ class Vault():
|
|
242
243
|
self, path: DictPath, value: Any, overwrite: bool | Type[ThrowError] = True, # type: ignore
|
243
244
|
create_parents: bool | Type[ThrowError] = True, encrypt: bool = False
|
244
245
|
) -> bool:
|
245
|
-
|
246
|
+
f"""
|
246
247
|
Creates or updates a value in the vault's variables. The value has to be serializable into YAML.
|
247
248
|
If the last/only key of the key path does not exist yet, it will be created.
|
248
249
|
If the variable is set successfully, `True` is returned. If any of the below checks fail, `False` is returned.
|
249
|
-
Be aware that appending a new entry to a list requires the key to be equal to the length of the list (i.e. largest index + 1)
|
250
|
+
Be aware that appending a new entry to a list requires the key to be equal to the length of the list (i.e. largest index + 1),
|
251
|
+
or to be the special symbol '{ APPEND_SENTINEL }'.
|
250
252
|
On updated leaf values, comment and Jinja2 metadata is preserved.
|
251
253
|
When appending a new value or editing an indexable item, metadata may get messed up.
|
252
254
|
|
@@ -262,7 +264,7 @@ class Vault():
|
|
262
264
|
- `encrypt`: Controls if the value should be recursively encrypted before storing it (only plain `str`s get encrypted)
|
263
265
|
- `True`: Attempt to copy and convert the value('s leaf values) into an `EncryptedVar` before storing it
|
264
266
|
- `False`: Store the value as-is
|
265
|
-
|
267
|
+
"""
|
266
268
|
path: tuple[Hashable, ...] = Vault._to_path(path) # XXX typer complains if not explicitly re-typed
|
267
269
|
# Encrypt value if necessary
|
268
270
|
if encrypt:
|
@@ -288,10 +290,13 @@ class Vault():
|
|
288
290
|
if not isinstance(parent, dict | list):
|
289
291
|
raise TypeError(f"Indexing into a { type(parent) } is not supported ({ par_path })")
|
290
292
|
# Check if index is of correct type
|
291
|
-
if isinstance(parent, list) and type(segment) is not int:
|
292
|
-
raise TypeError(f"Type of list index has to be int, got { type(segment) } ({ par_path }[{ segment }])")
|
293
|
+
if isinstance(parent, list) and segment != APPEND_SENTINEL and type(segment) is not int:
|
294
|
+
raise TypeError(f"Type of list index has to be int (or str as '{ APPEND_SENTINEL }'), got { type(segment) } ({ par_path }[{ segment }])")
|
293
295
|
# Check if the current segment has to be created in the parent
|
294
|
-
if (
|
296
|
+
if (
|
297
|
+
(isinstance(parent, dict) and segment not in parent) or \
|
298
|
+
(isinstance(parent, list) and (segment == APPEND_SENTINEL or cast(int, segment) >= len(parent)))
|
299
|
+
):
|
295
300
|
if not is_last:
|
296
301
|
if create_parents is ThrowError:
|
297
302
|
raise KeyError(f"Parents of { '.'.join(map(str, path)) } could not be resolved ({ segment } not in { par_path })")
|
@@ -299,9 +304,9 @@ class Vault():
|
|
299
304
|
return False
|
300
305
|
# Create nested dictionary as next parent or set value of leaf, depending on index
|
301
306
|
segment_value: Any = value if is_last else CommentedMap()
|
302
|
-
# Check that a new list item has a specified index of (largest list index + 1)
|
307
|
+
# Check that a new list item has a specified index of (largest list index + 1) or is the special append sentinel
|
303
308
|
# This is done because the method of creating an index of e.g. 7 in a list of length 3 is ambiguous
|
304
|
-
if isinstance(parent, list) and segment != len(parent):
|
309
|
+
if isinstance(parent, list) and segment != len(parent) and segment != APPEND_SENTINEL:
|
305
310
|
raise IndexError(f"Creating new list item, but index { segment } exceeds appendment index { len(parent) } ({ par_path })")
|
306
311
|
# Set value
|
307
312
|
if isinstance(parent, dict):
|
@@ -316,6 +321,8 @@ class Vault():
|
|
316
321
|
return False
|
317
322
|
parent[segment] = value # type: ignore
|
318
323
|
# Advance parent
|
324
|
+
if isinstance(parent, list) and segment == APPEND_SENTINEL:
|
325
|
+
segment = len(parent) - 1 # element has already been appended
|
319
326
|
parent = parent[segment] # type: ignore
|
320
327
|
par_path = f"{ par_path }.{ segment }"
|
321
328
|
return True
|
@@ -0,0 +1,13 @@
|
|
1
|
+
ansible_vars/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
ansible_vars/cli.py,sha256=sgpFi1ltsgJ5Dt9Fbf8p4uAkAD2d7pD3Z5ZwXjyqd9k,66450
|
3
|
+
ansible_vars/constants.py,sha256=TXn1mEco5FgyRVWEcx4spgqSNirR2vFE9SZJnMNcYic,1745
|
4
|
+
ansible_vars/errors.py,sha256=6dzyksPKWira9O2-Ir3MIOwr4XjN9MSBiRp5e6siY6Q,1256
|
5
|
+
ansible_vars/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
ansible_vars/util.py,sha256=NJ_qufelfe0m4i80sb81PYYbbkVhoHNcpkJdl8XYpTQ,21241
|
7
|
+
ansible_vars/vault.py,sha256=bZpGu3qhETWeGNf7xuBwYk80XeaBIBPuFfJ6JhC9rK0,47663
|
8
|
+
ansible_vars/vault_crypt.py,sha256=ZXa6QywyWdRVhY3YkFuk-COYs50MG252uakqe3bUUog,12116
|
9
|
+
ansible_vars-1.0.18.dist-info/METADATA,sha256=MhYniY-CIFYgr-O9uNOj4sYSsy5qWUkFMYNYpoXHZ8c,21071
|
10
|
+
ansible_vars-1.0.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
11
|
+
ansible_vars-1.0.18.dist-info/entry_points.txt,sha256=RrhkEH0MbfRzflguVrfYfthsFC5V2fkFnizUG3uHMtQ,55
|
12
|
+
ansible_vars-1.0.18.dist-info/licenses/LICENSE,sha256=ocyJHLG5wD12qB4uam2pqWTHIJmzloiyNyTex6Q2DKo,1062
|
13
|
+
ansible_vars-1.0.18.dist-info/RECORD,,
|
@@ -1,13 +0,0 @@
|
|
1
|
-
ansible_vars/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
ansible_vars/cli.py,sha256=cp891u9-kZoJireRIsTh-zy_9cTZPifLio2U7NqRoQM,66428
|
3
|
-
ansible_vars/constants.py,sha256=VNr78qbzdJ0Vn0psbzjjQngNG3VbHhk6NXTz30VNUno,1622
|
4
|
-
ansible_vars/errors.py,sha256=6dzyksPKWira9O2-Ir3MIOwr4XjN9MSBiRp5e6siY6Q,1256
|
5
|
-
ansible_vars/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
ansible_vars/util.py,sha256=UwGPBT19pee7lBpWuBzLPAvcrHUBAn6i1MrJvzM9OQ4,21265
|
7
|
-
ansible_vars/vault.py,sha256=pBZVz64qdj1vstC9rZBIJ3O9n-_AHhhbySN1Q7eMWho,47199
|
8
|
-
ansible_vars/vault_crypt.py,sha256=ZXa6QywyWdRVhY3YkFuk-COYs50MG252uakqe3bUUog,12116
|
9
|
-
ansible_vars-1.0.16.dist-info/METADATA,sha256=QqgRP-yb3BHIis97g15QFpQNn5kL2stPVRmz5KZmQ6A,21071
|
10
|
-
ansible_vars-1.0.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
11
|
-
ansible_vars-1.0.16.dist-info/entry_points.txt,sha256=RrhkEH0MbfRzflguVrfYfthsFC5V2fkFnizUG3uHMtQ,55
|
12
|
-
ansible_vars-1.0.16.dist-info/licenses/LICENSE,sha256=ocyJHLG5wD12qB4uam2pqWTHIJmzloiyNyTex6Q2DKo,1062
|
13
|
-
ansible_vars-1.0.16.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|