Tests verifying functionality ansible runtime infrastructure

New tests verify callback order of precedence, white list
handling and environment variable setting under various conditions.

Closes-Bug: #1922726

Signed-off-by: Jiri Podivin <jpodivin@redhat.com>
Change-Id: I20b0c9a4289c7c8885e5b1981c8bea81c1deab47
This commit is contained in:
Jiri Podivin 2021-01-18 16:55:50 +01:00
parent 5558cb0d15
commit 1701904ca3
1 changed files with 615 additions and 3 deletions

View File

@ -19,12 +19,14 @@ try:
except ImportError:
import mock
from unittest import TestCase
import os
from ansible_runner import Runner
from validations_libs import constants
from validations_libs.ansible import Ansible
from validations_libs.tests import fakes
try:
version = pkg_resources.get_distribution("ansible_runner").version
backward_compat = (version < '1.4.0')
@ -363,10 +365,10 @@ class TestAnsible(TestCase):
return_value="/foo/inventory.yaml")
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch('validations_libs.ansible.Ansible._ansible_env_var',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake.py'})
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
@mock.patch('os.environ.copy', return_value={})
@mock.patch('os.path.abspath', return_value='/tmp/foo/localhost')
def test_run_specific_log_path(self, moch_path, mock_env, mock_env_var,
def test_run_specific_log_path(self, mock_path, mock_env, mock_env_var,
mock_config, mock_dump_artifact, mock_run,
mock_mkdirs, mock_exists, mock_open):
_playbook, _rc, _status = self.run.run(
@ -390,7 +392,7 @@ class TestAnsible(TestCase):
if not backward_compat:
opt.update({
'envvars': {
'ANSIBLE_STDOUT_CALLBACK': 'fake.py',
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CONFIG': '/tmp/foo/artifacts/ansible.cfg',
'VALIDATIONS_LOG_DIR': '/tmp/foo'},
'project_dir': '/tmp',
@ -479,3 +481,613 @@ class TestAnsible(TestCase):
self.assertEqual((_playbook, _rc, _status),
('existing.yaml', 0, 'successful'))
mock_open.assert_called_with('/tmp/ansible.cfg', 'w')
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch(
'ansible_runner.utils.dump_artifact',
autospec=True,
return_value="/foo/inventory.yaml")
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
@mock.patch('os.path.abspath', return_value='/tmp/foo/localhost')
@mock.patch('os.environ.copy', return_value={})
def test_run_no_log_path(self, mock_env, mock_path,
mock_env_var, mock_config,
mock_dump_artifact, mock_run,
mock_exists, mock_open):
"""
Tests if leaving default (None) log_path appropriately sets
'ANSIBLE_CONFIG' and 'fact_cache' envvars,
using constants.constants.VALIDATION_ANSIBLE_ARTIFACT_PATH.
Bulk of the mocks are only for purposes of convenience.
Assertions:
Presence of key: value pairs.
"""
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp')
opt = {
'artifact_dir': '/tmp',
'extravars': {},
'ident': '',
'inventory': '/tmp/foo/localhost',
'playbook': 'existing.yaml',
'private_data_dir': '/tmp',
'quiet': False,
'rotate_artifacts': 256,
'verbosity': 0}
if not backward_compat:
opt.update({
'envvars': {
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CONFIG': os.path.join(
constants.VALIDATION_ANSIBLE_ARTIFACT_PATH,
'ansible.cfg')},
'project_dir': '/tmp',
'fact_cache': constants.VALIDATION_ANSIBLE_ARTIFACT_PATH,
'fact_cache_type': 'jsonfile'})
mock_config.assert_called_once_with(**opt)
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch(
'ansible_runner.utils.dump_artifact',
autospec=True,
return_value="/foo/inventory.yaml")
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
@mock.patch('os.path.abspath', return_value='/tmp/foo/localhost')
@mock.patch('os.environ.copy', return_value={})
def test_run_tags(self, mock_env, mock_path,
mock_env_var, mock_config,
mock_dump_artifact, mock_run,
mock_exists, mock_open):
"""
Tests if specifying tags appropriately sets
'tags' envvar, passed as dict entry to RunnerConfig.
Bulk of the mocks are only for purposes of convenience.
Assertions:
Presence of key: value pairs.
"""
tags = ','.join(['master', 'train', 'fake'])
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
log_path='/tmp/foo',
tags=tags)
opt = {
'artifact_dir': '/tmp',
'extravars': {},
'ident': '',
'inventory': '/tmp/foo/localhost',
'playbook': 'existing.yaml',
'private_data_dir': '/tmp',
'quiet': False,
'rotate_artifacts': 256,
'verbosity': 0,
'tags': tags}
if not backward_compat:
opt.update({
'envvars': {
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CONFIG': '/tmp/foo/artifacts/ansible.cfg',
'VALIDATIONS_LOG_DIR': '/tmp/foo'},
'project_dir': '/tmp',
'fact_cache': '/tmp/foo/artifacts/',
'fact_cache_type': 'jsonfile'})
mock_config.assert_called_once_with(**opt)
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._encode_envvars',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks',
'ANSIBLE_CONFIG': os.path.join(
constants.VALIDATION_ANSIBLE_ARTIFACT_PATH,
'ansible.cfg')})
@mock.patch(
'os.environ.copy',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
@mock.patch('os.path.abspath', return_value='/tmp/foo/localhost')
def test_run_ansible_playbook_dir(self, mock_path, mock_env,
mock_encode_envvars,
mock_config, mock_run,
mock_exists, mock_open):
"""
Tests if leaving default (None) log_path and setting playbook_dir
appropriately sets 'project_dir' value in r_opts dict.
Bulk of the mocks are only for purposes of convenience.
Assertions:
Presence of key: value pairs.
"""
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
playbook_dir='/tmp/fake_playbooks')
opt = {
'artifact_dir': '/tmp',
'extravars': {},
'ident': '',
'inventory': '/tmp/foo/localhost',
'playbook': 'existing.yaml',
'private_data_dir': '/tmp',
'quiet': False,
'rotate_artifacts': 256,
'verbosity': 0}
if not backward_compat:
opt.update({
'envvars': {
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CONFIG': os.path.join(
constants.VALIDATION_ANSIBLE_ARTIFACT_PATH,
'ansible.cfg'),
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks'
},
'project_dir': '/tmp/fake_playbooks',
'fact_cache': constants.VALIDATION_ANSIBLE_ARTIFACT_PATH,
'fact_cache_type': 'jsonfile'})
mock_config.assert_called_once_with(**opt)
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'log_plays,mail,fake,validation_json,profile_tasks'
})
@mock.patch('os.environ.copy', return_value={})
def test_run_callback_whitelist_extend(self, mock_env,
mock_env_var, mock_config,
mock_run, mock_exists,
mock_open):
"""Tests if Ansible._callbacks method appropriately constructs callback_whitelist,
when provided explicit whitelist and output_callback.
Bulk of the mocks are only for purposes of convenience.
Assertions:
Presence of key: value pairs.
"""
_playbook, _rc, _status = self.run.run(
ssh_user='root',
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
log_path='/tmp/foo',
output_callback='fake',
callback_whitelist='log_plays,mail')
args = {
'output_callback': 'fake',
'ssh_user': 'root',
'workdir': '/tmp',
'connection': 'smart',
'gathering_policy': 'smart',
'module_path': None,
'key': None,
'extra_env_variables': None,
'ansible_timeout': 30,
'callback_whitelist': 'log_plays,mail,fake,profile_tasks,vf_validation_json',
'base_dir': '/usr/share/ansible',
'python_interpreter': None}
#Specific form of Ansible.env_var neccessiates convoluted arg unpacking.
mock_env_var.assert_called_once_with(*args.values(), validation_cfg_file=None)
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks'
})
@mock.patch('os.environ.copy', return_value={})
def test_run_callback_whitelist_none(self, mock_env,
mock_env_var, mock_config,
mock_run, mock_exists,
mock_open):
"""Tests if Ansible._callbacks method appropriately constructs callback_whitelist,
when provided default (None) whitelist and specific output_callback.
Bulk of the mocks are only for purposes of convenience.
Assertions:
Presence of key: value pairs.
"""
_playbook, _rc, _status = self.run.run(
ssh_user='root',
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
log_path='/tmp/foo',
output_callback='fake')
args = {
'output_callback': 'fake',
'ssh_user': 'root',
'workdir': '/tmp',
'connection': 'smart',
'gathering_policy': 'smart',
'module_path': None,
'key': None,
'extra_env_variables': None,
'ansible_timeout': 30,
'callback_whitelist': 'fake,profile_tasks,vf_validation_json',
'base_dir': '/usr/share/ansible',
'python_interpreter': None}
#Specific form of Ansible.env_var neccessiates convoluted arg unpacking.
mock_env_var.assert_called_once_with(*args.values(), validation_cfg_file=None)
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'different_fake',
'ANSIBLE_CALLBACK_WHITELIST': 'different_fake,validation_json,profile_tasks'
})
@mock.patch(
'os.environ.copy',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'different_fake'})
def test_run_callback_precedence(self, mock_env,
mock_env_var, mock_config,
mock_run, mock_exists, mock_open):
"""Tests if Ansible._callbacks method reaches for output_callback
if and only if env dict doesn't contain 'ANSIBLE_STDOUT_CALLBACK' key.
Bulk of the mocks are only for purposes of convenience.
Assertions:
Presence of key: value pairs.
"""
_playbook, _rc, _status = self.run.run(
ssh_user='root',
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
log_path='/tmp/foo',
output_callback='fake')
args = {
'output_callback': 'different_fake',
'ssh_user': 'root',
'workdir': '/tmp',
'connection': 'smart',
'gathering_policy': 'smart',
'module_path': None,
'key': None,
'extra_env_variables': None,
'ansible_timeout': 30,
'callback_whitelist': 'different_fake,profile_tasks,vf_validation_json',
'base_dir': '/usr/share/ansible',
'python_interpreter': None}
#Specific form of Ansible.env_var neccessiates convoluted arg unpacking.
mock_env_var.assert_called_once_with(*args.values(), validation_cfg_file=None)
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks'
})
@mock.patch(
'os.environ.copy',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
def test_run_ansible_artifact_path_set(self, mock_env,
mock_env_var, mock_config,
mock_run, mock_exists, mock_open):
"""Tests if specified 'ansible_artifact_path' is passed in a valid
and unchanged form to RunnerConfig as value of 'fact_cache' param.
Additional assertion on number of calls is placed,
to ensure that RunnerConfig is called only once.
Otherwise followup assertions could fail.
Assertions:
Validity of specified path in filesystem:
os.lstat raises FileNotFoundError only if specified path is valid,
but does not exist in current filesystem.
Passing of specified value (ansible_artifact_path) to RunnerConfig.
"""
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
log_path='/tmp/foo',
output_callback='fake',
ansible_artifact_path='/tmp/artifact/path')
mock_config.assert_called_once()
"""Is the path even valid in our filesystem? Index 1 stands for kwargs in py<=36.
os.lstat raises FileNotFoundError only if specified path is valid,
but does not exist in current filesystem.
"""
self.assertRaises(FileNotFoundError, os.lstat, mock_config.call_args[1]['fact_cache'])
self.assertTrue('/tmp/artifact/path' in mock_config.call_args[1]['fact_cache'])
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks'
})
@mock.patch(
'os.environ.copy',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
def test_run_ansible_artifact_path_from_log_path(self, mock_env,
mock_env_var, mock_config,
mock_run, mock_exists, mock_open):
"""Tests if specified 'log_path' is passed in a valid
and unchanged form to RunnerConfig as value of 'fact_cache' param,
in absence of specified 'ansible_artifact_path'.
Additional assertion on number of calls is placed,
to ensure that RunnerConfig is called only once.
Otherwise followup assertions could fail.
Assertions:
Validity of specified path in filesystem.:
os.lstat raises FileNotFoundError only if specified path is valid,
but does not exist in current filesystem.
Passing of specified value (log_path) to RunnerConfig.
"""
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
log_path='/tmp/foo',
output_callback='fake')
mock_config.assert_called_once()
"""Is the path even valid in our filesystem? Index 1 stands for kwargs in py<=36.
os.lstat raises FileNotFoundError only if specified path is valid,
but does not exist in current filesystem.
"""
self.assertRaises(FileNotFoundError, os.lstat, mock_config.call_args[1]['fact_cache'])
self.assertTrue('/tmp/foo' in mock_config.call_args[1]['fact_cache'])
@mock.patch.object(
constants,
'VALIDATION_ANSIBLE_ARTIFACT_PATH',
new='foo/bar')
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._ansible_env_var',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks',
})
@mock.patch(
'os.environ.copy',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
def test_run_ansible_artifact_path_from_constants(self, mock_env,
mock_env_var, mock_config,
mock_run, mock_exists,
mock_open):
"""Tests if 'constants.constants.VALIDATION_ANSIBLE_ARTIFACT_PATH' passed in a valid
and unchanged form to RunnerConfig as value of 'fact_cache' param,
in absence of specified 'ansible_artifact_path' or 'log_path'.
Additional assertion on number of calls is placed,
to ensure that RunnerConfig is called only once.
Otherwise followup assertions could fail.
Assertions:
Validity of specified path in filesystem.:
os.lstat raises FileNotFoundError only if specified path is valid,
but does not exist in current filesystem.
Passing of specified value (log_path) to RunnerConfig.
"""
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp')
mock_config.assert_called_once()
"""Is the path even valid in our filesystem? Index 1 stands for kwargs in py<=36.
os.lstat raises FileNotFoundError only if specified path is valid,
but does not exist in current filesystem.
"""
self.assertRaises(FileNotFoundError, os.lstat, mock_config.call_args[1]['fact_cache'])
self.assertTrue(constants.VALIDATION_ANSIBLE_ARTIFACT_PATH in mock_config.call_args[1]['fact_cache'])
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._encode_envvars',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks',
'ANSIBLE_CONFIG': os.path.join(
constants.VALIDATION_ANSIBLE_ARTIFACT_PATH,
'ansible.cfg')})
@mock.patch(
'os.environ.copy',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
def test_run_ansible_envvars(self, mock_env,
mock_encode_envvars,
mock_config, mock_run,
mock_exists, mock_open):
"""Tests if Ansible._ansible_env_var method,
and following conditionals, correctly assemble the env dict.
Assertions:
Dictinary passed to Ansible._encode_envvars contains key: value
pairs representing proper superset of key: value pairs required.
"""
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp')
env = {
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_DISPLAY_FAILED_STDERR': True,
'ANSIBLE_FORKS': 36,
'ANSIBLE_TIMEOUT': 30,
'ANSIBLE_GATHER_TIMEOUT': 45,
'ANSIBLE_SSH_RETRIES': 3,
'ANSIBLE_PIPELINING': True,
'ANSIBLE_CALLBACK_WHITELIST': 'fake,profile_tasks,vf_validation_json',
'ANSIBLE_RETRY_FILES_ENABLED': False,
'ANSIBLE_HOST_KEY_CHECKING': False,
'ANSIBLE_TRANSPORT': 'smart',
'ANSIBLE_CACHE_PLUGIN_TIMEOUT': 7200,
'ANSIBLE_GATHERING': 'smart',
'ANSIBLE_CONFIG': os.path.join(
constants.VALIDATION_ANSIBLE_ARTIFACT_PATH,
'ansible.cfg')}
#Test will work properly only if the method was called once.
mock_encode_envvars.assert_called_once()
"""True if, and only if, every item (key:value pair) in the env dict
is also present in the kwargs dict. Index 1 stands for kwargs in py<=36
This test does not rely on order of items.
"""
self.assertGreaterEqual(
mock_encode_envvars.call_args[1]['env'].items(),
env.items())
@mock.patch('six.moves.builtins.open')
@mock.patch('os.path.exists', return_value=True)
@mock.patch.object(
Runner,
'run',
return_value=fakes.fake_ansible_runner_run_return(rc=0))
@mock.patch('ansible_runner.runner_config.RunnerConfig')
@mock.patch(
'validations_libs.ansible.Ansible._encode_envvars',
return_value={
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_CALLBACK_WHITELIST': 'fake,validation_json,profile_tasks',
'ANSIBLE_CONFIG': '/tmp/foo/artifacts/ansible.cfg'})
@mock.patch(
'os.environ.copy',
return_value={'ANSIBLE_STDOUT_CALLBACK': 'fake'})
def test_run_ansible_envvars_logdir(self, mock_env,
mock_encode_envvars,
mock_config, mock_run,
mock_exists, mock_open):
"""Tests if Ansible._ansible_env_var method,
and following conditionals, correctly assemble the env dict.
While using the specified `log_path` value in appropriate places.
Assertions:
Dictinary passed to Ansible._encode_envvars contains key: value
pairs representing proper superset of key: value pairs required.
"""
_playbook, _rc, _status = self.run.run(
playbook='existing.yaml',
inventory='localhost,',
workdir='/tmp',
log_path='/tmp/foo')
env = {
'ANSIBLE_STDOUT_CALLBACK': 'fake',
'ANSIBLE_DISPLAY_FAILED_STDERR': True,
'ANSIBLE_FORKS': 36,
'ANSIBLE_TIMEOUT': 30,
'ANSIBLE_GATHER_TIMEOUT': 45,
'ANSIBLE_SSH_RETRIES': 3,
'ANSIBLE_PIPELINING': True,
'ANSIBLE_CALLBACK_WHITELIST': 'fake,profile_tasks,vf_validation_json',
'ANSIBLE_RETRY_FILES_ENABLED': False,
'ANSIBLE_HOST_KEY_CHECKING': False,
'ANSIBLE_TRANSPORT': 'smart',
'ANSIBLE_CACHE_PLUGIN_TIMEOUT': 7200,
'ANSIBLE_GATHERING': 'smart',
'ANSIBLE_CONFIG': '/tmp/foo/artifacts/ansible.cfg',
'VALIDATIONS_LOG_DIR': '/tmp/foo'}
#Test will work properly only if the method was called once.
mock_encode_envvars.assert_called_once()
"""True if, and only if, every item (key:value pair) in the env dict
is also present in the kwargs dict. Index 1 stands for kwargs in py<=36
This test does not rely on order of items.
"""
self.assertGreaterEqual(
mock_encode_envvars.call_args[1]['env'].items(),
env.items())