File fix-state.orchestrate_single-to-not-pass-pillar-none.patch of Package salt

From 89fece2e17e7730acaf249030e9c1bad652fb8c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
 <psuarezhernandez@suse.com>
Date: Thu, 17 Feb 2022 15:11:16 +0000
Subject: [PATCH] Fix "state.orchestrate_single" to not pass
 pillar=None (3000) (#486)

* state.orchestrate_single does not pass pillar=None

Passing a pillar to state.single can results in state functions not
working when they don't accept a pillar keyword argument. One example
where this is the case is salt.wait_for_event. When no pillar is
provided, it does not need to be passed.

* Fix unit tests for 3002.2

Co-authored-by: Alexander Graul <agraul@suse.com>
---
 changelog/61092.fixed            |  3 +++
 salt/runners/state.py            | 11 ++++-----
 tests/unit/runners/test_state.py | 38 ++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 5 deletions(-)
 create mode 100644 changelog/61092.fixed
 create mode 100644 tests/unit/runners/test_state.py

diff --git a/changelog/61092.fixed b/changelog/61092.fixed
new file mode 100644
index 0000000000..6ca66839c9
--- /dev/null
+++ b/changelog/61092.fixed
@@ -0,0 +1,3 @@
+state.orchestrate_single only passes a pillar if it is set to the state
+function. This allows it to be used with state functions that don't accept a
+pillar keyword argument.
diff --git a/salt/runners/state.py b/salt/runners/state.py
index e7e61ec4da..29d659bbc5 100644
--- a/salt/runners/state.py
+++ b/salt/runners/state.py
@@ -152,10 +152,12 @@ def orchestrate_single(fun, name, test=None, queue=False, pillar=None, **kwargs)
 
         salt-run state.orchestrate_single fun=salt.wheel name=key.list_all
     '''
-    if pillar is not None and not isinstance(pillar, dict):
-        raise SaltInvocationError(
-            'Pillar data must be formatted as a dictionary'
-        )
+    if pillar is not None:
+        if isinstance(pillar, dict):
+            kwargs["pillar"] = pillar
+        else:
+            raise SaltInvocationError("Pillar data must be formatted as a dictionary")
+
     __opts__['file_client'] = 'local'
     minion = salt.minion.MasterMinion(__opts__)
     running = minion.functions['state.single'](
@@ -163,7 +165,6 @@ def orchestrate_single(fun, name, test=None, queue=False, pillar=None, **kwargs)
             name,
             test=None,
             queue=False,
-            pillar=pillar,
             **kwargs)
     ret = {minion.opts['id']: running}
     __jid_event__.fire_event({'data': ret, 'outputter': 'highstate'}, 'progress')
diff --git a/tests/unit/runners/test_state.py b/tests/unit/runners/test_state.py
new file mode 100644
index 0000000000..1de33ca85e
--- /dev/null
+++ b/tests/unit/runners/test_state.py
@@ -0,0 +1,38 @@
+from salt.runners import state as state_runner
+from tests.support.mixins import LoaderModuleMockMixin
+from tests.support.mock import Mock, patch
+from tests.support.unit import TestCase
+
+
+class StateRunnerTest(TestCase, LoaderModuleMockMixin):
+    def setup_loader_modules(self):
+        return {state_runner: {"__opts__": {}, "__jid_event__": Mock()}}
+
+    def test_orchestrate_single_passes_pillar(self):
+        """
+        test state.orchestrate_single passes given pillar to state.single
+        """
+        mock_master_minion = Mock()
+        mock_state_single = Mock()
+        mock_master_minion.functions = {"state.single": mock_state_single}
+        mock_master_minion.opts = {"id": "dummy"}
+        test_pillar = {"test_entry": "exists"}
+        with patch("salt.minion.MasterMinion", Mock(return_value=mock_master_minion)):
+            state_runner.orchestrate_single(
+                fun="pillar.get", name="test_entry", pillar=test_pillar
+            )
+            assert mock_state_single.call_args.kwargs["pillar"] == test_pillar
+
+    def test_orchestrate_single_does_not_pass_none_pillar(self):
+        """
+        test state.orchestrate_single does not pass pillar=None to state.single
+        """
+        mock_master_minion = Mock()
+        mock_state_single = Mock()
+        mock_master_minion.functions = {"state.single": mock_state_single}
+        mock_master_minion.opts = {"id": "dummy"}
+        with patch("salt.minion.MasterMinion", Mock(return_value=mock_master_minion)):
+            state_runner.orchestrate_single(
+                fun="pillar.get", name="test_entry", pillar=None
+            )
+            assert "pillar" not in mock_state_single.call_args.kwargs
-- 
2.35.1


openSUSE Build Service is sponsored by