Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/2386-simple_role_to_get_job_status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
trivial:
- zos_job_query - Enhanced to return proper status of a job_id.
(https://github.com/ansible-collections/ibm_zos_core/pull/2386).
31 changes: 1 addition & 30 deletions plugins/modules/zos_job_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,38 +468,9 @@ def parsing_jobs(jobs_raw):
# replaced with None in the jobs.py and msg_txt field describes the job query instead
if job.get("ret_code") is None:
status_raw = "JOB NOT FOUND"
ret_code["msg"] = status_raw
elif job.get("ret_code").get("msg", "JOB NOT FOUND") is None:
status_raw = "JOB NOT FOUND"
else:
status_raw = job.get("ret_code").get("msg", "JOB NOT FOUND")

if "AC" in status_raw:
# the job is active
ret_code["msg"] = None
ret_code["msg_code"] = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is not set, will it still be returned as None or not returned at all ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would make sense to set them as none at the start of the function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It returns as None, but right better to be safe

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we cover that case of been None

ret_code["code"] = None
ret_code["msg_txt"] = None

elif "CC" in status_raw:
# status = 'Completed normally'
ret_code["msg"] = status_raw

elif "ABEND" in status_raw:
# status = 'Ended abnormally'
ret_code["msg"] = status_raw

elif "ABENDU" in status_raw:
# status = 'Ended abnormally'
ret_code["msg"] = status_raw

elif "CANCELED" in status_raw or "JCLERR" in status_raw or "JCL ERROR" in status_raw or "JOB NOT FOUND" in status_raw:
# status = status_raw
ret_code["msg"] = status_raw
ret_code["code"] = None
ret_code["msg_code"] = None

else:
# status = 'Unknown'
ret_code["msg"] = status_raw

job_dict = {
Expand Down
9 changes: 9 additions & 0 deletions roles/job_status/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# ibm.ibm_zos_core.job_status

This role gathers job status and if the jos is active about a giving a job_id.

## Role Variables

Tue only variable required is:

- `job_id`: ID of the job to query status and if is active or not.
47 changes: 47 additions & 0 deletions roles/job_status/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
- name: "Query job {{ job_id }}"
ibm.ibm_zos_core.zos_job_query:
job_name: "*"
owner: "*"
job_id: "{{ job_id }}"
register: jobs_status

- name: Normalize return values
ansible.builtin.set_fact:
jobs_list: "{{ jobs_status.jobs }}"
when: jobs_status is defined and jobs_status.jobs is defined and (jobs_status.jobs | length > 0)

- name: Extract ret_code.msg from {{ job_id }}
set_fact:
job_status: >-
{% set rc = jobs_list[0].ret_code | default({}) %}
{% if rc is mapping %}
{% if rc.msg is defined and rc.msg is not none and rc.msg|string != '' %}
{{ rc.msg | string | trim }}
{% elif rc.msg_txt is defined and rc.msg_txt is not none and rc.msg_txt|string != '' %}
{{ rc.msg_txt | string | trim }}
{% elif rc.message is defined and rc.message is not none and rc.message|string != '' %}
{{ rc.message | string | trim }}
{% else %}
UNKNOWN
{% endif %}
{% else %}
{{ rc | string | trim }}
{% endif %}
job_active_from_msg: "{{ 'AC' in (jobs_list[0].ret_code.msg | default('')) }}"

- name: Clean job_status value
set_fact:
job_status: "{{ job_status | trim }}"

- name: Verify if {{ job_id }} is found
when: jobs_list is not defined or jobs_list | length == 0
set_fact:
job_status: "JOB_NOT_FOUND"
job_active_from_msg: "JOB_NOT_FOUND"

- name: See job_status and job_active from {{ job_id }}
ansible.builtin.debug:
msg:
job_status: "{{ job_status }}"
job_active: "{{ job_active_from_msg }}"
30 changes: 30 additions & 0 deletions tests/functional/roles/test_role_job_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-

# Copyright (c) IBM Corporation 2025
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import absolute_import, division, print_function

import pytest
__metaclass__ = type

def test_my_role_with_vars(ansible_zos_module):
hosts = ansible_zos_module

jobs = hosts.all.zos_job_query(job_id="*", owner="*")
for job in jobs.contacted.values():
job_id = job.get("jobs")[0].get("job_id")

hosts.all.set_fact(job_id=job_id)
results = hosts.all.include_role(name="job_status")
for result in results.contacted.values():
assert result.get("msg").get("job_active") is not None
assert result.get("msg").get("job_status") is not None