123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- # -*- coding: utf-8 -*-
- """
- :codeauthor: Thayne Harbaugh (tharbaug@adobe.com)
- tests.integration.shell.saltcli
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- :NOTE: this was named ``saltcli`` rather than ``salt`` because ``salt`` conflates
- in the python importer with the expected ``salt`` namespace and breaks imports.
- """
- from __future__ import absolute_import
- import logging
- import os
- import shutil
- import pytest
- import salt.defaults.exitcodes
- import salt.utils.path
- log = logging.getLogger(__name__)
- @pytest.mark.windows_whitelisted
- class TestRetcode(object):
- """
- Tests to ensure that we set non-zero retcodes when execution fails
- """
- def test_zero_exit_code_salt(self, salt_cli):
- """
- Test that a zero exit code is set when there are no errors and there is
- no explicit False result set in the return data.
- """
- ret = salt_cli.run("test.ping", minion_tgt="minion")
- assert ret.exitcode == 0, ret
- def test_zero_exit_code_salt_call(self, salt_call_cli):
- """
- Test that a zero exit code is set when there are no errors and there is
- no explicit False result set in the return data.
- """
- ret = salt_call_cli.run("test.ping")
- assert ret.exitcode == 0, ret
- def test_context_retcode_salt(self, salt_cli):
- """
- Test that a nonzero retcode set in the context dunder will cause the
- salt CLI to set a nonzero retcode.
- """
- # test.retcode will set the retcode in the context dunder
- ret = salt_cli.run("test.retcode", "0", minion_tgt="minion")
- assert ret.exitcode == 0, ret
- ret = salt_cli.run("test.retcode", "42", minion_tgt="minion")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- def test_context_retcode_salt_call(self, salt_call_cli):
- """
- Test that a nonzero retcode set in the context dunder will cause the
- salt CLI to set a nonzero retcode.
- """
- # Test salt-call, making sure to also confirm the behavior of
- # retcode_passthrough.
- ret = salt_call_cli.run("test.retcode", "0")
- assert ret.exitcode == 0, ret
- ret = salt_call_cli.run("test.retcode", "42")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run("--retcode-passthrough", "test.retcode", "42")
- assert ret.exitcode == 42, ret
- # Test a state run that exits with one or more failures
- ret = salt_call_cli.run("state.single", "test.fail_without_changes", "foo")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run(
- "--retcode-passthrough", "state.single", "test.fail_without_changes", "foo"
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_STATE_FAILURE, ret
- # Test a state compiler error
- ret = salt_call_cli.run("state.apply", "thisslsfiledoesnotexist")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run(
- "--retcode-passthrough", "state.apply", "thisslsfiledoesnotexist"
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR, ret
- def test_salt_error(self, salt_cli):
- """
- Test that we return the expected retcode when a minion function raises
- an exception.
- """
- ret = salt_cli.run("test.raise_exception", "TypeError", minion_tgt="minion")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_cli.run(
- "test.raise_exception",
- "salt.exceptions.CommandNotFoundError",
- minion_tgt="minion",
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_cli.run(
- "test.raise_exception",
- "salt.exceptions.CommandExecutionError",
- minion_tgt="minion",
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_cli.run(
- "test.raise_exception",
- "salt.exceptions.SaltInvocationError",
- minion_tgt="minion",
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_cli.run(
- "test.raise_exception",
- "OSError",
- "2",
- '"No such file or directory" /tmp/foo.txt',
- minion_tgt="minion",
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_cli.run(
- "test.echo", "{foo: bar, result: False}", minion_tgt="minion"
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_cli.run(
- "test.echo", "{foo: bar, success: False}", minion_tgt="minion"
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- def test_salt_call_error(self, salt_call_cli):
- """
- Test that we return the expected retcode when a minion function raises
- an exception.
- """
- ret = salt_call_cli.run("test.raise_exception", "TypeError")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run(
- "test.raise_exception", "salt.exceptions.CommandNotFoundError"
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run(
- "test.raise_exception", "salt.exceptions.CommandExecutionError"
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run(
- "test.raise_exception", "salt.exceptions.SaltInvocationError"
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run(
- "test.raise_exception",
- "OSError",
- "2",
- "No such file or directory",
- "/tmp/foo.txt",
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run("test.echo", "{foo: bar, result: False}")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- ret = salt_call_cli.run("test.echo", "{foo: bar, success: False}")
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- def test_missing_minion(self, salt_cli, salt_master):
- """
- Test that a minion which doesn't respond results in a nonzeo exit code
- """
- good = salt.utils.path.join(salt_master.config["pki_dir"], "minions", "minion")
- bad = salt.utils.path.join(salt_master.config["pki_dir"], "minions", "minion2")
- try:
- # Copy the key
- shutil.copyfile(good, bad)
- ret = salt_cli.run(
- "--timeout=5", "test.ping", minion_tgt="minion2", _timeout=120
- )
- assert ret.exitcode == salt.defaults.exitcodes.EX_GENERIC, ret
- finally:
- # Now get rid of it
- try:
- os.remove(bad)
- except OSError as exc:
- if exc.errno != os.errno.ENOENT:
- log.error(
- "Failed to remove %s, this may affect other tests: %s", bad, exc
- )
- def test_exit_status_unknown_argument(self, salt_cli):
- """
- Ensure correct exit status when an unknown argument is passed to salt CLI.
- """
- ret = salt_cli.run("--unknown-argument")
- assert ret.exitcode == salt.defaults.exitcodes.EX_USAGE, ret
- assert "Usage" in ret.stderr
- assert "no such option: --unknown-argument" in ret.stderr
- def test_exit_status_correct_usage(self, salt_cli):
- """
- Ensure correct exit status when salt CLI starts correctly.
- """
- ret = salt_cli.run("test.ping", minion_tgt="minion")
- assert ret.exitcode == salt.defaults.exitcodes.EX_OK, ret
|