Skip to content
5 changes: 5 additions & 0 deletions changelogs/fragments/2385-stat-filter-plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
minor_changes:
- plugins/filter/filter_by_resource_type.py - Added new filter plugin, stat,
to filter the output returned by zos_stat depending on the type of resource
that was queried.
(https://github.com/ansible-collections/ibm_zos_core/pull/2385).
211 changes: 211 additions & 0 deletions plugins/filter/filter_by_resource_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
# 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 ansible.errors import AnsibleFilterError


VALID_FIELDS = {
'data_set': [
'type',
'dsorg',
'has_extended_attrs',
'extended_attrs_bits',
'creation_date',
'expiration_date',
'sms_data_class',
'sms_mgmt_class',
'sms_storage_class',
'encrypted',
'key_label',
'key_status',
'racf',
],
'seq': [
'record_format',
'record_length',
'block_size',
'creation_time',
'last_reference',
'updated_since_backup',
'jcl_attrs',
'volser',
'num_volumes',
'volumes',
'missing_volumes',
'device_type',
'space_units',
'primary_space',
'secondary_space',
'allocation_available',
'allocation_used',
'extents_allocated',
'extents_used',
'blocks_per_track',
'tracks_per_cylinder',
'seq_type',
],
'pds': [
'record_format',
'record_length',
'block_size',
'creation_time',
'last_reference',
'updated_since_backup',
'jcl_attrs',
'volser',
'num_volumes',
'volumes',
'missing_volumes',
'device_type',
'space_units',
'primary_space',
'secondary_space',
'allocation_available',
'allocation_used',
'extents_allocated',
'extents_used',
'blocks_per_track',
'tracks_per_cylinder',
'dir_blocks_allocated',
'dir_blocks_used',
'members',
'pages_allocated',
'pages_used',
'perc_pages_used',
'pdse_version',
'max_pdse_generation',
],
'vsam': [
'data',
'index'
],
'file': [
'mode',
'atime',
'mtime',
'ctime',
'checksum',
'uid',
'gid',
'size',
'inode',
'dev',
'nlink',
'isdir',
'ischr',
'isblk',
'isreg',
'isfifo',
'islnk',
'issock',
'isuid',
'isgid',
'wusr',
'rusr',
'xusr',
'wgrp',
'rgrp',
'xgrp',
'woth',
'roth',
'xoth',
'writeable',
'readable',
'executable',
'pw_name',
'gr_name',
'lnk_source',
'lnk_target',
'charset',
'mimetype',
'audit_bits',
'file_format'
],
'aggregate': [
'auditfid',
'bitmap_file_size',
'converttov5',
'filesystem_table_size',
'free',
'free_1k_fragments',
'free_8k_blocks',
'log_file_size',
'sysplex_aware',
'total_size',
'version',
'quiesced'
],
'gdg': [
'limit',
'scratch',
'empty',
'order',
'purge',
'extended',
'active_gens'
]
}


def filter_stat(attributes, resource):
"""Filter a dictionary that was output by zos_stat.

Arguments:
attributes {dict} -- Dictionary containing all the stat attributes returned by zos_stat.
resource {str} -- One of 'data_set', 'file', 'aggregate' or 'gdg'.

Returns:
dict -- A reduced attributes dictionary.
"""
if not isinstance(attributes, dict):
raise AnsibleFilterError("The 'attributes' object passed is not a dictionary. This filter needs a dictionary to filter.")
if resource not in ['data_set', 'file', 'aggregate', 'gdg']:
raise AnsibleFilterError(f"The given resource {resource} is not one of 'data_set', 'file', 'aggregate' or 'gdg'.")

attributes = attributes.get('stat', {})

root_attrs = [
'name',
'resource_type',
'exists',
'isfile',
'isdataset',
'isaggregate',
'isgdg'
]
cleaned_attributes = {key: attributes.get(key) for key in root_attrs}
cleaned_attributes['attributes'] = {}

for field in VALID_FIELDS[resource]:
cleaned_attributes['attributes'][field] = attributes.get('attributes', {}).get(field)

if resource == 'data_set' and cleaned_attributes['attributes']['dsorg'] is not None:
if 'ps' in cleaned_attributes['attributes']['dsorg']:
for field in VALID_FIELDS['seq']:
cleaned_attributes['attributes'][field] = attributes.get('attributes', {}).get(field)
if 'po' in cleaned_attributes['attributes']['dsorg']:
for field in VALID_FIELDS['pds']:
cleaned_attributes['attributes'][field] = attributes.get('attributes', {}).get(field)
if cleaned_attributes['attributes']['dsorg'] == 'vsam':
for field in VALID_FIELDS['vsam']:
cleaned_attributes['attributes'][field] = attributes.get('attributes', {}).get(field)

return cleaned_attributes


class FilterModule(object):
""" Jinja2 filter for the returned JSON by the zos_stat module. """

def filters(self):
filters = {
"filter_by_resource_type": filter_stat,
}
return filters
46 changes: 46 additions & 0 deletions plugins/filter/filter_by_resource_type.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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.
DOCUMENTATION:
name: filter_by_resource_type
author: Alex Moreno (@rexemin)
version_added: "2.0.0"
short_description: filter returned fields from zos_stat
description:
- Extract only the relevant fields for a resource from the output of zos_stat.
- Choose between data set, file, aggregate or GDG fields.
options:
attributes:
description:
- Output from zos_stat.
type: dict
required: true
resource:
description:
- Type of resource which fields should be filtered from the returned JSON of zos_stat.
- If the resource is a data set, the filter will only include the relevant fields for
the specific type of data set queried by zos_stat. When C(isdataset=False), only
common data sets attribute fields will be returned.
type: str
required: true
choices:
- data_set
- file
- aggregate
- gdg

EXAMPLES: |
# Get only data set specific attributes.
clean_output: "{{ zos_stat_output | ibm.ibm_zos_core.filter_by_resource_type('data_set')}}"

RETURN:
_value:
description: Stripped-down dictionary containing the fields relevant for the selected resource.
type: dict
Loading