Allow AnsibleVaultEncryptedUnicode to pass through exec_jsonrpc (#48306)

* Allow AnsibleVaultEncryptedUnicode to pass through exec_jsonrpc

* Add changelog

(cherry picked from commit f05979932b)

Conflicts:
	lib/ansible/module_utils/connection.py
pull/54704/head
Nathaniel Case 7 years ago committed by Toshio Kuratomi
parent 635ff3966f
commit fc2336aef2

@ -0,0 +1,4 @@
---
bugfixes:
- Use custom JSON encoder in conneciton.py so that ansible objects (AnsibleVaultEncryptedUnicode, for example)
can be sent to the persistent connection process

@ -33,9 +33,11 @@ import socket
import struct
import traceback
import uuid
from datetime import date, datetime
from functools import partial
from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.common._collections_compat import Mapping
from ansible.module_utils.six import iteritems
from ansible.module_utils.six.moves import cPickle
@ -141,7 +143,14 @@ class Connection(object):
'\nSee the socket_path issue catergory in Network Debug and Troubleshooting Guide')
try:
data = json.dumps(req)
data = json.dumps(req, cls=AnsibleJSONEncoder)
except TypeError as exc:
raise ConnectionError(
"Failed to encode some variables as JSON for communication with ansible-connection. "
"The original exception was: %s" % to_text(exc)
)
try:
out = self.send(data)
response = json.loads(out)
@ -189,3 +198,29 @@ class Connection(object):
sf.close()
return to_text(response, errors='surrogate_or_strict')
# NOTE: This is a modified copy of the class in parsing.ajson to get around not
# being able to import that directly, nor some of the type classes
class AnsibleJSONEncoder(json.JSONEncoder):
'''
Simple encoder class to deal with JSON encoding of Ansible internal types
'''
def default(self, o):
if type(o).__name__ == 'AnsibleVaultEncryptedUnicode':
# vault object
value = {'__ansible_vault': to_text(o._ciphertext, errors='surrogate_or_strict', nonstring='strict')}
elif type(o).__name__ == 'AnsibleUnsafe':
# unsafe object
value = {'__ansible_unsafe': to_text(o, errors='surrogate_or_strict', nonstring='strict')}
elif isinstance(o, Mapping):
# hostvars and other objects
value = dict(o)
elif isinstance(o, (date, datetime)):
# date object
value = o.isoformat()
else:
# use default encoder
value = super(AnsibleJSONEncoder, self).default(o)
return value

Loading…
Cancel
Save