mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
feat(macdefaults): Add basic support for array-add and dict-add
This commit is contained in:
parent
6e51f3b755
commit
aaba6250c0
4 changed files with 437 additions and 108 deletions
|
@ -1,11 +1,11 @@
|
|||
"""
|
||||
Set defaults on macOS.
|
||||
Set defaults settings on macOS.
|
||||
|
||||
This module uses defaults cli under the hood to read and write defaults on macOS.
|
||||
|
||||
So the module is limited to the capabilities of the defaults command.
|
||||
Thus, the module is limited to the capabilities of the defaults command.
|
||||
|
||||
Read macOS defaults help page for more information on the defaults command.
|
||||
Read macOS defaults help page for more information on defaults command.
|
||||
|
||||
"""
|
||||
|
||||
|
@ -33,11 +33,11 @@ def __virtual__():
|
|||
|
||||
def write(domain, key, value, vtype=None, user=None, type=None):
|
||||
"""
|
||||
Write a default to the system.
|
||||
Write a default to the system
|
||||
|
||||
Limitations:
|
||||
- There is no multi-level support for arrays and dictionaries.
|
||||
- Internal values types for arrays and dictionaries cannot be specified.
|
||||
- There is no multi-level support for arrays and dictionaries
|
||||
- Internal values types for arrays and dictionaries cannot be specified
|
||||
|
||||
CLI Example:
|
||||
|
||||
|
@ -45,28 +45,28 @@ def write(domain, key, value, vtype=None, user=None, type=None):
|
|||
|
||||
salt '*' macdefaults.write com.apple.CrashReporter DialogType Server
|
||||
|
||||
salt '*' macdefaults.write NSGlobalDomain ApplePersistence True type=bool
|
||||
salt '*' macdefaults.write NSGlobalDomain ApplePersistence True vtype=bool
|
||||
|
||||
domain
|
||||
The name of the domain to write to.
|
||||
The name of the domain to write to
|
||||
|
||||
key
|
||||
The key of the given domain to write to.
|
||||
The key of the given domain to write to
|
||||
|
||||
value
|
||||
The value to write to the given key.
|
||||
The value to write to the given key
|
||||
|
||||
vtype
|
||||
The type of value to be written, valid types are string, data, int[eger],
|
||||
float, bool[ean], date, array, array-add, dict, dict-add
|
||||
|
||||
type
|
||||
Deprecated! Use vtype instead.
|
||||
type collides with Python's built-in type() function.
|
||||
This parameter will be removed in 3009.
|
||||
Deprecated! Use vtype instead
|
||||
type collides with Python's built-in type() function
|
||||
This parameter will be removed in 3009
|
||||
|
||||
user
|
||||
The user to write the defaults to.
|
||||
The user to write the defaults to
|
||||
|
||||
"""
|
||||
if type is not None:
|
||||
|
@ -95,7 +95,7 @@ def write(domain, key, value, vtype=None, user=None, type=None):
|
|||
elif not isinstance(value, list):
|
||||
raise ValueError("Value must be a list, dict, int, float, bool, or string")
|
||||
|
||||
# Quote values that are not integers or floats
|
||||
# Quote values that are neither integers nor floats
|
||||
value = map(lambda v: str(v) if isinstance(v, (int, float)) else f'"{v}"', value)
|
||||
|
||||
cmd = f'write "{domain}" "{key}" -{vtype} {" ".join(value)}'
|
||||
|
@ -169,25 +169,25 @@ def delete(domain, key, user=None):
|
|||
|
||||
def read_type(domain, key, user=None):
|
||||
"""
|
||||
Read the type of the given type.
|
||||
If the given key is not found, then return None.
|
||||
Read a default type from the system
|
||||
If the key is not found, None is returned.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' macdefaults.read-type com.apple.CrashReporter DialogType
|
||||
salt '*' macdefaults.read_type com.apple.CrashReporter DialogType
|
||||
|
||||
salt '*' macdefaults.read_type NSGlobalDomain ApplePersistence
|
||||
|
||||
domain
|
||||
The name of the domain to read from.
|
||||
The name of the domain to read from
|
||||
|
||||
key
|
||||
The key of the given domain to read the type of.
|
||||
The key of the given domain to read the type of
|
||||
|
||||
user
|
||||
The user to read the defaults as.
|
||||
The user to read the defaults as
|
||||
|
||||
"""
|
||||
cmd = f'read-type "{domain}" "{key}"'
|
||||
|
@ -203,23 +203,13 @@ def read_type(domain, key, user=None):
|
|||
|
||||
def _default_to_python(value, vtype=None):
|
||||
"""
|
||||
Cast a value returned by defaults in vytpe to Python type.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' macdefaults.cast_value_to_type "1" int
|
||||
|
||||
salt '*' macdefaults.cast_value_to_type "1.0" float
|
||||
|
||||
salt '*' macdefaults.cast_value_to_type "TRUE" bool
|
||||
Cast the value returned by the defaults command in vytpe to Python type
|
||||
|
||||
value
|
||||
The value to cast.
|
||||
The value to cast
|
||||
|
||||
vtype
|
||||
The type to cast the value to.
|
||||
The type to cast the value to
|
||||
|
||||
"""
|
||||
if vtype in ["integer", "int"]:
|
||||
|
@ -238,10 +228,10 @@ def _default_to_python(value, vtype=None):
|
|||
def _parse_defaults_array(value):
|
||||
"""
|
||||
Parse an array from a string returned by `defaults read`
|
||||
and returns the array content as a list.
|
||||
and returns the array content as a list
|
||||
|
||||
value
|
||||
A multiline string with the array content, including the surrounding parenthesis.
|
||||
A multiline string with the array content, including the surrounding parenthesis
|
||||
|
||||
"""
|
||||
lines = value.splitlines()
|
||||
|
@ -268,12 +258,11 @@ def _parse_defaults_array(value):
|
|||
def _parse_defaults_dict(value):
|
||||
"""
|
||||
Parse a dictionary from a string returned by `defaults read`
|
||||
and returns the dictionary content as a Python dictionary
|
||||
|
||||
value (str):
|
||||
A multiline string with the dictionary content, including the surrounding curly braces.
|
||||
A multiline string with the dictionary content, including the surrounding curly braces
|
||||
|
||||
Returns:
|
||||
dict: The dictionary content as a Python dictionary.
|
||||
"""
|
||||
lines = value.splitlines()
|
||||
if not re.match(r"\s*\{", lines[0]) or not re.match(r"\s*\}", lines[-1]):
|
||||
|
@ -294,10 +283,10 @@ def _parse_defaults_dict(value):
|
|||
|
||||
def _convert_to_number_if_possible(value):
|
||||
"""
|
||||
Convert a string to a number if possible.
|
||||
Convert a string to a number if possible
|
||||
|
||||
value
|
||||
The string to convert.
|
||||
The string to convert
|
||||
|
||||
"""
|
||||
try:
|
||||
|
@ -311,15 +300,15 @@ def _convert_to_number_if_possible(value):
|
|||
|
||||
def _convert_to_defaults_boolean(value):
|
||||
"""
|
||||
Convert a boolean to a string that can be used with the defaults command.
|
||||
Convert a boolean to a string that can be used with the defaults command
|
||||
|
||||
value
|
||||
The boolean value to convert.
|
||||
The boolean value to convert
|
||||
|
||||
"""
|
||||
if value is True:
|
||||
if value in (True, 1):
|
||||
return "TRUE"
|
||||
if value is False:
|
||||
if value in (False, 0):
|
||||
return "FALSE"
|
||||
|
||||
BOOLEAN_ALLOWED_VALUES = ["TRUE", "YES", "FALSE", "NO"]
|
||||
|
@ -333,14 +322,14 @@ def _convert_to_defaults_boolean(value):
|
|||
|
||||
def _run_defaults_cmd(action, runas=None):
|
||||
"""
|
||||
Run a 'defaults' command.
|
||||
Run the 'defaults' command with the given action
|
||||
|
||||
action
|
||||
The action to perform with all of its parameters.
|
||||
The action to perform with all of its parameters
|
||||
Example: 'write com.apple.CrashReporter DialogType "Server"'
|
||||
|
||||
runas
|
||||
The user to run the command as.
|
||||
The user to run the command as
|
||||
|
||||
"""
|
||||
ret = __salt__["cmd.run_all"](f"defaults {action}", runas=runas)
|
||||
|
@ -354,10 +343,10 @@ def _run_defaults_cmd(action, runas=None):
|
|||
|
||||
def _remove_timestamp(text):
|
||||
"""
|
||||
Remove the timestamp from the output of the defaults command.
|
||||
Remove the timestamp from the output of the defaults command if found
|
||||
|
||||
text
|
||||
The text to remove the timestamp from.
|
||||
The text to remove the timestamp from
|
||||
|
||||
"""
|
||||
pattern = r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d{3})?\s+defaults\[\d+\:\d+\]"
|
||||
|
|
|
@ -4,13 +4,8 @@ Writing/reading defaults from a macOS minion
|
|||
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
import salt.utils.platform
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = "macdefaults"
|
||||
|
||||
|
||||
|
@ -43,14 +38,13 @@ def write(name, domain, value, vtype="string", user=None):
|
|||
user
|
||||
The user to write the defaults to
|
||||
|
||||
|
||||
"""
|
||||
ret = {"name": name, "result": True, "comment": "", "changes": {}}
|
||||
|
||||
current_value = __salt__["macdefaults.read"](domain, name, user)
|
||||
value = _cast_value(value, vtype)
|
||||
|
||||
if _compare_values(value, current_value, strict=re.match(r"-add$", vtype) is None):
|
||||
if _compare_values(value, current_value, vtype):
|
||||
ret["comment"] += f"{domain} {name} is already set to {value}"
|
||||
else:
|
||||
out = __salt__["macdefaults.write"](domain, name, value, vtype, user)
|
||||
|
@ -76,7 +70,6 @@ def absent(name, domain, user=None):
|
|||
user
|
||||
The user to write the defaults to
|
||||
|
||||
|
||||
"""
|
||||
ret = {"name": name, "result": True, "comment": "", "changes": {}}
|
||||
|
||||
|
@ -90,9 +83,9 @@ def absent(name, domain, user=None):
|
|||
return ret
|
||||
|
||||
|
||||
def _compare_values(new, current, strict=True):
|
||||
def _compare_values(new, current, vtype):
|
||||
"""
|
||||
Compare two values
|
||||
Compare two values based on their type
|
||||
|
||||
new
|
||||
The new value to compare
|
||||
|
@ -100,24 +93,73 @@ def _compare_values(new, current, strict=True):
|
|||
current
|
||||
The current value to compare
|
||||
|
||||
strict
|
||||
If True, the values must be exactly the same, if False, the new value
|
||||
must be in the current value
|
||||
vtype
|
||||
The type of default value to be compared
|
||||
|
||||
"""
|
||||
if strict:
|
||||
return new == current
|
||||
return new in current
|
||||
if vtype == "array-add":
|
||||
return _is_subarray(new, current)
|
||||
if vtype == "dict-add":
|
||||
return all([key in current and new[key] == current[key] for key in new.keys()])
|
||||
|
||||
return new == current
|
||||
|
||||
|
||||
def _is_subarray(new, current):
|
||||
"""
|
||||
Check if new is a subarray of current array.
|
||||
|
||||
This method does not check only whether all elements in new array
|
||||
are present in current array, but also whether the elements are in
|
||||
the same order.
|
||||
|
||||
new
|
||||
The new array to compare
|
||||
|
||||
current
|
||||
The current array to compare
|
||||
|
||||
"""
|
||||
current_len = len(current)
|
||||
new_len = len(new)
|
||||
|
||||
if new_len == 0:
|
||||
return True
|
||||
if new_len > current_len:
|
||||
return False
|
||||
|
||||
for i in range(current_len - new_len + 1):
|
||||
# Check if the new array is found at this position
|
||||
if current[i : i + new_len] == new:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _cast_value(value, vtype):
|
||||
"""
|
||||
Cast the given macOS default value to Python type
|
||||
|
||||
value
|
||||
The value to cast from macOS default
|
||||
|
||||
vtype
|
||||
The type to cast the value from
|
||||
|
||||
"""
|
||||
|
||||
def safe_cast(val, to_type, default=None):
|
||||
"""
|
||||
Auxiliary function to safely cast a value to a given type
|
||||
|
||||
"""
|
||||
try:
|
||||
return to_type(val)
|
||||
except ValueError:
|
||||
return default
|
||||
|
||||
if vtype in ("bool", "boolean"):
|
||||
if value not in [True, "TRUE", "YES", False, "FALSE", "NO"]:
|
||||
if value not in [True, 1, "TRUE", "YES", False, 0, "FALSE", "NO"]:
|
||||
raise ValueError(f"Invalid value for boolean: {value}")
|
||||
return value in [True, "TRUE", "YES"]
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ def test_write_default():
|
|||
)
|
||||
|
||||
|
||||
def test_write_with_user():
|
||||
def test_write_default_with_user():
|
||||
"""
|
||||
Test writing a default setting with a specific user
|
||||
"""
|
||||
|
@ -67,9 +67,9 @@ def test_write_with_user():
|
|||
)
|
||||
|
||||
|
||||
def test_write_true_boolean():
|
||||
def test_write_default_true_boolean():
|
||||
"""
|
||||
Test writing a True boolean setting
|
||||
Test writing a default True boolean setting
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
@ -80,9 +80,9 @@ def test_write_true_boolean():
|
|||
)
|
||||
|
||||
|
||||
def test_write_false_bool():
|
||||
def test_write_default_false_bool():
|
||||
"""
|
||||
Test writing a False boolean setting
|
||||
Test writing a default False boolean setting
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
@ -93,9 +93,9 @@ def test_write_false_bool():
|
|||
)
|
||||
|
||||
|
||||
def test_write_int():
|
||||
def test_write_default_int():
|
||||
"""
|
||||
Test writing an int setting
|
||||
Test writing a default int setting
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
@ -106,9 +106,9 @@ def test_write_int():
|
|||
)
|
||||
|
||||
|
||||
def test_write_integer():
|
||||
def test_write_default_integer():
|
||||
"""
|
||||
Test writing an integer setting
|
||||
Test writing a default integer setting
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
@ -119,9 +119,9 @@ def test_write_integer():
|
|||
)
|
||||
|
||||
|
||||
def test_write_float():
|
||||
def test_write_default_float():
|
||||
"""
|
||||
Test writing a float setting
|
||||
Test writing a default float setting
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
@ -132,9 +132,9 @@ def test_write_float():
|
|||
)
|
||||
|
||||
|
||||
def test_write_array():
|
||||
def test_write_default_array():
|
||||
"""
|
||||
Test writing an array setting
|
||||
Test writing a default array setting
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
@ -147,9 +147,9 @@ def test_write_array():
|
|||
)
|
||||
|
||||
|
||||
def test_write_dictionary():
|
||||
def test_write_default_dictionary():
|
||||
"""
|
||||
Test writing a dictionary setting
|
||||
Test writing a default dictionary setting
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
@ -186,7 +186,7 @@ def test_read_default():
|
|||
assert result == "Server"
|
||||
|
||||
|
||||
def test_read_with_user():
|
||||
def test_read_default_with_user():
|
||||
"""
|
||||
Test reading a default setting as a specific user
|
||||
"""
|
||||
|
@ -210,9 +210,9 @@ def test_read_with_user():
|
|||
assert result == "Server"
|
||||
|
||||
|
||||
def test_read_integer():
|
||||
def test_read_default_integer():
|
||||
"""
|
||||
Test reading an integer setting
|
||||
Test reading a default integer setting
|
||||
"""
|
||||
|
||||
def custom_run_defaults_cmd(action, runas=None):
|
||||
|
@ -234,9 +234,9 @@ def test_read_integer():
|
|||
assert result == 12
|
||||
|
||||
|
||||
def test_read_float():
|
||||
def test_read_default_float():
|
||||
"""
|
||||
Test reading a float setting
|
||||
Test reading a default float setting
|
||||
"""
|
||||
|
||||
def custom_run_defaults_cmd(action, runas=None):
|
||||
|
@ -258,15 +258,15 @@ def test_read_float():
|
|||
assert result == 0.85
|
||||
|
||||
|
||||
def test_read_array():
|
||||
def test_read_default_array():
|
||||
"""
|
||||
Test reading an array setting
|
||||
Test reading a default array setting
|
||||
"""
|
||||
|
||||
defaults_output = """(
|
||||
element 1,
|
||||
element 2,
|
||||
0.1,
|
||||
0.1000,
|
||||
1
|
||||
)"""
|
||||
|
||||
|
@ -289,14 +289,16 @@ def test_read_array():
|
|||
assert result == ["element 1", "element 2", 0.1, 1]
|
||||
|
||||
|
||||
def test_read_dictionary():
|
||||
def test_read_default_dictionary():
|
||||
"""
|
||||
Test reading a dictionary setting
|
||||
Test reading a default dictionary setting
|
||||
"""
|
||||
|
||||
defaults_output = """{
|
||||
keyCode = 36;
|
||||
modifierFlags = 786432;
|
||||
anotherKey = "another value with spaces";
|
||||
floatNumber = 0.8500;
|
||||
}"""
|
||||
|
||||
def custom_run_defaults_cmd(action, runas=None):
|
||||
|
@ -315,7 +317,12 @@ def test_read_dictionary():
|
|||
call('read-type "com.apple.CrashReporter" "Crash"', runas=None),
|
||||
]
|
||||
)
|
||||
assert result == {"keyCode": 36, "modifierFlags": 786432}
|
||||
assert result == {
|
||||
"keyCode": 36,
|
||||
"modifierFlags": 786432,
|
||||
"anotherKey": "another value with spaces",
|
||||
"floatNumber": 0.85,
|
||||
}
|
||||
|
||||
|
||||
def test_delete_default():
|
||||
|
@ -331,9 +338,9 @@ def test_delete_default():
|
|||
)
|
||||
|
||||
|
||||
def test_delete_with_user():
|
||||
def test_delete_default_with_user():
|
||||
"""
|
||||
Test delete a setting as a specific user
|
||||
Test delete a default setting as a specific user
|
||||
"""
|
||||
mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch("salt.modules.macdefaults._run_defaults_cmd", mock):
|
||||
|
|
|
@ -9,7 +9,7 @@ def configure_loader_modules():
|
|||
return {macdefaults: {}}
|
||||
|
||||
|
||||
def test_write():
|
||||
def test_write_default():
|
||||
"""
|
||||
Test writing a default setting
|
||||
"""
|
||||
|
@ -34,7 +34,7 @@ def test_write():
|
|||
assert out == expected
|
||||
|
||||
|
||||
def test_write_set():
|
||||
def test_write_default_already_set():
|
||||
"""
|
||||
Test writing a default setting that is already set
|
||||
"""
|
||||
|
@ -57,7 +57,7 @@ def test_write_set():
|
|||
assert out == expected
|
||||
|
||||
|
||||
def test_write_boolean():
|
||||
def test_write_default_boolean():
|
||||
"""
|
||||
Test writing a default setting with a boolean
|
||||
"""
|
||||
|
@ -68,7 +68,7 @@ def test_write_boolean():
|
|||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value="0")
|
||||
read_mock = MagicMock(return_value=False)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
|
@ -82,9 +82,9 @@ def test_write_boolean():
|
|||
assert out == expected
|
||||
|
||||
|
||||
def test_write_boolean_match():
|
||||
def test_write_default_boolean_already_set():
|
||||
"""
|
||||
Test writing a default setting with a boolean that is already set to the same value
|
||||
Test writing a default setting with a boolean that is already set
|
||||
"""
|
||||
expected = {
|
||||
"changes": {},
|
||||
|
@ -105,7 +105,7 @@ def test_write_boolean_match():
|
|||
assert out == expected
|
||||
|
||||
|
||||
def test_write_integer():
|
||||
def test_write_default_integer():
|
||||
"""
|
||||
Test writing a default setting with a integer
|
||||
"""
|
||||
|
@ -116,7 +116,7 @@ def test_write_integer():
|
|||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value="99")
|
||||
read_mock = MagicMock(return_value=99)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
|
@ -130,9 +130,9 @@ def test_write_integer():
|
|||
assert out == expected
|
||||
|
||||
|
||||
def test_write_integer_match():
|
||||
def test_write_default_integer_already_set():
|
||||
"""
|
||||
Test writing a default setting with a integer that is already set to the same value
|
||||
Test writing a default setting with an integer that is already set
|
||||
"""
|
||||
expected = {
|
||||
"changes": {},
|
||||
|
@ -153,7 +153,298 @@ def test_write_integer_match():
|
|||
assert out == expected
|
||||
|
||||
|
||||
def test_absent_already():
|
||||
def test_write_default_float():
|
||||
"""
|
||||
Test writing a default setting with a float
|
||||
"""
|
||||
expected = {
|
||||
"changes": {"written": "com.apple.something Key is set to 0.865"},
|
||||
"comment": "",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=0.4)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write("Key", "com.apple.something", 0.865, vtype="float")
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
write_mock.assert_called_once_with(
|
||||
"com.apple.something", "Key", 0.865, "float", None
|
||||
)
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_float_already_set():
|
||||
"""
|
||||
Test writing a default setting with a float that is already set_default
|
||||
"""
|
||||
expected = {
|
||||
"changes": {},
|
||||
"comment": "com.apple.something Key is already set to 0.865",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=0.865)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write("Key", "com.apple.something", 0.86500, vtype="float")
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
assert not write_mock.called
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_array():
|
||||
"""
|
||||
Test writing a default setting with an array
|
||||
"""
|
||||
value = ["a", 1, 0.5, True]
|
||||
expected = {
|
||||
"changes": {"written": f"com.apple.something Key is set to {value}"},
|
||||
"comment": "",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=None)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write("Key", "com.apple.something", value, vtype="array")
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
write_mock.assert_called_once_with(
|
||||
"com.apple.something", "Key", value, "array", None
|
||||
)
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_array_already_set():
|
||||
"""
|
||||
Test writing a default setting with an array that is already set
|
||||
"""
|
||||
value = ["a", 1, 0.5, True]
|
||||
expected = {
|
||||
"changes": {},
|
||||
"comment": f"com.apple.something Key is already set to {value}",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=value)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write("Key", "com.apple.something", value, vtype="array")
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
assert not write_mock.called
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_array_add():
|
||||
"""
|
||||
Test writing a default setting adding an array to another
|
||||
"""
|
||||
write_value = ["a", 1]
|
||||
read_value = ["b", 2]
|
||||
expected = {
|
||||
"changes": {"written": f"com.apple.something Key is set to {write_value}"},
|
||||
"comment": "",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=read_value)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write(
|
||||
"Key", "com.apple.something", write_value, vtype="array-add"
|
||||
)
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
write_mock.assert_called_once_with(
|
||||
"com.apple.something", "Key", write_value, "array-add", None
|
||||
)
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_array_add_already_set_distinct_order():
|
||||
"""
|
||||
Test writing a default setting adding an array to another that is already set
|
||||
The new array is in a different order than the existing one
|
||||
"""
|
||||
write_value = ["a", 1]
|
||||
read_value = ["b", 1, "a", 2]
|
||||
expected = {
|
||||
"changes": {"written": f"com.apple.something Key is set to {write_value}"},
|
||||
"comment": "",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=read_value)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write(
|
||||
"Key", "com.apple.something", write_value, vtype="array-add"
|
||||
)
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
write_mock.assert_called_once_with(
|
||||
"com.apple.something", "Key", write_value, "array-add", None
|
||||
)
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_array_add_already_set_same_order():
|
||||
"""
|
||||
Test writing a default setting adding an array to another that is already set
|
||||
The new array is already in the same order as the existing one
|
||||
"""
|
||||
write_value = ["a", 1]
|
||||
read_value = ["b", "a", 1, 2]
|
||||
expected = {
|
||||
"changes": {},
|
||||
"comment": f"com.apple.something Key is already set to {write_value}",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=read_value)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write(
|
||||
"Key", "com.apple.something", write_value, vtype="array-add"
|
||||
)
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
assert not write_mock.called
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_dict():
|
||||
"""
|
||||
Test writing a default setting with a dictionary
|
||||
"""
|
||||
value = {"string": "bar", "integer": 1, "float": 0.5, "boolean": True}
|
||||
expected = {
|
||||
"changes": {"written": f"com.apple.something Key is set to {value}"},
|
||||
"comment": "",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=None)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write("Key", "com.apple.something", value, vtype="dict")
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
write_mock.assert_called_once_with(
|
||||
"com.apple.something", "Key", value, "dict", None
|
||||
)
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_dict_already_set():
|
||||
"""
|
||||
Test writing a default setting with a dictionary that is already set
|
||||
"""
|
||||
value = {"string": "bar", "integer": 1, "float": 0.5, "boolean": True}
|
||||
expected = {
|
||||
"changes": {},
|
||||
"comment": f"com.apple.something Key is already set to {value}",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=value)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write("Key", "com.apple.something", value, vtype="dict")
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
assert not write_mock.called
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_dict_add():
|
||||
"""
|
||||
Test writing a default setting adding elements to a dictionary
|
||||
"""
|
||||
write_value = {"string": "bar", "integer": 1}
|
||||
read_value = {"integer": 1, "float": 0.5, "boolean": True}
|
||||
expected = {
|
||||
"changes": {"written": f"com.apple.something Key is set to {write_value}"},
|
||||
"comment": "",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=read_value)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write(
|
||||
"Key", "com.apple.something", write_value, vtype="dict-add"
|
||||
)
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
write_mock.assert_called_once_with(
|
||||
"com.apple.something", "Key", write_value, "dict-add", None
|
||||
)
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_write_default_dict_add_already_set():
|
||||
"""
|
||||
Test writing a default setting adding elements to a dictionary that is already set
|
||||
"""
|
||||
write_value = {"string": "bar", "integer": 1}
|
||||
read_value = {"string": "bar", "integer": 1, "float": 0.5, "boolean": True}
|
||||
expected = {
|
||||
"changes": {},
|
||||
"comment": f"com.apple.something Key is already set to {write_value}",
|
||||
"name": "Key",
|
||||
"result": True,
|
||||
}
|
||||
|
||||
read_mock = MagicMock(return_value=read_value)
|
||||
write_mock = MagicMock(return_value={"retcode": 0})
|
||||
with patch.dict(
|
||||
macdefaults.__salt__,
|
||||
{"macdefaults.read": read_mock, "macdefaults.write": write_mock},
|
||||
):
|
||||
out = macdefaults.write(
|
||||
"Key", "com.apple.something", write_value, vtype="dict-add"
|
||||
)
|
||||
read_mock.assert_called_once_with("com.apple.something", "Key", None)
|
||||
assert not write_mock.called
|
||||
assert out == expected
|
||||
|
||||
|
||||
def test_absent_default_already():
|
||||
"""
|
||||
Test ensuring non-existent defaults value is absent
|
||||
"""
|
||||
|
@ -171,9 +462,9 @@ def test_absent_already():
|
|||
assert out == expected
|
||||
|
||||
|
||||
def test_absent_deleting_existing():
|
||||
def test_absent_default_deleting_existing():
|
||||
"""
|
||||
Test removing an existing value
|
||||
Test removing an existing default value
|
||||
"""
|
||||
expected = {
|
||||
"changes": {"absent": "com.apple.something Key is now absent"},
|
||||
|
|
Loading…
Add table
Reference in a new issue