Skip to content

Commit 673bd70

Browse files
AndreMarcel99Andre Marcel Gutierrez BenitezAndre Marcel Gutierrez Benitezddimatos
authored
Add force (disp=shr) option to zos_lineinfile and update zos_blockinfile with the same locking test case. (#731)
* Add DISP=SHR by function force to the user * Add helper function for force cases only for EOF inserts * Test cases added * Just to check in the change case * All test cases for force in zos_lineinfile working properly * Test cases for force blockinfile * Fixes for style of code * One identation error * One identation error * One identation error * Documentation error * All test cases for line infile and block infile * Comments * Change the stdout to assert with expected of ds * Error of test case * Fragment added * Solve typo errors * Update to remove uncessary comment Signed-off-by: ddimatos <dimatos@gmail.com> * Update changelog fragment Signed-off-by: ddimatos <dimatos@gmail.com> * Update module with force comments Signed-off-by: ddimatos <dimatos@gmail.com> * Solve some test problems * Copyright year * Copyright year * Add cases for other ecodes * Add test for all encodings * Cover all encodes test cases with force * Blockinfile force added for other encodes and DS types --------- Signed-off-by: ddimatos <dimatos@gmail.com> Co-authored-by: Andre Marcel Gutierrez Benitez <andre@MacBook-Pro-de-Andre-2.local> Co-authored-by: Andre Marcel Gutierrez Benitez <andre@mbp-de-andre-2.gdl.mex.ibm.com> Co-authored-by: ddimatos <dimatos@gmail.com>
1 parent a856d18 commit 673bd70

File tree

6 files changed

+640
-27
lines changed

6 files changed

+640
-27
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
minor_changes:
2+
- zos_lineinfile - would access data sets with exclusive access so no other
3+
task can read the data, this enhancement allows for a data set to be opened
4+
with a disposition set to share so that other tasks can access the data when
5+
option `force` is set to `true`.
6+
(https://github.com/ansible-collections/ibm_zos_core/pull/731)

plugins/modules/zos_lineinfile.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@
173173
required: false
174174
type: str
175175
default: IBM-1047
176+
force:
177+
description:
178+
- Specifies that the data set can be shared with others during an update
179+
which results in the data set you are updating to be simultaneously
180+
updated by others.
181+
- This is helpful when a data set is being used in a long running process
182+
such as a started task and you are wanting to update or read.
183+
- The C(force) option enables sharing of data sets through the disposition
184+
I(DISP=SHR).
185+
required: false
186+
type: bool
187+
default: false
176188
notes:
177189
- It is the playbook author or user's responsibility to avoid files
178190
that should not be encoded, such as binary files. A user is described
@@ -218,6 +230,14 @@
218230
regexp: '^(.*)User(\d+)m(.*)$'
219231
line: '\1APPUser\3'
220232
backrefs: yes
233+
234+
- name: Add a line to a member while a task is in execution
235+
zos_lineinfile:
236+
src: SOME.PARTITIONED.DATA.SET(DATA)
237+
insertafter: EOF
238+
line: 'Should be a working test now'
239+
force: True
240+
221241
"""
222242

223243
RETURN = r"""
@@ -271,7 +291,7 @@
271291
DS_TYPE = ['PS', 'PO']
272292

273293

274-
def present(src, line, regexp, ins_aft, ins_bef, encoding, first_match, backrefs):
294+
def present(src, line, regexp, ins_aft, ins_bef, encoding, first_match, backrefs, force):
275295
"""Replace a line with the matching regex pattern
276296
Insert a line before/after the matching pattern
277297
Insert a line at BOF/EOF
@@ -292,6 +312,7 @@ def present(src, line, regexp, ins_aft, ins_bef, encoding, first_match, backrefs
292312
encoding: {str} -- Encoding of the src.
293313
first_match: {bool} -- Take the first matching regex pattern.
294314
backrefs: {bool} -- Back reference
315+
force: {bool} -- force for modify a member part of a task in execution
295316
296317
Returns:
297318
str -- Information in JSON format. keys:
@@ -310,10 +331,11 @@ def present(src, line, regexp, ins_aft, ins_bef, encoding, first_match, backrefs
310331
backref=backrefs,
311332
state=True,
312333
debug=True,
334+
force=force,
313335
)
314336

315337

316-
def absent(src, line, regexp, encoding):
338+
def absent(src, line, regexp, encoding, force):
317339
"""Delete lines with matching regex pattern
318340
319341
Arguments:
@@ -322,14 +344,15 @@ def absent(src, line, regexp, encoding):
322344
regexp will be ignored.
323345
regexp: {str} -- The regular expression to look for in every line of the src.
324346
encoding: {str} -- Encoding of the src.
347+
force: {bool} -- force for modify a member part of a task in execution
325348
326349
Returns:
327350
str -- Information in JSON format. keys:
328351
cmd: {str} -- dsed shell command
329352
found: {int} -- Number of matching regex pattern
330353
changed: {bool} -- Indicates if the source was modified.
331354
"""
332-
return datasets.lineinfile(src, line, regex=regexp, encoding=encoding, state=False, debug=True)
355+
return datasets.lineinfile(src, line, regex=regexp, encoding=encoding, state=False, debug=True, force=force)
333356

334357

335358
def quotedString(string):
@@ -364,7 +387,8 @@ def main():
364387
backup_name=dict(type='str', required=False, default=None),
365388
firstmatch=dict(type='bool', default=False),
366389
encoding=dict(type='str', default="IBM-1047"),
367-
tmp_hlq=dict(type='str', required=False, default=None)
390+
tmp_hlq=dict(type='str', required=False, default=None),
391+
force=dict(type='bool', required=False, default=False)
368392
)
369393
module = AnsibleModule(
370394
argument_spec=module_args,
@@ -385,6 +409,7 @@ def main():
385409
firstmatch=dict(arg_type="bool", required=False, default=False),
386410
backrefs=dict(arg_type="bool", dependencies=['regexp'], required=False, default=False),
387411
tmp_hlq=dict(type='qualifier_or_empty', required=False, default=None),
412+
force=dict(arg_type='bool', required=False, default=False),
388413
mutually_exclusive=[["insertbefore", "insertafter"]],)
389414

390415
try:
@@ -406,6 +431,7 @@ def main():
406431
ins_bef = parsed_args.get('insertbefore')
407432
encoding = parsed_args.get('encoding')
408433
tmphlq = parsed_args.get('tmp_hlq')
434+
force = parsed_args.get('force')
409435

410436
if parsed_args.get('state') == 'present':
411437
if backrefs and regexp is None:
@@ -453,9 +479,10 @@ def main():
453479
# state=present, insert/replace a line with matching regex pattern
454480
# state=absent, delete lines with matching regex pattern
455481
if parsed_args.get('state') == 'present':
456-
return_content = present(src, quotedString(line), quotedString(regexp), quotedString(ins_aft), quotedString(ins_bef), encoding, firstmatch, backrefs)
482+
return_content = present(src, quotedString(line), quotedString(regexp), quotedString(ins_aft), quotedString(ins_bef), encoding, firstmatch,
483+
backrefs, force)
457484
else:
458-
return_content = absent(src, quotedString(line), quotedString(regexp), encoding)
485+
return_content = absent(src, quotedString(line), quotedString(regexp), encoding, force)
459486
stdout = return_content.stdout_response
460487
stderr = return_content.stderr_response
461488
rc = return_content.rc

tests/functional/modules/test_zos_blockinfile_func.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: utf-8 -*-
22

3-
# Copyright (c) IBM Corporation 2020, 2022
3+
# Copyright (c) IBM Corporation 2020, 2022, 2023
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.
66
# You may obtain a copy of the License at
@@ -17,6 +17,8 @@
1717
DsGeneral,
1818
DsNotSupportedHelper,
1919
DsGeneralResultKeyMatchesRegex,
20+
DsGeneralForce,
21+
DsGeneralForceFail,
2022
)
2123
import os
2224
import sys
@@ -238,6 +240,14 @@
238240
test_ds_block_insertafter_eof_with_backup_name=dict(
239241
block="export ZOAU_ROOT\nexport ZOAU_HOME\nexport ZOAU_DIR",
240242
state="present", backup=True, backup_name=MVS_BACKUP_DS),
243+
test_ds_block_insertafter_regex_force=dict(
244+
path="",insertafter="ZOAU_ROOT=",
245+
block="ZOAU_ROOT=/mvsutil-develop_dsed\nZOAU_HOME=\\$ZOAU_ROOT\nZOAU_DIR=\\$ZOAU_ROOT",
246+
state="present", force=True),
247+
test_ds_block_insertafter_regex_force_fail=dict(
248+
path="",insertafter="ZOAU_ROOT=",
249+
block="ZOAU_ROOT=/mvsutil-develop_dsed\nZOAU_HOME=\\$ZOAU_ROOT\nZOAU_DIR=\\$ZOAU_ROOT",
250+
state="present", force=False),
241251
expected=dict(test_uss_block_insertafter_regex_defaultmarker="""if [ -z STEPLIB ] && tty -s;
242252
then
243253
export STEPLIB=none
@@ -1498,6 +1508,17 @@ def test_ds_block_insertafter_eof_with_backup(ansible_zos_module, dstype, encodi
14981508
ansible_zos_module.all.zos_data_set(name=backup_ds_name, state="absent")
14991509

15001510

1511+
@pytest.mark.ds
1512+
@pytest.mark.parametrize("dstype", DS_TYPE)
1513+
def test_ds_block_insertafter_regex_force(ansible_zos_module, dstype):
1514+
TEST_ENV["DS_TYPE"] = dstype
1515+
DsGeneralForce(
1516+
ansible_zos_module, TEST_ENV,
1517+
TEST_INFO["test_ds_block_insertafter_regex_force"],
1518+
TEST_INFO["expected"]["test_uss_block_insertafter_regex_defaultmarker"]
1519+
)
1520+
1521+
15011522
#########################
15021523
# Negative tests
15031524
#########################
@@ -1545,4 +1566,14 @@ def test_ds_not_supported(ansible_zos_module, dstype):
15451566
DsNotSupportedHelper(
15461567
TEST_INFO["test_ds_block_insertafter_regex"]["test_name"], ansible_zos_module,
15471568
TEST_ENV, TEST_INFO["test_uss_block_insertafter_regex"]
1548-
)
1569+
)
1570+
1571+
1572+
@pytest.mark.ds
1573+
@pytest.mark.parametrize("dstype", DS_TYPE)
1574+
def test_ds_block_insertafter_regex_fail(ansible_zos_module, dstype):
1575+
TEST_ENV["DS_TYPE"] = dstype
1576+
DsGeneralForceFail(
1577+
ansible_zos_module, TEST_ENV,
1578+
TEST_INFO["test_ds_block_insertafter_regex_force_fail"],
1579+
)

0 commit comments

Comments
 (0)