From 2f24eeb9d1247519a4c6f5acc543ecf4c0f3edfc Mon Sep 17 00:00:00 2001 From: nicholasmhughes Date: Thu, 28 Mar 2024 17:59:28 -0400 Subject: [PATCH] specify explicit kwargs for pillar data and item funcs --- salt/modules/pillar.py | 79 +++++++++++++++++--- salt/utils/args.py | 2 +- tests/pytests/integration/grains/__init__.py | 0 tests/pytests/unit/modules/test_pillar.py | 5 +- 4 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 tests/pytests/integration/grains/__init__.py diff --git a/salt/modules/pillar.py b/salt/modules/pillar.py index e78a7644a3f5..dbe75be88af1 100644 --- a/salt/modules/pillar.py +++ b/salt/modules/pillar.py @@ -242,7 +242,7 @@ def items(*args, pillar=None, pillar_enc=None, pillarenv=None, saltenv=None): """ # Preserve backwards compatibility if args: - return item(*args) + return item(*args, pillarenv=pillarenv, saltenv=saltenv) if pillarenv is None: if __opts__.get("pillarenv_from_saltenv", False): @@ -275,7 +275,56 @@ def items(*args, pillar=None, pillar_enc=None, pillarenv=None, saltenv=None): # Allow pillar.data to also be used to return pillar data -data = salt.utils.functools.alias_function(items, "data") +def data(*args, pillar=None, pillar_enc=None, pillarenv=None, saltenv=None): + """ + Calls the master for a fresh pillar, generates the pillar data on the + fly (same as :py:func:`items`) + + pillar + If specified, allows for a dictionary of pillar data to be made + available to pillar and ext_pillar rendering. these pillar variables + will also override any variables of the same name in pillar or + ext_pillar. + + pillar_enc + If specified, the data passed in the ``pillar`` argument will be passed + through this renderer to decrypt it. + + .. note:: + This will decrypt on the minion side, so the specified renderer + must be set up on the minion for this to work. Alternatively, + pillar data can be decrypted master-side. For more information, see + the :ref:`Pillar Encryption ` documentation. + Pillar data that is decrypted master-side, is not decrypted until + the end of pillar compilation though, so minion-side decryption + will be necessary if the encrypted pillar data must be made + available in an decrypted state pillar/ext_pillar rendering. + + pillarenv + Pass a specific pillar environment from which to compile pillar data. + If not specified, then the minion's :conf_minion:`pillarenv` option is + not used, and if that also is not specified then all configured pillar + environments will be merged into a single pillar dictionary and + returned. + + saltenv + Included only for compatibility with + :conf_minion:`pillarenv_from_saltenv`, and is otherwise ignored. + + CLI Examples: + + .. code-block:: bash + + salt '*' pillar.data + """ + + return items( + *args, + pillar=pillar, + pillar_enc=pillar_enc, + pillarenv=pillarenv, + saltenv=saltenv, + ) def _obfuscate_inner(var): @@ -294,7 +343,7 @@ def _obfuscate_inner(var): return f"<{var.__class__.__name__}>" -def obfuscate(*args, **kwargs): +def obfuscate(*args, pillar=None, pillar_enc=None, pillarenv=None, saltenv=None): """ .. versionadded:: 2015.8.0 @@ -321,7 +370,15 @@ def obfuscate(*args, **kwargs): salt '*' pillar.obfuscate """ - return _obfuscate_inner(items(*args, **kwargs)) + return _obfuscate_inner( + items( + *args, + pillar=pillar, + pillar_enc=pillar_enc, + pillarenv=pillarenv, + saltenv=saltenv, + ) + ) # naming chosen for consistency with grains.ls, although it breaks the short @@ -382,7 +439,7 @@ def ls(*args, pillar=None, pillar_enc=None, pillarenv=None, saltenv=None): ) -def item(*args, **kwargs): +def item(*args, default=None, delimiter=None, pillarenv=None, saltenv=None): """ .. versionadded:: 0.16.2 @@ -436,10 +493,12 @@ def item(*args, **kwargs): salt '*' pillar.item foo bar baz """ ret = {} - default = kwargs.get("default", "") - delimiter = kwargs.get("delimiter", DEFAULT_TARGET_DELIM) - pillarenv = kwargs.get("pillarenv", None) - saltenv = kwargs.get("saltenv", None) + + if default is None: + default = "" + + if delimiter is None: + delimiter = DEFAULT_TARGET_DELIM pillar_dict = ( __pillar__ @@ -450,7 +509,7 @@ def item(*args, **kwargs): try: for arg in args: ret[arg] = salt.utils.data.traverse_dict_and_list( - pillar_dict, arg, default, delimiter + data=pillar_dict, key=arg, default=default, delimiter=delimiter ) except KeyError: pass diff --git a/salt/utils/args.py b/salt/utils/args.py index 551099ce7b49..8a9b38eb1b08 100644 --- a/salt/utils/args.py +++ b/salt/utils/args.py @@ -252,7 +252,7 @@ def get_function_argspec(func, is_class_method=None): defaults = [] varargs = keywords = None for param in sig.parameters.values(): - if param.kind == param.POSITIONAL_OR_KEYWORD: + if param.kind in [param.POSITIONAL_OR_KEYWORD, param.KEYWORD_ONLY]: args.append(param.name) if param.default is not inspect._empty: defaults.append(param.default) diff --git a/tests/pytests/integration/grains/__init__.py b/tests/pytests/integration/grains/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/pytests/unit/modules/test_pillar.py b/tests/pytests/unit/modules/test_pillar.py index 3849aa591962..6acca56993c7 100644 --- a/tests/pytests/unit/modules/test_pillar.py +++ b/tests/pytests/unit/modules/test_pillar.py @@ -43,7 +43,10 @@ def test_obfuscate_with_kwargs(pillar_value): ) as pillar_items_mock: ret = pillarmod.obfuscate(saltenv="saltenv") # ensure the kwargs are passed along to pillar.items - assert call(saltenv="saltenv") in pillar_items_mock.mock_calls + assert ( + call(pillar=None, pillar_enc=None, pillarenv=None, saltenv="saltenv") + in pillar_items_mock.mock_calls + ) assert ret == dict(a="", b="")