mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-03-26 21:33:12 +00:00
Add to_toml filter (#11423)
* Add to_toml filter This is based heavily on the to_yaml filter, but with a pared-down feature set. * Protect import * Don't quote datetime as a string * Use Ansible error types * Import correct error types * Don't use AnsibleTypeError It doesn't seem to be available on older Ansible core versions. * Fix antsibull-nox errors * Install dependencies for to_toml integration test Co-authored-by: Felix Fontein <felix@fontein.de> * Reduce author list to main contributor Co-authored-by: Felix Fontein <felix@fontein.de> * Update version added for to_toml Co-authored-by: Felix Fontein <felix@fontein.de> * Use AnsibleError for missing import Co-authored-by: Felix Fontein <felix@fontein.de> * Use AnsibleFilterError for runtime type check Co-authored-by: Felix Fontein <felix@fontein.de> * Move common code to plugin_utils/_tags.py * Mark module util as private Co-authored-by: Felix Fontein <felix@fontein.de> * Update BOTMETA for to_toml Co-authored-by: Felix Fontein <felix@fontein.de> * Fix typo * Correct version number Co-authored-by: Felix Fontein <felix@fontein.de> * Use to_text for to_toml dict key conversions Co-authored-by: Felix Fontein <felix@fontein.de> * Add tomlkit requirement to docs Co-authored-by: Felix Fontein <felix@fontein.de> * Add missing import * Add aliases for for to_toml integration test --------- Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
85
plugins/plugin_utils/_tags.py
Normal file
85
plugins/plugin_utils/_tags.py
Normal file
@@ -0,0 +1,85 @@
|
||||
# Copyright (c) Contributors to the Ansible project
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# Note that this module util is **PRIVATE** to the collection. It can have breaking changes at any time.
|
||||
# Do not use this from other collections or standalone plugins/modules!
|
||||
|
||||
import typing as t
|
||||
from collections.abc import Mapping, Set
|
||||
|
||||
from ansible.module_utils.common.collections import is_sequence
|
||||
|
||||
try:
|
||||
# This is ansible-core 2.19+
|
||||
from ansible.parsing.vault import VaultHelper, VaultLib
|
||||
from ansible.utils.vars import transform_to_native_types
|
||||
|
||||
HAS_TRANSFORM_TO_NATIVE_TYPES = True
|
||||
except ImportError:
|
||||
HAS_TRANSFORM_TO_NATIVE_TYPES = False
|
||||
|
||||
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
|
||||
from ansible.utils.unsafe_proxy import AnsibleUnsafe
|
||||
|
||||
|
||||
def _to_native_types_compat(value: t.Any, *, redact_value: str | None) -> t.Any:
|
||||
"""Compatibility function for ansible-core 2.18 and before."""
|
||||
if value is None:
|
||||
return value
|
||||
if isinstance(value, AnsibleUnsafe):
|
||||
# This only works up to ansible-core 2.18:
|
||||
return _to_native_types_compat(value._strip_unsafe(), redact_value=redact_value) # type: ignore
|
||||
# But that's fine, since this code path isn't taken on ansible-core 2.19+ anyway.
|
||||
if isinstance(value, Mapping):
|
||||
return {
|
||||
_to_native_types_compat(key, redact_value=redact_value): _to_native_types_compat(
|
||||
val, redact_value=redact_value
|
||||
)
|
||||
for key, val in value.items()
|
||||
}
|
||||
if isinstance(value, Set):
|
||||
return {_to_native_types_compat(elt, redact_value=redact_value) for elt in value}
|
||||
if is_sequence(value):
|
||||
return [_to_native_types_compat(elt, redact_value=redact_value) for elt in value]
|
||||
if isinstance(value, AnsibleVaultEncryptedUnicode):
|
||||
if redact_value is not None:
|
||||
return redact_value
|
||||
# This only works up to ansible-core 2.18:
|
||||
return value.data
|
||||
# But that's fine, since this code path isn't taken on ansible-core 2.19+ anyway.
|
||||
if isinstance(value, bytes):
|
||||
return bytes(value)
|
||||
if isinstance(value, str):
|
||||
return str(value)
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def _to_native_types(value: t.Any, *, redact: bool) -> t.Any:
|
||||
if isinstance(value, Mapping):
|
||||
return {_to_native_types(k, redact=redact): _to_native_types(v, redact=redact) for k, v in value.items()}
|
||||
if is_sequence(value):
|
||||
return [_to_native_types(e, redact=redact) for e in value]
|
||||
if redact:
|
||||
ciphertext = VaultHelper.get_ciphertext(value, with_tags=False)
|
||||
if ciphertext and VaultLib.is_encrypted(ciphertext):
|
||||
return "<redacted>"
|
||||
return transform_to_native_types(value, redact=redact)
|
||||
|
||||
|
||||
def remove_all_tags(value: t.Any, *, redact_sensitive_values: bool = False) -> t.Any:
|
||||
"""
|
||||
Remove all tags from all values in the input.
|
||||
|
||||
If ``redact_sensitive_values`` is ``True``, all sensitive values will be redacted.
|
||||
"""
|
||||
if HAS_TRANSFORM_TO_NATIVE_TYPES:
|
||||
return _to_native_types(value, redact=redact_sensitive_values)
|
||||
|
||||
return _to_native_types_compat( # type: ignore[unreachable]
|
||||
value,
|
||||
redact_value="<redacted>"
|
||||
if redact_sensitive_values
|
||||
else None, # same string as in ansible-core 2.19 by transform_to_native_types()
|
||||
)
|
||||
Reference in New Issue
Block a user