From cc5ee6caac1576cdc90ab6b6973c317c90a6d733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Thu, 10 Jul 2025 13:30:02 -0600 Subject: [PATCH 01/39] Test --- tests/functional/modules/test_zos_replace_func.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/modules/test_zos_replace_func.py b/tests/functional/modules/test_zos_replace_func.py index cf57fd2e9e..797f690800 100644 --- a/tests/functional/modules/test_zos_replace_func.py +++ b/tests/functional/modules/test_zos_replace_func.py @@ -350,6 +350,7 @@ def test_uss_after(ansible_zos_module): params["target"] = full_path results = hosts.all.zos_replace(**params) for result in results.contacted.values(): + print(result) assert result.get("changed") == True assert result.get("target") == full_path assert result.get("found") == 2 From 2f7a1c4ac7efedc42133676a5f4e34bf7f7a9acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Tue, 15 Jul 2025 21:14:10 -0600 Subject: [PATCH 02/39] Modify action job submit --- plugins/action/zos_job_submit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/action/zos_job_submit.py b/plugins/action/zos_job_submit.py index 1f8cdf465a..5456fb3ec7 100644 --- a/plugins/action/zos_job_submit.py +++ b/plugins/action/zos_job_submit.py @@ -45,16 +45,16 @@ def run(self, tmp=None, task_vars=None): module_args = self._task.args.copy() use_template = _process_boolean(module_args.get("use_template")) - location = module_args.get("location") - if use_template and location != "local": + remote_src = module_args.get("remote_src") + if use_template and remote_src: result.update(dict( failed=True, changed=False, - msg="Use of Jinja2 templates is only valid for local files. Location is set to '{0}' but should be 'local'".format(location) + msg="Use of Jinja2 templates is only valid for local files. remote_src is set to '{0}' but should be False".format(remote_src) )) return result - if location == "local": + if not remote_src: source = self._task.args.get("src", None) From 1972bd6c1a8eee58d1309e544ccbc1ee9345f7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Tue, 15 Jul 2025 21:15:17 -0600 Subject: [PATCH 03/39] Replace structure for empty jobs --- plugins/module_utils/job.py | 45 ++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/plugins/module_utils/job.py b/plugins/module_utils/job.py index 1b0351d682..d3f2fce065 100644 --- a/plugins/module_utils/job.py +++ b/plugins/module_utils/job.py @@ -167,6 +167,7 @@ def _job_not_found(job_id, owner, job_name, dd_name): job_not_found_msg = "with the name {0}".format(job_name.upper()) job = {} + job["job_not_found"] = True job["job_id"] = job_id job["job_name"] = job_name job["subsystem"] = None @@ -175,24 +176,36 @@ def _job_not_found(job_id, owner, job_name, dd_name): job["cpu_time"] = None job["execution_node"] = None job["origin_node"] = None + job["content_type"] = None + job["creation_date"] = None + job["creation_time"] = None + job["execution_time"] = None + job["job_class"] = None + job["svc_class"] = None + job["priority"] = None + job["asid"] = None + job["queue_position"] = None + job["program_name"] = None job["ret_code"] = {} job["ret_code"]["msg"] = None job["ret_code"]["code"] = None job["ret_code"]["msg_code"] = None job["ret_code"]["msg_txt"] = "The job {0} could not be found.".format(job_not_found_msg) + job["steps"] = [] - job["class"] = "" + job["class"] = None - job["ddnames"] = [] + job["dds"] = [] dd = {} - dd["ddname"] = dd_name - dd["record_count"] = "0" - dd["id"] = "" + dd["dd_name"] = dd_name + dd["record_count"] = 0 + dd["id"] = None dd["stepname"] = None - dd["procstep"] = "" - dd["byte_count"] = "0" - job["ddnames"].append(dd) + dd["procstep"] = None + dd["byte_count"] = 0 + dd["content"] = None + job["dds"].append(dd) jobs.append(job) @@ -351,8 +364,8 @@ def _get_job_status(job_id="*", owner="*", job_name="*", dd_name=None, dd_scan=T job = {} job["job_id"] = entry.job_id job["job_name"] = entry.name - job["subsystem"] = "" - job["system"] = "" + job["subsystem"] = None + job["system"] = None job["owner"] = entry.owner job["cpu_time"] = None job["execution_node"] = None @@ -380,9 +393,9 @@ def _get_job_status(job_id="*", owner="*", job_name="*", dd_name=None, dd_scan=T job["creation_time"] = str(entry.creation_datetime)[12:] job["queue_position"] = entry.queue_position job["program_name"] = entry.program_name - job["class"] = "" + job["class"] = None job["steps"] = [] - job["ddnames"] = [] + job["dds"] = [] job["duration"] = duration if hasattr(entry, "execution_time"): job["execution_time"] = entry.execution_time @@ -444,7 +457,7 @@ def _get_job_status(job_id="*", owner="*", job_name="*", dd_name=None, dd_scan=T if dd_name not in single_dd["dd_name"]: continue else: - dd["ddname"] = single_dd["dd_name"] + dd["dd_name"] = single_dd["dd_name"] if "records" in single_dd: dd["record_count"] = single_dd["records"] @@ -495,8 +508,8 @@ def _get_job_status(job_id="*", owner="*", job_name="*", dd_name=None, dd_scan=T job["steps"].extend(_parse_steps(tmpcont)) - job["ddnames"].append(dd) - if len(job["class"]) < 1: + job["dds"].append(dd) + if job["class"] is None: job["class"] = entry.job_class if job["system"] is None: @@ -545,7 +558,7 @@ def _ddname_pattern(contents, resolve_dependencies): re.IGNORECASE, ): raise ValueError( - 'Invalid argument type for "{0}". Expected "ddname_pattern"'.format( + 'Invalid argument type for "{0}". Expected "dd_name_pattern"'.format( contents ) ) From 47510bcb30b602d57ee45765b331cb483f8dcac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Tue, 15 Jul 2025 21:16:09 -0600 Subject: [PATCH 04/39] Modify structure --- plugins/modules/zos_job_output.py | 90 +++++++++++++++---------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/plugins/modules/zos_job_output.py b/plugins/modules/zos_job_output.py index 19be248566..10c660a955 100644 --- a/plugins/modules/zos_job_output.py +++ b/plugins/modules/zos_job_output.py @@ -55,11 +55,12 @@ - The owner who ran the job. (e.g "IBMUSER", "*") type: str required: false - ddname: + dd_name: description: - Data definition name (show only this DD on a found job). (e.g "JESJCL", "?") type: str + aliases: [ddname] required: false attributes: @@ -75,21 +76,21 @@ """ EXAMPLES = r""" -- name: Job output with ddname +- name: Job output with dd_name zos_job_output: job_id: "STC02560" - ddname: "JESMSGLG" + dd_name: "JESMSGLG" -- name: JES Job output without ddname +- name: JES Job output without dd_name zos_job_output: job_id: "STC02560" -- name: JES Job output with all ddnames +- name: JES Job output with all dd_name zos_job_output: job_id: "STC*" job_name: "*" owner: "IBMUSER" - ddname: "?" + dd_name: "?" """ RETURN = r""" @@ -169,13 +170,13 @@ it represents the time elapsed from the job execution start and current time. type: str sample: 00:00:10 - ddnames: + dds: description: Data definition names. type: list elements: dict contains: - ddname: + dd_name: description: Data definition name. type: str @@ -285,34 +286,30 @@ Return code converted to integer value (when possible). type: int sample: 00 - steps: - description: - Series of JCL steps that were executed and their return codes. - type: list - elements: dict - contains: - step_name: - description: - Name of the step shown as "was executed" in the DD section. - type: str - sample: "STEP0001" - step_cc: - description: - The CC returned for this step in the DD section. - type: int - sample: 0 sample: ret_code: { "code": 0, "msg": "CC 0000", "msg_code": "0000", "msg_txt": "", - "steps": [ - { "step_name": "STEP0001", - "step_cc": 0 - } - ] } + steps: + description: + Series of JCL steps that were executed and their return codes. + type: list + elements: dict + contains: + step_name: + description: + Name of the step shown as "was executed" in the DD section. + type: str + sample: "STEP0001" + step_cc: + description: + The CC returned for this step in the DD section. + type: int + sample: 0 + sample: [ { "step_name": "STEP0001", "step_cc": 0}] sample: [ { @@ -439,12 +436,8 @@ "msg": "CC 0000", "msg_code": "0000", "msg_txt": "", - "steps": [ - { "step_name": "STEP0001", - "step_cc": 0 - } - ] }, + "steps": [{ "step_name": "STEP0001","step_cc": 0}] "system": "STL1", "subsystem": "STL1", "cpu_time": 1414, @@ -456,7 +449,7 @@ description: Indicates if any changes were made during module operation type: bool - returned: on success + returned: always """ @@ -495,7 +488,7 @@ def run_module(): job_id=dict(type="str", required=False), job_name=dict(type="str", required=False), owner=dict(type="str", required=False), - ddname=dict(type="str", required=False), + dd_name=dict(type="str", required=False, aliases=['ddname']), ) module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) @@ -504,7 +497,7 @@ def run_module(): job_id=dict(type="job_identifier", required=False), job_name=dict(type="job_identifier", required=False), owner=dict(type="str", required=False), - ddname=dict(type="str", required=False), + dd_name=dict(type="str", required=False, aliases=['ddname']), ) try: @@ -517,27 +510,34 @@ def run_module(): stderr=str(err) ) + results = {} + results["changed"] = False + job_id = module.params.get("job_id") job_name = module.params.get("job_name") owner = module.params.get("owner") - ddname = module.params.get("ddname") + dd_name = module.params.get("dd_name") if not job_id and not job_name and not owner: - module.fail_json(msg="Please provide a job_id or job_name or owner") + module.fail_json(msg="Please provide a job_id or job_name or owner", stderr="", **results) try: results = {} - results["jobs"] = job_output(job_id=job_id, owner=owner, job_name=job_name, dd_name=ddname) - results["changed"] = False + results["jobs"] = job_output(job_id=job_id, owner=owner, job_name=job_name, dd_name=dd_name) + for job in results["jobs"]: + if "job_not_found" in job: + results["changed"] = False + del job['job_not_found'] + else: + results["changed"] = True except zoau_exceptions.JobFetchException as fetch_exception: module.fail_json( - msg="ZOAU exception", - rc=fetch_exception.response.rc, - stdout=fetch_exception.response.stdout_response, + msg=f"ZOAU exception {fetch_exception.response.stdout_response} rc {fetch_exception.response.rc}", stderr=fetch_exception.response.stderr_response, + changed=False ) except Exception as e: - module.fail_json(msg=repr(e)) + module.fail_json(msg=repr(e), **results) module.exit_json(**results) From e9994dade5e06138d8227a3080557882e5e48dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Tue, 15 Jul 2025 21:17:03 -0600 Subject: [PATCH 05/39] Modify test to properly test new interface --- .../modules/test_zos_job_output_func.py | 247 ++++++++++++++++-- 1 file changed, 224 insertions(+), 23 deletions(-) diff --git a/tests/functional/modules/test_zos_job_output_func.py b/tests/functional/modules/test_zos_job_output_func.py index e1db120d2f..64caf0f3ec 100644 --- a/tests/functional/modules/test_zos_job_output_func.py +++ b/tests/functional/modules/test_zos_job_output_func.py @@ -37,6 +37,9 @@ def test_zos_job_output_no_job_id(ansible_zos_module): results = hosts.all.zos_job_output(job_id="") for result in results.contacted.values(): assert result.get("changed") is False + assert result.get("stderr") is not None + assert result.get("msg") is not None + assert result.get("failed") is True assert result.get("jobs") is None @@ -46,7 +49,9 @@ def test_zos_job_output_invalid_job_id(ansible_zos_module): for result in results.contacted.values(): assert result.get("changed") is False assert result.get("stderr") is not None + assert result.get("msg") is not None assert result.get("failed") is True + assert result.get("jobs") is None def test_zos_job_output_no_job_name(ansible_zos_module): @@ -54,6 +59,9 @@ def test_zos_job_output_no_job_name(ansible_zos_module): results = hosts.all.zos_job_output(job_name="") for result in results.contacted.values(): assert result.get("changed") is False + assert result.get("stderr") is not None + assert result.get("msg") is not None + assert result.get("failed") is True assert result.get("jobs") is None @@ -62,7 +70,46 @@ def test_zos_job_output_invalid_job_name(ansible_zos_module): results = hosts.all.zos_job_output(job_name="INVALID") for result in results.contacted.values(): assert result.get("changed") is False - assert result.get("jobs")[0].get("ret_code").get("msg_txt") is not None + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("subsystem") is None + assert job.get("system") is None + assert job.get("owner") is not None + assert job.get("cpu_time") is None + assert job.get("execution_node") is None + assert job.get("origin_node") is None + assert job.get("content_type") is None + assert job.get("creation_date") is None + assert job.get("creation_time") is None + assert job.get("execution_time") is None + assert job.get("job_class") is None + assert job.get("svc_class") is None + assert job.get("priority") is None + assert job.get("asid") is None + assert job.get("queue_position") is None + assert job.get("program_name") is None + assert job.get("class") is None + assert job.get("steps") is not None + assert job.get("dds") is not None + + rc = job.get("ret_code") + assert rc.get("msg") is None + assert rc.get("code") is None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") == "unavailable" + assert dds.get("record_count") == 0 + assert dds.get("id") is None + assert dds.get("stepname") is None + assert dds.get("procstep") is None + assert dds.get("byte_count") == 0 + assert dds.get("content") is None def test_zos_job_output_no_owner(ansible_zos_module): @@ -71,14 +118,20 @@ def test_zos_job_output_no_owner(ansible_zos_module): for result in results.contacted.values(): assert result.get("changed") is False assert result.get("msg") is not None + assert result.get("stderr") is not None + assert result.get("failed") is True + assert result.get("jobs") is None def test_zos_job_output_invalid_owner(ansible_zos_module): hosts = ansible_zos_module results = hosts.all.zos_job_output(owner="INVALID") for result in results.contacted.values(): - assert result.get("failed") is True + assert result.get("changed") is False assert result.get("stderr") is not None + assert result.get("msg") is not None + assert result.get("failed") is True + assert result.get("jobs") is None def test_zos_job_output_reject(ansible_zos_module): @@ -87,6 +140,9 @@ def test_zos_job_output_reject(ansible_zos_module): for result in results.contacted.values(): assert result.get("changed") is False assert result.get("msg") is not None + assert result.get("stderr") is not None + assert result.get("failed") is True + assert result.get("jobs") is None def test_zos_job_output_job_exists(ansible_zos_module): @@ -99,29 +155,96 @@ def test_zos_job_output_job_exists(ansible_zos_module): ) jobs = hosts.all.zos_job_submit( - src=f"{TEMP_PATH}/SAMPLE", location="uss", volume=None + src=f"{TEMP_PATH}/SAMPLE", remote_src=True, volume=None ) for job in jobs.contacted.values(): - print(job) + assert job.get("changed") is True + assert job.get("msg", False) is False assert job.get("jobs") is not None - for job in jobs.contacted.values(): - submitted_job_id = job.get("jobs")[0].get("job_id") - assert submitted_job_id is not None + job_ = job.get("jobs")[0] + assert job_.get("job_id") is not None + submitted_job_id = job_.get("job_id") + assert job_.get("job_name") is not None + assert job_.get("content_type") is not None + assert job_.get("duration") is not None + assert job_.get("execution_time") is not None + assert job_.get("job_class") is not None + assert job_.get("svc_class") is None + assert job_.get("priority") is not None + assert job_.get("asid") is not None + assert job_.get("creation_date") is not None + assert job_.get("creation_time") is not None + assert job_.get("queue_position") is not None + assert job_.get("program_name") is not None + + dds = job_.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job_.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job_.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" results = hosts.all.zos_job_output(job_id=submitted_job_id) # was SAMPLE?! for result in results.contacted.values(): - assert result.get("changed") is False + assert result.get("changed") is True + assert result.get("msg", False) is False assert result.get("jobs") is not None - assert result.get("jobs")[0].get("ret_code").get("steps") is not None - assert result.get("jobs")[0].get("ret_code").get("steps")[0].get("step_name") == "STEP0001" - assert result.get("jobs")[0].get("content_type") == "JOB" - assert result.get("jobs")[0].get("execution_time") is not None - assert "system" in result.get("jobs")[0] - assert "subsystem" in result.get("jobs")[0] - assert "cpu_time" in result.get("jobs")[0] - assert "execution_node" in result.get("jobs")[0] - assert "origin_node" in result.get("jobs")[0] + + job = result.get("jobs")[0] + assert job.get("job_id") == submitted_job_id + assert job.get("job_name") is not None + assert job.get("subsystem") is not None + assert job.get("system") is not None + assert job.get("owner") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None + assert job.get("origin_node") is not None + assert job.get("content_type") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + assert job.get("class") is not None + assert job.get("steps") is not None + assert job.get("dds") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + finally: hosts.all.file(path=TEMP_PATH, state="absent") @@ -134,17 +257,55 @@ def test_zos_job_output_job_exists_with_filtered_ddname(ansible_zos_module): cmd=f"echo {quote(JCL_FILE_CONTENTS)} > {TEMP_PATH}/SAMPLE" ) result = hosts.all.zos_job_submit( - src=f"{TEMP_PATH}/SAMPLE", location="uss", volume=None + src=f"{TEMP_PATH}/SAMPLE", remote_src=True, volume=None ) hosts.all.file(path=TEMP_PATH, state="absent") dd_name = "JESMSGLG" results = hosts.all.zos_job_output(job_name="HELLO", ddname=dd_name) for result in results.contacted.values(): - assert result.get("changed") is False + assert result.get("changed") is True + assert result.get("msg", False) is False assert result.get("jobs") is not None - for job in result.get("jobs"): - assert len(job.get("ddnames")) == 1 - assert job.get("ddnames")[0].get("ddname") == dd_name + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("subsystem") is not None + assert job.get("system") is not None + assert job.get("owner") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None + assert job.get("origin_node") is not None + assert job.get("content_type") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + assert job.get("class") is not None + assert job.get("steps") is not None + assert job.get("dds") is not None + assert len(job.get("dds")) == 1 + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" + + dds = job.get("dds")[0] + assert dds.get("dd_name") == dd_name + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + finally: hosts.all.file(path=TEMP_PATH, state="absent") @@ -153,4 +314,44 @@ def test_zos_job_submit_job_id_and_owner_included(ansible_zos_module): hosts = ansible_zos_module results = hosts.all.zos_job_output(job_id="STC00*", owner="MASTER") for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_txt") is not None + assert result.get("changed") is False + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("subsystem") is None + assert job.get("system") is None + assert job.get("owner") is not None + assert job.get("cpu_time") is None + assert job.get("execution_node") is None + assert job.get("origin_node") is None + assert job.get("content_type") is None + assert job.get("creation_date") is None + assert job.get("creation_time") is None + assert job.get("execution_time") is None + assert job.get("job_class") is None + assert job.get("svc_class") is None + assert job.get("priority") is None + assert job.get("asid") is None + assert job.get("queue_position") is None + assert job.get("program_name") is None + assert job.get("class") is None + assert job.get("steps") is not None + assert job.get("dds") is not None + + rc = job.get("ret_code") + assert rc.get("msg") is None + assert rc.get("code") is None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") == "unavailable" + assert dds.get("record_count") == 0 + assert dds.get("id") is None + assert dds.get("stepname") is None + assert dds.get("procstep") is None + assert dds.get("byte_count") == 0 + assert dds.get("content") is None From 75b09f71cb7d305900311e9e2381211a65b23545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Tue, 15 Jul 2025 21:17:48 -0600 Subject: [PATCH 06/39] Modify test on base of job submit new interface --- .../modules/test_zos_job_query_func.py | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/tests/functional/modules/test_zos_job_query_func.py b/tests/functional/modules/test_zos_job_query_func.py index 929200a748..b9160d7d2f 100644 --- a/tests/functional/modules/test_zos_job_query_func.py +++ b/tests/functional/modules/test_zos_job_query_func.py @@ -111,41 +111,45 @@ def test_zos_job_id_query_multi_wildcards_func(ansible_zos_module): cmd=f"cp {temp_path}/SAMPLE \"//'{jdata_set_name}(SAMPLE)'\"" ) results = hosts.all.zos_job_submit( - src=f"{jdata_set_name}(SAMPLE)", location="data_set", wait_time_s=10 + src=f"{jdata_set_name}(SAMPLE)", remote_src=True, wait_time=10 ) for result in results.contacted.values(): - # Default validation assert result.get("changed") is True - assert result.get("jobs") is not None assert result.get("msg", False) is False + assert result.get("jobs") is not None job = result.get("jobs")[0] - assert job.get("job_name") is not None - assert job.get("owner") is not None assert job.get("job_id") is not None + assert job.get("job_name") is not None assert job.get("content_type") is not None - assert job.get("system") is not None - assert job.get("subsystem") is not None - assert job.get("origin_node") is not None - assert job.get("execution_node") is not None - assert job.get("cpu_time") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None assert job.get("job_class") is not None + assert job.get("svc_class") is None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None assert job.get("creation_time") is not None + assert job.get("queue_position") is not None assert job.get("program_name") is not None - assert job.get("svc_class") is None - assert job.get("steps") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None step = job.get("steps")[0] assert step.get("step_name") is not None assert step.get("step_cc") is not None rc = job.get("ret_code") - assert rc.get("msg") is not None - assert rc.get("msg_code") == "0000" + assert rc.get("msg") == "CC" assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" assert rc.get("msg_txt") == "CC" fulljobid = job.get("job_id") @@ -204,40 +208,45 @@ def test_zos_job_name_query_multi_wildcards_func(ansible_zos_module): cmd=f"cp {temp_path}/SAMPLE \"//'{ndata_set_name}(SAMPLE)'\"" ) results = hosts.all.zos_job_submit( - src=f"{ndata_set_name}(SAMPLE)", location="data_set", wait_time_s=10 + src=f"{ndata_set_name}(SAMPLE)", remote_src=True, wait_time=10 ) for result in results.contacted.values(): assert result.get("changed") is True - assert result.get("jobs") is not None assert result.get("msg", False) is False + assert result.get("jobs") is not None job = result.get("jobs")[0] - assert job.get("job_name") is not None - assert job.get("owner") is not None assert job.get("job_id") is not None + assert job.get("job_name") is not None assert job.get("content_type") is not None - assert job.get("system") is not None - assert job.get("subsystem") is not None - assert job.get("origin_node") is not None - assert job.get("execution_node") is not None - assert job.get("cpu_time") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None assert job.get("job_class") is not None + assert job.get("svc_class") is None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None assert job.get("creation_time") is not None + assert job.get("queue_position") is not None assert job.get("program_name") is not None - assert job.get("svc_class") is None - assert job.get("steps") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None step = job.get("steps")[0] assert step.get("step_name") is not None assert step.get("step_cc") is not None rc = job.get("ret_code") - assert rc.get("msg") is not None - assert rc.get("msg_code") == "0000" + assert rc.get("msg") == "CC" assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" assert rc.get("msg_txt") == "CC" jobname = "HE*L*" From f21e73e994a2408732ba9ad0d9ba188c1bd78c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Tue, 15 Jul 2025 21:20:54 -0600 Subject: [PATCH 07/39] Be alignt --- tests/functional/modules/test_zos_replace_func.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/functional/modules/test_zos_replace_func.py b/tests/functional/modules/test_zos_replace_func.py index 797f690800..cf57fd2e9e 100644 --- a/tests/functional/modules/test_zos_replace_func.py +++ b/tests/functional/modules/test_zos_replace_func.py @@ -350,7 +350,6 @@ def test_uss_after(ansible_zos_module): params["target"] = full_path results = hosts.all.zos_replace(**params) for result in results.contacted.values(): - print(result) assert result.get("changed") == True assert result.get("target") == full_path assert result.get("found") == 2 From 33f8a0f95a8ccc571031b3aa6a3378850af22366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Wed, 16 Jul 2025 16:01:26 -0600 Subject: [PATCH 08/39] Modify job submit --- plugins/modules/zos_job_submit.py | 388 ++++---- .../modules/test_zos_job_submit_func.py | 904 +++++++++++++++--- 2 files changed, 946 insertions(+), 346 deletions(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index 1852327ec5..bf01553569 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -46,35 +46,31 @@ - When using a generation data set, only already created generations are valid. If either the relative name is positive, or negative but not found, the module will fail. - location: + remote_src: required: false - default: data_set - type: str - choices: - - data_set - - uss - - local + default: true + type: bool description: - - The JCL location. Supported choices are C(data_set), C(uss) or C(local). - - C(data_set) can be a PDS, PDSE, sequential data set, or a generation data set. - - C(uss) means the JCL location is located in UNIX System Services (USS). - - C(local) means locally to the Ansible control node. - wait_time_s: + - If set to C(false), the module searches for C(src) at the local machine. + - If set to C(true), the module goes to the remote/target machine for C(src). + wait_time: required: false default: 10 type: int description: - - Option I(wait_time_s) is the total time that module + - Option I(wait_time) is the total time that module L(zos_job_submit,./zos_job_submit.html) will wait for a submitted job to complete. The time begins when the module is executed on the managed node. - - I(wait_time_s) is measured in seconds and must be a value greater than 0 + - I(wait_time) is measured in seconds and must be a value greater than 0 and less than 86400. - - The module can submit and forget jobs by setting I(wait_time_s) to 0. This way the + - The module can submit and forget jobs by setting I(wait_time) to 0. This way the module will not try to retrieve the job details other than job id. Job details and contents can be retrieved later by using L(zos_job_query,./zos_job_query.html) or L(zos_job_output,./zos_job_output.html) if needed. + - If I(remote_src=False) and I(wait_time) is 0 the module not gonna clean the copy + of the file on remote system, to avoid problems on the submission of the job. max_rc: required: false type: int @@ -96,12 +92,12 @@ - When configured, the L(zos_job_submit,./zos_job_submit.html) will try to catalog the data set for the volume serial. If it is not able to, the module will fail. - - Ignored for I(location=uss) and I(location=local). + - Ignored for I(remote_src=False). encoding: description: - Specifies which encoding the local JCL file should be converted from and to, before submitting the job. - - This option is only supported for when I(location=local). + - This option is only supported for when I(remote_src=False). - If this parameter is not provided, and the z/OS systems default encoding can not be identified, the JCL file will be converted from UTF-8 to IBM-1047 by default, otherwise the module will detect the z/OS system @@ -194,13 +190,13 @@ description: Total duration time of the job execution, if it has finished. type: str sample: 00:00:10 - ddnames: + dds: description: Data definition names. type: list elements: dict contains: - ddname: + dd_name: description: Data definition name. type: str @@ -298,34 +294,31 @@ is the case of a job that errors or is active. type: int sample: 0 - steps: - description: - Series of JCL steps that were executed and their return codes. - type: list - elements: dict - contains: - step_name: - description: - Name of the step shown as "was executed" in the DD section. - type: str - sample: "STEP0001" - step_cc: - description: - The CC returned for this step in the DD section. - type: int - sample: 0 sample: ret_code: { "code": 0, "msg": "CC 0000", "msg_code": "0000", "msg_txt": "", - "steps": [ - { "step_name": "STEP0001", - "step_cc": 0 - }, - ] } + steps: + description: + Series of JCL steps that were executed and their return codes. + type: list + elements: dict + contains: + step_name: + description: + Name of the step shown as "was executed" in the DD section. + type: str + sample: "STEP0001" + step_cc: + description: + The CC returned for this step in the DD section. + type: int + sample: 0 + sample: + "steps": [{ "step_name": "STEP0001", "step_cc": 0 }] job_class: description: Job class for this job. @@ -367,38 +360,11 @@ The name of the program found in the job's last completed step found in the PGM parameter. type: str sample: "IEBGENER" - system: - description: - The job entry system that MVS uses to do work. - type: str - sample: STL1 - subsystem: - description: - The job entry subsystem that MVS uses to do work. - type: str - sample: STL1 - cpu_time: - description: - Sum of the CPU time used by each job step, in microseconds. - type: int - sample: 5 - execution_node: - description: - Execution node that picked the job and executed it. - type: str - sample: "STL1" - origin_node: - description: - Origin node that submitted the job. - type: str - sample: "STL1" - sample: [ { - "class": "K", "content_type": "JOB", - "ddnames": [ + "dds": [ { "byte_count": "677", "content": [ @@ -419,7 +385,7 @@ "- 12 SYSOUT SPOOL KBYTES", "- 0.00 MINUTES EXECUTION TIME" ], - "ddname": "JESMSGLG", + "dd_name": "JESMSGLG", "id": "2", "procstep": "", "record_count": "16", @@ -476,7 +442,7 @@ " 15 ++SYSPRINT DD SYSOUT=* ", " ++* " ], - "ddname": "JESJCL", + "dd_name": "JESJCL", "id": "3", "procstep": "", "record_count": "47", @@ -530,7 +496,7 @@ " IEF033I JOB/DBDGEN00/STOP 2020073.1250 ", " CPU: 0 HR 00 MIN 00.03 SEC SRB: 0 HR 00 MIN 00.00 SEC " ], - "ddname": "JESYSMSG", + "dd_name": "JESYSMSG", "id": "4", "procstep": "", "record_count": "44", @@ -585,7 +551,7 @@ " **** END OF MESSAGE SUMMARY REPORT **** ", " " ], - "ddname": "SYSPRINT", + "dd_name": "SYSPRINT", "id": "102", "procstep": "L", "record_count": "45", @@ -594,18 +560,13 @@ ], "job_id": "JOB00361", "job_name": "DBDGEN00", - "owner": "OMVSADM", "ret_code": { "code": 0, "msg": "CC 0000", "msg_code": "0000", - "msg_txt": "", - "steps": [ - { "step_name": "DLORD6", - "step_cc": 0 - } - ] + "msg_txt": "" }, + "steps": [ { "step_name": "DLORD6", "step_cc": 0 }] "job_class": "K", "execution_time": "00:00:10", "svc_class": "?", @@ -615,11 +576,6 @@ "creation_date": "2023-05-03", "creation_time": "12:13:00", "queue_position": 3, - "subsystem": "STL1", - "system": "STL1", - "cpu_time": 1, - "execution_node": "STL1", - "origin_node": "STL1" } ] """ @@ -628,19 +584,19 @@ - name: Submit JCL in a PDSE member. zos_job_submit: src: HLQ.DATA.LLQ(SAMPLE) - location: data_set + remote_src: true register: response - name: Submit JCL in USS with no DDs in the output. zos_job_submit: src: /u/tester/demo/sample.jcl - location: uss + remote_src: true return_output: false - name: Convert local JCL to IBM-037 and submit the job. zos_job_submit: src: /Users/maxy/ansible-playbooks/provision/sample.jcl - location: local + remote_src: false encoding: from: ISO8859-1 to: IBM-037 @@ -648,36 +604,36 @@ - name: Submit JCL in an uncataloged PDSE on volume P2SS01. zos_job_submit: src: HLQ.DATA.LLQ(SAMPLE) - location: data_set + remote_src: true volume: P2SS01 - name: Submit a long running PDS job and wait up to 30 seconds for completion. zos_job_submit: src: HLQ.DATA.LLQ(LONGRUN) - location: data_set - wait_time_s: 30 + remote_src: true + wait_time: 30 - name: Submit a long running PDS job and wait up to 30 seconds for completion. zos_job_submit: src: HLQ.DATA.LLQ(LONGRUN) - location: data_set - wait_time_s: 30 + remote_src: true + wait_time: 30 - name: Submit JCL and set the max return code the module should fail on to 16. zos_job_submit: src: HLQ.DATA.LLQ - location: data_set + remote_src: true max_rc: 16 - name: Submit JCL from the latest generation data set in a generation data group. zos_job_submit: src: HLQ.DATA.GDG(0) - location: data_set + remote_src: true - name: Submit JCL from a previous generation data set in a generation data group. zos_job_submit: src: HLQ.DATA.GDG(-2) - location: data_set + remote_src: true """ from ansible_collections.ibm.ibm_zos_core.plugins.module_utils.encode import ( @@ -820,7 +776,7 @@ def submit_src_jcl(module, src, src_name=None, timeout=0, is_unix=True, start_ti job_fetched = jobs.fetch_multiple(job_submitted.job_id)[0] job_fetch_rc = job_fetched.return_code job_fetch_status = job_fetched.status - # Allow for jobs that need more time to be fectched to run the wait_time_s + # Allow for jobs that need more time to be fectched to run the wait_time except zoau_exceptions.JobFetchException as err: if duration >= timeout: raise err @@ -885,52 +841,6 @@ def submit_src_jcl(module, src, src_name=None, timeout=0, is_unix=True, start_ti return job_submitted.job_id if job_submitted else None, duration -def build_return_schema(result): - """ Builds return values schema with empty values. - - Parameters - ---------- - result : dict - Dictionary used to return values at execution finalization. - - Returns - ------- - dict - Dictionary used to return values at execution finalization. - """ - result = { - "jobs": [], - "job_id": None, - "job_name": None, - "duration": None, - "execution_time": None, - "ddnames": { - "ddname": None, - "record_count": None, - "id": None, - "stepname": None, - "procstep": None, - "byte_count": None, - "content": [], - }, - "ret_code": { - "code": None, - "msg": None, - "msg_code": None, - "msg_txt": None, - "steps": [], - }, - "job_class": None, - "svc_class": None, - "priority": None, - "asid": None, - "creation_date": None, - "queue_position": None, - "program_name": None, - } - return result - - def run_module(): """Initialize module. @@ -939,14 +849,14 @@ def run_module(): fail_json Parameter verification failed. fail_json - The value for option 'wait_time_s' is not valid. + The value for option 'wait_time' is not valid. """ module_args = dict( src=dict(type="str", required=True), - location=dict( - type="str", - default="data_set", - choices=["data_set", "uss", "local"], + remote_src=dict( + type="bool", + default=True, + required=False ), encoding=dict( type="dict", @@ -966,7 +876,7 @@ def run_module(): ), volume=dict(type="str", required=False), return_output=dict(type="bool", required=False, default=True), - wait_time_s=dict(type="int", default=10), + wait_time=dict(type="int", default=10), max_rc=dict(type="int", required=False), use_template=dict(type='bool', default=False), template_parameters=dict( @@ -1014,10 +924,10 @@ def run_module(): arg_defs = dict( src=dict(arg_type="data_set_or_path", required=True), - location=dict( - arg_type="str", - default="data_set", - choices=["data_set", "uss", "local"], + remote_src=dict( + arg_type="bool", + default=True, + required=False ), from_encoding=dict( arg_type="encoding", default=Defaults.DEFAULT_ASCII_CHARSET, required=False), @@ -1026,7 +936,7 @@ def run_module(): ), volume=dict(arg_type="volume", required=False), return_output=dict(arg_type="bool", default=True), - wait_time_s=dict(arg_type="int", required=False, default=10), + wait_time=dict(arg_type="int", required=False, default=10), max_rc=dict(arg_type="int", required=False), ) @@ -1042,22 +952,21 @@ def run_module(): msg="Parameter verification failed", stderr=str(err)) # Extract values from set module options - location = parsed_args.get("location") + remote_src = parsed_args.get("remote_src") volume = parsed_args.get("volume") src = parsed_args.get("src") return_output = parsed_args.get("return_output") - wait_time_s = parsed_args.get("wait_time_s") + wait_time = parsed_args.get("wait_time") max_rc = parsed_args.get("max_rc") - temp_file = parsed_args.get("src") if location == "local" else None + temp_file = parsed_args.get("src") if not remote_src else None # Default 'changed' is False in case the module is not able to execute result = dict(changed=False) # Builds return value schema to make sure we return the return values schema. - result = build_return_schema(result) - if wait_time_s < 0 or wait_time_s > MAX_WAIT_TIME_S: + if wait_time < 0 or wait_time > MAX_WAIT_TIME_S: result["failed"] = True - result["msg"] = ("The value for option 'wait_time_s' is not valid, it must " + result["msg"] = ("The value for option 'wait_time' is not valid, it must " "be greater than 0 and less than {0}.".format(str(MAX_WAIT_TIME_S))) module.fail_json(**result) @@ -1065,68 +974,72 @@ def run_module(): duration = 0 start_time = timer() - if location == "data_set": - # Resolving a relative GDS name and escaping special symbols if needed. - src_data = data_set.MVSDataSet(src) - - # Checking that the source is actually present on the system. - if volume is not None: - volumes = [volume] - # Get the data set name to catalog it. - src_ds_name = data_set.extract_dsname(src_data.name) - present, changed = DataSet.attempt_catalog_if_necessary(src_ds_name, volumes) - - if not present: - module.fail_json( - msg=(f"Unable to submit job {src_data.name} because the data set could " - f"not be cataloged on the volume {volume}.") - ) - elif data_set.is_member(src_data.name): - if not DataSet.data_set_member_exists(src_data.name): - module.fail_json(msg=f"Cannot submit job, the data set member {src_data.raw_name} was not found.") + if remote_src: + if "/" in src: + if path.exists(src): + if path.isfile(src): + job_submitted_id, duration = submit_src_jcl( + module, src, src_name=src, timeout=wait_time, is_unix=True) + else: + module.fail_json(msg=f"Unable to submit job {src} is a folder, must be a file.", **result) + else: + module.fail_json(msg=f"Unable to submit job {src} does not exists.", **result) else: - if not DataSet.data_set_exists(src_data.name): - module.fail_json(msg=f"Cannot submit job, the data set {src_data.raw_name} was not found.") + # Resolving a relative GDS name and escaping special symbols if needed. + src_data = data_set.MVSDataSet(src) + + # Checking that the source is actually present on the system. + if volume is not None: + volumes = [volume] + # Get the data set name to catalog it. + src_ds_name = data_set.extract_dsname(src_data.name) + present, changed = DataSet.attempt_catalog_if_necessary(src_ds_name, volumes) + + if not present: + module.fail_json( + msg=(f"Unable to submit job {src_data.name} because the data set could " + f"not be cataloged on the volume {volume}."), **result + ) + elif data_set.is_member(src_data.name): + if not DataSet.data_set_member_exists(src_data.name): + module.fail_json(msg=f"Cannot submit job, the data set member {src_data.raw_name} was not found.", **result) + else: + if not DataSet.data_set_exists(src_data.name): + module.fail_json(msg=f"Cannot submit job, the data set {src_data.raw_name} was not found.", **result) + job_submitted_id, duration = submit_src_jcl( + module, src_data.name, src_name=src_data.raw_name, timeout=wait_time, is_unix=False, start_time=start_time) + else: job_submitted_id, duration = submit_src_jcl( - module, src_data.name, src_name=src_data.raw_name, timeout=wait_time_s, is_unix=False, start_time=start_time) - elif location == "uss": - job_submitted_id, duration = submit_src_jcl( - module, src, src_name=src, timeout=wait_time_s, is_unix=True) - elif location == "local": - job_submitted_id, duration = submit_src_jcl( - module, src, src_name=src, timeout=wait_time_s, is_unix=True) + module, src, src_name=src, timeout=wait_time, is_unix=True) # Explictly pass None for the unused args else a default of '*' will be # used and return undersirable results job_output_txt = None - result['job_id'] = job_submitted_id is_changed = True # If wait_time_s is 0, we do a deploy and forget strategy. - if wait_time_s != 0: + if wait_time != 0: try: job_output_txt = job_output( job_id=job_submitted_id, owner=None, job_name=None, dd_name=None, - dd_scan=return_output, duration=duration, timeout=wait_time_s, start_time=start_time) + dd_scan=return_output, duration=duration, timeout=wait_time, start_time=start_time) # This is resolvig a bug where the duration coming from job_output is passed by value, duration # being an immutable type can not be changed and must be returned or accessed from the job.py. - if job_output is not None: + if job_output_txt is not None: duration = job_output_txt[0].get("duration") if not None else duration - result["execution_time"] = job_output_txt[0].get("execution_time") - - result["duration"] = duration + job_output_txt = parsing_job_response(job_output_txt, duration) - if duration >= wait_time_s: + if duration >= wait_time: result["failed"] = True result["changed"] = False _msg = ("The JCL submitted with job id {0} but appears to be a long " "running job that exceeded its maximum wait time of {1} " "second(s). Consider using module zos_job_query to poll for " - "a long running job or increase option 'wait_time_s' to a value " - "greater than {2}.".format(str(job_submitted_id), str(wait_time_s), str(duration))) + "a long running job or increase option 'wait_time' to a value " + "greater than {2}.".format(str(job_submitted_id), str(wait_time), str(duration))) _msg_suffix = ("Consider using module zos_job_query to poll for " - "a long running job or increase option 'wait_time_s' to a value " + "a long running job or increase option 'wait_time' to a value " "greater than {0}.".format(str(duration))) if job_output_txt is not None: @@ -1142,6 +1055,7 @@ def run_module(): if job_output_txt: result["jobs"] = job_output_txt job_ret_code = job_output_txt[0].get("ret_code") + steps = job_output_txt[0].get("steps") if job_ret_code: job_ret_code_msg = job_ret_code.get("msg") @@ -1149,7 +1063,7 @@ def run_module(): job_ret_code_msg_code = job_ret_code.get("msg_code") if return_output is True and max_rc is not None: - is_changed = assert_valid_return_code(max_rc, job_ret_code_code, job_ret_code, result) + is_changed = assert_valid_return_code(max_rc, job_ret_code_code, job_ret_code, steps, result) if job_ret_code_msg is not None: if re.search("^(?:{0})".format("|".join(JOB_STATUSES)), job_ret_code_msg): @@ -1162,8 +1076,8 @@ def run_module(): raise Exception(_msg) if job_ret_code_code is not None and job_ret_code_msg == 'NOEXEC': - job_dd_names = job_output_txt[0].get("ddnames") - jes_jcl_dd = search_dictionaries("ddname", "JESJCL", job_dd_names) + job_dd_names = job_output_txt[0].get("dds") + jes_jcl_dd = search_dictionaries("dd_name", "JESJCL", job_dd_names) # These are the conditions for a job run with TYPRUN=COPY. if not jes_jcl_dd: job_ret_code.update({"msg": "TYPRUN=COPY"}) @@ -1179,8 +1093,8 @@ def run_module(): # so further analyze the # JESJCL DD to figure out if its a TYPRUN job - job_dd_names = job_output_txt[0].get("ddnames") - jes_jcl_dd = search_dictionaries("ddname", "JESJCL", job_dd_names) + job_dd_names = job_output_txt[0].get("dds") + jes_jcl_dd = search_dictionaries("dd_name", "JESJCL", job_dd_names) # Its possible jobs don't have a JESJCL which are active and this would # cause an index out of range error. @@ -1237,7 +1151,7 @@ def run_module(): else: _msg = "The job output log is unavailable." result["stderr"] = _msg - result["jobs"] = None + result["jobs"] = [] raise Exception(_msg) except Exception as err: result["failed"] = True @@ -1251,14 +1165,15 @@ def run_module(): finally: if temp_file is not None: shutil.rmtree(path.dirname(temp_file)) + else: + result["jobs"] = build_empty_response(job_submitted_id) # If max_rc is set, we don't want to default to changed=True, rely on 'is_changed' result["changed"] = True if is_changed else False - result["failed"] = False module.exit_json(**result) -def assert_valid_return_code(max_rc, job_rc, ret_code, result): +def assert_valid_return_code(max_rc, job_rc, ret_code, steps, result): """Asserts valid return code. Parameters @@ -1301,7 +1216,7 @@ def assert_valid_return_code(max_rc, job_rc, ret_code, result): result["stderr"] = _msg raise Exception(_msg) - for step in ret_code["steps"]: + for step in steps: step_cc_rc = int(step["step_cc"]) step_name_for_rc = step["step_name"] if step_cc_rc > max_rc: @@ -1325,6 +1240,65 @@ def assert_valid_return_code(max_rc, job_rc, ret_code, result): return True +def parsing_job_response(jobs_raw, duration): + """_summary_ + + Args: + jobs_raw (_type_): _description_ + """ + job = jobs_raw[0] + jobs = [] + for job in jobs_raw: + job_dict = { + "job_id": job.get("job_id"), + "job_name": job.get("job_name"), + "content_type": job.get("content_type"), + "duration": duration, + "execution_time": job.get("execution_time"), + "dds": job.get("dds"), + "ret_code": job.get("ret_code"), + "steps": job.get("steps"), + "job_class": job.get("job_class"), + "svc_class": job.get("svc_class"), + "priority": job.get("priority"), + "asid": job.get("asid"), + "creation_date": job.get("creation_date"), + "creation_time": job.get("creation_time"), + "queue_position": job.get("queue_position"), + "program_name": job.get("program_name"), + } + jobs.append(job_dict) + return jobs + + +def build_empty_response(job_submitted_id): + """_summary_ + + Args: + jobs_raw (_type_): _description_ + """ + jobs = [] + job_dict = { + "job_id": job_submitted_id, + "job_name": None, + "content_type": None, + "duration": None, + "execution_time": None, + "dds": [], + "ret_code": {"code": None, "msg": None, "msg_code": None, "msg_txt": None,}, + "steps": [], + "job_class": None, + "svc_class": None, + "priority": None, + "asid": None, + "creation_date": None, + "creation_time": None, + "queue_position": None, + "program_name": None, + } + jobs.append(job_dict) + return jobs + def main(): run_module() diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index fca001a3ec..90d5099ca2 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -416,7 +416,7 @@ - name: Submit async job. ibm.ibm_zos_core.zos_job_submit: src: {3} - location: local + remote_src: false async: 45 poll: 0 register: job_task @@ -475,22 +475,51 @@ def test_job_submit_pds(ansible_zos_module, location): ) if bool(location.get("default_location")): results = hosts.all.zos_job_submit( - src="{0}(SAMPLE)".format(data_set_name), wait_time_s=30 + src="{0}(SAMPLE)".format(data_set_name), remote_src=True, wait_time=30 ) else: results = hosts.all.zos_job_submit( - src="{0}(SAMPLE)".format(data_set_name), location="data_set", wait_time_s=30 + src="{0}(SAMPLE)".format(data_set_name), remote_src=True, wait_time=30 ) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 assert result.get("changed") is True - assert "system" in result.get("jobs")[0] - assert "subsystem" in result.get("jobs")[0] - assert "cpu_time" in result.get("jobs")[0] - assert "execution_node" in result.get("jobs")[0] - assert "origin_node" in result.get("jobs")[0] + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") hosts.all.zos_data_set(name=data_set_name, state="absent") @@ -515,12 +544,46 @@ def test_job_submit_pds_special_characters(ansible_zos_module): ) results = hosts.all.zos_job_submit( src="{0}(SAMPLE)".format(data_set_name_special_chars), - location="data_set", + remote_src=True, ) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") hosts.all.zos_data_set(name=data_set_name_special_chars, state="absent") @@ -535,13 +598,46 @@ def test_job_submit_uss(ansible_zos_module): cmd="echo {0} > {1}/SAMPLE".format(quote(JCL_FILE_CONTENTS), temp_path) ) results = hosts.all.zos_job_submit( - src=f"{temp_path}/SAMPLE", location="uss", volume=None + src=f"{temp_path}/SAMPLE", remote_src=True, volume=None ) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 - assert result.get("jobs")[0].get("content_type") == "JOB" assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") @@ -555,35 +651,36 @@ def test_job_submit_and_forget_uss(ansible_zos_module): cmd="echo {0} > {1}/SAMPLE".format(quote(JCL_FILE_CONTENTS), temp_path) ) results = hosts.all.zos_job_submit( - src=f"{temp_path}/SAMPLE", location="uss", volume=None, wait_time_s=0, + src=f"{temp_path}/SAMPLE", remote_src=True, volume=None, wait_time=0, ) for result in results.contacted.values(): - assert result.get("job_id") is not None assert result.get("changed") is True - assert len(result.get("jobs")) == 0 - assert result.get("job_name") is None - assert result.get("duration") is None - assert result.get("execution_time") is None - assert result.get("ddnames") is not None - assert result.get("ddnames").get("ddname") is None - assert result.get("ddnames").get("record_count") is None - assert result.get("ddnames").get("id") is None - assert result.get("ddnames").get("stepname") is None - assert result.get("ddnames").get("procstep") is None - assert result.get("ddnames").get("byte_count") is None - assert len(result.get("ddnames").get("content")) == 0 - assert result.get("ret_code") is not None - assert result.get("ret_code").get("msg") is None - assert result.get("ret_code").get("msg_code") is None - assert result.get("ret_code").get("code") is None - assert len(result.get("ret_code").get("steps")) == 0 - assert result.get("job_class") is None - assert result.get("svc_class") is None - assert result.get("priority") is None - assert result.get("asid") is None - assert result.get("creation_time") is None - assert result.get("queue_position") is None - assert result.get("program_name") is None + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is None + assert job.get("content_type") is None + assert job.get("duration") is None + assert job.get("execution_time") is None + assert job.get("job_class") is None + assert job.get("svc_class") is None + assert job.get("priority") is None + assert job.get("asid") is None + assert job.get("creation_date") is None + assert job.get("creation_time") is None + assert job.get("queue_position") is None + assert job.get("program_name") is None + assert job.get("dds") is not None + assert len(job.get("dds")) == 0 + assert job.get("steps") is not None + assert len(job.get("steps")) == 0 + rc = job.get("ret_code") + assert rc.get("msg") is None + assert rc.get("code") is None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is None finally: hosts.all.file(path=temp_path, state="absent") @@ -593,13 +690,46 @@ def test_job_submit_local(ansible_zos_module): with open(tmp_file.name, "w",encoding="utf-8") as f: f.write(JCL_FILE_CONTENTS) hosts = ansible_zos_module - results = hosts.all.zos_job_submit(src=tmp_file.name, location="local", wait_time_s=10) + results = hosts.all.zos_job_submit(src=tmp_file.name, remote_src=False, wait_time=10) for result in results.contacted.values(): - print(result) - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" def test_job_submit_local_extra_r(ansible_zos_module): @@ -607,12 +737,46 @@ def test_job_submit_local_extra_r(ansible_zos_module): with open(tmp_file.name, "w",encoding="utf-8") as f: f.write(JCL_FILE_CONTENTS_BACKSLASH_R) hosts = ansible_zos_module - results = hosts.all.zos_job_submit(src=tmp_file.name, location="local", wait_time_s=10) + results = hosts.all.zos_job_submit(src=tmp_file.name, remote_src=False, wait_time=10) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" def test_job_submit_local_badjcl(ansible_zos_module): @@ -620,11 +784,12 @@ def test_job_submit_local_badjcl(ansible_zos_module): with open(tmp_file.name, "w",encoding="utf-8") as f: f.write(JCL_FILE_CONTENTS_BAD) hosts = ansible_zos_module - results = hosts.all.zos_job_submit(src=tmp_file.name, location="local", wait_time_s=10) + results = hosts.all.zos_job_submit(src=tmp_file.name, remote_src=False, wait_time=10) for result in results.contacted.values(): - # Expecting: The job completion code (CC) was not in the job log....." assert result.get("changed") is False + assert result.get("msg") is not None + assert result.get("failed") is True assert re.search(r'completion code', repr(result.get("msg"))) @@ -655,13 +820,47 @@ def test_job_submit_pds_volume(ansible_zos_module, volumes_on_systems): results = hosts.all.zos_job_submit( src=data_set_name+"(SAMPLE)", - location="data_set", + remote_src=True, volume=volume_1 ) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 - assert result.get('changed') is True + assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") hosts.all.zos_data_set(name=data_set_name, state="absent") @@ -689,14 +888,46 @@ def test_job_submit_pds_5_sec_job_wait_15(ansible_zos_module): hosts = ansible_zos_module results = hosts.all.zos_job_submit(src=data_set_name+"(BPXSLEEP)", - location="data_set", wait_time_s=wait_time_s) + remote_src=True, wait_time=wait_time_s) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 - assert result.get('changed') is True - assert result.get('duration') <= wait_time_s - assert result.get('execution_time') is not None + assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") <= wait_time_s + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") hosts.all.zos_data_set(name=data_set_name, state="absent") @@ -724,18 +955,51 @@ def test_job_submit_pds_30_sec_job_wait_60(ansible_zos_module): hosts = ansible_zos_module results = hosts.all.zos_job_submit(src=data_set_name+"(BPXSLEEP)", - location="data_set", wait_time_s=wait_time_s) + remote_src=True, wait_time=wait_time_s) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 - assert result.get('changed') is True - assert result.get('duration') <= wait_time_s - assert result.get('execution_time') is not None + assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") <= wait_time_s + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") hosts.all.zos_data_set(name=data_set_name, state="absent") + def test_job_submit_pds_30_sec_job_wait_10_negative(ansible_zos_module): """This submits a 30 second job and only waits 10 seconds""" try: @@ -759,15 +1023,45 @@ def test_job_submit_pds_30_sec_job_wait_10_negative(ansible_zos_module): hosts = ansible_zos_module results = hosts.all.zos_job_submit(src=data_set_name+"(BPXSLEEP)", - location="data_set", wait_time_s=wait_time_s) + remote_src=True, wait_time=wait_time_s) for result in results.contacted.values(): + assert result.get("changed") is False assert result.get("msg") is not None - assert result.get('changed') is False - assert result.get('duration') >= wait_time_s - # expecting at least "long running job that exceeded its maximum wait" + assert result.get("failed") is True assert re.search(r'exceeded', repr(result.get("msg"))) - assert result.get('execution_time') is not None + assert result.get("jobs") is not None + job = result.get("jobs")[0] + + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") >= wait_time_s + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is not None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is None + assert len(job.get("steps")) == 0 + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") == 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") == 0 + assert dds.get("content") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "AC" + assert rc.get("code") is None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is not None finally: hosts.all.file(path=temp_path, state="absent") hosts.all.zos_data_set(name=data_set_name, state="absent") @@ -797,22 +1091,23 @@ def test_job_submit_max_rc(ansible_zos_module, args): results = hosts.all.zos_job_submit( src=tmp_file.name, - location="local", + remote_src=False, max_rc=args["max_rc"], - wait_time_s=args["wait_time_s"] + wait_time=args["wait_time_s"] ) for result in results.contacted.values(): # Should fail normally as a non-zero RC will result in job submit failure if args["max_rc"] is None: + assert result.get("changed") is False assert result.get("msg") is not None - assert result.get('changed') is False + assert result.get("failed") is True # On busy systems, it is possible that the duration even for a job with a non-zero return code # will take considerable time to obtain the job log and thus you could see either error msg below #Expecting: - "The job return code 8 was non-zero in the job output, this job has failed" # - Consider using module zos_job_query to poll for a long running job or # increase option \\'wait_times_s` to a value greater than 10.", - duration = result.get('duration') + duration = result.get("jobs")[0].get('duration') if duration >= args["wait_time_s"]: re.search(r'long running job', repr(result.get("msg"))) @@ -821,13 +1116,14 @@ def test_job_submit_max_rc(ansible_zos_module, args): # Should fail with normally as well, job fails with an RC 8 yet max is set to 4 elif args["max_rc"] == 4: - assert result.get("msg") is not None - assert result.get('changed') is False # Expecting "The job return code, # 'ret_code[code]' 8 for the submitted job is greater # than the value set for option 'max_rc' 4. # Increase the value for 'max_rc' otherwise # this job submission has failed. + assert result.get("changed") is False + assert result.get("msg") is not None + assert result.get("failed") is True assert re.search( r'the submitted job is greater than the value set for option', repr(result.get("msg")) @@ -837,9 +1133,43 @@ def test_job_submit_max_rc(ansible_zos_module, args): # Will not fail and as the max_rc is set to 12 and the rc is 8 is a change true # there are other possibilities like an ABEND or JCL ERROR will fail this even # with a MAX RC - assert result.get("msg") is None - assert result.get('changed') is True - assert result.get("jobs")[0].get("ret_code").get("code") < 12 + assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") < 12 + assert rc.get("msg_code") != "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=tmp_file.name, state="absent") @@ -909,15 +1239,49 @@ def test_job_submit_jinja_template(ansible_zos_module, args): results = hosts.all.zos_job_submit( src=tmp_file.name, - location="local", + remote_src=False, use_template=True, template_parameters=args["options"] ) for result in results.contacted.values(): - assert result.get('changed') is True - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 + assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: os.remove(tmp_file.name) @@ -933,16 +1297,50 @@ def test_job_submit_full_input(ansible_zos_module): ) results = hosts.all.zos_job_submit( src=f"{temp_path}/SAMPLE", - location="uss", + remote_src=True, volume=None, # This job used to set wait=True, but since it has been deprecated # and removed, it now waits up to 30 seconds. - wait_time_s=30 + wait_time=30 ) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") @@ -952,11 +1350,44 @@ def test_negative_job_submit_local_jcl_no_dsn(ansible_zos_module): with open(tmp_file.name, "w",encoding="utf-8") as f: f.write(JCL_FILE_CONTENTS_NO_DSN) hosts = ansible_zos_module - results = hosts.all.zos_job_submit(src=tmp_file.name, wait_time_s=20, location="local") + results = hosts.all.zos_job_submit(src=tmp_file.name, wait_time=20, remote_src=False) for result in results.contacted.values(): assert result.get("changed") is False + assert result.get("msg") is not None assert re.search(r'completion code', repr(result.get("msg"))) - assert result.get("jobs")[0].get("job_id") is not None + assert result.get("failed") is True + assert result.get("jobs") is not None + job = result.get("jobs")[0] + + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + assert len(job.get("steps")) == 0 + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "JCLERR" + assert rc.get("code") is None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is not None def test_negative_job_submit_local_jcl_invalid_user(ansible_zos_module): @@ -964,16 +1395,48 @@ def test_negative_job_submit_local_jcl_invalid_user(ansible_zos_module): with open(tmp_file.name, "w",encoding="utf-8") as f: f.write(JCL_FILE_CONTENTS_INVALID_USER) hosts = ansible_zos_module - results = hosts.all.zos_job_submit(src=tmp_file.name, location="local") + results = hosts.all.zos_job_submit(src=tmp_file.name, remote_src=False) for result in results.contacted.values(): assert result.get("changed") is False assert re.search(r'please review the error for further details', repr(result.get("msg"))) assert re.search(r'please review the job log for status SEC', repr(result.get("msg"))) - assert result.get("jobs")[0].get("job_id") is not None + assert result.get("failed") is True + assert result.get("jobs") is not None + job = result.get("jobs")[0] + + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is None + assert len(job.get("steps")) == 0 + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "SEC" + assert rc.get("code") is None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is not None assert re.search( r'please review the job log for status SEC', - repr(result.get("jobs")[0].get("ret_code").get("msg_txt")) + repr(rc.get("msg_txt")) ) @@ -983,22 +1446,50 @@ def test_job_submit_local_jcl_typrun_scan(ansible_zos_module): f.write(JCL_FILE_CONTENTS_TYPRUN_SCAN) hosts = ansible_zos_module results = hosts.all.zos_job_submit(src=tmp_file.name, - location="local", - wait_time_s=20, + remote_src=False, + wait_time=20, encoding={ "from": "UTF-8", "to": "IBM-1047" },) for result in results.contacted.values(): assert result.get("changed") is False - assert result.get("jobs")[0].get("job_id") is not None + assert result.get("jobs") is not None + job = result.get("jobs")[0] + + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is None + assert len(job.get("steps")) == 0 + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "TYPRUN=SCAN" + assert rc.get("code") is None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is not None assert re.search( r'run with special job processing TYPRUN=SCAN', - repr(result.get("jobs")[0].get("ret_code").get("msg_txt")) + repr(rc.get("msg_txt")) ) - assert result.get("jobs")[0].get("ret_code").get("code") is None - assert result.get("jobs")[0].get("ret_code").get("msg") == "TYPRUN=SCAN" - assert result.get("jobs")[0].get("ret_code").get("msg_code") is None def test_job_submit_local_jcl_typrun_copy(ansible_zos_module): @@ -1007,8 +1498,8 @@ def test_job_submit_local_jcl_typrun_copy(ansible_zos_module): f.write(JCL_FILE_CONTENTS_TYPRUN_COPY) hosts = ansible_zos_module results = hosts.all.zos_job_submit(src=tmp_file.name, - location="local", - wait_time_s=20, + remote_src=False, + wait_time=20, encoding={ "from": "UTF-8", "to": "IBM-1047" @@ -1018,18 +1509,43 @@ def test_job_submit_local_jcl_typrun_copy(ansible_zos_module): # assert result.get("changed") is False # When running a job with TYPRUN=COPY, a copy of the JCL will be kept in the JES spool, so # effectively, the system is changed even though the job didn't run. - assert result.get("changed") is True - assert result.get("jobs")[0].get("job_id") is not None + assert result.get("changed") is False + assert result.get("jobs") is not None + job = result.get("jobs")[0] + + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is None + assert len(job.get("steps")) == 0 + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "NOEXEC" + assert rc.get("code") == None + assert rc.get("msg_code") is None + assert rc.get("msg_txt") is not None assert re.search( - r'The job was run with TYPRUN=COPY.', - repr(result.get("jobs")[0].get("ret_code").get("msg_txt")) + r'NOEXEC.', + repr(rc.get("msg_txt")) ) - assert result.get("jobs")[0].get("ret_code").get("code") == 0 - assert result.get("jobs")[0].get("ret_code").get("msg") == 'TYPRUN=COPY' - assert result.get("jobs")[0].get("ret_code").get("msg_code") == '0000' - # assert result.get("jobs")[0].get("ret_code").get("code") is None - # assert result.get("jobs")[0].get("ret_code").get("msg") is None - # assert result.get("jobs")[0].get("ret_code").get("msg_code") is None def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): @@ -1038,22 +1554,41 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): f.write(JCL_FILE_CONTENTS_TYPRUN_HOLD) hosts = ansible_zos_module results = hosts.all.zos_job_submit(src=tmp_file.name, - location="local", - wait_time_s=20, + remote_src=False, + wait_time=20, encoding={ "from": "UTF-8", "to": "IBM-1047" },) for result in results.contacted.values(): assert result.get("changed") is False - assert result.get("jobs")[0].get("job_id") is not None + assert result.get("jobs") is not None + job = result.get("jobs")[0] + + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is None + assert job.get("job_class") is not None + assert job.get("svc_class") is not None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is None + assert len(job.get("steps")) == 0 + assert len(job.get("dds")) == 0 + + rc = job.get("ret_code") assert re.search( r'long running job', - repr(result.get("jobs")[0].get("ret_code").get("msg_txt")) + repr(rc.get("msg_txt")) ) - assert result.get("jobs")[0].get("ret_code").get("code") is None - assert result.get("jobs")[0].get("ret_code").get("msg") == "AC" - assert result.get("jobs")[0].get("ret_code").get("msg_code") is None + assert rc.get("code") is None + assert rc.get("msg") == "HOLD" + assert rc.get("msg_code") is None def test_job_submit_local_jcl_typrun_jclhold(ansible_zos_module): @@ -1062,22 +1597,41 @@ def test_job_submit_local_jcl_typrun_jclhold(ansible_zos_module): f.write(JCL_FILE_CONTENTS_TYPRUN_JCLHOLD) hosts = ansible_zos_module results = hosts.all.zos_job_submit(src=tmp_file.name, - location="local", - wait_time_s=20, + remote_src=False, + wait_time=20, encoding={ "from": "UTF-8", "to": "IBM-1047" },) for result in results.contacted.values(): assert result.get("changed") is False - assert result.get("jobs")[0].get("job_id") is not None + assert result.get("jobs") is not None + job = result.get("jobs")[0] + + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is None + assert len(job.get("steps")) == 0 + assert len(job.get("dds")) == 0 + + rc = job.get("ret_code") assert re.search( r'long running job', - repr(result.get("jobs")[0].get("ret_code").get("msg_txt")) + repr(rc.get("msg_txt")) ) - assert result.get("jobs")[0].get("ret_code").get("code") is None - assert result.get("jobs")[0].get("ret_code").get("msg") == "AC" - assert result.get("jobs")[0].get("ret_code").get("msg_code") is None + assert rc.get("code") is None + assert rc.get("msg") == "HOLD" + assert rc.get("msg_code") is None @pytest.mark.parametrize("generation", ["0", "-1"]) @@ -1102,11 +1656,45 @@ def test_job_from_gdg_source(ansible_zos_module, generation): cmd="dcp '{0}/SAMPLE' '{1}'".format(temp_path, gds_name) ) - results = hosts.all.zos_job_submit(src=gds_name, location="data_set") + results = hosts.all.zos_job_submit(src=gds_name, remote_src=True) for result in results.contacted.values(): - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") hosts.all.zos_data_set(name=f"{source}(0)", state="absent") @@ -1125,10 +1713,12 @@ def test_inexistent_negative_gds(ansible_zos_module): # Only creating generation 0. hosts.all.zos_data_set(name=f"{source}(+1)", state="present", type="seq") - results = hosts.all.zos_job_submit(src=gds_name, location="data_set") + results = hosts.all.zos_job_submit(src=gds_name, remote_src=True) for result in results.contacted.values(): assert result.get("changed") is False - assert "was not found" in result.get("msg") + assert result.get("msg") is not None + assert result.get("failed") is True + assert re.search(r'was not found', repr(result.get("msg"))) finally: hosts.all.zos_data_set(name=f"{source}(0)", state="absent") hosts.all.zos_data_set(name=source, state="absent") @@ -1145,10 +1735,12 @@ def test_inexistent_positive_gds(ansible_zos_module): # Only creating generation 0. hosts.all.zos_data_set(name=gds_name, state="present", type="seq") - results = hosts.all.zos_job_submit(src=gds_name, location="data_set") + results = hosts.all.zos_job_submit(src=gds_name, remote_src=True) for result in results.contacted.values(): assert result.get("changed") is False - assert "was not found" in result.get("msg") + assert result.get("msg") is not None + assert result.get("failed") is True + assert re.search(r'was not found', repr(result.get("msg"))) finally: hosts.all.zos_data_set(name=f"{source}(0)", state="absent") hosts.all.zos_data_set(name=source, state="absent") @@ -1176,16 +1768,50 @@ def test_zoau_bugfix_invalid_utf8_chars(ansible_zos_module): results = hosts.all.zos_job_submit( src=tmp_file.name, - location="local", - wait_time_s=15 + remote_src=False, + wait_time=15 ) for result in results.contacted.values(): # We shouldn't get an error now that ZOAU handles invalid/unprintable # UTF-8 chars correctly. - assert result.get("jobs")[0].get("ret_code").get("msg_code") == "0000" - assert result.get("jobs")[0].get("ret_code").get("code") == 0 assert result.get("changed") is True + assert result.get("msg", False) is False + assert result.get("jobs") is not None + + job = result.get("jobs")[0] + assert job.get("job_id") is not None + assert job.get("job_name") is not None + assert job.get("content_type") is not None + assert job.get("duration") is not None + assert job.get("execution_time") is not None + assert job.get("job_class") is not None + assert job.get("svc_class") is None + assert job.get("priority") is not None + assert job.get("asid") is not None + assert job.get("creation_date") is not None + assert job.get("creation_time") is not None + assert job.get("queue_position") is not None + assert job.get("program_name") is not None + + dds = job.get("dds")[0] + assert dds.get("dd_name") is not None + assert dds.get("record_count") != 0 + assert dds.get("id") is not None + assert dds.get("stepname") is not None + assert dds.get("procstep") is not None + assert dds.get("byte_count") != 0 + assert dds.get("content") is not None + + step = job.get("steps")[0] + assert step.get("step_name") is not None + assert step.get("step_cc") is not None + + rc = job.get("ret_code") + assert rc.get("msg") == "CC" + assert rc.get("code") == 0 + assert rc.get("msg_code") == "0000" + assert rc.get("msg_txt") == "CC" finally: hosts.all.file(path=temp_path, state="absent") From 0d46bdc0866c230afa9d182bcf8c1d4263c2ac14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Wed, 16 Jul 2025 16:38:10 -0600 Subject: [PATCH 09/39] Add fragment --- .../2208_update_job_modules_interfaces.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 changelogs/fragments/2208_update_job_modules_interfaces.yml diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml new file mode 100644 index 0000000000..a91bae4864 --- /dev/null +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -0,0 +1,13 @@ +breaking_changes: + - zos_job_output - Interface value ``ddname`` is substitute for ``dd_name``, but ``ddname`` is an alias. Return value ``changed`` is always retun, ``steps`` are no longer under `ret_code` + but is now included under `jobs`. Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. + (https://github.com/ansible-collections/ibm_zos_core/pull/2208). + - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. + Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Return values ``system``, ``subsystem``, ``cpu_time``, ``execution_node`` + and ``origin node`` is no longer returned. Now all values are retuned under jobs exception for changed. + (https://github.com/ansible-collections/ibm_zos_core/pull/2208). + +trivial: + - test/zos_job_query_func.py - Update test validation to new values for job submit. Return value ``steps`` are no longer under `ret_code` + but is now included under `jobs`. + (https://github.com/ansible-collections/ibm_zos_core/pull/2208). \ No newline at end of file From 84b4292e3c400f6e8e0bb42ae93d13d5befa7a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Wed, 16 Jul 2025 16:38:35 -0600 Subject: [PATCH 10/39] Better fragment --- changelogs/fragments/2204-Update_zos_job_query_module.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2204-Update_zos_job_query_module.yml b/changelogs/fragments/2204-Update_zos_job_query_module.yml index 0e2a79c186..54e1e9c37d 100644 --- a/changelogs/fragments/2204-Update_zos_job_query_module.yml +++ b/changelogs/fragments/2204-Update_zos_job_query_module.yml @@ -1,3 +1,3 @@ breaking_changes: - - zos_job_query - Return value ``message`` is deprecated in favor of ``msg``. Return value ``steps`` are no longer under `` but is now included under jobs. + - zos_job_query - Return value ``message`` is deprecated in favor of ``msg``. Return value ``steps`` are no longer under `ret_code` but is now included under jobs. (https://github.com/ansible-collections/ibm_zos_core/pull/2204). \ No newline at end of file From ade2f0b2f1162d5fae50d583855b53103b454ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Wed, 16 Jul 2025 16:38:51 -0600 Subject: [PATCH 11/39] Update documentation --- plugins/modules/zos_job_output.py | 6 +++--- plugins/modules/zos_job_submit.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/modules/zos_job_output.py b/plugins/modules/zos_job_output.py index 10c660a955..268ab092c3 100644 --- a/plugins/modules/zos_job_output.py +++ b/plugins/modules/zos_job_output.py @@ -60,7 +60,7 @@ - Data definition name (show only this DD on a found job). (e.g "JESJCL", "?") type: str - aliases: [ddname] + aliases: [ ddname ] required: false attributes: @@ -309,7 +309,7 @@ The CC returned for this step in the DD section. type: int sample: 0 - sample: [ { "step_name": "STEP0001", "step_cc": 0}] + sample: [{ "step_name": "STEP0001", "step_cc": 0 }] sample: [ { @@ -437,7 +437,7 @@ "msg_code": "0000", "msg_txt": "", }, - "steps": [{ "step_name": "STEP0001","step_cc": 0}] + "steps": [{ "step_name": "STEP0001","step_cc": 0 }] "system": "STL1", "subsystem": "STL1", "cpu_time": 1414, diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index bf01553569..871e1c3c8d 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -566,7 +566,7 @@ "msg_code": "0000", "msg_txt": "" }, - "steps": [ { "step_name": "DLORD6", "step_cc": 0 }] + "steps": [{ "step_name": "DLORD6", "step_cc": 0 }] "job_class": "K", "execution_time": "00:00:10", "svc_class": "?", From cebe0b918ff7f52fd53a40388ca3b514bedecc53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Thu, 17 Jul 2025 13:38:52 -0600 Subject: [PATCH 12/39] Fix commit --- changelogs/fragments/2204-Update_zos_job_query_module.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2204-Update_zos_job_query_module.yml b/changelogs/fragments/2204-Update_zos_job_query_module.yml index 54e1e9c37d..083614866e 100644 --- a/changelogs/fragments/2204-Update_zos_job_query_module.yml +++ b/changelogs/fragments/2204-Update_zos_job_query_module.yml @@ -1,3 +1,3 @@ breaking_changes: - - zos_job_query - Return value ``message`` is deprecated in favor of ``msg``. Return value ``steps`` are no longer under `ret_code` but is now included under jobs. + - zos_job_query - Return value ``message`` is deprecated in favor of ``msg``. Return value ``steps`` are no longer under ``ret_code`` but is now included under jobs. (https://github.com/ansible-collections/ibm_zos_core/pull/2204). \ No newline at end of file From 41e965309b32131f5bb2bce156b61bb1d93fc0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Thu, 17 Jul 2025 13:40:10 -0600 Subject: [PATCH 13/39] Fix documentation --- plugins/modules/zos_job_output.py | 50 ++++++++++++++++++------------- plugins/modules/zos_job_submit.py | 12 +++++--- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/plugins/modules/zos_job_output.py b/plugins/modules/zos_job_output.py index 268ab092c3..454ca96160 100644 --- a/plugins/modules/zos_job_output.py +++ b/plugins/modules/zos_job_output.py @@ -31,7 +31,7 @@ such as "TCP*" or "*". - The owner can be specific such as "IBMUSER", or one that uses a pattern like "*". - - If there is no ddname, or if ddname="?", output of all the ddnames under + - If there is no dd_name, or if dd_name="?", output of all the dds under the given job will be displayed. version_added: "1.0.0" author: @@ -60,8 +60,8 @@ - Data definition name (show only this DD on a found job). (e.g "JESJCL", "?") type: str - aliases: [ ddname ] required: false + aliases: [ ddname ] attributes: action: @@ -140,7 +140,7 @@ sample: "STL1" class: description: - Identifies the data set used in a system output data set, usually called a sysout data set. + Identifies the data set used in a system output data set, usually called a sysout data set. type: str sample: content_type: @@ -172,13 +172,13 @@ sample: 00:00:10 dds: description: - Data definition names. + Data definition names. type: list elements: dict contains: dd_name: description: - Data definition name. + Data definition name. type: str sample: JESMSGLG record_count: @@ -188,7 +188,7 @@ sample: 17 id: description: - The file ID. + The file ID. type: str sample: 2 stepname: @@ -199,8 +199,8 @@ sample: JES2 procstep: description: - Identifies the set of statements inside JCL grouped together to - perform a particular function. + Identifies the set of statements inside JCL grouped together to + perform a particular function. type: str sample: PROC1 byte_count: @@ -210,7 +210,7 @@ sample: 574 content: description: - The ddname content. + The dd content. type: list elements: str sample: @@ -228,7 +228,7 @@ " 5 //SYSUT1 DD * ", " 6 //SYSUT2 DD SYSOUT=* ", " 7 // " - ] + ] job_class: description: Job class for this job. @@ -262,7 +262,7 @@ sample: "IEBGENER" ret_code: description: - Return code output collected from job log. + Return code output collected from job log. type: dict contains: msg: @@ -278,12 +278,12 @@ sample: S0C4 msg_txt: description: - Returns additional information related to the job. + Returns additional information related to the job. type: str sample: "No job can be located with this job name: HELLO" code: description: - Return code converted to integer value (when possible). + Return code converted to integer value (when possible). type: int sample: 00 sample: @@ -309,13 +309,17 @@ The CC returned for this step in the DD section. type: int sample: 0 - sample: [{ "step_name": "STEP0001", "step_cc": 0 }] + sample: [ + { "step_name": "STEP0001", + "step_cc": 0 + } + ] sample: [ { "class": "R", "content_type": "JOB", - "ddnames": [ + "dds": [ { "byte_count": "775", "content": [ @@ -337,7 +341,7 @@ "- 6 SYSOUT SPOOL KBYTES", "- 0.00 MINUTES EXECUTION TIME" ], - "ddname": "JESMSGLG", + "dd_name": "JESMSGLG", "id": "2", "procstep": "", "record_count": "17", @@ -361,7 +365,7 @@ " 6 //SYSUT2 DD SYSOUT=* ", " 7 // " ], - "ddname": "JESJCL", + "dd_name": "JESJCL", "id": "3", "procstep": "", "record_count": "14", @@ -390,7 +394,7 @@ " IEF033I JOB/HELLO /STOP 2020049.1025 ", " CPU: 0 HR 00 MIN 00.00 SEC SRB: 0 HR 00 MIN 00.00 SEC " ], - "ddname": "JESYSMSG", + "dd_name": "JESYSMSG", "id": "4", "procstep": "", "record_count": "19", @@ -404,7 +408,7 @@ " ", " PROCESSING ENDED AT EOD " ], - "ddname": "SYSPRINT", + "dd_name": "SYSPRINT", "id": "102", "procstep": "", "record_count": "4", @@ -415,7 +419,7 @@ "content": [ " HELLO, WORLD " ], - "ddname": "SYSUT2", + "dd_name": "SYSUT2", "id": "103", "procstep": "", "record_count": "1", @@ -437,7 +441,11 @@ "msg_code": "0000", "msg_txt": "", }, - "steps": [{ "step_name": "STEP0001","step_cc": 0 }] + "steps": [ + { "step_name": "STEP0001", + "step_cc": 0 + } + ], "system": "STL1", "subsystem": "STL1", "cpu_time": 1414, diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index 871e1c3c8d..d2feae8943 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -82,7 +82,7 @@ type: bool description: - Whether to print the DD output. - - If false, an empty list will be returned in the ddnames field. + - If false, an empty list will be returned in the dds field. volume: required: false type: str @@ -230,7 +230,7 @@ sample: 574 content: description: - The ddname content. + The dd content. type: list elements: str sample: @@ -566,7 +566,11 @@ "msg_code": "0000", "msg_txt": "" }, - "steps": [{ "step_name": "DLORD6", "step_cc": 0 }] + "steps": [ + { "step_name": "DLORD6", + "step_cc": 0 + } + ], "job_class": "K", "execution_time": "00:00:10", "svc_class": "?", @@ -1142,7 +1146,7 @@ def run_module(): if not return_output: for job in result.get("jobs", []): - job["ddnames"] = [] + job["dds"] = [] else: _msg = "The 'ret_code' dictionary was unavailable in the job log." result["ret_code"] = None From 3b5ee97a4a733cf76ee2942fc4f1f8a99c73957b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Thu, 17 Jul 2025 14:03:42 -0600 Subject: [PATCH 14/39] Keep documentation --- plugins/modules/zos_job_submit.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index d2feae8943..c9d94cc767 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -318,7 +318,11 @@ type: int sample: 0 sample: - "steps": [{ "step_name": "STEP0001", "step_cc": 0 }] + "steps": [ + { "step_name": "STEP0001", + "step_cc": 0 + } + ] job_class: description: Job class for this job. @@ -564,7 +568,7 @@ "code": 0, "msg": "CC 0000", "msg_code": "0000", - "msg_txt": "" + "msg_txt": "", }, "steps": [ { "step_name": "DLORD6", From 0ec06600f0e68c6d2119b607b1141bd29a7e4b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Thu, 17 Jul 2025 14:43:26 -0600 Subject: [PATCH 15/39] Replace job submit --- plugins/modules/zos_job_submit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index c9d94cc767..1238a45032 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -316,7 +316,7 @@ description: The CC returned for this step in the DD section. type: int - sample: 0 + sample: 0 sample: "steps": [ { "step_name": "STEP0001", From 8886ca4b31b9ac095e8f6d65c79d0fb6584f8cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Thu, 17 Jul 2025 14:59:34 -0600 Subject: [PATCH 16/39] Fix sanity --- plugins/modules/zos_job_output.py | 6 +++--- plugins/modules/zos_job_submit.py | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/modules/zos_job_output.py b/plugins/modules/zos_job_output.py index 454ca96160..70451c7cae 100644 --- a/plugins/modules/zos_job_output.py +++ b/plugins/modules/zos_job_output.py @@ -534,10 +534,10 @@ def run_module(): results["jobs"] = job_output(job_id=job_id, owner=owner, job_name=job_name, dd_name=dd_name) for job in results["jobs"]: if "job_not_found" in job: - results["changed"] = False - del job['job_not_found'] + results["changed"] = False + del job['job_not_found'] else: - results["changed"] = True + results["changed"] = True except zoau_exceptions.JobFetchException as fetch_exception: module.fail_json( msg=f"ZOAU exception {fetch_exception.response.stdout_response} rc {fetch_exception.response.rc}", diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index 1238a45032..6518122940 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -1174,7 +1174,7 @@ def run_module(): if temp_file is not None: shutil.rmtree(path.dirname(temp_file)) else: - result["jobs"] = build_empty_response(job_submitted_id) + result["jobs"] = build_empty_response(job_submitted_id) # If max_rc is set, we don't want to default to changed=True, rely on 'is_changed' result["changed"] = True if is_changed else False @@ -1293,7 +1293,7 @@ def build_empty_response(job_submitted_id): "duration": None, "execution_time": None, "dds": [], - "ret_code": {"code": None, "msg": None, "msg_code": None, "msg_txt": None,}, + "ret_code": {"code": None, "msg": None, "msg_code": None, "msg_txt": None}, "steps": [], "job_class": None, "svc_class": None, @@ -1307,6 +1307,7 @@ def build_empty_response(job_submitted_id): jobs.append(job_dict) return jobs + def main(): run_module() From 49f79978108d3c03da97a30f11fa1e39aeab4bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Thu, 17 Jul 2025 15:05:13 -0600 Subject: [PATCH 17/39] Fix sanity --- plugins/modules/zos_job_submit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index 6518122940..aedca770ab 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -1006,7 +1006,7 @@ def run_module(): if not present: module.fail_json( msg=(f"Unable to submit job {src_data.name} because the data set could " - f"not be cataloged on the volume {volume}."), **result + f"not be cataloged on the volume {volume}."), **result ) elif data_set.is_member(src_data.name): if not DataSet.data_set_member_exists(src_data.name): From 4d8102ce110095642ed14648ffe6b08241d3310f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 11:57:09 -0600 Subject: [PATCH 18/39] Return values --- changelogs/fragments/2208_update_job_modules_interfaces.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml index a91bae4864..807beef7ac 100644 --- a/changelogs/fragments/2208_update_job_modules_interfaces.yml +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -2,9 +2,8 @@ breaking_changes: - zos_job_output - Interface value ``ddname`` is substitute for ``dd_name``, but ``ddname`` is an alias. Return value ``changed`` is always retun, ``steps`` are no longer under `ret_code` but is now included under `jobs`. Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). - - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. - Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Return values ``system``, ``subsystem``, ``cpu_time``, ``execution_node`` - and ``origin node`` is no longer returned. Now all values are retuned under jobs exception for changed. + - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. + Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Now all values are retuned under jobs exception for changed. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). trivial: From 14702c14cfb89911d8dc52ad7738c170d7556da8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 11:57:42 -0600 Subject: [PATCH 19/39] Return values to module --- plugins/modules/zos_job_submit.py | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index aedca770ab..109b106c67 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -364,6 +364,31 @@ The name of the program found in the job's last completed step found in the PGM parameter. type: str sample: "IEBGENER" + system: + description: + The job entry system that MVS uses to do work. + type: str + sample: STL1 + subsystem: + description: + The job entry subsystem that MVS uses to do work. + type: str + sample: STL1 + cpu_time: + description: + Sum of the CPU time used by each job step, in microseconds. + type: int + sample: 5 + execution_node: + description: + Execution node that picked the job and executed it. + type: str + sample: "STL1" + origin_node: + description: + Origin node that submitted the job. + type: str + sample: "STL1" sample: [ { @@ -584,6 +609,11 @@ "creation_date": "2023-05-03", "creation_time": "12:13:00", "queue_position": 3, + "subsystem": "STL1", + "system": "STL1", + "cpu_time": 1, + "execution_node": "STL1", + "origin_node": "STL1" } ] """ @@ -1268,6 +1298,11 @@ def parsing_job_response(jobs_raw, duration): "steps": job.get("steps"), "job_class": job.get("job_class"), "svc_class": job.get("svc_class"), + "system": job.get("system"), + "subsystem": job.get("subsystem"), + "origin_node": job.get("origin_node"), + "cpu_time": job.get("cpu_time"), + "execution_node": job.get("execution_node"), "priority": job.get("priority"), "asid": job.get("asid"), "creation_date": job.get("creation_date"), From 0327d5816f09e955b797bc164e21376bb010c225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 12:05:28 -0600 Subject: [PATCH 20/39] Return values to test suite and empty response --- plugins/modules/zos_job_submit.py | 5 + .../modules/test_zos_job_submit_func.py | 133 ++++++++++++++++-- 2 files changed, 124 insertions(+), 14 deletions(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index 109b106c67..dfcccfae3a 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -1332,6 +1332,11 @@ def build_empty_response(job_submitted_id): "steps": [], "job_class": None, "svc_class": None, + "system": None, + "subsystem": None, + "origin_node": None, + "cpu_time": None, + "execution_node": None, "priority": None, "asid": None, "creation_date": None, diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index 90d5099ca2..48cb2c4e00 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -495,6 +495,11 @@ def test_job_submit_pds(ansible_zos_module, location): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -559,6 +564,11 @@ def test_job_submit_pds_special_characters(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -613,6 +623,11 @@ def test_job_submit_uss(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -666,6 +681,11 @@ def test_job_submit_and_forget_uss(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is None assert job.get("asid") is None assert job.get("creation_date") is None @@ -705,6 +725,11 @@ def test_job_submit_local(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -752,6 +777,11 @@ def test_job_submit_local_extra_r(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -836,6 +866,11 @@ def test_job_submit_pds_volume(ansible_zos_module, volumes_on_systems): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -903,6 +938,11 @@ def test_job_submit_pds_5_sec_job_wait_15(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -970,6 +1010,11 @@ def test_job_submit_pds_30_sec_job_wait_60(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1030,7 +1075,7 @@ def test_job_submit_pds_30_sec_job_wait_10_negative(ansible_zos_module): assert result.get("msg") is not None assert result.get("failed") is True assert re.search(r'exceeded', repr(result.get("msg"))) - assert result.get("jobs") is not None + assert result.get("jobs") is not None job = result.get("jobs")[0] assert job.get("job_id") is not None @@ -1040,6 +1085,11 @@ def test_job_submit_pds_30_sec_job_wait_10_negative(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is not None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1145,6 +1195,11 @@ def test_job_submit_max_rc(ansible_zos_module, args): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1257,6 +1312,11 @@ def test_job_submit_jinja_template(ansible_zos_module, args): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1316,6 +1376,11 @@ def test_job_submit_full_input(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1356,7 +1421,7 @@ def test_negative_job_submit_local_jcl_no_dsn(ansible_zos_module): assert result.get("msg") is not None assert re.search(r'completion code', repr(result.get("msg"))) assert result.get("failed") is True - assert result.get("jobs") is not None + assert result.get("jobs") is not None job = result.get("jobs")[0] assert job.get("job_id") is not None @@ -1366,6 +1431,11 @@ def test_negative_job_submit_local_jcl_no_dsn(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1402,9 +1472,9 @@ def test_negative_job_submit_local_jcl_invalid_user(ansible_zos_module): assert re.search(r'please review the error for further details', repr(result.get("msg"))) assert re.search(r'please review the job log for status SEC', repr(result.get("msg"))) assert result.get("failed") is True - assert result.get("jobs") is not None + assert result.get("jobs") is not None job = result.get("jobs")[0] - + assert job.get("job_id") is not None assert job.get("job_name") is not None assert job.get("content_type") is not None @@ -1412,6 +1482,11 @@ def test_negative_job_submit_local_jcl_invalid_user(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1454,9 +1529,9 @@ def test_job_submit_local_jcl_typrun_scan(ansible_zos_module): },) for result in results.contacted.values(): assert result.get("changed") is False - assert result.get("jobs") is not None + assert result.get("jobs") is not None job = result.get("jobs")[0] - + assert job.get("job_id") is not None assert job.get("job_name") is not None assert job.get("content_type") is not None @@ -1464,6 +1539,11 @@ def test_job_submit_local_jcl_typrun_scan(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1510,9 +1590,9 @@ def test_job_submit_local_jcl_typrun_copy(ansible_zos_module): # When running a job with TYPRUN=COPY, a copy of the JCL will be kept in the JES spool, so # effectively, the system is changed even though the job didn't run. assert result.get("changed") is False - assert result.get("jobs") is not None + assert result.get("jobs") is not None job = result.get("jobs")[0] - + assert job.get("job_id") is not None assert job.get("job_name") is not None assert job.get("content_type") is not None @@ -1520,6 +1600,11 @@ def test_job_submit_local_jcl_typrun_copy(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1562,9 +1647,9 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): },) for result in results.contacted.values(): assert result.get("changed") is False - assert result.get("jobs") is not None + assert result.get("jobs") is not None job = result.get("jobs")[0] - + assert job.get("job_id") is not None assert job.get("job_name") is not None assert job.get("content_type") is not None @@ -1572,6 +1657,11 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is not None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1605,9 +1695,9 @@ def test_job_submit_local_jcl_typrun_jclhold(ansible_zos_module): },) for result in results.contacted.values(): assert result.get("changed") is False - assert result.get("jobs") is not None + assert result.get("jobs") is not None job = result.get("jobs")[0] - + assert job.get("job_id") is not None assert job.get("job_name") is not None assert job.get("content_type") is not None @@ -1615,6 +1705,11 @@ def test_job_submit_local_jcl_typrun_jclhold(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1670,6 +1765,11 @@ def test_job_from_gdg_source(ansible_zos_module, generation): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1787,6 +1887,11 @@ def test_zoau_bugfix_invalid_utf8_chars(ansible_zos_module): assert job.get("execution_time") is not None assert job.get("job_class") is not None assert job.get("svc_class") is None + assert job.get("system") is not None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None + assert job.get("cpu_time") is not None + assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None assert job.get("creation_date") is not None @@ -1844,7 +1949,7 @@ def test_job_submit_async(get_config): cut_python_path, python_version, tmp_file.name - )), + )), playbook.name )) @@ -1854,7 +1959,7 @@ def test_job_submit_async(get_config): ssh_key, user, python_path - )), + )), inventory.name )) From b4ca89d974b4d20a9f6c63258b9a5bc15ee36b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:28:25 -0600 Subject: [PATCH 21/39] Update changelogs/fragments/2208_update_job_modules_interfaces.yml Co-authored-by: Fernando Flores --- changelogs/fragments/2208_update_job_modules_interfaces.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml index 807beef7ac..7e15f1d0a7 100644 --- a/changelogs/fragments/2208_update_job_modules_interfaces.yml +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -1,5 +1,5 @@ breaking_changes: - - zos_job_output - Interface value ``ddname`` is substitute for ``dd_name``, but ``ddname`` is an alias. Return value ``changed`` is always retun, ``steps`` are no longer under `ret_code` + - zos_job_output - Option name ``ddname`` is substituted for ``dd_name``, but ``ddname`` is kept as an alias.. Return value ``changed`` is always returned and return value ``steps`` are no longer under ``ret_code`` but is now included under `jobs`. Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. From ed9905edd2e3e913b4dbc9b348892b81d56b8e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:28:33 -0600 Subject: [PATCH 22/39] Update changelogs/fragments/2208_update_job_modules_interfaces.yml Co-authored-by: Fernando Flores --- changelogs/fragments/2208_update_job_modules_interfaces.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml index 7e15f1d0a7..30b9bbf030 100644 --- a/changelogs/fragments/2208_update_job_modules_interfaces.yml +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -3,7 +3,7 @@ breaking_changes: but is now included under `jobs`. Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. - Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Now all values are retuned under jobs exception for changed. + Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Now all values are retuned under jobs excepting ``changed``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). trivial: From b46b1fdc0ba40796cf133adaa377a2c7b74eecb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:28:42 -0600 Subject: [PATCH 23/39] Update changelogs/fragments/2208_update_job_modules_interfaces.yml Co-authored-by: Fernando Flores --- changelogs/fragments/2208_update_job_modules_interfaces.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml index 30b9bbf030..a8db1244be 100644 --- a/changelogs/fragments/2208_update_job_modules_interfaces.yml +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -1,6 +1,6 @@ breaking_changes: - zos_job_output - Option name ``ddname`` is substituted for ``dd_name``, but ``ddname`` is kept as an alias.. Return value ``changed`` is always returned and return value ``steps`` are no longer under ``ret_code`` - but is now included under `jobs`. Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. + but is now included under `jobs`. Return value ``ddnames`` is replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replaced by ``dd_name``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Now all values are retuned under jobs excepting ``changed``. From cf8e264e6021c6f7b51fe0214b0dae1019a29215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:11:02 -0600 Subject: [PATCH 24/39] Fix job submit --- tests/functional/modules/test_zos_job_submit_func.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index 48cb2c4e00..0583a10dcc 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -669,6 +669,7 @@ def test_job_submit_and_forget_uss(ansible_zos_module): src=f"{temp_path}/SAMPLE", remote_src=True, volume=None, wait_time=0, ) for result in results.contacted.values(): + print(result) assert result.get("changed") is True assert result.get("msg", False) is False assert result.get("jobs") is not None From 1c1eb891938ab7d2fe8debe913291c3e606e0f58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:19:52 -0600 Subject: [PATCH 25/39] Validate test case --- tests/functional/modules/test_zos_job_submit_func.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index 0583a10dcc..14339c8fe0 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -669,7 +669,6 @@ def test_job_submit_and_forget_uss(ansible_zos_module): src=f"{temp_path}/SAMPLE", remote_src=True, volume=None, wait_time=0, ) for result in results.contacted.values(): - print(result) assert result.get("changed") is True assert result.get("msg", False) is False assert result.get("jobs") is not None @@ -682,10 +681,10 @@ def test_job_submit_and_forget_uss(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is None assert job.get("svc_class") is None - assert job.get("system") is not None - assert job.get("subsystem") is not None - assert job.get("origin_node") is not None - assert job.get("cpu_time") is not None + assert job.get("system") is None + assert job.get("subsystem") is None + assert job.get("origin_node") is None + assert job.get("cpu_time") is None assert job.get("execution_node") is not None assert job.get("priority") is None assert job.get("asid") is None From b9911123d23b0f0f45499114d721b8e9b012a1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:24:36 -0600 Subject: [PATCH 26/39] Validate test case --- tests/functional/modules/test_zos_job_submit_func.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index 14339c8fe0..9850ee22b1 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -685,7 +685,7 @@ def test_job_submit_and_forget_uss(ansible_zos_module): assert job.get("subsystem") is None assert job.get("origin_node") is None assert job.get("cpu_time") is None - assert job.get("execution_node") is not None + assert job.get("execution_node") is None assert job.get("priority") is None assert job.get("asid") is None assert job.get("creation_date") is None From f69ba71cc150f7d3283ab3e9dcef08ab262dccbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:33:10 -0600 Subject: [PATCH 27/39] Validate test case --- tests/functional/modules/test_zos_job_submit_func.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index 9850ee22b1..c300a84c58 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -1646,6 +1646,7 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): "to": "IBM-1047" },) for result in results.contacted.values(): + print(result) assert result.get("changed") is False assert result.get("jobs") is not None job = result.get("jobs")[0] @@ -1657,9 +1658,9 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is not None - assert job.get("system") is not None - assert job.get("subsystem") is not None - assert job.get("origin_node") is not None + assert job.get("system") not None + assert job.get("subsystem") not None + assert job.get("origin_node") not None assert job.get("cpu_time") is not None assert job.get("execution_node") is not None assert job.get("priority") is not None From 80dd2be6fa629abd23bd9b9e85cfc0dad5986681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:36:31 -0600 Subject: [PATCH 28/39] Validate test case --- tests/functional/modules/test_zos_job_submit_func.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index c300a84c58..e67682f0ab 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -1658,10 +1658,10 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is not None - assert job.get("system") not None - assert job.get("subsystem") not None - assert job.get("origin_node") not None - assert job.get("cpu_time") is not None + assert job.get("system") is None + assert job.get("subsystem") is None + assert job.get("origin_node") is None + assert job.get("cpu_time") not None assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None From b88ca4f2e277239a5997487019eb0c407e1e0715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:40:10 -0600 Subject: [PATCH 29/39] Validate test case --- tests/functional/modules/test_zos_job_submit_func.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index e67682f0ab..1e8c630897 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -1661,7 +1661,7 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): assert job.get("system") is None assert job.get("subsystem") is None assert job.get("origin_node") is None - assert job.get("cpu_time") not None + assert job.get("cpu_time") is not None assert job.get("execution_node") is not None assert job.get("priority") is not None assert job.get("asid") is not None From ca75e70b271ca75f6cd2229be8e5cc0f61776045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:48:45 -0600 Subject: [PATCH 30/39] Validate test case --- tests/functional/modules/test_zos_job_submit_func.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index 1e8c630897..7b1b6e5d4e 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -1659,8 +1659,8 @@ def test_job_submit_local_jcl_typrun_hold(ansible_zos_module): assert job.get("job_class") is not None assert job.get("svc_class") is not None assert job.get("system") is None - assert job.get("subsystem") is None - assert job.get("origin_node") is None + assert job.get("subsystem") is not None + assert job.get("origin_node") is not None assert job.get("cpu_time") is not None assert job.get("execution_node") is not None assert job.get("priority") is not None From afc2bf588d6cc67eb45aa493b2eadd12574d45c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= Date: Fri, 1 Aug 2025 14:57:47 -0600 Subject: [PATCH 31/39] Validate test case --- tests/functional/modules/test_zos_job_submit_func.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/functional/modules/test_zos_job_submit_func.py b/tests/functional/modules/test_zos_job_submit_func.py index 7b1b6e5d4e..efa4140794 100644 --- a/tests/functional/modules/test_zos_job_submit_func.py +++ b/tests/functional/modules/test_zos_job_submit_func.py @@ -1695,6 +1695,7 @@ def test_job_submit_local_jcl_typrun_jclhold(ansible_zos_module): "to": "IBM-1047" },) for result in results.contacted.values(): + print(result) assert result.get("changed") is False assert result.get("jobs") is not None job = result.get("jobs")[0] @@ -1706,7 +1707,7 @@ def test_job_submit_local_jcl_typrun_jclhold(ansible_zos_module): assert job.get("execution_time") is None assert job.get("job_class") is not None assert job.get("svc_class") is None - assert job.get("system") is not None + assert job.get("system") is None assert job.get("subsystem") is not None assert job.get("origin_node") is not None assert job.get("cpu_time") is not None From a39b28dc4826a58a1156a56565202470e4f50f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 17:17:08 -0600 Subject: [PATCH 32/39] Update changelogs/fragments/2204-Update_zos_job_query_module.yml Co-authored-by: Alex Moreno --- changelogs/fragments/2204-Update_zos_job_query_module.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2204-Update_zos_job_query_module.yml b/changelogs/fragments/2204-Update_zos_job_query_module.yml index 083614866e..b3a2270c37 100644 --- a/changelogs/fragments/2204-Update_zos_job_query_module.yml +++ b/changelogs/fragments/2204-Update_zos_job_query_module.yml @@ -1,3 +1,3 @@ breaking_changes: - - zos_job_query - Return value ``message`` is deprecated in favor of ``msg``. Return value ``steps`` are no longer under ``ret_code`` but is now included under jobs. + - zos_job_query - Return field ``message`` is deprecated in favor of ``msg``. Return field ``steps`` is no longer under ``ret_code`` but is now included under ``jobs``. (https://github.com/ansible-collections/ibm_zos_core/pull/2204). \ No newline at end of file From 8030ad2d0e48c9ad2c45c673e412ec6df1d65261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 17:18:11 -0600 Subject: [PATCH 33/39] Update plugins/modules/zos_job_submit.py Co-authored-by: Fernando Flores --- plugins/modules/zos_job_submit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index dfcccfae3a..66cff5b8a5 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -51,7 +51,7 @@ default: true type: bool description: - - If set to C(false), the module searches for C(src) at the local machine. + - If set to C(false), the module searches for C(src) in the controller node. - If set to C(true), the module goes to the remote/target machine for C(src). wait_time: required: false From b70786bfd1d4478bd1c2ded2adda56395306eee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 17:20:06 -0600 Subject: [PATCH 34/39] Update plugins/modules/zos_job_submit.py Co-authored-by: Fernando Flores --- plugins/modules/zos_job_submit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index 66cff5b8a5..e47958ab9e 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -52,7 +52,7 @@ type: bool description: - If set to C(false), the module searches for C(src) in the controller node. - - If set to C(true), the module goes to the remote/target machine for C(src). + - If set to C(true), the module searches for the file C(src) in the managed node. wait_time: required: false default: 10 From c4e9db8aeacad671174b96731f51d6ec75a21b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 17:20:27 -0600 Subject: [PATCH 35/39] Update plugins/modules/zos_job_submit.py Co-authored-by: Alex Moreno --- plugins/modules/zos_job_submit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index e47958ab9e..6e90d4fdd5 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -70,7 +70,7 @@ L(zos_job_query,./zos_job_query.html) or L(zos_job_output,./zos_job_output.html) if needed. - If I(remote_src=False) and I(wait_time) is 0 the module not gonna clean the copy - of the file on remote system, to avoid problems on the submission of the job. + of the file on the remote system, to avoid problems with job submission. max_rc: required: false type: int From d8da79d24bad6bd7d030b050966d5ee972f0a2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Fri, 1 Aug 2025 17:20:45 -0600 Subject: [PATCH 36/39] Update plugins/modules/zos_job_submit.py Co-authored-by: Alex Moreno --- plugins/modules/zos_job_submit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/zos_job_submit.py b/plugins/modules/zos_job_submit.py index 6e90d4fdd5..d347efcc33 100644 --- a/plugins/modules/zos_job_submit.py +++ b/plugins/modules/zos_job_submit.py @@ -69,7 +69,7 @@ Job details and contents can be retrieved later by using L(zos_job_query,./zos_job_query.html) or L(zos_job_output,./zos_job_output.html) if needed. - - If I(remote_src=False) and I(wait_time) is 0 the module not gonna clean the copy + - If I(remote_src=False) and I(wait_time=0), the module will not clean the copy of the file on the remote system, to avoid problems with job submission. max_rc: required: false From 0b07a67f8e56104adfb914ee6817ef3cf402e9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:00:08 -0600 Subject: [PATCH 37/39] Update changelogs/fragments/2208_update_job_modules_interfaces.yml Co-authored-by: Alex Moreno --- changelogs/fragments/2208_update_job_modules_interfaces.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml index a8db1244be..9cf8b6051e 100644 --- a/changelogs/fragments/2208_update_job_modules_interfaces.yml +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -1,5 +1,5 @@ breaking_changes: - - zos_job_output - Option name ``ddname`` is substituted for ``dd_name``, but ``ddname`` is kept as an alias.. Return value ``changed`` is always returned and return value ``steps`` are no longer under ``ret_code`` + - zos_job_output - Option name ``ddname`` is substituted for ``dd_name``, but ``ddname`` is kept as an alias. Return value ``changed`` is always returned and return value ``steps`` are no longer under ``ret_code`` but is now included under `jobs`. Return value ``ddnames`` is replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replaced by ``dd_name``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. From 68cd69832d5a9b138201da6ec2eda6786b880a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:00:19 -0600 Subject: [PATCH 38/39] Update changelogs/fragments/2208_update_job_modules_interfaces.yml Co-authored-by: Alex Moreno --- changelogs/fragments/2208_update_job_modules_interfaces.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml index 9cf8b6051e..630498c479 100644 --- a/changelogs/fragments/2208_update_job_modules_interfaces.yml +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -2,7 +2,7 @@ breaking_changes: - zos_job_output - Option name ``ddname`` is substituted for ``dd_name``, but ``ddname`` is kept as an alias. Return value ``changed`` is always returned and return value ``steps`` are no longer under ``ret_code`` but is now included under `jobs`. Return value ``ddnames`` is replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replaced by ``dd_name``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). - - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` ir replace for ``wait_time``. + - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` is replaced for ``wait_time``. Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Now all values are retuned under jobs excepting ``changed``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). From 5076094105b5d3026db1bbcfc24c8edc130d761f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Marcel=20Guti=C3=A9rrez=20Ben=C3=ADtez?= <68956970+AndreMarcel99@users.noreply.github.com> Date: Mon, 4 Aug 2025 15:00:29 -0600 Subject: [PATCH 39/39] Update changelogs/fragments/2208_update_job_modules_interfaces.yml Co-authored-by: Alex Moreno --- changelogs/fragments/2208_update_job_modules_interfaces.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/fragments/2208_update_job_modules_interfaces.yml b/changelogs/fragments/2208_update_job_modules_interfaces.yml index 630498c479..e84fc8d9cf 100644 --- a/changelogs/fragments/2208_update_job_modules_interfaces.yml +++ b/changelogs/fragments/2208_update_job_modules_interfaces.yml @@ -3,7 +3,7 @@ breaking_changes: but is now included under `jobs`. Return value ``ddnames`` is replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replaced by ``dd_name``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). - zos_job_submit - Interface value ``location`` is replace for ``remote_src`` in a bool value and ``wait_time_s`` is replaced for ``wait_time``. - Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Now all values are retuned under jobs excepting ``changed``. + Return value ``ddnames`` replaced by ``dds`` and value ``ddname`` under ``ddnames`` is replace by ``dd_name``. Now all values are returned under ``jobs`` except ``changed``. (https://github.com/ansible-collections/ibm_zos_core/pull/2208). trivial: