diff --git a/endevor/Field-Developed-Programs/ISPF-tools-for-Quick-Edit-and-Endevor/Moveout.rex b/endevor/Field-Developed-Programs/ISPF-tools-for-Quick-Edit-and-Endevor/Moveout.rex index 0ad0a72..1908703 100644 --- a/endevor/Field-Developed-Programs/ISPF-tools-for-Quick-Edit-and-Endevor/Moveout.rex +++ b/endevor/Field-Developed-Programs/ISPF-tools-for-Quick-Edit-and-Endevor/Moveout.rex @@ -33,6 +33,7 @@ ADDRESS ISREDIT " REPLACE "MYMBR LPOS1+1 LPOS2 REPRC = RC LPOS1 = 1 + IF SYSVAR(SYSENV) = 'BACK' THEN SAY MYMBR END; /* ELSE (RETCODE ...) */ IF REPRC = 0 THEN , ADDRESS ISREDIT " DELETE "LPOS1 LPOS2 ; diff --git a/endevor/ServiceNow-Interface/C1UEXTR7.rex b/endevor/ServiceNow-Interface/C1UEXTR7.rex deleted file mode 100644 index ab6f3fe..0000000 --- a/endevor/ServiceNow-Interface/C1UEXTR7.rex +++ /dev/null @@ -1,604 +0,0 @@ -/* rexx */ -/* Perform various Package actions in REXX */ -/* */ -/* A COBOL exit CALLS this REXX and provides values for */ -/* REXX variables, including these. */ -/* Find documentation on these in the TechDocs documentation */ -/* where each underscore appears as a dash in the documentation. */ -/* For example, PECB_PACKAGE_ID is documented as */ -/* PECB-PACKAGE-ID */ -/* */ -/* PECB_PACKAGE_ID PAPP_GROUP_NAME */ -/* PECB_FUNCTION_LITERAL PAPP_ENVIRONMENT */ -/* PECB_SUBFUNC_LITERAL PAPP_QUORUM_COUNT */ -/* PECB_BEF_AFTER_LITERAL PAPP_APPROVER_FLAG */ -/* PECB_USER_BATCH_JOBNAME PAPP_APPR_GRP_TYPE */ -/* PREQ_PKG_CAST_COMPVAL PAPP_APPR_GRP_DISQ */ -/* PHDR_PKG_SHR_OPTION PAPP_SEQUENCE_NUMBER */ -/* PHDR_PKG_ENV */ -/* PHDR_PKG_STGID */ -/* Address fields are provided for fields that may be */ -/* modified by the REXX. */ -/* Address_PECB_MESSAGE Address_MYSMTP_SUBJECT */ -/* Address_MYSMTP_MESSAGE Address_MYSMTP_TEXT */ -/* Address_MYSMTP_USERID Address_MYSMTP_URL */ -/* Address_MYSMTP_FROM Address_MYSMTP_EMAIL_IDS */ -/* MYSMTP_EMAIL_IDS MYSMTP_EMAIL_ID_SIZE */ -/* */ - /* Values to be set for your site...... */ - /* For package REVIEW (APPROVE/DENY)..... */ - /* Enter location of Approver Group sequencing ... */ - ApproverGroupSequence= 'YOURSITE.NDVR.PARMLIB(APPROVER)' - - /* Do you want all CAST actions to be peformed in Batch? */ - Force_CAST_in_Batch = 'Y' ; /* Y/N */ - Force_CAST_in_Batch = 'N' ; /* Y/N */ - - /* If wanting to limit the use of this exit, uncomment... */ - If USERID() /= 'IBMUSER' then exit - - /* If wanting to send email, use these variables with */ - /* designated maximum lengths. The Rexx will put them */ - /* into their proper places. */ - /* */ - /* Variable Description max-Len */ - /* */ - /* MySMTP_Message Email Message 80 */ - /* MySMTP_From Email From name 50 */ - /* MySMTP_Subject Email Subject 50 */ - /* MySMTP_textline.1 Text line in email 133 */ - /* MySMTP_textline.2 " 133 */ - /* MySMTP_textline.nn up to 99 133 */ - /* MySMTP_textline.0 Number Text lines used (max 99) 2 */ - /* MySMTP_URL Y/N 1 */ - /* MYSMTP_EMAIL_IDS List of space delimited userids *Exit */ - /* The COBOL exit OCCURS clause determines / */ - /* In case these are not already allocated, these are attempted */ - STRING = "ALLOC DD(SYSTSPRT) SYSOUT(A) " - CALL BPXWDYN STRING; - STRING = "ALLOC DD(SYSTSIN) DUMMY" - CALL BPXWDYN STRING; - - /* Parms are REXX statements passed from COBOL exit */ - Arg Parms - Parms = Strip(Parms) - sa= 'Parms len=' Length(Parms) - - /* If C1UEXTR7 is allocated to anything, turn on Trace */ - WhatDDName = 'C1UEXTR7' - CALL BPXWDYN "INFO FI("WhatDDName")", - "INRTDSN(DSNVAR) INRDSNT(myDSNT)" - If Substr(DSNVAR,1,1) /= ' ' then TraceRQ = 'Y' - - If TraceRQ = 'Y' then, - Say 'C1UEXTR7 is called again:' - - /* Parms from C1UEXT07 is a string of REXX statements */ - - Interpret Parms - If TraceRQ = 'Y' & PECB_MODE = 'B' then Trace r - - If Substr(PHDR_PKG_NOTE5,1,5) = 'TRACE' then TraceRQ = 'Y' - - If TraceRQ = 'Y' then, - Do - Trace ?r - Sa= 'CALL_REASON = ' CALL_REASON - Sa= 'PECB_FUNCTION_LITERAL = ' PECB_FUNCTION_LITERAL - Sa= 'PECB_SUBFUNC_LITERAL = ' PECB_SUBFUNC_LITERAL - Sa= 'PECB_BEF_AFTER_LITERAL= ' PECB_BEF_AFTER_LITERAL - Sa= 'PECB_PACKAGE_ID = ' PECB_PACKAGE_ID - Sa= 'MYSMTP_EMAIL_ID_SIZE = ' MYSMTP_EMAIL_ID_SIZE - End - - /* Initialize variables.... */ - Message = '' - MessageCode = ' ' - MyRc = 0 - - /* Validate Package prefix with ServiceNow */ - If PECB_FUNCTION_LITERAL ='CREATE' &, - PECB_BEF_AFTER_LITERAL ='BEFORE' &, - Substr(PECB_PACKAGE_ID,1,3) = 'PRB' then, - Do - Call Validate_PackageID - If MyRc > 0 then Exit - End - - /* Enforce packages to be Backout Enabled */ - IF PREQ_BACKOUT_ENABLED /= 'Y' then, - Do - Message = 'Package made to be Backout enabled' - MyRc = 4 - hexAddress = D2X(Address_PREQ_BACKOUT_ENABLED) - storrep = STORAGE(hexAddress,,'Y') - Call SetExitReturnInfo - Exit - End; - - If PECB_FUNCTION_LITERAL ='CAST' &, - PECB_SUBFUNC_LITERAL ='CAST' &, - PECB_BEF_AFTER_LITERAL ='BEFORE' &, - PECB_MODE = "T" &, /* TSO foreground */ - Force_CAST_in_Batch = 'Y' then, - Call SubmitBatchCAST - Else, - If PECB_FUNCTION_LITERAL ='CAST' &, - PECB_SUBFUNC_LITERAL ='CAST' &, - PECB_BEF_AFTER_LITERAL ='AFTER' then, - Call ManageEmails ; - - Exit - -ManageEmails: - - If TraceRQ = 'Y' then Trace ?R - whereami = 'ManageEmails' - - /* Only run if the exit is giving us an Approver Group */ - If Substr(CALL_REASON,1,16) = 'APPROVER GROUP #' then, - Do - Call SaveOffApproverGrpInfo - Return - End - - /*****************************************************************/ - /* Initializaztion and Example statements */ - /*****************************************************************/ - MySMTP_Message =, - 'YOURSITE.YOUR.NDVR.NODES1.CLSTREXX(C1UEXTR7)' - MySMTP_Subject = 'Please Approve Package' PECB_PACKAGE_ID - MySMTP_From = Left('YOURSITE your testing Endevor',50) - MySMTP_textline.1 = 'Package' PECB_PACKAGE_ID, - ' has been CAST and is ready for APPROVAL.' - MySMTP_textline.2 = 'Your Review and approval of package', - PECB_PACKAGE_ID 'is reqested.' - MySMTP_textline.3 = ' ' - MySMTP_textline.4 = ' ' - MySMTP_textline.0 = 4 - MYSMTP_EMAIL_IDS = '' - - /* Only run if the exit says all Approver Grps are done */ - If Substr(CALL_REASON,1,22) = 'NO MORE APPROVER GRPS ' then, - Do - Call CheckApproverGroupSequence - Return - End - - Return - -Validate_PackageID: - - If TraceRQ = 'Y' then Trace ?R - whereami = 'Validate_PackageID' - /* build STDENV input */ - CALL BPXWDYN , - "ALLOC DD(STDENV) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", - " RECFM(F,B) TRACKS ", - " NEW UNCATALOG REUSE "; - Queue "EXPORT PATH=$PATH:" ||, - "'/usr/lpp/IBM/cyp/v3r11/pyz/lib/python3.11/'" - Queue "EXPORT VIRTUAL_ENV=" ||, - "'/u/users/NDVRTeam/venv/lib/python3.11/site-packages/'" - "EXECIO 2 DISKW STDENV (finis" - - /* build BPXBATCH inputs and outputs */ - /* build STDPARM input */ - CALL BPXWDYN , - "ALLOC DD(STDPARM) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", - " RECFM(F,B) TRACKS ", - " NEW UNCATALOG REUSE "; - Queue "sh cd " ||, - "/u/users/NDVRTeam/venv/lib/python3.11/site-packages;" - Queue "python ServiceNow.py" Substr(PECB_PACKAGE_ID,1,10) - "EXECIO 2 DISKW STDPARM (finis" - - CALL BPXWDYN , - "ALLOC DD(STDOUT) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", - " RECFM(F,B) TRACKS ", - " NEW UNCATALOG REUSE "; - Notnow =, - "ALLOC DD(STDOUT) DA('IBMUSER.STDOUT') OLD REUSE " - - CALL BPXWDYN , - "ALLOC DD(STDERR) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", - " RECFM(F,B) TRACKS ", - " NEW UNCATALOG REUSE "; - Notnow =, - "ALLOC DD(STDERR) DA(*) SHR REUSE" - - CALL BPXWDYN "ALLOC DD(STDIN) DUMMY SHR REUSE" - CALL BPXWDYN "ALLOC DD(STDERR) DA(*) SHR REUSE" - - ADDRESS LINK 'BPXBATCH' - CallRC = RC - - "EXECIO * DISKR STDOUT (Stem stdout. finis" - lastrec# = stdout.0 - lastrecord = Substr(stdout.lastrec#,1,40) - - If Pos("Exists",lastrecord) = 0 then, - Do - Message = 'C1UEXTR7 - Package prefix' PECB_PACKAGE_ID ||, - ' is not defined to Service-Now' - MessageCode = 'U033' - MyRc = 8 - Call SetExitReturnInfo - End - - If CallRC = 0 then, - Do - CALL BPXWDYN "FREE DD(STDENV) " - CALL BPXWDYN "FREE DD(STDPARM)" - CALL BPXWDYN "FREE DD(STDOUT) " - CALL BPXWDYN "FREE DD(STDIN) " - CALL BPXWDYN "FREE DD(STDERR) " - End - - Return; - -SaveOffApproverGrpInfo: - - If TraceRQ = 'Y' then Trace ?R - PAPP_SEQUENCE_NUMBER = Substr(CALL_REASON,17,4) - numberQueued = QUEUED() - If PAPP_SEQUENCE_NUMBER = "0001" & numberQueued > 0 then, - Do numberQueued /* Clear out whatever is queued */ - pull leftovers - End - If PAPP_SEQUENCE_NUMBER = "0001" then, - CALL BPXWDYN , /* save Approver group data */ - "ALLOC DD(C1UEXTD7) LRECL(180) BLKSIZE(18000) SPACE(1,1) ", - " RECFM(F,B) TRACKS ", - " MOD UNCATALOG REUSE "; - - pkgGrp# = Strip(PAPP_SEQUENCE_NUMBER,'L','0') - PAPP_GROUP_NAME = Strip(PAPP_GROUP_NAME) - Queue 'pkgGrp# = 'pkgGrp# - Queue 'GROUP_NAME.pkgGrp# ="'PAPP_GROUP_NAME'"' - Queue 'ENVIRONMENT.pkgGrp# ="'Strip(PAPP_ENVIRONMENT)'"' - Queue 'APPR_GRP_TYPE.pkgGrp# ="'Strip(PAPP_APPR_GRP_TYPE)'"' - Queue 'APPR_GRP_DISQ.pkgGrp# ="'Strip(PAPP_APPR_GRP_DISQ)'"' - Queue 'APPROVAL_FLAGS.pkgGrp# ="'Strip(PAPP_APPROVAL_FLAGS)'"' - Queue 'STATUS.'PAPP_GROUP_NAME '="'Strip(PAPP_APPROVER_FLAG)'"' - Queue 'QUORUM.'PAPP_GROUP_NAME '='Strip(PAPP_QUORUM_COUNT,'L','0') - Queue 'USRLST.'PAPP_GROUP_NAME '="'Strip(PAPP_APPROVAL_IDS)'"' - - numberQueued = QUEUED() - "EXECIO" numberQueued " DISKW C1UEXTD7 " - - Return; - -CheckApproverGroupSequence: - - If TraceRQ = 'Y' then Trace ?R - whereami = 'CheckApproverGroupSequence' - - /* If C1UEXTD7 is allocated to anything, we have approvers */ - WhatDDName = 'C1UEXTD7' - CALL BPXWDYN "INFO FI("WhatDDName")", - "INRTDSN(DSNVAR) INRDSNT(myDSNT)" - If Substr(DSNVAR,1,1) = ' ' then Return - - "EXECIO 0 DISKW C1UEXTD7 (Finis" - "EXECIO * DISKR C1UEXTD7 (Finis" - CALL BPXWDYN "FREE DD(C1UEXTD7)" - numberQueued = QUEUED() - - /* Analyze Exit-provided Approver Group info */ - pkgGrp# = 0 - /* By default, ordered Approver Groups are not related */ - STATUS. = 'NotRelated' - QUORUM. = 0 - - /* Return Approver Group info for this package */ - Do q# = 1 to numberQueued - Parse Pull something - If TraceRQ = 'Y' then say "@187" something - interpret something - End; - ThisEnvironment = ENVIRONMENT.pkgGrp# - - /* Read the site's required Approver Group sequencing */ - CALL BPXWDYN, - "ALLOC DD(APPROVER) DA('"ApproverGroupSequence"') SHR REUSE" - "EXECIO * DISKR APPROVER (Stem ordered. Finis" - CALL BPXWDYN "FREE DD(APPROVER)" - - /* Build a sequenced list of all named Approver Groups */ - OrderedApproverGroups = '' - /* Set a default value to be 1 greater than number of groups */ - NotOrdered = ordered.0 + 1 - Sequence. = NotOrdered - Do ord# = 1 to ordered.0 - orderedEntry = ordered.ord# - orderedEnv = Word(orderedEntry,1) - If orderedEnv /= thisEnvironment then iterate - orderedApproverGroup = Word(orderedEntry,2) - If orderedApproverGroup = 'AllOthers' then, - DefaultOrder = ord# - SEQUENCE.orderedApproverGroup = ord# - If TraceRQ = 'Y' then, - say "@201 Sequence for" orderedApproverGroup "is" ord# - End; /* Do ord# = 1 to ordered.0 */ - - Sequence.NotOrdered = DefaultOrder - unsorted_list = "" - /* Build a list of Approver Groups for this package */ - PackageApproverGroups = '' - Do p# = 1 to pkgGrp# - PackageApproverGroup = GROUP_NAME.p# - thisSequence = SEQUENCE.PackageApproverGroup - entry = Right(thisSequence,4,'0') || '.' ||, - PackageApproverGroup - unsorted_list = unsorted_list entry - If TraceRQ = 'Y' then, - Say "unsorted_list=" unsorted_list - End; - - Call SortApproverGroupList; - - If TraceRQ = 'Y' then say "@220 PackageApproverGroups =", - sorted_list, - ' ThisEnvironment =' ThisEnvironment - /* Go through the Sorted list to identify the status */ - /* of the next group(s) to be approved */ - /* Find the 1st Approver group this user belongs to.... */ - thisApprover = USERID() - - lastSequence = NotOrdered - Do seq# = 1 to Words(sorted_list) - entry = Word(sorted_list,seq#) - Parse Var entry thisSequence '.' orderedApproverGroup - orderedGroupStatus = STATUS.orderedApproverGroup - If orderedGroupStatus = 'APPROVED' then Iterate; - orderedGroupQuorum = QUORUM.orderedApproverGroup - If orderedGroupQuorum = 0 then Iterate; - If thisSequence > lastSequence then, - Do - Say 'We need to wait' - Leave; - End; - lastSequence = thisSequence - ListApprovers = USRLST.orderedApproverGroup - whereApprover = Wordpos(thisApprover,ListApprovers) - thisApproversFlag = " " - If whereApprover > 0 then, - Do - thisApproverGroup = orderedApproverGroup - thisApproversFlag = Word(APPROVAL_FLAGS.grp#,whereApprover) - End - - If TraceRQ = 'Y' then, - Say orderedApproverGroup 'has status of' orderedGroupStatus, - " Quorum" orderedGroupQuorum - - IF whereApprover > 0 &, - orderedGroupStatus /= 'NotRelated' then, - say 'You must wait for the' orderedApproverGroup, - " group's approval" - - If Words(ListApprovers) > 0 then, - Do w# = 1 to Words(ListApprovers) - Approver = Word(ListApprovers,w#) - If Wordpos(Approver,MYSMTP_EMAIL_IDS) = 0 &, - Substr(Approver,1,1) > '00'X then, - MYSMTP_EMAIL_IDS = MYSMTP_EMAIL_IDS Approver - End; /* Do w# = 1 to Words(ListApprovers) */ - - End; /* Do seq# = 1 to Words(sorted_list) */ - - /* Prepare email to the usrids in MYSMTP_EMAIL_IDS */ - Call PrepareEmail - - Return; - -SortApproverGroupList: - - If TraceRQ = 'Y' then Trace ?R - whereami = 'SortApproverGroupList' - say words(unsorted_list) unsorted_list; - drop sorted_list; - sorted_list = ""; - do forever ; - if words(unsorted_list) = 0 then leave; - lowest_entry = 1; - do entry = 1 to words(unsorted_list) - if word(unsorted_list,entry) <, - word(unsorted_list,lowest_entry) then, - lowest_entry = entry; - end; /* do entry = 1 .... */ - sorted_list = sorted_list word(unsorted_list,lowest_entry); - sa= "sorted_list=" sorted_list ; - position = wordindex(unsorted_list,lowest_entry) ; - len = length(word(unsorted_list,lowest_entry)); - unsorted_list =, - overlay(copies(" ",len),unsorted_list,position) ; - sa= "unsorted_list=" unsorted_list ; - end; /* do forever */ - drop unsorted_list; - say words(sorted_list) sorted_list; - - Return; - -PrepareEmail: - - If TraceRQ = 'Y' then Trace ?R - whereami = 'PrepareEmail' -/* Here you can make last-moment adjustments to the email */ - shortlist = Substr(MYSMTP_EMAIL_IDS,1,100) - If Substr(MYSMTP_EMAIL_IDS,100,1) /= ' ' &, - Substr(MYSMTP_EMAIL_IDS,101,1) /= ' ' then, - Do - whereEnd = WordIndex(shortlist,Words(shortlist)) - shortlist = DELWORD(shortlist,whereEnd) - End - MySMTP_textline.4 = 'Sent to Group:' shortlist - -/* Code in the section below should not be changed */ -/* Code in the section below should not be changed */ -/* Code in the section below should not be changed */ - - MySMTP_Message = Left(MySMTP_Message,80) - hexAddress = D2X(Address_MYSMTP_MESSAGE) - storrep = STORAGE(hexAddress,,Message) - - MySMTP_From = Left(MySMTP_From,50) - hexAddress = D2X(Address_MYSMTP_FROM) - storrep = STORAGE(hexAddress,,MySMTP_From) - - MySMTP_Subject = Left(MySMTP_Subject,50) - hexAddress = D2X(Address_MySMTP_Subject) - storrep = STORAGE(hexAddress,,MySMTP_Subject) - -/* If TraceRQ = 'Y' then Trace ?r */ - MYSMTP_COUNTER = '' - numberLines = Right(MySMTP_textline.0,2,'0') - Do l# = 1 to Length(numberLines) - MYSMTP_COUNTER = MYSMTP_COUNTER ||, - 'F' || Substr(numberLines,l#,1) - End - If TraceRQ = 'Y' then say 'MYSMTP_COUNTER=' MYSMTP_COUNTER - - MYSMTP_TEXT = X2C(MYSMTP_COUNTER) - Do line# = 1 to numberLines - MYSMTP_TEXT = MYSMTP_TEXT || Left(MySMTP_textline.line#,133) - End; /* Do line# = 1 to MySMTP_textline.0 */ - - hexAddress = D2X(Address_MYSMTP_TEXT) - storrep = STORAGE(hexAddress,,MYSMTP_TEXT) - - MySMTP_URL = 'N' - hexAddress = D2X(Address_MYSMTP_URL) - storrep = STORAGE(hexAddress,,MySMTP_URL) - - /* Provide distribution list ( list of userids ) to Exit */ - MYSMTP_EMAIL_IDS =, - Space(Strip(Translate(MYSMTP_EMAIL_IDS,' ','00'x))) - MYSMTP_EMAIL_IDS = MYSMTP_EMAIL_IDS '0000'x - MYSMTP_EMAIL_IDS = Left(MYSMTP_EMAIL_IDS,MYSMTP_EMAIL_ID_SIZE) - hexAddress = D2X(Address_MYSMTP_EMAIL_IDS) - storrep = STORAGE(hexAddress,,MYSMTP_EMAIL_IDS) - - Return; - -SubmitBatchCAST: - - If TraceRQ = 'Y' then Trace ?R - whereami = 'SubmitBatchCAST' - - /* For CASTing a package in Batch */ - /* Build a JCL model, and name its location here.... */ - CastPackageModel = 'YOURSITE.NDVR.TEAM.MODELS(CASTPKGE)' - /* Name a work dataset to be created then deleted... */ - CastPackageJCL = USERID()".C1UEXTR7.SUBMIT" - - "ALLOC F(CASTPKGE) DA('"CastPackageModel"') SHR REUSE" - "Execio * DISKR CASTPKGE (Stem jcl. Finis" - "FREE DD(CASTPKGE)" - - /* Adjust jobcard - only line 1 */ - jcl.1 = Overlay(USERID(),jcl.1,3) - /* If ZACCTNUM is allocated then get Users' Acct number */ - /* ZACCTNUM can optionally be called before C1UEXTR7 */ - /* and provide a User Accounting number. 7 */ - WhatDDName = 'ZACCTNUM' - CALL BPXWDYN "INFO FI("WhatDDName")", - "INRTDSN(DSNVAR) INRDSNT(myDSNT)" - If Substr(DSNVAR,1,1) /= ' ' then, - Do - "EXECIO 1 DISKR ZACCTNUM ( Finis" - Pull ZACCTNUM - ZACCTNUM = Word(Translate(ZACCTNUM,' ',"'"),2) - tail = '(' || ZACCTNUM || '), ' - whereParen = Pos('(', jcl.1) - if whereParen > 0 then, - jcl.1 = Overlay(tail,jcl.1,whereParen) - End - - "ALLOC F(SUBMTJCL) DA('"CastPackageJCL"') ", - "LRECL(80) BLKSIZE(16800) SPACE(5,5)", - "RECFM(F B) TRACKS ", - "MOD CATALOG REUSE " ; - "Execio * DISKW SUBMTJCL (Stem jcl. " - - /* Push Cast command (in reverse order). */ - If PREQ_PKG_CAST_COMPVAL = 'Y' then, - PUSH ' OPTION VALIDATE COMPONENTS .' - Else, - If PREQ_PKG_CAST_COMPVAL = 'W' then, - PUSH ' OPTION VALIDATE COMPONENT WITH WARNING .' - Else, - PUSH ' OPTION DO NOT VALIDATE COMPONENT .' - PUSH " CAST PACKAGE '" || PECB_PACKAGE_ID || "'" - "Execio 2 DISKW SUBMTJCL ( finis" - - Call Submit_n_save_jobInfo ; - "FREE F(SUBMTJCL) DELETE " - Message = JobData - MyRc = 8 - PACKAGE = PECB_PACKAGE_ID - MessageCode = 'U033' - Call SetExitReturnInfo - - Return; - -Submit_n_save_jobInfo: /* submit CastPackageModel job and save job info */ - - If TraceRQ = 'Y' then Trace ?R - whereami = 'Submit_n_save_jobInfo' - If TraceRQ = 'Y' then Say 'Submit_n_save_jobInfo:' - - Address TSO "PROFILE NOINTERCOM" /* turn off msg notific */ - CALL MSG "ON" - CALL OUTTRAP "out." - ADDRESS TSO "SUBMIT '"CastPackageJCL"'" ; - If RC > 4 then, - Do - MyRC = 8 - Message = 'Cannot find Element member to submit.' - Call SetExitReturnInfo - Exit(12) - End - CALL OUTTRAP "OFF" - Address TSO "PROFILE INTERCOM" /* turn on msg notific */ - - JobData = Strip(out.1); - jobinfo = Word(JobData,2) ; - If jobinfo = 'JOB' then, - jobinfo = Word(JobData,3) ; - SelectJobName = Word(Translate(jobinfo,' ',')('),1) ; - SelectJobNumber = Word(Translate(jobinfo,' ',')('),2) ; - - Return; - -SetExitReturnInfo: - - If TraceRQ = 'Y' then Trace ?R - whereami = 'SetExitReturnInfo' - If TraceRQ = 'Y' then Say 'SetExitReturnInfo: ' - - hexAddress = D2X(Address_PECB_MESSAGE) - storrep = STORAGE(hexAddress,,Message) - hexAddress = D2X(Address_PECB_ERROR_MESS_LENGTH) - storrep = STORAGE(hexAddress,,'0084'X) - hexAddress = D2X(Address_PECB_MODS_MADE_TO_PREQ) - storrep = STORAGE(hexAddress,,'Y') - - If MessageCode /= ' ' then, - Do - hexAddress = D2X(Address_PECB_MESSAGE_ID) - storrep = STORAGE(hexAddress,,MessageCode) - End - - -/* Set the return code for the exit */ -/* for PECB-NDVR-EXIT-RC */ - hexAddress = D2X(Address_PECB_NDVR_EXIT_RC) - If MyRc = 4 then, - storrep = STORAGE(hexAddress,,'00000004'X) - Else, - storrep = STORAGE(hexAddress,,'00000008'X) - - RETURN ; - diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/BatchQuery.jcl b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/BatchQuery.jcl new file mode 100644 index 0000000..34522d9 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/BatchQuery.jcl @@ -0,0 +1,15 @@ +//IBMUSERS JOB (0000), +// CLASS=A,MSGCLASS=X,REGION=4M, +// NOTIFY=&SYSUID +//*==================================================================* +// SET C1CCID=PRB0000014 +// SET C1CCID=CHG0040007 +//*==================================================================* +//* STEP 1 -- Execute REXX -> Python -> ServiceNow +//*------------------------------------------------------------------- +//STEP1 EXEC PGM=IRXJCL,PARM='SNOWQERY &C1CCID' +//SYSEXEC DD DISP=SHR,DSN=YOURSITE.NDVR.TEAM.REXX +//SYSTSIN DD DUMMY +//SYSTSPRT DD SYSOUT=* +//STDERR DD SYSOUT=* +//*-------------------------------------------------------------------- diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/BatchQuery.rex b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/BatchQuery.rex new file mode 100644 index 0000000..520be60 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/BatchQuery.rex @@ -0,0 +1,63 @@ +/* REXX */ + Trace ?R + Arg REQ_CCID . + If Substr(REQ_CCID,1,3) = 'PRB' |, + Substr(REQ_CCID,1,3) = 'CHG' then Call Validate_CCID; + Exit + +Validate_CCID: + + /* build STDENV input */ + CALL BPXWDYN , + "ALLOC DD(STDENV) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "EXPORT PATH=$PATH:" ||, + "'/usr/lpp/IBM/cyp/v3r11/pyz/lib/python3.11/'" + Queue "EXPORT VIRTUAL_ENV=" ||, + "'/u/users/NDVRTeam/venv/lib/python3.11/site-packages/'" + "EXECIO 2 DISKW STDENV (finis" + + /* build BPXBATCH inputs and outputs */ + /* build STDPARM input */ + CALL BPXWDYN , + "ALLOC DD(STDPARM) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "sh cd " ||, + "/u/users/NDVRTeam/venv/lib/python3.11/site-packages;" + Queue "python ServiceNow.py" REQ_CCID + "EXECIO 2 DISKW STDPARM (finis" + + CALL BPXWDYN , + "ALLOC DD(STDOUT) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Notnow =, + "ALLOC DD(STDOUT) DA('IBMUSER.STDOUT') OLD REUSE " + + CALL BPXWDYN "ALLOC DD(STDIN) DUMMY SHR REUSE" + CALL BPXWDYN "ALLOC DD(STDERR) DA(*) SHR REUSE" + + ADDRESS LINK 'BPXBATCH' + + "EXECIO * DISKR STDOUT (Stem stdout. finis" + lastrec# = stdout.0 + lastrecord = Substr(stdout.lastrec#,1,40) + + If Pos("Exists",lastrecord) = 0 then, + Do + Message = 'C1UEXTR2 - CCID ' REQ_CCID ||, + ' is not defined to Service-Now' + MessageCode = 'U012' + MyRc = 8 + End + + CALL BPXWDYN "FREE DD(STDENV) " + CALL BPXWDYN "FREE DD(STDPARM)" + CALL BPXWDYN "FREE DD(STDOUT) " + CALL BPXWDYN "FREE DD(STDIN) " + CALL BPXWDYN "FREE DD(STDERR) " + + Return; + diff --git a/endevor/ServiceNow-Interface/C1UEXT02.cob b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXT02.cob similarity index 99% rename from endevor/ServiceNow-Interface/C1UEXT02.cob rename to endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXT02.cob index 2d9f66b..cdee489 100644 --- a/endevor/ServiceNow-Interface/C1UEXT02.cob +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXT02.cob @@ -32,12 +32,10 @@ FILE-CONTROL. DATA DIVISION. FILE SECTION. - ***************************************************************** * W O R K I N G S T O R A G E * ***************************************************************** WORKING-STORAGE SECTION. - 77 WS-TRACE PIC X VALUE 'N'. 77 FLAGS PIC S9(8) BINARY. 77 REXX-RETURN-CODE PIC S9(8) BINARY. @@ -46,10 +44,8 @@ 77 EXECBLK-PTR POINTER. 77 ARGTABLE-PTR POINTER. 77 EVALBLK-PTR POINTER. - 01 IRXJCL PIC X(6) VALUE 'IRXJCL'. 01 IRXEXEC-PGM PIC X(08) VALUE 'IRXEXEC'. - 01 WS-VARIABLES. 03 WS-POINTER PIC 9(8) COMP. 03 WS-WORK-ADDRESS-ADR PIC S9(8) COMP SYNC . @@ -64,13 +60,10 @@ 03 ADDRESS-REQ-COMMENT PIC 9(10) . 03 WS-INSPECT-CCID PIC X(12) . 03 WS-INSPECT-COMMENT PIC X(40) . - - 01 BPXWDYN PIC X(8) VALUE 'BPXWDYN'. 01 ALLOC-STRING. 05 ALLOC-LENGTH PIC S9(4) BINARY VALUE 100. 05 ALLOC-TEXT PIC X(100). - * The block of data below is passed to the REXX program C1UEXTR2 * to ensure new elements are Registered. * The bulk of the logic is found in C1UEXTR2 @@ -81,7 +74,6 @@ 03 FILLER PIC X(01) VALUE SPACE . 02 ELM-EXECUTE-PARMS-IRXEXEC. 00004800 03 WS-REXX-STATEMENTS PIC X(4000). - 01 EXECBLK. 05 EXECBLK-ACRYN PIC X(08) VALUE 'IRXEXECB'. 05 EXECBLK-LENGTH PIC S9(8) BINARY @@ -94,7 +86,6 @@ 05 EXECBLK-DSNPTR POINTER VALUE NULL. 05 EXECBLK-DSNLEN PIC 9(04) COMP VALUE 0. - 01 EVALBLK. 05 EVALBLK-EVPAD1 PIC S9(8) BINARY VALUE 0. @@ -105,7 +96,6 @@ 05 EVALBLK-EVPAD2 PIC S9(8) BINARY VALUE 0. 05 EVALBLK-EVDATA PIC X(256). - 01 ARGUMENT. 02 ARGUMENT-1 OCCURS 1 TIMES. 05 ARGSTRING-PTR POINTER. @@ -114,13 +104,10 @@ VALUE -1. 02 ARGSTRING-LAST2 PIC S9(8) BINARY VALUE -1. - - *----------------------------------------------------------------- LINKAGE SECTION. *----------------------------------------------------------------- COPY EXITBLKS. - PROCEDURE DIVISION USING EXIT-CONTROL-BLOCK REQUEST-INFO-BLOCK @@ -130,10 +117,8 @@ TGT-ENVIRONMENT-BLOCK TGT-ELEMENT-MASTER-INFO-BLOCK TGT-FILE-CONTROL-BLOCK. - IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: RETURN-CODE =' RETURN-CODE . - IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: Entered' ' SRC-ENV-TYPE-OF-BLOCK=' SRC-ENV-TYPE-OF-BLOCK @@ -142,59 +127,45 @@ ' SRC-ENV-IO-TYPE=' SRC-ENV-IO-TYPE ' TGT-ENV-IO-TYPE=' TGT-ENV-IO-TYPE END-IF. - IF PACKAGE-INSPECT THEN GOBACK. - MOVE SPACES TO WS-REXX-STATEMENTS . - IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: Setting up addresses ' . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF ECB-RETURN-CODE . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-ECB-RETURN-CODE . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF ECB-MESSAGE-CODE. MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-ECB-MESSAGE-CODE. - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF ECB-MESSAGE-LENGTH. MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-ECB-MESSAGE-LENGTH . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF ECB-MESSAGE-TEXT . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-ECB-MESSAGE-TEXT . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF REQ-CCID . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-REQ-CCID . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF REQ-COMMENT . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-REQ-COMMENT . - ***** ***** / Convert COBOL exit block Datanames into Rexx \ ***** ***** IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: removing quote chars ' . - MOVE 1 TO WS-POINTER. - INSPECT REQ-CCID REPLACING ALL '"' BY X'7D'. INSPECT REQ-COMMENT REPLACING ALL '"' BY X'7D'. - IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: Stringing ECB vars ' . - STRING 'ECB_TSO_BATCH_MODE = "' DELIMITED BY SIZE @@ -313,11 +284,9 @@ INTO WS-REXX-STATEMENTS WITH POINTER WS-POINTER END-STRING. - IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: Stringing SRC vars ' 'SRC-ENV-IO-TYPE=' SRC-ENV-IO-TYPE . - IF SRC-ENV-LENGTH GREATER THAN ZERO MOVE SRC-ELM-ACTION-CCID TO WS-INSPECT-CCID INSPECT WS-INSPECT-CCID @@ -326,7 +295,6 @@ WS-INSPECT-COMMENT INSPECT WS-INSPECT-COMMENT REPLACING ALL '"' BY X'7D' - INSPECT WS-INSPECT-CCID REPLACING ALL '"' BY X'7D' INSPECT WS-INSPECT-COMMENT REPLACING ALL '"' BY X'7D' STRING @@ -357,7 +325,6 @@ INTO WS-REXX-STATEMENTS WITH POINTER WS-POINTER END-STRING - STRING 'SRC_ENV_ENVIRONMENT_NAME = "' DELIMITED BY SIZE @@ -411,11 +378,9 @@ WITH POINTER WS-POINTER END-STRING END-IF . - IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: Stringing TGT vars ' END-IF . - IF TGT-ENV-LENGTH GREATER THAN ZERO STRING 'TGT_ENV_ENVIRONMENT_NAME = "' @@ -481,7 +446,6 @@ INTO WS-REXX-STATEMENTS WITH POINTER WS-POINTER END-STRING - IF TGT-ENV-TYPE-OF-BLOCK = 'C' MOVE TGT-ELM-ACTION-CCID TO WS-INSPECT-CCID INSPECT WS-INSPECT-CCID @@ -490,7 +454,6 @@ WS-INSPECT-COMMENT INSPECT WS-INSPECT-COMMENT REPLACING ALL '"' BY X'7D' - STRING 'TGT_ELM_ACTION_CCID = "' DELIMITED BY SIZE @@ -511,11 +474,9 @@ END-IF. ***** \ Convert COBOL exit block Datanames into Rexx / ***** - IF WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: Calling Rexx' END-IF. - *****IF TSO MOVE 'C1UEXTR2' TO EXECBLK-MEMBER MOVE 4000 TO ARGSTRING-LENGTH(1) @@ -534,11 +495,8 @@ ***** END-IF ***** PERFORM 2201-FREE-SYSEXEC *****END-IF . - MOVE 0 TO RETURN-CODE . - GOBACK. - 1800-REXX-CALL-VIA-IRXEXEC. SET ARGSTRING-PTR (1) TO ARGUMENT-PTR . CALL 'SET-ARGUMENT-POINTER' USING ARGTABLE-PTR @@ -549,7 +507,6 @@ EVALBLK . MOVE 536870912 TO FLAGS MOVE 0 TO REXX-RETURN-CODE . - *--- CALL THE REXX EXEC --- CALL IRXEXEC-PGM USING EXECBLK-PTR ARGTABLE-PTR @@ -561,83 +518,66 @@ DUMMY-ZERO DUMMY-ZERO REXX-RETURN-CODE. - IF REXX-RETURN-CODE NOT = 0 DISPLAY 'C1UEXT02: IRXEXEC RETURN CODE = ' REXX-RETURN-CODE END-IF - CANCEL IRXEXEC-PGM . - ***************************************************************** ** Allocate DD REXFILE for TSO processing ***************************************************************** 2100-ALLOCATE-REXFILE. - MOVE SPACES TO ALLOC-TEXT . STRING 'ALLOC DD(REXFILE2) ', - 'DA(Your.Endevor.CLSTREXX)' + 'DA(your.ndvrhlq.REXX)' DELIMITED BY SIZE ' SHR REUSE' DELIMITED BY SIZE INTO ALLOC-TEXT END-STRING. PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . - ***************************************************************** ** Allocate DD SYSEXEC for batch processing ***************************************************************** 2101-ALLOCATE-SYSEXEC. - MOVE SPACES TO ALLOC-TEXT . STRING 'ALLOC DD(SYSEXEC) ', - 'DA(Your.Endevor.CLSTREXX)' + 'DA(your.ndvrhlq.REXX)' DELIMITED BY SIZE ' SHR REUSE' DELIMITED BY SIZE INTO ALLOC-TEXT END-STRING. PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . - ***************************************************************** ** DYNAMICALLY DE-ALLOCATE UNNEEDED REXX FILES ***************************************************************** 2200-FREE-REXFILES. - MOVE 'FREE DD(REXFILE2)' TO ALLOC-TEXT PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . - ***************************************************************** ** CALL BPXWDYN TO PREFORM REQUIRED REXX FUNCTIONS 2201-FREE-SYSEXEC. - MOVE 'FREE DD(SYSEXEC)' TO ALLOC-TEXT PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . - ***************************************************************** ** CALL BPXWDYN TO PREFORM REQUIRED REXX FUNCTIONS 9000-DYNAMIC-ALLOC-DEALLOC. - CALL BPXWDYN USING ALLOC-STRING - IF RETURN-CODE NOT = ZERO OR WS-TRACE = 'Y' THEN DISPLAY 'C1UEXT02: ALLOCATION result: RETURN CODE = ' RETURN-CODE DISPLAY ALLOC-TEXT END-IF - MOVE SPACES TO ALLOC-TEXT . - - ****************************************************************** * BEGIN NESTED PROGRAMS USED TO SET THE POINTERS OF DATA AREAS * THAT ARE BEING PASSED TO IRXEXEC SO THAT A REXX ROUTINE CAN * PASS DATA (OTHER THAN A RETURN CODE) BACK TO A COBOL PROGRAM. ****************************************************************** - ******** SET-ARG1-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-ARG1-POINTER. @@ -647,13 +587,11 @@ LINKAGE SECTION. 77 ARG-PTR POINTER. 77 ARG1 PIC X(16). - PROCEDURE DIVISION USING ARG-PTR ARG1. SET ARG-PTR TO ADDRESS OF ARG1 GOBACK. END PROGRAM SET-ARG1-POINTER. - ******** SET-ARGUMENT-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-ARGUMENT-POINTER. @@ -673,7 +611,6 @@ SET ARGTABLE-PTR TO ADDRESS OF ARGUMENT GOBACK. END PROGRAM SET-ARGUMENT-POINTER. - ******** SET-EXECBLK-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-EXECBLK-POINTER. @@ -696,7 +633,6 @@ SET EXECBLK-PTR TO ADDRESS OF EXECBLK GOBACK. END PROGRAM SET-EXECBLK-POINTER. - ******** SET-EVALBLK-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-EVALBLK-POINTER. diff --git a/endevor/ServiceNow-Interface/C1UEXTR2.rex b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTR2.rex similarity index 64% rename from endevor/ServiceNow-Interface/C1UEXTR2.rex rename to endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTR2.rex index 71b8612..82146d3 100644 --- a/endevor/ServiceNow-Interface/C1UEXTR2.rex +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTR2.rex @@ -6,20 +6,16 @@ /* o Reuses a comment value from element if comment is blank */ /* o Gives a friendly reminder if the SIGNOUT OVERRIDE is on */ /* -------------------------------------------------------------- */ - STRING = "ALLOC DD(SYSTSPRT) SYSOUT(A) " CALL BPXWDYN STRING; STRING = "ALLOC DD(SYSTSIN) DUMMY" CALL BPXWDYN STRING; - /* If C1UEXTR2 is allocated to anything, turn on Trace */ WhatDDName = 'C1UEXTR2' CALL BPXWDYN "INFO FI("WhatDDName")", "INRTDSN(DSNVAR) INRDSNT(myDSNT)" if Substr(DSNVAR,1,1) /= = ' ' then Trace ?r - Sa= 'You called ....CLSTREXX(C1UEXTR2) ' - /* In case these are not provided by the Exit */ SRC_ELM_ACTION_CCID = ' ' SRC_ELM_LEVEL_COMMENT = ' ' @@ -27,40 +23,48 @@ TGT_ELM_LEVEL_COMMENT = ' ' /* These Element Actions determine whehter to */ /* use SRC or TGT variables */ - ActionsThatUse_SRC = 'RETRIEVE MOVE DELETE GENERATE' + ActionsThatUse_SRC = 'RETRIEVE MOVE DELETE GENERATE TRANSFER' ActionsThatUse_TGT = 'UPDATE ' - Arg Parms Parms = Strip(Parms) sa= 'Parms len=' Length(Parms) - /* Parms from C1UEXT02 is a string of REXX statements */ Interpret Parms MyRc = 0 Message ='' MessageCode = ' ' - + /* Find already used/validated CCID value from Element block */ + If Wordpos(ECB_ACTION_NAME,ActionsThatUse_SRC) > 0 then, + Former_CCID = SRC_ELM_ACTION_CCID + Else, + If Wordpos(ECB_ACTION_NAME,ActionsThatUse_TGT) > 0 then, + Former_CCID = TGT_ELM_ACTION_CCID /* If CCID is left blank, then apply last used CCID */ /* otherwise if it appears to be a ServiceNow - validate */ If REQ_CCID = COPIES(' ',12) then Call Update_CCID; Else, - If Substr(REQ_CCID,1,3) = 'PRB' then Call Validate_CCID; - + If Substr(REQ_CCID,1,3) = 'PRB' |, + Substr(REQ_CCID,1,3) = 'CHG' &, + REQ_CCID /= Former_CCID Then, + Do + Message = SERVINOW('C1UEXTR2' REQ_CCID ECB_TSO_BATCH_MODE) + If POS('**NOT**', Message) > 0 then, + Do + MessageCode = 'U012' + MyRc = 8 + End; /* If POS('**NOT**', Message) > 0 */ + End; /* If Substr(REQ_CCID,1,3) = 'PRB' ... 'CHG' */ /* If COMMENT is left blank, then apply last used COMMENT */ If MyRc < 8 &, REQ_COMMENT = COPIES(' ',40) then Call Update_COMMENT; - sa= 'MyRc =' MyRc - /* Did user specify OVERRIDE SIGNOUT ? */ If MyRc = 0 & REQ_SISO_INDICATOR = 'Y' then Do Message = 'Remember that you have set OVERRIDE SIGNOUT' MyRc = 4 End - If MyRc = 0 then Exit - If Message /= '' then, Do hexAddress = D2X(Address_ECB_MESSAGE_TEXT) @@ -68,109 +72,37 @@ hexAddress = D2X(Address_ECB_MESSAGE_LENGTH) storrep = STORAGE(hexAddress,,'0084'X) End - If MessageCode /= ' ' then, Do hexAddress = D2X(Address_ECB_MESSAGE_CODE) storrep = STORAGE(hexAddress,,MessageCode) End - /* Tell Endevor something changed or something failed */ hexAddress = D2X(Address_ECB_RETURN_CODE) If MyRc = 4 then, storrep = STORAGE(hexAddress,,'00000004'X) Else, storrep = STORAGE(hexAddress,,'00000008'X) - Exit - Update_CCID: - - If Wordpos(ECB_ACTION_NAME,ActionsThatUse_SRC) > 0 then, - Replace_CCID = SRC_ELM_ACTION_CCID - Else, - If Wordpos(ECB_ACTION_NAME,ActionsThatUse_TGT) > 0 then, - Replace_CCID = TGT_ELM_ACTION_CCID - /* Still missing a CCID? */ - If Substr(Replace_CCID,1,1) < 'a' then, + If Substr(Former_CCID,1,1) < 'a' then, Do MyRc = 8 Message = '** A CCID value is required **' MessageCode = 'U012' Return; End - hexAddress = D2X(Address_REQ_CCID) - storrep = STORAGE(hexAddress,,Replace_CCID) + storrep = STORAGE(hexAddress,,Former_CCID) MyRc = 4 - - Return; - -Validate_CCID: - - /* build STDENV input */ - CALL BPXWDYN , - "ALLOC DD(STDENV) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", - " RECFM(F,B) TRACKS ", - " NEW UNCATALOG REUSE "; - Queue "EXPORT PATH=$PATH:" ||, - "'/usr/lpp/IBM/cyp/v3r11/pyz/lib/python3.11/'" - Queue "EXPORT VIRTUAL_ENV=" ||, - "'/u/users/NDVRTeam/venv/lib/python3.11/site-packages/'" - "EXECIO 2 DISKW STDENV (finis" - - /* build BPXBATCH inputs and outputs */ - /* build STDPARM input */ - CALL BPXWDYN , - "ALLOC DD(STDPARM) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", - " RECFM(F,B) TRACKS ", - " NEW UNCATALOG REUSE "; - Queue "sh cd " ||, - "/u/users/NDVRTeam/venv/lib/python3.11/site-packages;" - Queue "python ServiceNow.py" REQ_CCID - "EXECIO 2 DISKW STDPARM (finis" - - CALL BPXWDYN , - "ALLOC DD(STDOUT) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", - " RECFM(F,B) TRACKS ", - " NEW UNCATALOG REUSE "; - Notnow =, - "ALLOC DD(STDOUT) DA('WALJO11.STDOUT') OLD REUSE " - - CALL BPXWDYN "ALLOC DD(STDIN) DUMMY SHR REUSE" - CALL BPXWDYN "ALLOC DD(STDERR) DA(*) SHR REUSE" - - ADDRESS LINK 'BPXBATCH' - - "EXECIO * DISKR STDOUT (Stem stdout. finis" - lastrec# = stdout.0 - lastrecord = Substr(stdout.lastrec#,1,40) - - If Pos("Exists",lastrecord) = 0 then, - Do - Message = 'C1UEXTR2 - CCID ' REQ_CCID ||, - ' is not defined to Service-Now' - MessageCode = 'U012' - MyRc = 8 - End - - CALL BPXWDYN "FREE DD(STDENV) " - CALL BPXWDYN "FREE DD(STDPARM)" - CALL BPXWDYN "FREE DD(STDOUT) " - CALL BPXWDYN "FREE DD(STDIN) " - CALL BPXWDYN "FREE DD(STDERR) " - Return; - Update_COMMENT: - If Wordpos(ECB_ACTION_NAME,ActionsThatUse_SRC) > 0 then, Replace_COMMENT = SRC_ELM_LEVEL_COMMENT Else, If Wordpos(ECB_ACTION_NAME,ActionsThatUse_TGT) > 0 then, Replace_COMMENT = TGT_ELM_LEVEL_COMMENT - If Substr(Replace_COMMENT,1,1) < 'a' then, Do MyRc = 8 @@ -178,10 +110,7 @@ Update_COMMENT: MessageCode = 'U011' Return; End - hexAddress = D2X(Address_REQ_COMMENT) storrep = STORAGE(hexAddress,,Replace_COMMENT) MyRc = 4 - Return; - diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTR7.rex b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTR7.rex new file mode 100644 index 0000000..5ced79e --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTR7.rex @@ -0,0 +1,264 @@ +/* rexx */ + /* Make CAST actions always be batch... */ + /* Values to be set for your site...... */ + /* Build a JCL model, and name its location here.... */ + CastPackageModel = 'your.ndvrhlq.SKELS(CASTPKGE)' + CastPackageModel = '' + /* Name a work dataset to be created then deleted... */ + CastPackageJCL = USERID()".C1UEXTR7.SUBMIT" + /* If wanting to limit the use of this exit, uncomment... */ +/* If USERID() /= 'IBMUSER' then exit */ + STRING = "ALLOC DD(SYSTSPRT) SYSOUT(A) " + CALL BPXWDYN STRING; + STRING = "ALLOC DD(SYSTSIN) DUMMY" + CALL BPXWDYN STRING; + /* If C1UEXTR7 is allocated to anything, turn on Trace */ + WhatDDName = 'C1UEXTR7' + CALL BPXWDYN "INFO FI("WhatDDName")", + "INRTDSN(DSNVAR) INRDSNT(myDSNT)" + if RESULT = 0 then Trace ?r + Sa= 'You called C1UEXTR7 ' + Message = '' + MessageCode = ' ' + /* Values to be set for your site...... */ + /* For package REVIEW (APPROVE/DENY)..... */ + /* Enter location of Approver Group sequencing ... */ + ApproverGroupSequence= 'your.ndvrhlq.PARMLIB(APPROVER)' + ApproverGroupSequence= '' + /* Do you want all CAST actions to be peformed in Batch? */ + Force_CAST_in_Batch = 'Y' ; /* Y/N */ + Force_CAST_in_Batch = 'N' ; /* Y/N */ + Cast_with_SonarQube= 'N' /* Y/N/?=Check Notes and pkg content*/ + Cast_with_SonarQube= 'Y' /* Y/N/?=Check Notes and pkg content*/ + Arg Parms + sa= 'Parms len=' Length(Parms) + MyRc = 0 + /* Parms from C1UEXT07 is a string of REXX statements */ + Interpret Parms + If Substr(PHDR_PKG_NOTE5,1,5) = 'TRACE' then TraceRc = 1 + /* Validate Package prefix with ServiceNow */ + If PECB_FUNCTION_LITERAL ='CREATE' &, + PECB_BEF_AFTER_LITERAL ='BEFORE' &, + (Substr(PECB_PACKAGE_ID,1,3) = 'PRB' |, + Substr(PECB_PACKAGE_ID,1,3) = 'CHG' ) then, + Do + PackageSnowRef = Substr(PECB_PACKAGE_ID,1,10) + Message = SERVINOW('C1UEXTR7' PackageSnowRef PECB-MODE ) + If POS('**NOT**', Message) > 0 then, + Do + MyRc = 8 + Call SetExitReturnInfo + Exit + End; /* If POS('**NOT**', Message) > 0 */ + End; /* If PECB_FUNCTION_LITERAL ='CREATE' ... */ + /* Is package ready to be automatically Executed..... */ + IF PHDR_PACKAGE_STATUS = 'APPROVED' &, + PECB_BEF_AFTER_LITERAL = 'AFTER' &, + (PECB_FUNCTION_LITERAL = 'CAST' |, + PECB_FUNCTION_LITERAL = 'REVIEW') Then, + Do + PKGEXECT_Parm = Copies(' ',055) + PKGEXECT_Parm = Overlay(PECB_PACKAGE_ID ,PKGEXECT_Parm,001) + PKGEXECT_Parm = Overlay(PHDR_PKG_ENV ,PKGEXECT_Parm,018) + PKGEXECT_Parm = Overlay(PHDR_PKG_STGID ,PKGEXECT_Parm,026) + PKGEXECT_Parm = Overlay(REXX_EXEC_MODE ,PKGEXECT_Parm,028) + PKGEXECT_Parm = Overlay(PHDR_PKG_CREATE_USER,PKGEXECT_Parm,029) + PKGEXECT_Parm = Overlay(PHDR_PKG_UPDATE_USER,PKGEXECT_Parm,037) + PKGEXECT_Parm = Overlay(PHDR_PKG_CAST_USER ,PKGEXECT_Parm,045) + Call PKGEXECT PKGEXECT_Parm + Exit + End + /* Is package ready to be CAST in batch ............. */ + /* Does PACKAGE builder indicate the package has COBOL ? */ + thisPackageHasCobol = 'N' + If Substr(PREQ_PACKAGE_COMMENT,47,4) = '+COB' then, + thisPackageHasCobol = 'Y' + If Cast_with_SonarQube= 'Y' & thisPackageHasCobol = 'Y' then, + Do + /* Does user want to BYPASS SonarQube for this package ? */ + AllNotes = , + PHDR_PKG_NOTE1 || PHDR_PKG_NOTE2 || PHDR_PKG_NOTE3 ||, + PHDR_PKG_NOTE4 || PHDR_PKG_NOTE5 || PHDR_PKG_NOTE6 ||, + PHDR_PKG_NOTE7 || PHDR_PKG_NOTE8 + If Pos('BYPASS SONARQUBE',AllNotes) > 0 then, + Cast_with_SonarQube= 'N' + End + /* If Going to interface with SonarQube, do CAST in Batch */ + /* if foreground, re-Submit in Batch */ + IF Cast_with_SonarQube= 'Y' &, + thisPackageHasCobol= 'Y' &, + PECB_FUNCTION_LITERAL = 'CAST' &, + PECB_BEF_AFTER_LITERAL = 'BEFORE' &, + PECB_MODE = "T" then, /* TSO foreground */ + Do + Call SubmitBatchCAST + Exit + End + /* If Going to interface with SonarQube, do CAST in Batch */ + /* if Batch, engage the interface with SonarQube */ + IF Cast_with_SonarQube= 'Y' &, + thisPackageHasCobol= 'Y' &, + PECB_FUNCTION_LITERAL = 'CAST' &, + PECB_BEF_AFTER_LITERAL = 'BEFORE' &, + PECB_MODE = "B" then, /* TSO foreground */ + Do + Message = SONRQUBE(PECB_PACKAGE_ID) + If Message /= '' then, + Do + MyRc = 8 + Call SetExitReturnInfo + End + Exit + End + EXIT + If Substr(PHDR_PKG_NOTE5,1,5) = 'TRACE' then TraceRc = 1 + IF PHDR_PACKAGE_STATUS = 'APPROVED' &, + PECB_BEF_AFTER_LITERAL = 'AFTER' &, + (PECB_FUNCTION_LITERAL = 'CAST' |, + PECB_FUNCTION_LITERAL = 'REVIEW') Then, + Do + PKGEXECT_Parm = Copies(' ',055) + PKGEXECT_Parm = Overlay(PECB_PACKAGE_ID ,PKGEXECT_Parm,001) + PKGEXECT_Parm = Overlay(PHDR_PKG_ENV ,PKGEXECT_Parm,018) + PKGEXECT_Parm = Overlay(PHDR_PKG_STGID ,PKGEXECT_Parm,026) + PKGEXECT_Parm = Overlay(REXX_EXEC_MODE ,PKGEXECT_Parm,028) + PKGEXECT_Parm = Overlay(PHDR_PKG_CREATE_USER,PKGEXECT_Parm,029) + PKGEXECT_Parm = Overlay(PHDR_PKG_UPDATE_USER,PKGEXECT_Parm,037) + PKGEXECT_Parm = Overlay(PHDR_PKG_CAST_USER ,PKGEXECT_Parm,045) + Call PKGEXECT PKGEXECT_Parm + Exit + End + /* Enforce packages to be Backout Enabled */ + IF PREQ_BACKOUT_ENABLED /= 'Y' then, + Do + Message = 'Package made to be Backout enabled' + MyRc = 4 + hexAddress = D2X(Address_PREQ_BACKOUT_ENABLED) + storrep = STORAGE(hexAddress,,'Y') + Call SetExitReturnInfo + End; + Exit +SubmitBatchCAST: + /* Preparing to CAST The package... */ + If PREQ_PKG_CAST_COMPVAL = 'Y' then, + CastOption = ' OPTION VALIDATE COMPONENTS' + Else, + If PREQ_PKG_CAST_COMPVAL = 'W' then, + CastOption = ' OPTION VALIDATE COMPONENT WITH WARNING' + Else, + CastOption = ' OPTION DO NOT VALIDATE COMPONENT' + /* Variable settings for each site ---> */ + WhereIam = WHERE@M1() + interpret 'Call' WhereIam "'MyDATALibrary'" + MyDATALibrary = Result + interpret 'Call' WhereIam "'MySEN2Library'" + MySEN2Library = Result + interpret 'Call' WhereIam "'MySENULibrary'" + MySENULibrary = Result + interpret 'Call' WhereIam "'AltIDAcctCode'" + AltIDAcctCode = Result + interpret 'Call' WhereIam "'MySENULibrary'" + MySENULibrary = Result + interpret 'Call' WhereIam "'AltIDJobClass'" + AltIDJobClass = Result + /* <---- Variable settings for each site */ + Sa= 'Running C1UEXTR7 ' + /* Allocate and prepare files for ENBPIU00 execution */ + /* OPTIONS will contain date and time values */ + /* */ + STRING = "ALLOC DD(OPTIONS) LRECL(80) BLKSIZE(27920) ", + " DSORG(PS) ", + " SPACE(1,1) RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + CALL BPXWDYN STRING; + QUEUE " $nomessages = 'Y' " ; + QUEUE " Package = '"PECB_PACKAGE_ID"'" ; + QUEUE " Userid = '"USERID()"'" ; + QUEUE " Userjob = '"USERID()|| SUBSTR(Package,1,1)"'" + QUEUE " AltIDAcctCode = '"AltIDAcctCode"'" + QUEUE " MySEN2Library = '"MySEN2Library"'" + QUEUE " MySENULibrary = '"MySENULibrary"'" + QUEUE " AltIDJobClass = '"AltIDJobClass"'" + QUEUE " CastOption = '"CastOption"'" + "EXECIO " QUEUED() "DISKW OPTIONS (FINIS" + /* */ + /* TABLE is simple to allow the CAST */ + /* */ + STRING = "ALLOC DD(TABLE) LRECL(80) BLKSIZE(8000) ", + " DSORG(PS) ", + " SPACE(1,1) RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + CALL BPXWDYN STRING; + QUEUE "* Do " + QUEUE " * " + "EXECIO 2 DISKW TABLE (FINIS" + STRING = 'ALLOC DD(MODEL) ', + "DA('"MySEN2Library"(CASTPKGE)') SHR REUSE " + CALL BPXWDYN STRING; + /* TBLOUT is assigned to a temporary dataset to receive the jcl */ + /* */ + STRING = "ALLOC DD(TBLOUT) LRECL(80) BLKSIZE(27920) ", + " DA("CastPackageJCL") ", + " DSORG(PS) ", + " SPACE(1,1) RECFM(F,B) TRACKS ", + " NEW CATALOG REUSE "; + CALL BPXWDYN STRING; + /* */ + /* Now call ENBPIU00 which does the rest */ + /* */ + "ENBPIU00 M 1 " + "EXECIO 0 DISKW TBLOUT (FINIS" + CALL BPXWDYN "FREE DD(OPTIONS)" ; + CALL BPXWDYN "FREE DD(TABLE)" ; + CALL BPXWDYN "FREE DD(MODEL)" ; + Call Submit_n_save_jobInfo ; + Message = JobData + MyRc = 8 + PACKAGE = PECB_PACKAGE_ID + MessageCode = 'U033' + Call SetExitReturnInfo + CALL BPXWDYN "FREE DD(TBLOUT) DELETE" + Return +Submit_n_save_jobInfo: /* submit CastPackageModel job and save job info */ + If TraceRc = 1 then Say 'Submit_n_save_jobInfo:' + Address TSO "PROFILE NOINTERCOM" /* turn off msg notific */ + CALL MSG "ON" + CALL OUTTRAP "out." + ADDRESS TSO "SUBMIT '"CastPackageJCL"'" ; + If RC > 4 then, + Do + MyRC = 8 + Message = 'Cannot find Element member to submit.' + Call SetExitReturnInfo + Exit(12) + End + CALL OUTTRAP "OFF" + Address TSO "PROFILE INTERCOM" /* turn on msg notific */ + JobData = Strip(out.1); + jobinfo = Word(JobData,2) ; + If jobinfo = 'JOB' then, + jobinfo = Word(JobData,3) ; + SelectJobName = Word(Translate(jobinfo,' ',')('),1) ; + SelectJobNumber = Word(Translate(jobinfo,' ',')('),2) ; + Return; +SetExitReturnInfo: + If TraceRc = 1 then Say 'SetExitReturnInfo: ' + hexAddress = D2X(Address_PECB_MESSAGE) + storrep = STORAGE(hexAddress,,Message) + hexAddress = D2X(Address_PECB_ERROR_MESS_LENGTH) + storrep = STORAGE(hexAddress,,'0084'X) + hexAddress = D2X(ADDRESS_PECB_MODS_MADE_TO_PREQ) + storrep = STORAGE(hexAddress,,'Y') + If MessageCode /= ' ' then, + Do + hexAddress = D2X(Address_PECB_MESSAGE_ID) + storrep = STORAGE(hexAddress,,MessageCode) + End +/* Set the return code for the exit */ +/* for PECB-NDVR-EXIT-RC */ + hexAddress = D2X(Address_PECB_NDVR_EXIT_RC) + If MyRc = 4 then, + storrep = STORAGE(hexAddress,,'00000004'X) + Else, + storrep = STORAGE(hexAddress,,'00000008'X) + RETURN ; diff --git a/endevor/ServiceNow-Interface/C1UEXTT7.cob b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTT7.cob similarity index 95% rename from endevor/ServiceNow-Interface/C1UEXTT7.cob rename to endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTT7.cob index 8fb2755..82e4ac6 100644 --- a/endevor/ServiceNow-Interface/C1UEXTT7.cob +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/C1UEXTT7.cob @@ -13,32 +13,23 @@ ** DATA DIVISION. FILE SECTION. - WORKING-STORAGE SECTION. - COPY NOTIFYDS. - 01 WS-VGET PIC X(8) VALUE 'VGET '. 01 WS-PROFILE PIC X(8) VALUE 'PROFILE '. 01 WS-ISPLINK PIC X(8) VALUE 'ISPLINK ' . - 01 WS-C1BJC1-JOBCARD PIC X(80) . 01 WS-C1BJC1 PIC X(08) VALUE '(C1BJC1)'. - 01 WS-C1PJC1-JOBCARD PIC X(80) . 01 WS-C1PJC1 PIC X(08) VALUE '(C1PJC1)'. - 01 WS-CALLING-REASON PIC X(24). - 01 WS-VARIABLES. 03 WS-POINTER PIC 9(09) COMP. 03 WS-WORK-ADDRESS-ADR PIC 9(09) COMP SYNC . 03 WS-WORK-ADDRESS-PTR REDEFINES WS-WORK-ADDRESS-ADR USAGE IS POINTER . - 03 WS-PECB-REQUEST-RETURNCODE PIC 9999 . 03 WS-PECB-NDVR-HIGH-RC PIC 9999 . - 03 WS-DISPLAY-NUMBER-FOR4 PIC 9(04) . 03 WS-DISPLAY-NUMBER-FOR9 PIC 9(09) . 00490200 @@ -57,7 +48,6 @@ OCCURS 320 . 03 FILLER PIC X(8). 01 MYSMTP-EMAIL-ID-SIZE PIC 9(8). - 01 WS-ADDRESSES. 03 ADDRESS-MYSMTP-MESSAGE PIC 9(09) . 03 ADDRESS-MYSMTP-USERID PIC 9(09) . @@ -74,15 +64,12 @@ 03 ADDRESS-PECB-MODS-MADE-TO-PREQ PIC 9(09) . 03 ADDRESS-PREQ-SHARE-ENABLED PIC 9(09) . 03 ADDRESS-PREQ-BACKOUT-ENABLED PIC 9(09) . - 01 BPXWDYN PIC X(8) VALUE 'BPXWDYN'. 01 ALLOC-STRING. 05 ALLOC-LENGTH PIC S9(4) BINARY VALUE 100. 05 ALLOC-TEXT PIC X(100). - 01 IRXJCL PIC X(6) VALUE 'IRXJCL'. 01 IRXEXEC-PGM PIC X(08) VALUE 'IRXEXEC'. - * * DEFINE THE IRXEXEC DATA AREAS AND ARG BLOCKS * @@ -99,7 +86,6 @@ 77 ARGTABLE-PTR POINTER. 77 EVALBLK-PTR POINTER. 77 TEMP-PTR POINTER. - 01 EXECBLK. 05 EXECBLK-ACRYN PIC X(08) VALUE 'IRXEXECB'. 05 EXECBLK-LENGTH PIC S9(8) BINARY @@ -112,7 +98,6 @@ 05 EXECBLK-DSNPTR POINTER VALUE NULL. 05 EXECBLK-DSNLEN PIC 9(04) COMP VALUE 0. - 01 EVALBLK. 05 EVALBLK-EVPAD1 PIC S9(8) BINARY VALUE 0. @@ -123,7 +108,6 @@ 05 EVALBLK-EVPAD2 PIC S9(8) BINARY VALUE 0. 05 EVALBLK-EVDATA PIC X(256). - 01 ARGUMENT. 02 ARGUMENT-1 OCCURS 1 TIMES. 05 ARGSTRING-PTR POINTER. @@ -132,7 +116,6 @@ VALUE -1. 02 ARGSTRING-LAST2 PIC S9(8) BINARY VALUE -1. - * The block of data below can be used with either an * IRXJCL or IRXEXEC call to the rexx program C1UEXTR7. * IRXJCL is used when running in batch (batch CAST) . @@ -144,10 +127,8 @@ 03 FILLER PIC X(1) VALUE SPACE . 02 PKG-C1UEXTR7-PARMS-IRXEXEC. 03 WS-REXX-STATEMENTS PIC X(3000). - LINKAGE SECTION. COPY PKGXBLKS. - PROCEDURE DIVISION USING PACKAGE-EXIT-BLOCK PACKAGE-REQUEST-BLOCK @@ -159,15 +140,13 @@ PACKAGE-EXIT-SHIPMENT-BLOCK PACKAGE-EXIT-SCL-BLOCK. **** - IF PECB-USER-BATCH-JOBNAME(1:7) NOT = 'WALJO11' AND - PECB-USER-BATCH-JOBNAME(1:7) NOT = 'PL05958' - GOBACK. + **** IF PECB-USER-BATCH-JOBNAME(1:7) NOT = 'IBMUSER' AND + **** PECB-USER-BATCH-JOBNAME(1:7) NOT = 'PL05958' + **** GOBACK. **** - ********* DISPLAY 'C1UEXT07: GOT INTO C1UEXTT7'. ********* MOVE PECB-FUNCTION-CODE TO WS-DISPLAY-NUMBER-FOR9. ********* DISPLAY 'PECB-FUNCTION-CODE=' WS-DISPLAY-NUMBER-FOR9. - IF SETUP-EXIT-OPTIONS MOVE ZERO TO PECB-UEXIT-HOLD-FIELD ********* to enforce package create rules @@ -176,22 +155,27 @@ MOVE 'Y' TO PECB-BEFORE-CREATE-EDIT MOVE 'Y' TO PECB-BEFORE-CREATE-IMPT MOVE 'Y' TO PECB-BEFORE-REV-APPR -********* to enforce Approver Group Sequencing - MOVE 'Y' TO PECB-AFTER-REV-APPR ********* to enforce package backout = Y MOVE 'Y' TO PECB-BEFORE-CAST ********* to enforce Approver Group Sequencing + MOVE 'Y' TO PECB-AFTER-REV-APPR MOVE 'Y' TO PECB-AFTER-CAST -********* MOVE 'Y' TO PECB-MID-CAST + MOVE 'Y' TO PECB-MID-CAST ********* MOVE 'Y' TO PECB-BEFORE-MOD-IMPT ********* MOVE 'Y' TO PECB-AFTER-RESET ********* MOVE 'Y' TO PECB-AFTER-DELETE +********* to support automated package shipping + MOVE 'Y' TO PECB-AFTER-EXEC + MOVE 'Y' TO PECB-REQ-ELEMENT-ACTION-BIBO + MOVE 'Y' TO PECB-AFTER-BACKOUT + MOVE 'Y' TO PECB-AFTER-BACKIN +********* to support submission of package Execute jobs +**done*** MOVE 'Y' TO PECB-AFTER-REV-APPR +**done*** MOVE 'Y' TO PECB-AFTER-CAST MOVE ZEROS TO RETURN-CODE GOBACK. - MOVE 0 TO PECB-NDVR-EXIT-RC. MOVE SPACES TO WS-REXX-STATEMENTS . - ********* If just starting out, request Approver Group info IF PECB-REQUEST-RETURNCODE = 0 AND PECB-AFTER AND (CAST-PACKAGE OR REVIEW-PACKAGE) @@ -199,20 +183,6 @@ MOVE 'Y' TO PECB-REQ-APPROVER-REC GOBACK ELSE -********* If Before the CAST, just pass Package info to the REXX - IF PECB-BEFORE AND - (CREATE-PACKAGE OR CAST-PACKAGE) - IF CREATE-PACKAGE - MOVE 'Before CREATE' TO WS-CALLING-REASON - ELSE - MOVE 'Before CAST' TO WS-CALLING-REASON - END-IF - PERFORM 1000-ALLOCATE-REXFILE - PERFORM 0500-CALL-C1UEXTR7-REXX - PERFORM 2000-FREE-REXFILES - GOBACK - END-IF . - ********* If we just received an Appprover Group block, ********* pass it to the REXX and ask for more... IF PECB-SUCCESSFUL-RECORD-SENT @@ -226,8 +196,7 @@ PERFORM 0500-CALL-C1UEXTR7-REXX MOVE 'Y' TO PECB-REQ-APPROVER-REC GOBACK - END-IF . - + ELSE ********* Endevor says 'no more Appprover Group blocks' ********* tell REXX and let it decide on email IF PECB-END-OF-FILE-FOR-REC-TYP OR @@ -242,49 +211,49 @@ END-IF PERFORM 2000-FREE-REXFILES GOBACK - END-IF . - - + ELSE +********* If Before the CAST, just pass Package info to the REXX + IF (PECB-BEFORE OR PECB-MID) AND + (CREATE-PACKAGE OR CAST-PACKAGE) + IF CREATE-PACKAGE + MOVE 'Before CREATE' TO WS-CALLING-REASON + ELSE + MOVE 'Before CAST' TO WS-CALLING-REASON + END-IF. +********* For many conditions, call REXX and let it decide what to do + PERFORM 1000-ALLOCATE-REXFILE. + PERFORM 0500-CALL-C1UEXTR7-REXX. + PERFORM 2000-FREE-REXFILES. 0100-MAIN-EXIT. GOBACK. - 0500-CALL-C1UEXTR7-REXX. - * Give addresses of updatable fields to the REXX. * MAKES A CALL TO THE REXX ROUTINE C1UEXTR7. - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF MYSMTP-MESSAGE . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-MYSMTP-MESSAGE. - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF MYSMTP-USERID . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-MYSMTP-USERID . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF MYSMTP-FROM . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-MYSMTP-FROM . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF MYSMTP-SUBJECT . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-MYSMTP-SUBJECT. - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF MYSMTP-TEXT . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-MYSMTP-TEXT . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF MYSMTP-URL . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-MYSMTP-URL . - MOVE SPACES TO MYSMTP-EMAIL-IDS . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF MYSMTP-EMAIL-IDS . MOVE WS-WORK-ADDRESS-ADR @@ -294,55 +263,43 @@ COMPUTE MYSMTP-EMAIL-ID-SIZE = WS-WORK-ADDRESS-ADR - 4 - ADDRESS-MYSMTP-EMAIL-IDS . - - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF PECB-NDVR-EXIT-RC . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-PECB-NDVR-EXIT-RC. - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF PECB-MESSAGE . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-PECB-MESSAGE . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF PECB-ERROR-MESS-LENGTH . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-PECB-ERROR-MESS-LENGTH. - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF PECB-MODS-MADE-TO-PREQ . MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-PECB-MODS-MADE-TO-PREQ. - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF PECB-MESSAGE-ID. MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-PECB-MESSAGE-ID . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF PREQ-SHARE-ENABLED. MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-PREQ-SHARE-ENABLED . - SET WS-WORK-ADDRESS-PTR TO ADDRESS OF PREQ-BACKOUT-ENABLED. MOVE WS-WORK-ADDRESS-ADR TO ADDRESS-PREQ-BACKOUT-ENABLED . - MOVE PECB-REQUEST-RETURNCODE TO WS-PECB-REQUEST-RETURNCODE. - MOVE PECB-NDVR-HIGH-RC TO WS-PECB-NDVR-HIGH-RC . - ***** ***** / Convert COBOL exit block Datanames into Rexx \ ***** ***** MOVE 1 TO WS-POINTER. - STRING 'PECB_PACKAGE_ID = "' PECB-PACKAGE-ID '";' 'PECB_FUNCTION_LITERAL="' PECB-FUNCTION-LITERAL '";' @@ -355,6 +312,9 @@ 'PHDR_PKG_STGID ="' PHDR-PKG-STGID '";' 'PECB_MODE = "' PECB-MODE '";' 'PECB_AUTOCAST ="' PECB-AUTOCAST '";' + 'PECB_ACT_REC_EXIST_FLAG="' PECB-ACT-REC-EXIST-FLAG '";' + 'PECB_APP_REC_EXIST_FLAG="' PECB-APP-REC-EXIST-FLAG '";' + 'PECB_BAC_REC_EXIST_FLAG="' PECB-BAC-REC-EXIST-FLAG '";' 'PECB_REQUEST_RETURNCODE=' WS-PECB-REQUEST-RETURNCODE ';' 'PECB_NDVR_HIGH_RC = ' WS-PECB-NDVR-HIGH-RC ';' 'PREQ_BACKOUT_ENABLED="' PREQ-BACKOUT-ENABLED '";' @@ -384,16 +344,15 @@ DELIMITED BY SIZE INTO WS-REXX-STATEMENTS WITH POINTER WS-POINTER . - ********* For these text fields, make sure none use a double quote ********* character. This ensures the integrity of the REXX - IF REVIEW-PACKAGE OR - (CAST-PACKAGE AND PECB-AFTER) + IF PAPP-QUORUM-COUNT > 0 AND + (REVIEW-PACKAGE OR + (CAST-PACKAGE AND PECB-AFTER) ) MOVE PAPP-QUORUM-COUNT TO WS-DISPLAY-NUMBER-FOR4 STRING 'CALL_REASON="' WS-CALLING-REASON '";' 'PAPP_GROUP_NAME ="' PAPP-GROUP-NAME '";' - 'PAPP_GROUP_NAME ="' PAPP-GROUP-NAME '";' 'PAPP_ENVIRONMENT="' PAPP-ENVIRONMENT '";' 'PAPP_QUORUM_COUNT="' WS-DISPLAY-NUMBER-FOR4 '";' 'PAPP_APPROVER_FLAG="' PAPP-APPROVER-FLAG '";' @@ -419,7 +378,6 @@ INTO WS-REXX-STATEMENTS WITH POINTER WS-POINTER END-STRING - PERFORM VARYING WS-INX FROM 1 BY 1 UNTIL WS-INX GREATER THAN PAPP-APPROVER-NUMBER STRING PAPP-APPROVAL-FLAG(WS-INX) ' ' @@ -434,9 +392,8 @@ WITH POINTER WS-POINTER END-STRING END-IF. - ******* Replace any double quote characters in data to be passed - IF CAST-PACKAGE + IF CAST-PACKAGE OR REVIEW-PACKAGE INSPECT PREQ-PACKAGE-COMMENT REPLACING ALL '"' BY X'7D' INSPECT PHDR-PKG-NOTE1 REPLACING ALL '"' BY X'7D' INSPECT PHDR-PKG-NOTE2 REPLACING ALL '"' BY X'7D' @@ -468,13 +425,10 @@ WITH POINTER WS-POINTER END-STRING END-IF. - ***** \ Convert COBOL exit block Datanames into Rexx / ***** - MOVE 'C1UEXTR7' TO EXECBLK-MEMBER . MOVE 3000 TO ARGSTRING-LENGTH(1) - IF PECB-TSO-MODE CALL 'SET-ARG1-POINTER' USING ARGUMENT-PTR PKG-C1UEXTR7-PARMS-IRXEXEC @@ -483,12 +437,10 @@ ELSE ********* DISPLAY 'C1UEXT07: Running in Batch ' CALL IRXJCL USING PKG-C1UEXTR7-PARMS-IRXJCL . - IF RETURN-CODE NOT = 0 DISPLAY 'C1UEXT07: BAD CALL TO IRXJCL - RC = ' RETURN-CODE END-IF - MOVE 0 TO RETURN-CODE . 0800-REXX-CALL-VIA-IRXEXEC. @@ -509,7 +461,6 @@ * I.E. EXEC INVOKED AS SUBROUTINE MOVE 536870912 TO FLAGS MOVE 0 TO REXX-RETURN-CODE . - ********* DISPLAY 'C1UEXT07: CALLING IRXEXC ' ********* PECB-PACKAGE-ID . *--- CALL THE REXX EXEC --- @@ -522,24 +473,18 @@ DUMMY-ZERO DUMMY-ZERO DUMMY-ZERO . - IF REXX-RETURN-CODE NOT = 0 DISPLAY 'C1UEXT07: IRXEXEC RETURN CODE = ' REXX-RETURN-CODE END-IF - CANCEL IRXEXEC-PGM . - 0900-SEND-EMAILS. - ********** DISPLAY 'C1UEXTT7: MYSMTP-MESSAGE=' MYSMTP-MESSAGE . ********** DISPLAY 'C1UEXTT7: MYSMTP-FROM =' MYSMTP-FROM . ********** DISPLAY 'C1UEXTT7: MYSMTP-SUBJECT=' MYSMTP-SUBJECT . ********** DISPLAY 'C1UEXTT7: MYSMTP-TEXT ' MYSMTP-TEXT(1:80). - MOVE 1 TO WS-POINTER. - PERFORM UNTIL MYSMTP-EMAIL-IDS(WS-POINTER:1) = LOW-VALUES OR MYSMTP-EMAIL-IDS(WS-POINTER:8) @@ -552,7 +497,6 @@ INTO MYSMTP-USERID WITH POINTER WS-POINTER END-UNSTRING - IF MYSMTP-USERID NOT = SPACES ********** DISPLAY 'C1UEXTT7: Emailing ' MYSMTP-USERID ********** ' WS-POINTER=' WS-POINTER ' ' @@ -564,23 +508,18 @@ MYSMTP-TEXT MYSMTP-URL END-IF - IF RETURN-CODE > 0 DISPLAY 'CALL BC1PMLIF RC = ' RETURN-CODE DISPLAY MYSMTP-MESSAGE END-IF ********** ADD 1 TO WS-POINTER END-PERFORM. - *----------------------------------------------------------------- - 1000-ALLOCATE-REXFILE. - MOVE SPACES TO ALLOC-TEXT. - IF PECB-BATCH-MODE STRING 'ALLOC DD(SYSEXEC) ', - 'DA(Your.Endevor.CLSTREXX)' + 'DA(your.ndvrhlq.REXX)' DELIMITED BY SIZE ' SHR REUSE' DELIMITED BY SIZE @@ -588,61 +527,48 @@ END-STRING ELSE STRING 'ALLOC DD(REXFILE7) ', - 'DA(Your.Endevor.CLSTREXX)' + 'DA(your.ndvrhlq.REXX)' DELIMITED BY SIZE ' SHR REUSE' DELIMITED BY SIZE INTO ALLOC-TEXT END-STRING END-IF. - PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . - ********** MOVE 'CONCAT DDLIST(REXFILE,REXFILE2)' ********** TO ALLOC-TEXT . ********** ********** PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . - ***************************************************************** ** DYNAMICALLY DE-ALLOCATE UNNEEDED REXX FILES ***************************************************************** 2000-FREE-REXFILES. - MOVE SPACES TO ALLOC-TEXT. - IF PECB-BATCH-MODE MOVE 'FREE DD(SYSEXEC)' TO ALLOC-TEXT ELSE MOVE 'FREE DD(REXFILE7)' TO ALLOC-TEXT END-IF. - - PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . ***************************************************************** ** CALL BPXWDYN TO PREFORM REQUIRED REXX FUNCTIONS ***************************************************************** 9000-DYNAMIC-ALLOC-DEALLOC. - CALL BPXWDYN USING ALLOC-STRING - IF RETURN-CODE NOT = ZERO DISPLAY 'C1UEXT07: ALLOCATION FAILED: RETURN CODE = ' RETURN-CODE DISPLAY ALLOC-TEXT END-IF - ********* DISPLAY ALLOC-TEXT . MOVE SPACES TO ALLOC-TEXT . - - ****************************************************************** * BEGIN NESTED PROGRAMS USED TO SET THE POINTERS OF DATA AREAS * THAT ARE BEING PASSED TO IRXEXEC SO THAT A REXX ROUTINE CAN * PASS DATA (OTHER THAN A RETURN CODE) BACK TO A COBOL PROGRAM. ****************************************************************** - ******** SET-ARG1-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-ARG1-POINTER. @@ -657,7 +583,6 @@ SET ARG-PTR TO ADDRESS OF ARG1 GOBACK. END PROGRAM SET-ARG1-POINTER. - ******** SET-ARGUMENT-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-ARGUMENT-POINTER. @@ -677,7 +602,6 @@ SET ARGTABLE-PTR TO ADDRESS OF ARGUMENT GOBACK. END PROGRAM SET-ARGUMENT-POINTER. - ******** SET-EXECBLK-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-EXECBLK-POINTER. @@ -700,7 +624,6 @@ SET EXECBLK-PTR TO ADDRESS OF EXECBLK GOBACK. END PROGRAM SET-EXECBLK-POINTER. - ******** SET-EVALBLK-POINTER ******** IDENTIFICATION DIVISION. PROGRAM-ID. SET-EVALBLK-POINTER. diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/CHECK_ITSM_ID go b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/CHECK_ITSM_ID go new file mode 100644 index 0000000..f7929cc --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/CHECK_ITSM_ID go @@ -0,0 +1,259 @@ +package main + +import ( + "crypto/tls" + "crypto/x509" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "strings" +) + +const ( + Certificate_Path = "/u/users/ibmuser/certificates/service-now-com-chain.pem" + ServicenowURI = "https://yournode.service-now.com" + Oauth_url = "/oauth_token.do" + IncidentPath = "/api/now/table/incident" + ChangeRequestPath = "/api/now/table/change_request" + queryParms = "?sysparm_display_value=true&sysparm_query=number=" + grant_type = "grant_type=password" + client_id = "client_id=your-client-id-name" + client_secret = "client_secret=your-secret" + username = "username=admin" + password = "password=your-password" + contentType = "application/x-www-form-urlencoded" + + Jira_Certificate_Path = "/u/users/ibmuser/certificates/atlassian-net-chain.pem" + Jira_URI = "https://yourname.atlassian.net" + JiraIssuePath = "/rest/api/3/issue/" + JiraUserID = "emailAddress@yoursite.com" + JiraAccessToken = "111111111111111111111111111111111111111111111111222222222222222222222222222222222222222222222222" + + "33333333333333333333333333333333333333333333333344444444444444444444444444444444444444444444444" +) + +type ServiceNow_Token struct { + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + Scope string `json:"scope"` + TokenType string `json:"token_type"` + ExpiresIn int `json:"expires_in"` +} + +//*************************************************************************************************************************************** +// Function validate_ServiceNow : +// +// Returns TRUE if the SnowObj ID exists in the Jira Instance at resource resource_uri, Otherwise FALSE +// +//*************************************************************************************************************************************** +func validate_ServiceNow(resource_uri, SnowObj string) bool { + + //**************************************************************** + //READ Certificates from File for TLS connection + //**************************************************************** + + caCert, err := os.ReadFile(Certificate_Path) + if err != nil { + log.Fatal(err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + client := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: caCertPool, + }, + }, + } + + + //**************************************************************** + // Get OAuth Token + //**************************************************************** + + payload := strings.NewReader(grant_type + "&" + + client_id + "&" + + client_secret + "&" + + username + "&" + + password) + + res, err := client.Post(ServicenowURI+Oauth_url, contentType, payload) + if err != nil { + fmt.Printf("Error during POST Method to get Oauth Token: %s", err) + return false + } + + body, err := io.ReadAll(res.Body) + res.Body.Close() + + if res.StatusCode > 299 { + log.Fatalf("Response failed with status code: %d and\nbody: %s\n", res.StatusCode, body) + } + + if err != nil { + log.Fatal(err) + } + + var newToken ServiceNow_Token + err = json.Unmarshal(body, &newToken) + + if err != nil { + log.Fatalf("No OAuth Token returned by ServiceNow Instance: %s.", ServicenowURI) + log.Fatal(err) + } + + //**************************************************************** + // Validate existance of the Snow Object using OAuth Token + //**************************************************************** + + req, _ := http.NewRequest("GET", ServicenowURI+resource_uri, nil) + + req.Header.Add("Accept", "application/json") + req.Header.Add("Authorization", "Bearer "+newToken.AccessToken) + + res, err = client.Do(req) + + if err != nil { + fmt.Println("HTTP call failed:", err) + return false + } + + defer res.Body.Close() + body, _ = io.ReadAll(res.Body) + + var jsonData map[string]interface{} + err = json.Unmarshal(body, &jsonData) + + if err != nil { + fmt.Printf("Error unmarshalling JSON: %v", err) + return false + } + + dataArray, ok := jsonData["result"].([]interface{}) + if !ok { + fmt.Println("Expected 'result' to be an array") + return false + } + if len(dataArray) == 0 { + fmt.Printf("ServiceNow object %s is not defined at %s.\n", SnowObj, ServicenowURI) + return false + } else { + fmt.Printf("ServiceNow object %s has been found in ServiceNow instance at %s.\n", SnowObj, ServicenowURI) + return true + } + +} + +//*************************************************************************************************************************************** +// Function validate_Jira : +// +// Returns TRUE if the JiraObj ID exists in Jira Instance at resource_uri, Otherwise FALSE +// +//*************************************************************************************************************************************** +func validate_Jira(resource_uri, JiraObj string) bool { + + //**************************************************************** + // READ Certificates from File for TLS connection + //**************************************************************** + + caCert, err := os.ReadFile(Jira_Certificate_Path) + if err != nil { + log.Fatal(err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + client := &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: caCertPool, + }, + }, + } + + //**************************************************************** + // GET Jira ITSM Object ID + //**************************************************************** + + req, _ := http.NewRequest("GET", Jira_URI+resource_uri, nil) + req.SetBasicAuth(JiraUserID, JiraAccessToken) + //req.Header.Add("Authorization", "Basic "+JiraAccessToken) + res, err := client.Do(req) + + if err != nil { + fmt.Println("HTTP call failed:", err) + return false + } + + defer res.Body.Close() + body, _ := io.ReadAll(res.Body) + + + switch HTTP_Code := res.StatusCode; { + + case HTTP_Code == http.StatusNotFound: + fmt.Printf("Jira object %s is not defined at %s.\n", JiraObj, Jira_URI) + return false + + case HTTP_Code == http.StatusOK: + fmt.Printf("Jira object %s has been found at %s.\n", JiraObj, Jira_URI) + return true + + default: + fmt.Printf("Response from Jira failed with status code: %d and\nbody: %s\n", res.StatusCode, body) + return false + } +} + +func main() { + + //**************************************************************** + // Get Parameters from caller + //**************************************************************** + var ObjID string + + if len(os.Args) > 1 { + ObjID = os.Args[1] + } else { + fmt.Printf("No parameter has been passed to this program\n") + os.Exit(8) + } + + var requestURI string + + switch SnowObjType := ObjID[0:3]; SnowObjType { + + case "INC": + requestURI = IncidentPath + queryParms + ObjID + if validate_ServiceNow(requestURI, ObjID) { + os.Exit(0) + } else { + os.Exit(8) + } + + case "CHG": + requestURI = ChangeRequestPath + queryParms + ObjID + if validate_ServiceNow(requestURI, ObjID) { + os.Exit(0) + } else { + os.Exit(8) + } + + default: + if ObjID[0:2] == "EI" { + requestURI = JiraIssuePath + ObjID[0:2] + "-" + ObjID[2:] + if validate_Jira(requestURI, ObjID) { + os.Exit(0) + } else { + os.Exit(8) + } + } else { + fmt.Printf("ITSM Tool Object ID is not controlled: %s.\n", SnowObjType) + os.Exit(8) + } + } + +} diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/README.md b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/README.md new file mode 100644 index 0000000..07ff5da --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/README.md @@ -0,0 +1,50 @@ +# ServiceNow interface to Endevor + +## Overview +Items in this folder are example Endevor objects for interfacing with ServiceNow. This interface assumes that the manual activity that triggers automated actions begins in Endevor, Quick-Edit, Code4Z or zowe. + +Processing starts with an Endevor action, such as an element Generate or a package create. Endevor calls one of the COBOL exits. The COBOL exit collects Endevor exit block information and passes it to a REXX subroutine. Rexx then calls the python code or GoLang code to query ServiceNow. The results of the query return as a JSON string, visible to both the Python or GoLang and REXX. + +Details for Endevor Exit actions can be found [here](https://techdocs.broadcom.com/us/en/ca-mainframe-software/devops/ca-endevor-software-change-manager/19-0/reference/api-and-user-exits-reference/exits-reference.html). +Note that Endevor supports "exits that are written in either assembler or in high-level languages such as COBOL". The exits provided in this folder are written in COBOL, but there is no requirement for implementers or users to have knowledge of COBOL. All processing logic for this solution is coded in the Rexx, and the Python or Golang subroutines. + +## Where to start +Python uses the "square bracket" characters, "[" and "]". On the mainframe these characters must be the hex AD and hex BD characters to run properly. + +If you have not yet loaded the Python "requests" package, make that be your first step. If you are not sure whether the "requests" package is installed, you can use this step to find out. + +If you have already installed the "request" package and it is found in the search path, then comment out the sys.path line in the python. For example: + + # Name the directory where the 'requests' are found + # sys.path.append('/usslocation/forpython/uptoNotIncludingrequests') + +Test your python or GoLang access to ServiceNow. For example, copy the Python code into a USS directory and using OMVS, issue a command like this one: + + python Servicenow.py CHG1234567 + +Resulting messages will tell you whether you have successfully connected. + +## Installing the "requests" package + +If you know that the python "request" package has not been installed, or if you receive a message indicating that it cannot be found, then execute these steps: + +- On USS issue this command: + + python -m pip install requests +- Within the python code enter the name of the uss directory that contains the "requests" folder, for example: + + sys.path.append('/usslocation/forpython/uptoNotIncludingrequests') + +## Other items in the Folder + +Other items in this folder are Endevor exit code examples that query ServiceNow. Endevor functions listed below, each use a COBOL exit, a REXX subroutine and a Python subroutine. Functions include: +- **Exit 2**. Before element action exit code to validate a CCID value with ServiceNow. +- **Exit 7**. Package exit code to validate (a portion of) a package namee with ServiceNow. +- **C1UEXTR2** and **C1UEXTR7** are Rexx subroutines to the COBOL exit programs. The C1UEXTR2 module is coded to not call the SERVINOW subroutine when the requested CCID already exists on an element. So for example, Update and MOVE actions might find the requested CCID value already on the element and bypass the validation. +- **SERVINOW** is a REXX subroutine to both C1UEXTR2 and C1UEXTR7 and is the member that calls the Python code to validate a 10-byte value with ServiceNow. + + +REXX examples contain code that allows on-demand REXX tracing to be invoked - without modifying the REXX code. The examples allow you to limit the tracing to a list of userids. You can create your own list of userids or eliminate it altogether. Then, simply allocate the name of the REXX program to DUMMY. For example, to engage the Trace for C1UEXTR2, then allocate C1UEXTR2 to DUMMY. There are two ways to do the allocation: + +- In TSO forground, enter "TSO ALLLOC F(C1UEXTR2) DUMMY" +- In batch, include a JCL line "//C1UEXTR2 DD DUMMY" diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/SERVINOW.rex b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/SERVINOW.rex new file mode 100644 index 0000000..29c256b --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/SERVINOW.rex @@ -0,0 +1,45 @@ +/* REXX */ +/* Validate the Ticket# with Service-Now */ +/* This routine can be used to validate a CCID or package */ +/* name (for example) as valid Service-Now ticket numbers. */ + isItThere = , + BPXWDYN("INFO FI(SERVINOW) INRTDSN(DSNVAR) INRDSNT(myDSNT)") + If isItThere = 0 then Trace ?r + Arg Caller Ticket# TSOorBatch . + If TSOorBatch = 'B' then say "SERVINOW - validating" Ticket# + NEWSTACK + /* Designate how many validated Ticket Numbers to remember */ + Message = Caller'/SERVINOW - Ticket Number ' Ticket# ||, + ' is defined to Service-Now' +/* Set up the variables for running Python */ + command = "sh cd /u/users/ibmuser;", + "python python/ServiceNow.py" Ticket# + stdout.0 = 0 + stderr.0 = 0 + stdin.0 = 0 + env.0 = 4 + env.1 = "PATH=" || , + "/usr/lpp/IBM/cyp/pyz/bin/:" || , + "/bin:/usslocation/usr/lpp/java/J8.0_64/bin:" || , + "/usr/lpp/IBM/cyp/v3r9/pyz/bin:" || , + "/usr/lpp/IBM/zoautil/bin:" || , + "/usr/lpp/IBM/zoautil/env/bin:" || , + "/u/users/cai/moi/v2001/s1801/bin:/u/users/nodejs/nodejs/bin:" + env.2 = "LIBPATH=" || , + "/lib:" || , + "/usr/lib:" || , + "/usslocation/usr/lpp/java/J8.0_64/include:" || , + "/usr/lpp/IBM/cyp/v3r9/pyz/lib:" || , +"/usslocation/forpython/python3.11/site-packages/pip/_vendor" + env.3 = '_BPXK_AUTOCVT=ON' + env.4 = '_CEE_RUNOPTS=FILETAG(AUTOCVT,AUTOTAG) POSIX(ON)' +/* Call Python to parse the data */ + call bpxwunix command,stdin.,stdout.,stderr.,env. + lastrec# = stdout.0 + lastrecord = Substr(stdout.lastrec#,1,40) + whereExists = Pos("Exists",lastrecord) + If whereExists = 0 then, + Message = Caller'/SERVINOW - Ticket Number ' Ticket# ||, + ' is **NOT** defined to Service-Now' + DELSTACK + Return Message; diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/ServiceNow.py b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/ServiceNow.py new file mode 100644 index 0000000..750357e --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+PythonOrGoLang-Example/ServiceNow.py @@ -0,0 +1,44 @@ +# +import os #Import standard Python os lib +import platform #Import standard Python platform lib +import sys #Import standard Python sys lib +# Name the directory where the 'requests' are found +sys.path.append('/usslocation/forpython/python3.11/site-packages/pip/_vendor') +import requests +from requests.auth import HTTPBasicAuth +import json +## Build the complete url here +print("#Arguments:", sys.argv�1:�) # Additional arguments passed +listticketnumber = sys.argv�1:2� +print("#listticketnumber :", type(listticketnumber), listticketnumber) +ticketnumber = listticketnumber�0� +ticketnumberType = type(ticketnumber) +mySubstring = ticketnumber�0:3� # does a substring +# +url = "https://yoursite.service-now.com/api/now/table" +if mySubstring == 'PRB': + print('problem ticket query') + url = url + "/problem?sysparm_query=number=" +else: + print('Change ticket query') + url = url + "/change_request?sysparm_query=number=" +# +url = url + ticketnumber +print("#url:", url) # complete url +# +response = requests.get(url, auth=HTTPBasicAuth('admin', 'yourpassword')) +print(response.content) +out = json.loads(response.content) +n = out�'result'� +# +typeout = type(out) +typen = type(n) +print("#n type", typen) +print("#out type", typeout) +# +if len(n) == 0: + print("error - no output") +elif "number" in n�0�.keys(): + print("Exists") +else: + print("error - not found") diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/C1X2CUST.cob b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/C1X2CUST.cob new file mode 100644 index 0000000..b18cbd4 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/C1X2CUST.cob @@ -0,0 +1,334 @@ + ******************************************************************00110000 + IDENTIFICATION DIVISION. + ******************************************************************00110000 + + PROGRAM-ID. C1X2CUST. + AUTHOR. (C) 2025 Broadcom + Jose Benigno Gonzalez for CUST. + + ****************************************************************** + ENVIRONMENT DIVISION. + ****************************************************************** + 00220000 + *-----------------------------------------------------------------00230000 + CONFIGURATION SECTION. 00240000 + *-----------------------------------------------------------------00250000 + + SOURCE-COMPUTER. IBM-S390 WITH DEBUGGING MODE. + + OBJECT-COMPUTER. IBM-S390. + 00260000 + SPECIAL-NAMES. 00270000 + DECIMAL-POINT IS COMMA + CLASS VALID-NAME 'A' THRU 'I' + 'J' THRU 'R' + 'S' THRU 'Z' + '0' THRU '9'. + 00290000 + + ****************************************************************** + DATA DIVISION. + ****************************************************************** + 00390000 + *-----------------------------------------------------------------00400000 + WORKING-STORAGE SECTION. + *-----------------------------------------------------------------00400000 + + 01 RACF_GROUP PIC X(8). + 01 WK-REQ-CCID. + 03 WK-REQ-CCID-MOD PIC X(3). + 03 WK-REQ-CCID-SUFIX. + 05 WK-REQ-CCID-SUFIX-NUM PIC 9(7). + 03 WK-REQ-CCID-PAD PIC X(2). + 01 WK-ENV PIC X(8). + 01 SN-OBJECT-NUMBER PIC X(10). + 01 PGM PIC X(8). + + 77 WK-TALLY PIC 9(2). + 77 TRIMMED-LEN PIC 9(2). + + *COPY WSCOMMON. + *COPY WSEX02. + + + *================================================================ + *================================================================ + *= List of parameters passed by ref to the IRXJCL + *================================================================ + *==LINKAGE TO IRXJCL============================================= + 01 IRXPARM. + 03 PARM-LENGTH PIC 9(4) COMP. + 03 REXX-NAME PIC X(9). + *--ARGUMENTOS PASADOS AL REXX -------------------------------- + 03 PARM1-A USAGE POINTER. + 03 PARM1-L PIC 9(4) COMP. + 03 PARM2-A USAGE POINTER. + 03 PARM2-L PIC 9(4) COMP. + 03 PARM3-A USAGE POINTER. + 03 PARM3-L PIC 9(4) COMP. + 03 PARM4-A USAGE POINTER. + 03 PARM4-L PIC 9(4) COMP. + *================================================================ + 77 PGM-NAME PIC X(8) VALUE 'IRXJCL'. + * Input/Output Parameter + 77 SNOWOBJ PIC X(10) VALUE SPACES. + * Input Parameter + 77 AUTHTYPE PIC X(8) VALUE SPACES. + 77 ACTION PIC X(8) VALUE SPACES. + * Ouput Parameter + 77 OBJSTATE PIC X(15) VALUE SPACES. + *================================================================ + *----------------------------------------------------------------- + * + * Dynalloc Areas for INFO Request - SNOWTRC DD allocation + * + *----------------------------------------------------------------- + 01 WS-WORK-AREA. + 05 WS-RC PIC 9(9) COMP-5. + 05 WS-DYN-PGM PIC X(8) VALUE 'BPXWDY2 '. + + 01 WDYN-PARM. + 05 WDYN-VALUE PIC X(40) VALUE + 'INFO DD(SNOWTRC) '. + 05 WDYN-NULL PIC X(01) VALUE LOW-VALUES. + + 01 TRACEAPI PIC X(1). + 88 TRACE-DISABLE VALUE '0'. + 88 TRACE-ENABLE VALUE '1'. + + *----------------------------------------------------------------- + * + *----------------------------------------------------------------- + + *-----------------------------------------------------------------00400000 + LINKAGE SECTION. + *-----------------------------------------------------------------00400000 + + COPY EXITBLKS. 00010000 + + ****************************************************************** + PROCEDURE DIVISION USING EXIT-CONTROL-BLOCK + REQUEST-INFO-BLOCK + SRC-ENVIRONMENT-BLOCK + SRC-ELEMENT-MASTER-INFO-BLOCK + SRC-FILE-CONTROL-BLOCK + TGT-ENVIRONMENT-BLOCK + TGT-ELEMENT-MASTER-INFO-BLOCK + TGT-FILE-CONTROL-BLOCK. + + *================================================================ + *-- CONSTRUIMOS LISTA DE PARAMETROS A SER PASADA AL LLAMADOR===== + *================================================================ + * 77 PGM-NAME PIC X(8) VALUE 'IRXJCL'. + * Input/Output Parameter + * 77 SNOW-CR PIC X(10) VALUE SPACES. + * Input Parameter + * 77 AUTHTYPE PIC X(8) VALUE SPACES. + * 77 ACTION PIC X(8) VALUE SPACES. + * Ouput Parameter + * 77 CR-START-DATE PIC X(7) VALUE SPACES. + * 77 CR-START-TIME PIC X(5) VALUE SPACES. + * 77 CR-END-DATE PIC X(7) VALUE SPACES. + * 77 CR-END-TIME PIC X(5) VALUE SPACES. + * 77 OBJSTATE PIC X(15) VALUE SPACES. + * 77 CR-STATUS PIC X(5) VALUE SPACES. + * 77 CR-APPROVAL PIC X(20) VALUE SPACES. + + MOVE +100 TO PARM-LENGTH + MOVE "SNOWCUST" TO REXX-NAME + + SET PARM1-A TO ADDRESS OF SNOWOBJ + MOVE +10 TO PARM1-L + + SET PARM2-A TO ADDRESS OF AUTHTYPE + MOVE +8 TO PARM2-L + + SET PARM3-A TO ADDRESS OF ACTION + MOVE +8 TO PARM3-L + + SET PARM4-A TO ADDRESS OF OBJSTATE + MOVE +15 TO PARM4-L + + MOVE 0 TO TRACEAPI + PERFORM CHECK-TRACE-DDNAME-ALLOC + + IF TRACE-ENABLE + + DISPLAY '------------------------------------------' + + DISPLAY 'EX02 - START' + DISPLAY 'EX02' + DISPLAY 'EX02 - RC ' ECB-RETURN-CODE + DISPLAY 'EX02 - USER-ID ' ECB-USER-ID + DISPLAY 'EX02 - ACTION ' ECB-ACTION-NAME + DISPLAY 'EX02 - HIGH-RC ' ECB-HIGH-RC + DISPLAY 'EX02 - REQ-CCID ' REQ-CCID + DISPLAY 'EX02 - REQ-COMMENT ' REQ-COMMENT + DISPLAY 'EX02 - REQ-SISO-INDICATOR 'REQ-SISO-INDICATOR + DISPLAY 'EX02' + DISPLAY 'EX02 - ACCION DESDE: 'ECB-API-IND + DISPLAY 'EX02' + DISPLAY 'EX02 - SRC-ENV-ENVIRONMENT-NAME: ' + SRC-ENV-ENVIRONMENT-NAME + DISPLAY 'EX02 - TGT-ENV-ENVIRONMENT-NAME: ' + TGT-ENV-ENVIRONMENT-NAME + DISPLAY 'EX02' + DISPLAY 'EX02 - STOP' + + DISPLAY '------------------------------------------' + + END-IF + + EVALUATE TRUE + WHEN MOVE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN RETRIEVE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN ADD-ACTION + MOVE TGT-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN UPDATE-ACTION + MOVE TGT-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN RETRIEVE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN GENERATE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN OTHER + EXIT + END-EVALUATE + + GOBACK. + + *-----------------------------------------------------------------00400000 + CHECK-CCID-VALUE. + *-----------------------------------------------------------------00400000 + IF WK-ENV(1:3) = 'DEV' + IF REQ-CCID(1:3) = 'INC' OR + REQ-CCID(1:3) = 'CHG' + MOVE REQ-CCID TO WK-REQ-CCID + PERFORM CHECK-CCID-SN + END-IF + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + CHECK-CCID-SN. + *----------------------------------------------------------------- + + MOVE ZERO TO WK-TALLY + INSPECT FUNCTION REVERSE(WK-REQ-CCID) + TALLYING WK-TALLY FOR LEADING SPACES + COMPUTE TRIMMED-LEN = 12 - WK-TALLY + + IF TRIMMED-LEN = 10 + + IF WK-REQ-CCID-SUFIX-NUM IS NUMERIC + + MOVE WK-REQ-CCID(1:10) TO SN-OBJECT-NUMBER + PERFORM VALIDATE-SN-OBJECT + + IF RETURN-CODE = 0 + + DISPLAY "------------------------------------------" + DISPLAY "Servicenow Object STATE : " OBJSTATE + DISPLAY "------------------------------------------" + + ELSE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + ELSE + + MOVE 8 TO ECB-RETURN-CODE + MOVE 'ServiceNOW Object Number should be NUMERIC' + TO ECB-MESSAGE-TEXT + MOVE '0231' TO ECB-MESSAGE-CODE + + END-IF + + ELSE + + MOVE 8 TO ECB-RETURN-CODE + MOVE 'CCID For ServiceNOW Must Have 10 CHARACTERS' + TO ECB-MESSAGE-TEXT + MOVE '0230' TO ECB-MESSAGE-CODE + + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + VALIDATE-SN-OBJECT. + *-----------------------------------------------------------------00400000 + * MOVE 'SETDUB1S' TO PGM + * + * CALL PGM USING BY REFERENCE RACF_GROUP + * + *************************************************************** + MOVE SN-OBJECT-NUMBER TO SNOWOBJ + MOVE 'BASIC' TO AUTHTYPE + + IF REQ-CCID(1:3) = 'CHG' + MOVE 'VALCHG' TO ACTION + ELSE + MOVE 'VALINC' TO ACTION + END-IF + + MOVE SPACES TO OBJSTATE + + CALL PGM-NAME USING BY REFERENCE IRXPARM + + IF RETURN-CODE NOT = 0 + + IF TRACE-ENABLE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + MOVE 8 TO ECB-RETURN-CODE + MOVE '0236' TO ECB-MESSAGE-CODE + MOVE 'ServiceNow Obj could not be validated in the service + - 'now instance.' + TO ECB-MESSAGE-TEXT + + ELSE + IF TRACE-ENABLE + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "Servicenow CR STATE : " OBJSTATE + DISPLAY "------------------------------------------" + END-IF + END-IF + + + EXIT. + + *----------------------------------------------------------------- + CHECK-TRACE-DDNAME-ALLOC. + *----------------------------------------------------------------- + * validate if DDNAME SNOWTRACE esta activaE + + CALL WS-DYN-PGM USING WDYN-VALUE + RETURNING WS-RC. + IF WS-RC = 0 + + MOVE 1 TO TRACEAPI + + END-IF + + EXIT. + + diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/C1X7CUST.cob b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/C1X7CUST.cob new file mode 100644 index 0000000..6dd0687 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/C1X7CUST.cob @@ -0,0 +1,373 @@ + ******************************************************************00110000 + IDENTIFICATION DIVISION. + ******************************************************************00110000 + + PROGRAM-ID. C1X7CUST. + AUTHOR. (C) 2025 Broadcom + Jose Benigno Gonzalez for CUST. + + ****************************************************************** + ENVIRONMENT DIVISION. + ****************************************************************** + 00220000 + *-----------------------------------------------------------------00230000 + CONFIGURATION SECTION. 00240000 + *-----------------------------------------------------------------00250000 + + SOURCE-COMPUTER. IBM-S390 WITH DEBUGGING MODE. + + OBJECT-COMPUTER. IBM-S390. + 00260000 + SPECIAL-NAMES. 00270000 + DECIMAL-POINT IS COMMA + CLASS VALID-NAME 'A' THRU 'I' + 'J' THRU 'R' + 'S' THRU 'Z' + '0' THRU '9'. + 00290000 + + ****************************************************************** + DATA DIVISION. + ****************************************************************** + 00390000 + *-----------------------------------------------------------------00400000 + WORKING-STORAGE SECTION. + *-----------------------------------------------------------------00400000 + + 01 RACF_GROUP PIC X(8). + + 01 WK-PKG-SNOW. + 03 WK-PKG-SNOW-MOD PIC X(3). + 03 WK-PKG-SNOW-SUFIX. + 05 WK-PKG-SNOW-SUFIX-NUM PIC 9(7). + 03 WK-PKG-SNOW-PAD PIC X(6). + + 01 WK-ENV PIC X(8). + 01 SN-OBJECT-NUMBER PIC X(10). + 01 PGM PIC X(8). + + 77 WK-TALLY PIC 9(2). + 77 TRIMMED-LEN PIC 9(2). + + + + *================================================================ + *================================================================ + *= List of parameters passed by ref to the IRXJCL + *================================================================ + *==LINKAGE TO IRXJCL============================================= + 01 IRXPARM. + 03 PARM-LENGTH PIC 9(4) COMP. + 03 REXX-NAME PIC X(9). + *--ARGUMENTOS PASADOS AL REXX -------------------------------- + 03 PARM1-A USAGE POINTER. + 03 PARM1-L PIC 9(4) COMP. + 03 PARM2-A USAGE POINTER. + 03 PARM2-L PIC 9(4) COMP. + 03 PARM3-A USAGE POINTER. + 03 PARM3-L PIC 9(4) COMP. + 03 PARM4-A USAGE POINTER. + 03 PARM4-L PIC 9(4) COMP. + *================================================================ + 77 PGM-NAME PIC X(8) VALUE 'IRXJCL'. + * Input/Output Parameter + 77 SNOWOBJ PIC X(10) VALUE SPACES. + * Input Parameter + 77 AUTHTYPE PIC X(8) VALUE SPACES. + 77 ACTION PIC X(8) VALUE SPACES. + * Ouput Parameter + 77 OBJSTATE PIC X(15) VALUE SPACES. + *================================================================ + *----------------------------------------------------------------- + * + * Dynalloc Areas for INFO Request - SNOWTRC DD allocation + * + *----------------------------------------------------------------- + 01 WS-WORK-AREA. + 05 WS-RC PIC 9(9) COMP-5. + 05 WS-DYN-PGM PIC X(8) VALUE 'BPXWDY2 '. + + 01 WDYN-PARM. + 05 WDYN-VALUE PIC X(40) VALUE + 'INFO DD(SNOWTRC) '. + 05 WDYN-NULL PIC X(01) VALUE LOW-VALUES. + + 01 TRACEAPI PIC X(1). + 88 TRACE-DISABLE VALUE '0'. + 88 TRACE-ENABLE VALUE '1'. + + *----------------------------------------------------------------- + LINKAGE SECTION. + *----------------------------------------------------------------- + + COPY PKGXBLKS. + + ****************************************************************** + PROCEDURE DIVISION USING PACKAGE-EXIT-BLOCK + PACKAGE-REQUEST-BLOCK + PACKAGE-EXIT-HEADER-BLOCK + PACKAGE-EXIT-FILE-BLOCK + PACKAGE-EXIT-ACTION-BLOCK + PACKAGE-EXIT-APPROVER-MAP + PACKAGE-EXIT-BACKOUT-BLOCK + PACKAGE-EXIT-SHIPMENT-BLOCK + PACKAGE-EXIT-SCL-BLOCK + PACKAGE-EXIT-COLLECT-BLOCK. + ****************************************************************** + + *----------------------------------------------------------------- + MAIN SECTION. + *-----------------------------------------------------------------00110000 + + MOVE 0 TO TRACEAPI + PERFORM CHECK-TRACE-DDNAME-ALLOC + + IF TRACE-ENABLE + + DISPLAY '---------------------------------------------' + + DISPLAY 'EX07 - START' + DISPLAY 'EX07' + DISPLAY 'EX07 - PACKAGE-ID ' PECB-PACKAGE-ID + DISPLAY 'EX07 - FUNCTION ' PECB-FUNCTION-LITERAL + DISPLAY 'EX07 - SUBFUNC ' PECB-SUBFUNC-LITERAL + DISPLAY 'EX07 - BEF-AFTER ' PECB-BEF-AFTER-LITERAL + DISPLAY 'EX07' + DISPLAY 'EX07 - STOP' + + DISPLAY '---------------------------------------------' + + END-IF + + MOVE +100 TO PARM-LENGTH + MOVE "SNOWCUST" TO REXX-NAME + + SET PARM1-A TO ADDRESS OF SNOWOBJ + MOVE +10 TO PARM1-L + + SET PARM2-A TO ADDRESS OF AUTHTYPE + MOVE +8 TO PARM2-L + + SET PARM3-A TO ADDRESS OF ACTION + MOVE +8 TO PARM3-L + + SET PARM4-A TO ADDRESS OF OBJSTATE + MOVE +15 TO PARM4-L + + PERFORM P-MAIN + + GOBACK. + + *----------------------------------------------------------------- + P-MAIN. + *----------------------------------------------------------------- + + EVALUATE TRUE + WHEN SETUP-EXIT-OPTIONS + MOVE 'N' TO PECB-BEFORE-BACKIN + MOVE 'N' TO PECB-AFTER-BACKIN + MOVE 'N' TO PECB-BEFORE-BACKOUT + MOVE 'N' TO PECB-AFTER-BACKOUT + MOVE 'N' TO PECB-BEFORE-CAST + MOVE 'N' TO PECB-MID-CAST + MOVE 'N' TO PECB-AFTER-CAST + MOVE 'N' TO PECB-BEFORE-COMMIT + MOVE 'N' TO PECB-AFTER-COMMIT + MOVE 'Y' TO PECB-BEFORE-CREATE-BLD + MOVE 'N' TO PECB-AFTER-CREATE-BLD + MOVE 'Y' TO PECB-BEFORE-CREATE-COPY + MOVE 'N' TO PECB-AFTER-CREATE-COPY + MOVE 'Y' TO PECB-BEFORE-CREATE-EDIT + MOVE 'N' TO PECB-AFTER-CREATE-EDIT + MOVE 'Y' TO PECB-BEFORE-CREATE-IMPT + MOVE 'N' TO PECB-AFTER-CREATE-IMPT + MOVE 'N' TO PECB-BEFORE-DELETE + MOVE 'N' TO PECB-AFTER-DELETE + MOVE 'N' TO PECB-BEFORE-DSPLY-APPR + MOVE 'N' TO PECB-BEFORE-DSPLY-BKOUT + MOVE 'N' TO PECB-BEFORE-DSPLY-SCL + MOVE 'N' TO PECB-BEFORE-DSPLY-ELMSM + MOVE 'N' TO PECB-BEFORE-DSPLY-PKG + MOVE 'N' TO PECB-BEFORE-DSPLY-RPT + MOVE 'N' TO PECB-BEFORE-EXEC + MOVE 'N' TO PECB-AFTER-EXEC + MOVE 'N' TO PECB-BEFORE-EXPORT + MOVE 'N' TO PECB-AFTER-EXPORT + MOVE 'Y' TO PECB-BEFORE-GENPID + MOVE 'N' TO PECB-AFTER-GENPID + MOVE 'N' TO PECB-BEFORE-LIST + MOVE 'N' TO PECB-AFTER-LIST + MOVE 'N' TO PECB-BEFORE-MOD-BLD + MOVE 'N' TO PECB-AFTER-MOD-BLD + MOVE 'N' TO PECB-BEFORE-MOD-CPY + MOVE 'N' TO PECB-AFTER-MOD-CPY + MOVE 'N' TO PECB-BEFORE-MOD-EDIT + MOVE 'N' TO PECB-AFTER-MOD-EDIT + MOVE 'N' TO PECB-BEFORE-MOD-IMPT + MOVE 'N' TO PECB-AFTER-MOD-IMPT + MOVE 'N' TO PECB-BEFORE-RESET + MOVE 'N' TO PECB-AFTER-RESET + MOVE 'N' TO PECB-BEFORE-REV-APPR + MOVE 'N' TO PECB-AFTER-REV-APPR + MOVE 'N' TO PECB-BEFORE-REV-DENY + MOVE 'N' TO PECB-AFTER-REV-DENY + MOVE 'N' TO PECB-BEFORE-SHIP-XMIT + MOVE 'N' TO PECB-AFTER-SHIP-XMIT + MOVE 'N' TO PECB-BEFORE-SHIP-CON + MOVE 'N' TO PECB-AFTER-SHIP-CON + WHEN CREATE-PACKAGE + EVALUATE TRUE + WHEN PECB-BEFORE + IF PECB-UEXIT-HOLD-FIELD = 8 + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0719' TO PECB-MESSAGE-ID + MOVE 'Package creation Error.' + TO PECB-MESSAGE + END-IF + WHEN PECB-AFTER + EXIT + END-EVALUATE + WHEN GENERATE-PACKAGE-ID + EVALUATE TRUE + WHEN PECB-BEFORE + PERFORM PROCESS-GENPKGID-GEN + MOVE PECB-NDVR-EXIT-RC TO PECB-UEXIT-HOLD-FIELD + WHEN PECB-AFTER + EXIT + END-EVALUATE + END-EVALUATE + + EXIT. + + + *-----------------------------------------------------------------00400000 + PROCESS-GENPKGID-GEN. + *-----------------------------------------------------------------00400000 + IF PECB-PACKAGE-ID(1:3) ='INC' OR + PECB-PACKAGE-ID(1:3) ='CHG' + + MOVE PECB-PACKAGE-ID TO WK-PKG-SNOW + PERFORM CHECK-PKGID-SN + + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + CHECK-PKGID-SN. + *----------------------------------------------------------------- + + MOVE ZERO TO WK-TALLY + INSPECT FUNCTION REVERSE(WK-PKG-SNOW) + TALLYING WK-TALLY FOR LEADING SPACES + COMPUTE TRIMMED-LEN = 16 - WK-TALLY + + DISPLAY 'TRIMMED-LEN: 'TRIMMED-LEN + + IF TRIMMED-LEN >= 10 + + IF WK-PKG-SNOW-SUFIX-NUM IS NUMERIC + + MOVE WK-PKG-SNOW(1:10) TO SN-OBJECT-NUMBER + PERFORM VALIDATE-SN-OBJECT + + IF RETURN-CODE = 0 + + DISPLAY "------------------------------------------" + DISPLAY "Servicenow Object STATE : " OBJSTATE + DISPLAY "------------------------------------------" + + ELSE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + ELSE + + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0729' TO PECB-MESSAGE-ID + MOVE 'Package ID for ServiceNow Object must be numeric' + TO PECB-MESSAGE + + END-IF + + ELSE + + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0710' TO PECB-MESSAGE-ID + MOVE 'PackageID for ServiceNow object must have at least + - '10 characters.' + TO PECB-MESSAGE + + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + VALIDATE-SN-OBJECT. + *-----------------------------------------------------------------00400000 + * MOVE 'SETDUB1S' TO PGM + * + * CALL PGM USING BY REFERENCE RACF_GROUP + * + *************************************************************** + MOVE SN-OBJECT-NUMBER TO SNOWOBJ + MOVE 'BASIC' TO AUTHTYPE + + IF PECB-PACKAGE-ID(1:3) = 'CHG' + MOVE 'VALCHG' TO ACTION + ELSE + MOVE 'VALINC' TO ACTION + END-IF + + MOVE SPACES TO OBJSTATE + + CALL PGM-NAME USING BY REFERENCE IRXPARM + + IF RETURN-CODE NOT = 0 + + IF TRACE-ENABLE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0717' TO PECB-MESSAGE-ID + MOVE 'ServiceNow Obj could not be validated in the service + - 'now instance.' + TO PECB-MESSAGE + + ELSE + IF TRACE-ENABLE + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "Servicenow CR STATE : " OBJSTATE + DISPLAY "------------------------------------------" + END-IF + END-IF + + + EXIT. + + *----------------------------------------------------------------- + CHECK-TRACE-DDNAME-ALLOC. + *----------------------------------------------------------------- + * validate if DDNAME SNOWTRACE esta activaE + + CALL WS-DYN-PGM USING WDYN-VALUE + RETURNING WS-RC. + IF WS-RC = 0 + + MOVE 1 TO TRACEAPI + + END-IF + + EXIT. + + diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CIUU23.txt b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CIUU23.txt new file mode 100644 index 0000000..0784c65 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CIUU23.txt @@ -0,0 +1,8 @@ +CIUU230E 'Invalid CCID length' .ALARM=YES +'CCID for ServiceNow must have 10 Characters' + +CIUU231E 'Invalid Incident DataType' .ALARM=YES +'ServiceNOW Incident Number must be NUMERIC' + +CIUU236E 'Object does not exist' .ALARM=YES +'ServiceNow Object is not created in the Repository' diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CIUU71.txt b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CIUU71.txt new file mode 100644 index 0000000..21ee28e --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CIUU71.txt @@ -0,0 +1,8 @@ +CIUU710E 'Invalid PackageID length' .T=W .A=Y +'Invalid PackageID Length for new servicenow change request.' + +CIUU717E 'CR not avilable' .T=W .A=Y +'Change Request could not be validated in the servicenow instance.' + +CIUU719E 'Invalid Content' .T=W .A=Y +'Package ID Change Request Number must be a numeric value.' diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CUST_ndvrsnow.rex b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CUST_ndvrsnow.rex new file mode 100644 index 0000000..1e58a82 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/CUST_ndvrsnow.rex @@ -0,0 +1,2129 @@ +/* REXX */ +/*********************************************************************/ +/* AUTHOR. (C) 2025 Broadcom */ +/* Jose Benigno Gonzalez for CUST. */ +/* */ +/* Validates Endevor CCID against ServiceNow change request and */ +/* Incident Management Module - Called from Endevor Exit 2 */ +/* */ +/* Currently in Dev Phase: */ +/* Validates the first ten characters of the packageID against */ +/* ServiceNow change request and Incident Management Module - Called */ +/* from Endevor Exit 7 */ +/* */ +/*------------------------------------------------------------------- */ +/* Obtenemos las direcciones y longitudes los paametros de entrada */ +/*-------------------------------------------------------------------*/ + trace R + +/* Validate parameter passed to the REXX testsno9*/ +/**/ + +/*-------------------------------------------------------------------*/ +/* Obtenemos las direcciones y longitudes los paametros de entrada */ +/*-------------------------------------------------------------------*/ +argstr = ARG(1) + + +parse var argstr 1 A_parm1 , /* servicenow change request */ + 9 L_parm1 , + 13 A_parm2 , /* Auth Type (BASIC or OAUTH) */ + 21 L_parm2 , + 25 A_parm3 , /* Action from Endevor */ + 33 L_parm3 , + 37 A_parm4 , /* CR/INC State */ + 45 L_parm4 , + 49 . + +parm1_d = X2D(L_parm1) /* decimal length of servicenow CR field */ +parm2_d = X2D(L_parm2) /* decimal length of AUTHTYPE field */ +parm3_d = X2D(L_parm3) /* decimal length of Action field */ +parm4_d = X2D(L_parm4) /* decimal length of CR/INC State */ + + +snowObjNumber = strip(storage(A_parm1,parm1_d)) +AuthType = strip(STORAGE(A_parm2,parm2_d)) +Action = strip(STORAGE(A_parm3,parm3_d)) +snowObjState = strip(STORAGE(A_parm4,parm4_d)) + + +verbose= 0 + +SnowTrc_RC = bpxwdyn("info fi(snowtrc) INRTTYP(DSType)") +If SnowTrc_RC = 0 Then do + Verbose = 1 +end + +/* Get Web Enablement Toolkit REXX constants */ + call HTTP_getToolkitConstants + if RESULT <> 0 then + exit fatalError( '** Environment error **' ) + +/* Indicate Program start */ + say '************************************************' + say '** HTTP Web Enablement Toolkit Sample (Begin) **' + say '************************************************' + +/* Initialize variables in program */ + call InitializeVars + + /* get a connection handle */ + call HTTP_init HWTH_HANDLETYPE_CONNECTION + if RESULT <> 0 then + call fatalError('** Connection could not be initialized **') + + /* Set the necessary options before connecting to the server */ + call HTTP_setupConnection + if RESULT <> 0 then + cleanup('CON','** Connection failed to be set up **') + + /* Connect to the HTTP server */ + call HTTP_connect + if RESULT <> 0 then + cleanup('CON','** Connection failed **') + + /* Obtain a request handle */ + call HTTP_init HWTH_HANDLETYPE_HTTPREQUEST + if RESULT <> 0 then + cleanup('CON','** Request could not be initialized **') + +select + + when Action = 'VALINC' then do + + queryParms = '?sysparm_display_value=true' + queryParms = queryParms || '&' ||'sysparm_query=number=' + queryParms = queryParms ||snowObjNumber + + requestURI = IncidentPath || queryParms + + call HTTP_setupRequest "GET", RequestURI, "GETINC" + + if RESULT <> 0 then + cleanup('CONREQ','** Submit job request failed to be setup **') + + /* Make the request to ServiceNow */ + call HTTP_request + if RESULT <> 0 then + cleanup('CONREQ','** ServiceNow request failed **') + + /* Analyze ServiceNow Incident (Response Body) json */ + if VERBOSE then + say "response body GETINC: "||ResponseBody + + if ResponseStatusCode == HTTP_OK & ResponseBody <> '{"result":}' then + Do + call correlateData ResponseBody, "INC" + if result <> 0 Then do + say '*** Error during JSON correlation ***' + end + else do + + SnowCR_state = left(Incident.state,parm4_d) + IntRC = STORAGE(A_parm4,,SnowCR_state) + + programRc = 0 + + end + + End + else Do + If ResponseStatusCode <> HTTP_OK then do + say '***Bad resp received: 'ResponseStatusCode'.' + end + else do + say '*** Object does not exist in servicenow application *** ' + programRc = 8 + end + end + + end + + + when Action = 'VALCHG' then do + + queryParms = '?sysparm_display_value=true' + queryParms = queryParms || '&' ||'sysparm_query=number=' + queryParms = queryParms ||snowObjNumber + + requestURI = ChangeRequestPath || queryParms + + call HTTP_setupRequest "GET", requestURI, "GETCHG" + + if RESULT <> 0 then + cleanup('CONREQ','** Submit job request failed to be setup **') + + /* Make the request to ServiceNow */ + call HTTP_request + if RESULT <> 0 then + cleanup('CONREQ','** ServiceNow request failed **') + + /* Analyze ServiceNow Incident (Response Body) json */ + if VERBOSE then + say "response body GETCHG: "||ResponseBody + + if ResponseStatusCode == HTTP_OK & ResponseBody <> '{"result":}' then + Do + call correlateData ResponseBody, "CHG" + if result <> 0 Then do + say '*** Error during JSON correlation ***' + end + else do + + SnowCR_state = left(ChgRequest.state,parm4_d) + IntRC = STORAGE(A_parm4,,SnowCR_state) + + programRc = 0 + + end + + End + else Do + If ResponseStatusCode <> HTTP_OK then do + say '***Bad resp received: 'ResponseStatusCode'.' + end + else do + say '*** Object does not exist in servicenow application *** ' + programRc = 8 + end + end + + end + + otherwise + say '***Action not implememented yet ***' + +end /* select */ + +cleanup('CONREQ','HTTP Web Enablement Toolkit Sample (Ends)') + +return programRc + + +/*******************************************************/ +/* Function: InitalizeVars */ +/* */ +/* Initialize global vars used throughout the program */ +/*******************************************************/ +InitializeVars: + + programRc = -1 + +/* Initialize Connection and Request handle */ + ConnectionHandle = '' + RequestHandle = '' + +/* Initialize response-related variables */ + HTTP_OK = 200 + HTTP_Created = 201 + HTTP_Accepted = 202 + StatCode = '' + ResponseStatusCode = '' + ResponseReason = '' + ResponseHeaders. = '' + ResponseBody = '' + +/* Servicenow specific variables */ + ServicenowURI = 'https://dev&&&&&&.service-now.com' /* <== '***CHANGE*** + + RingName= '' /* <== '***CHANGE*** + +/* BASIC Authentication */ + + BASIC_UserName = 'admin' /* <== '***CHANGE*** + BASIC_Password = '%%%%%%%%%%%%' /* <== '***CHANGE*** + + /* PATH for GET Request*/ + ChangeRequestPath = '/api/now/table/change_request' + IncidentPath = '/api/now/table/incident' + AffectedCIPath = '/api/now/table/task_ci' + + /* PATH for POST Request*/ + OAuthPath = '/oauth_token.do' + NewChangeRequestPath='/api/sn_chg_rest/change' + +/* Servicenow specific variables for API Json Response */ + + Incident. = '' + ChgRequest. ='' + AffectedCI. ='' + + +return + + +/*******************************************************************/ +/* Function: correlateData() */ +/* */ +/* Use JSON Parser services to process the data returned */ +/* by the web server. */ +/* */ +/* Return 0 if all parsing activity was performed successfully, */ +/* -1 if otherwise. */ +/*******************************************************************/ +correlateData: + snowJSONResponse = arg(1) + snowObjectType = arg(2) /* INC, CHG, TASK */ + parserHandle = '' + isJSON = 0; + jRespHead = "application/json" + l = length(jRespHead) + /******************************************************************/ + /* Check to make sure that the data coming back is in JSON format */ + /* Loop thru all of the response headers and see if any of them */ + /* say Content-Type=application/json */ + /******************************************************************/ + if VERBOSE then + say "CHECKING HEADERS" + + do i = 1 to ResponseHeaders.0 /* 1 to total # of headers*/ + /* Header Name check */ + if ResponseHeaders.i = "Content-Type" then + /* Header value check */ + if substr(ResponseHeaders.i.1,1,l) = jRespHead then + isJSON = 1; + end + + /* if none of the headers was JSON, then don't call parser */ + if isJSON = 0 Then do + return fatalError( '** Data did not come back in JSON format ** ') + end + + /***********************************/ + /* Obtain a JSON Parser instance. */ + /***********************************/ + call JSON_initParser + if RESULT <> 0 then + return fatalError( '** Pre-processing error (parser init failure) **' ) + /****************************/ + /* Parse the response data. */ + /****************************/ + call JSON_parse snowJSONResponse + if RESULT <> 0 then + do + call JSON_termParser + return fatalError( '** Error while parsing SN Incident data **' ) + end + /*****************************************/ + /* Extract specific data and surface it, */ + /* then release the parser instance. */ + /*****************************************/ + call JSON_searchAndDeserializeData snowObjectType + call JSON_termParser + + return 0 + +/*******************************************************/ +/* Function: cleanup */ +/* */ +/* Cleanup a connection and possibly a request */ +/* depending on the parameters pasted in. */ +/*******************************************************/ +cleanup: + cleanupType = arg(1) + errorMsg = arg(2) + + if cleanupType = 'CONREQ' then + call HTTP_terminate RequestHandle, HWTH_NOFORCE + + /* Unconditionally release the connection handle */ + call HTTP_terminate ConnectionHandle, HWTH_NOFORCE + + /* Say error message */ + say errorMsg + + call closeToolkitTrace traceDD + +exit programRC + +/*****************************************************/ +/* HTTP-related functions */ +/* */ +/* These { HTTP_xxx } functions are located together */ +/* for ease of reference and are used to demonstrate */ +/* how this portion of the Web Enablement Toolkit */ +/* can be used. */ +/*****************************************************/ + +/*******************************************************/ +/* Function: HTTP_getToolkitConstants */ +/* */ +/* Access constants used by the toolkit (for return */ +/* codes, etc), via the HWTCONST toolkit api. */ +/* */ +/* Returns: 0 if toolkit constants accessed, -1 if not */ +/*******************************************************/ +HTTP_getToolkitConstants: + /***********************************************/ + /* Ensure that the toolkit host command is */ + /* available in your REXX environment (no harm */ + /* done if already present). Do this before */ + /* your first toolkit api invocation. Also, */ + /* ensure no conflicting signal-handling in */ + /* cases of running in USS environments. */ + /***********************************************/ + if VERBOSE then + say 'Setting hwtcalls on, syscalls sigoff' + call hwtcalls 'on' + call syscalls 'SIGOFF' + /************************************************/ + /* Call the HWTCONST toolkit api. This should */ + /* make all toolkit-related constants available */ + /* to procedures via (expose of) HWT_CONSTANTS */ + /************************************************/ + if VERBOSE then + say 'Including HWT Constants...' + address hwthttp "hwtconst ", + "ReturnCode ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwtconst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtconst (hwthttp) failure **' ) + end /* endif hwtconst failure */ + return 0 /* end function */ + + +/*************************************************/ +/* Function: HTTP_init */ +/* */ +/* Create a handle of the designated type, via */ +/* the HWTHINIT toolkit api. Populate the */ +/* corresponding global variable with the result */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/*************************************************/ +HTTP_init: + HandleType = arg(1) + /***********************************/ + /* Call the HWTHINIT toolkit api. */ + /***********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthinit ", + "ReturnCode ", + "HandleType ", + "HandleOut ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthinit', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthinit failure **' ) + end + if HandleType == HWTH_HANDLETYPE_CONNECTION then + ConnectionHandle = HandleOut + else + RequestHandle = HandleOut + return 0 /* end Function */ + + +/****************************************************/ +/* Function: HTTP_setupConnection */ +/* */ +/* Sets the necessary connection options, via the */ +/* HWTHSET toolkit api. The global variable */ +/* ConnectionHandle orients the api as to the scope */ +/* of the option(s). */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/****************************************************/ +HTTP_setupConnection: + if VERBOSE then + do + /*****************************************************************/ + /* Set the HWT_OPT_VERBOSE option, if appropriate. */ + /* This option is handy when developing an application (but may */ + /* be undesirable once development is complete). Inner workings */ + /* of the toolkit are traced by messages written to standard */ + /* output, or optionally redirected to file (by use of the */ + /* HWTH_OPT_VERBOSE_OUTPUT option). */ + /*****************************************************************/ + say '**** Set HWTH_OPT_VERBOSE for connection ****' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_VERBOSE ", + "HWTH_VERBOSE_ON ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_VERBOSE) failure **' ) + end /* endif hwthset failure */ + + Call TurnOnVerboseOutput + + end /* endif script invocation requested (-V) VERBOSE */ + + /***********************************************************************/ + /* Set HWTH_OPT_USE_SSL */ + /***********************************************************************/ + if VERBOSE then + say '****** Set WTH_OPT_USE_SSL fot SSL ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_USE_SSL ", + "HWTH_SSL_USE ", + "DiagArea." + /* "HWTH_SSL_NONE ", */ + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_USE_SSL) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_SSLVERSION */ + /***********************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_SSLVERSION ***' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_SSLVERSION ", + "HWTH_SSLVERSION_TLSv12 ", + "DiagArea." + /* "HWTH_SSLVERSION_TLSv13 ", + "HWTH_SSLVERSION_DEFAULT ",*/ + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_SSLVERSION) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_SSLKEYTYPE */ + /***********************************************************************/ + /**/ + if VERBOSE then + say '****** Set HWTH_OPT_SSLKEYTYPE ***' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_SSLKEYTYPE ", + "HWTH_SSLKEYTYPE_KEYRINGNAME ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_SSLKEYTYPE) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_SSLKEY */ + /***********************************************************************/ + /**/ + if VERBOSE then + say '****** Set HWTH_OPT_SSLKEY ***' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_SSLKEY ", + "RingName ", + "DiagArea." + /* "IZUSVR.ZOSMF02 ", */ + /* "IZUSVR.KEYR01 ", */ + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_SSLKEY) failure **' ) + end /* endif hwthset failure */ + + /****************************************************************************/ + /* Set URI for connection to Service Now Cloud SaaS */ + /****************************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_URI for connection ******' + + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_URI ", + "ServicenowURI ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_URI) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_COOKIETYPE */ + /* Enable the cookie engine for this connection. Any "eligible" */ + /* stored cookies will be resent to the host on subsequent */ + /* interactions automatically. */ + /***********************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_COOKIETYPE for session cookies ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_COOKIETYPE ", + "HWTH_COOKIETYPE_SESSION ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_COOKIETYPE) failure **' ) + end /* endif hwthset failure */ + + + if VERBOSE then + say 'Connection setup successful' + return 0 /* end subroutine */ + + +/*************************************************************/ +/* Function: HTTP_connect */ +/* */ +/* Connect to the configured domain (host) via the HWTHCONN */ +/* toolkit api. */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/*************************************************************/ +HTTP_connect: + if VERBOSE then + say 'Issue Connect' + /**********************************/ + /* Call the HWTHCONN toolkit api */ + /**********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthconn ", + "ReturnCode ", + "ConnectionHandle ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthconn', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthconn failure **' ) + end + if VERBOSE then + say 'Connect (hwthconn) successful' + return 0 /* end function */ + + +/************************************************************/ +/* Function: HTTP_setupRequest */ +/* */ +/* Sets the necessary request options. The global variable */ +/* RequestHandle orients the api as to the scope of the */ +/* option(s). */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/************************************************************/ +HTTP_setupRequest: +HTTP_Method = arg(1) +RequestURI = arg(2) +Action = arg(3) + + if VERBOSE then + say '****** Set HWTH_OPT_REQUESTMETHOD for request **' + /**************************************************************/ + /* Set HTTP Request method. */ + /* A ??? request method is used to modify a resource on server*/ + /**************************************************************/ + ReturnCode = -1 + DiagArea. = '' + + select + when HTTP_Method = 'GET' then do + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTMETHOD ", + "HWTH_HTTP_REQUEST_GET ", + "DiagArea." + end + + when HTTP_Method = 'POST' then do + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTMETHOD ", + "HWTH_HTTP_REQUEST_POST ", + "DiagArea." + end + + when HTTP_Method = 'PATCH' then do + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTMETHOD ", + "HWTH_HTTP_REQUEST_PATCH ", + "DiagArea." + end + + Otherwise + return fatalError( '** hwthset (HWTH_OPT_REQUESTMETHOD) invalid **' ) + end + + + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError('hwthset (HWTH_OPT_REQUESTMETHOD) failure **' ) + end /* endif hwthset failure */ +/*****************************************************************/ +/* Set the request URI */ +/* Set the URN URI that identifies a resource by name that is */ +/* the target of our request. */ +/*****************************************************************/ + if VERBOSE then + say'****** Set HWTH_OPT_URI for request ******' + + + if VERBOSE then + say 'request URI:' requestURI + + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_URI ", + "requestURI ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_URI) failure **' ) + end /* endif hwthset failure */ + +/*****************************************************************/ +/* Authenticating to the ServiceNow Instance */ +/* Single sign-on uses HTTP basic authentication to fulfill the */ +/* request. Set the authentication level to basic and */ +/* specify userid and password */ +/*****************************************************************/ + + /* Set Authentication Type based on AUTHType parameter */ + If AuthType /= 'OAUTH' Then do + + if VERBOSE then + say'****** Set HWTH_OPT_HTTPAUTH for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_HTTPAUTH ", + "HWTH_HTTPAUTH_BASIC ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_HTTPAUTH) failure **' ) + end /* endif hwthset failure */ + + /* Set username */ + if VERBOSE then + say'****** Set HWTH_OPT_USERNAME for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_USERNAME ", + "BASIC_UserName ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_USERNAME) failure **' ) + end /* endif hwthset failure */ + + /* Set password */ + if VERBOSE then + say'****** Set HWTH_OPT_PASSWORD for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_PASSWORD ", + "BASIC_Password ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_PASSWORD) failure **' ) + end /* endif hwthset failure */ + end + + Else do + + if VERBOSE then + say'****** Set HWTH_OPT_HTTPAUTH for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_HTTPAUTH ", + "HWTH_HTTPAUTH_NONE ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_HTTPAUTH) failure **' ) + end /* endif hwthset failure */ + + end + /* */ + /*********************************************************/ + /* Set the stem variable for receiving response headers */ + /*********************************************************/ + ReturnCode = -1 + DiagArea. = '' + ResponseHeaders. = '' + + if VERBOSE then + say '****** Set HWTH_OPT_RESPONSEHDR_USERDATA for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_RESPONSEHDR_USERDATA ", + "ResponseHeaders. ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_RESPONSEHDR_USERDATA) failure **') + end /* endif hwthset failure */ + + /*******************************************************************/ + /* Have the toolkit convert the response body from ASCII to EBCDIC */ + /* (so that we may pass it to our parser in a form that the latter */ + /* will understand) */ + /*******************************************************************/ + ReturnCode = -1 + DiagArea. = '' + if VERBOSE then + say '****** Set HWTH_OPT_TRANSLATE_RESPBODY for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_TRANSLATE_RESPBODY ", + "HWTH_XLATE_RESPBODY_A2E ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_TRANSLATE_RESPBODY) failure **' ) + end /* endif hwthset failure */ + + /*******************************************************************/ + /* Have the toolkit convert the request body from EBCDIC TO ASCII */ + /*******************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_TRANSLATE_REQBODY for request' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_TRANSLATE_REQBODY ", + "HWTH_XLATE_REQBODY_E2A ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_TRANSLATE_REQBODY) failure **' ) + end /* endif hwthset failure */ + + /**************************************************/ + /* Set Request body */ + /**************************************************/ + ReturnCode = -1 + DiagArea. = '' + + select + + when Action = 'NEWCHG' then do + RequestBody = '{"short_description":"Change Request created on behalf of + end + + when Action = 'ADDCHGNT' then do + Notes = 'Endevor Package ID ' Ndvr_Pkg_id ' has been created for this Chan + RequestBody = '{"work_notes":"' || Notes || '"}' + end + + otherwise RequestBody = "" + + end + + if VERBOSE then + say '****** Set HWTH_OPT_REQUESTBODY for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTBODY ", + "RequestBody ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_REQUESTBODY) failure **') + end /* endif hwthset failure */ + + + /*************************************************/ + /* Set the variable for receiving response body */ + /**************************************************/ + ReturnCode = -1 + DiagArea. = '' + ResponseBody. = '' + + if VERBOSE then + say '****** Set HWTH_OPT_RESPONSEBODY_USERDATA for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_RESPONSEBODY_USERDATA ", + "ResponseBody ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_RESPONSEBODY_USERDATA) failure **') + end /* endif hwthset failure */ + + /*************************************************************/ + /* Set any request header(s) we may have. This depends upon */ + /* the Http request (often we might not have any). */ + /*************************************************************/ + call HTTP_setRequestHeaders + if RESULT <> 0 then + return fatalError( '** Unable to set Request Headers **' ) + + if VERBOSE then + say 'Request setup successful' + return 0 /* end function */ + +/****************************************************************/ +/* Function: HTTP_terminate */ +/* */ +/* Release the designated Connection or Request handle via the */ +/* HWTHTERM toolkit api. */ +/* */ +/* Returns: */ +/* 0 if successful, -1 if not */ +/****************************************************************/ +HTTP_terminate: + + handleIn = arg(1) + forceOption = arg(2) + if VERBOSE then + say 'Terminate' + /***********************************/ + /* Call the HWTHTERM toolkit api. */ + /***********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthterm ", + "ReturnCode ", + "handleIn ", + "forceOption ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthterm', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthterm failure **' ) + end /* endif hwthterm failure */ + if VERBOSE then + say 'Terminate (hwthterm) succeeded' + return 0 /* end function */ + + +/****************************************************************/ +/* Function: HTTP_request */ +/* */ +/* Make the configured Http request via the HWTHRQST toolkit */ +/* api. */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/****************************************************************/ +HTTP_request: + if VERBOSE then + say 'Making Http Request' + ReturnCode = -1 + DiagArea. = '' + /***********************************/ + /* Call the HWTHRQST toolkit api. */ + /***********************************/ + address hwthttp "hwthrqst ", + "ReturnCode ", + "ConnectionHandle ", + "RequestHandle ", + "HttpStatusCode ", + "HttpReasonCode ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthrqst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthrqst failure **' ) + end /* endif hwthrqst failure */ + /****************************************************************/ + /* The ReturnCode indicates merely whether the request was made */ + /* (and response received) without error. The origin server's */ + /* response, of course, is another matter. The HttpStatusCode */ + /* and HttpReasonCode record how the server responded. Any */ + /* header(s) and/or body included in that response are to be */ + /* found in the variables which we established earlier. */ + /****************************************************************/ + ResponseStatusCode = strip(HttpStatusCode,'L',0) + ResponseReasonCode = strip(HttpReasonCode) + if VERBOSE then + do + say 'Request completed' + say 'HTTP Status Code: '||StatCode + say 'HTTP Response Reason Code: '||ResponseReasonCode + end + + return 0 /* end function */ + +/*************************************************************/ +/* Function: HTTP_setRequestHeaders */ +/* */ +/* Add appropriate Request Headers, by first building an */ +/* "SList", and then setting the HWTH_OPT_HTTPHEADERS */ +/* option of the Request with that list. */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/*************************************************************/ +HTTP_setRequestHeaders: + + +If Action = 'NEWCHG' Then do + + SList = '' + acceptHeader = 'Accept: */*' + Authorization = 'Authorization: Bearer' + + + ReturnCode = -1 + DiagArea. = '' + if VERBOSE then + say 'Create new SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_NEW ", + "SList ", + "acceptHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_NEW) failure **' ) + end /* endif hwthslst failure */ + +end + +Else do + + SList = '' + acceptJsonHeader = 'Accept: application/json' + acceptLanguageHeader = 'Accept-Language: en-US' + contentTypeHeader = 'Content-Type: application/json' + Authorization = 'Authorization: Bearer' + + /**********************************************************************/ + /* Create a brand new SList and specify the first header to be an */ + /* "Accept" header that requests that the server return any response */ + /* body text in JSON format. */ + /**********************************************************************/ + ReturnCode = -1 + DiagArea. = '' + if VERBOSE then + say 'Create new SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_NEW ", + "SList ", + "acceptJsonHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_NEW) failure **' ) + end /* endif hwthslst failure */ + /***********************************************************/ + /* Append the Accept-Language request header to the SList */ + /* to infer to the server the regional settings which are */ + /* preferred by this application. */ + /***********************************************************/ + if VERBOSE then + say 'Append to SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_APPEND ", + "SList ", + "acceptLanguageHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_APPEND) failure **' ) + end /* endif hwthslst failure */ + /***********************************************************/ + /* Append the Content-Type request header to the SList */ + /* to specify that the data sent on the put request is in */ + /* JSON format */ + /***********************************************************/ + if VERBOSE then + say 'Append to SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_APPEND ", + "SList ", + "contentTypeHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_APPEND) failure **' ) + end /* endif hwthslst failure */ + +end + /**********************************************************/ + /* ADD the Authorization Request Header if OAUTH */ + /***********************************************************/ + If AuthType= 'OAUTH' then do + + BearerToken = Authorization || ' ' || snow_access_token + + if VERBOSE then + say 'Append to SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_APPEND ", + "SList ", + "BearerToken ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_APPEND) failure **' ) + end /* endif hwthslst failure */ + + end + + /************************************/ + /* Set the request headers with the */ + /* just-produced list */ + /************************************/ + if VERBOSE then + say 'Set HWTH_OPT_HTTPHEADERS for request' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_HTTPHEADERS ", + "SList ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_HTTPHEADERS) failure **' ) + end /* endif hwthset failure */ + + + return 0 /* end function */ + + + + +/*************************************************************/ +/* Function: HTTP_isError */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* set of { HWTH_xx } return codes for evidence of error. */ +/* This set is ordered: HWTH_OK < HWTH_WARNING < ... */ +/* with remaining codes indicating error, so we may check */ +/* via single inequality. */ +/* */ +/* Returns: 1 if any toolkit error is indicated, 0 */ +/* otherwise. */ +/*************************************************************/ +HTTP_isError: + RexxRC = arg(1) + if RexxRC <> 0 then + return 1 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == '' then + return 0 + if ToolkitRC <= HWTH_WARNING then + return 0 + return 1 /* end function */ + + +/*************************************************************/ +/* Function: HTTP_isWarning */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* specific HWTH_WARNING return code. */ +/* */ +/* Returns: 1 if toolkit rc HWTH_WARNING is indicated, 0 */ +/* otherwise. */ +/*************************************************************/ +HTTP_isWarning: + RexxRC = arg(1) + if RexxRC <> 0 then + return 0 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == '' then + return 0 + if ToolkitRC <> HWTH_WARNING then + return 0 + return 1 /* end function */ + + +/***********************************************/ +/* Procedure: HTTP_surfaceDiag() */ +/* */ +/* Surface input error information. Note that */ +/* when the RexxRC is nonzero, the ToolkitRC */ +/* and DiagArea content are moot and are */ +/* suppressed (so as to not mislead). */ +/***********************************************/ +HTTP_surfaceDiag: procedure expose DiagArea. + say + say '*ERROR* ('||arg(1)||') at time: '||Time() + say 'Rexx RC: '||arg(2)', Toolkit ReturnCode: '||arg(3) + say 'DiagArea.Service: '||DiagArea.HWTH_service + say 'DiagArea.ReasonCode: '||DiagArea.HWTH_reasonCode + say 'DiagArea.ReasonDesc: '||DiagArea.HWTH_reasonDesc + say + return /* end procedure */ + + +/***********************************************/ +/* Function: fatalError */ +/* */ +/* Surfaces the input message, and returns */ +/* a canonical failure code. */ +/* */ +/* Returns: -1 to indicate fatal script error. */ +/***********************************************/ + fatalError: + errorMsg = arg(1) + say errorMsg + return -1 /* end function */ + +/***********************************************/ +/* Function: TurnOnVerboseOutput */ +/* */ +/* Sets the zFS UNIX file where the toolkit */ +/* trace will be written */ +/***********************************************/ +TurnOnVerboseOutput: + /**********************************************************/ + say '**** Set HWTH_OPT_VERBOSE_OUTPUT for connection ****' + + traceDataSetName = '' + traceDD = 'HWTTRACE' + + call closeToolkitTrace traceDD + + allocRc = allocateTracefile(traceDataSetName,traceDD) + + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_VERBOSE_OUTPUT ", + "traceDD ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_VERBOSE) failure **' ) + end /* endif hwthset failure */ + return + + + /*************************************************/ + /* Procedure: allocateTracefile */ + /* */ + /* Allocate a previously created trace data set */ + /* with the required attributes (which */ + /* must already exist), and a known DDname. */ + /*************************************************/ + allocateTracefile: procedure expose (PROC_GLOBALS) + datasetName = arg(1) + DDname = arg(2) + + /* allocates datasetName to DDName and directs messages */ + /* to z/OS UNIX standard error (sdterr) */ + + alloc = 'alloc fi('||DDname||') ' + /* alloc = alloc||'da('||quoted(datasetName)||') old msg(2)' */ + alloc = alloc || 'sysout recfm(v)' + + call bpxwdyn alloc + allocRc = Result + + return allocRc /* end procedure */ + + /***********************************************************/ + /* Procedure: closeToolkitTrace */ + /* */ + /* Free the ddname which an earlier redirectToolkitTraceXX */ + /* caused allocation to associate with an HFS file. */ + /***********************************************************/ + closeToolkitTrace: procedure expose (PROC_GLOBALS) + DDname = arg(1) + call bpxwdyn 'free fi('DDname')' + return /* end procedure */ + + /*******************************************************/ + /* Function: quoted */ + /*******************************************************/ + quoted: + stringIn = arg(1) + return "'"||stringIn||"'" + +/*****************************************************/ +/* JSON-related functions */ +/* */ +/* These { JSON_xxx } functions are located together */ +/* for ease of reference and are used to demonstrate */ +/* how this portion of the Web Enablement Toolkit */ +/* can be used in conjunction with the Http-related */ +/* toolkit functions. */ +/*****************************************************/ + +/**********************************************************/ +/* Function: JSON_initParser */ +/* */ +/* Initializes the global parserHandle variable via */ +/* call to toolkit service HWTJINIT. */ +/* */ +/* Returns: 0 if successful, -1 if unsuccessful */ +/**********************************************************/ +JSON_initParser: + if VERBOSE then + say 'Initializing Json Parser' + /***********************************/ + /* Call the HWTJINIT toolkit api. */ + /***********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjinit ", + "ReturnCode ", + "handleOut ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjinit', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjinit failure **' ) + end /* endif hwtjinit failure */ + parserHandle = handleOut + if VERBOSE then + say 'Json Parser init (hwtjinit) succeeded' + return 0 /* end function */ + + +/**********************************************************************/ +/* Function: JSON_parse */ +/* */ +/* Parses the input text body (which should be syntactically correct */ +/* JSON text) via call to toolkit service HWTJPARS. */ +/* */ + /* Returns: 0 if successful, -1 if unsuccessful */ +/**********************************************************************/ +JSON_parse: + jsonTextBody = arg(1) + if VERBOSE then + say 'Invoke Json Parser' + /**************************************************/ + /* Call the HWTJPARS toolkit api. */ + /* Parse scans the input text body and creates an */ + /* internal representation of the JSON data, */ + /* suitable for search and create operations. */ + /**************************************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjpars ", + "ReturnCode ", + "parserHandle ", + "jsonTextBody ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjpars', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjpars failure **' ) + end /* endif hwtjpars failure */ + if VERBOSE then + say 'JSON data parsed successfully' + return 0 /* end function */ + + +/*******************************************************************/ +/* Subroutine: JSON_searchAndDeserializeData */ +/* */ +/* Search for specific values and objects in the parsed response */ +/* body, and deserialize them into the distanceData. stem variable */ +/* */ +/*******************************************************************/ +JSON_searchAndDeserializeData: +snowObjectType = arg(1) + +/*-------------------------------------------------------------------*/ +/* Borramos el area del parametro de salida antes de modificarlo */ +/*-------------------------------------------------------------------*/ + Incident. = '' + ChgRequest. ='' + AffectedCI. ='' + SNData. = '' + + select + /*******************************************************************/ + /* return incident attributes got from JSON */ + /*******************************************************************/ + when snowObjectType = 'INC' then do + + /***************************************/ + /* Get Open Date */ + /***************************************/ + Incident.OpenedAt = JSON_findValue( 0, "opened_at", HWTJ_STRING_TYPE ) + Incident.state = JSON_findValue( 0, "state", HWTJ_STRING_TYPE ) + Incident.Active = JSON_findValue( 0, "active", HWTJ_STRING_TYPE ) + Incident.Priority = JSON_findValue( 0, "priority", HWTJ_STRING_TYPE ) + + + end + + when snowObjectType = 'CHG' then do + + /***************************************/ + /* Get Open Date */ + /***************************************/ + ChgRequest.start_date= JSON_findValue( 0,"start_date", HWTJ_STRING_TYPE) + ChgRequest.end_date = JSON_findValue( 0,"end_date", HWTJ_STRING_TYPE) + ChgRequest.state = JSON_findValue( 0,"state", HWTJ_STRING_TYPE ) + ChgRequest.Active = JSON_findValue( 0,"active", HWTJ_STRING_TYPE ) + ChgRequest.sys_id = JSON_findValue( 0,"sys_id", HWTJ_STRING_TYPE ) + ChgRequest.number = JSON_findValue( 0,"number", HWTJ_STRING_TYPE ) + ChgRequest.approval = JSON_findValue( 0,"approval", HWTJ_STRING_TYPE ) + + end + + when snowObjectType = 'NEWCHG' then do + + /***************************************/ + /* Get Open Date */ + /***************************************/ + CHG_Obj = JSON_findValue( 0, "result", HWTJ_OBJECT_TYPE ) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"number", HWTJ_OBJECT_TYPE ) + ChgRequest.number = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"state", HWTJ_OBJECT_TYPE ) + ChgRequest.state = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"active", HWTJ_OBJECT_TYPE ) + ChgRequest.active = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"sys_id", HWTJ_OBJECT_TYPE ) + ChgRequest.sys_id = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"approval", HWTJ_OBJECT_TYPE ) + ChgRequest.approval = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"start_date", HWTJ_OBJECT_TYPE ) + ChgRequest.start_date = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"end_date", HWTJ_OBJECT_TYPE ) + ChgRequest.start_date = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + end + + when snowObjectType = 'TASK' then do + end + + otherwise + nop + end + + return /* end subroutine */ +/******************************************************************/ +/* Function: JSON_findValue */ +/* */ +/* Searches the appropriate portion of the parsed JSON data (that */ +/* designated by the objectToSearch argument) for an entry whose */ +/* name matches the designated searchName argument. Returns a */ +/* value or handle, depending on the expectedType. */ +/* */ +/* Returns: value or handle as described above, or a null result */ +/* if no suitable value or handle is found. */ +/******************************************************************/ +JSON_findValue: + objectToSearch = arg(1) /* 0 */ + searchName = arg(2) /* label */ + expectedType = arg(3) /* tipo de dato */ + + +/*********************************************************/ +/* Trying to find a value for a null entry is perhaps a */ +/* bit nonsensical, but for completeness we include the */ +/* possibility. We make an arbitrary choice on what to */ +/* return, and do this first, to avoid wasted processing */ +/*********************************************************/ + if expectedType == HWTJ_NULL_TYPE then + return '(null)' + if VERBOSE then + say 'Invoke Json Search' + /********************************************************/ + /* Search the specified object for the specified name. */ + /* The value 0 is specified (for the "startingHandle") */ + /* to indicate that the search should start at the */ + /* beginning of the designated object. */ + /********************************************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjsrch ", + "ReturnCode ", + "parserHandle ", + "HWTJ_SEARCHTYPE_OBJECT ", + "searchName ", + "objectToSearch ", + "0 ", + "searchResult ", + "DiagArea." + RexxRC = RC + /************************************************************/ + /* Differentiate a not found condition from an error, and */ + /* tolerate the former. Note the order dependency here, */ + /* at least as the called routines are currently written. */ + /************************************************************/ + if JSON_isNotFound(RexxRC,ReturnCode) then + return '(not found)' + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjsrch', RexxRC, ReturnCode, DiagArea. + say '** hwtjsrch failure **' + return '' + end /* endif hwtjsrch failed */ + /******************************************/ + /* Verify the type of the search result */ + /******************************************/ + resultType = JSON_getType( searchResult ) + if resultType <> expectedType then + do + say '** Type mismatch ('||resultType||','||expectedType||') **' + return '' + end /* endif unexpected type */ + /******************************************************/ + /* Return the located object or array, as appropriate */ + /******************************************************/ + if expectedType == HWTJ_OBJECT_TYPE | expectedType == HWTJ_ARRAY_TYPE then + do + return searchResult + end /* endif object or array type */ + /*******************************************************/ + /* Return the located string or number, as appropriate */ + /*******************************************************/ + if expectedType == HWTJ_STRING_TYPE | expectedType == HWTJ_NUMBER_TYPE then + do + if VERBOSE then + say 'Invoke Json Get Value' + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjgval ", + "ReturnCode ", + "parserHandle ", + "searchResult ", + "result ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgval', RexxRC, ReturnCode, DiagArea. + say '** hwtjgval failure **' + return '' + end /* endif hwtjgval failed */ + + return result + end /* endif string or number type */ + /****************************************************/ + /* Return the located boolean value, as appropriate */ + /****************************************************/ + if expectedType == HWTJ_BOOLEAN_TYPE then + do + if VERBOSE then + say 'Invoke Json Get Boolean Value' + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjgbov ", + "ReturnCode ", + "parserHandle ", + "searchResult ", + "result ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgbov', RexxRC, ReturnCode, DiagArea. + say '** hwtjgbov failure **' + return '' + end /* endif hwtjgbov failed */ + return result + end /* endif boolean type */ + if VERBOSE then + say '** No return value found **' + return '' /* end function */ + + +/***********************************************************/ +/* Function: JSON_getType */ +/* */ +/* Determine the Json type of the designated search result */ +/* via the HWTJGJST toolkit api. */ +/* */ +/* Returns: Non-negative integral number indicating type */ +/* if successful, -1 if not. */ +/***********************************************************/ +JSON_getType: + searchResult = arg(1) + if VERBOSE then + say 'Invoke Json Get Type' + /*********************************/ + /* Call the HWTHGJST toolkit api */ + /*********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjgjst ", + "ReturnCode ", + "parserHandle ", + "searchResult ", + "resultTypeName ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgjst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgjst failure **' ) + end /* endif hwtjgjst failure */ + else + do + /******************************************************/ + /* Convert the returned type name into its equivalent */ + /* constant, and return that more convenient value. */ + /* Note that the interpret instruction might more */ + /* typically be used here, but the goal here is to */ + /* familiarize the reader with these types. */ + /******************************************************/ + type = strip(resultTypeName) + if type == 'HWTJ_STRING_TYPE' then + return HWTJ_STRING_TYPE + if type == 'HWTJ_NUMBER_TYPE' then + return HWTJ_NUMBER_TYPE + if type == 'HWTJ_BOOLEAN_TYPE' then + return HWTJ_BOOLEAN_TYPE + if type == 'HWTJ_ARRAY_TYPE' then + return HWTJ_ARRAY_TYPE + if type == 'HWTJ_OBJECT_TYPE' then + return HWTJ_OBJECT_TYPE + if type == 'HWTJ_NULL_TYPE' then + return HWTJ_NULL_TYPE + end + /***********************************************/ + /* This return should not occur, in practice. */ + /***********************************************/ + return fatalError( 'Unsupported Type ('||type||') from hwtjgjst' ) + + +/**********************************************************/ +/* Function: JSON_termParser */ +/* */ +/* Cleans up parser resources and invalidates the parser */ +/* instance handle, via call to the HWTJTERM toolkit api. */ +/* Note that as the REXX environment is single-threaded, */ +/* no consideration of any "busy" outcome from the api is */ +/* done (as it would be in other language environments). */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/**********************************************************/ +JSON_termParser: + if VERBOSE then + say 'Terminate Json Parser' + /**********************************/ + /* Call the HWTJTERM toolkit api */ + /**********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjterm ", + "ReturnCode ", + "parserHandle ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjterm', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjterm failure **' ) + end /* endif hwtjterm failure */ + if VERBOSE then + say 'Json Parser terminated' + return 0 /* end function */ + + +/*************************************************************/ +/* Function: JSON_isNotFound */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* specific return code for a "not found" condition. */ +/* */ +/* Returns: 1 if a HWTJ_JSRCH_SRCHSTR_NOT_FOUND condition */ +/* is indicated, 0 otherwise. */ +/*************************************************************/ +JSON_isNotFound: + RexxRC = arg(1) + if RexxRC <> 0 then + return 0 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == HWTJ_JSRCH_SRCHSTR_NOT_FOUND then + return 1 + return 0 /* end function */ + + +/*************************************************************/ +/* Function: JSON_isError */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* set of { HWTJ_xx } return codes for evidence of error. */ +/* This set is ordered: HWTJ_OK < HWTJ_WARNING < ... */ +/* with remaining codes indicating error, so we may check */ +/* via single inequality. */ +/* */ +/* Returns: 1 if any toolkit error is indicated, 0 */ +/* otherwise. */ +/*************************************************************/ +JSON_isError: + RexxRC = arg(1) + if RexxRC <> 0 then + return 1 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == '' then + return 0 + if ToolkitRC <= HWTJ_WARNING then + return 0 + return 1 /* end function */ + + +/***********************************************/ +/* Procedure: JSON_surfaceDiag */ +/* */ +/* Surface input error information. Note that */ +/* when the RexxRC is nonzero, the ToolkitRC */ +/* and DiagArea content are moot and are */ +/* suppressed (so as to not mislead). */ +/* */ +/***********************************************/ +JSON_surfaceDiag: procedure expose DiagArea. + who = arg(1) + RexxRC = arg(2) + ToolkitRC = arg(3) + say + say '*ERROR* ('||who||') at time: '||Time() + say 'Rexx RC: '||RexxRC||', Toolkit ReturnCode: '||ToolkitRC + if RexxRC == 0 then + do + say 'DiagArea.ReasonCode: '||DiagArea.ReasonCode + say 'DiagArea.ReasonDesc: '||DiagArea.ReasonDesc + end + say + return /* end procedure */ + + +/*******************************************************/ +/* Function: quoted */ +/*******************************************************/ +quoted: + stringIn = arg(1) +return "'"||stringIn||"'" +/*******************************************************/ +/* Function: delay */ +/*******************************************************/ +delay: + /* Rexx Delay */ + DelaySec = 0.250000 /* readable width */ + elapsed = TIME(R) + do until elapsed >= DelaySec + elapsed = TIME('E') + end +return + +/***********************************************/ +/* Function: usage */ +/* */ +/* Provide usage guidance to the invoker. */ +/* */ +/* Returns: -1 to indicate fatal script error. */ +/***********************************************/ +usage: + whyString = arg(1) + say + say 'usage:' + say 'ex SNOWOAUT ' + say ' ' + say + say '('||whyString||')' + say + return -1 /* end function */ + + /***********************************************/ +/* Function: GetArgs */ +/* */ +/* Parse script arguments and make appropriate */ +/* variable assignments, or return fatal error */ +/* code via usage() invocation. */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/***********************************************/ +GetArgs: + S = arg(1) + argCount = words(S) + if argCount == 0 | argCount < 3 | argCount > 4 then + return usage( 'Wrong number of arguments' ) + + do i = 1 to argCount + localArg = word(S,i) + select + when (i == 1) then + do + apikey = localArg + end + when (i == 2) | (i == 3) then + call parseLocation + otherwise + if localArg == '-v' then + VERBOSE = 1 + end + end +return 0 /* end function */ + + +/***********************************************/ +/* Function: get_AffectedCI_List */ +/* */ +/* get the Affecte CI list of a CHG Request */ +/***********************************************/ +get_AffectedCI_List: + sys_id = arg(1) + ACI_List. = arg(2) + +call HTTP_setupRequest "TASK", sys_id, "TASK" +if RESULT <> 0 then +cleanup('CONREQ','** Submit job request failed to be setup **') + +/* Make the request to ServiceNow */ +call HTTP_request +if RESULT <> 0 then +cleanup('CONREQ','** ServiceNow request failed **') + +/* Analyze ServiceNow ChanheRequest (Response Body) json */ +if VERBOSE then + say 'response body snow TASK 'sys_id': ' ||ResponseBody + +if ResponseStatusCode == HTTP_OK then +Do + call Process_task_ci_json ResponseBody, ACI_List. + + if result <> 0 Then do + say '*** Error during JSON correlation ***' + end + else do + programRc = 0 + end +End +else Do + say '***Bad resp received: 'ResponseStatusCode'.' +end + +return programRc + + +/***********************************************/ +/* Function: Process_task_ci_json */ +/* */ +/* help implementing new functionalities */ +/* using as example a json text read from a */ +/* file. */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/***********************************************/ + +Process_task_ci_json: + jsonTEXT = arg(1) + ACI_List. = arg(2) + +say 'Response Body received at Process_task_ci_json: 'jsonTEXT +call JSON_initParser +if RESULT <> 0 then + return fatalError( '** Pre-processing error (parser init failure) **' ) + +/****************************/ +/* Parse the response data. */ +/****************************/ +call JSON_parse jsonTEXT +if RESULT <> 0 then + do + call JSON_termParser + return fatalError( '** Error while parsing Input JSON Text **' ) + end +/*****************************************/ +/* Extract specific data and surface it, */ +/* then release the parser instance. */ +/*****************************************/ +if VERBOSE then + say 'Getting number of elements returned in the array of objects' + +AffectedCIsList = JSON_findValue( 0, "result", HWTJ_ARRAY_TYPE ) + +/* NumOfElements = 0 */ + +address hwtjson "hwtjgnue ", + "ReturnCode ", + "parserHandle ", + "AffectedCIsList ", + "NumOfAffectedCIs ", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then +do + call JSON_surfaceDiag 'hwtjgnue', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgnue failure **' ) +end /* endif hwtjinit failure */ + +/*Say 'Number of affected CIs in the Change Request: 'NumOfAffectedCIs +say '' */ + +/* Process each element of the array of objects */ + +ACI_List.0 = NumOfAffectedCIs + +do AffectedCI=0 to NumOfAffectedCIs-1 + +address hwtjson "hwtjgaen ", + "ReturnCode ", + "ParserHandle ", + "AffectedCIsList ", + "AffectedCI", + "EntryValueHandle", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgaen', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgaen failure **' ) + end /* endif hwtjinit failure */ + + Entry = AffectedCI+1 + display_val = JSON_findValue( EntryValueHandle, + ,"display_value" , + ,HWTJ_STRING_TYPE) + + ACI_List.Entry.display_value = display_val + + + created_on = JSON_findValue( EntryValueHandle, + ,"sys_created_on" , + ,HWTJ_STRING_TYPE) + + ACI_List.Entry.sys_created_on = created_on + + + + /* say ' Affected CI 'AffectedCI+1': 'ACI_List.Entry.display_value + say ' Affected CI 'AffectedCI+1': 'ACI_List.Entry.sys_created_on */ + + +end /* do AffectedCI */ + +call JSON_termParser + +return 0 + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ + +/***********************************************/ +/* Function: debug_json_text */ +/* */ +/* help implementing new functionalities */ +/* using as example a json text read from a */ +/* file. */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/***********************************************/ + +debug_json_text: + +/* Validate the JSON Text read from ddname JSONIN */ +/* and copied in responsebody */ + +"execio 1 diskr JSONIN (stem jsonIN." + +jsonTEXT = strip(jsonIN.1) +say '' +say 'JSON Text read from File: ' +say '' +say jsonTEXT +say '' + +/* */ +call JSON_initParser +if RESULT <> 0 then + return fatalError( '** Pre-processing error (parser init failure) **' ) +/****************************/ +/* Parse the response data. */ +/****************************/ +call JSON_parse jsonTEXT +if RESULT <> 0 then + do + call JSON_termParser + return fatalError( '** Error while parsing Input JSON Text **' ) + end +/*****************************************/ +/* Extract specific data and surface it, */ +/* then release the parser instance. */ +/*****************************************/ +if VERBOSE then +say 'Getting number of elements returned in the array of objects' + +AffectedCIsList = JSON_findValue( 0, "result", HWTJ_ARRAY_TYPE ) + +/* NumOfElements = 0 */ + +address hwtjson "hwtjgnue ", + "ReturnCode ", + "parserHandle ", + "AffectedCIsList ", + "NumOfAffectedCIs ", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then +do + call JSON_surfaceDiag 'hwtjgnue', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgnue failure **' ) +end /* endif hwtjinit failure */ + +Say 'Number of affected CIs in the Change Request: 'NumOfAffectedCIs +say '' + +/* Process each element of the array of objects */ + +do AffectedCI=0 to NumOfAffectedCIs-1 + +address hwtjson "hwtjgaen ", + "ReturnCode ", + "ParserHandle ", + "AffectedCIsList ", + "AffectedCI", + "EntryValueHandle", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgaen', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgaen failure **' ) + end /* endif hwtjinit failure */ + + disp_val=JSON_findValue( EntryValueHandle,"display_value" , + ,HWTJ_STRING_TYPE) + + say ' Affected CI 'AffectedCI+1': 'disp_val + +end /* do AffectedCI */ + +call JSON_termParser + +return 100 + diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/README.md b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/README.md new file mode 100644 index 0000000..d9d698e --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/README.md @@ -0,0 +1,20 @@ +# COBOL+REXX+WebEnablementToolki + +## Overview + + +Open each folder to find additional details for each approach. + +Other items in this folder are Endevor exit code examples that query ServiceNow. Endevor functions listed below, each use a COBOL exit, a REXX subroutine and a Python subroutine. Functions include: +- **C1X2CUST.cob**. Before element action exit code to validate a CCID value with ServiceNow +- **C1X7CUST.cob**. Package exit code to validate (a portion of) a package namee with ServiceNow. + +Processing starts with an Endevor action, such as an element Generate or a package create. Endevor then calls a COBOL exit. The COBOL examples collect exit block information from Endevor and pass it to a REXX subroutine. Rexx then calls the python code to query ServiceNow. The results of the query return as a JSON string, which is visible to both the Python and REXX. + + +**SNOWCustomer.rex** is to be placed in the REXX library identified in the COBOL exit program. It uses BPXBATCH to call *CUST_ndvrsnow.rex** on USS. + +> cmd = 'SH /u/users/ibmuser/rexx/CUST_ndvrsnow.rexx' + + +**CUST_ndvrsnow.rex** is to be placed onto a USS directory. \ No newline at end of file diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/SNOWCustomer.rex b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/SNOWCustomer.rex new file mode 100644 index 0000000..717c196 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/SNOWCustomer.rex @@ -0,0 +1,150 @@ +/* rexx */ +/*********************************************************************/ +/* AUTHOR. (C) 2025 Broadcom */ +/* Jose Benigno Gonzalez for CUST. */ +/* */ +/* Validates Endevor CCID against ServiceNow change request and */ +/* Incident Management Module - Called from Endevor Exit 2 */ +/* */ +/* Currently in Dev Phase: */ +/* Validates the first ten characters of the packageID against */ +/* ServiceNow change request and Incident Management Module - Called */ +/* from Endevor Exit 7 */ +/* */ +/*********************************************************************/ +trace off + +argstr = ARG(1) +hexs = C2X(argstr) + +hwtRC = call hwtcalls 'on' +if hwtRC > 0 THEN do + say "cannot establish hwtcalls environment rc="hwtRC + exit hwtRC +end + +verbose= 0 +SnowTrc_RC = bpxwdyn("info fi(snowtrc) INRTTYP(variable)") +If SnowTrc_RC = 0 Then do + Verbose = 1 +end + +/* + Allocation of mandatory ddnames for BPXBATCH +*/ + +If Verbose then exitrc = bpxwdyn("alloc fi(STDOUT) sysout") + else exitrc = bpxwdyn("alloc fi(STDOUT) ", + "dsorg(ps) lrecl(16383) ", + "SPACE(5,1) CYL RECFM(F,B) new delete ") + +If exitRC <> 0 Then Do + say 'DynAlloc error for STDOUT DDname: 'exitRC + call Issue_Message(exitrc) + Return exitRC +End + +If Verbose then exitrc = bpxwdyn("alloc fi(STDERR) sysout") + else exitrc = bpxwdyn("alloc fi(STDERR) ", + "dsorg(ps) lrecl(512) ", + "SPACE(10) TRACKS RECFM(F,B) new delete") + +If exitRC <> 0 Then Do + say 'DynAlloc error for STDERR DDname: 'exitRC + call Issue_Message(exitrc) + Return exitRC +End + +exitrc = bpxwdyn("alloc dd(stdenv) ", + "lrecl(80) recfm(f,b) tracks space(5,1) ", + "new delete") + +If exitRC <> 0 Then Do + say 'DynAlloc error for STDENV DDname: 'exitRC + call Issue_Message(exitrc) + Return exitRC +End + +STDENV_Rec = '_BPX_SHAREAS=YES' +queue Left(STDENV_Rec,80) + +STDENV_Rec = '_BPX_BATCH_SPAWN=YES' +queue Left(PARMIN_Rec,80) + +"Execio" queued() "Diskw STDENV (FINIS" + +/* + Call the servicenow driver interface +*/ +cmd = 'SH /u/users/ibmuser/rexx/CUST_ndvrsnow.rexx' +cmd = cmd || ' ' ||hexs + +prog = 'BPXBATCH' +address 'ATTCHMVS' prog 'cmd' + +BPX_rc = rc + + +exitrc = bpxwdyn("free dd(STDOUT)") +exitrc = bpxwdyn("free dd(STDERR)") +exitrc = bpxwdyn("free dd(STDENV)") + + +sysRC = syscalls('OFF') + +return BPX_rc + +/*****************************************************************/ +/* Procedures */ +/*****************************************************************/ +Issue_Message: Procedure expose s99msg. +Parse ARG exitrc +Numeric digits 10 +Select + when ((exitrc <= -1610612737) & (exitrc >= -2147483648)) |, + (exitrc > 0) Then + Do + /***************************************************************/ + /* */ + /* Ha ocurrido un Error durante la Alocacion Dinamica */ + /* */ + /***************************************************************/ + RetCodeX = D2X(exitrc,8) + say ' ' + say ' *************************************************' + say ' * DynAlloc S99Error: 'substr(RetCodeX,1,4)' *' + say ' * DynAlloc S99Info : 'substr(RetCodeX,5,4)' *' + say ' *************************************************' + say ' ' + if s99msg.0 > 0 then + Do + Say 'DYNALC02E Mensajes de Error S99msg DynAlloc: ' + say ' ' + Do I = 1 Until I = s99msg.0 + say ' 's99msg.i + End + End /* S99msg.o */ + End /* Do exitrc */ + When (exitrc <= -21) & (exitrc >= -99) then + Do + Clave = (exitrc+20) * -1 + say ' ' + Say 'DYNALC03E Error en la clave 'Clave' pasada a DynAlloc', + 'desde programa bpxwdyn.' + End + When (exitrc = 20) then + Do + say ' ' + Say 'DYNALC04E Lista de Parametros de bpxwdyn incorrecta.' + Say ' Revise el manual Using REXX and z/OS UNIX', + 'System Services, para mayor informacion.' + End + When substr(exitrc,2,3) = 100 then + Do + nop + End + Otherwise + nop +End /* Select */ +return + diff --git a/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/ServiceNowSubroutineQuery.cob b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/ServiceNowSubroutineQuery.cob new file mode 100644 index 0000000..3844886 --- /dev/null +++ b/endevor/ServiceNow-Interface/COBOL+REXX+WebEnablementToolkit/ServiceNowSubroutineQuery.cob @@ -0,0 +1,1119 @@ + IDENTIFICATION DIVISION. + PROGRAM-ID. SNINCQRY. + DATA DIVISION. + + WORKING-STORAGE SECTION. + + * Global vars required for majority of HTTP services + 01 Conn-Handle Pic X(12) Value Zeros. + 01 Rqst-Handle Pic X(12) Value Zeros. + 01 Diag-Area Pic X(136) Value Zeros. + + * Slist is used to pass custom HTTP headers on request + 01 Slist-Handle Pic 9(9) Binary Value 0. + + * Dummy vars used by HWTHSET service + 01 option-val-char Pic X(999) Value Spaces. + 01 option-val-numeric Pic 9(9) Binary Value 0. + 01 option-val-addr Pointer Value Null. + 01 option-val-len Pic 9(9) Binary Value 0. + + * Function pointers used to setup response exit routines + 01 header-cb-ptr Function-Pointer Value Null. + 01 rspbdy-cb-ptr Function-Pointer Value Null. + + * Data passed to the response header exit routine + 01 hdr-udata. + 05 hdr-udata-eye Pic X(8) Value 'HDRUDATA'. + 05 hdr-rspcode-ptr Pointer Value Null. + 05 hdr-count-ptr Pointer value Null. + 05 hdr-flags-ptr Pointer Value Null. + + * Response status code returned from the server + * This gets passed to the response header exit + * through the header user data structure + 01 http-resp-code Pic 9(9) Binary Value 0. + + * Count of HTTP headers processed by our exit + 01 http-hdr-count Pic 9(9) Binary Value 0. + + * Data passed to the response body exit routine + 01 body-udata. + 05 body-udata-eye Pic X(8) Value 'BDYUDATA'. + 05 hdr-flags-ptr Pointer Value Null. + 05 resp-body-data-ptr Pointer Value Null. + + * Flag shared between response body and response header exits + * Used by the response header exit to indicate that the response + * body is JSON. + 01 hdr-flags. + 05 json-response-flag Pic 9. + 88 json-response-true Value 1. + 88 json-response-false Value 0. + + 01 request-status-flag Pic 9. + 88 request-successful Value 1. + 88 request-unsuccessful Value 0. + + * Structure for storing data returned from ServiceNow website + * Filled out by the response body exit + 01 resp-body-data. + 05 resp-body-data-eye Pic X(8) Value 'INCIDENT'. + 05 Incident-info. + 10 Incident-number Pic X(10). + 10 Incident-state Pic X(1). + 10 Incident-active Pic X(5). + 10 Incident-priority Pic X(1). + 10 Incident-openedat Pic X(19). + + * Temp variables for storing data + 77 Debug PIC X(3). + 77 WK-TALLY PIC 9(2). + 77 UserName PIC X(32) Value Spaces. + 77 UserName-LEN PIC 9(9) USAGE BINARY VALUE 0. + 77 UserPassword PIC X(32) Value Spaces. + 77 UserPassword-LEN PIC 9(9) USAGE BINARY VALUE 0. + 77 TRACE-DD PIC X(8) Value Spaces. + + + + * + COPY HWTHICOB. + * + LINKAGE SECTION. + + * User-supplied parameter: expecting a 3-char IATA airport code + *01 jcl-parm. + * 05 parm-len Pic S9(3) binary. + * 05 parm-string. + * 10 parm-char Pic X occurs 0 to 100 times + * depending on parm-len. + 01 INC-NUMBER PIC X(11). + 01 INC-IS-ACTIVE PIC x(5). + 01 INC-STATE PIC x(1). + + PROCEDURE DIVISION using INC-NUMBER + INC-IS-ACTIVE + INC-STATE. + Begin. + MOVE 'NO' to Debug + + If Debug = 'YES' + + Display "***********************************************" + Display "** HTTP Web Enablement Toolkit Sample Begins **" + Display "* *" + Display "Incident: " INC-NUMBER + + End-if + + *> Initialize and set up a connection handle + Perform HTTP-Init-Connection + + If (HWTH-OK) + + *> Set the required options before connecting to the server + Perform HTTP-Setup-Connection + + If (HWTH-OK) + + *> Connect to the HTTP server + Perform HTTP-Connect + + If (HWTH-OK) + + *> Initialize and set up a request + Perform HTTP-Init-Request + + If (HWTH-OK) + + *> Set the necessary options before connecting + *> to the server. + Perform HTTP-Setup-Request + + If (HWTH-OK) + + *> Send the request + Perform HTTP-Issue-Request + + If (HWTH-OK) + + *> If the response code was ok, write the data + If http-resp-code equal 200 then + Perform Display-Incident-Data + Set request-successful to true + End-If + End-If + End-If + + *> Terminate the request + Perform HTTP-Terminate-Request + End-If + + *> Disconnect the connection + Perform HTTP-Disconnect + End-If + End-If + + *> Terminate the connection + Perform HTTP-Terminate-Connection + End-If + + *> If the last service was successful and the request + *> completed successfully, then put successful message + If HWTH-OK AND request-successful then + If Debug = 'YES' + Display "** Program Ended Successfully **" + End-if + MOVE 0 TO RETURN-CODE + else + If Debug = 'YES' + Display "** Program Ended Unsuccessfully **" + End-if + MOVE 4095 TO RETURN-CODE + End-if + + If Debug = 'YES' + Display "** HTTP Web Enablement Toolkit Sample Ends **" + Display "***********************************************" + END-IF + GOBACK. + + **************************************************************** + * * + * Function: HTTP-Init-Connection * + * Initializes a connection handle using the HWTHINIT service * + * * + **************************************************************** + HTTP-Init-Connection. + + Set HWTH-HANDLETYPE-CONNECTION to true. + + Call "HWTHINIT" using + HWTH-RETURN-CODE + HWTH-HANDLETYPE + Conn-Handle + HWTH-DIAG-AREA + + If (HWTH-OK) + If Debug = 'YES' + Display "** Initialize succeeded (HWTHINIT)" + End-if + else + Display "HWTHINIT FAILED: " + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + **************************************************************** + * * + * Function: HTTP-Init-Request * + * Initializes a request handle using the HWTHINIT service * + * * + **************************************************************** + HTTP-Init-Request. + + Set HWTH-HANDLETYPE-HTTPREQUEST to true. + + Call "HWTHINIT" using + HWTH-RETURN-CODE + HWTH-HANDLETYPE + Rqst-Handle + HWTH-DIAG-AREA + + If (HWTH-OK) + If Debug = 'YES' + Display "** Initialize succeeded (HWTHINIT)" + End-if + else + Display "HWTHINIT FAILED: " + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + * Function: HTTP-Setup-Connection * + * Sets the necessary connection options * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + HTTP-Setup-Connection. + + *> ______________________________________________________ + *> | | + *> | First, set the verbose option on. This option is | + *> | handy when developing an application. Lots of | + *> | informational error messages are written to | + *> | standard output to help in debugging efforts. | + *> | This option should likely be turned off with | + *> | HWTH_VERBOSE_OFF or just not set at all (default is | + *> | off) when the application goes into production. | + *> |______________________________________________________| + Set HWTH-OPT-VERBOSE to true. + Set HWTH-VERBOSE-ON to true. + Set option-val-addr to address of HWTH-VERBOSE. + Compute option-val-len = function length (HWTH-VERBOSE). + + If Debug = 'YES' + Display "** Set HWTH-OPT-VERBOSE for connection" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA. + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set HWTH-OPT-VERBOSE-OUTPUT | + *> |______________________________________________________| + Set HWTH-OPT-VERBOSE-OUTPUT to true + Move "HWTTRACE" To TRACE-DD + + Set option-val-addr to address of TRACE-DD + Compute option-val-len = + function length (TRACE-DD) + + If Debug = 'YES' + Display "** Set HWTH-OPT-VERBOSE-OUTPUT for connection **" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set HWTH_OPT_USE_SSL. | + *> |______________________________________________________| + Set HWTH-OPT-USE-SSL to true + Set HWTH-SSL-USE to true + + Set option-val-addr to address of HWTH-USESSL + Compute option-val-len = + function length (HWTH-USESSL) + + If Debug = 'YES' + Display "** Set HWTH-OPT-USE-SSL for connection" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set HWTH_OPT_SSLVERSION. | + *> |______________________________________________________| + Set HWTH-OPT-SSLVERSION to true + Set HWTH-SSLVERSION-TLSV12 to true + + Set option-val-addr to address of HWTH-SSLVERSION + Compute option-val-len = + function length (HWTH-SSLVERSION) + + If Debug = 'YES' + Display "** Set HWTH-OPT-SSLVERSION for connection" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set HWTH_OPT_SSLVERSION. | + *> |______________________________________________________| + Set HWTH-OPT-SSLKEYTYPE to true + Set HWTH-SSLKEYTYPE-KEYRINGNAME to true + + Set option-val-addr to address of HWTH-SSLKEYTYPE + Compute option-val-len = + function length (HWTH-SSLKEYTYPE) + + If Debug = 'YES' + Display "** Set HWTH-OPT-SSLKEYTYPE for connection" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set HWTH_OPT_SSLKEY. | + *> |______________________________________________________| + Set HWTH-OPT-SSLKEY to true + + Move "**CHANGE** KEYRING NAME" to option-val-char + Move 16 to option-val-len + + Set option-val-addr to address of option-val-char + + If Debug = 'YES' + Display "** Set HWTH-OPT-SSLKEY for connection" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set URI for connection handle to ServiceNow app | + *> |______________________________________________________| + Set HWTH-OPT-URI to true + + Move "**CHANGE** SERVICENOW INSTANCE URL" + to option-val-char + Move 33 to option-val-len + + Set option-val-addr to address of option-val-char + + If Debug = 'YES' + Display "** Set HWTH-OPT-URI for connection" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set HWTH_OPT_COOKIETYPE | + *> | Enable the cookie engine for this connection. Any | + *> | "eligible" stored cookies will be resent to the | + *> | host on subsequent interactions automatically. | + *> | interactions automatically. | + *> |______________________________________________________| + Set HWTH-OPT-COOKIETYPE to true + Set HWTH-COOKIETYPE-SESSION to true + Set option-val-addr to address of HWTH-COOKIETYPE + Compute option-val-len = + function length (HWTH-COOKIETYPE) + + If Debug = 'YES' + Display "** Set HWTH-OPT-COOKIETYPE for connection" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + else + Display "HWTHSET FAILED: " + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + **************************************************************** + * * + * Function: HTTP-Connect * + * Issues the hwthconn service and performs error checking * + * * + **************************************************************** + HTTP-Connect. + + Call "HWTHCONN" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-DIAG-AREA + + If (HWTH-OK) + + If Debug = 'YES' + Display "** Connect succeeded (HWTHCONN)" + End-if + + else + Display "Connect failed (HWTHCONN)." + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + **************************************************************** + * * + * Function: HTTP-Issue-Request * + * Issues the hwthrqst service and performs error checking * + * * + **************************************************************** + HTTP-Issue-Request. + + Call "HWTHRQST" using + HWTH-RETURN-CODE + Conn-Handle + Rqst-Handle + HWTH-DIAG-AREA + + If (HWTH-OK) + If Debug = 'YES' + Display "** Request succeeded (HWTHRQST)" + End-if + else + Display "Request failed (HWTHRQST)." + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + * Function: HTTP-Setup-Request * + * Sets the necessary request options * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + HTTP-Setup-Request. + + *> ______________________________________________________ + *> | | + *> | Set HTTP Request method. | + *> | A GET request method is used to get data from | + *> | the server. | + *> |______________________________________________________| + Set HWTH-OPT-REQUESTMETHOD to true + Set HWTH-HTTP-REQUEST-GET to true + Set option-val-addr to address of HWTH-REQUESTMETHOD + Compute option-val-len = + function length (HWTH-REQUESTMETHOD) + + If Debug = 'YES' + Display "** Set HWTH-REQUESTMETHOD for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set the request URI | + *> | Set the URI that identifies a resource by name | + *> | that is the target of our request. | + *> |______________________________________________________| + Set HWTH-OPT-URI to true + Move 1 to option-val-len + STRING "/api/now/table/incident?sysparm_query=number=" + DELIMITED BY SIZE + INC-NUMBER DELIMITED BY SIZE + INTO + option-val-char WITH POINTER option-val-len + + Set option-val-addr to address of option-val-char + SUBTRACT 1 FROM option-val-len + + If Debug = 'YES' + Display "** Set HWTH-OPT-URI for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + Move "**CHANGE** ADMIN USERID" to UserName + Move "**CHANGE** ADMIN PASSWORD" to UserPassword + + Move ZERO TO WK-TALLY + Inspect Function Reverse(UserName) + TALLYING WK-TALLY FOR LEADING SPACES + COMPUTE UserName-LEN = 32 - WK-TALLY + + Move ZERO TO WK-TALLY + Inspect Function Reverse(UserPassword) + TALLYING WK-TALLY FOR LEADING SPACES + COMPUTE UserPassword-LEN = 32 - WK-TALLY + + *> ______________________________________________________ + *> | | + *> | ServiceNow Instance Authentication | + *> | Single sign-on uses HTTP basic authentication | + *> |______________________________________________________| + Set HWTH-OPT-HTTPAUTH to true + Set HWTH-HTTPAUTH-BASIC to true + + Set option-val-addr to address of HWTH-HTTPAUTH + Compute option-val-len = + function length (HWTH-HTTPAUTH) + + If Debug = 'YES' + Display "** HWTH-OPT-HTTPAUTH for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | ServiceNow Instance UserName | + *> |______________________________________________________| + Set HWTH-OPT-USERNAME to true + + Set option-val-addr to address of UserName + + If Debug = 'YES' + Display "** HWTH-OPT-USERNAME for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + USERNAME-LEN + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | ServiceNow Instance UserPassword | + *> |______________________________________________________| + Set HWTH-OPT-PASSWORD to true + + Set option-val-addr to address of UserPassword + + If Debug = 'YES' + Display "** HWTH-OPT-USRNAME for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + USERPASSWORD-LEN + HWTH-DIAG-AREA + End-If + + + If HWTH-OK + + *> Create a list of HTTP headers + Perform Build-Slist + + *> Specify the HTTP request headers + Set HWTH-OPT-HTTPHEADERS to true + Set option-val-addr to address of Slist-Handle + Compute option-val-len = function length(Slist-Handle) + + If Debug = 'YES' + Display "** Set HWTH-OPT-HTTPHEADERS for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> Direct the toolkit to convert the response body + *> from ASCII to EBCDIC + Set HWTH-OPT-TRANSLATE-RESPBODY to true + Set HWTH-XLATE-RESPBODY-A2E to true + Set option-val-addr to address of HWTH-XLATE-RESPBODY + Compute option-val-len = + function length (HWTH-XLATE-RESPBODY) + + If Debug = 'YES' + Display "** Set HWTH-OPT-TRANSLATE-RESPBODY for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set the response header callback routine | + *> | Set the address of the routine that is to receive | + *> | control once for every response header that we | + *> | receive | + *> |______________________________________________________| + Set HWTH-OPT-RESPONSEHDR-EXIT to true + Set header-cb-ptr to ENTRY "HWTHHDRX" + Set option-val-addr to address of header-cb-ptr + Compute option-val-len = + function length (header-cb-ptr) + + If Debug = 'YES' + Display "** Set HWTH-OPT-RESPONSEHDR-EXIT for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> Initialize the header user data pointers to allow + *> the response header exit to communicate the HTTP status + *> code and hdr-flags to the main program + Set hdr-rspcode-ptr to address of http-resp-code + Set hdr-count-ptr to address of http-hdr-count + Set hdr-flags-ptr of hdr-udata to address of hdr-flags + + *> ______________________________________________________ + *> | | + *> | Set the response header callback routine user data | + *> | Example to show how data can be passed to the | + *> | response header callback routine to allow the | + *> | routine to customize its processing. | + *> |______________________________________________________| + Set HWTH-OPT-RESPONSEHDR-USERDATA to true + Set option-val-addr to address of hdr-udata + Compute option-val-len = function length(hdr-udata) + + If Debug = 'YES' + Display "** Set HWTH-OPT-RESPONSEHDR-USERDATA for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set the response body callback routine | + *> | Set the address of the routine that is to receive | + *> | control if there is a response body returned by | + *> | the server | + *> |______________________________________________________| + Set HWTH-OPT-RESPONSEBODY-EXIT to true + Set rspbdy-cb-ptr to ENTRY "HWTHBDYX" + Set option-val-addr to address of rspbdy-cb-ptr + Compute option-val-len = + function length (rspbdy-cb-ptr) + + If Debug = 'YES' + Display "** Set HWTH-OPT-RESPONSEBODY-EXIT for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Set the response body callback routine user data | + *> | Example to show how data can be passed to the | + *> | response body callback routine to allow the routine| + *> | to customize its processing. | + *> |______________________________________________________| + Set hdr-flags-ptr of body-udata to address of hdr-flags + Set resp-body-data-ptr to address of resp-body-data + + Set HWTH-OPT-RESPONSEBODY-USERDATA to true + Set option-val-addr to address of body-udata + Compute option-val-len = function length(body-udata) + + If Debug = 'YES' + Display "** Set HWTH-OPT-RESPONSEBODY-USERDATA for request" + End-if + Call "HWTHSET" using + HWTH-RETURN-CODE + rqst-handle + HWTH-Set-OPTION + option-val-addr + option-val-len + HWTH-DIAG-AREA + End-If + . + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + * Function: Build-Slist * + * Sets the necessary request options * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + Build-Slist. + + + + *> ______________________________________________________ + *> | | + *> | Add the Accept request header | + *> | Create a brand new SLST and specify the first | + *> | header to be an "ACCEPT" header that requests that | + *> | the server return the data requested by the GET | + *> | request to be in JSON format. | + *> |______________________________________________________| + Move 1 to option-val-len. + String "Accept: application/json" delimited by size + into option-val-char with pointer + option-val-len. + Subtract 1 from option-val-len. + + Set option-val-addr to address of option-val-char. + Set HWTH-SLST-NEW to true. + + Call "HWTHSLST" using + HWTH-RETURN-CODE + rqst-handle + HWTH-SLST-function + Slist-Handle + option-val-addr + option-val-len + HWTH-DIAG-AREA. + If HWTH-OK + + *> ______________________________________________________ + *> | | + *> | Add the Accept-Language request header | + *> | Append to the just-created SLST and specify an | + *> | additional option "Accept-Language" to infer to | + *> | the server the regional settings preferred by this | + *> | application. | + *> |______________________________________________________| + Move 1 to option-val-len + String "Accept-Language: en-US" delimited by size + into option-val-char with pointer + option-val-len + Subtract 1 from option-val-len + + Set option-val-addr to address of option-val-char + Set HWTH-SLST-APPEND to true + + If Debug = 'YES' + Display "** Adding SLIST APPEND" + End-if + Call "HWTHSLST" using + HWTH-RETURN-CODE + rqst-handle + HWTH-SLST-function + Slist-Handle + option-val-addr + option-val-len + HWTH-DIAG-AREA + else + Display "Slist service failed (HWTHSLST)." + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + **************************************************************** + * * + * Display-Incident-Data * + * * + * * + **************************************************************** + * 10 Incident-number Pic X(11). + * 10 Incident-state Pic X(1). + * 10 Incident-active Pic X(5). + * 10 Incident-priority Pic X(1). + * 10 Incident-openedat Pic X(19). + + Display-Incident-Data. + + If Debug = 'YES' + Display "***********************************" + Display "Incident data for " INC-NUMBER + Display "***********************************" + + Display "Incident Number: " Incident-number + Display "Incident state: " Incident-state + + Display "Inicident Active: " Incident-active + + Display "Incident Priority: " Incident-priority + Display "Incident Open Date: " Incident-openedat + Display "-----------------------------------" + End-if + MOVE Incident-state to INC-STATE + Move Incident-active to INC-IS-ACTIVE + . + + **************************************************************** + * * + * Function: HTTP-Disconnect * + * Issues the hwthdisc service and performs error checking * + * * + **************************************************************** + HTTP-Disconnect. + + Call "HWTHDISC" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-DIAG-AREA + + If (HWTH-OK) + If Debug = 'YES' + Display "** Disconnect succeeded (HWTHDISC)" + End-if + else + Display "Disconnect failed (HWTHDISC)." + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + **************************************************************** + * * + * Function: HTTP-Terminate-Connection * + * Issues the hwthterm service and performs error checking * + * * + **************************************************************** + HTTP-Terminate-Connection. + + Set HWTH-NOFORCE to true. + + Call "HWTHTERM" using + HWTH-RETURN-CODE + Conn-Handle + HWTH-FORCETYPE + HWTH-DIAG-AREA. + + If (HWTH-OK) + If Debug = 'YES' + Display "** Terminate succeeded (HWTHTERM)" + End-if + else + Display "Terminate failed (HWTHTERM)." + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + **************************************************************** + * * + * Function: HTTP-Terminate-Request * + * Issues the hwthterm service and performs error checking * + * * + **************************************************************** + HTTP-Terminate-Request. + + Set HWTH-NOFORCE to true. + + Call "HWTHTERM" using + HWTH-RETURN-CODE + Rqst-Handle + HWTH-FORCETYPE + HWTH-DIAG-AREA. + + If (HWTH-OK) + If Debug = 'YES' + Display "** Terminate succeeded (HWTHTERM)" + End-if + else + Display "Terminate failed (HWTHTERM)." + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + * Function: Set-Http-Option * + * Sets the specified HTTP option * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + IDENTIFICATION DIVISION. + PROGRAM-ID Set-Http-Option COMMON. + DATA DIVISION. + + LINKAGE SECTION. + 01 handle Pic X(12). + 01 option Pic 9(9) Binary. + 01 option-val-addr USAGE POINTER. + 01 option-val-len Pic 9(9) Binary. + + PROCEDURE DIVISION using handle, + option, + option-val-addr, + option-val-len. + Begin. + + Call "HWTHSET" using + HWTH-RETURN-CODE + handle + option + option-val-addr + option-val-len + HWTH-DIAG-AREA. + + If (HWTH-OK) + Display "** Set succeeded (HWTHSET)" + else + Display "Set failed (HWTHSET)." + Call "DSPHDIAG" using + HWTH-RETURN-CODE + HWTH-DIAG-AREA + End-If + . + + End Program Set-Http-Option. + + END PROGRAM SNINCQRY. + + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + * Function: HWTHHDRX * + * Sample Response Header Callback Routine (Exit) * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** + IDENTIFICATION DIVISION. + PROGRAM-ID HWTHHDRX. + DATA DIVISION. + + WORKING-STORAGE SECTION. + 01 Content-Type Pic X(12) Value "CONTENT-TYPE". + 01 Json-Content Pic X(16) Value "APPLICATION/JSON". + 01 Max-Display-Size Pic 9(9) Binary Value 30. + 01 rsp-status-code Pic 9(9) Binary Value 0. + 01 Debug Pic x(3). + + LOCAL-STORAGE SECTION. + 01 name-max-len Pic 9(9) Binary Value 0. + 01 value-max-len Pic 9(9) Binary Value 0. + 01 name-ucase Pic X(999) Value Spaces. + 01 value-ucase Pic X(999) Value Spaces. + 01 Content-Type-Len Pic 9(9) Binary Value 0. + 01 Json-Content-Len Pic 9(9) Binary Value 0. + + 01 HWTH-RESP-EXIT-FLAGS Global Pic 9(9) Binary. + 88 HWTH-EXITFLAG-COOKIESTORE-FULL Value 1. + + 01 HWTH-RESP-EXIT-RC GLOBAL PIC 9(9) BINARY. + 88 HWTH-RESP-EXIT-RC-OK VALUE 0. + 88 HWTH-RESP-EXIT-RC-ABORT VALUE 1. + + LINKAGE SECTION. + 01 http-resp-line Pic X(20). + 01 exit-flags Pic 9(9) Binary. + 01 hdr-name-ptr Usage Pointer. + 01 hdr-name-len Pic 9(9) Binary. + 01 hdr-value-ptr Usage Pointer. + 01 hdr-value-len Pic 9(9) Binary. + 01 hdr-udata-ptr Usage Pointer. + 01 hdr-udata-len Pic 9(9) Binary. + + 01 hdr-name-dsect Pic X(999). + 01 hdr-value-dsect Pic X(999). + 01 reason-dsect Pic X(128). + + 01 hdr-udata. + 05 hdr-udata-eye Pic X(8). + 05 hdr-rspcode-ptr Pointer. + 05 hdr-count-ptr Pointer. + 05 hdr-flags-ptr Pointer. + + 01 http-resp-code Pic 9(9) Binary. + 01 http-hdr-count Pic 9(9) Binary. + + 01 hdr-flags. + 05 json-response-flag Pic 9. + 88 json-response-true Value 1. + 88 json-response-false Value 0. + + 01 HWTH-RESP-STATUS-MAP. + 05 HWTH-STATUS-CODE Pic 9(9) Binary. + 05 HWTH-STATUS-VERS-PTR Pointer. + 05 HWTH-STATUS-VERS-LEN Pic 9(9) Binary. + 05 HWTH-STATUS-REASON-PTR Pointer. + 05 HWTH-STATUS-REASON-LEN Pic 9(9) Binary. + + PROCEDURE DIVISION using http-resp-line, + exit-flags + hdr-name-ptr, + hdr-name-len, + hdr-value-ptr, + hdr-value-len, + hdr-udata-ptr, + hdr-udata-len. + Begin. + + Move 'NO' to Debug + + If Debug = 'YES' + Display "*******************************************" + Display "** Response Header Exit Receives Control **" + End-if + + diff --git a/endevor/ServiceNow-Interface/README.md b/endevor/ServiceNow-Interface/README.md index 7b2c7c3..32551d5 100644 --- a/endevor/ServiceNow-Interface/README.md +++ b/endevor/ServiceNow-Interface/README.md @@ -1,9 +1,11 @@ # ServiceNow interface to Endevor -Items in this folder show example Endevor exit code that interfaces with ServiceNow. This interface assumes that the automated activity begins in Endevor. These samples are provided as is and are not officially supported (see [license](https://github.com/BroadcomMFD/broadcom-product-scripts/blob/main/LICENSE -) for more information). +## Overview +Items in this folder are objects that serve as examples for interfacing Endevor with ServiceNow. They assume that the automated activity begins in Endevor. -An alternative interface begins with ServiceNow, and allows actions in ServiceNow to automate package actions in Endevor. See these sites for more details: +## An Alternative not Covered Here + +An alternative interface, not supported by items in this folder, begins with ServiceNow, and allows actions in ServiceNow to automate package actions in Endevor. See these sites for more details: - [Endevor Package Integration with ServiceNow ](https://medium.com/modern-mainframe/endevor-package-integration-with-servicenow-5302c7d3780a) @@ -12,13 +14,14 @@ An alternative interface begins with ServiceNow, and allows actions in ServiceNo ](https://medium.com/modern-mainframe/endevor-package-integration-with-servicenow-part-2-e982e92b3214 ) -This folder contains Endevor exit code examples that causes Endevor activity to reach out to ServiceNow. Each function uses a COBOL exit, a REXX subroutine and a Python subroutine. Functions include: -- Exit 2. Before element action exit code to validate a CCID value with ServiceNow (C1UEXT02 / C1UEXTR2 / ServiceNow.py) -- Exit 7. Package exit code to validate (a portion of) a package namee with ServiceNow. (C1UEXT07 / C1UEXTR7 / ServiceNow.py) +## What is in this folder + +For Endevor to query ServiceNow, there are at least two choices. They give you the opportunity to choose a method most compatible to your skills and site requirements. Two methods are located within sub-folders in this section. + +- **COBOL+REXX+WebEnablementToolkit** - contains items that leverage [IBM's Web Enablement Toolkit](https://www.ibm.com/docs/en/zos/3.2.0?topic=languages-zos-client-web-enablement-toolkit), avoiding any dependencies for off-host and Open Source items. -Processing starts with an Endevor action. Endevor then calls an example COBOL exit. The COBOL examples show how you can collect exit block information and pass it to a REXX subroutine. Rexx then calls the same example python code. +- **COBOL+REXX+PythonOrGolang-Example** - contains items that depend use a simple Python or a GoLang member on USS, instead of using the Web Enablement Toolkit. -Both REXX examples contain code that allows on-demand REXX tracing to be automatically invoked. Simply allocate the name of the REXX program to DUMMY. For example, to engage the Trace for C1UEXTR2, then allocate C1UEXTR2 to DUMMY. There are two ways to do the allocation: +Open each folder to find additional details. -- In TSO forground, enter "TSO ALLLOC F(C1UEXTR2) DUMMY" -- In batch, include a JCL line "//C1UEXTR2 DD DUMMY" +The processing begins with an Endevor action, such as generating an element or creating a package. These actions trigger an Endevor-engaged COBOL exit. The COBOL examples gather exit block information from Endevor and transmit it to a REXX subroutine. The COBOL exits are expected to remain static. Ultimately, REXX, Python, or GoLang will perform the query to ServiceNow. The query's response is a JSON string, which can then be further examined as required. diff --git a/endevor/ServiceNow-Interface/ServiceNow.bat b/endevor/ServiceNow-Interface/ServiceNow.bat new file mode 100644 index 0000000..006ab27 --- /dev/null +++ b/endevor/ServiceNow-Interface/ServiceNow.bat @@ -0,0 +1,53 @@ +REM In Windows, execute this command file to collect all Package +@ECHO OFF +ECHO ./ ADD NAME=@README > ServiceNow.moveout +ECHO These items come from the Endevor GitHub at >> ServiceNow.moveout +ECHO https://github.com/BroadcomMFD/broadcom-product-scripts >> ServiceNow.moveout +ECHO ------------------------------------------------------- >> ServiceNow.moveout +ECHO These are cob : C1UEXT02 C1UEXTT7 SNINCQRY C1X2CUST C1X7CUST >> ServiceNow.moveout +ECHO These are rex/CSIQCLS0 : C1UEXTR2 C1UEXTR7 SNOWQERY NDVRSNOW SNOWCUST >> ServiceNow.moveout +ECHO These are jcl : SNOW@JCL >> ServiceNow.moveout +ECHO These are txt : CIUU23 CIUU71 >> ServiceNow.moveout +ECHO ./ ADD NAME=C1UEXT02 >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\C1UEXT02.cob >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=C1UEXTR2 >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\C1UEXTR2.rex >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=C1UEXTR7 >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\C1UEXTR7.rex >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=C1UEXTT7 >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\C1UEXTT7.cob >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=SERVICPY >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\ServiceNow.py >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=SNINCQRY >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\ServiceNowSubroutineQuery.cob >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=SNOW@JCL >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\BatchQuery.jcl >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=SNOWQERY >> ServiceNow.moveout +TYPE COBOL+REXX+Python-Example\BatchQuery.rex >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=C1X2CUST >> ServiceNow.moveout +TYPE COBOL+REXX+WebEnablementToolkit\C1X2CUST.cob >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=C1X7CUST >> ServiceNow.moveout +TYPE COBOL+REXX+WebEnablementToolkit\C1X7CUST.cob >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=CIUU23 >> ServiceNow.moveout +TYPE COBOL+REXX+WebEnablementToolkit\CIUU23.txt >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=CIUU71 >> ServiceNow.moveout +TYPE COBOL+REXX+WebEnablementToolkit\CIUU71.txt >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=NDVRSNOW >> ServiceNow.moveout +TYPE COBOL+REXX+WebEnablementToolkit\Customer_ndvrsnow.rex >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +ECHO ./ ADD NAME=SNOWCUST >> ServiceNow.moveout +TYPE COBOL+REXX+WebEnablementToolkit\SNOWCustomer.rex >> ServiceNow.moveout +ECHO. >> ServiceNow.moveout +REM diff --git a/endevor/ServiceNow-Interface/ServiceNow.moveout b/endevor/ServiceNow-Interface/ServiceNow.moveout new file mode 100644 index 0000000..3333c03 --- /dev/null +++ b/endevor/ServiceNow-Interface/ServiceNow.moveout @@ -0,0 +1,5399 @@ +./ ADD NAME=@README +These items come from the Endevor GitHub at +https://github.com/BroadcomMFD/broadcom-product-scripts +------------------------------------------------------- +These are cob : C1UEXT02 C1UEXTT7 SNINCQRY C1X2CUST C1X7CUST +These are rex/CSIQCLS0 : C1UEXTR2 C1UEXTR7 SNOWQERY NDVRSNOW SNOWCUST +These are jcl : SNOW@JCL +These are txt : CIUU23 CIUU71 +./ ADD NAME=C1UEXT02 + PROCESS DYNAM OUTDD(DISPLAYS) + ***************************************************************** + * https://github.com/BroadcomMFD/broadcom-product-scripts + * DESCRIPTION: C1UEXT02 is called before Element processing. * + * It gathers Endevor info from the exit blocks * + * then calls REXX program C1UEXTR2. * + * * + * SETUP: The REXX C1UEXTR2 gets called from DD REXFILE2. * + * Change the DSN to a secure dataset.(2 places) * + * * + * STRING 'ALLOC DD(REXFILE2) ', <--look for REXFILE2/SYSEXEC * + * 'DA(ESS.ENDEVOR.EXIT.REXX)' <----- here * + * DELIMITED BY SIZE * + * ' SHR REUSE' * + * DELIMITED BY SIZE * + * INTO ALLOC-TEXT * + * END-STRING. * + * * + * Change the .REXX dataset name to the name of your dataset * + * that contains your C1UEXTR2 Rexx program. * + ***************************************************************** + ** see also EAGGXCOB for Calling IRXEXEC - the IBM example * + ** for calling IRXEXEC from a Cobol program * + ***************************************************************** + IDENTIFICATION DIVISION. + PROGRAM-ID. C1UEXT02. + DATE-COMPILED. + DATE-WRITTEN. + ENVIRONMENT DIVISION. + CONFIGURATION SECTION. + SOURCE-COMPUTER. IBM-370. + OBJECT-COMPUTER. IBM-370. + * * + ***************************************************************** + INPUT-OUTPUT SECTION. + FILE-CONTROL. + DATA DIVISION. + FILE SECTION. + + ***************************************************************** + * W O R K I N G S T O R A G E * + ***************************************************************** + WORKING-STORAGE SECTION. + + 77 WS-TRACE PIC X VALUE 'N'. + 77 FLAGS PIC S9(8) BINARY. + 77 REXX-RETURN-CODE PIC S9(8) BINARY. + 77 DUMMY-ZERO PIC S9(8) BINARY VALUE 0. + 77 ARGUMENT-PTR POINTER. + 77 EXECBLK-PTR POINTER. + 77 ARGTABLE-PTR POINTER. + 77 EVALBLK-PTR POINTER. + + 01 IRXJCL PIC X(6) VALUE 'IRXJCL'. + 01 IRXEXEC-PGM PIC X(08) VALUE 'IRXEXEC'. + + 01 WS-VARIABLES. + 03 WS-POINTER PIC 9(8) COMP. + 03 WS-WORK-ADDRESS-ADR PIC S9(8) COMP SYNC . + 03 WS-WORK-ADDRESS-PTR REDEFINES WS-WORK-ADDRESS-ADR + USAGE IS POINTER . + 03 ADDRESS-ECB-RETURN-CODE PIC 9(10) . + 03 ADDRESS-ECB-MESSAGE-CODE PIC 9(10) . + 03 ADDRESS-ECB-MESSAGE-LENGTH PIC 9(10) . + 03 ADDRESS-ECB-MESSAGE-TEXT PIC 9(10) . + 03 ADDRESS-REQ-SISO-INDICATOR PIC 9(10) . + 03 ADDRESS-REQ-CCID PIC 9(10) . + 03 ADDRESS-REQ-COMMENT PIC 9(10) . + 03 WS-INSPECT-CCID PIC X(12) . + 03 WS-INSPECT-COMMENT PIC X(40) . + + + 01 BPXWDYN PIC X(8) VALUE 'BPXWDYN'. + 01 ALLOC-STRING. + 05 ALLOC-LENGTH PIC S9(4) BINARY VALUE 100. + 05 ALLOC-TEXT PIC X(100). + + * The block of data below is passed to the REXX program C1UEXTR2 + * to ensure new elements are Registered. + * The bulk of the logic is found in C1UEXTR2 + 01 ELM-C1UEXTR2-PARMS-IRXJCL. + 02 ELM-EXECUTE-PARMS-IRXJCL-TOP. + 03 PARM-LENGTH PIC X(02) VALUE X'0F89'. 00004500 + 03 REXX-NAME PIC X(08) VALUE 'C1UEXTR2'. + 03 FILLER PIC X(01) VALUE SPACE . + 02 ELM-EXECUTE-PARMS-IRXEXEC. 00004800 + 03 WS-REXX-STATEMENTS PIC X(4000). + + 01 EXECBLK. + 05 EXECBLK-ACRYN PIC X(08) VALUE 'IRXEXECB'. + 05 EXECBLK-LENGTH PIC S9(8) BINARY + VALUE 48. + 05 EXECBLK-RESERVED PIC S9(8) BINARY + VALUE 0. + 05 EXECBLK-MEMBER PIC X(08) VALUE 'C1UEXTR2'. + 05 EXECBLK-DDNAME PIC X(08) VALUE 'REXFILE2'. + 05 EXECBLK-SUBCOM PIC X(08) VALUE SPACES. + 05 EXECBLK-DSNPTR POINTER VALUE NULL. + 05 EXECBLK-DSNLEN PIC 9(04) COMP + VALUE 0. + + 01 EVALBLK. + 05 EVALBLK-EVPAD1 PIC S9(8) BINARY + VALUE 0. + 05 EVALBLK-EVSIZE PIC S9(8) BINARY + VALUE 34. + 05 EVALBLK-EVLEN PIC S9(8) BINARY + VALUE 0. + 05 EVALBLK-EVPAD2 PIC S9(8) BINARY + VALUE 0. + 05 EVALBLK-EVDATA PIC X(256). + + 01 ARGUMENT. + 02 ARGUMENT-1 OCCURS 1 TIMES. + 05 ARGSTRING-PTR POINTER. + 05 ARGSTRING-LENGTH PIC S9(8) BINARY. + 02 ARGSTRING-LAST1 PIC S9(8) BINARY + VALUE -1. + 02 ARGSTRING-LAST2 PIC S9(8) BINARY + VALUE -1. + + + *----------------------------------------------------------------- + LINKAGE SECTION. + *----------------------------------------------------------------- + COPY EXITBLKS. + + PROCEDURE DIVISION USING + EXIT-CONTROL-BLOCK + REQUEST-INFO-BLOCK + SRC-ENVIRONMENT-BLOCK + SRC-ELEMENT-MASTER-INFO-BLOCK + SRC-FILE-CONTROL-BLOCK + TGT-ENVIRONMENT-BLOCK + TGT-ELEMENT-MASTER-INFO-BLOCK + TGT-FILE-CONTROL-BLOCK. + + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: RETURN-CODE =' RETURN-CODE . + + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: Entered' + ' SRC-ENV-TYPE-OF-BLOCK=' SRC-ENV-TYPE-OF-BLOCK + ' TGT-ENV-TYPE-OF-BLOCK=' TGT-ENV-TYPE-OF-BLOCK + DISPLAY 'C1UEXT02: ' + ' SRC-ENV-IO-TYPE=' SRC-ENV-IO-TYPE + ' TGT-ENV-IO-TYPE=' TGT-ENV-IO-TYPE + END-IF. + + IF PACKAGE-INSPECT THEN GOBACK. + + MOVE SPACES TO WS-REXX-STATEMENTS . + + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: Setting up addresses ' . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF ECB-RETURN-CODE . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-ECB-RETURN-CODE . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF ECB-MESSAGE-CODE. + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-ECB-MESSAGE-CODE. + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF ECB-MESSAGE-LENGTH. + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-ECB-MESSAGE-LENGTH . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF ECB-MESSAGE-TEXT . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-ECB-MESSAGE-TEXT . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF REQ-CCID . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-REQ-CCID . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF REQ-COMMENT . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-REQ-COMMENT . + + ***** + ***** / Convert COBOL exit block Datanames into Rexx \ + ***** + ***** + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: removing quote chars ' . + + MOVE 1 TO WS-POINTER. + + INSPECT REQ-CCID REPLACING ALL '"' BY X'7D'. + INSPECT REQ-COMMENT REPLACING ALL '"' BY X'7D'. + + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: Stringing ECB vars ' . + + STRING + 'ECB_TSO_BATCH_MODE = "' + DELIMITED BY SIZE + ECB-TSO-BATCH-MODE + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'ECB_USER_ID = "' + DELIMITED BY SIZE + ECB-USER-ID + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'ECB_ACTION_NAME = "' + DELIMITED BY SIZE + ECB-ACTION-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_CCID = "' + DELIMITED BY SIZE + REQ-CCID + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'Address_REQ_CCID = ' + DELIMITED BY SIZE + ADDRESS-REQ-CCID + DELIMITED BY SIZE + ';' + DELIMITED BY SIZE + 'REQ_COMMENT = "' + DELIMITED BY SIZE + REQ-COMMENT + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'Address_REQ_COMMENT = ' + DELIMITED BY SIZE + ADDRESS-REQ-COMMENT + DELIMITED BY SIZE + ';' + DELIMITED BY SIZE + 'REQ_SISO_INDICATOR = "' + DELIMITED BY SIZE + REQ-SISO-INDICATOR + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_DELETE_AFTER = "' + DELIMITED BY SIZE + REQ-DELETE-AFTER + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_SYNCHRONIZE = "' + DELIMITED BY SIZE + REQ-SYNCHRONIZE + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_IGNGEN_FAIL = "' + DELIMITED BY SIZE + REQ-IGNGEN-FAIL + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_PROCESSOR_GROUP = "' + DELIMITED BY SIZE + REQ-PROCESSOR-GROUP + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_OVERWRITE_INDICATOR = "' + DELIMITED BY SIZE + REQ-OVERWRITE-INDICATOR + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_GEN_COPYBACK = "' + DELIMITED BY SIZE + REQ-GEN-COPYBACK + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_BENE = "' + DELIMITED BY SIZE + REQ-BENE + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'REQ_AUTOGEN = "' + DELIMITED BY SIZE + REQ-AUTOGEN + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'Address_ECB_RETURN_CODE = ' ADDRESS-ECB-RETURN-CODE + DELIMITED BY SIZE + '; ' + DELIMITED BY SIZE + 'Address_ECB_MESSAGE_CODE = ' ADDRESS-ECB-MESSAGE-CODE + DELIMITED BY SIZE + '; ' + DELIMITED BY SIZE + 'Address_ECB_MESSAGE_LENGTH = ' + ADDRESS-ECB-MESSAGE-LENGTH + DELIMITED BY SIZE + '; ' + DELIMITED BY SIZE + 'Address_ECB_MESSAGE_TEXT = ' + ADDRESS-ECB-MESSAGE-TEXT + DELIMITED BY SIZE + '; ' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING. + + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: Stringing SRC vars ' + 'SRC-ENV-IO-TYPE=' SRC-ENV-IO-TYPE . + + IF SRC-ENV-LENGTH GREATER THAN ZERO + MOVE SRC-ELM-ACTION-CCID TO WS-INSPECT-CCID + INSPECT WS-INSPECT-CCID + REPLACING ALL '"' BY X'7D' + MOVE SRC-ELM-LEVEL-COMMENT TO + WS-INSPECT-COMMENT + INSPECT WS-INSPECT-COMMENT + REPLACING ALL '"' BY X'7D' + + INSPECT WS-INSPECT-CCID REPLACING ALL '"' BY X'7D' + INSPECT WS-INSPECT-COMMENT REPLACING ALL '"' BY X'7D' + STRING + 'SRC_ELM_ACTION_CCID = "' + DELIMITED BY SIZE + WS-INSPECT-CCID + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ELM_LEVEL_COMMENT= "' + DELIMITED BY SIZE + WS-INSPECT-COMMENT + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ELM_LAST_PROC_PACKAGE = "' + DELIMITED BY SIZE + SRC-ELM-LAST-PROC-PACKAGE + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ELM_PROCESSOR_GROUP = "' + DELIMITED BY SIZE + SRC-ELM-PROCESSOR-GROUP + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + + STRING + 'SRC_ENV_ENVIRONMENT_NAME = "' + DELIMITED BY SIZE + SRC-ENV-ENVIRONMENT-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ENV_STAGE_NAME = "' + DELIMITED BY SIZE + SRC-ENV-STAGE-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ENV_SYSTEM_NAME = "' + DELIMITED BY SIZE + SRC-ENV-SYSTEM-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ENV_SUBSYSTEM_NAME = "' + DELIMITED BY SIZE + SRC-ENV-SUBSYSTEM-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ENV_TYPE_NAME = "' + DELIMITED BY SIZE + SRC-ENV-TYPE-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ENV_ELEMENT_NAME = "' + DELIMITED BY SIZE + SRC-ENV-ELEMENT-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ENV_TYPE_OF_BLOCK = "' + DELIMITED BY SIZE + SRC-ENV-TYPE-OF-BLOCK + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'SRC_ENV_IO_TYPE = "' + DELIMITED BY SIZE + SRC-ENV-IO-TYPE + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + END-IF . + + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: Stringing TGT vars ' + END-IF . + + IF TGT-ENV-LENGTH GREATER THAN ZERO + STRING + 'TGT_ENV_ENVIRONMENT_NAME = "' + DELIMITED BY SIZE + TGT-ENV-ENVIRONMENT-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ENV_STAGE_NAME = "' + DELIMITED BY SIZE + TGT-ENV-STAGE-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ENV_SYSTEM_NAME = "' + DELIMITED BY SIZE + TGT-ENV-SYSTEM-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ENV_SUBSYSTEM_NAME = "' + DELIMITED BY SIZE + TGT-ENV-SUBSYSTEM-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ENV_TYPE_NAME = "' + DELIMITED BY SIZE + TGT-ENV-TYPE-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ENV_ELEMENT_NAME = "' + DELIMITED BY SIZE + TGT-ENV-ELEMENT-NAME + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ENV_TYPE_OF_BLOCK = "' + DELIMITED BY SIZE + TGT-ENV-TYPE-OF-BLOCK + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ENV_IO_TYPE = "' + DELIMITED BY SIZE + TGT-ENV-IO-TYPE + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ELM_LAST_PROC_PACKAGE = "' + DELIMITED BY SIZE + TGT-ELM-LAST-PROC-PACKAGE + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ELM_PROCESSOR_GROUP = "' + DELIMITED BY SIZE + TGT-ELM-PROCESSOR-GROUP + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + + IF TGT-ENV-TYPE-OF-BLOCK = 'C' + MOVE TGT-ELM-ACTION-CCID TO WS-INSPECT-CCID + INSPECT WS-INSPECT-CCID + REPLACING ALL '"' BY X'7D' + MOVE TGT-ELM-LEVEL-COMMENT TO + WS-INSPECT-COMMENT + INSPECT WS-INSPECT-COMMENT + REPLACING ALL '"' BY X'7D' + + STRING + 'TGT_ELM_ACTION_CCID = "' + DELIMITED BY SIZE + WS-INSPECT-CCID + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + 'TGT_ELM_LEVEL_COMMENT= "' + DELIMITED BY SIZE + WS-INSPECT-COMMENT + DELIMITED BY SIZE + '";' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + END-IF + END-IF. + ***** \ Convert COBOL exit block Datanames into Rexx / + ***** + + IF WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: Calling Rexx' + END-IF. + + *****IF TSO + MOVE 'C1UEXTR2' TO EXECBLK-MEMBER + MOVE 4000 TO ARGSTRING-LENGTH(1) + MOVE SPACES TO ALLOC-TEXT + PERFORM 2100-ALLOCATE-REXFILE + CALL 'SET-ARG1-POINTER' USING ARGUMENT-PTR + ELM-EXECUTE-PARMS-IRXEXEC + PERFORM 1800-REXX-CALL-VIA-IRXEXEC + PERFORM 2200-FREE-REXFILES + *****ELSE + ***** PERFORM 2101-ALLOCATE-SYSEXEC + ***** CALL IRXJCL USING ELM-C1UEXTR2-PARMS-IRXJCL + ***** IF RETURN-CODE NOT = 0 + ***** DISPLAY 'C1UEXT02: BAD CALL TO IRXJCL - RC = ' + ***** RETURN-CODE + ***** END-IF + ***** PERFORM 2201-FREE-SYSEXEC + *****END-IF . + + MOVE 0 TO RETURN-CODE . + + GOBACK. + + 1800-REXX-CALL-VIA-IRXEXEC. + SET ARGSTRING-PTR (1) TO ARGUMENT-PTR . + CALL 'SET-ARGUMENT-POINTER' USING ARGTABLE-PTR + ARGUMENT . + CALL 'SET-EXECBLK-POINTER' USING EXECBLK-PTR + EXECBLK . + CALL 'SET-EVALBLK-POINTER' USING EVALBLK-PTR + EVALBLK . + MOVE 536870912 TO FLAGS + MOVE 0 TO REXX-RETURN-CODE . + + *--- CALL THE REXX EXEC --- + CALL IRXEXEC-PGM USING EXECBLK-PTR + ARGTABLE-PTR + FLAGS + DUMMY-ZERO + DUMMY-ZERO + EVALBLK-PTR + DUMMY-ZERO + DUMMY-ZERO + DUMMY-ZERO + REXX-RETURN-CODE. + + IF REXX-RETURN-CODE NOT = 0 + DISPLAY 'C1UEXT02: IRXEXEC RETURN CODE = ' + REXX-RETURN-CODE + END-IF + + CANCEL IRXEXEC-PGM + . + + ***************************************************************** + ** Allocate DD REXFILE for TSO processing + ***************************************************************** + 2100-ALLOCATE-REXFILE. + + MOVE SPACES TO ALLOC-TEXT . + STRING 'ALLOC DD(REXFILE2) ', + 'DA(YOURSITE.YOUR.NDVR.NODES1.CLSTREXX)' + DELIMITED BY SIZE + ' SHR REUSE' + DELIMITED BY SIZE + INTO ALLOC-TEXT + END-STRING. + PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . + + ***************************************************************** + ** Allocate DD SYSEXEC for batch processing + ***************************************************************** + 2101-ALLOCATE-SYSEXEC. + + MOVE SPACES TO ALLOC-TEXT . + STRING 'ALLOC DD(SYSEXEC) ', + 'DA(YOURSITE.YOUR.NDVR.NODES1.CLSTREXX)' + DELIMITED BY SIZE + ' SHR REUSE' + DELIMITED BY SIZE + INTO ALLOC-TEXT + END-STRING. + PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . + + ***************************************************************** + ** DYNAMICALLY DE-ALLOCATE UNNEEDED REXX FILES + ***************************************************************** + 2200-FREE-REXFILES. + + MOVE 'FREE DD(REXFILE2)' TO ALLOC-TEXT + PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . + + ***************************************************************** + ** CALL BPXWDYN TO PREFORM REQUIRED REXX FUNCTIONS + 2201-FREE-SYSEXEC. + + MOVE 'FREE DD(SYSEXEC)' TO ALLOC-TEXT + PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . + + ***************************************************************** + ** CALL BPXWDYN TO PREFORM REQUIRED REXX FUNCTIONS + 9000-DYNAMIC-ALLOC-DEALLOC. + + CALL BPXWDYN USING ALLOC-STRING + + IF RETURN-CODE NOT = ZERO OR + WS-TRACE = 'Y' THEN + DISPLAY 'C1UEXT02: ALLOCATION result: RETURN CODE = ' + RETURN-CODE + DISPLAY ALLOC-TEXT + END-IF + + MOVE SPACES TO ALLOC-TEXT + . + + + ****************************************************************** + * BEGIN NESTED PROGRAMS USED TO SET THE POINTERS OF DATA AREAS + * THAT ARE BEING PASSED TO IRXEXEC SO THAT A REXX ROUTINE CAN + * PASS DATA (OTHER THAN A RETURN CODE) BACK TO A COBOL PROGRAM. + ****************************************************************** + + ******** SET-ARG1-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-ARG1-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 ARG-PTR POINTER. + 77 ARG1 PIC X(16). + + PROCEDURE DIVISION USING ARG-PTR + ARG1. + SET ARG-PTR TO ADDRESS OF ARG1 + GOBACK. + END PROGRAM SET-ARG1-POINTER. + + ******** SET-ARGUMENT-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-ARGUMENT-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 ARGTABLE-PTR POINTER. + 01 ARGUMENT. + 02 ARGUMENT-1 OCCURS 1 TIMES. + 05 ARGSTRING-PTR POINTER. + 05 ARGSTRING-LENGTH PIC S9(8) BINARY. + 02 ARGSTRING-LAST1 PIC S9(8) BINARY. + 02 ARGSTRING-LAST2 PIC S9(8) BINARY. + PROCEDURE DIVISION USING ARGTABLE-PTR + ARGUMENT. + SET ARGTABLE-PTR TO ADDRESS OF ARGUMENT + GOBACK. + END PROGRAM SET-ARGUMENT-POINTER. + + ******** SET-EXECBLK-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-EXECBLK-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 EXECBLK-PTR POINTER. + 01 EXECBLK. + 03 EXECBLK-ACRYN PIC X(8). + 03 EXECBLK-LENGTH PIC 9(4) COMP. + 03 EXECBLK-RESERVED PIC 9(4) COMP. + 03 EXECBLK-MEMBER PIC X(8). + 03 EXECBLK-DDNAME PIC X(8). + 03 EXECBLK-SUBCOM PIC X(8). + 03 EXECBLK-DSNPTR POINTER. + 03 EXECBLK-DSNLEN PIC 9(4) COMP. + PROCEDURE DIVISION USING EXECBLK-PTR + EXECBLK. + SET EXECBLK-PTR TO ADDRESS OF EXECBLK + GOBACK. + END PROGRAM SET-EXECBLK-POINTER. + + ******** SET-EVALBLK-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-EVALBLK-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 EVALBLK-PTR POINTER. + 01 EVALBLK. + 03 EVALBLK-EVPAD1 PIC 9(4) COMP. + 03 EVALBLK-EVSIZE PIC 9(4) COMP. + 03 EVALBLK-EVLEN PIC 9(4) COMP. + 03 EVALBLK-EVPAD2 PIC 9(4) COMP. + 03 EVALBLK-EVDATA PIC X(256). + PROCEDURE DIVISION USING EVALBLK-PTR + EVALBLK. + SET EVALBLK-PTR TO ADDRESS OF EVALBLK + GOBACK. + END PROGRAM SET-EVALBLK-POINTER. + *--- END OF MAIN PROGRAM + END PROGRAM C1UEXT02. + +./ ADD NAME=C1UEXTR2 +/* rexx */ +/* -------------------------------------------------------------- */ +/* This is a simple version that: */ +/* o Reuses a CCID value already on the element if CCID is blank */ +/* o Validates a CCID with Service-Now */ +/* o Reuses a comment value from element if comment is blank */ +/* o Gives a friendly reminder if the SIGNOUT OVERRIDE is on */ +/* -------------------------------------------------------------- */ + + STRING = "ALLOC DD(SYSTSPRT) SYSOUT(A) " + CALL BPXWDYN STRING; + STRING = "ALLOC DD(SYSTSIN) DUMMY" + CALL BPXWDYN STRING; + + /* If C1UEXTR2 is allocated to anything, turn on Trace */ + WhatDDName = 'C1UEXTR2' + CALL BPXWDYN "INFO FI("WhatDDName")", + "INRTDSN(DSNVAR) INRDSNT(myDSNT)" + if Substr(DSNVAR,1,1) /= = ' ' then Trace ?r + + Sa= 'You called ....CLSTREXX(C1UEXTR2) ' + + /* In case these are not provided by the Exit */ + SRC_ELM_ACTION_CCID = ' ' + SRC_ELM_LEVEL_COMMENT = ' ' + TGT_ELM_ACTION_CCID = ' ' + TGT_ELM_LEVEL_COMMENT = ' ' + /* These Element Actions determine whehter to */ + /* use SRC or TGT variables */ + ActionsThatUse_SRC = 'RETRIEVE MOVE DELETE GENERATE' + ActionsThatUse_TGT = 'UPDATE ' + + Arg Parms + Parms = Strip(Parms) + sa= 'Parms len=' Length(Parms) + + /* Parms from C1UEXT02 is a string of REXX statements */ + Interpret Parms + MyRc = 0 + Message ='' + MessageCode = ' ' + + /* If CCID is left blank, then apply last used CCID */ + /* otherwise if it appears to be a ServiceNow - validate */ + If REQ_CCID = COPIES(' ',12) then Call Update_CCID; + Else, + If Substr(REQ_CCID,1,3) = 'PRB' |, + Substr(REQ_CCID,1,3) = 'CHG' then Call Validate_CCID; + + /* If COMMENT is left blank, then apply last used COMMENT */ + If MyRc < 8 &, + REQ_COMMENT = COPIES(' ',40) then Call Update_COMMENT; + + sa= 'MyRc =' MyRc + + /* Did user specify OVERRIDE SIGNOUT ? */ + If MyRc = 0 & REQ_SISO_INDICATOR = 'Y' then + Do + Message = 'Remember that you have set OVERRIDE SIGNOUT' + MyRc = 4 + End + + If MyRc = 0 then Exit + + If Message /= '' then, + Do + hexAddress = D2X(Address_ECB_MESSAGE_TEXT) + storrep = STORAGE(hexAddress,,Message) + hexAddress = D2X(Address_ECB_MESSAGE_LENGTH) + storrep = STORAGE(hexAddress,,'0084'X) + End + + If MessageCode /= ' ' then, + Do + hexAddress = D2X(Address_ECB_MESSAGE_CODE) + storrep = STORAGE(hexAddress,,MessageCode) + End + + /* Tell Endevor something changed or something failed */ + hexAddress = D2X(Address_ECB_RETURN_CODE) + If MyRc = 4 then, + storrep = STORAGE(hexAddress,,'00000004'X) + Else, + storrep = STORAGE(hexAddress,,'00000008'X) + + Exit + +Update_CCID: + + If Wordpos(ECB_ACTION_NAME,ActionsThatUse_SRC) > 0 then, + Replace_CCID = SRC_ELM_ACTION_CCID + Else, + If Wordpos(ECB_ACTION_NAME,ActionsThatUse_TGT) > 0 then, + Replace_CCID = TGT_ELM_ACTION_CCID + + /* Still missing a CCID? */ + If Substr(Replace_CCID,1,1) < 'a' then, + Do + MyRc = 8 + Message = '** A CCID value is required **' + MessageCode = 'U012' + Return; + End + + hexAddress = D2X(Address_REQ_CCID) + storrep = STORAGE(hexAddress,,Replace_CCID) + MyRc = 4 + + Return; + +Validate_CCID: + + /* build STDENV input */ + CALL BPXWDYN , + "ALLOC DD(STDENV) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "EXPORT PATH=$PATH:" ||, + "'/usr/lpp/IBM/cyp/v3r11/pyz/lib/python3.11/'" + Queue "EXPORT VIRTUAL_ENV=" ||, + "'/u/users/NDVRTeam/venv/lib/python3.11/site-packages/'" + "EXECIO 2 DISKW STDENV (finis" + + /* build BPXBATCH inputs and outputs */ + /* build STDPARM input */ + CALL BPXWDYN , + "ALLOC DD(STDPARM) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "sh cd " ||, + "/u/users/NDVRTeam/venv/lib/python3.11/site-packages;" + Queue "python ServiceNow.py" REQ_CCID + "EXECIO 2 DISKW STDPARM (finis" + + CALL BPXWDYN , + "ALLOC DD(STDOUT) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Notnow =, + "ALLOC DD(STDOUT) DA('IBMUSER.STDOUT') OLD REUSE " + + CALL BPXWDYN "ALLOC DD(STDIN) DUMMY SHR REUSE" + CALL BPXWDYN "ALLOC DD(STDERR) DA(*) SHR REUSE" + + ADDRESS LINK 'BPXBATCH' + + "EXECIO * DISKR STDOUT (Stem stdout. finis" + lastrec# = stdout.0 + lastrecord = Substr(stdout.lastrec#,1,40) + + If Pos("Exists",lastrecord) = 0 then, + Do + Message = 'C1UEXTR2 - CCID ' REQ_CCID ||, + ' is not defined to Service-Now' + MessageCode = 'U012' + MyRc = 8 + End + + CALL BPXWDYN "FREE DD(STDENV) " + CALL BPXWDYN "FREE DD(STDPARM)" + CALL BPXWDYN "FREE DD(STDOUT) " + CALL BPXWDYN "FREE DD(STDIN) " + CALL BPXWDYN "FREE DD(STDERR) " + + Return; + +Update_COMMENT: + + If Wordpos(ECB_ACTION_NAME,ActionsThatUse_SRC) > 0 then, + Replace_COMMENT = SRC_ELM_LEVEL_COMMENT + Else, + If Wordpos(ECB_ACTION_NAME,ActionsThatUse_TGT) > 0 then, + Replace_COMMENT = TGT_ELM_LEVEL_COMMENT + + If Substr(Replace_COMMENT,1,1) < 'a' then, + Do + MyRc = 8 + Message = '** A COMMENT value is required **' + MessageCode = 'U011' + Return; + End + + hexAddress = D2X(Address_REQ_COMMENT) + storrep = STORAGE(hexAddress,,Replace_COMMENT) + MyRc = 4 + + Return; + + +./ ADD NAME=C1UEXTR7 +/* rexx */ +/* Perform various Package actions in REXX */ +/* */ +/* A COBOL exit CALLS this REXX and provides values for */ +/* REXX variables, including these. */ +/* Find documentation on these in the TechDocs documentation */ +/* where each underscore appears as a dash in the documentation. */ +/* For example, PECB_PACKAGE_ID is documented as */ +/* PECB-PACKAGE-ID */ +/* */ +/* PECB_PACKAGE_ID PAPP_GROUP_NAME */ +/* PECB_FUNCTION_LITERAL PAPP_ENVIRONMENT */ +/* PECB_SUBFUNC_LITERAL PAPP_QUORUM_COUNT */ +/* PECB_BEF_AFTER_LITERAL PAPP_APPROVER_FLAG */ +/* PECB_USER_BATCH_JOBNAME PAPP_APPR_GRP_TYPE */ +/* PREQ_PKG_CAST_COMPVAL PAPP_APPR_GRP_DISQ */ +/* PHDR_PKG_SHR_OPTION PAPP_SEQUENCE_NUMBER */ +/* PHDR_PKG_ENV */ +/* PHDR_PKG_STGID */ +/* Address fields are provided for fields that may be */ +/* modified by the REXX. */ +/* Address_PECB_MESSAGE Address_MYSMTP_SUBJECT */ +/* Address_MYSMTP_MESSAGE Address_MYSMTP_TEXT */ +/* Address_MYSMTP_USERID Address_MYSMTP_URL */ +/* Address_MYSMTP_FROM Address_MYSMTP_EMAIL_IDS */ +/* MYSMTP_EMAIL_IDS MYSMTP_EMAIL_ID_SIZE */ +/* */ + /* Values to be set for your site...... */ + /* For package REVIEW (APPROVE/DENY)..... */ + /* Enter location of Approver Group sequencing ... */ + ApproverGroupSequence= 'YOURSITE.NDVR.PARMLIB(APPROVER)' + + /* Do you want all CAST actions to be peformed in Batch? */ + Force_CAST_in_Batch = 'Y' ; /* Y/N */ + Force_CAST_in_Batch = 'N' ; /* Y/N */ + + /* If wanting to limit the use of this exit, uncomment... */ + If USERID() /= 'IBMUSER' then exit + + /* If wanting to send email, use these variables with */ + /* designated maximum lengths. The Rexx will put them */ + /* into their proper places. */ + /* */ + /* Variable Description max-Len */ + /* */ + /* MySMTP_Message Email Message 80 */ + /* MySMTP_From Email From name 50 */ + /* MySMTP_Subject Email Subject 50 */ + /* MySMTP_textline.1 Text line in email 133 */ + /* MySMTP_textline.2 " 133 */ + /* MySMTP_textline.nn up to 99 133 */ + /* MySMTP_textline.0 Number Text lines used (max 99) 2 */ + /* MySMTP_URL Y/N 1 */ + /* MYSMTP_EMAIL_IDS List of space delimited userids *Exit */ + /* The COBOL exit OCCURS clause determines / */ + /* In case these are not already allocated, these are attempted */ + STRING = "ALLOC DD(SYSTSPRT) SYSOUT(A) " + CALL BPXWDYN STRING; + STRING = "ALLOC DD(SYSTSIN) DUMMY" + CALL BPXWDYN STRING; + + /* Parms are REXX statements passed from COBOL exit */ + Arg Parms + Parms = Strip(Parms) + sa= 'Parms len=' Length(Parms) + + /* If C1UEXTR7 is allocated to anything, turn on Trace */ + WhatDDName = 'C1UEXTR7' + CALL BPXWDYN "INFO FI("WhatDDName")", + "INRTDSN(DSNVAR) INRDSNT(myDSNT)" + If Substr(DSNVAR,1,1) /= ' ' then TraceRQ = 'Y' + + If TraceRQ = 'Y' then, + Say 'C1UEXTR7 is called again:' + + /* Parms from C1UEXT07 is a string of REXX statements */ + + Interpret Parms + If TraceRQ = 'Y' & PECB_MODE = 'B' then Trace r + + If Substr(PHDR_PKG_NOTE5,1,5) = 'TRACE' then TraceRQ = 'Y' + + If TraceRQ = 'Y' then, + Do + Trace ?r + Sa= 'CALL_REASON = ' CALL_REASON + Sa= 'PECB_FUNCTION_LITERAL = ' PECB_FUNCTION_LITERAL + Sa= 'PECB_SUBFUNC_LITERAL = ' PECB_SUBFUNC_LITERAL + Sa= 'PECB_BEF_AFTER_LITERAL= ' PECB_BEF_AFTER_LITERAL + Sa= 'PECB_PACKAGE_ID = ' PECB_PACKAGE_ID + Sa= 'MYSMTP_EMAIL_ID_SIZE = ' MYSMTP_EMAIL_ID_SIZE + End + + /* Initialize variables.... */ + Message = '' + MessageCode = ' ' + MyRc = 0 + + /* Validate Package prefix with ServiceNow */ + If PECB_FUNCTION_LITERAL ='CREATE' &, + PECB_BEF_AFTER_LITERAL ='BEFORE' &, + (Substr(PECB_PACKAGE_ID,1,3) = 'PRB' |, + Substr(PECB_PACKAGE_ID,1,3) = 'CHG' ) then, + Do + Call Validate_PackageID + If MyRc > 0 then Exit + End + + /* Enforce packages to be Backout Enabled */ + IF PREQ_BACKOUT_ENABLED /= 'Y' then, + Do + Message = 'Package made to be Backout enabled' + MyRc = 4 + hexAddress = D2X(Address_PREQ_BACKOUT_ENABLED) + storrep = STORAGE(hexAddress,,'Y') + Call SetExitReturnInfo + Exit + End; + + If PECB_FUNCTION_LITERAL ='CAST' &, + PECB_SUBFUNC_LITERAL ='CAST' &, + PECB_BEF_AFTER_LITERAL ='BEFORE' &, + PECB_MODE = "T" &, /* TSO foreground */ + Force_CAST_in_Batch = 'Y' then, + Call SubmitBatchCAST + Else, + If PECB_FUNCTION_LITERAL ='CAST' &, + PECB_SUBFUNC_LITERAL ='CAST' &, + PECB_BEF_AFTER_LITERAL ='AFTER' then, + Call ManageEmails ; + + Exit + +ManageEmails: + + If TraceRQ = 'Y' then Trace ?R + whereami = 'ManageEmails' + + /* Only run if the exit is giving us an Approver Group */ + If Substr(CALL_REASON,1,16) = 'APPROVER GROUP #' then, + Do + Call SaveOffApproverGrpInfo + Return + End + + /*****************************************************************/ + /* Initializaztion and Example statements */ + /*****************************************************************/ + MySMTP_Message =, + 'YOURSITE.NDVR.REXX(C1UEXTR7)' + MySMTP_Subject = 'Please Approve Package' PECB_PACKAGE_ID + MySMTP_From = Left('YOURSITE your testing Endevor',50) + MySMTP_textline.1 = 'Package' PECB_PACKAGE_ID, + ' has been CAST and is ready for APPROVAL.' + MySMTP_textline.2 = 'Your Review and approval of package', + PECB_PACKAGE_ID 'is reqested.' + MySMTP_textline.3 = ' ' + MySMTP_textline.4 = ' ' + MySMTP_textline.0 = 4 + MYSMTP_EMAIL_IDS = '' + + /* Only run if the exit says all Approver Grps are done */ + If Substr(CALL_REASON,1,22) = 'NO MORE APPROVER GRPS ' then, + Do + Call CheckApproverGroupSequence + Return + End + + Return + +Validate_PackageID: + + If TraceRQ = 'Y' then Trace ?R + whereami = 'Validate_PackageID' + /* build STDENV input */ + CALL BPXWDYN , + "ALLOC DD(STDENV) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "EXPORT PATH=$PATH:" ||, + "'/usr/lpp/IBM/cyp/v3r11/pyz/lib/python3.11/'" + Queue "EXPORT VIRTUAL_ENV=" ||, + "'/u/users/NDVRTeam/venv/lib/python3.11/site-packages/'" + "EXECIO 2 DISKW STDENV (finis" + + /* build BPXBATCH inputs and outputs */ + /* build STDPARM input */ + CALL BPXWDYN , + "ALLOC DD(STDPARM) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "sh cd " ||, + "/u/users/NDVRTeam/venv/lib/python3.11/site-packages;" + Queue "python ServiceNow.py" Substr(PECB_PACKAGE_ID,1,10) + "EXECIO 2 DISKW STDPARM (finis" + + CALL BPXWDYN , + "ALLOC DD(STDOUT) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Notnow =, + "ALLOC DD(STDOUT) DA('IBMUSER.STDOUT') OLD REUSE " + + CALL BPXWDYN , + "ALLOC DD(STDERR) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Notnow =, + "ALLOC DD(STDERR) DA(*) SHR REUSE" + + CALL BPXWDYN "ALLOC DD(STDIN) DUMMY SHR REUSE" + CALL BPXWDYN "ALLOC DD(STDERR) DA(*) SHR REUSE" + + ADDRESS LINK 'BPXBATCH' + CallRC = RC + + "EXECIO * DISKR STDOUT (Stem stdout. finis" + lastrec# = stdout.0 + lastrecord = Substr(stdout.lastrec#,1,40) + + If Pos("Exists",lastrecord) = 0 then, + Do + Message = 'C1UEXTR7 - Package prefix' PECB_PACKAGE_ID ||, + ' is not defined to Service-Now' + MessageCode = 'U033' + MyRc = 8 + Call SetExitReturnInfo + End + + If CallRC = 0 then, + Do + CALL BPXWDYN "FREE DD(STDENV) " + CALL BPXWDYN "FREE DD(STDPARM)" + CALL BPXWDYN "FREE DD(STDOUT) " + CALL BPXWDYN "FREE DD(STDIN) " + CALL BPXWDYN "FREE DD(STDERR) " + End + + Return; + +SaveOffApproverGrpInfo: + + If TraceRQ = 'Y' then Trace ?R + PAPP_SEQUENCE_NUMBER = Substr(CALL_REASON,17,4) + numberQueued = QUEUED() + If PAPP_SEQUENCE_NUMBER = "0001" & numberQueued > 0 then, + Do numberQueued /* Clear out whatever is queued */ + pull leftovers + End + If PAPP_SEQUENCE_NUMBER = "0001" then, + CALL BPXWDYN , /* save Approver group data */ + "ALLOC DD(C1UEXTD7) LRECL(180) BLKSIZE(18000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " MOD UNCATALOG REUSE "; + + pkgGrp# = Strip(PAPP_SEQUENCE_NUMBER,'L','0') + PAPP_GROUP_NAME = Strip(PAPP_GROUP_NAME) + Queue 'pkgGrp# = 'pkgGrp# + Queue 'GROUP_NAME.pkgGrp# ="'PAPP_GROUP_NAME'"' + Queue 'ENVIRONMENT.pkgGrp# ="'Strip(PAPP_ENVIRONMENT)'"' + Queue 'APPR_GRP_TYPE.pkgGrp# ="'Strip(PAPP_APPR_GRP_TYPE)'"' + Queue 'APPR_GRP_DISQ.pkgGrp# ="'Strip(PAPP_APPR_GRP_DISQ)'"' + Queue 'APPROVAL_FLAGS.pkgGrp# ="'Strip(PAPP_APPROVAL_FLAGS)'"' + Queue 'STATUS.'PAPP_GROUP_NAME '="'Strip(PAPP_APPROVER_FLAG)'"' + Queue 'QUORUM.'PAPP_GROUP_NAME '='Strip(PAPP_QUORUM_COUNT,'L','0') + Queue 'USRLST.'PAPP_GROUP_NAME '="'Strip(PAPP_APPROVAL_IDS)'"' + + numberQueued = QUEUED() + "EXECIO" numberQueued " DISKW C1UEXTD7 " + + Return; + +CheckApproverGroupSequence: + + If TraceRQ = 'Y' then Trace ?R + whereami = 'CheckApproverGroupSequence' + + /* If C1UEXTD7 is allocated to anything, we have approvers */ + WhatDDName = 'C1UEXTD7' + CALL BPXWDYN "INFO FI("WhatDDName")", + "INRTDSN(DSNVAR) INRDSNT(myDSNT)" + If Substr(DSNVAR,1,1) = ' ' then Return + + "EXECIO 0 DISKW C1UEXTD7 (Finis" + "EXECIO * DISKR C1UEXTD7 (Finis" + CALL BPXWDYN "FREE DD(C1UEXTD7)" + numberQueued = QUEUED() + + /* Analyze Exit-provided Approver Group info */ + pkgGrp# = 0 + /* By default, ordered Approver Groups are not related */ + STATUS. = 'NotRelated' + QUORUM. = 0 + + /* Return Approver Group info for this package */ + Do q# = 1 to numberQueued + Parse Pull something + If TraceRQ = 'Y' then say "@187" something + interpret something + End; + ThisEnvironment = ENVIRONMENT.pkgGrp# + + /* Read the site's required Approver Group sequencing */ + CALL BPXWDYN, + "ALLOC DD(APPROVER) DA('"ApproverGroupSequence"') SHR REUSE" + "EXECIO * DISKR APPROVER (Stem ordered. Finis" + CALL BPXWDYN "FREE DD(APPROVER)" + + /* Build a sequenced list of all named Approver Groups */ + OrderedApproverGroups = '' + /* Set a default value to be 1 greater than number of groups */ + NotOrdered = ordered.0 + 1 + Sequence. = NotOrdered + Do ord# = 1 to ordered.0 + orderedEntry = ordered.ord# + orderedEnv = Word(orderedEntry,1) + If orderedEnv /= thisEnvironment then iterate + orderedApproverGroup = Word(orderedEntry,2) + If orderedApproverGroup = 'AllOthers' then, + DefaultOrder = ord# + SEQUENCE.orderedApproverGroup = ord# + If TraceRQ = 'Y' then, + say "@201 Sequence for" orderedApproverGroup "is" ord# + End; /* Do ord# = 1 to ordered.0 */ + + Sequence.NotOrdered = DefaultOrder + unsorted_list = "" + /* Build a list of Approver Groups for this package */ + PackageApproverGroups = '' + Do p# = 1 to pkgGrp# + PackageApproverGroup = GROUP_NAME.p# + thisSequence = SEQUENCE.PackageApproverGroup + entry = Right(thisSequence,4,'0') || '.' ||, + PackageApproverGroup + unsorted_list = unsorted_list entry + If TraceRQ = 'Y' then, + Say "unsorted_list=" unsorted_list + End; + + Call SortApproverGroupList; + + If TraceRQ = 'Y' then say "@220 PackageApproverGroups =", + sorted_list, + ' ThisEnvironment =' ThisEnvironment + /* Go through the Sorted list to identify the status */ + /* of the next group(s) to be approved */ + /* Find the 1st Approver group this user belongs to.... */ + thisApprover = USERID() + + lastSequence = NotOrdered + Do seq# = 1 to Words(sorted_list) + entry = Word(sorted_list,seq#) + Parse Var entry thisSequence '.' orderedApproverGroup + orderedGroupStatus = STATUS.orderedApproverGroup + If orderedGroupStatus = 'APPROVED' then Iterate; + orderedGroupQuorum = QUORUM.orderedApproverGroup + If orderedGroupQuorum = 0 then Iterate; + If thisSequence > lastSequence then, + Do + Sa= 'We need to wait' + Leave; + End; + lastSequence = thisSequence + ListApprovers = USRLST.orderedApproverGroup + whereApprover = Wordpos(thisApprover,ListApprovers) + thisApproversFlag = " " + If whereApprover > 0 then, + Do + thisApproverGroup = orderedApproverGroup + thisApproversFlag = Word(APPROVAL_FLAGS.grp#,whereApprover) + End + + If TraceRQ = 'Y' then, + Say orderedApproverGroup 'has status of' orderedGroupStatus, + " Quorum" orderedGroupQuorum + + IF whereApprover > 0 &, + orderedGroupStatus /= 'NotRelated' then, + sa= 'You must wait for the' orderedApproverGroup, + " group's approval" + + If Words(ListApprovers) > 0 then, + Do w# = 1 to Words(ListApprovers) + Approver = Word(ListApprovers,w#) + If Wordpos(Approver,MYSMTP_EMAIL_IDS) = 0 &, + Substr(Approver,1,1) > '00'X then, + MYSMTP_EMAIL_IDS = MYSMTP_EMAIL_IDS Approver + End; /* Do w# = 1 to Words(ListApprovers) */ + + End; /* Do seq# = 1 to Words(sorted_list) */ + + /* Prepare email to the usrids in MYSMTP_EMAIL_IDS */ + Call PrepareEmail + + Return; + +SortApproverGroupList: + + If TraceRQ = 'Y' then Trace ?R + whereami = 'SortApproverGroupList' + sa= words(unsorted_list) unsorted_list; + drop sorted_list; + sorted_list = ""; + do forever ; + if words(unsorted_list) = 0 then leave; + lowest_entry = 1; + do entry = 1 to words(unsorted_list) + if word(unsorted_list,entry) <, + word(unsorted_list,lowest_entry) then, + lowest_entry = entry; + end; /* do entry = 1 .... */ + sorted_list = sorted_list word(unsorted_list,lowest_entry); + sa= "sorted_list=" sorted_list ; + position = wordindex(unsorted_list,lowest_entry) ; + len = length(word(unsorted_list,lowest_entry)); + unsorted_list =, + overlay(copies(" ",len),unsorted_list,position) ; + sa= "unsorted_list=" unsorted_list ; + end; /* do forever */ + drop unsorted_list; + sa= words(sorted_list) sorted_list; + + Return; + +PrepareEmail: + + If TraceRQ = 'Y' then Trace ?R + whereami = 'PrepareEmail' +/* Here you can make last-moment adjustments to the email */ + shortlist = Substr(MYSMTP_EMAIL_IDS,1,100) + If Substr(MYSMTP_EMAIL_IDS,100,1) /= ' ' &, + Substr(MYSMTP_EMAIL_IDS,101,1) /= ' ' then, + Do + whereEnd = WordIndex(shortlist,Words(shortlist)) + shortlist = DELWORD(shortlist,whereEnd) + End + MySMTP_textline.4 = 'Sent to Group:' shortlist + +/* Code in the section below should not be changed */ +/* Code in the section below should not be changed */ +/* Code in the section below should not be changed */ + + MySMTP_Message = Left(MySMTP_Message,80) + hexAddress = D2X(Address_MYSMTP_MESSAGE) + storrep = STORAGE(hexAddress,,Message) + + MySMTP_From = Left(MySMTP_From,50) + hexAddress = D2X(Address_MYSMTP_FROM) + storrep = STORAGE(hexAddress,,MySMTP_From) + + MySMTP_Subject = Left(MySMTP_Subject,50) + hexAddress = D2X(Address_MySMTP_Subject) + storrep = STORAGE(hexAddress,,MySMTP_Subject) + +/* If TraceRQ = 'Y' then Trace ?r */ + MYSMTP_COUNTER = '' + numberLines = Right(MySMTP_textline.0,2,'0') + Do l# = 1 to Length(numberLines) + MYSMTP_COUNTER = MYSMTP_COUNTER ||, + 'F' || Substr(numberLines,l#,1) + End + If TraceRQ = 'Y' then say 'MYSMTP_COUNTER=' MYSMTP_COUNTER + + MYSMTP_TEXT = X2C(MYSMTP_COUNTER) + Do line# = 1 to numberLines + MYSMTP_TEXT = MYSMTP_TEXT || Left(MySMTP_textline.line#,133) + End; /* Do line# = 1 to MySMTP_textline.0 */ + + hexAddress = D2X(Address_MYSMTP_TEXT) + storrep = STORAGE(hexAddress,,MYSMTP_TEXT) + + MySMTP_URL = 'N' + hexAddress = D2X(Address_MYSMTP_URL) + storrep = STORAGE(hexAddress,,MySMTP_URL) + + /* Provide distribution list ( list of userids ) to Exit */ + MYSMTP_EMAIL_IDS =, + Space(Strip(Translate(MYSMTP_EMAIL_IDS,' ','00'x))) + MYSMTP_EMAIL_IDS = MYSMTP_EMAIL_IDS '0000'x + MYSMTP_EMAIL_IDS = Left(MYSMTP_EMAIL_IDS,MYSMTP_EMAIL_ID_SIZE) + hexAddress = D2X(Address_MYSMTP_EMAIL_IDS) + storrep = STORAGE(hexAddress,,MYSMTP_EMAIL_IDS) + + Return; + +SubmitBatchCAST: + + If TraceRQ = 'Y' then Trace ?R + whereami = 'SubmitBatchCAST' + + /* For CASTing a package in Batch */ + /* Build a JCL model, and name its location here.... */ + CastPackageModel = 'YOURSITE.NDVR.TEAM.MODELS(CASTPKGE)' + /* Name a work dataset to be created then deleted... */ + CastPackageJCL = USERID()".C1UEXTR7.SUBMIT" + + "ALLOC F(CASTPKGE) DA('"CastPackageModel"') SHR REUSE" + "Execio * DISKR CASTPKGE (Stem jcl. Finis" + "FREE DD(CASTPKGE)" + + /* Adjust jobcard - only line 1 */ + jcl.1 = Overlay(USERID(),jcl.1,3) + /* If ZACCTNUM is allocated then get Users' Acct number */ + /* ZACCTNUM can optionally be called before C1UEXTR7 */ + /* and provide a User Accounting number. 7 */ + WhatDDName = 'ZACCTNUM' + CALL BPXWDYN "INFO FI("WhatDDName")", + "INRTDSN(DSNVAR) INRDSNT(myDSNT)" + If Substr(DSNVAR,1,1) /= ' ' then, + Do + "EXECIO 1 DISKR ZACCTNUM ( Finis" + Pull ZACCTNUM + ZACCTNUM = Word(Translate(ZACCTNUM,' ',"'"),2) + tail = '(' || ZACCTNUM || '), ' + whereParen = Pos('(', jcl.1) + if whereParen > 0 then, + jcl.1 = Overlay(tail,jcl.1,whereParen) + End + + "ALLOC F(SUBMTJCL) DA('"CastPackageJCL"') ", + "LRECL(80) BLKSIZE(16800) SPACE(5,5)", + "RECFM(F B) TRACKS ", + "MOD CATALOG REUSE " ; + "Execio * DISKW SUBMTJCL (Stem jcl. " + + /* Push Cast command (in reverse order). */ + If PREQ_PKG_CAST_COMPVAL = 'Y' then, + PUSH ' OPTION VALIDATE COMPONENTS .' + Else, + If PREQ_PKG_CAST_COMPVAL = 'W' then, + PUSH ' OPTION VALIDATE COMPONENT WITH WARNING .' + Else, + PUSH ' OPTION DO NOT VALIDATE COMPONENT .' + PUSH " CAST PACKAGE '" || PECB_PACKAGE_ID || "'" + "Execio 2 DISKW SUBMTJCL ( finis" + + Call Submit_n_save_jobInfo ; + "FREE F(SUBMTJCL) DELETE " + Message = JobData + MyRc = 8 + PACKAGE = PECB_PACKAGE_ID + MessageCode = 'U033' + Call SetExitReturnInfo + + Return; + +Submit_n_save_jobInfo: /* submit CastPackageModel job and save job info */ + + If TraceRQ = 'Y' then Trace ?R + whereami = 'Submit_n_save_jobInfo' + If TraceRQ = 'Y' then Say 'Submit_n_save_jobInfo:' + + Address TSO "PROFILE NOINTERCOM" /* turn off msg notific */ + CALL MSG "ON" + CALL OUTTRAP "out." + ADDRESS TSO "SUBMIT '"CastPackageJCL"'" ; + If RC > 4 then, + Do + MyRC = 8 + Message = 'Cannot find Element member to submit.' + Call SetExitReturnInfo + Exit(12) + End + CALL OUTTRAP "OFF" + Address TSO "PROFILE INTERCOM" /* turn on msg notific */ + + JobData = Strip(out.1); + jobinfo = Word(JobData,2) ; + If jobinfo = 'JOB' then, + jobinfo = Word(JobData,3) ; + SelectJobName = Word(Translate(jobinfo,' ',')('),1) ; + SelectJobNumber = Word(Translate(jobinfo,' ',')('),2) ; + + Return; + +SetExitReturnInfo: + + If TraceRQ = 'Y' then Trace ?R + whereami = 'SetExitReturnInfo' + If TraceRQ = 'Y' then Say 'SetExitReturnInfo: ' + + hexAddress = D2X(Address_PECB_MESSAGE) + storrep = STORAGE(hexAddress,,Message) + hexAddress = D2X(Address_PECB_ERROR_MESS_LENGTH) + storrep = STORAGE(hexAddress,,'0084'X) + hexAddress = D2X(Address_PECB_MODS_MADE_TO_PREQ) + storrep = STORAGE(hexAddress,,'Y') + + If MessageCode /= ' ' then, + Do + hexAddress = D2X(Address_PECB_MESSAGE_ID) + storrep = STORAGE(hexAddress,,MessageCode) + End + + +/* Set the return code for the exit */ +/* for PECB-NDVR-EXIT-RC */ + hexAddress = D2X(Address_PECB_NDVR_EXIT_RC) + If MyRc = 4 then, + storrep = STORAGE(hexAddress,,'00000004'X) + Else, + storrep = STORAGE(hexAddress,,'00000008'X) + + RETURN ; + + +./ ADD NAME=C1UEXTT7 + PROCESS DYNAM OUTDD(DISPLAYS) + IDENTIFICATION DIVISION. + PROGRAM-ID. C1UEXT07. + ***************************************************************** + * DESCRIPTION: THIS PGM IS CALLED for misc Package actions. + * It gathers Endevor info from the exit blocks * + * then calls REXX program C1UEXTR7. * + * Together they can force CAST actions to be in Batch. * + ***************************************************************** + ENVIRONMENT DIVISION. + INPUT-OUTPUT SECTION. + FILE-CONTROL. + ** + DATA DIVISION. + FILE SECTION. + + WORKING-STORAGE SECTION. + + COPY NOTIFYDS. + + 01 WS-VGET PIC X(8) VALUE 'VGET '. + 01 WS-PROFILE PIC X(8) VALUE 'PROFILE '. + 01 WS-ISPLINK PIC X(8) VALUE 'ISPLINK ' . + + 01 WS-C1BJC1-JOBCARD PIC X(80) . + 01 WS-C1BJC1 PIC X(08) VALUE '(C1BJC1)'. + + 01 WS-C1PJC1-JOBCARD PIC X(80) . + 01 WS-C1PJC1 PIC X(08) VALUE '(C1PJC1)'. + + 01 WS-CALLING-REASON PIC X(24). + + 01 WS-VARIABLES. + 03 WS-POINTER PIC 9(09) COMP. + 03 WS-WORK-ADDRESS-ADR PIC 9(09) COMP SYNC . + 03 WS-WORK-ADDRESS-PTR REDEFINES WS-WORK-ADDRESS-ADR + USAGE IS POINTER . + + 03 WS-PECB-REQUEST-RETURNCODE PIC 9999 . + 03 WS-PECB-NDVR-HIGH-RC PIC 9999 . + + 03 WS-DISPLAY-NUMBER-FOR4 PIC 9(04) . + 03 WS-DISPLAY-NUMBER-FOR9 PIC 9(09) . + 00490200 + 01 PGM PIC X(8). + 01 MYSMTP-MESSAGE PIC X(80). + 01 MYSMTP-USERID PIC X(8). + 01 MYSMTP-FROM PIC X(50). + 01 MYSMTP-SUBJECT PIC X(50). + 01 MYSMTP-TEXT. + 03 MYSMTP-COUNTER PIC 9(2). + 03 MYSMTP-MSG-TEXT. + 05 MYSMTP-LINE PIC X(133) OCCURS 99. + 01 MYSMTP-URL PIC X(1). + 01 MYSMTP-EMAIL-IDS. + 03 FILLER PIC X(09) + OCCURS 320 . + 03 FILLER PIC X(8). + 01 MYSMTP-EMAIL-ID-SIZE PIC 9(8). + + 01 WS-ADDRESSES. + 03 ADDRESS-MYSMTP-MESSAGE PIC 9(09) . + 03 ADDRESS-MYSMTP-USERID PIC 9(09) . + 03 ADDRESS-MYSMTP-FROM PIC 9(09) . + 03 ADDRESS-MYSMTP-SUBJECT PIC 9(09) . + 03 ADDRESS-MYSMTP-TEXT PIC 9(09) . + 03 ADDRESS-MYSMTP-URL PIC 9(09) . + 03 ADDRESS-MYSMTP-EMAIL-IDS PIC 9(09) . + 00510000 + 03 ADDRESS-PECB-NDVR-EXIT-RC PIC 9(09) . + 03 ADDRESS-PECB-MESSAGE-ID PIC 9(09) . + 03 ADDRESS-PECB-MESSAGE PIC 9(09) . + 03 ADDRESS-PECB-ERROR-MESS-LENGTH PIC 9(09) . + 03 ADDRESS-PECB-MODS-MADE-TO-PREQ PIC 9(09) . + 03 ADDRESS-PREQ-SHARE-ENABLED PIC 9(09) . + 03 ADDRESS-PREQ-BACKOUT-ENABLED PIC 9(09) . + + 01 BPXWDYN PIC X(8) VALUE 'BPXWDYN'. + 01 ALLOC-STRING. + 05 ALLOC-LENGTH PIC S9(4) BINARY VALUE 100. + 05 ALLOC-TEXT PIC X(100). + + 01 IRXJCL PIC X(6) VALUE 'IRXJCL'. + 01 IRXEXEC-PGM PIC X(08) VALUE 'IRXEXEC'. + + * + * DEFINE THE IRXEXEC DATA AREAS AND ARG BLOCKS + * + 77 WS-INX PIC 9(08) COMP . + 77 FLAGS PIC S9(8) BINARY. + 77 REXX-RETURN-CODE PIC S9(8) BINARY. + 77 DUMMY-ZERO PIC S9(8) BINARY. + 77 LPAR-ID PIC X(04). + 88 DO-NOT-PROCESS-LPAR VALUE 'SKIP'. + 77 ARG1 PIC X(16). + 77 UPDPRINT-FILE-STATUS PIC X(02). + 77 ARGUMENT-PTR POINTER. + 77 EXECBLK-PTR POINTER. + 77 ARGTABLE-PTR POINTER. + 77 EVALBLK-PTR POINTER. + 77 TEMP-PTR POINTER. + + 01 EXECBLK. + 05 EXECBLK-ACRYN PIC X(08) VALUE 'IRXEXECB'. + 05 EXECBLK-LENGTH PIC S9(8) BINARY + VALUE 48. + 05 EXECBLK-RESERVED PIC S9(8) BINARY + VALUE 0. + 05 EXECBLK-MEMBER PIC X(08) VALUE 'C1UEXTR7'. + 05 EXECBLK-DDNAME PIC X(08) VALUE 'REXFILE7'. + 05 EXECBLK-SUBCOM PIC X(08) VALUE SPACES. + 05 EXECBLK-DSNPTR POINTER VALUE NULL. + 05 EXECBLK-DSNLEN PIC 9(04) COMP + VALUE 0. + + 01 EVALBLK. + 05 EVALBLK-EVPAD1 PIC S9(8) BINARY + VALUE 0. + 05 EVALBLK-EVSIZE PIC S9(8) BINARY + VALUE 34. + 05 EVALBLK-EVLEN PIC S9(8) BINARY + VALUE 0. + 05 EVALBLK-EVPAD2 PIC S9(8) BINARY + VALUE 0. + 05 EVALBLK-EVDATA PIC X(256). + + 01 ARGUMENT. + 02 ARGUMENT-1 OCCURS 1 TIMES. + 05 ARGSTRING-PTR POINTER. + 05 ARGSTRING-LENGTH PIC S9(8) BINARY. + 02 ARGSTRING-LAST1 PIC S9(8) BINARY + VALUE -1. + 02 ARGSTRING-LAST2 PIC S9(8) BINARY + VALUE -1. + + * The block of data below can be used with either an + * IRXJCL or IRXEXEC call to the rexx program C1UEXTR7. + * IRXJCL is used when running in batch (batch CAST) . + * IRXEXEC is used when running in foreground (CAST or APPROVE). + 01 PKG-C1UEXTR7-PARMS-IRXJCL. + 02 PKG-C1UEXTR7-PARMS-IRXJCL-TOP. + 03 PARM-LENGTH PIC X(2) VALUE X'0BC1'. + 03 REXX-NAME PIC X(8) VALUE 'C1UEXTR7'. + 03 FILLER PIC X(1) VALUE SPACE . + 02 PKG-C1UEXTR7-PARMS-IRXEXEC. + 03 WS-REXX-STATEMENTS PIC X(3000). + + LINKAGE SECTION. + COPY PKGXBLKS. + + PROCEDURE DIVISION USING + PACKAGE-EXIT-BLOCK + PACKAGE-REQUEST-BLOCK + PACKAGE-EXIT-HEADER-BLOCK + PACKAGE-EXIT-FILE-BLOCK + PACKAGE-EXIT-ACTION-BLOCK + PACKAGE-EXIT-APPROVER-MAP + PACKAGE-EXIT-BACKOUT-BLOCK + PACKAGE-EXIT-SHIPMENT-BLOCK + PACKAGE-EXIT-SCL-BLOCK. + **** + IF PECB-USER-BATCH-JOBNAME(1:7) NOT = 'IBMUSER' AND + PECB-USER-BATCH-JOBNAME(1:7) NOT = 'PL05958' + GOBACK. + **** + +********* DISPLAY 'C1UEXT07: GOT INTO C1UEXTT7'. +********* MOVE PECB-FUNCTION-CODE TO WS-DISPLAY-NUMBER-FOR9. +********* DISPLAY 'PECB-FUNCTION-CODE=' WS-DISPLAY-NUMBER-FOR9. + + IF SETUP-EXIT-OPTIONS + MOVE ZERO TO PECB-UEXIT-HOLD-FIELD +********* to enforce package create rules + MOVE 'Y' TO PECB-BEFORE-CREATE-BLD + MOVE 'Y' TO PECB-BEFORE-CREATE-COPY + MOVE 'Y' TO PECB-BEFORE-CREATE-EDIT + MOVE 'Y' TO PECB-BEFORE-CREATE-IMPT + MOVE 'Y' TO PECB-BEFORE-REV-APPR +********* to enforce Approver Group Sequencing + MOVE 'Y' TO PECB-AFTER-REV-APPR +********* to enforce package backout = Y + MOVE 'Y' TO PECB-BEFORE-CAST +********* to enforce Approver Group Sequencing + MOVE 'Y' TO PECB-AFTER-CAST +********* MOVE 'Y' TO PECB-MID-CAST +********* MOVE 'Y' TO PECB-BEFORE-MOD-IMPT +********* MOVE 'Y' TO PECB-AFTER-RESET +********* MOVE 'Y' TO PECB-AFTER-DELETE + MOVE ZEROS TO RETURN-CODE + GOBACK. + + MOVE 0 TO PECB-NDVR-EXIT-RC. + MOVE SPACES TO WS-REXX-STATEMENTS . + +********* If just starting out, request Approver Group info + IF PECB-REQUEST-RETURNCODE = 0 AND PECB-AFTER AND + (CAST-PACKAGE OR REVIEW-PACKAGE) + PERFORM 1000-ALLOCATE-REXFILE + MOVE 'Y' TO PECB-REQ-APPROVER-REC + GOBACK + ELSE +********* If Before the CAST, just pass Package info to the REXX + IF PECB-BEFORE AND + (CREATE-PACKAGE OR CAST-PACKAGE) + IF CREATE-PACKAGE + MOVE 'Before CREATE' TO WS-CALLING-REASON + ELSE + MOVE 'Before CAST' TO WS-CALLING-REASON + END-IF + PERFORM 1000-ALLOCATE-REXFILE + PERFORM 0500-CALL-C1UEXTR7-REXX + PERFORM 2000-FREE-REXFILES + GOBACK + END-IF . + +********* If we just received an Appprover Group block, +********* pass it to the REXX and ask for more... + IF PECB-SUCCESSFUL-RECORD-SENT + MOVE PAPP-SEQUENCE-NUMBER TO WS-DISPLAY-NUMBER-FOR4 + MOVE SPACES TO WS-CALLING-REASON + STRING 'Approver Group #' + WS-DISPLAY-NUMBER-FOR4 + DELIMITED BY SIZE + INTO WS-CALLING-REASON + END-STRING + PERFORM 0500-CALL-C1UEXTR7-REXX + MOVE 'Y' TO PECB-REQ-APPROVER-REC + GOBACK + END-IF . + +********* Endevor says 'no more Appprover Group blocks' +********* tell REXX and let it decide on email + IF PECB-END-OF-FILE-FOR-REC-TYP OR + PECB-NO-RECORDS-FOUND + MOVE 'NO MORE Approver Grps ' TO WS-CALLING-REASON + PERFORM 0500-CALL-C1UEXTR7-REXX + IF MYSMTP-COUNTER NUMERIC AND + MYSMTP-COUNTER GREATER THAN '00' AND + MYSMTP-EMAIL-IDS(1:1) GREATER THAN SPACE + MOVE 'BC1PMLIF' TO PGM + PERFORM 0900-SEND-EMAILS + END-IF + PERFORM 2000-FREE-REXFILES + GOBACK + END-IF . + + + 0100-MAIN-EXIT. + GOBACK. + + 0500-CALL-C1UEXTR7-REXX. + + * Give addresses of updatable fields to the REXX. + * MAKES A CALL TO THE REXX ROUTINE C1UEXTR7. + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-MESSAGE . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-MYSMTP-MESSAGE. + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-USERID . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-MYSMTP-USERID . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-FROM . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-MYSMTP-FROM . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-SUBJECT . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-MYSMTP-SUBJECT. + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-TEXT . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-MYSMTP-TEXT . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-URL . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-MYSMTP-URL . + + MOVE SPACES TO MYSMTP-EMAIL-IDS . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-EMAIL-IDS . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-MYSMTP-EMAIL-IDS . + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF MYSMTP-EMAIL-ID-SIZE . + COMPUTE MYSMTP-EMAIL-ID-SIZE = + WS-WORK-ADDRESS-ADR - 4 - + ADDRESS-MYSMTP-EMAIL-IDS . + + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF PECB-NDVR-EXIT-RC . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-PECB-NDVR-EXIT-RC. + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF PECB-MESSAGE . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-PECB-MESSAGE . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF PECB-ERROR-MESS-LENGTH . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-PECB-ERROR-MESS-LENGTH. + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF PECB-MODS-MADE-TO-PREQ . + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-PECB-MODS-MADE-TO-PREQ. + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF PECB-MESSAGE-ID. + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-PECB-MESSAGE-ID . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF PREQ-SHARE-ENABLED. + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-PREQ-SHARE-ENABLED . + + SET WS-WORK-ADDRESS-PTR TO + ADDRESS OF PREQ-BACKOUT-ENABLED. + MOVE WS-WORK-ADDRESS-ADR + TO ADDRESS-PREQ-BACKOUT-ENABLED . + + MOVE PECB-REQUEST-RETURNCODE TO + WS-PECB-REQUEST-RETURNCODE. + + MOVE PECB-NDVR-HIGH-RC TO + WS-PECB-NDVR-HIGH-RC . + + ***** + ***** / Convert COBOL exit block Datanames into Rexx \ + ***** + ***** + MOVE 1 TO WS-POINTER. + + STRING + 'PECB_PACKAGE_ID = "' PECB-PACKAGE-ID '";' + 'PECB_FUNCTION_LITERAL="' PECB-FUNCTION-LITERAL '";' + 'PECB_SUBFUNC_LITERAL="' PECB-SUBFUNC-LITERAL '";' + 'PECB_BEF_AFTER_LITERAL="' PECB-BEF-AFTER-LITERAL '";' + 'PECB_USER_BATCH_JOBNAME="' PECB-USER-BATCH-JOBNAME '";' + 'PREQ_PKG_CAST_COMPVAL="' PREQ-PKG-CAST-COMPVAL '";' + 'PHDR_PKG_SHR_OPTION ="' PHDR-PKG-SHR-OPTION '";' + 'PHDR_PKG_ENV ="' PHDR-PKG-ENV '";' + 'PHDR_PKG_STGID ="' PHDR-PKG-STGID '";' + 'PECB_MODE = "' PECB-MODE '";' + 'PECB_AUTOCAST ="' PECB-AUTOCAST '";' + 'PECB_REQUEST_RETURNCODE=' WS-PECB-REQUEST-RETURNCODE ';' + 'PECB_NDVR_HIGH_RC = ' WS-PECB-NDVR-HIGH-RC ';' + 'PREQ_BACKOUT_ENABLED="' PREQ-BACKOUT-ENABLED '";' + 'Address_PREQ_BACKOUT_ENABLED=' + ADDRESS-PREQ-BACKOUT-ENABLED ';' + 'PREQ_SHARE_ENABLED="' PREQ-SHARE-ENABLED '";' + 'Address_PREQ_SHARE_ENABLED=' + ADDRESS-PREQ-SHARE-ENABLED ';' + 'Address_PECB_MODS_MADE_TO_PREQ=' + ADDRESS-PECB-MODS-MADE-TO-PREQ ';' + 'Address_PECB_NDVR_EXIT_RC=' + ADDRESS-PECB-NDVR-EXIT-RC ';' + 'Address_PECB_MESSAGE_ID=' ADDRESS-PECB-MESSAGE-ID ';' + 'Address_PECB_ERROR_MESS_LENGTH = ' + ADDRESS-PECB-ERROR-MESS-LENGTH ';' + 'Address_PECB_MESSAGE = ' ADDRESS-PECB-MESSAGE ';' + 'Address_MYSMTP_MESSAGE=' ADDRESS-MYSMTP-MESSAGE ';' + 'Address_MYSMTP_USERID =' ADDRESS-MYSMTP-USERID ';' + 'Address_MYSMTP_FROM =' ADDRESS-MYSMTP-FROM ';' + 'Address_MYSMTP_SUBJECT=' ADDRESS-MYSMTP-SUBJECT ';' + 'Address_MYSMTP_TEXT =' ADDRESS-MYSMTP-TEXT ';' + 'Address_MYSMTP_URL =' ADDRESS-MYSMTP-URL ';' + 'Address_MYSMTP_EMAIL_IDS=' + ADDRESS-MYSMTP-EMAIL-IDS ';' + 'MYSMTP_EMAIL_ID_SIZE=' + MYSMTP-EMAIL-ID-SIZE ';' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER . + +********* For these text fields, make sure none use a double quote +********* character. This ensures the integrity of the REXX + IF REVIEW-PACKAGE OR + (CAST-PACKAGE AND PECB-AFTER) + MOVE PAPP-QUORUM-COUNT TO WS-DISPLAY-NUMBER-FOR4 + STRING + 'CALL_REASON="' WS-CALLING-REASON '";' + 'PAPP_GROUP_NAME ="' PAPP-GROUP-NAME '";' + 'PAPP_GROUP_NAME ="' PAPP-GROUP-NAME '";' + 'PAPP_ENVIRONMENT="' PAPP-ENVIRONMENT '";' + 'PAPP_QUORUM_COUNT="' WS-DISPLAY-NUMBER-FOR4 '";' + 'PAPP_APPROVER_FLAG="' PAPP-APPROVER-FLAG '";' + 'PAPP_APPR_GRP_TYPE="' PAPP-APPR-GRP-TYPE '";' + 'PAPP_APPR_GRP_DISQ="' PAPP-APPR-GRP-DISQ '";' + DELIMITED BY SIZE + 'PAPP_APPROVAL_IDS= "' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + PERFORM VARYING WS-INX FROM 1 BY 1 UNTIL + WS-INX GREATER THAN PAPP-APPROVER-NUMBER + STRING PAPP-APPROVAL-ID(WS-INX) ' ' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + END-PERFORM + STRING '";' + 'PAPP_APPROVAL_FLAGS= "' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + + PERFORM VARYING WS-INX FROM 1 BY 1 UNTIL + WS-INX GREATER THAN PAPP-APPROVER-NUMBER + STRING PAPP-APPROVAL-FLAG(WS-INX) ' ' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + END-PERFORM + STRING '";' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + END-IF. + +******* Replace any double quote characters in data to be passed + IF CAST-PACKAGE + INSPECT PREQ-PACKAGE-COMMENT REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE1 REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE2 REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE3 REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE4 REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE5 REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE6 REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE7 REPLACING ALL '"' BY X'7D' + INSPECT PHDR-PKG-NOTE8 REPLACING ALL '"' BY X'7D' + STRING + 'CALL_REASON="' WS-CALLING-REASON '";' + 'PREQ_PACKAGE_COMMENT = "' PREQ-PACKAGE-COMMENT '";' + 'PHDR_PACKAGE_TYPE = "' PHDR-PACKAGE-TYPE '";' + 'PHDR_PACKAGE_STATUS = "' PHDR-PACKAGE-STATUS '";' + 'PHDR_PKG_BACKOUT_STATUS="' PHDR-PKG-BACKOUT-STATUS '";' + 'PHDR_PKG_CREATE_USER = "' PHDR-PKG-CREATE-USER '";' + 'PHDR_PKG_CAST_USER = "' PHDR-PKG-CAST-USER '";' + 'PHDR_PKG_NOTE1 = "' PHDR-PKG-NOTE1 '";' + 'PHDR_PKG_NOTE2 = "' PHDR-PKG-NOTE2 '";' + 'PHDR_PKG_NOTE3 = "' PHDR-PKG-NOTE3 '";' + 'PHDR_PKG_NOTE4 = "' PHDR-PKG-NOTE4 '";' + 'PHDR_PKG_NOTE5 = "' PHDR-PKG-NOTE5 '";' + 'PHDR_PKG_NOTE6 = "' PHDR-PKG-NOTE6 '";' + 'PHDR_PKG_NOTE7 = "' PHDR-PKG-NOTE7 '";' + 'PHDR_PKG_NOTE8 = "' PHDR-PKG-NOTE8 '";' + 'PHDR_PKG_CAST_COMPVAL = "' PHDR-PKG-CAST-COMPVAL '";' + DELIMITED BY SIZE + INTO WS-REXX-STATEMENTS + WITH POINTER WS-POINTER + END-STRING + END-IF. + + ***** \ Convert COBOL exit block Datanames into Rexx / + ***** + + MOVE 'C1UEXTR7' TO EXECBLK-MEMBER . + MOVE 3000 TO ARGSTRING-LENGTH(1) + + IF PECB-TSO-MODE + CALL 'SET-ARG1-POINTER' USING ARGUMENT-PTR + PKG-C1UEXTR7-PARMS-IRXEXEC + PERFORM 0800-REXX-CALL-VIA-IRXEXEC + MOVE 0 TO PECB-NDVR-HIGH-RC + ELSE +********* DISPLAY 'C1UEXT07: Running in Batch ' + CALL IRXJCL USING PKG-C1UEXTR7-PARMS-IRXJCL . + + IF RETURN-CODE NOT = 0 + DISPLAY 'C1UEXT07: BAD CALL TO IRXJCL - RC = ' + RETURN-CODE + END-IF + + MOVE 0 TO RETURN-CODE + . + 0800-REXX-CALL-VIA-IRXEXEC. + *--- GET THE ADDRESS OF THE ARGUMENT(S) TO BE PASSED TO IXREXEC + *--- AND LOAD INTO THE ARGUMENT TABLES +******* IF PECB-USER-BATCH-JOBNAME(1:7) = 'PL05958' +******* DISPLAY 'C1UEXT07: SETTING UP REXX EXECUTION' +******* ' FOR PACKAGE 'PECB-PACKAGE-ID +******* END-IF . + SET ARGSTRING-PTR (1) TO ARGUMENT-PTR . + CALL 'SET-ARGUMENT-POINTER' USING ARGTABLE-PTR + ARGUMENT . + CALL 'SET-EXECBLK-POINTER' USING EXECBLK-PTR + EXECBLK . + CALL 'SET-EVALBLK-POINTER' USING EVALBLK-PTR + EVALBLK . + *--- SET FLAGS TO HEX 20000000 + * I.E. EXEC INVOKED AS SUBROUTINE + MOVE 536870912 TO FLAGS + MOVE 0 TO REXX-RETURN-CODE . + +********* DISPLAY 'C1UEXT07: CALLING IRXEXC ' +********* PECB-PACKAGE-ID . + *--- CALL THE REXX EXEC --- + CALL IRXEXEC-PGM USING EXECBLK-PTR + ARGTABLE-PTR + FLAGS + DUMMY-ZERO + DUMMY-ZERO + EVALBLK-PTR + DUMMY-ZERO + DUMMY-ZERO + DUMMY-ZERO . + + IF REXX-RETURN-CODE NOT = 0 + DISPLAY 'C1UEXT07: IRXEXEC RETURN CODE = ' + REXX-RETURN-CODE + END-IF + + CANCEL IRXEXEC-PGM + . + + 0900-SEND-EMAILS. + +********** DISPLAY 'C1UEXTT7: MYSMTP-MESSAGE=' MYSMTP-MESSAGE . +********** DISPLAY 'C1UEXTT7: MYSMTP-FROM =' MYSMTP-FROM . +********** DISPLAY 'C1UEXTT7: MYSMTP-SUBJECT=' MYSMTP-SUBJECT . +********** DISPLAY 'C1UEXTT7: MYSMTP-TEXT ' MYSMTP-TEXT(1:80). + + MOVE 1 TO WS-POINTER. + + PERFORM UNTIL + MYSMTP-EMAIL-IDS(WS-POINTER:1) = LOW-VALUES OR + MYSMTP-EMAIL-IDS(WS-POINTER:8) + LESS THAN OR EQUAL SPACES OR + WS-POINTER GREATER THAN OR EQUAL + MYSMTP-EMAIL-ID-SIZE + MOVE SPACES TO MYSMTP-USERID + UNSTRING MYSMTP-EMAIL-IDS + DELIMITED BY SPACE + INTO MYSMTP-USERID + WITH POINTER WS-POINTER + END-UNSTRING + + IF MYSMTP-USERID NOT = SPACES +********** DISPLAY 'C1UEXTT7: Emailing ' MYSMTP-USERID +********** ' WS-POINTER=' WS-POINTER ' ' +********** MYSMTP-EMAIL-IDS(WS-POINTER:60) + CALL PGM USING MYSMTP-MESSAGE + MYSMTP-USERID + MYSMTP-FROM + MYSMTP-SUBJECT + MYSMTP-TEXT + MYSMTP-URL + END-IF + + IF RETURN-CODE > 0 + DISPLAY 'CALL BC1PMLIF RC = ' RETURN-CODE + DISPLAY MYSMTP-MESSAGE + END-IF +********** ADD 1 TO WS-POINTER + END-PERFORM. + + *----------------------------------------------------------------- + + 1000-ALLOCATE-REXFILE. + + MOVE SPACES TO ALLOC-TEXT. + + IF PECB-BATCH-MODE + STRING 'ALLOC DD(SYSEXEC) ', + 'DA(YOURSITE.NDVR.REXX)' + DELIMITED BY SIZE + ' SHR REUSE' + DELIMITED BY SIZE + INTO ALLOC-TEXT + END-STRING + ELSE + STRING 'ALLOC DD(REXFILE7) ', + 'DA(YOURSITE.NDVR.REXX)' + DELIMITED BY SIZE + ' SHR REUSE' + DELIMITED BY SIZE + INTO ALLOC-TEXT + END-STRING + END-IF. + + PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . + +********** MOVE 'CONCAT DDLIST(REXFILE,REXFILE2)' +********** TO ALLOC-TEXT . +********** +********** PERFORM 9000-DYNAMIC-ALLOC-DEALLOC . + + ***************************************************************** + ** DYNAMICALLY DE-ALLOCATE UNNEEDED REXX FILES + ***************************************************************** + 2000-FREE-REXFILES. + + MOVE SPACES TO ALLOC-TEXT. + + IF PECB-BATCH-MODE + MOVE 'FREE DD(SYSEXEC)' TO ALLOC-TEXT + ELSE + MOVE 'FREE DD(REXFILE7)' TO ALLOC-TEXT + END-IF. + + + PERFORM 9000-DYNAMIC-ALLOC-DEALLOC + . + ***************************************************************** + ** CALL BPXWDYN TO PREFORM REQUIRED REXX FUNCTIONS + ***************************************************************** + 9000-DYNAMIC-ALLOC-DEALLOC. + + CALL BPXWDYN USING ALLOC-STRING + + IF RETURN-CODE NOT = ZERO + DISPLAY 'C1UEXT07: ALLOCATION FAILED: RETURN CODE = ' + RETURN-CODE + DISPLAY ALLOC-TEXT + END-IF + +********* DISPLAY ALLOC-TEXT . + MOVE SPACES TO ALLOC-TEXT + . + + + ****************************************************************** + * BEGIN NESTED PROGRAMS USED TO SET THE POINTERS OF DATA AREAS + * THAT ARE BEING PASSED TO IRXEXEC SO THAT A REXX ROUTINE CAN + * PASS DATA (OTHER THAN A RETURN CODE) BACK TO A COBOL PROGRAM. + ****************************************************************** + + ******** SET-ARG1-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-ARG1-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 ARG-PTR POINTER. + 77 ARG1 PIC X(16). + PROCEDURE DIVISION USING ARG-PTR + ARG1. + SET ARG-PTR TO ADDRESS OF ARG1 + GOBACK. + END PROGRAM SET-ARG1-POINTER. + + ******** SET-ARGUMENT-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-ARGUMENT-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 ARGTABLE-PTR POINTER. + 01 ARGUMENT. + 02 ARGUMENT-1 OCCURS 1 TIMES. + 05 ARGSTRING-PTR POINTER. + 05 ARGSTRING-LENGTH PIC S9(8) BINARY. + 02 ARGSTRING-LAST1 PIC S9(8) BINARY. + 02 ARGSTRING-LAST2 PIC S9(8) BINARY. + PROCEDURE DIVISION USING ARGTABLE-PTR + ARGUMENT. + SET ARGTABLE-PTR TO ADDRESS OF ARGUMENT + GOBACK. + END PROGRAM SET-ARGUMENT-POINTER. + + ******** SET-EXECBLK-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-EXECBLK-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 EXECBLK-PTR POINTER. + 01 EXECBLK. + 03 EXECBLK-ACRYN PIC X(8). + 03 EXECBLK-LENGTH PIC 9(4) COMP. + 03 EXECBLK-RESERVED PIC 9(4) COMP. + 03 EXECBLK-MEMBER PIC X(8). + 03 EXECBLK-DDNAME PIC X(8). + 03 EXECBLK-SUBCOM PIC X(8). + 03 EXECBLK-DSNPTR POINTER. + 03 EXECBLK-DSNLEN PIC 9(4) COMP. + PROCEDURE DIVISION USING EXECBLK-PTR + EXECBLK. + SET EXECBLK-PTR TO ADDRESS OF EXECBLK + GOBACK. + END PROGRAM SET-EXECBLK-POINTER. + + ******** SET-EVALBLK-POINTER ******** + IDENTIFICATION DIVISION. + PROGRAM-ID. SET-EVALBLK-POINTER. + ENVIRONMENT DIVISION. + DATA DIVISION. + WORKING-STORAGE SECTION. + LINKAGE SECTION. + 77 EVALBLK-PTR POINTER. + 01 EVALBLK. + 03 EVALBLK-EVPAD1 PIC 9(4) COMP. + 03 EVALBLK-EVSIZE PIC 9(4) COMP. + 03 EVALBLK-EVLEN PIC 9(4) COMP. + 03 EVALBLK-EVPAD2 PIC 9(4) COMP. + 03 EVALBLK-EVDATA PIC X(256). + PROCEDURE DIVISION USING EVALBLK-PTR + EVALBLK. + SET EVALBLK-PTR TO ADDRESS OF EVALBLK + GOBACK. + END PROGRAM SET-EVALBLK-POINTER. + *--- END OF MAIN PROGRAM + END PROGRAM C1UEXT07. + +./ ADD NAME=SERVICPY +# +import os #Import standard Python os lib +import platform #Import standard Python platform lib +import sys #Import standard Python sys lib +import requests +from requests.auth import HTTPBasicAuth +import json + +## Build the complete url here +print("#Arguments:", sys.argv[1:]) # Additional arguments passed +listticketnumber = sys.argv[1:2] +print("#listticketnumber :", type(listticketnumber), listticketnumber) +ticketnumber = listticketnumber[0] +ticketnumberType = type(ticketnumber) +mySubstring = ticketnumber[0:3] # does a substring +# +url = "https://your.service-now.com/api/now/table" +if mySubstring == 'PRB': + print('problem ticket query') + url = url + "/problem?sysparm_query=" +else: + print('Change ticket query') + url = url + "/change_request?sysparm_query=" +# +url = url + ticketnumber +print("#url:", url) # complete url +# +response = requests.get(url, auth=HTTPBasicAuth('admin', 'passw')) +print(response.content) +out = json.loads(response.content) +n = out['result'] + +# +typeout = type(out) +typen = type(n) +print("#n type", typen) +print("#out type", typeout) +# + +if len(n) == 0: + print("error - no output") +elif "number" in n[0].keys(): + print("Exists") +else: + print("error - not found") + + +./ ADD NAME=SNINCQRY + +./ ADD NAME=SNOW@JCL +//IBMUSERS JOB (0000), +// CLASS=A,MSGCLASS=X,REGION=4M, +// NOTIFY=&SYSUID +//*==================================================================* +// SET C1CCID=PRB0000014 +// SET C1CCID=CHG0040007 +//*==================================================================* +//* STEP 1 -- Execute REXX -> Python -> ServiceNow +//*------------------------------------------------------------------- +//STEP1 EXEC PGM=IRXJCL,PARM='SNOWQERY &C1CCID' +//SYSEXEC DD DISP=SHR,DSN=YOURSITE.NDVR.TEAM.REXX +//SYSTSIN DD DUMMY +//SYSTSPRT DD SYSOUT=* +//STDERR DD SYSOUT=* +//*-------------------------------------------------------------------- + +./ ADD NAME=SNOWQERY +/* REXX */ + Trace ?R + Arg REQ_CCID . + If Substr(REQ_CCID,1,3) = 'PRB' |, + Substr(REQ_CCID,1,3) = 'CHG' then Call Validate_CCID; + Exit + +Validate_CCID: + + /* build STDENV input */ + CALL BPXWDYN , + "ALLOC DD(STDENV) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "EXPORT PATH=$PATH:" ||, + "'/usr/lpp/IBM/cyp/v3r11/pyz/lib/python3.11/'" + Queue "EXPORT VIRTUAL_ENV=" ||, + "'/u/users/NDVRTeam/venv/lib/python3.11/site-packages/'" + "EXECIO 2 DISKW STDENV (finis" + + /* build BPXBATCH inputs and outputs */ + /* build STDPARM input */ + CALL BPXWDYN , + "ALLOC DD(STDPARM) LRECL(080) BLKSIZE(24000) SPACE(1,1) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Queue "sh cd " ||, + "/u/users/NDVRTeam/venv/lib/python3.11/site-packages;" + Queue "python ServiceNow.py" REQ_CCID + "EXECIO 2 DISKW STDPARM (finis" + + CALL BPXWDYN , + "ALLOC DD(STDOUT) LRECL(200) BLKSIZE(20000) SPACE(5,5) ", + " RECFM(F,B) TRACKS ", + " NEW UNCATALOG REUSE "; + Notnow =, + "ALLOC DD(STDOUT) DA('IBMUSER.STDOUT') OLD REUSE " + + CALL BPXWDYN "ALLOC DD(STDIN) DUMMY SHR REUSE" + CALL BPXWDYN "ALLOC DD(STDERR) DA(*) SHR REUSE" + + ADDRESS LINK 'BPXBATCH' + + "EXECIO * DISKR STDOUT (Stem stdout. finis" + lastrec# = stdout.0 + lastrecord = Substr(stdout.lastrec#,1,40) + + If Pos("Exists",lastrecord) = 0 then, + Do + Message = 'C1UEXTR2 - CCID ' REQ_CCID ||, + ' is not defined to Service-Now' + MessageCode = 'U012' + MyRc = 8 + End + + CALL BPXWDYN "FREE DD(STDENV) " + CALL BPXWDYN "FREE DD(STDPARM)" + CALL BPXWDYN "FREE DD(STDOUT) " + CALL BPXWDYN "FREE DD(STDIN) " + CALL BPXWDYN "FREE DD(STDERR) " + + Return; + + +./ ADD NAME=C1X2CUST + ******************************************************************00110000 + IDENTIFICATION DIVISION. + ******************************************************************00110000 + + PROGRAM-ID. C1X2JPMC. + AUTHOR. (C) 2025 Broadcom + Jose Benigno Gonzalez for JPCM. + + ****************************************************************** + ENVIRONMENT DIVISION. + ****************************************************************** + 00220000 + *-----------------------------------------------------------------00230000 + CONFIGURATION SECTION. 00240000 + *-----------------------------------------------------------------00250000 + + SOURCE-COMPUTER. IBM-S390 WITH DEBUGGING MODE. + + OBJECT-COMPUTER. IBM-S390. + 00260000 + SPECIAL-NAMES. 00270000 + DECIMAL-POINT IS COMMA + CLASS VALID-NAME 'A' THRU 'I' + 'J' THRU 'R' + 'S' THRU 'Z' + '0' THRU '9'. + 00290000 + + ****************************************************************** + DATA DIVISION. + ****************************************************************** + 00390000 + *-----------------------------------------------------------------00400000 + WORKING-STORAGE SECTION. + *-----------------------------------------------------------------00400000 + + 01 RACF_GROUP PIC X(8). + 01 WK-REQ-CCID. + 03 WK-REQ-CCID-MOD PIC X(3). + 03 WK-REQ-CCID-SUFIX. + 05 WK-REQ-CCID-SUFIX-NUM PIC 9(7). + 03 WK-REQ-CCID-PAD PIC X(2). + 01 WK-ENV PIC X(8). + 01 SN-OBJECT-NUMBER PIC X(10). + 01 PGM PIC X(8). + + 77 WK-TALLY PIC 9(2). + 77 TRIMMED-LEN PIC 9(2). + + *COPY WSCOMMON. + *COPY WSEX02. + + + *================================================================ + *================================================================ + *= List of parameters passed by ref to the IRXJCL + *================================================================ + *==LINKAGE TO IRXJCL============================================= + 01 IRXPARM. + 03 PARM-LENGTH PIC 9(4) COMP. + 03 REXX-NAME PIC X(9). + *--ARGUMENTOS PASADOS AL REXX -------------------------------- + 03 PARM1-A USAGE POINTER. + 03 PARM1-L PIC 9(4) COMP. + 03 PARM2-A USAGE POINTER. + 03 PARM2-L PIC 9(4) COMP. + 03 PARM3-A USAGE POINTER. + 03 PARM3-L PIC 9(4) COMP. + 03 PARM4-A USAGE POINTER. + 03 PARM4-L PIC 9(4) COMP. + *================================================================ + 77 PGM-NAME PIC X(8) VALUE 'IRXJCL'. + * Input/Output Parameter + 77 SNOWOBJ PIC X(10) VALUE SPACES. + * Input Parameter + 77 AUTHTYPE PIC X(8) VALUE SPACES. + 77 ACTION PIC X(8) VALUE SPACES. + * Ouput Parameter + 77 OBJSTATE PIC X(15) VALUE SPACES. + *================================================================ + *----------------------------------------------------------------- + * + * Dynalloc Areas for INFO Request - SNOWTRC DD allocation + * + *----------------------------------------------------------------- + 01 WS-WORK-AREA. + 05 WS-RC PIC 9(9) COMP-5. + 05 WS-DYN-PGM PIC X(8) VALUE 'BPXWDY2 '. + + 01 WDYN-PARM. + 05 WDYN-VALUE PIC X(40) VALUE + 'INFO DD(SNOWTRC) '. + 05 WDYN-NULL PIC X(01) VALUE LOW-VALUES. + + 01 TRACEAPI PIC X(1). + 88 TRACE-DISABLE VALUE '0'. + 88 TRACE-ENABLE VALUE '1'. + + *----------------------------------------------------------------- + * + *----------------------------------------------------------------- + + *-----------------------------------------------------------------00400000 + LINKAGE SECTION. + *-----------------------------------------------------------------00400000 + + COPY EXITBLKS. 00010000 + + ****************************************************************** + PROCEDURE DIVISION USING EXIT-CONTROL-BLOCK + REQUEST-INFO-BLOCK + SRC-ENVIRONMENT-BLOCK + SRC-ELEMENT-MASTER-INFO-BLOCK + SRC-FILE-CONTROL-BLOCK + TGT-ENVIRONMENT-BLOCK + TGT-ELEMENT-MASTER-INFO-BLOCK + TGT-FILE-CONTROL-BLOCK. + + *================================================================ + *-- CONSTRUIMOS LISTA DE PARAMETROS A SER PASADA AL LLAMADOR===== + *================================================================ + * 77 PGM-NAME PIC X(8) VALUE 'IRXJCL'. + * Input/Output Parameter + * 77 SNOW-CR PIC X(10) VALUE SPACES. + * Input Parameter + * 77 AUTHTYPE PIC X(8) VALUE SPACES. + * 77 ACTION PIC X(8) VALUE SPACES. + * Ouput Parameter + * 77 CR-START-DATE PIC X(7) VALUE SPACES. + * 77 CR-START-TIME PIC X(5) VALUE SPACES. + * 77 CR-END-DATE PIC X(7) VALUE SPACES. + * 77 CR-END-TIME PIC X(5) VALUE SPACES. + * 77 OBJSTATE PIC X(15) VALUE SPACES. + * 77 CR-STATUS PIC X(5) VALUE SPACES. + * 77 CR-APPROVAL PIC X(20) VALUE SPACES. + + MOVE +100 TO PARM-LENGTH + MOVE "SNOWJPMC" TO REXX-NAME + + SET PARM1-A TO ADDRESS OF SNOWOBJ + MOVE +10 TO PARM1-L + + SET PARM2-A TO ADDRESS OF AUTHTYPE + MOVE +8 TO PARM2-L + + SET PARM3-A TO ADDRESS OF ACTION + MOVE +8 TO PARM3-L + + SET PARM4-A TO ADDRESS OF OBJSTATE + MOVE +15 TO PARM4-L + + MOVE 0 TO TRACEAPI + PERFORM CHECK-TRACE-DDNAME-ALLOC + + IF TRACE-ENABLE + + DISPLAY '------------------------------------------' + + DISPLAY 'EX02 - START' + DISPLAY 'EX02' + DISPLAY 'EX02 - RC ' ECB-RETURN-CODE + DISPLAY 'EX02 - USER-ID ' ECB-USER-ID + DISPLAY 'EX02 - ACTION ' ECB-ACTION-NAME + DISPLAY 'EX02 - HIGH-RC ' ECB-HIGH-RC + DISPLAY 'EX02 - REQ-CCID ' REQ-CCID + DISPLAY 'EX02 - REQ-COMMENT ' REQ-COMMENT + DISPLAY 'EX02 - REQ-SISO-INDICATOR 'REQ-SISO-INDICATOR + DISPLAY 'EX02' + DISPLAY 'EX02 - ACCION DESDE: 'ECB-API-IND + DISPLAY 'EX02' + DISPLAY 'EX02 - SRC-ENV-ENVIRONMENT-NAME: ' + SRC-ENV-ENVIRONMENT-NAME + DISPLAY 'EX02 - TGT-ENV-ENVIRONMENT-NAME: ' + TGT-ENV-ENVIRONMENT-NAME + DISPLAY 'EX02' + DISPLAY 'EX02 - STOP' + + DISPLAY '------------------------------------------' + + END-IF + + EVALUATE TRUE + WHEN MOVE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN RETRIEVE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN ADD-ACTION + MOVE TGT-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN UPDATE-ACTION + MOVE TGT-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN RETRIEVE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN GENERATE-ACTION + MOVE SRC-ENV-ENVIRONMENT-NAME TO WK-ENV + PERFORM CHECK-CCID-VALUE + WHEN OTHER + EXIT + END-EVALUATE + + GOBACK. + + *-----------------------------------------------------------------00400000 + CHECK-CCID-VALUE. + *-----------------------------------------------------------------00400000 + IF WK-ENV(1:3) = 'DEV' + IF REQ-CCID(1:3) = 'INC' OR + REQ-CCID(1:3) = 'CHG' + MOVE REQ-CCID TO WK-REQ-CCID + PERFORM CHECK-CCID-SN + END-IF + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + CHECK-CCID-SN. + *----------------------------------------------------------------- + + MOVE ZERO TO WK-TALLY + INSPECT FUNCTION REVERSE(WK-REQ-CCID) + TALLYING WK-TALLY FOR LEADING SPACES + COMPUTE TRIMMED-LEN = 12 - WK-TALLY + + IF TRIMMED-LEN = 10 + + IF WK-REQ-CCID-SUFIX-NUM IS NUMERIC + + MOVE WK-REQ-CCID(1:10) TO SN-OBJECT-NUMBER + PERFORM VALIDATE-SN-OBJECT + + IF RETURN-CODE = 0 + + DISPLAY "------------------------------------------" + DISPLAY "Servicenow Object STATE : " OBJSTATE + DISPLAY "------------------------------------------" + + ELSE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + ELSE + + MOVE 8 TO ECB-RETURN-CODE + MOVE 'ServiceNOW Object Number should be NUMERIC' + TO ECB-MESSAGE-TEXT + MOVE '0231' TO ECB-MESSAGE-CODE + + END-IF + + ELSE + + MOVE 8 TO ECB-RETURN-CODE + MOVE 'CCID For ServiceNOW Must Have 10 CHARACTERS' + TO ECB-MESSAGE-TEXT + MOVE '0230' TO ECB-MESSAGE-CODE + + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + VALIDATE-SN-OBJECT. + *-----------------------------------------------------------------00400000 + * MOVE 'SETDUB1S' TO PGM + * + * CALL PGM USING BY REFERENCE RACF_GROUP + * + *************************************************************** + MOVE SN-OBJECT-NUMBER TO SNOWOBJ + MOVE 'BASIC' TO AUTHTYPE + + IF REQ-CCID(1:3) = 'CHG' + MOVE 'VALCHG' TO ACTION + ELSE + MOVE 'VALINC' TO ACTION + END-IF + + MOVE SPACES TO OBJSTATE + + CALL PGM-NAME USING BY REFERENCE IRXPARM + + IF RETURN-CODE NOT = 0 + + IF TRACE-ENABLE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + MOVE 8 TO ECB-RETURN-CODE + MOVE '0236' TO ECB-MESSAGE-CODE + MOVE 'ServiceNow Obj could not be validated in the service + - 'now instance.' + TO ECB-MESSAGE-TEXT + + ELSE + IF TRACE-ENABLE + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "Servicenow CR STATE : " OBJSTATE + DISPLAY "------------------------------------------" + END-IF + END-IF + + + EXIT. + + *----------------------------------------------------------------- + CHECK-TRACE-DDNAME-ALLOC. + *----------------------------------------------------------------- + * validate if DDNAME SNOWTRACE esta activaE + + CALL WS-DYN-PGM USING WDYN-VALUE + RETURNING WS-RC. + IF WS-RC = 0 + + MOVE 1 TO TRACEAPI + + END-IF + + EXIT. + + +./ ADD NAME=C1X7CUST + ******************************************************************00110000 + IDENTIFICATION DIVISION. + ******************************************************************00110000 + + PROGRAM-ID. C1X7JPMC. + AUTHOR. (C) 2025 Broadcom + Jose Benigno Gonzalez for JPMC. + + ****************************************************************** + ENVIRONMENT DIVISION. + ****************************************************************** + 00220000 + *-----------------------------------------------------------------00230000 + CONFIGURATION SECTION. 00240000 + *-----------------------------------------------------------------00250000 + + SOURCE-COMPUTER. IBM-S390 WITH DEBUGGING MODE. + + OBJECT-COMPUTER. IBM-S390. + 00260000 + SPECIAL-NAMES. 00270000 + DECIMAL-POINT IS COMMA + CLASS VALID-NAME 'A' THRU 'I' + 'J' THRU 'R' + 'S' THRU 'Z' + '0' THRU '9'. + 00290000 + + ****************************************************************** + DATA DIVISION. + ****************************************************************** + 00390000 + *-----------------------------------------------------------------00400000 + WORKING-STORAGE SECTION. + *-----------------------------------------------------------------00400000 + + 01 RACF_GROUP PIC X(8). + + 01 WK-PKG-SNOW. + 03 WK-PKG-SNOW-MOD PIC X(3). + 03 WK-PKG-SNOW-SUFIX. + 05 WK-PKG-SNOW-SUFIX-NUM PIC 9(7). + 03 WK-PKG-SNOW-PAD PIC X(6). + + 01 WK-ENV PIC X(8). + 01 SN-OBJECT-NUMBER PIC X(10). + 01 PGM PIC X(8). + + 77 WK-TALLY PIC 9(2). + 77 TRIMMED-LEN PIC 9(2). + + + + *================================================================ + *================================================================ + *= List of parameters passed by ref to the IRXJCL + *================================================================ + *==LINKAGE TO IRXJCL============================================= + 01 IRXPARM. + 03 PARM-LENGTH PIC 9(4) COMP. + 03 REXX-NAME PIC X(9). + *--ARGUMENTOS PASADOS AL REXX -------------------------------- + 03 PARM1-A USAGE POINTER. + 03 PARM1-L PIC 9(4) COMP. + 03 PARM2-A USAGE POINTER. + 03 PARM2-L PIC 9(4) COMP. + 03 PARM3-A USAGE POINTER. + 03 PARM3-L PIC 9(4) COMP. + 03 PARM4-A USAGE POINTER. + 03 PARM4-L PIC 9(4) COMP. + *================================================================ + 77 PGM-NAME PIC X(8) VALUE 'IRXJCL'. + * Input/Output Parameter + 77 SNOWOBJ PIC X(10) VALUE SPACES. + * Input Parameter + 77 AUTHTYPE PIC X(8) VALUE SPACES. + 77 ACTION PIC X(8) VALUE SPACES. + * Ouput Parameter + 77 OBJSTATE PIC X(15) VALUE SPACES. + *================================================================ + *----------------------------------------------------------------- + * + * Dynalloc Areas for INFO Request - SNOWTRC DD allocation + * + *----------------------------------------------------------------- + 01 WS-WORK-AREA. + 05 WS-RC PIC 9(9) COMP-5. + 05 WS-DYN-PGM PIC X(8) VALUE 'BPXWDY2 '. + + 01 WDYN-PARM. + 05 WDYN-VALUE PIC X(40) VALUE + 'INFO DD(SNOWTRC) '. + 05 WDYN-NULL PIC X(01) VALUE LOW-VALUES. + + 01 TRACEAPI PIC X(1). + 88 TRACE-DISABLE VALUE '0'. + 88 TRACE-ENABLE VALUE '1'. + + *----------------------------------------------------------------- + LINKAGE SECTION. + *----------------------------------------------------------------- + + COPY PKGXBLKS. + + ****************************************************************** + PROCEDURE DIVISION USING PACKAGE-EXIT-BLOCK + PACKAGE-REQUEST-BLOCK + PACKAGE-EXIT-HEADER-BLOCK + PACKAGE-EXIT-FILE-BLOCK + PACKAGE-EXIT-ACTION-BLOCK + PACKAGE-EXIT-APPROVER-MAP + PACKAGE-EXIT-BACKOUT-BLOCK + PACKAGE-EXIT-SHIPMENT-BLOCK + PACKAGE-EXIT-SCL-BLOCK + PACKAGE-EXIT-COLLECT-BLOCK. + ****************************************************************** + + *----------------------------------------------------------------- + MAIN SECTION. + *-----------------------------------------------------------------00110000 + + MOVE 0 TO TRACEAPI + PERFORM CHECK-TRACE-DDNAME-ALLOC + + IF TRACE-ENABLE + + DISPLAY '---------------------------------------------' + + DISPLAY 'EX07 - START' + DISPLAY 'EX07' + DISPLAY 'EX07 - PACKAGE-ID ' PECB-PACKAGE-ID + DISPLAY 'EX07 - FUNCTION ' PECB-FUNCTION-LITERAL + DISPLAY 'EX07 - SUBFUNC ' PECB-SUBFUNC-LITERAL + DISPLAY 'EX07 - BEF-AFTER ' PECB-BEF-AFTER-LITERAL + DISPLAY 'EX07' + DISPLAY 'EX07 - STOP' + + DISPLAY '---------------------------------------------' + + END-IF + + MOVE +100 TO PARM-LENGTH + MOVE "SNOWJPMC" TO REXX-NAME + + SET PARM1-A TO ADDRESS OF SNOWOBJ + MOVE +10 TO PARM1-L + + SET PARM2-A TO ADDRESS OF AUTHTYPE + MOVE +8 TO PARM2-L + + SET PARM3-A TO ADDRESS OF ACTION + MOVE +8 TO PARM3-L + + SET PARM4-A TO ADDRESS OF OBJSTATE + MOVE +15 TO PARM4-L + + PERFORM P-MAIN + + GOBACK. + + *----------------------------------------------------------------- + P-MAIN. + *----------------------------------------------------------------- + + EVALUATE TRUE + WHEN SETUP-EXIT-OPTIONS + MOVE 'N' TO PECB-BEFORE-BACKIN + MOVE 'N' TO PECB-AFTER-BACKIN + MOVE 'N' TO PECB-BEFORE-BACKOUT + MOVE 'N' TO PECB-AFTER-BACKOUT + MOVE 'N' TO PECB-BEFORE-CAST + MOVE 'N' TO PECB-MID-CAST + MOVE 'N' TO PECB-AFTER-CAST + MOVE 'N' TO PECB-BEFORE-COMMIT + MOVE 'N' TO PECB-AFTER-COMMIT + MOVE 'Y' TO PECB-BEFORE-CREATE-BLD + MOVE 'N' TO PECB-AFTER-CREATE-BLD + MOVE 'Y' TO PECB-BEFORE-CREATE-COPY + MOVE 'N' TO PECB-AFTER-CREATE-COPY + MOVE 'Y' TO PECB-BEFORE-CREATE-EDIT + MOVE 'N' TO PECB-AFTER-CREATE-EDIT + MOVE 'Y' TO PECB-BEFORE-CREATE-IMPT + MOVE 'N' TO PECB-AFTER-CREATE-IMPT + MOVE 'N' TO PECB-BEFORE-DELETE + MOVE 'N' TO PECB-AFTER-DELETE + MOVE 'N' TO PECB-BEFORE-DSPLY-APPR + MOVE 'N' TO PECB-BEFORE-DSPLY-BKOUT + MOVE 'N' TO PECB-BEFORE-DSPLY-SCL + MOVE 'N' TO PECB-BEFORE-DSPLY-ELMSM + MOVE 'N' TO PECB-BEFORE-DSPLY-PKG + MOVE 'N' TO PECB-BEFORE-DSPLY-RPT + MOVE 'N' TO PECB-BEFORE-EXEC + MOVE 'N' TO PECB-AFTER-EXEC + MOVE 'N' TO PECB-BEFORE-EXPORT + MOVE 'N' TO PECB-AFTER-EXPORT + MOVE 'Y' TO PECB-BEFORE-GENPID + MOVE 'N' TO PECB-AFTER-GENPID + MOVE 'N' TO PECB-BEFORE-LIST + MOVE 'N' TO PECB-AFTER-LIST + MOVE 'N' TO PECB-BEFORE-MOD-BLD + MOVE 'N' TO PECB-AFTER-MOD-BLD + MOVE 'N' TO PECB-BEFORE-MOD-CPY + MOVE 'N' TO PECB-AFTER-MOD-CPY + MOVE 'N' TO PECB-BEFORE-MOD-EDIT + MOVE 'N' TO PECB-AFTER-MOD-EDIT + MOVE 'N' TO PECB-BEFORE-MOD-IMPT + MOVE 'N' TO PECB-AFTER-MOD-IMPT + MOVE 'N' TO PECB-BEFORE-RESET + MOVE 'N' TO PECB-AFTER-RESET + MOVE 'N' TO PECB-BEFORE-REV-APPR + MOVE 'N' TO PECB-AFTER-REV-APPR + MOVE 'N' TO PECB-BEFORE-REV-DENY + MOVE 'N' TO PECB-AFTER-REV-DENY + MOVE 'N' TO PECB-BEFORE-SHIP-XMIT + MOVE 'N' TO PECB-AFTER-SHIP-XMIT + MOVE 'N' TO PECB-BEFORE-SHIP-CON + MOVE 'N' TO PECB-AFTER-SHIP-CON + WHEN CREATE-PACKAGE + EVALUATE TRUE + WHEN PECB-BEFORE + IF PECB-UEXIT-HOLD-FIELD = 8 + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0719' TO PECB-MESSAGE-ID + MOVE 'Package creation Error.' + TO PECB-MESSAGE + END-IF + WHEN PECB-AFTER + EXIT + END-EVALUATE + WHEN GENERATE-PACKAGE-ID + EVALUATE TRUE + WHEN PECB-BEFORE + PERFORM PROCESS-GENPKGID-GEN + MOVE PECB-NDVR-EXIT-RC TO PECB-UEXIT-HOLD-FIELD + WHEN PECB-AFTER + EXIT + END-EVALUATE + END-EVALUATE + + EXIT. + + + *-----------------------------------------------------------------00400000 + PROCESS-GENPKGID-GEN. + *-----------------------------------------------------------------00400000 + IF PECB-PACKAGE-ID(1:3) ='INC' OR + PECB-PACKAGE-ID(1:3) ='CHG' + + MOVE PECB-PACKAGE-ID TO WK-PKG-SNOW + PERFORM CHECK-PKGID-SN + + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + CHECK-PKGID-SN. + *----------------------------------------------------------------- + + MOVE ZERO TO WK-TALLY + INSPECT FUNCTION REVERSE(WK-PKG-SNOW) + TALLYING WK-TALLY FOR LEADING SPACES + COMPUTE TRIMMED-LEN = 16 - WK-TALLY + + DISPLAY 'TRIMMED-LEN: 'TRIMMED-LEN + + IF TRIMMED-LEN >= 10 + + IF WK-PKG-SNOW-SUFIX-NUM IS NUMERIC + + MOVE WK-PKG-SNOW(1:10) TO SN-OBJECT-NUMBER + PERFORM VALIDATE-SN-OBJECT + + IF RETURN-CODE = 0 + + DISPLAY "------------------------------------------" + DISPLAY "Servicenow Object STATE : " OBJSTATE + DISPLAY "------------------------------------------" + + ELSE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + ELSE + + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0729' TO PECB-MESSAGE-ID + MOVE 'Package ID for ServiceNow Object must be numeric' + TO PECB-MESSAGE + + END-IF + + ELSE + + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0710' TO PECB-MESSAGE-ID + MOVE 'PackageID for ServiceNow object must have at least + - '10 characters.' + TO PECB-MESSAGE + + END-IF + + EXIT. + + *-----------------------------------------------------------------00400000 + VALIDATE-SN-OBJECT. + *-----------------------------------------------------------------00400000 + * MOVE 'SETDUB1S' TO PGM + * + * CALL PGM USING BY REFERENCE RACF_GROUP + * + *************************************************************** + MOVE SN-OBJECT-NUMBER TO SNOWOBJ + MOVE 'BASIC' TO AUTHTYPE + + IF PECB-PACKAGE-ID(1:3) = 'CHG' + MOVE 'VALCHG' TO ACTION + ELSE + MOVE 'VALINC' TO ACTION + END-IF + + MOVE SPACES TO OBJSTATE + + CALL PGM-NAME USING BY REFERENCE IRXPARM + + IF RETURN-CODE NOT = 0 + + IF TRACE-ENABLE + + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "------------------------------------------" + + END-IF + + MOVE 8 TO PECB-NDVR-EXIT-RC + MOVE '0717' TO PECB-MESSAGE-ID + MOVE 'ServiceNow Obj could not be validated in the service + - 'now instance.' + TO PECB-MESSAGE + + ELSE + IF TRACE-ENABLE + DISPLAY "------------------------------------------" + DISPLAY "REXX Return Code : " RETURN-CODE + DISPLAY "Servicenow CR STATE : " OBJSTATE + DISPLAY "------------------------------------------" + END-IF + END-IF + + + EXIT. + + *----------------------------------------------------------------- + CHECK-TRACE-DDNAME-ALLOC. + *----------------------------------------------------------------- + * validate if DDNAME SNOWTRACE esta activaE + + CALL WS-DYN-PGM USING WDYN-VALUE + RETURNING WS-RC. + IF WS-RC = 0 + + MOVE 1 TO TRACEAPI + + END-IF + + EXIT. + + +./ ADD NAME=CIUU23 +CIUU230E 'Invalid CCID length' .ALARM=YES +'CCID for ServiceNow must have 10 Characters' + +CIUU231E 'Invalid Incident DataType' .ALARM=YES +'ServiceNOW Incident Number must be NUMERIC' + +CIUU236E 'Object does not exist' .ALARM=YES +'ServiceNow Object is not created in the Repository' + +./ ADD NAME=CIUU71 +CIUU710E 'Invalid PackageID length' .T=W .A=Y +'Invalid PackageID Length for new servicenow change request.' + +CIUU717E 'CR not avilable' .T=W .A=Y +'Change Request could not be validated in the servicenow instance.' + +CIUU719E 'Invalid Content' .T=W .A=Y +'Package ID Change Request Number must be a numeric value.' + +./ ADD NAME=NDVRSNOW +/* REXX */ +/*********************************************************************/ +/* AUTHOR. (C) 2025 Broadcom */ +/* Jose Benigno Gonzalez for JPCM. */ +/* */ +/* Validates Endevor CCID against ServiceNow change request and */ +/* Incident Management Module - Called from Endevor Exit 2 */ +/* */ +/* Currently in Dev Phase: */ +/* Validates the first ten characters of the packageID against */ +/* ServiceNow change request and Incident Management Module - Called */ +/* from Endevor Exit 7 */ +/* */ +/*------------------------------------------------------------------- */ +/* Obtenemos las direcciones y longitudes los paametros de entrada */ +/*-------------------------------------------------------------------*/ + trace R + +/* Validate parameter passed to the REXX testsno9*/ +/**/ + +/*-------------------------------------------------------------------*/ +/* Obtenemos las direcciones y longitudes los paametros de entrada */ +/*-------------------------------------------------------------------*/ +argstr = ARG(1) + + +parse var argstr 1 A_parm1 , /* servicenow change request */ + 9 L_parm1 , + 13 A_parm2 , /* Auth Type (BASIC or OAUTH) */ + 21 L_parm2 , + 25 A_parm3 , /* Action from Endevor */ + 33 L_parm3 , + 37 A_parm4 , /* CR/INC State */ + 45 L_parm4 , + 49 . + +parm1_d = X2D(L_parm1) /* decimal length of servicenow CR field */ +parm2_d = X2D(L_parm2) /* decimal length of AUTHTYPE field */ +parm3_d = X2D(L_parm3) /* decimal length of Action field */ +parm4_d = X2D(L_parm4) /* decimal length of CR/INC State */ + + +snowObjNumber = strip(storage(A_parm1,parm1_d)) +AuthType = strip(STORAGE(A_parm2,parm2_d)) +Action = strip(STORAGE(A_parm3,parm3_d)) +snowObjState = strip(STORAGE(A_parm4,parm4_d)) + + +verbose= 0 + +SnowTrc_RC = bpxwdyn("info fi(snowtrc) INRTTYP(DSType)") +If SnowTrc_RC = 0 Then do + Verbose = 1 +end + +/* Get Web Enablement Toolkit REXX constants */ + call HTTP_getToolkitConstants + if RESULT <> 0 then + exit fatalError( '** Environment error **' ) + +/* Indicate Program start */ + say '************************************************' + say '** HTTP Web Enablement Toolkit Sample (Begin) **' + say '************************************************' + +/* Initialize variables in program */ + call InitializeVars + + /* get a connection handle */ + call HTTP_init HWTH_HANDLETYPE_CONNECTION + if RESULT <> 0 then + call fatalError('** Connection could not be initialized **') + + /* Set the necessary options before connecting to the server */ + call HTTP_setupConnection + if RESULT <> 0 then + cleanup('CON','** Connection failed to be set up **') + + /* Connect to the HTTP server */ + call HTTP_connect + if RESULT <> 0 then + cleanup('CON','** Connection failed **') + + /* Obtain a request handle */ + call HTTP_init HWTH_HANDLETYPE_HTTPREQUEST + if RESULT <> 0 then + cleanup('CON','** Request could not be initialized **') + +select + + when Action = 'VALINC' then do + + queryParms = '?sysparm_display_value=true' + queryParms = queryParms || '&' ||'sysparm_query=number=' + queryParms = queryParms ||snowObjNumber + + requestURI = IncidentPath || queryParms + + call HTTP_setupRequest "GET", RequestURI, "GETINC" + + if RESULT <> 0 then + cleanup('CONREQ','** Submit job request failed to be setup **') + + /* Make the request to ServiceNow */ + call HTTP_request + if RESULT <> 0 then + cleanup('CONREQ','** ServiceNow request failed **') + + /* Analyze ServiceNow Incident (Response Body) json */ + if VERBOSE then + say "response body GETINC: "||ResponseBody + + if ResponseStatusCode == HTTP_OK & ResponseBody <> '{"result":[]}' then + Do + call correlateData ResponseBody, "INC" + if result <> 0 Then do + say '*** Error during JSON correlation ***' + end + else do + + SnowCR_state = left(Incident.state,parm4_d) + IntRC = STORAGE(A_parm4,,SnowCR_state) + + programRc = 0 + + end + + End + else Do + If ResponseStatusCode <> HTTP_OK then do + say '***Bad resp received: 'ResponseStatusCode'.' + end + else do + say '*** Object does not exist in servicenow application *** ' + programRc = 8 + end + end + + end + + + when Action = 'VALCHG' then do + + queryParms = '?sysparm_display_value=true' + queryParms = queryParms || '&' ||'sysparm_query=number=' + queryParms = queryParms ||snowObjNumber + + requestURI = ChangeRequestPath || queryParms + + call HTTP_setupRequest "GET", requestURI, "GETCHG" + + if RESULT <> 0 then + cleanup('CONREQ','** Submit job request failed to be setup **') + + /* Make the request to ServiceNow */ + call HTTP_request + if RESULT <> 0 then + cleanup('CONREQ','** ServiceNow request failed **') + + /* Analyze ServiceNow Incident (Response Body) json */ + if VERBOSE then + say "response body GETCHG: "||ResponseBody + + if ResponseStatusCode == HTTP_OK & ResponseBody <> '{"result":[]}' then + Do + call correlateData ResponseBody, "CHG" + if result <> 0 Then do + say '*** Error during JSON correlation ***' + end + else do + + SnowCR_state = left(ChgRequest.state,parm4_d) + IntRC = STORAGE(A_parm4,,SnowCR_state) + + programRc = 0 + + end + + End + else Do + If ResponseStatusCode <> HTTP_OK then do + say '***Bad resp received: 'ResponseStatusCode'.' + end + else do + say '*** Object does not exist in servicenow application *** ' + programRc = 8 + end + end + + end + + otherwise + say '***Action not implememented yet ***' + +end /* select */ + +cleanup('CONREQ','HTTP Web Enablement Toolkit Sample (Ends)') + +return programRc + + +/*******************************************************/ +/* Function: InitalizeVars */ +/* */ +/* Initialize global vars used throughout the program */ +/*******************************************************/ +InitializeVars: + + programRc = -1 + +/* Initialize Connection and Request handle */ + ConnectionHandle = '' + RequestHandle = '' + +/* Initialize response-related variables */ + HTTP_OK = 200 + HTTP_Created = 201 + HTTP_Accepted = 202 + StatCode = '' + ResponseStatusCode = '' + ResponseReason = '' + ResponseHeaders. = '' + ResponseBody = '' + +/* Servicenow specific variables */ + ServicenowURI = 'https://dev&&&&&&.service-now.com' /* <== '***CHANGE***' */ + + RingName= '' /* <== '***CHANGE***' */ + +/* BASIC Authentication */ + + BASIC_UserName = 'admin' /* <== '***CHANGE***' */ + BASIC_Password = '%%%%%%%%%%%%' /* <== '***CHANGE***' */ + + /* PATH for GET Request*/ + ChangeRequestPath = '/api/now/table/change_request' + IncidentPath = '/api/now/table/incident' + AffectedCIPath = '/api/now/table/task_ci' + + /* PATH for POST Request*/ + OAuthPath = '/oauth_token.do' + NewChangeRequestPath='/api/sn_chg_rest/change' + +/* Servicenow specific variables for API Json Response */ + + Incident. = '' + ChgRequest. ='' + AffectedCI. ='' + + +return + + +/*******************************************************************/ +/* Function: correlateData() */ +/* */ +/* Use JSON Parser services to process the data returned */ +/* by the web server. */ +/* */ +/* Return 0 if all parsing activity was performed successfully, */ +/* -1 if otherwise. */ +/*******************************************************************/ +correlateData: + snowJSONResponse = arg(1) + snowObjectType = arg(2) /* INC, CHG, TASK */ + parserHandle = '' + isJSON = 0; + jRespHead = "application/json" + l = length(jRespHead) + /******************************************************************/ + /* Check to make sure that the data coming back is in JSON format */ + /* Loop thru all of the response headers and see if any of them */ + /* say Content-Type=application/json */ + /******************************************************************/ + if VERBOSE then + say "CHECKING HEADERS" + + do i = 1 to ResponseHeaders.0 /* 1 to total # of headers*/ + /* Header Name check */ + if ResponseHeaders.i = "Content-Type" then + /* Header value check */ + if substr(ResponseHeaders.i.1,1,l) = jRespHead then + isJSON = 1; + end + + /* if none of the headers was JSON, then don't call parser */ + if isJSON = 0 Then do + return fatalError( '** Data did not come back in JSON format ** ') + end + + /***********************************/ + /* Obtain a JSON Parser instance. */ + /***********************************/ + call JSON_initParser + if RESULT <> 0 then + return fatalError( '** Pre-processing error (parser init failure) **' ) + /****************************/ + /* Parse the response data. */ + /****************************/ + call JSON_parse snowJSONResponse + if RESULT <> 0 then + do + call JSON_termParser + return fatalError( '** Error while parsing SN Incident data **' ) + end + /*****************************************/ + /* Extract specific data and surface it, */ + /* then release the parser instance. */ + /*****************************************/ + call JSON_searchAndDeserializeData snowObjectType + call JSON_termParser + + return 0 + +/*******************************************************/ +/* Function: cleanup */ +/* */ +/* Cleanup a connection and possibly a request */ +/* depending on the parameters pasted in. */ +/*******************************************************/ +cleanup: + cleanupType = arg(1) + errorMsg = arg(2) + + if cleanupType = 'CONREQ' then + call HTTP_terminate RequestHandle, HWTH_NOFORCE + + /* Unconditionally release the connection handle */ + call HTTP_terminate ConnectionHandle, HWTH_NOFORCE + + /* Say error message */ + say errorMsg + + call closeToolkitTrace traceDD + +exit programRC + +/*****************************************************/ +/* HTTP-related functions */ +/* */ +/* These { HTTP_xxx } functions are located together */ +/* for ease of reference and are used to demonstrate */ +/* how this portion of the Web Enablement Toolkit */ +/* can be used. */ +/*****************************************************/ + +/*******************************************************/ +/* Function: HTTP_getToolkitConstants */ +/* */ +/* Access constants used by the toolkit (for return */ +/* codes, etc), via the HWTCONST toolkit api. */ +/* */ +/* Returns: 0 if toolkit constants accessed, -1 if not */ +/*******************************************************/ +HTTP_getToolkitConstants: + /***********************************************/ + /* Ensure that the toolkit host command is */ + /* available in your REXX environment (no harm */ + /* done if already present). Do this before */ + /* your first toolkit api invocation. Also, */ + /* ensure no conflicting signal-handling in */ + /* cases of running in USS environments. */ + /***********************************************/ + if VERBOSE then + say 'Setting hwtcalls on, syscalls sigoff' + call hwtcalls 'on' + call syscalls 'SIGOFF' + /************************************************/ + /* Call the HWTCONST toolkit api. This should */ + /* make all toolkit-related constants available */ + /* to procedures via (expose of) HWT_CONSTANTS */ + /************************************************/ + if VERBOSE then + say 'Including HWT Constants...' + address hwthttp "hwtconst ", + "ReturnCode ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwtconst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtconst (hwthttp) failure **' ) + end /* endif hwtconst failure */ + return 0 /* end function */ + + +/*************************************************/ +/* Function: HTTP_init */ +/* */ +/* Create a handle of the designated type, via */ +/* the HWTHINIT toolkit api. Populate the */ +/* corresponding global variable with the result */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/*************************************************/ +HTTP_init: + HandleType = arg(1) + /***********************************/ + /* Call the HWTHINIT toolkit api. */ + /***********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthinit ", + "ReturnCode ", + "HandleType ", + "HandleOut ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthinit', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthinit failure **' ) + end + if HandleType == HWTH_HANDLETYPE_CONNECTION then + ConnectionHandle = HandleOut + else + RequestHandle = HandleOut + return 0 /* end Function */ + + +/****************************************************/ +/* Function: HTTP_setupConnection */ +/* */ +/* Sets the necessary connection options, via the */ +/* HWTHSET toolkit api. The global variable */ +/* ConnectionHandle orients the api as to the scope */ +/* of the option(s). */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/****************************************************/ +HTTP_setupConnection: + if VERBOSE then + do + /*****************************************************************/ + /* Set the HWT_OPT_VERBOSE option, if appropriate. */ + /* This option is handy when developing an application (but may */ + /* be undesirable once development is complete). Inner workings */ + /* of the toolkit are traced by messages written to standard */ + /* output, or optionally redirected to file (by use of the */ + /* HWTH_OPT_VERBOSE_OUTPUT option). */ + /*****************************************************************/ + say '**** Set HWTH_OPT_VERBOSE for connection ****' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_VERBOSE ", + "HWTH_VERBOSE_ON ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_VERBOSE) failure **' ) + end /* endif hwthset failure */ + + Call TurnOnVerboseOutput + + end /* endif script invocation requested (-V) VERBOSE */ + + /***********************************************************************/ + /* Set HWTH_OPT_USE_SSL */ + /***********************************************************************/ + if VERBOSE then + say '****** Set WTH_OPT_USE_SSL fot SSL ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_USE_SSL ", + "HWTH_SSL_USE ", + "DiagArea." + /* "HWTH_SSL_NONE ", */ + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_USE_SSL) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_SSLVERSION */ + /***********************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_SSLVERSION ***' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_SSLVERSION ", + "HWTH_SSLVERSION_TLSv12 ", + "DiagArea." + /* "HWTH_SSLVERSION_TLSv13 ", + "HWTH_SSLVERSION_DEFAULT ",*/ + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_SSLVERSION) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_SSLKEYTYPE */ + /***********************************************************************/ + /**/ + if VERBOSE then + say '****** Set HWTH_OPT_SSLKEYTYPE ***' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_SSLKEYTYPE ", + "HWTH_SSLKEYTYPE_KEYRINGNAME ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_SSLKEYTYPE) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_SSLKEY */ + /***********************************************************************/ + /**/ + if VERBOSE then + say '****** Set HWTH_OPT_SSLKEY ***' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_SSLKEY ", + "RingName ", + "DiagArea." + /* "IZUSVR.ZOSMF02 ", */ + /* "IZUSVR.KEYR01 ", */ + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_SSLKEY) failure **' ) + end /* endif hwthset failure */ + + /****************************************************************************/ + /* Set URI for connection to Service Now Cloud SaaS */ + /****************************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_URI for connection ******' + + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_URI ", + "ServicenowURI ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_URI) failure **' ) + end /* endif hwthset failure */ + + /***********************************************************************/ + /* Set HWTH_OPT_COOKIETYPE */ + /* Enable the cookie engine for this connection. Any "eligible" */ + /* stored cookies will be resent to the host on subsequent */ + /* interactions automatically. */ + /***********************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_COOKIETYPE for session cookies ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_COOKIETYPE ", + "HWTH_COOKIETYPE_SESSION ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_COOKIETYPE) failure **' ) + end /* endif hwthset failure */ + + + if VERBOSE then + say 'Connection setup successful' + return 0 /* end subroutine */ + + +/*************************************************************/ +/* Function: HTTP_connect */ +/* */ +/* Connect to the configured domain (host) via the HWTHCONN */ +/* toolkit api. */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/*************************************************************/ +HTTP_connect: + if VERBOSE then + say 'Issue Connect' + /**********************************/ + /* Call the HWTHCONN toolkit api */ + /**********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthconn ", + "ReturnCode ", + "ConnectionHandle ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthconn', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthconn failure **' ) + end + if VERBOSE then + say 'Connect (hwthconn) successful' + return 0 /* end function */ + + +/************************************************************/ +/* Function: HTTP_setupRequest */ +/* */ +/* Sets the necessary request options. The global variable */ +/* RequestHandle orients the api as to the scope of the */ +/* option(s). */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/************************************************************/ +HTTP_setupRequest: +HTTP_Method = arg(1) +RequestURI = arg(2) +Action = arg(3) + + if VERBOSE then + say '****** Set HWTH_OPT_REQUESTMETHOD for request **' + /**************************************************************/ + /* Set HTTP Request method. */ + /* A ??? request method is used to modify a resource on server*/ + /**************************************************************/ + ReturnCode = -1 + DiagArea. = '' + + select + when HTTP_Method = 'GET' then do + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTMETHOD ", + "HWTH_HTTP_REQUEST_GET ", + "DiagArea." + end + + when HTTP_Method = 'POST' then do + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTMETHOD ", + "HWTH_HTTP_REQUEST_POST ", + "DiagArea." + end + + when HTTP_Method = 'PATCH' then do + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTMETHOD ", + "HWTH_HTTP_REQUEST_PATCH ", + "DiagArea." + end + + Otherwise + return fatalError( '** hwthset (HWTH_OPT_REQUESTMETHOD) invalid **' ) + end + + + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError('hwthset (HWTH_OPT_REQUESTMETHOD) failure **' ) + end /* endif hwthset failure */ +/*****************************************************************/ +/* Set the request URI */ +/* Set the URN URI that identifies a resource by name that is */ +/* the target of our request. */ +/*****************************************************************/ + if VERBOSE then + say'****** Set HWTH_OPT_URI for request ******' + + + if VERBOSE then + say 'request URI:' requestURI + + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_URI ", + "requestURI ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_URI) failure **' ) + end /* endif hwthset failure */ + +/*****************************************************************/ +/* Authenticating to the ServiceNow Instance */ +/* Single sign-on uses HTTP basic authentication to fulfill the */ +/* request. Set the authentication level to basic and */ +/* specify userid and password */ +/*****************************************************************/ + + /* Set Authentication Type based on AUTHType parameter */ + If AuthType /= 'OAUTH' Then do + + if VERBOSE then + say'****** Set HWTH_OPT_HTTPAUTH for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_HTTPAUTH ", + "HWTH_HTTPAUTH_BASIC ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_HTTPAUTH) failure **' ) + end /* endif hwthset failure */ + + /* Set username */ + if VERBOSE then + say'****** Set HWTH_OPT_USERNAME for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_USERNAME ", + "BASIC_UserName ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_USERNAME) failure **' ) + end /* endif hwthset failure */ + + /* Set password */ + if VERBOSE then + say'****** Set HWTH_OPT_PASSWORD for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_PASSWORD ", + "BASIC_Password ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_PASSWORD) failure **' ) + end /* endif hwthset failure */ + end + + Else do + + if VERBOSE then + say'****** Set HWTH_OPT_HTTPAUTH for request ******' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_HTTPAUTH ", + "HWTH_HTTPAUTH_NONE ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_HTTPAUTH) failure **' ) + end /* endif hwthset failure */ + + end + /* */ + /*********************************************************/ + /* Set the stem variable for receiving response headers */ + /*********************************************************/ + ReturnCode = -1 + DiagArea. = '' + ResponseHeaders. = '' + + if VERBOSE then + say '****** Set HWTH_OPT_RESPONSEHDR_USERDATA for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_RESPONSEHDR_USERDATA ", + "ResponseHeaders. ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_RESPONSEHDR_USERDATA) failure **') + end /* endif hwthset failure */ + + /*******************************************************************/ + /* Have the toolkit convert the response body from ASCII to EBCDIC */ + /* (so that we may pass it to our parser in a form that the latter */ + /* will understand) */ + /*******************************************************************/ + ReturnCode = -1 + DiagArea. = '' + if VERBOSE then + say '****** Set HWTH_OPT_TRANSLATE_RESPBODY for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_TRANSLATE_RESPBODY ", + "HWTH_XLATE_RESPBODY_A2E ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_TRANSLATE_RESPBODY) failure **' ) + end /* endif hwthset failure */ + + /*******************************************************************/ + /* Have the toolkit convert the request body from EBCDIC TO ASCII */ + /*******************************************************************/ + if VERBOSE then + say '****** Set HWTH_OPT_TRANSLATE_REQBODY for request' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_TRANSLATE_REQBODY ", + "HWTH_XLATE_REQBODY_E2A ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_TRANSLATE_REQBODY) failure **' ) + end /* endif hwthset failure */ + + /**************************************************/ + /* Set Request body */ + /**************************************************/ + ReturnCode = -1 + DiagArea. = '' + + select + + when Action = 'NEWCHG' then do + RequestBody = '{"short_description":"Change Request created on behalf of Endevor"}' + end + + when Action = 'ADDCHGNT' then do + Notes = 'Endevor Package ID ' Ndvr_Pkg_id ' has been created for this Change Request.' + RequestBody = '{"work_notes":"' || Notes || '"}' + end + + otherwise RequestBody = "" + + end + + if VERBOSE then + say '****** Set HWTH_OPT_REQUESTBODY for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_REQUESTBODY ", + "RequestBody ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_REQUESTBODY) failure **') + end /* endif hwthset failure */ + + + /*************************************************/ + /* Set the variable for receiving response body */ + /**************************************************/ + ReturnCode = -1 + DiagArea. = '' + ResponseBody. = '' + + if VERBOSE then + say '****** Set HWTH_OPT_RESPONSEBODY_USERDATA for request ******' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_RESPONSEBODY_USERDATA ", + "ResponseBody ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_RESPONSEBODY_USERDATA) failure **') + end /* endif hwthset failure */ + + /*************************************************************/ + /* Set any request header(s) we may have. This depends upon */ + /* the Http request (often we might not have any). */ + /*************************************************************/ + call HTTP_setRequestHeaders + if RESULT <> 0 then + return fatalError( '** Unable to set Request Headers **' ) + + if VERBOSE then + say 'Request setup successful' + return 0 /* end function */ + +/****************************************************************/ +/* Function: HTTP_terminate */ +/* */ +/* Release the designated Connection or Request handle via the */ +/* HWTHTERM toolkit api. */ +/* */ +/* Returns: */ +/* 0 if successful, -1 if not */ +/****************************************************************/ +HTTP_terminate: + + handleIn = arg(1) + forceOption = arg(2) + if VERBOSE then + say 'Terminate' + /***********************************/ + /* Call the HWTHTERM toolkit api. */ + /***********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthterm ", + "ReturnCode ", + "handleIn ", + "forceOption ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthterm', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthterm failure **' ) + end /* endif hwthterm failure */ + if VERBOSE then + say 'Terminate (hwthterm) succeeded' + return 0 /* end function */ + + +/****************************************************************/ +/* Function: HTTP_request */ +/* */ +/* Make the configured Http request via the HWTHRQST toolkit */ +/* api. */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/****************************************************************/ +HTTP_request: + if VERBOSE then + say 'Making Http Request' + ReturnCode = -1 + DiagArea. = '' + /***********************************/ + /* Call the HWTHRQST toolkit api. */ + /***********************************/ + address hwthttp "hwthrqst ", + "ReturnCode ", + "ConnectionHandle ", + "RequestHandle ", + "HttpStatusCode ", + "HttpReasonCode ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthrqst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthrqst failure **' ) + end /* endif hwthrqst failure */ + /****************************************************************/ + /* The ReturnCode indicates merely whether the request was made */ + /* (and response received) without error. The origin server's */ + /* response, of course, is another matter. The HttpStatusCode */ + /* and HttpReasonCode record how the server responded. Any */ + /* header(s) and/or body included in that response are to be */ + /* found in the variables which we established earlier. */ + /****************************************************************/ + ResponseStatusCode = strip(HttpStatusCode,'L',0) + ResponseReasonCode = strip(HttpReasonCode) + if VERBOSE then + do + say 'Request completed' + say 'HTTP Status Code: '||StatCode + say 'HTTP Response Reason Code: '||ResponseReasonCode + end + + return 0 /* end function */ + +/*************************************************************/ +/* Function: HTTP_setRequestHeaders */ +/* */ +/* Add appropriate Request Headers, by first building an */ +/* "SList", and then setting the HWTH_OPT_HTTPHEADERS */ +/* option of the Request with that list. */ +/* */ +/* Returns: 0 if successful, -1 if not */ +/*************************************************************/ +HTTP_setRequestHeaders: + + +If Action = 'NEWCHG' Then do + + SList = '' + acceptHeader = 'Accept: */*' + Authorization = 'Authorization: Bearer' + + + ReturnCode = -1 + DiagArea. = '' + if VERBOSE then + say 'Create new SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_NEW ", + "SList ", + "acceptHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_NEW) failure **' ) + end /* endif hwthslst failure */ + +end + +Else do + + SList = '' + acceptJsonHeader = 'Accept: application/json' + acceptLanguageHeader = 'Accept-Language: en-US' + contentTypeHeader = 'Content-Type: application/json' + Authorization = 'Authorization: Bearer' + + /**********************************************************************/ + /* Create a brand new SList and specify the first header to be an */ + /* "Accept" header that requests that the server return any response */ + /* body text in JSON format. */ + /**********************************************************************/ + ReturnCode = -1 + DiagArea. = '' + if VERBOSE then + say 'Create new SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_NEW ", + "SList ", + "acceptJsonHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_NEW) failure **' ) + end /* endif hwthslst failure */ + /***********************************************************/ + /* Append the Accept-Language request header to the SList */ + /* to infer to the server the regional settings which are */ + /* preferred by this application. */ + /***********************************************************/ + if VERBOSE then + say 'Append to SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_APPEND ", + "SList ", + "acceptLanguageHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_APPEND) failure **' ) + end /* endif hwthslst failure */ + /***********************************************************/ + /* Append the Content-Type request header to the SList */ + /* to specify that the data sent on the put request is in */ + /* JSON format */ + /***********************************************************/ + if VERBOSE then + say 'Append to SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_APPEND ", + "SList ", + "contentTypeHeader ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_APPEND) failure **' ) + end /* endif hwthslst failure */ + +end + /**********************************************************/ + /* ADD the Authorization Request Header if OAUTH */ + /***********************************************************/ + If AuthType= 'OAUTH' then do + + BearerToken = Authorization || ' ' || snow_access_token + + if VERBOSE then + say 'Append to SList' + address hwthttp "hwthslst ", + "ReturnCode ", + "RequestHandle ", + "HWTH_SLST_APPEND ", + "SList ", + "BearerToken ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthslst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthslst (HWTH_SLST_APPEND) failure **' ) + end /* endif hwthslst failure */ + + end + + /************************************/ + /* Set the request headers with the */ + /* just-produced list */ + /************************************/ + if VERBOSE then + say 'Set HWTH_OPT_HTTPHEADERS for request' + ReturnCode = -1 + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "RequestHandle ", + "HWTH_OPT_HTTPHEADERS ", + "SList ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_HTTPHEADERS) failure **' ) + end /* endif hwthset failure */ + + + return 0 /* end function */ + + + + +/*************************************************************/ +/* Function: HTTP_isError */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* set of { HWTH_xx } return codes for evidence of error. */ +/* This set is ordered: HWTH_OK < HWTH_WARNING < ... */ +/* with remaining codes indicating error, so we may check */ +/* via single inequality. */ +/* */ +/* Returns: 1 if any toolkit error is indicated, 0 */ +/* otherwise. */ +/*************************************************************/ +HTTP_isError: + RexxRC = arg(1) + if RexxRC <> 0 then + return 1 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == '' then + return 0 + if ToolkitRC <= HWTH_WARNING then + return 0 + return 1 /* end function */ + + +/*************************************************************/ +/* Function: HTTP_isWarning */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* specific HWTH_WARNING return code. */ +/* */ +/* Returns: 1 if toolkit rc HWTH_WARNING is indicated, 0 */ +/* otherwise. */ +/*************************************************************/ +HTTP_isWarning: + RexxRC = arg(1) + if RexxRC <> 0 then + return 0 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == '' then + return 0 + if ToolkitRC <> HWTH_WARNING then + return 0 + return 1 /* end function */ + + +/***********************************************/ +/* Procedure: HTTP_surfaceDiag() */ +/* */ +/* Surface input error information. Note that */ +/* when the RexxRC is nonzero, the ToolkitRC */ +/* and DiagArea content are moot and are */ +/* suppressed (so as to not mislead). */ +/***********************************************/ +HTTP_surfaceDiag: procedure expose DiagArea. + say + say '*ERROR* ('||arg(1)||') at time: '||Time() + say 'Rexx RC: '||arg(2)', Toolkit ReturnCode: '||arg(3) + say 'DiagArea.Service: '||DiagArea.HWTH_service + say 'DiagArea.ReasonCode: '||DiagArea.HWTH_reasonCode + say 'DiagArea.ReasonDesc: '||DiagArea.HWTH_reasonDesc + say + return /* end procedure */ + + +/***********************************************/ +/* Function: fatalError */ +/* */ +/* Surfaces the input message, and returns */ +/* a canonical failure code. */ +/* */ +/* Returns: -1 to indicate fatal script error. */ +/***********************************************/ + fatalError: + errorMsg = arg(1) + say errorMsg + return -1 /* end function */ + +/***********************************************/ +/* Function: TurnOnVerboseOutput */ +/* */ +/* Sets the zFS UNIX file where the toolkit */ +/* trace will be written */ +/***********************************************/ +TurnOnVerboseOutput: + /**********************************************************/ + say '**** Set HWTH_OPT_VERBOSE_OUTPUT for connection ****' + + traceDataSetName = '' + traceDD = 'HWTTRACE' + + call closeToolkitTrace traceDD + + allocRc = allocateTracefile(traceDataSetName,traceDD) + + DiagArea. = '' + address hwthttp "hwthset ", + "ReturnCode ", + "ConnectionHandle ", + "HWTH_OPT_VERBOSE_OUTPUT ", + "traceDD ", + "DiagArea." + RexxRC = RC + if HTTP_isError(RexxRC,ReturnCode) then + do + call HTTP_surfaceDiag 'hwthset', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwthset (HWTH_OPT_VERBOSE) failure **' ) + end /* endif hwthset failure */ + return + + + /*************************************************/ + /* Procedure: allocateTracefile */ + /* */ + /* Allocate a previously created trace data set */ + /* with the required attributes (which */ + /* must already exist), and a known DDname. */ + /*************************************************/ + allocateTracefile: procedure expose (PROC_GLOBALS) + datasetName = arg(1) + DDname = arg(2) + + /* allocates datasetName to DDName and directs messages */ + /* to z/OS UNIX standard error (sdterr) */ + + alloc = 'alloc fi('||DDname||') ' + /* alloc = alloc||'da('||quoted(datasetName)||') old msg(2)' */ + alloc = alloc || 'sysout recfm(v)' + + call bpxwdyn alloc + allocRc = Result + + return allocRc /* end procedure */ + + /***********************************************************/ + /* Procedure: closeToolkitTrace */ + /* */ + /* Free the ddname which an earlier redirectToolkitTraceXX */ + /* caused allocation to associate with an HFS file. */ + /***********************************************************/ + closeToolkitTrace: procedure expose (PROC_GLOBALS) + DDname = arg(1) + call bpxwdyn 'free fi('DDname')' + return /* end procedure */ + + /*******************************************************/ + /* Function: quoted */ + /*******************************************************/ + quoted: + stringIn = arg(1) + return "'"||stringIn||"'" + +/*****************************************************/ +/* JSON-related functions */ +/* */ +/* These { JSON_xxx } functions are located together */ +/* for ease of reference and are used to demonstrate */ +/* how this portion of the Web Enablement Toolkit */ +/* can be used in conjunction with the Http-related */ +/* toolkit functions. */ +/*****************************************************/ + +/**********************************************************/ +/* Function: JSON_initParser */ +/* */ +/* Initializes the global parserHandle variable via */ +/* call to toolkit service HWTJINIT. */ +/* */ +/* Returns: 0 if successful, -1 if unsuccessful */ +/**********************************************************/ +JSON_initParser: + if VERBOSE then + say 'Initializing Json Parser' + /***********************************/ + /* Call the HWTJINIT toolkit api. */ + /***********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjinit ", + "ReturnCode ", + "handleOut ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjinit', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjinit failure **' ) + end /* endif hwtjinit failure */ + parserHandle = handleOut + if VERBOSE then + say 'Json Parser init (hwtjinit) succeeded' + return 0 /* end function */ + + +/**********************************************************************/ +/* Function: JSON_parse */ +/* */ +/* Parses the input text body (which should be syntactically correct */ +/* JSON text) via call to toolkit service HWTJPARS. */ +/* */ + /* Returns: 0 if successful, -1 if unsuccessful */ +/**********************************************************************/ +JSON_parse: + jsonTextBody = arg(1) + if VERBOSE then + say 'Invoke Json Parser' + /**************************************************/ + /* Call the HWTJPARS toolkit api. */ + /* Parse scans the input text body and creates an */ + /* internal representation of the JSON data, */ + /* suitable for search and create operations. */ + /**************************************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjpars ", + "ReturnCode ", + "parserHandle ", + "jsonTextBody ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjpars', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjpars failure **' ) + end /* endif hwtjpars failure */ + if VERBOSE then + say 'JSON data parsed successfully' + return 0 /* end function */ + + +/*******************************************************************/ +/* Subroutine: JSON_searchAndDeserializeData */ +/* */ +/* Search for specific values and objects in the parsed response */ +/* body, and deserialize them into the distanceData. stem variable */ +/* */ +/*******************************************************************/ +JSON_searchAndDeserializeData: +snowObjectType = arg(1) + +/*-------------------------------------------------------------------*/ +/* Borramos el area del parametro de salida antes de modificarlo */ +/*-------------------------------------------------------------------*/ + Incident. = '' + ChgRequest. ='' + AffectedCI. ='' + SNData. = '' + + select + /*******************************************************************/ + /* return incident attributes got from JSON */ + /*******************************************************************/ + when snowObjectType = 'INC' then do + + /***************************************/ + /* Get Open Date */ + /***************************************/ + Incident.OpenedAt = JSON_findValue( 0, "opened_at", HWTJ_STRING_TYPE ) + Incident.state = JSON_findValue( 0, "state", HWTJ_STRING_TYPE ) + Incident.Active = JSON_findValue( 0, "active", HWTJ_STRING_TYPE ) + Incident.Priority = JSON_findValue( 0, "priority", HWTJ_STRING_TYPE ) + + + end + + when snowObjectType = 'CHG' then do + + /***************************************/ + /* Get Open Date */ + /***************************************/ + ChgRequest.start_date= JSON_findValue( 0,"start_date", HWTJ_STRING_TYPE) + ChgRequest.end_date = JSON_findValue( 0,"end_date", HWTJ_STRING_TYPE) + ChgRequest.state = JSON_findValue( 0,"state", HWTJ_STRING_TYPE ) + ChgRequest.Active = JSON_findValue( 0,"active", HWTJ_STRING_TYPE ) + ChgRequest.sys_id = JSON_findValue( 0,"sys_id", HWTJ_STRING_TYPE ) + ChgRequest.number = JSON_findValue( 0,"number", HWTJ_STRING_TYPE ) + ChgRequest.approval = JSON_findValue( 0,"approval", HWTJ_STRING_TYPE ) + + end + + when snowObjectType = 'NEWCHG' then do + + /***************************************/ + /* Get Open Date */ + /***************************************/ + CHG_Obj = JSON_findValue( 0, "result", HWTJ_OBJECT_TYPE ) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"number", HWTJ_OBJECT_TYPE ) + ChgRequest.number = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"state", HWTJ_OBJECT_TYPE ) + ChgRequest.state = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"active", HWTJ_OBJECT_TYPE ) + ChgRequest.active = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"sys_id", HWTJ_OBJECT_TYPE ) + ChgRequest.sys_id = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"approval", HWTJ_OBJECT_TYPE ) + ChgRequest.approval = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"start_date", HWTJ_OBJECT_TYPE ) + ChgRequest.start_date = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + CHG_Num_obj = JSON_findValue(CHG_Obj,"end_date", HWTJ_OBJECT_TYPE ) + ChgRequest.start_date = JSON_findValue(CHG_Num_obj,, + "display_value",, + HWTJ_STRING_TYPE) + + end + + when snowObjectType = 'TASK' then do + end + + otherwise + nop + end + + return /* end subroutine */ +/******************************************************************/ +/* Function: JSON_findValue */ +/* */ +/* Searches the appropriate portion of the parsed JSON data (that */ +/* designated by the objectToSearch argument) for an entry whose */ +/* name matches the designated searchName argument. Returns a */ +/* value or handle, depending on the expectedType. */ +/* */ +/* Returns: value or handle as described above, or a null result */ +/* if no suitable value or handle is found. */ +/******************************************************************/ +JSON_findValue: + objectToSearch = arg(1) /* 0 */ + searchName = arg(2) /* label */ + expectedType = arg(3) /* tipo de dato */ + + +/*********************************************************/ +/* Trying to find a value for a null entry is perhaps a */ +/* bit nonsensical, but for completeness we include the */ +/* possibility. We make an arbitrary choice on what to */ +/* return, and do this first, to avoid wasted processing */ +/*********************************************************/ + if expectedType == HWTJ_NULL_TYPE then + return '(null)' + if VERBOSE then + say 'Invoke Json Search' + /********************************************************/ + /* Search the specified object for the specified name. */ + /* The value 0 is specified (for the "startingHandle") */ + /* to indicate that the search should start at the */ + /* beginning of the designated object. */ + /********************************************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjsrch ", + "ReturnCode ", + "parserHandle ", + "HWTJ_SEARCHTYPE_OBJECT ", + "searchName ", + "objectToSearch ", + "0 ", + "searchResult ", + "DiagArea." + RexxRC = RC + /************************************************************/ + /* Differentiate a not found condition from an error, and */ + /* tolerate the former. Note the order dependency here, */ + /* at least as the called routines are currently written. */ + /************************************************************/ + if JSON_isNotFound(RexxRC,ReturnCode) then + return '(not found)' + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjsrch', RexxRC, ReturnCode, DiagArea. + say '** hwtjsrch failure **' + return '' + end /* endif hwtjsrch failed */ + /******************************************/ + /* Verify the type of the search result */ + /******************************************/ + resultType = JSON_getType( searchResult ) + if resultType <> expectedType then + do + say '** Type mismatch ('||resultType||','||expectedType||') **' + return '' + end /* endif unexpected type */ + /******************************************************/ + /* Return the located object or array, as appropriate */ + /******************************************************/ + if expectedType == HWTJ_OBJECT_TYPE | expectedType == HWTJ_ARRAY_TYPE then + do + return searchResult + end /* endif object or array type */ + /*******************************************************/ + /* Return the located string or number, as appropriate */ + /*******************************************************/ + if expectedType == HWTJ_STRING_TYPE | expectedType == HWTJ_NUMBER_TYPE then + do + if VERBOSE then + say 'Invoke Json Get Value' + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjgval ", + "ReturnCode ", + "parserHandle ", + "searchResult ", + "result ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgval', RexxRC, ReturnCode, DiagArea. + say '** hwtjgval failure **' + return '' + end /* endif hwtjgval failed */ + + return result + end /* endif string or number type */ + /****************************************************/ + /* Return the located boolean value, as appropriate */ + /****************************************************/ + if expectedType == HWTJ_BOOLEAN_TYPE then + do + if VERBOSE then + say 'Invoke Json Get Boolean Value' + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjgbov ", + "ReturnCode ", + "parserHandle ", + "searchResult ", + "result ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgbov', RexxRC, ReturnCode, DiagArea. + say '** hwtjgbov failure **' + return '' + end /* endif hwtjgbov failed */ + return result + end /* endif boolean type */ + if VERBOSE then + say '** No return value found **' + return '' /* end function */ + + +/***********************************************************/ +/* Function: JSON_getType */ +/* */ +/* Determine the Json type of the designated search result */ +/* via the HWTJGJST toolkit api. */ +/* */ +/* Returns: Non-negative integral number indicating type */ +/* if successful, -1 if not. */ +/***********************************************************/ +JSON_getType: + searchResult = arg(1) + if VERBOSE then + say 'Invoke Json Get Type' + /*********************************/ + /* Call the HWTHGJST toolkit api */ + /*********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjgjst ", + "ReturnCode ", + "parserHandle ", + "searchResult ", + "resultTypeName ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgjst', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgjst failure **' ) + end /* endif hwtjgjst failure */ + else + do + /******************************************************/ + /* Convert the returned type name into its equivalent */ + /* constant, and return that more convenient value. */ + /* Note that the interpret instruction might more */ + /* typically be used here, but the goal here is to */ + /* familiarize the reader with these types. */ + /******************************************************/ + type = strip(resultTypeName) + if type == 'HWTJ_STRING_TYPE' then + return HWTJ_STRING_TYPE + if type == 'HWTJ_NUMBER_TYPE' then + return HWTJ_NUMBER_TYPE + if type == 'HWTJ_BOOLEAN_TYPE' then + return HWTJ_BOOLEAN_TYPE + if type == 'HWTJ_ARRAY_TYPE' then + return HWTJ_ARRAY_TYPE + if type == 'HWTJ_OBJECT_TYPE' then + return HWTJ_OBJECT_TYPE + if type == 'HWTJ_NULL_TYPE' then + return HWTJ_NULL_TYPE + end + /***********************************************/ + /* This return should not occur, in practice. */ + /***********************************************/ + return fatalError( 'Unsupported Type ('||type||') from hwtjgjst' ) + + +/**********************************************************/ +/* Function: JSON_termParser */ +/* */ +/* Cleans up parser resources and invalidates the parser */ +/* instance handle, via call to the HWTJTERM toolkit api. */ +/* Note that as the REXX environment is single-threaded, */ +/* no consideration of any "busy" outcome from the api is */ +/* done (as it would be in other language environments). */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/**********************************************************/ +JSON_termParser: + if VERBOSE then + say 'Terminate Json Parser' + /**********************************/ + /* Call the HWTJTERM toolkit api */ + /**********************************/ + ReturnCode = -1 + DiagArea. = '' + address hwtjson "hwtjterm ", + "ReturnCode ", + "parserHandle ", + "DiagArea." + RexxRC = RC + if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjterm', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjterm failure **' ) + end /* endif hwtjterm failure */ + if VERBOSE then + say 'Json Parser terminated' + return 0 /* end function */ + + +/*************************************************************/ +/* Function: JSON_isNotFound */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* specific return code for a "not found" condition. */ +/* */ +/* Returns: 1 if a HWTJ_JSRCH_SRCHSTR_NOT_FOUND condition */ +/* is indicated, 0 otherwise. */ +/*************************************************************/ +JSON_isNotFound: + RexxRC = arg(1) + if RexxRC <> 0 then + return 0 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == HWTJ_JSRCH_SRCHSTR_NOT_FOUND then + return 1 + return 0 /* end function */ + + +/*************************************************************/ +/* Function: JSON_isError */ +/* */ +/* Check the input processing codes. Note that if the input */ +/* RexxRC is nonzero, then the toolkit return code is moot */ +/* (the toolkit function was likely not even invoked). If */ +/* the toolkit return code is relevant, check it against the */ +/* set of { HWTJ_xx } return codes for evidence of error. */ +/* This set is ordered: HWTJ_OK < HWTJ_WARNING < ... */ +/* with remaining codes indicating error, so we may check */ +/* via single inequality. */ +/* */ +/* Returns: 1 if any toolkit error is indicated, 0 */ +/* otherwise. */ +/*************************************************************/ +JSON_isError: + RexxRC = arg(1) + if RexxRC <> 0 then + return 1 + ToolkitRC = strip(arg(2),'L',0) + if ToolkitRC == '' then + return 0 + if ToolkitRC <= HWTJ_WARNING then + return 0 + return 1 /* end function */ + + +/***********************************************/ +/* Procedure: JSON_surfaceDiag */ +/* */ +/* Surface input error information. Note that */ +/* when the RexxRC is nonzero, the ToolkitRC */ +/* and DiagArea content are moot and are */ +/* suppressed (so as to not mislead). */ +/* */ +/***********************************************/ +JSON_surfaceDiag: procedure expose DiagArea. + who = arg(1) + RexxRC = arg(2) + ToolkitRC = arg(3) + say + say '*ERROR* ('||who||') at time: '||Time() + say 'Rexx RC: '||RexxRC||', Toolkit ReturnCode: '||ToolkitRC + if RexxRC == 0 then + do + say 'DiagArea.ReasonCode: '||DiagArea.ReasonCode + say 'DiagArea.ReasonDesc: '||DiagArea.ReasonDesc + end + say + return /* end procedure */ + + +/*******************************************************/ +/* Function: quoted */ +/*******************************************************/ +quoted: + stringIn = arg(1) +return "'"||stringIn||"'" +/*******************************************************/ +/* Function: delay */ +/*******************************************************/ +delay: + /* Rexx Delay */ + DelaySec = 0.250000 /* readable width */ + elapsed = TIME(R) + do until elapsed >= DelaySec + elapsed = TIME('E') + end +return + +/***********************************************/ +/* Function: usage */ +/* */ +/* Provide usage guidance to the invoker. */ +/* */ +/* Returns: -1 to indicate fatal script error. */ +/***********************************************/ +usage: + whyString = arg(1) + say + say 'usage:' + say 'ex SNOWOAUT ' + say ' ' + say + say '('||whyString||')' + say + return -1 /* end function */ + + /***********************************************/ +/* Function: GetArgs */ +/* */ +/* Parse script arguments and make appropriate */ +/* variable assignments, or return fatal error */ +/* code via usage() invocation. */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/***********************************************/ +GetArgs: + S = arg(1) + argCount = words(S) + if argCount == 0 | argCount < 3 | argCount > 4 then + return usage( 'Wrong number of arguments' ) + + do i = 1 to argCount + localArg = word(S,i) + select + when (i == 1) then + do + apikey = localArg + end + when (i == 2) | (i == 3) then + call parseLocation + otherwise + if localArg == '-v' then + VERBOSE = 1 + end + end +return 0 /* end function */ + + +/***********************************************/ +/* Function: get_AffectedCI_List */ +/* */ +/* get the Affecte CI list of a CHG Request */ +/***********************************************/ +get_AffectedCI_List: + sys_id = arg(1) + ACI_List. = arg(2) + +call HTTP_setupRequest "TASK", sys_id, "TASK" +if RESULT <> 0 then +cleanup('CONREQ','** Submit job request failed to be setup **') + +/* Make the request to ServiceNow */ +call HTTP_request +if RESULT <> 0 then +cleanup('CONREQ','** ServiceNow request failed **') + +/* Analyze ServiceNow ChanheRequest (Response Body) json */ +if VERBOSE then + say 'response body snow TASK 'sys_id': ' ||ResponseBody + +if ResponseStatusCode == HTTP_OK then +Do + call Process_task_ci_json ResponseBody, ACI_List. + + if result <> 0 Then do + say '*** Error during JSON correlation ***' + end + else do + programRc = 0 + end +End +else Do + say '***Bad resp received: 'ResponseStatusCode'.' +end + +return programRc + + +/***********************************************/ +/* Function: Process_task_ci_json */ +/* */ +/* help implementing new functionalities */ +/* using as example a json text read from a */ +/* file. */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/***********************************************/ + +Process_task_ci_json: + jsonTEXT = arg(1) + ACI_List. = arg(2) + +say 'Response Body received at Process_task_ci_json: 'jsonTEXT +call JSON_initParser +if RESULT <> 0 then + return fatalError( '** Pre-processing error (parser init failure) **' ) + +/****************************/ +/* Parse the response data. */ +/****************************/ +call JSON_parse jsonTEXT +if RESULT <> 0 then + do + call JSON_termParser + return fatalError( '** Error while parsing Input JSON Text **' ) + end +/*****************************************/ +/* Extract specific data and surface it, */ +/* then release the parser instance. */ +/*****************************************/ +if VERBOSE then + say 'Getting number of elements returned in the array of objects' + +AffectedCIsList = JSON_findValue( 0, "result", HWTJ_ARRAY_TYPE ) + +/* NumOfElements = 0 */ + +address hwtjson "hwtjgnue ", + "ReturnCode ", + "parserHandle ", + "AffectedCIsList ", + "NumOfAffectedCIs ", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then +do + call JSON_surfaceDiag 'hwtjgnue', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgnue failure **' ) +end /* endif hwtjinit failure */ + +/*Say 'Number of affected CIs in the Change Request: 'NumOfAffectedCIs +say '' */ + +/* Process each element of the array of objects */ + +ACI_List.0 = NumOfAffectedCIs + +do AffectedCI=0 to NumOfAffectedCIs-1 + +address hwtjson "hwtjgaen ", + "ReturnCode ", + "ParserHandle ", + "AffectedCIsList ", + "AffectedCI", + "EntryValueHandle", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgaen', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgaen failure **' ) + end /* endif hwtjinit failure */ + + Entry = AffectedCI+1 + display_val = JSON_findValue( EntryValueHandle, + ,"display_value" , + ,HWTJ_STRING_TYPE) + + ACI_List.Entry.display_value = display_val + + + created_on = JSON_findValue( EntryValueHandle, + ,"sys_created_on" , + ,HWTJ_STRING_TYPE) + + ACI_List.Entry.sys_created_on = created_on + + + + /* say ' Affected CI 'AffectedCI+1': 'ACI_List.Entry.display_value + say ' Affected CI 'AffectedCI+1': 'ACI_List.Entry.sys_created_on */ + + +end /* do AffectedCI */ + +call JSON_termParser + +return 0 + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ + +/***********************************************/ +/* Function: debug_json_text */ +/* */ +/* help implementing new functionalities */ +/* using as example a json text read from a */ +/* file. */ +/* */ +/* Returns: 0 if successful, -1 if not. */ +/***********************************************/ + +debug_json_text: + +/* Validate the JSON Text read from ddname JSONIN */ +/* and copied in responsebody */ + +"execio 1 diskr JSONIN (stem jsonIN." + +jsonTEXT = strip(jsonIN.1) +say '' +say 'JSON Text read from File: ' +say '' +say jsonTEXT +say '' + +/* */ +call JSON_initParser +if RESULT <> 0 then + return fatalError( '** Pre-processing error (parser init failure) **' ) +/****************************/ +/* Parse the response data. */ +/****************************/ +call JSON_parse jsonTEXT +if RESULT <> 0 then + do + call JSON_termParser + return fatalError( '** Error while parsing Input JSON Text **' ) + end +/*****************************************/ +/* Extract specific data and surface it, */ +/* then release the parser instance. */ +/*****************************************/ +if VERBOSE then +say 'Getting number of elements returned in the array of objects' + +AffectedCIsList = JSON_findValue( 0, "result", HWTJ_ARRAY_TYPE ) + +/* NumOfElements = 0 */ + +address hwtjson "hwtjgnue ", + "ReturnCode ", + "parserHandle ", + "AffectedCIsList ", + "NumOfAffectedCIs ", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then +do + call JSON_surfaceDiag 'hwtjgnue', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgnue failure **' ) +end /* endif hwtjinit failure */ + +Say 'Number of affected CIs in the Change Request: 'NumOfAffectedCIs +say '' + +/* Process each element of the array of objects */ + +do AffectedCI=0 to NumOfAffectedCIs-1 + +address hwtjson "hwtjgaen ", + "ReturnCode ", + "ParserHandle ", + "AffectedCIsList ", + "AffectedCI", + "EntryValueHandle", + "DiagArea." + +RexxRC = RC +if JSON_isError(RexxRC,ReturnCode) then + do + call JSON_surfaceDiag 'hwtjgaen', RexxRC, ReturnCode, DiagArea. + return fatalError( '** hwtjgaen failure **' ) + end /* endif hwtjinit failure */ + + disp_val=JSON_findValue( EntryValueHandle,"display_value" , + ,HWTJ_STRING_TYPE) + + say ' Affected CI 'AffectedCI+1': 'disp_val + +end /* do AffectedCI */ + +call JSON_termParser + +return 100 + +./ ADD NAME=SNOWCUST +/* rexx */ +/*********************************************************************/ +/* AUTHOR. (C) 2025 Broadcom */ +/* Jose Benigno Gonzalez for JPCM. */ +/* */ +/* Validates Endevor CCID against ServiceNow change request and */ +/* Incident Management Module - Called from Endevor Exit 2 */ +/* */ +/* Currently in Dev Phase: */ +/* Validates the first ten characters of the packageID against */ +/* ServiceNow change request and Incident Management Module - Called */ +/* from Endevor Exit 7 */ +/* */ +/*********************************************************************/ +trace off + +argstr = ARG(1) +hexs = C2X(argstr) + +hwtRC = call hwtcalls 'on' +if hwtRC > 0 THEN do + say "cannot establish hwtcalls environment rc="hwtRC + exit hwtRC +end + +verbose= 0 +SnowTrc_RC = bpxwdyn("info fi(snowtrc) INRTTYP(variable)") +If SnowTrc_RC = 0 Then do + Verbose = 1 +end + +/* + Allocation of mandatory ddnames for BPXBATCH +*/ + +If Verbose then exitrc = bpxwdyn("alloc fi(STDOUT) sysout") + else exitrc = bpxwdyn("alloc fi(STDOUT) ", + "dsorg(ps) lrecl(16383) ", + "SPACE(5,1) CYL RECFM(F,B) new delete ") + +If exitRC <> 0 Then Do + say 'DynAlloc error for STDOUT DDname: 'exitRC + call Issue_Message(exitrc) + Return exitRC +End + +If Verbose then exitrc = bpxwdyn("alloc fi(STDERR) sysout") + else exitrc = bpxwdyn("alloc fi(STDERR) ", + "dsorg(ps) lrecl(512) ", + "SPACE(10) TRACKS RECFM(F,B) new delete") + +If exitRC <> 0 Then Do + say 'DynAlloc error for STDERR DDname: 'exitRC + call Issue_Message(exitrc) + Return exitRC +End + +exitrc = bpxwdyn("alloc dd(stdenv) ", + "lrecl(80) recfm(f,b) tracks space(5,1) ", + "new delete") + +If exitRC <> 0 Then Do + say 'DynAlloc error for STDENV DDname: 'exitRC + call Issue_Message(exitrc) + Return exitRC +End + +STDENV_Rec = '_BPX_SHAREAS=YES' +queue Left(STDENV_Rec,80) + +STDENV_Rec = '_BPX_BATCH_SPAWN=YES' +queue Left(PARMIN_Rec,80) + +"Execio" queued() "Diskw STDENV (FINIS" + +/* + Call the servicenow driver interface +*/ +cmd = 'SH /u/users/gonjo08/rexx/JPMC_ndvrsnow.rexx' +cmd = cmd || ' ' ||hexs + +prog = 'BPXBATCH' +address 'ATTCHMVS' prog 'cmd' + +BPX_rc = rc + + +exitrc = bpxwdyn("free dd(STDOUT)") +exitrc = bpxwdyn("free dd(STDERR)") +exitrc = bpxwdyn("free dd(STDENV)") + + +sysRC = syscalls('OFF') + +return BPX_rc + +/*****************************************************************/ +/* Procedures */ +/*****************************************************************/ +Issue_Message: Procedure expose s99msg. +Parse ARG exitrc +Numeric digits 10 +Select + when ((exitrc <= -1610612737) & (exitrc >= -2147483648)) |, + (exitrc > 0) Then + Do + /***************************************************************/ + /* */ + /* Ha ocurrido un Error durante la Alocacion Dinamica */ + /* */ + /***************************************************************/ + RetCodeX = D2X(exitrc,8) + say ' ' + say ' *************************************************' + say ' * DynAlloc S99Error: 'substr(RetCodeX,1,4)' *' + say ' * DynAlloc S99Info : 'substr(RetCodeX,5,4)' *' + say ' *************************************************' + say ' ' + if s99msg.0 > 0 then + Do + Say 'DYNALC02E Mensajes de Error S99msg DynAlloc: ' + say ' ' + Do I = 1 Until I = s99msg.0 + say ' 's99msg.i + End + End /* S99msg.o */ + End /* Do exitrc */ + When (exitrc <= -21) & (exitrc >= -99) then + Do + Clave = (exitrc+20) * -1 + say ' ' + Say 'DYNALC03E Error en la clave 'Clave' pasada a DynAlloc', + 'desde programa bpxwdyn.' + End + When (exitrc = 20) then + Do + say ' ' + Say 'DYNALC04E Lista de Parametros de bpxwdyn incorrecta.' + Say ' Revise el manual Using REXX and z/OS UNIX', + 'System Services, para mayor informacion.' + End + When substr(exitrc,2,3) = 100 then + Do + nop + End + Otherwise + nop +End /* Select */ +return + diff --git a/endevor/ServiceNow-Interface/ServiceNow.py b/endevor/ServiceNow-Interface/ServiceNow.py deleted file mode 100644 index 81c65cd..0000000 --- a/endevor/ServiceNow-Interface/ServiceNow.py +++ /dev/null @@ -1,38 +0,0 @@ -# -import os #Import standard Python os lib -import platform #Import standard Python platform lib s -import sys #Import standard Python sys lib -import requests -from requests.auth import HTTPBasicAuth -import json - -print("Script name:", sys.argvÝ0¨) - -## Build the complete url here -url = "https://somewhere.service-now.com/api/now/table/problem?sysparm_query=number=" -print("#Arguments:", sys.argvÝ1:¨) # Additional arguments passed -listticketnumber = sys.argvÝ1:2¨ -print("#listticketnumber :", type(listticketnumber), listticketnumber) -ticketnumber = listticketnumberÝ0¨ -ticketnumberType = type(ticketnumber) -print('#' + ticketnumberType, ticketnumber) -url = url + ticketnumber -print("#url:", url) # complete url -# -response = requests.get(url, auth=HTTPBasicAuth('user', 'passw') -print(response.content) -out = json.loads(response.content) -n = outÝ'result'¨ - -# -#n type -#out type -# - -if len(n) == 0: - print("error - no output") -elif "number" in nÝ0¨.keys(): - print("Exists") -else: - print("error - not found") - \ No newline at end of file