2016-11-30 06:21:53 +01:00
|
|
|
"""Miscellaneous utility functions and classes specific to ansible cli tools."""
|
2019-07-12 08:46:20 +02:00
|
|
|
from __future__ import (absolute_import, division, print_function)
|
|
|
|
__metaclass__ = type
|
2016-11-30 06:21:53 +01:00
|
|
|
|
2019-06-05 07:08:23 +02:00
|
|
|
import json
|
2016-11-30 06:21:53 +01:00
|
|
|
import os
|
|
|
|
|
2019-08-06 23:43:29 +02:00
|
|
|
from .constants import (
|
2019-02-18 22:28:25 +01:00
|
|
|
SOFT_RLIMIT_NOFILE,
|
|
|
|
)
|
|
|
|
|
2019-08-06 23:43:29 +02:00
|
|
|
from .util import (
|
2017-10-04 20:36:53 +02:00
|
|
|
common_environment,
|
2019-06-05 07:08:23 +02:00
|
|
|
display,
|
|
|
|
find_python,
|
2017-10-04 20:36:53 +02:00
|
|
|
ApplicationError,
|
2019-08-09 01:14:19 +02:00
|
|
|
ANSIBLE_LIB_ROOT,
|
2019-08-06 02:40:00 +02:00
|
|
|
ANSIBLE_TEST_DATA_ROOT,
|
2019-08-09 02:21:38 +02:00
|
|
|
ANSIBLE_BIN_PATH,
|
2019-09-26 16:19:58 +02:00
|
|
|
ANSIBLE_SOURCE_ROOT,
|
2017-10-04 20:36:53 +02:00
|
|
|
)
|
|
|
|
|
2019-08-06 23:43:29 +02:00
|
|
|
from .util_common import (
|
2019-09-26 16:19:58 +02:00
|
|
|
create_temp_dir,
|
2019-07-11 07:00:34 +02:00
|
|
|
run_command,
|
2019-08-28 08:40:06 +02:00
|
|
|
ResultType,
|
2019-07-11 07:00:34 +02:00
|
|
|
)
|
|
|
|
|
2019-08-06 23:43:29 +02:00
|
|
|
from .config import (
|
2019-08-13 22:18:55 +02:00
|
|
|
PosixIntegrationConfig,
|
2019-06-05 07:08:23 +02:00
|
|
|
EnvironmentConfig,
|
2019-08-21 21:12:37 +02:00
|
|
|
CommonConfig,
|
2017-10-04 20:36:53 +02:00
|
|
|
)
|
2016-11-30 06:21:53 +01:00
|
|
|
|
2019-08-06 23:43:29 +02:00
|
|
|
from .data import (
|
2019-07-23 04:24:48 +02:00
|
|
|
data_context,
|
|
|
|
)
|
2016-11-30 06:21:53 +01:00
|
|
|
|
2019-06-05 07:08:23 +02:00
|
|
|
CHECK_YAML_VERSIONS = {}
|
|
|
|
|
|
|
|
|
2019-01-10 23:43:21 +01:00
|
|
|
def ansible_environment(args, color=True, ansible_config=None):
|
2016-11-30 06:21:53 +01:00
|
|
|
"""
|
|
|
|
:type args: CommonConfig
|
2017-03-08 20:45:38 +01:00
|
|
|
:type color: bool
|
2019-01-10 23:43:21 +01:00
|
|
|
:type ansible_config: str | None
|
2016-11-30 06:21:53 +01:00
|
|
|
:rtype: dict[str, str]
|
|
|
|
"""
|
|
|
|
env = common_environment()
|
|
|
|
path = env['PATH']
|
|
|
|
|
2019-08-09 02:21:38 +02:00
|
|
|
if not path.startswith(ANSIBLE_BIN_PATH + os.path.pathsep):
|
|
|
|
path = ANSIBLE_BIN_PATH + os.path.pathsep + path
|
2016-11-30 06:21:53 +01:00
|
|
|
|
2019-08-13 22:18:55 +02:00
|
|
|
if not ansible_config:
|
|
|
|
# use the default empty configuration unless one has been provided
|
2019-08-21 21:12:37 +02:00
|
|
|
ansible_config = args.get_ansible_config()
|
2017-10-04 20:36:53 +02:00
|
|
|
|
2019-01-10 23:43:21 +01:00
|
|
|
if not args.explain and not os.path.exists(ansible_config):
|
2017-10-04 20:36:53 +02:00
|
|
|
raise ApplicationError('Configuration not found: %s' % ansible_config)
|
|
|
|
|
2016-11-30 06:21:53 +01:00
|
|
|
ansible = dict(
|
2019-02-18 22:28:25 +01:00
|
|
|
ANSIBLE_PYTHON_MODULE_RLIMIT_NOFILE=str(SOFT_RLIMIT_NOFILE),
|
2017-03-08 20:45:38 +01:00
|
|
|
ANSIBLE_FORCE_COLOR='%s' % 'true' if args.color and color else 'false',
|
2019-08-13 22:18:55 +02:00
|
|
|
ANSIBLE_FORCE_HANDLERS='true', # allow cleanup handlers to run when tests fail
|
|
|
|
ANSIBLE_HOST_PATTERN_MISMATCH='error', # prevent tests from unintentionally passing when hosts are not found
|
|
|
|
ANSIBLE_INVENTORY='/dev/null', # force tests to provide inventory
|
2016-11-30 06:21:53 +01:00
|
|
|
ANSIBLE_DEPRECATION_WARNINGS='false',
|
2017-01-08 08:36:35 +01:00
|
|
|
ANSIBLE_HOST_KEY_CHECKING='false',
|
2019-01-08 23:03:15 +01:00
|
|
|
ANSIBLE_RETRY_FILES_ENABLED='false',
|
2019-08-13 22:18:55 +02:00
|
|
|
ANSIBLE_CONFIG=ansible_config,
|
2018-09-21 21:55:04 +02:00
|
|
|
ANSIBLE_LIBRARY='/dev/null',
|
2019-09-26 16:19:58 +02:00
|
|
|
PYTHONPATH=get_ansible_python_path(),
|
2016-11-30 06:21:53 +01:00
|
|
|
PAGER='/bin/cat',
|
|
|
|
PATH=path,
|
|
|
|
)
|
|
|
|
|
2019-08-13 22:18:55 +02:00
|
|
|
if isinstance(args, PosixIntegrationConfig):
|
|
|
|
ansible.update(dict(
|
|
|
|
ANSIBLE_PYTHON_INTERPRETER='/set/ansible_python_interpreter/in/inventory', # force tests to set ansible_python_interpreter in inventory
|
|
|
|
))
|
|
|
|
|
2016-11-30 06:21:53 +01:00
|
|
|
env.update(ansible)
|
|
|
|
|
2017-02-01 20:15:08 +01:00
|
|
|
if args.debug:
|
2017-10-26 09:21:46 +02:00
|
|
|
env.update(dict(
|
|
|
|
ANSIBLE_DEBUG='true',
|
2019-08-28 08:40:06 +02:00
|
|
|
ANSIBLE_LOG_PATH=os.path.join(ResultType.LOGS.name, 'debug.log'),
|
2017-10-26 09:21:46 +02:00
|
|
|
))
|
2017-02-01 20:15:08 +01:00
|
|
|
|
2019-07-23 04:24:48 +02:00
|
|
|
if data_context().content.collection:
|
|
|
|
env.update(dict(
|
|
|
|
ANSIBLE_COLLECTIONS_PATHS=data_context().content.collection.root,
|
|
|
|
))
|
|
|
|
|
2016-11-30 06:21:53 +01:00
|
|
|
return env
|
2019-06-05 07:08:23 +02:00
|
|
|
|
|
|
|
|
2019-09-26 16:19:58 +02:00
|
|
|
def get_ansible_python_path(): # type: () -> str
|
|
|
|
"""
|
|
|
|
Return a directory usable for PYTHONPATH, containing only the ansible package.
|
|
|
|
If a temporary directory is required, it will be cached for the lifetime of the process and cleaned up at exit.
|
|
|
|
"""
|
|
|
|
if ANSIBLE_SOURCE_ROOT:
|
|
|
|
# when running from source there is no need for a temporary directory to isolate the ansible package
|
|
|
|
return os.path.dirname(ANSIBLE_LIB_ROOT)
|
|
|
|
|
|
|
|
try:
|
|
|
|
return get_ansible_python_path.python_path
|
|
|
|
except AttributeError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
python_path = create_temp_dir(prefix='ansible-test-')
|
|
|
|
get_ansible_python_path.python_path = python_path
|
|
|
|
|
|
|
|
os.symlink(ANSIBLE_LIB_ROOT, os.path.join(python_path, 'ansible'))
|
|
|
|
|
|
|
|
return python_path
|
|
|
|
|
|
|
|
|
2019-06-05 07:08:23 +02:00
|
|
|
def check_pyyaml(args, version):
|
|
|
|
"""
|
|
|
|
:type args: EnvironmentConfig
|
|
|
|
:type version: str
|
|
|
|
"""
|
|
|
|
if version in CHECK_YAML_VERSIONS:
|
|
|
|
return
|
|
|
|
|
|
|
|
python = find_python(version)
|
2019-08-06 02:40:00 +02:00
|
|
|
stdout, _dummy = run_command(args, [python, os.path.join(ANSIBLE_TEST_DATA_ROOT, 'yamlcheck.py')], capture=True)
|
2019-06-05 07:08:23 +02:00
|
|
|
|
|
|
|
if args.explain:
|
|
|
|
return
|
|
|
|
|
|
|
|
CHECK_YAML_VERSIONS[version] = result = json.loads(stdout)
|
|
|
|
|
|
|
|
yaml = result['yaml']
|
|
|
|
cloader = result['cloader']
|
|
|
|
|
|
|
|
if not yaml:
|
|
|
|
display.warning('PyYAML is not installed for interpreter: %s' % python)
|
|
|
|
elif not cloader:
|
|
|
|
display.warning('PyYAML will be slow due to installation without libyaml support for interpreter: %s' % python)
|