Skip to content

Commit eca2257

Browse files
[Enabler] [conftest.py] Hot fix for testing the collection in Ansible 2.17.1 (#1772)
* Hijacking ansible-pytest to pass env vars * Decorate environment computation function * Update python used in test * Add playbook env vars debugging * Fix typo * Add Python version to env vars * Fix Python version in test * Add changelog fragment * Update index used by test * Fix zos_copy test * Escape dataset name in command calling drm * Use shlex.quote only on dataset name * Escape $ on dataset name * Fix dataset name escape * Fix escaping issues in tests --------- Co-authored-by: Fernando Flores <[email protected]>
1 parent a483fec commit eca2257

File tree

9 files changed

+58
-31
lines changed

9 files changed

+58
-31
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trivial:
2+
- tests/conftest.py - The testing suite could not load environment
3+
variables when executing modules. Fix now correctly passes all
4+
environment variables to the tests.
5+
(https://github.com/ansible-collections/ibm_zos_core/pull/1772).

tests/conftest.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,25 @@
1515
import pytest
1616
from ibm_zos_core.tests.helpers.ztest import ZTestHelper
1717
from ibm_zos_core.tests.helpers.volumes import get_volumes, get_volumes_with_vvds
18+
from ansible.plugins.action import ActionBase
1819
import sys
1920
from mock import MagicMock
2021
import importlib
2122

2223

24+
def add_vars_to_compute_environment(env_vars):
25+
"""This decorator injects the environment variables defined in a config
26+
file to the Ansible method responsible for constructing the environment
27+
string used by the SSH connection plugin."""
28+
def wrapper_compute_env(compute_environment_string):
29+
def wrapped_compute_environment_string(self, *args, **kwargs):
30+
self._task.environment = env_vars
31+
env_string = compute_environment_string(self, *args, **kwargs)
32+
return env_string
33+
return wrapped_compute_environment_string
34+
return wrapper_compute_env
35+
36+
2337
def pytest_addoption(parser):
2438
"""
2539
Add CLI options and modify options for pytest-ansible where needed.
@@ -57,7 +71,7 @@ def z_python_interpreter(request):
5771
interpreter_str = helper.build_interpreter_string()
5872
inventory = helper.get_inventory_info()
5973
python_path = helper.get_python_path()
60-
yield (interpreter_str, inventory, python_path)
74+
yield (helper._environment, interpreter_str, inventory, python_path)
6175

6276

6377
def clean_logs(adhoc):
@@ -81,7 +95,7 @@ def clean_logs(adhoc):
8195
def ansible_zos_module(request, z_python_interpreter):
8296
""" Initialize pytest-ansible plugin with values from
8397
our YAML config and inject interpreter path into inventory. """
84-
interpreter, inventory, python_path = z_python_interpreter
98+
env_vars, interpreter, inventory, python_path = z_python_interpreter
8599

86100
# next two lines perform similar action to ansible_adhoc fixture
87101
plugin = request.config.pluginmanager.getplugin("ansible")
@@ -93,9 +107,11 @@ def ansible_zos_module(request, z_python_interpreter):
93107
# Courtesy, pass along the python_path for some test cases need this information
94108
adhoc["options"]["ansible_python_path"] = python_path
95109

110+
# Adding the environment variables decorator to the Ansible engine.
111+
ActionBase._compute_environment_string = add_vars_to_compute_environment(env_vars)(ActionBase._compute_environment_string)
112+
96113
for host in hosts.values():
97-
host.vars["ansible_python_interpreter"] = interpreter
98-
# host.vars["ansible_connection"] = "zos_ssh"
114+
host.vars["ansible_python_interpreter"] = python_path
99115
yield adhoc
100116
try:
101117
clean_logs(adhoc)

tests/functional/modules/test_zos_archive_func.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ def test_mvs_archive_single_dataset(ansible_zos_module, format, data_set, record
400400
assert result.get("changed") is True
401401
assert result.get("dest") == archive_data_set
402402
assert src_data_set in result.get("archived")
403-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
403+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
404404
for c_result in cmd_result.contacted.values():
405405
assert archive_data_set in c_result.get("stdout")
406406
finally:
@@ -480,7 +480,7 @@ def test_mvs_archive_single_dataset_use_adrdssu(ansible_zos_module, format, data
480480
assert result.get("changed") is True
481481
assert result.get("dest") == archive_data_set
482482
assert src_data_set in result.get("archived")
483-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
483+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
484484
for c_result in cmd_result.contacted.values():
485485
assert archive_data_set in c_result.get("stdout")
486486
finally:
@@ -550,7 +550,7 @@ def test_mvs_archive_single_data_set_remove_target(ansible_zos_module, format, d
550550
assert result.get("changed") is True
551551
assert result.get("dest") == archive_data_set
552552
assert src_data_set in result.get("archived")
553-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
553+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
554554
for c_result in cmd_result.contacted.values():
555555
assert archive_data_set in c_result.get("stdout")
556556
assert src_data_set != c_result.get("stdout")
@@ -614,7 +614,7 @@ def test_mvs_archive_multiple_data_sets(ansible_zos_module, format, data_set):
614614
assert result.get("dest") == archive_data_set
615615
for ds in target_ds_list:
616616
assert ds.get("name") in result.get("archived")
617-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
617+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
618618
for c_result in cmd_result.contacted.values():
619619
assert archive_data_set in c_result.get("stdout")
620620
finally:
@@ -682,7 +682,7 @@ def test_mvs_archive_multiple_data_sets_with_exclusion(ansible_zos_module, forma
682682
assert exclude not in result.get("archived")
683683
else:
684684
assert ds.get("name") in result.get("archived")
685-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
685+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
686686
for c_result in cmd_result.contacted.values():
687687
assert archive_data_set in c_result.get("stdout")
688688
finally:
@@ -744,7 +744,7 @@ def test_mvs_archive_multiple_data_sets_and_remove(ansible_zos_module, format, d
744744
for result in archive_result.contacted.values():
745745
assert result.get("changed") is True
746746
assert result.get("dest") == archive_data_set
747-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
747+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
748748
for c_result in cmd_result.contacted.values():
749749
assert archive_data_set in c_result.get("stdout")
750750
for ds in target_ds_list:
@@ -820,7 +820,7 @@ def test_mvs_archive_multiple_data_sets_with_missing(ansible_zos_module, format,
820820
assert ds.get("name") not in result.get("archived")
821821
else:
822822
assert ds.get("name") in result.get("archived")
823-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
823+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
824824
for c_result in cmd_result.contacted.values():
825825
assert archive_data_set in c_result.get("stdout")
826826

@@ -902,7 +902,7 @@ def test_mvs_archive_single_dataset_force_lock(ansible_zos_module, format, data_
902902
assert result.get("changed") is True
903903
assert result.get("dest") == archive_data_set
904904
assert src_data_set in result.get("archived")
905-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
905+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
906906
for c_result in cmd_result.contacted.values():
907907
assert archive_data_set in c_result.get("stdout")
908908

@@ -958,7 +958,7 @@ def test_gdg_archive(ansible_zos_module, dstype, format):
958958
assert result.get("dest") == archive_data_set
959959
assert f"{data_set_name}.G0001V00" in result.get("archived")
960960
assert f"{data_set_name}.G0002V00" in result.get("archived")
961-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
961+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
962962
for c_result in cmd_result.contacted.values():
963963
assert archive_data_set in c_result.get("stdout")
964964
finally:
@@ -999,7 +999,7 @@ def test_archive_into_gds(ansible_zos_module, dstype, format):
999999
for result in archive_result.contacted.values():
10001000
assert result.get("changed") is True
10011001
assert data_set_name in result.get("archived")
1002-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
1002+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
10031003
for c_result in cmd_result.contacted.values():
10041004
assert archive_data_set in c_result.get("stdout")
10051005
finally:

tests/functional/modules/test_zos_backup_restore.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,8 @@ def test_backup_into_gds(ansible_zos_module, dstype):
897897
for result in results.contacted.values():
898898
assert result.get("changed") is True
899899
assert result.get("module_stderr") is None
900-
results = hosts.all.shell(cmd=f"drm \"{ds_name}\"")
900+
escaped_ds_name = ds_name.replace('$', '\$')
901+
results = hosts.all.shell(cmd=f"drm \"{escaped_ds_name}\"")
901902
for result in results.contacted.values():
902903
assert result.get("changed") is True
903904
assert result.get("module_stderr") is None

tests/functional/modules/test_zos_copy_func.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,7 +2046,7 @@ def test_copy_dest_lock(ansible_zos_module, ds_type, f_lock ):
20462046
hosts.all.zos_data_set(name=data_set_2, state="absent")
20472047

20482048

2049-
def test_copy_dest_lock_test_with_no_opercmd_access_pds_without_force_lock(ansible_zos_module):
2049+
def test_copy_dest_lock_test_with_no_opercmd_access_pds_without_force_lock(ansible_zos_module, z_python_interpreter):
20502050
"""
20512051
This tests the module exeception raised 'msg="Unable to determine if the source {0} is in use.".format(dataset_name)'.
20522052
This this a wrapper for the actual test case `managed_user_copy_dest_lock_test_with_no_opercmd_access`.
@@ -2055,7 +2055,7 @@ def test_copy_dest_lock_test_with_no_opercmd_access_pds_without_force_lock(ansib
20552055
managed_user_test_case_name = "managed_user_copy_dest_lock_test_with_no_opercmd_access"
20562056
try:
20572057
# Initialize the Managed user API from the pytest fixture.
2058-
managed_user = ManagedUser.from_fixture(ansible_zos_module)
2058+
managed_user = ManagedUser.from_fixture(ansible_zos_module, z_python_interpreter)
20592059

20602060
# Important: Execute the test case with the managed users execution utility.
20612061
managed_user.execute_managed_user_test(

tests/functional/modules/test_zos_fetch_func.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ def test_fetch_use_data_set_qualifier(ansible_zos_module):
788788
def test_fetch_flat_create_dirs(ansible_zos_module, z_python_interpreter):
789789
z_int = z_python_interpreter
790790
hosts = ansible_zos_module
791-
remote_host = z_int[1].get("inventory").strip(",")
791+
remote_host = z_int[2].get("inventory").strip(",")
792792
dest_path = f"/tmp/{remote_host}/etc/ssh/ssh_config"
793793
params = {
794794
"src":"/etc/ssh/ssh_config",

tests/functional/modules/test_zos_operator_func.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
environment:
3737
_BPXK_AUTOCVT: "ON"
3838
ZOAU_HOME: "{0}"
39-
PYTHONPATH: "{0}/lib"
39+
PYTHONPATH: "{0}/lib/{2}"
4040
LIBPATH: "{0}/lib:{1}/lib:/lib:/usr/lib:."
4141
PATH: "{0}/bin:/bin:/usr/lpp/rsusr/ported/bin:/var/bin:/usr/lpp/rsusr/ported/bin:/usr/lpp/java/java180/J8.0_64/bin:{1}/bin:"
4242
_CEE_RUNOPTS: "FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)"
@@ -62,7 +62,7 @@
6262
ansible_host: {0}
6363
ansible_ssh_private_key_file: {1}
6464
ansible_user: {2}
65-
ansible_python_interpreter: /allpython/3.9/usr/lpp/IBM/cyp/v3r9/pyz/bin/python3.9"""
65+
ansible_python_interpreter: /allpython/3.11/usr/lpp/IBM/cyp/v3r11/pyz/bin/python3"""
6666

6767

6868
def test_zos_operator_various_command(ansible_zos_module):
@@ -212,12 +212,15 @@ def test_zos_operator_parallel_terminal(get_config):
212212
python_path = enviroment["python_path"]
213213
cut_python_path = python_path[:python_path.find('/bin')].strip()
214214
zoau = enviroment["environment"]["ZOAU_ROOT"]
215+
python_version = cut_python_path.split('/')[2]
216+
215217
try:
216218
playbook = "playbook.yml"
217219
inventory = "inventory.yml"
218220
os.system("echo {0} > {1}".format(quote(PARALLEL_RUNNING.format(
219221
zoau,
220222
cut_python_path,
223+
python_version
221224
)), playbook))
222225
os.system("echo {0} > {1}".format(quote(INVENTORY.format(
223226
hosts,

tests/functional/modules/test_zos_unarchive_func.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ def test_gdg_unarchive(ansible_zos_module, dstype, format):
11581158
assert result.get("dest") == archive_data_set
11591159
assert f"{data_set_name}.G0001V00" in result.get("archived")
11601160
assert f"{data_set_name}.G0002V00" in result.get("archived")
1161-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
1161+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
11621162
for c_result in cmd_result.contacted.values():
11631163
assert archive_data_set in c_result.get("stdout")
11641164

@@ -1178,10 +1178,10 @@ def test_gdg_unarchive(ansible_zos_module, dstype, format):
11781178
assert len(result.get("missing")) == 0
11791179
assert f"{data_set_name}.G0001V00" in result.get("targets")
11801180
assert f"{data_set_name}.G0002V00" in result.get("targets")
1181-
cmd_result = hosts.all.shell(cmd = "dls {0}.*".format(HLQ))
1181+
cmd_result = hosts.all.shell(cmd = """dls "{0}.*" """.format(HLQ))
11821182
for c_result in cmd_result.contacted.values():
11831183
assert f"{data_set_name}.G0001V00" in c_result.get("stdout")
11841184
assert f"{data_set_name}.G0002V00" in c_result.get("stdout")
11851185
finally:
1186-
hosts.all.shell(cmd=f"drm {HLQ}.*")
1186+
hosts.all.shell(cmd=f'drm "{HLQ}.*"')
11871187

tests/helpers/users.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,20 +183,22 @@ def __init__(self, model_user: str = None, remote_host: str = None, zoau_path: s
183183
self._create_ssh_config_and_directory()
184184

185185
@classmethod
186-
def from_fixture(cls, pytest_fixture):
187-
188-
remote_host = pytest_fixture["options"]["inventory"].replace(",", "")
189-
model_user = pytest_fixture["options"]["user"]
190-
inventory_hosts = pytest_fixture["options"]["inventory_manager"]._inventory.hosts
186+
def from_fixture(cls, pytest_module_fixture, pytest_interpreter_fixture):
187+
remote_host = pytest_module_fixture["options"]["inventory"].replace(",", "")
188+
model_user = pytest_module_fixture["options"]["user"]
189+
inventory_hosts = pytest_module_fixture["options"]["inventory_manager"]._inventory.hosts
191190
inventory_list = list(inventory_hosts.values())[0].vars.get('ansible_python_interpreter').split(";")
192-
zoau_path = [v for v in inventory_list if f"ZOAU_HOME=" in v][0].split('=')[1].strip() or None
193-
pythonpath = [v for v in inventory_list if f"PYTHONPATH=" in v][0].split('=')[1].strip() or None
191+
environment_vars = pytest_interpreter_fixture[0]
192+
193+
zoau_path = environment_vars.get("ZOAU_HOME")
194+
pythonpath = environment_vars.get("PYTHONPATH")
194195
pyz_path = [v for v in inventory_list if f"bin/python" in v][0].split('/bin')[0].strip() or None
196+
195197
# TODO: To make this dynamic, we need to update AC and then also test with the new fixture because
196198
# the legacy fixture is using a VOLUMES keyword while raw fixture uses extra_args. Best to move
197199
# volumes to extra_args.
198200
volumes = "000000,222222"
199-
hostpattern = pytest_fixture["options"]["host_pattern"]
201+
hostpattern = pytest_module_fixture["options"]["host_pattern"]
200202
return cls(model_user, remote_host, zoau_path, pyz_path, pythonpath, volumes, hostpattern)
201203

202204

0 commit comments

Comments
 (0)