mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-30 06:11:26 -07:00
Support nested JSON decoding in AnsibleJSONDecoder (#45924)
* Support nested JSON decoding in AnsibleJSONDecoder * Add tests for vault portion of AnsibleJSONDecoder
This commit is contained in:
parent
df3655968f
commit
c0915e2f5a
4 changed files with 58 additions and 21 deletions
2
changelogs/fragments/ajson-nested-decode.yaml
Normal file
2
changelogs/fragments/ajson-nested-decode.yaml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- Ansible JSON Decoder - Switch from decode to object_hook to support nested use of __ansible_vault and __ansible_unsafe (https://github.com/ansible/ansible/pull/45514)
|
|
@ -20,33 +20,27 @@ class AnsibleJSONDecoder(json.JSONDecoder):
|
||||||
|
|
||||||
_vaults = {}
|
_vaults = {}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['object_hook'] = self.object_hook
|
||||||
|
super(AnsibleJSONDecoder, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_secrets(cls, secrets):
|
def set_secrets(cls, secrets):
|
||||||
cls._vaults['default'] = VaultLib(secrets=secrets)
|
cls._vaults['default'] = VaultLib(secrets=secrets)
|
||||||
|
|
||||||
def _decode_map(self, value):
|
def object_hook(self, pairs):
|
||||||
|
for key in pairs:
|
||||||
|
value = pairs[key]
|
||||||
|
|
||||||
if value.get('__ansible_unsafe', False):
|
if key == '__ansible_vault':
|
||||||
value = wrap_var(value.get('__ansible_unsafe'))
|
value = AnsibleVaultEncryptedUnicode(value)
|
||||||
elif value.get('__ansible_vault', False):
|
|
||||||
value = AnsibleVaultEncryptedUnicode(value.get('__ansible_vault'))
|
|
||||||
if self._vaults:
|
if self._vaults:
|
||||||
value.vault = self._vaults['default']
|
value.vault = self._vaults['default']
|
||||||
else:
|
|
||||||
for k in value:
|
|
||||||
if isinstance(value[k], Mapping):
|
|
||||||
value[k] = self._decode_map(value[k])
|
|
||||||
return value
|
return value
|
||||||
|
elif key == '__ansible_unsafe':
|
||||||
|
return wrap_var(value.get('__ansible_unsafe'))
|
||||||
|
|
||||||
def decode(self, obj):
|
return pairs
|
||||||
''' use basic json decoding except for specific ansible objects unsafe and vault '''
|
|
||||||
|
|
||||||
value = super(AnsibleJSONDecoder, self).decode(obj)
|
|
||||||
|
|
||||||
if isinstance(value, Mapping):
|
|
||||||
value = self._decode_map(value)
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: find way to integrate with the encoding modules do in module_utils
|
# TODO: find way to integrate with the encoding modules do in module_utils
|
||||||
|
|
19
test/units/parsing/fixtures/ajson.json
Normal file
19
test/units/parsing/fixtures/ajson.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"password": {
|
||||||
|
"__ansible_vault": "$ANSIBLE_VAULT;1.1;AES256\n34646264306632313333393636316562356435376162633631326264383934326565333633366238\n3863373264326461623132613931346165636465346337310a326434313830316337393263616439\n64653937313463396366633861363266633465663730303633323534363331316164623237363831\n3536333561393238370a313330316263373938326162386433313336613532653538376662306435\n3339\n"
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
"baz": [
|
||||||
|
{
|
||||||
|
"password": {
|
||||||
|
"__ansible_vault": "$ANSIBLE_VAULT;1.1;AES256\n34646264306632313333393636316562356435376162633631326264383934326565333633366238\n3863373264326461623132613931346165636465346337310a326434313830316337393263616439\n64653937313463396366633861363266633465663730303633323534363331316164623237363831\n3536333561393238370a313330316263373938326162386433313336613532653538376662306435\n3339\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"foo": {
|
||||||
|
"password": {
|
||||||
|
"__ansible_vault": "$ANSIBLE_VAULT;1.1;AES256\n34646264306632313333393636316562356435376162633631326264383934326565333633366238\n3863373264326461623132613931346165636465346337310a326434313830316337393263616439\n64653937313463396366633861363266633465663730303633323534363331316164623237363831\n3536333561393238370a313330316263373938326162386433313336613532653538376662306435\n3339\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
test/units/parsing/test_ajson.py
Normal file
22
test/units/parsing/test_ajson.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Copyright 2018, Matt Martz <matt@sivel.net>
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ansible.parsing.ajson import AnsibleJSONDecoder
|
||||||
|
from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
|
||||||
|
|
||||||
|
|
||||||
|
def test_AnsibleJSONDecoder_vault():
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), 'fixtures/ajson.json')) as f:
|
||||||
|
data = json.load(f, cls=AnsibleJSONDecoder)
|
||||||
|
|
||||||
|
assert isinstance(data['password'], AnsibleVaultEncryptedUnicode)
|
||||||
|
assert isinstance(data['bar']['baz'][0]['password'], AnsibleVaultEncryptedUnicode)
|
||||||
|
assert isinstance(data['foo']['password'], AnsibleVaultEncryptedUnicode)
|
Loading…
Add table
Add a link
Reference in a new issue