Mini Shell
"""
Module for running arbitrary tests
"""
import builtins
import logging
import os
import random
import sys
import time
import traceback
import salt.exceptions
import salt.loader
import salt.utils.args
import salt.utils.functools
import salt.utils.hashutils
import salt.utils.platform
import salt.utils.versions
import salt.version
from salt.config import DEFAULT_HASH_TYPE
from salt.utils.decorators import depends
__proxyenabled__ = ["*"]
# Don't shadow built-in's.
__func_alias__ = {
"true_": "true",
"false_": "false",
"try_": "try",
}
log = logging.getLogger(__name__)
@depends("non_existantmodulename")
def missing_func():
return "foo"
def attr_call():
"""
Call grains.items via the attribute
CLI Example:
.. code-block:: bash
salt '*' test.attr_call
"""
return __salt__.grains.items()
def module_report():
"""
Return a dict containing all of the execution modules with a report on
the overall availability via different references
CLI Example:
.. code-block:: bash
salt '*' test.module_report
"""
ret = {
"functions": [],
"function_attrs": [],
"function_subs": [],
"modules": [],
"module_attrs": [],
"missing_attrs": [],
"missing_subs": [],
}
for ref in __salt__:
if "." in ref:
ret["functions"].append(ref)
else:
ret["modules"].append(ref)
if hasattr(__salt__, ref):
ret["module_attrs"].append(ref)
for func in __salt__[ref]:
full = f"{ref}.{func}"
if hasattr(getattr(__salt__, ref), func):
ret["function_attrs"].append(full)
if func in __salt__[ref]:
ret["function_subs"].append(full)
for func in ret["functions"]:
if func not in ret["function_attrs"]:
ret["missing_attrs"].append(func)
if func not in ret["function_subs"]:
ret["missing_subs"].append(func)
return ret
def echo(text):
"""
Return a string - used for testing the connection
CLI Example:
.. code-block:: bash
salt '*' test.echo 'foo bar baz quo qux'
"""
return text
def ping():
"""
Used to make sure the minion is up and responding. Not an ICMP ping.
Returns ``True``.
CLI Example:
.. code-block:: bash
salt '*' test.ping
"""
if not salt.utils.platform.is_proxy():
log.debug("test.ping received for minion '%s'", __opts__.get("id"))
return True
else:
ping_cmd = __opts__["proxy"]["proxytype"] + ".ping"
if __opts__.get("add_proxymodule_to_opts", False):
return __opts__["proxymodule"][ping_cmd]()
else:
return __proxy__[ping_cmd]()
def sleep(length):
"""
Instruct the minion to initiate a process that will sleep for a given
period of time.
CLI Example:
.. code-block:: bash
salt '*' test.sleep 20
"""
time.sleep(int(length))
return True
def rand_sleep(max=60):
"""
Sleep for a random number of seconds, used to test long-running commands
and minions returning at differing intervals
CLI Example:
.. code-block:: bash
salt '*' test.rand_sleep 60
"""
time.sleep(random.randint(0, max))
return True
def version():
"""
Return the version of salt on the minion
CLI Example:
.. code-block:: bash
salt '*' test.version
"""
return salt.version.__version__
def versions_information():
"""
Report the versions of dependent and system software
CLI Example:
.. code-block:: bash
salt '*' test.versions_information
"""
return salt.version.versions_information()
def versions_report():
"""
Returns versions of components used by salt
CLI Example:
.. code-block:: bash
salt '*' test.versions_report
"""
return "\n".join(salt.version.versions_report())
versions = salt.utils.functools.alias_function(versions_report, "versions")
def conf_test():
"""
Return the value for test.foo in the minion configuration file, or return
the default value
CLI Example:
.. code-block:: bash
salt '*' test.conf_test
"""
return __salt__["config.option"]("test.foo")
def get_opts():
"""
Return the configuration options passed to this minion
CLI Example:
.. code-block:: bash
salt '*' test.get_opts
"""
return __opts__
def cross_test(func, args=None):
"""
Execute a minion function via the ``__salt__`` object in the test
module, used to verify that the Minion functions can be called
via the ``__salt__`` module.
CLI Example:
.. code-block:: bash
salt '*' test.cross_test file.gid_to_group 0
"""
if args is None:
args = []
return __salt__[func](*args)
def kwarg(**kwargs):
"""
Print out the data passed into the function ``**kwargs``, this is used to
both test the publication data and CLI ``kwarg`` passing, but also to display
the information available within the publication data.
CLI Example:
.. code-block:: bash
salt '*' test.kwarg num=1 txt="two" env='{a: 1, b: "hello"}'
"""
return kwargs
def arg(*args, **kwargs):
"""
Print out the data passed into the function ``*args`` and ``kwargs``, this
is used to both test the publication data and CLI argument passing, but
also to display the information available within the publication data.
:return: ``{"args": args, "kwargs": kwargs}``
:rtype: dict
CLI Example:
.. code-block:: bash
salt '*' test.arg 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
"""
return {"args": args, "kwargs": kwargs}
def arg_type(*args, **kwargs):
"""
Print out the types of the ``args`` and ``kwargs``. This is used to test the types
of the ``args`` and ``kwargs`` passed down to the Minion
:rtype: dict
CLI Example:
.. code-block:: bash
salt '*' test.arg_type 1 'int'
"""
ret = {"args": [], "kwargs": {}}
# all the args
for argument in args:
ret["args"].append(str(type(argument)))
# all the kwargs
for key, val in kwargs.items():
ret["kwargs"][key] = str(type(val))
return ret
def arg_repr(*args, **kwargs):
"""
Print out the data passed into the function ``*args`` and ``kwargs``, this
is used to both test the publication data and CLI argument passing, but
also to display the information available within the publication data.
:return: ``{"args": repr(args), "kwargs": repr(kwargs)}``
CLI Example:
.. code-block:: bash
salt '*' test.arg_repr 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
"""
return {"args": repr(args), "kwargs": repr(kwargs)}
def arg_clean(*args, **kwargs):
"""
Like :mod:`test.arg <salt.modules.test.arg>` but cleans ``kwargs`` of the ``__pub*`` items
CLI Example:
.. code-block:: bash
salt '*' test.arg_clean 1 "two" 3.1 txt="hello" wow='{a: 1, b: "hello"}'
"""
return dict(args=args, kwargs=salt.utils.args.clean_kwargs(**kwargs))
def fib(num):
"""
Return the ``num``-th Fibonacci number, and the time it took to compute in
seconds. Used for performance tests.
This function is designed to have terrible performance.
CLI Example:
.. code-block:: bash
salt '*' test.fib 3
"""
num = int(num)
if num < 0:
raise ValueError("Negative number is not allowed!")
start = time.time()
if num < 2:
return num, time.time() - start
prev = 0
curr = 1
i = 1
while i < num:
prev, curr = curr, prev + curr
i += 1
return curr, time.time() - start
def collatz(start):
"""
Execute the collatz conjecture from the passed starting number,
returns the sequence and the time it took to compute. Used for
performance tests.
CLI Example:
.. code-block:: bash
salt '*' test.collatz 3
"""
start = int(start)
begin = time.time()
steps = []
while start != 1:
steps.append(start)
if start > 1:
if start % 2 == 0:
start = start / 2
else:
start = start * 3 + 1
return steps, time.time() - begin
def outputter(data):
"""
Test the outputter, pass in data to return
CLI Example:
.. code-block:: bash
salt '*' test.outputter foobar
"""
return data
def retcode(code=42):
"""
Test that the returncode system is functioning correctly
CLI Example:
.. code-block:: bash
salt '*' test.retcode 42
"""
__context__["retcode"] = code
return True
def provider(module):
"""
Pass in a function name to discover what provider is being used
CLI Example:
.. code-block:: bash
salt '*' test.provider service
"""
func = ""
for key in __salt__:
if not key.startswith(f"{module}."):
continue
func = key
break
if not func:
return ""
pfn = sys.modules[__salt__[func].__module__].__file__
pfn = os.path.basename(pfn)
return pfn[: pfn.rindex(".")]
def providers():
"""
Return a dict of the provider names and the files that provided them
CLI Example:
.. code-block:: bash
salt '*' test.providers
"""
ret = {}
for funcname in __salt__:
modname = funcname.split(".")[0]
if modname not in ret:
ret[provider(modname)] = modname
return ret
def not_loaded():
"""
List the modules that were not loaded by the salt loader system
CLI Example:
.. code-block:: bash
salt '*' test.not_loaded
"""
prov = providers()
ret = set()
for mod_dir in salt.loader._module_dirs(__opts__, "modules", "module"):
if not os.path.isabs(mod_dir):
continue
if not os.path.isdir(mod_dir):
continue
for fn_ in os.listdir(mod_dir):
if fn_.startswith("_"):
continue
name = fn_.split(".")[0]
if name not in prov:
ret.add(name)
return sorted(ret)
def opts_pkg():
"""
Return an ``opts`` package with the ``grains`` and ``opts`` for this Minion.
This is primarily used to create the options used for Master side
state compiling routines
CLI Example:
.. code-block:: bash
salt '*' test.opts_pkg
"""
ret = {}
ret.update(__opts__)
ret["grains"] = __grains__.value()
return ret
def rand_str(size=9999999999, hash_type=None):
"""
This function has been renamed to
:mod:`test.random_hash <salt.modules.test.random_hash>`. This function will stay to
ensure backwards compatibility, but please switch to using the preferred name
:mod:`test.random_hash <salt.modules.test.random_hash>`.
"""
return random_hash(size=size, hash_type=hash_type)
def random_hash(size=9999999999, hash_type=None):
"""
.. versionadded:: 2015.5.2
.. versionchanged:: 2018.3.0
Function has been renamed from ``test.rand_str`` to
``test.random_hash``
Generates a random number between 1 and ``size``, then returns a hash of
that number. If no ``hash_type`` is passed, the ``hash_type`` specified by the
Minion's :conf_minion:`hash_type` config option is used.
CLI Example:
.. code-block:: bash
salt '*' test.random_hash
salt '*' test.random_hash hash_type=sha512
"""
if not hash_type:
hash_type = __opts__.get("hash_type", DEFAULT_HASH_TYPE)
return salt.utils.hashutils.random_hash(size=size, hash_type=hash_type)
def exception(message="Test Exception"):
"""
Raise an exception
Optionally provide an error message or output the full stack.
CLI Example:
.. code-block:: bash
salt '*' test.exception 'Oh noes!'
"""
raise Exception(message)
def stack():
"""
Return the current stack trace
CLI Example:
.. code-block:: bash
salt '*' test.stack
"""
return "".join(traceback.format_stack())
def tty(*args, **kwargs): # pylint: disable=W0613
"""
Deprecated! Moved to :mod:`cmd.tty <salt.modules.cmdmod.tty>`
CLI Example:
.. code-block:: bash
salt '*' test.tty tty0 'This is a test'
salt '*' test.tty pts3 'This is a test'
"""
return "ERROR: This function has been moved to cmd.tty"
def try_(module, return_try_exception=False, **kwargs):
"""
Try to run a module command. On an exception return ``None``.
If ``return_try_exception`` is set to ``True``, return the exception.
This can be helpful in templates where running a module might fail as expected.
Jinja Example:
.. code-block:: jinja
{% for i in range(0,230) %}
{{ salt['test.try'](module='ipmi.get_users', bmc_host='172.2.2.'+i)|yaml(False) }}
{% endfor %}
"""
try:
return __salt__[module](**kwargs)
except Exception as e: # pylint: disable=broad-except
if return_try_exception:
return e
return None
def assertion(assertion):
"""
Assert the given argument
CLI Example:
.. code-block:: bash
salt '*' test.assertion False
"""
assert assertion
def true_():
"""
Always return ``True``
CLI Example:
.. code-block:: bash
salt '*' test.true
"""
return True
def false_():
"""
Always return ``False``
CLI Example:
.. code-block:: bash
salt '*' test.false
"""
return False
def raise_exception(name, *args, **kwargs):
"""
Raise an exception. Built-in exceptions and those in
:mod:`salt.exceptions <salt.internals.salt.exceptions>`
can be raised by this test function. If no matching exception is found,
then no exception will be raised and this function will return ``False``.
This function is designed to test Salt's exception and return code
handling.
CLI Example:
.. code-block:: bash
salt '*' test.raise_exception TypeError "An integer is required"
salt '*' test.raise_exception salt.exceptions.CommandExecutionError "Something went wrong"
"""
def _is_exc(cls):
for base in cls.__bases__:
if base is BaseException:
break
else:
return _is_exc(base)
else:
return False
return True
try:
if name.startswith("salt.exceptions."):
exc = getattr(salt.exceptions, name[16:])
else:
exc = getattr(builtins, name)
if _is_exc(exc):
raise exc(*args, **salt.utils.args.clean_kwargs(**kwargs))
else:
log.error("%s is not an exception", name)
return False
except AttributeError:
log.error("No such exception: %s", name)
return False
def deprecation_warning():
r"""
Return True, but also produce two DeprecationWarnings. One by date, the
other by the codename - release Oganesson, which should correspond to Salt
3108.
CLI Example:
.. code-block:: bash
salt \* test.deprecation_warning
"""
# This warn should always stay in Salt.
salt.utils.versions.warn_until(
3108,
"This is a test deprecation warning by version.",
)
salt.utils.versions.warn_until_date(
"30000101",
"This is a test deprecation warning by date very far into the future ({date}).",
)
return True
Zerion Mini Shell 1.0