Skip to content

Commit 69018a4

Browse files
Merge pull request #1 from AndrewTwydell/fail-on-nodata
Fail on nodata
2 parents dfdcc7e + bcc032e commit 69018a4

File tree

4 files changed

+193
-10
lines changed

4 files changed

+193
-10
lines changed

plugins/module_utils/cmci.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,8 @@ def handle_response(self, response_dict): # type: (Dict) -> None
418418
feedback = errors_node[FEEDBACK]
419419
self.result[FEEDBACK] = read_error_node(feedback)
420420

421-
# Non-OK CPSM responses fail the module
422-
if cpsm_response_code != 1024:
421+
# If CPSM response code not in Valid List, fail the module
422+
if self.get_ok_cpsm_response_codes().count(cpsm_response_code) == 0:
423423
self._fail(
424424
'CMCI request failed with response "{0}" reason "{1}"'
425425
.format(
@@ -436,6 +436,9 @@ def handle_response(self, response_dict): # type: (Dict) -> None
436436
'Could not parse CMCI response: missing node "{0}"'
437437
.format(e.args[0])
438438
)
439+
440+
def get_ok_cpsm_response_codes(self):
441+
return [1024]
439442

440443
def init_url(self): # type: () -> str
441444
t = self._p.get(TYPE).lower()

plugins/modules/cmci_get.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@
4040
- The count value must be an integer; a value of zero is not permitted.
4141
type: int
4242
required: false
43+
fail_on_nodata:
44+
description:
45+
- Specifies whether the module should fail if no data is returned by the
46+
query. If set to true, the module will fail if no data is returned.
47+
- Default behaviour is for the module to fail if no data is returned. When
48+
set to false, the module will return OK, just with no records.
49+
type: bool
50+
required: false
51+
default: true
4352
'''
4453

4554

@@ -87,6 +96,23 @@
8796
value: MYGRP
8897
record_count: 1
8998
99+
- name: pass module even if bundle definition is not found
100+
cmci_get:
101+
cmci_host: 'winmvs2c.hursley.ibm.com'
102+
cmci_port: 10080
103+
cmci_cert: './sec/ansible.pem'
104+
cmci_key: './sec/ansible.key'
105+
context: 'iyk3z0r9'
106+
type: cicsdefinitionbundle
107+
resources:
108+
filter:
109+
name: MYBUNDLE
110+
get_parameters:
111+
- name: csdgroup
112+
value: MYGRP
113+
record_count: 1
114+
fail_on_nodata: "false"
115+
90116
- name: Using complex_filter to combine filter expressions and change operators
91117
cmci_get:
92118
cmci_host: 'winmvs2c.hursley.ibm.com'
@@ -496,6 +522,7 @@
496522

497523

498524
_RECORD_COUNT = 'record_count'
525+
_FAIL_ON_NODATA = 'fail_on_nodata'
499526

500527

501528
class AnsibleCMCIGetModule(AnsibleCMCIModule):
@@ -507,6 +534,10 @@ def init_argument_spec(self): # type: () -> Dict
507534
argument_spec.update({
508535
_RECORD_COUNT: {
509536
'type': 'int'
537+
},
538+
_FAIL_ON_NODATA: {
539+
'type': 'bool',
540+
'default': True
510541
}
511542
})
512543
argument_spec.update(RESOURCES_ARGUMENT)
@@ -522,6 +553,14 @@ def init_url(self): # type: () -> str
522553
url = url + '//' + str(self._p.get(_RECORD_COUNT))
523554

524555
return url
556+
557+
def get_ok_cpsm_response_codes(self):
558+
ok_codes = super(AnsibleCMCIGetModule, self).get_ok_cpsm_response_codes()
559+
560+
if not self._p.get(_FAIL_ON_NODATA):
561+
ok_codes.append(1027)
562+
563+
return ok_codes
525564

526565

527566
def main():

tests/unit/helpers/cmci_helper.py

100644100755
Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ def stub_records(self, method, resource_type, records, *args, **kwargs):
6161
**kwargs
6262
)
6363

64+
def stub_nodata(self, method, resource_type, *args, **kwargs):
65+
return self.stub_cmci(
66+
method,
67+
resource_type,
68+
response_dict=create_nodata_response(),
69+
*args,
70+
**kwargs
71+
)
72+
6473
def stub_non_ok_records(self, method, resource_type, feedback, *args, **kwargs):
6574
return self.stub_cmci(
6675
method,
@@ -73,7 +82,7 @@ def stub_non_ok_records(self, method, resource_type, feedback, *args, **kwargs):
7382
def stub_cmci(self, method, resource_type, scheme='https', host=HOST, port=PORT,
7483
context=CONTEXT, scope=None, parameters='', response_dict=None,
7584
headers=None, status_code=200, reason='OK',
76-
record_count=None, **kwargs):
85+
record_count=None, fail_on_nodata=True, **kwargs):
7786
if headers is None:
7887
headers = {'CONTENT-TYPE': 'application/xml'}
7988
url = '{0}://{1}:{2}/CICSSystemManagement/{3}/{4}/{5}{6}{7}'\
@@ -206,6 +215,17 @@ def create_records_response(resource_type, records): # type: (str, List) -> Ord
206215
))
207216
)
208217

218+
def create_nodata_response(): # type: (str, List) -> OrderedDict
219+
return create_cmci_response(
220+
('resultsummary', od(
221+
('@api_response1', '1027'),
222+
('@api_response2', '0'),
223+
('@api_response1_alt', 'NODATA'),
224+
('@api_response2_alt', ''),
225+
('@recordcount', '0')
226+
))
227+
)
228+
209229

210230
def create_feedback_response(errors): # type: (str, List) -> OrderedDict
211231

tests/unit/modules/test_cmci_get.py

100644100755
Lines changed: 128 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,117 @@ def test_ok_context_record_count(cmci_module): # type: (CMCITestHelper) -> None
552552
'type': 'cicslocalfile'
553553
})
554554

555+
def test_fail_on_nodata_false(cmci_module): # type: (CMCITestHelper) -> None
556+
cmci_module.stub_nodata('GET', 'cicslocalfile', fail_on_nodata=False)
557+
558+
cmci_module.expect(result(
559+
'https://winmvs2c.hursley.ibm.com:26040/CICSSystemManagement/cicslocalfile/CICSEX56/',
560+
records=None,
561+
cpsm_response='NODATA',
562+
cpsm_response_code=1027
563+
))
564+
565+
cmci_module.run(cmci_get, {
566+
'cmci_host': HOST,
567+
'cmci_port': PORT,
568+
'context': CONTEXT,
569+
'type': 'cicslocalfile',
570+
'fail_on_nodata': False
571+
})
572+
573+
def test_fail_on_nodata_false_record_count(cmci_module): # type: (CMCITestHelper) -> None
574+
cmci_module.stub_nodata('GET', 'cicslocalfile', record_count=1, fail_on_nodata=False)
575+
576+
cmci_module.expect(result(
577+
'https://winmvs2c.hursley.ibm.com:26040/CICSSystemManagement/cicslocalfile/CICSEX56///1',
578+
records=None,
579+
cpsm_response='NODATA',
580+
cpsm_response_code=1027
581+
))
582+
583+
cmci_module.run(cmci_get, {
584+
'cmci_host': HOST,
585+
'cmci_port': PORT,
586+
'context': CONTEXT,
587+
'type': 'cicslocalfile',
588+
'record_count': 1,
589+
'fail_on_nodata': False
590+
})
591+
592+
def test_fail_on_nodata_false_with_data(cmci_module): # type: (CMCITestHelper) -> None
593+
records = [{'name': 'bat', 'dsname': 'STEWF.BLOP.BLIP'}]
594+
595+
cmci_module.stub_records('GET', 'cicslocalfile', records, fail_on_nodata=False)
596+
597+
cmci_module.expect(result(
598+
'https://winmvs2c.hursley.ibm.com:26040/CICSSystemManagement/cicslocalfile/CICSEX56/',
599+
records=records,
600+
))
601+
602+
cmci_module.run(cmci_get, {
603+
'cmci_host': HOST,
604+
'cmci_port': PORT,
605+
'context': CONTEXT,
606+
'type': 'cicslocalfile',
607+
'fail_on_nodata': False
608+
})
609+
610+
def test_fail_on_nodata_true_with_data(cmci_module): # type: (CMCITestHelper) -> None
611+
records = [{'name': 'bat', 'dsname': 'STEWF.BLOP.BLIP'}]
612+
613+
cmci_module.stub_records('GET', 'cicslocalfile', records, fail_on_nodata=True)
614+
615+
cmci_module.expect(result(
616+
'https://winmvs2c.hursley.ibm.com:26040/CICSSystemManagement/cicslocalfile/CICSEX56/',
617+
records=records,
618+
))
619+
620+
cmci_module.run(cmci_get, {
621+
'cmci_host': HOST,
622+
'cmci_port': PORT,
623+
'context': CONTEXT,
624+
'type': 'cicslocalfile',
625+
'fail_on_nodata': True
626+
})
627+
628+
def test_fail_on_nodata_true_with_data_record_count(cmci_module): # type: (CMCITestHelper) -> None
629+
records = [{'name': 'bat', 'dsname': 'STEWF.BLOP.BLIP'}]
630+
631+
cmci_module.stub_records('GET', 'cicslocalfile', records, record_count=1, fail_on_nodata=True)
632+
633+
cmci_module.expect(result(
634+
'https://winmvs2c.hursley.ibm.com:26040/CICSSystemManagement/cicslocalfile/CICSEX56///1',
635+
records=records,
636+
))
637+
638+
cmci_module.run(cmci_get, {
639+
'cmci_host': HOST,
640+
'cmci_port': PORT,
641+
'context': CONTEXT,
642+
'type': 'cicslocalfile',
643+
'record_count': 1,
644+
'fail_on_nodata': True
645+
})
646+
647+
def test_fail_on_nodata_true(cmci_module): # type: (CMCITestHelper) -> None
648+
cmci_module.stub_nodata('GET', 'cicslocalfile', fail_on_nodata=True)
649+
650+
cmci_module.expect(result(
651+
'https://winmvs2c.hursley.ibm.com:26040/CICSSystemManagement/cicslocalfile/CICSEX56/',
652+
records=None,
653+
cpsm_response='NODATA',
654+
cpsm_response_code=1027,
655+
failed=True,
656+
msg='CMCI request failed with response "NODATA" reason "1027"'
657+
))
658+
659+
cmci_module.run(cmci_get, {
660+
'cmci_host': HOST,
661+
'cmci_port': PORT,
662+
'context': CONTEXT,
663+
'type': 'cicslocalfile',
664+
'fail_on_nodata': True
665+
})
555666

556667
def test_sanitise_filter_value(cmci_module): # type: (CMCITestHelper) -> None
557668
records = [{'applid': 'REGION1', 'cicsstaus': 'ACTIVE'}]
@@ -765,22 +876,32 @@ def test_invalid_cmci_type(cmci_module): # type: (CMCITestHelper) -> None
765876
}
766877
})
767878

768-
769-
def result(url, records, http_status='OK', http_status_code=200):
770-
return {
879+
def result(url, records, http_status='OK', http_status_code=200, cpsm_response='OK', cpsm_response_code=1024, failed=False, msg=None):
880+
result_dict = {
771881
'changed': False,
772882
'connect_version': '0560',
773883
'cpsm_reason': '',
774884
'cpsm_reason_code': 0,
775-
'cpsm_response': 'OK',
776-
'cpsm_response_code': 1024,
885+
'cpsm_response': cpsm_response,
886+
'cpsm_response_code': cpsm_response_code,
777887
'http_status': http_status,
778888
'http_status_code': http_status_code,
779-
'record_count': len(records),
780-
'records': records,
889+
'record_count': 0,
781890
'request': {
782891
'url': url,
783892
'method': 'GET',
784893
'body': None
785894
}
786895
}
896+
897+
if records != None:
898+
result_dict.update({
899+
'records': records,
900+
'record_count': len(records)
901+
})
902+
if failed == True and msg != None:
903+
result_dict.update({
904+
'failed': True,
905+
'msg': msg
906+
})
907+
return result_dict

0 commit comments

Comments
 (0)