fixes saltstack/salt#62983 add environment file serializer

This commit is contained in:
nicholasmhughes 2022-10-31 13:09:41 -04:00 committed by Megan Wilhite
parent c1c99cf5f3
commit b5749fc6d1
5 changed files with 127 additions and 0 deletions

1
changelog/62983.added Normal file
View file

@ -0,0 +1 @@
Add environment file serializer

View file

@ -11,6 +11,7 @@ serializer modules
:template: autosummary.rst.tmpl
configparser
envfile
json
msgpack
plist

View file

@ -0,0 +1,6 @@
salt.serializers.envfile
========================
.. automodule:: salt.serializers.envfile
:members:

View file

@ -0,0 +1,81 @@
"""
salt.serializers.envfile
~~~~~~~~~~~~~~~~~~~~~~~~
Implements environment file serializer.
"""
import salt.utils.platform
from salt.serializers import DeserializationError, SerializationError
from salt.utils.jinja import quote
from salt.utils.stringutils import dequote
__all__ = ["deserialize", "serialize", "available"]
available = True
def deserialize(stream_or_string, **options):
"""
Deserialize any string or stream like object into a Python data structure.
:param stream_or_string: stream or string to deserialize.
:param options: options given to the function
"""
try:
if not isinstance(stream_or_string, (bytes, str)):
stream_or_string = stream_or_string.read()
separator = options.get("separator", "=")
obj = {}
if isinstance(stream_or_string, bytes):
stream_or_string = stream_or_string.decode("utf-8")
for line in stream_or_string.splitlines():
key, val = line.split(separator, maxsplit=1)
if options.get("quoting") is False:
val = dequote(val)
obj[key] = val
except Exception as error: # pylint: disable=broad-except
raise DeserializationError(error)
return obj
def serialize(obj, **options):
"""
Serialize Python data to environment file.
:param obj: the data structure to serialize
:param options: options given to the function
"""
if not isinstance(obj, (dict, list, tuple, set)):
raise SerializationError("Input validation failed. Iterable required.")
if salt.utils.platform.is_windows():
linend = "\r\n"
else:
linend = "\n"
separator = options.get("separator", "=")
lines = []
try:
if isinstance(obj, dict):
for key, val in obj.items():
if options.get("quoting"):
val = quote(val)
lines.append(f"{key}{separator}{val}")
else:
for item in obj:
key, val = item
if options.get("quoting"):
val = quote(val)
lines.append(f"{key}{separator}{val}")
except Exception as error: # pylint: disable=broad-except
raise SerializationError(error)
return linend.join(lines)

View file

@ -5,6 +5,7 @@ import pytest
import yaml as _yaml
import salt.serializers.configparser as configparser
import salt.serializers.envfile as envfile
import salt.serializers.json as json
import salt.serializers.msgpack as msgpack
import salt.serializers.plist as plist
@ -397,3 +398,40 @@ def test_serialize_binary_plist():
deserialized = plist.deserialize(serialized)
assert deserialized == data, deserialized
def test_serialize_envfile():
data = {"foo": "bar baz"}
serialized = envfile.serialize(data)
assert serialized == "foo=bar baz", serialized
deserialized = envfile.deserialize(serialized)
assert deserialized == data, deserialized
def test_serialize_envfile_quoting():
data = {"foo": "bar baz"}
serialized = envfile.serialize(data, quoting=True)
assert serialized == "foo='bar baz'", serialized
deserialized = envfile.deserialize(serialized, quoting=False)
assert deserialized == data, deserialized
def test_serialize_envfile_separator():
data = {"foo": "bar baz"}
serialized = envfile.serialize(data, separator=" = ")
assert serialized == "foo = bar baz", serialized
deserialized = envfile.deserialize(serialized, separator=" = ")
assert deserialized == data, deserialized
def test_serialize_envfile_list_of_lists():
data = [["foo", "bar baz"], ["salt", "rocks"]]
expected = {"foo": "bar baz", "salt": "rocks"}
serialized = envfile.serialize(data)
assert serialized == "foo=bar baz\nsalt=rocks", serialized
deserialized = envfile.deserialize(serialized)
assert deserialized == expected, deserialized