146 lines
5.0 KiB
Diff
146 lines
5.0 KiB
Diff
|
From 7ab208fd2d23eaa582cdbba912d4538d8c87e5f4 Mon Sep 17 00:00:00 2001
|
||
|
From: Victor Zhestkov <vzhestkov@suse.com>
|
||
|
Date: Mon, 2 Oct 2023 13:24:15 +0200
|
||
|
Subject: [PATCH] Implement the calling for batch async from the salt
|
||
|
CLI
|
||
|
|
||
|
* Implement calling batch async with salt CLI
|
||
|
|
||
|
* Add the test for calling batch async with salt CLI
|
||
|
---
|
||
|
salt/cli/salt.py | 53 ++++++++++++++++++++++++++++-
|
||
|
tests/pytests/unit/cli/test_salt.py | 50 +++++++++++++++++++++++++++
|
||
|
2 files changed, 102 insertions(+), 1 deletion(-)
|
||
|
create mode 100644 tests/pytests/unit/cli/test_salt.py
|
||
|
|
||
|
diff --git a/salt/cli/salt.py b/salt/cli/salt.py
|
||
|
index f90057f668..e19cfa5ce6 100644
|
||
|
--- a/salt/cli/salt.py
|
||
|
+++ b/salt/cli/salt.py
|
||
|
@@ -47,7 +47,12 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
|
||
|
self.exit(2, "{}\n".format(exc))
|
||
|
return
|
||
|
|
||
|
- if self.options.batch or self.options.static:
|
||
|
+ if self.options.batch and self.config["async"]:
|
||
|
+ # _run_batch_async() will just return the jid and exit
|
||
|
+ # Execution will not continue past this point
|
||
|
+ # in batch async mode. Batch async is handled by the master.
|
||
|
+ self._run_batch_async()
|
||
|
+ elif self.options.batch or self.options.static:
|
||
|
# _run_batch() will handle all output and
|
||
|
# exit with the appropriate error condition
|
||
|
# Execution will not continue past this point
|
||
|
@@ -296,6 +301,52 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
|
||
|
retcode = job_retcode
|
||
|
sys.exit(retcode)
|
||
|
|
||
|
+ def _run_batch_async(self):
|
||
|
+ kwargs = {
|
||
|
+ "tgt": self.config["tgt"],
|
||
|
+ "fun": self.config["fun"],
|
||
|
+ "arg": self.config["arg"],
|
||
|
+ "timeout": self.options.timeout,
|
||
|
+ "show_timeout": self.options.show_timeout,
|
||
|
+ "show_jid": self.options.show_jid,
|
||
|
+ "batch": self.config["batch"],
|
||
|
+ }
|
||
|
+ tgt = kwargs.pop("tgt", "")
|
||
|
+ fun = kwargs.pop("fun", "")
|
||
|
+
|
||
|
+ if self.config.get("eauth", ""):
|
||
|
+ kwargs.update(
|
||
|
+ {
|
||
|
+ "eauth": self.config["eauth"],
|
||
|
+ }
|
||
|
+ )
|
||
|
+ for opt in ("username", "password"):
|
||
|
+ if opt in self.config:
|
||
|
+ kwargs[opt] = self.config[opt]
|
||
|
+
|
||
|
+ try:
|
||
|
+ ret = self.local_client.run_job(tgt, fun, **kwargs)
|
||
|
+ except (
|
||
|
+ AuthenticationError,
|
||
|
+ AuthorizationError,
|
||
|
+ SaltInvocationError,
|
||
|
+ EauthAuthenticationError,
|
||
|
+ SaltClientError,
|
||
|
+ ) as exc:
|
||
|
+ ret = str(exc)
|
||
|
+ self.exit(2, "ERROR: {}\n".format(exc))
|
||
|
+ if "jid" in ret and "error" not in ret:
|
||
|
+ salt.utils.stringutils.print_cli(
|
||
|
+ "Executed command with job ID: {}".format(ret["jid"])
|
||
|
+ )
|
||
|
+ else:
|
||
|
+ self._output_ret(ret, self.config.get("output", "nested"))
|
||
|
+
|
||
|
+ if "error" in ret:
|
||
|
+ sys.exit(1)
|
||
|
+
|
||
|
+ sys.exit(0)
|
||
|
+
|
||
|
def _print_errors_summary(self, errors):
|
||
|
if errors:
|
||
|
salt.utils.stringutils.print_cli("\n")
|
||
|
diff --git a/tests/pytests/unit/cli/test_salt.py b/tests/pytests/unit/cli/test_salt.py
|
||
|
new file mode 100644
|
||
|
index 0000000000..d9f4b5b097
|
||
|
--- /dev/null
|
||
|
+++ b/tests/pytests/unit/cli/test_salt.py
|
||
|
@@ -0,0 +1,50 @@
|
||
|
+import pytest
|
||
|
+
|
||
|
+from tests.support.mock import MagicMock, patch
|
||
|
+
|
||
|
+
|
||
|
+def test_saltcmd_batch_async_call():
|
||
|
+ """
|
||
|
+ Test calling batch async with salt CLI
|
||
|
+ """
|
||
|
+ import salt.cli.salt
|
||
|
+
|
||
|
+ local_client = MagicMock()
|
||
|
+ local_client.run_job = MagicMock(return_value={"jid": 123456})
|
||
|
+ with pytest.raises(SystemExit) as exit_info, patch(
|
||
|
+ "sys.argv",
|
||
|
+ [
|
||
|
+ "salt",
|
||
|
+ "--batch=10",
|
||
|
+ "--async",
|
||
|
+ "*",
|
||
|
+ "test.arg",
|
||
|
+ "arg1",
|
||
|
+ "arg2",
|
||
|
+ "kwarg1=val1",
|
||
|
+ ],
|
||
|
+ ), patch("salt.cli.salt.SaltCMD.process_config_dir", MagicMock), patch(
|
||
|
+ "salt.output.display_output", MagicMock()
|
||
|
+ ), patch(
|
||
|
+ "salt.client.get_local_client", return_value=local_client
|
||
|
+ ), patch(
|
||
|
+ "salt.utils.stringutils.print_cli", MagicMock()
|
||
|
+ ) as print_cli:
|
||
|
+ salt_cmd = salt.cli.salt.SaltCMD()
|
||
|
+ salt_cmd.config = {
|
||
|
+ "async": True,
|
||
|
+ "batch": 10,
|
||
|
+ "tgt": "*",
|
||
|
+ "fun": "test.arg",
|
||
|
+ "arg": ["arg1", "arg2", {"__kwarg__": True, "kwarg1": "val1"}],
|
||
|
+ }
|
||
|
+ salt_cmd._mixin_after_parsed_funcs = []
|
||
|
+ salt_cmd.run()
|
||
|
+
|
||
|
+ local_client.run_job.assert_called_once()
|
||
|
+ assert local_client.run_job.mock_calls[0].args[0] == "*"
|
||
|
+ assert local_client.run_job.mock_calls[0].args[1] == "test.arg"
|
||
|
+ assert local_client.run_job.mock_calls[0].kwargs["arg"] == ["arg1", "arg2", {"__kwarg__": True, "kwarg1": "val1"}]
|
||
|
+ assert local_client.run_job.mock_calls[0].kwargs["batch"] == 10
|
||
|
+ print_cli.assert_called_once_with("Executed command with job ID: 123456")
|
||
|
+ assert exit_info.value.code == 0
|
||
|
--
|
||
|
2.42.0
|
||
|
|