diff --git a/tests/zwe-remote-integration/package-lock.json b/tests/zwe-remote-integration/package-lock.json index 498a45332f..50039e9e89 100644 --- a/tests/zwe-remote-integration/package-lock.json +++ b/tests/zwe-remote-integration/package-lock.json @@ -16,6 +16,7 @@ "@types/jest": "^29.5.12", "@types/lodash": "^4.17.3", "@types/node": "20.12.7", + "@types/node-ssh": "^7.0.6", "@types/semver": "^7.5.8", "@types/xml2js": "0.4.14", "@types/yaml": "^1.9.7", @@ -40,6 +41,7 @@ "json-schema-to-ts": "^3.1.0", "lodash": "^4.17.21", "node-jq": "^4.3.1", + "node-ssh": "^13.2.0", "prettier": "3.2.5", "semver": "^7.6.2", "ts-jest": "29.1.2", @@ -2062,12 +2064,50 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/node-ssh": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/node-ssh/-/node-ssh-7.0.6.tgz", + "integrity": "sha512-XHyzfQ8/PW1C6VEW1f5tZntd6rFyppxXClDtxLvG311vWq46oQWa5ztCOPGNC0KIJekE8G6fd6NqmwIct63XmA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/ssh2": "*", + "@types/ssh2-streams": "*" + } + }, "node_modules/@types/semver": { "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, + "node_modules/@types/ssh2": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.0.tgz", + "integrity": "sha512-YcT8jP5F8NzWeevWvcyrrLB3zcneVjzYY9ZDSMAMboI+2zR1qYWFhwsyOFVzT7Jorn67vqxC0FRiw8YyG9P1ww==", + "dev": true, + "dependencies": { + "@types/node": "^18.11.18" + } + }, + "node_modules/@types/ssh2-streams": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.12.tgz", + "integrity": "sha512-Sy8tpEmCce4Tq0oSOYdfqaBpA3hDM8SoxoFh5vzFsu2oL+znzGz8oVWW7xb4K920yYMUY+PIG31qZnFMfPWNCg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ssh2/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/stack-utils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", @@ -7470,6 +7510,47 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node_modules/node-ssh": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/node-ssh/-/node-ssh-13.2.0.tgz", + "integrity": "sha512-7vsKR2Bbs66th6IWCy/7SN4MSwlVt+G6QrHB631BjRUM8/LmvDugtYhi0uAmgvHS/+PVurfNBOmELf30rm0MZg==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "make-dir": "^3.1.0", + "sb-promise-queue": "^2.1.0", + "sb-scandir": "^3.1.0", + "shell-escape": "^0.2.0", + "ssh2": "^1.14.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/node-ssh/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-ssh/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/nopt": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", @@ -8834,6 +8915,27 @@ "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", "dev": true }, + "node_modules/sb-promise-queue": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sb-promise-queue/-/sb-promise-queue-2.1.0.tgz", + "integrity": "sha512-zwq4YuP1FQFkGx2Q7GIkZYZ6PqWpV+bg0nIO1sJhWOyGyhqbj0MsTvK6lCFo5TQwX5pZr6SCQ75e8PCDCuNvkg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/sb-scandir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/sb-scandir/-/sb-scandir-3.1.0.tgz", + "integrity": "sha512-70BVm2xz9jn94zSQdpvYrEG101/UV9TVGcfWr9T5iob3QhCK4lYXeculfBqPGFv3XTeKgx4dpWyYIDeZUqo4kg==", + "dev": true, + "dependencies": { + "sb-promise-queue": "^2.1.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/seek-bzip": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", @@ -8887,6 +8989,12 @@ "node": ">=8" } }, + "node_modules/shell-escape": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz", + "integrity": "sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw==", + "dev": true + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", diff --git a/tests/zwe-remote-integration/package.json b/tests/zwe-remote-integration/package.json index 7d5d746cd7..58c94fbba9 100644 --- a/tests/zwe-remote-integration/package.json +++ b/tests/zwe-remote-integration/package.json @@ -12,6 +12,7 @@ "@types/jest": "^29.5.12", "@types/lodash": "^4.17.3", "@types/node": "20.12.7", + "@types/node-ssh": "^7.0.6", "@types/semver": "^7.5.8", "@types/xml2js": "0.4.14", "@types/yaml": "^1.9.7", @@ -33,7 +34,10 @@ "jest": "29.7.0", "jest-junit": "16.0.0", "jfrog-client-js": "^2.8.0", + "json-schema-to-ts": "^3.1.0", "lodash": "^4.17.21", + "node-jq": "^4.3.1", + "node-ssh": "^13.2.0", "prettier": "3.2.5", "semver": "^7.6.2", "ts-jest": "29.1.2", @@ -41,9 +45,7 @@ "typescript": "5.4.5", "xml2js": "0.6.2", "yaml": "^2.4.2", - "yn": "4.0.0", - "json-schema-to-ts": "^3.1.0", - "node-jq": "^4.3.1" + "yn": "4.0.0" }, "scripts": { "build": "tsc", diff --git a/tests/zwe-remote-integration/resources/test_config.yml b/tests/zwe-remote-integration/resources/test_config.yml index 172fa81ff9..7499745bbc 100644 --- a/tests/zwe-remote-integration/resources/test_config.yml +++ b/tests/zwe-remote-integration/resources/test_config.yml @@ -39,6 +39,8 @@ remote_teardown: true test_ds_hlq: # All test suite and test case datasets use the volume specified below test_volume: +# Storclas is used when tests require an SMS managed DS. If missing, SMS tests will be skipped. +test_storclas: zosmf_reject_unauthorized: # Download configmgr and zowe-install-packaging-tools using the manifest.json in this repo. ## If set to false, you can use a custom build of either artifact by placing them in the .build/ dir diff --git a/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/apfauth.test.ts.snap b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/apfauth.test.ts.snap index 45e007b566..88bdffe0af 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/apfauth.test.ts.snap +++ b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/apfauth.test.ts.snap @@ -32,15 +32,56 @@ Validity Exceptions(s) with object at `; exports[`init-apfauth (SHORT) apf bad authLoadLib 1`] = ` -" -$ Temporary directory '/tmp/.zweenv-0000' created. +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x103d chunk=0x1000 extend=0x103d +------------------------------------------------------------------------------- +>> APF authorize load libraries + +ERROR: * Exit code: 8 +ERROR: * Output: +ERROR: listds 'DOES.NOT.EXIST' label + DOES.NOT.EXIST + IKJ58503I DATA SET 'DOES.NOT.EXIST' NOT IN CATALOG +ERROR: Error ZWEL0320E: The dataset specified in 'zowe.setup.dataset.authLoadlib' does not exist." +`; + +exports[`init-apfauth (SHORT) apf bad authPluginLib 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x103e chunk=0x1000 extend=0x103e ------------------------------------------------------------------------------- >> APF authorize load libraries -Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEGENER) ---- JCL content --- -//ZWEGENER JOB +ERROR: * Exit code: 8 +ERROR: * Output: +ERROR: listds 'DOES.NOT.EXIST' label + DOES.NOT.EXIST + IKJ58503I DATA SET 'DOES.NOT.EXIST' NOT IN CATALOG +ERROR: Error ZWEL0320E: The dataset specified in 'zowe.setup.dataset.authPluginLib' does not exist." +`; + +exports[`init-apfauth (SHORT) apf empty jcllib post-generate 1`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/dataset + Validity Exceptions(s) with string at /zowe/setup/dataset/jcllib + string too short (len=0) '' 0 < MIN=3 at /zowe/setup/dataset/jcllib + string pattern match fail s='', pat='^([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}(\\.([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}){0,11}$', at /zowe/setup/dataset/jcllib" +`; + +exports[`init-apfauth (SHORT) apf simple --dry-run 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x1047 chunk=0x1000 extend=0x1047 +------------------------------------------------------------------------------- +>> APF authorize load libraries + +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEIAPF2) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWEIAPF2) +--- JCL Content --- +//ZWEIAPF2 JOB //* //* This program and the accompanying materials are made available //* under the terms of the Eclipse Public License v2.0 which @@ -53,132 +94,204 @@ Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEGENER) //* //********************************************************************* //* -//* This job is responsible for generating other jobs required -//* to configure Zowe. +//* This JCL is used to set APF for the two datasets of Zowe +//* Which need it. You can issue this, or use another +//* Way to accomplish the task. //* -//* The method of validating your configuration is using -//* JSON Schema . Zowe provides -//* the ConfigMgr to assist in this. This job will invoke -//* the ConfigMgr to validate your current configuration -//* before generating any jobs. If there are any values -//* that are incorrect, you will be notified. You should -//* fix the value and then run this job again. You can run -//* this job as many times as you need. +//* The following variables are derived from the zowe YAML config: +//* LOADLIB: the dataset that holds the APF portion of Zowe +//* PLUGLIB: The dataset that holds the extensions for ZIS. //* -//* Configmgr documentation: -//* https://docs.zowe.org/stable/user-guide/configmgr-using +//********************************************************************* //* -//* Note: Any string with braces has an associated yaml value -//* in one of the yaml definitions for Zowe. -//* You must find the value and substitute it. +//APFAUTH EXEC PGM=BPXBATCH +//BPXPRINT DD SYSOUT=* +//STDOUT DD SYSOUT=* +//STDERR DD SYSOUT=* +//STDPARM DD * +SH cd '/test/dir' && +cd bin/utils && +export LOADLIB='TEST.DATASET.PFX.SZWELOAD' && +export LOADLOC="VOLUME=TSTVOL" && +export PLUGLIB='TEST.DATASET.PFX.ZWESAPL' && +export PLUGLOC="VOLUME=TSTVOL" && +./opercmd.rex "SETPROG APF,ADD,DSN=$LOADLIB,$LOADLOC" && +./opercmd.rex "SETPROG APF,ADD,DSN=$PLUGLIB,$PLUGLOC" //* -//* {key} -> value +--- End of JCL --- +JCL not submitted, command run with "--dry-run" flag. +To perform command, re-run command without "--dry-run" flag, or submit the JCL directly + +>> Command run successfully. + + +>> Zowe load libraries are APF authorized successfully." +`; + +exports[`init-apfauth (SHORT) apf sms-managed authLoadLib 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x104a chunk=0x1000 extend=0x104a +------------------------------------------------------------------------------- +>> APF authorize load libraries + +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEIAPF2) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWEIAPF2) +--- JCL Content --- +//ZWEIAPF2 JOB //* -//GENER EXEC PGM=IKJEFT1B -//ISPPROF DD DSN=,DISP=(NEW,DELETE),UNIT=, -// DCB=(RECFM=FB,LRECL=80,BLKSIZE=3120,DSORG=PO), -// SPACE=(3120,(20,5,10)) +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html //* -//* Replace TEST.DATASET.PFX with the -//* Value as seen in zowe.yaml +//* SPDX-License-Identifier: EPL-2.0 //* -//SYSPROC DD DSN=TEST.DATASET.PFX.SZWEEXEC,DISP=SHR +//* Copyright Contributors to the Zowe Project. 2020, 2020 //* -//* Replace TEST.DATASET.PFX with the -//* Value as seen in zowe.yaml +//********************************************************************* //* -//STEPLIB DD DSN=TEST.DATASET.PFX.SZWELOAD,DISP=SHR -//ISPPLIB DD DSN=ISP.SISPPENU,DISP=SHR -//ISPMLIB DD DSN=ISP.SISPMENU,DISP=SHR -//ISPTLIB DD DSN=ISP.SISPTENU,DISP=SHR -//ISPSLIB DD DSN=ISP.SISPSENU,DISP=SHR +//* This JCL is used to set APF for the two datasets of Zowe +//* Which need it. You can issue this, or use another +//* Way to accomplish the task. //* -//* The order must be as follows. +//* The following variables are derived from the zowe YAML config: +//* LOADLIB: the dataset that holds the APF portion of Zowe +//* PLUGLIB: The dataset that holds the extensions for ZIS. //* -//* zowe-yaml-schema.json -//* server-common.json +//********************************************************************* //* -//* Replace /test/dir with where your Zowe run time -//* directory is, as seen in zowe.yaml +//APFAUTH EXEC PGM=BPXBATCH +//BPXPRINT DD SYSOUT=* +//STDOUT DD SYSOUT=* +//STDERR DD SYSOUT=* +//STDPARM DD * +SH cd '/test/dir' && +cd bin/utils && +export LOADLIB='TEST.DATASET.PFX.SZWELOAD' && +export LOADLOC=SMS && +export PLUGLIB='TEST.DATASET.PFX.ZWESAPL' && +export PLUGLOC="VOLUME=TSTVOL" && +./opercmd.rex "SETPROG APF,ADD,DSN=$LOADLIB,$LOADLOC" && +./opercmd.rex "SETPROG APF,ADD,DSN=$PLUGLIB,$PLUGLOC" //* -//MYSCHEMA DD *,DLM=$$ -FILE /test/dir/schemas/zowe-yaml-schema.json -FILE /test/dir/schemas/server-common.json -$$ +--- End of JCL --- +JCL not submitted, command run with "--dry-run" flag. +To perform command, re-run command without "--dry-run" flag, or submit the JCL directly + +>> Command run successfully. + + +>> Zowe load libraries are APF authorized successfully." +`; + +exports[`init-apfauth (SHORT) apf sms-managed authLoadLib and authPluginLib 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x104e chunk=0x1000 extend=0x104e +------------------------------------------------------------------------------- +>> APF authorize load libraries + +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEIAPF2) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWEIAPF2) +--- JCL Content --- +//ZWEIAPF2 JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html //* -//* The DD below must include one or more FILE or PARMLIB -//* Entries. The lower entries have their values -//* Overridden by the higher entries. -//* PARMLIB member must be named "ZWEYAML" +//* SPDX-License-Identifier: EPL-2.0 //* -//* Do not remove the defaults.yaml entry. +//* Copyright Contributors to the Zowe Project. 2020, 2020 //* -//* Ex. PARMLIB MY.ZOWE.CUSTOM.PARMLIB -//* FILE /the/zowe/defaults.yaml -//MYCONFIG DD *,DLM=$$ -FILE /test/dir/zowe.test.yaml -FILE /test/dir/files/defaults.yaml -$$ -//CMGROUT DD SYSOUT=* -//SYSPRINT DD SYSOUT=* -//SYSTSPRT DD SYSOUT=* +//********************************************************************* //* -//* Change 'generate' to 'nogenerate' if you only -//* want to validate your configuration. The default -//* option, 'generate', will validate and then generate -//* jobs based on your configuration. +//* This JCL is used to set APF for the two datasets of Zowe +//* Which need it. You can issue this, or use another +//* Way to accomplish the task. //* -//* - generate -//* - nogenerate +//* The following variables are derived from the zowe YAML config: +//* LOADLIB: the dataset that holds the APF portion of Zowe +//* PLUGLIB: The dataset that holds the extensions for ZIS. //* -//* Change 'noverbose' to 'verbose' below for -//* advanced logging. This is not needed unless -//* there is an error. +//********************************************************************* //* -//* - verbose -//* - noverbose +//APFAUTH EXEC PGM=BPXBATCH +//BPXPRINT DD SYSOUT=* +//STDOUT DD SYSOUT=* +//STDERR DD SYSOUT=* +//STDPARM DD * +SH cd '/test/dir' && +cd bin/utils && +export LOADLIB='TEST.DATASET.PFX.SZWELOAD' && +export LOADLOC=SMS && +export PLUGLIB='TEST.DATASET.PFX.ZWESAPL' && +export PLUGLOC=SMS && +./opercmd.rex "SETPROG APF,ADD,DSN=$LOADLIB,$LOADLOC" && +./opercmd.rex "SETPROG APF,ADD,DSN=$PLUGLIB,$PLUGLOC" //* -//SYSTSIN DD * -ISPSTART CMD(%ZWEGEN00 - -generate - -noverbose - -) - --- End of JCL --- -Submitting Job ZWEGENER -Job ZWEGENER(JOB00000) completed with RC=0 -Zowe JCL generated successfully -ERROR: * Exit code: 8 -ERROR: * Output: -ERROR: listds 'DOES.NOT.EXIST' label - DOES.NOT.EXIST - IKJ58503I DATA SET 'DOES.NOT.EXIST' NOT IN CATALOG -ERROR: Error ZWEL0320E: The dataset specified in 'zowe.setup.dataset.authLoadlib' does not exist." +JCL not submitted, command run with "--dry-run" flag. +To perform command, re-run command without "--dry-run" flag, or submit the JCL directly + +>> Command run successfully. + + +>> Zowe load libraries are APF authorized successfully." `; -exports[`init-apfauth (SHORT) apf bad authPluginLib 1`] = ` -" -$ Temporary directory '/tmp/.zweenv-0000' created. +exports[`init-apfauth (SHORT) apf sms-managed authPluginLib 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x104b chunk=0x1000 extend=0x104b ------------------------------------------------------------------------------- >> APF authorize load libraries -ERROR: * Exit code: 8 -ERROR: * Output: -ERROR: listds 'DOES.NOT.EXIST' label - DOES.NOT.EXIST - IKJ58503I DATA SET 'DOES.NOT.EXIST' NOT IN CATALOG -ERROR: Error ZWEL0320E: The dataset specified in 'zowe.setup.dataset.authPluginLib' does not exist." -`; +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEIAPF2) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWEIAPF2) +--- JCL Content --- +//ZWEIAPF2 JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html +//* +//* SPDX-License-Identifier: EPL-2.0 +//* +//* Copyright Contributors to the Zowe Project. 2020, 2020 +//* +//********************************************************************* +//* +//* This JCL is used to set APF for the two datasets of Zowe +//* Which need it. You can issue this, or use another +//* Way to accomplish the task. +//* +//* The following variables are derived from the zowe YAML config: +//* LOADLIB: the dataset that holds the APF portion of Zowe +//* PLUGLIB: The dataset that holds the extensions for ZIS. +//* +//********************************************************************* +//* +//APFAUTH EXEC PGM=BPXBATCH +//BPXPRINT DD SYSOUT=* +//STDOUT DD SYSOUT=* +//STDERR DD SYSOUT=* +//STDPARM DD * +SH cd '/test/dir' && +cd bin/utils && +export LOADLIB='TEST.DATASET.PFX.SZWELOAD' && +export LOADLOC="VOLUME=TSTVOL" && +export PLUGLIB='TEST.DATASET.PFX.ZWESAPL' && +export PLUGLOC=SMS && +./opercmd.rex "SETPROG APF,ADD,DSN=$LOADLIB,$LOADLOC" && +./opercmd.rex "SETPROG APF,ADD,DSN=$PLUGLIB,$PLUGLOC" +//* +--- End of JCL --- +JCL not submitted, command run with "--dry-run" flag. +To perform command, re-run command without "--dry-run" flag, or submit the JCL directly -exports[`init-apfauth (SHORT) apf empty jcllib post-generate 1`] = ` -" -$ Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data -Validity Exceptions(s) with object at - Validity Exceptions(s) with object at /zowe - Validity Exceptions(s) with object at /zowe/setup - Validity Exceptions(s) with object at /zowe/setup/dataset - Validity Exceptions(s) with string at /zowe/setup/dataset/jcllib - string too short (len=0) '' 0 < MIN=3 at /zowe/setup/dataset/jcllib - string pattern match fail s='', pat='^([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}(\\.([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}){0,11}$', at /zowe/setup/dataset/jcllib" +>> Command run successfully. + + +>> Zowe load libraries are APF authorized successfully." `; diff --git a/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/canary.test.ts.snap b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/canary.test.ts.snap index 04d96e7069..01f46cbfba 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/canary.test.ts.snap +++ b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/canary.test.ts.snap @@ -1,13 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`canary run echo 1`] = ` -" -$ hi" -`; +exports[`canary run echo 1`] = `"hi"`; exports[`canary run zwe help 1`] = ` -" -$ zwe +"zwe ------------------ Synopsis @@ -23,18 +19,25 @@ Description Global parameters --help|-h (optional) Display this help. + --debug|--verbose|-v (optional) Enable verbose mode. + --trace|-vv (optional) Enable trace level debug mode. + --silent|-s (optional) Do not display messages to standard output. + --log-dir|--log|-l string (optional) Write logs to this directory. + --config|-c string (optional) Path to Zowe configuration zowe.yaml file. + --configmgr (optional) Enable use of configmgr capabilities. + ------------------ Available sub-command(s) - certificate diff --git a/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/stc.test.ts.snap b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/stc.test.ts.snap new file mode 100644 index 0000000000..8fc4d93579 --- /dev/null +++ b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/stc.test.ts.snap @@ -0,0 +1,156 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`init-stc (LONG) run setup with defaults abc 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x105b chunk=0x1000 extend=0x105b +------------------------------------------------------------------------------- +>> Install Zowe main started task + +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEGENER) +--- JCL content --- +//ZWEGENER JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html +//* +//* SPDX-License-Identifier: EPL-2.0 +//* +//* Copyright Contributors to the Zowe Project. 2020, 2020 +//* +//********************************************************************* +//* +//* This job is responsible for generating other jobs required +//* to configure Zowe. +//* +//* The method of validating your configuration is using +//* JSON Schema . Zowe provides +//* the ConfigMgr to assist in this. This job will invoke +//* the ConfigMgr to validate your current configuration +//* before generating any jobs. If there are any values +//* that are incorrect, you will be notified. You should +//* fix the value and then run this job again. You can run +//* this job as many times as you need. +//* +//* Configmgr documentation: +//* https://docs.zowe.org/stable/user-guide/configmgr-using +//* +//* Note: Any string with braces has an associated yaml value +//* in one of the yaml definitions for Zowe. +//* You must find the value and substitute it. +//* +//* {key} -> value +//* +//GENER EXEC PGM=IKJEFT1B +//ISPPROF DD DSN=,DISP=(NEW,DELETE),UNIT=, +// DCB=(RECFM=FB,LRECL=80,BLKSIZE=3120,DSORG=PO), +// SPACE=(3120,(20,5,10)) +//* +//* Replace TEST.DATASET.PFX with the +//* Value as seen in zowe.yaml +//* +//SYSPROC DD DSN=TEST.DATASET.PFX.SZWEEXEC,DISP=SHR +//* +//* Replace TEST.DATASET.PFX with the +//* Value as seen in zowe.yaml +//* +//STEPLIB DD DSN=TEST.DATASET.PFX.SZWELOAD,DISP=SHR +//ISPPLIB DD DSN=ISP.SISPPENU,DISP=SHR +//ISPMLIB DD DSN=ISP.SISPMENU,DISP=SHR +//ISPTLIB DD DSN=ISP.SISPTENU,DISP=SHR +//ISPSLIB DD DSN=ISP.SISPSENU,DISP=SHR +//* +//* The order must be as follows. +//* +//* zowe-yaml-schema.json +//* server-common.json +//* +//* Replace /test/dir with where your Zowe run time +//* directory is, as seen in zowe.yaml +//* +//MYSCHEMA DD *,DLM=$$ +FILE /test/dir/schemas/zowe-yaml-schema.json +FILE /test/dir/schemas/server-common.json +$$ +//* +//* The DD below must include one or more FILE or PARMLIB +//* Entries. The lower entries have their values +//* Overridden by the higher entries. +//* PARMLIB member must be named "ZWEYAML" +//* +//* Ex. PARMLIB MY.ZOWE.CUSTOM.PARMLIB +//* FILE /some/other/zowe.yaml +//MYCONFIG DD *,DLM=$$ +FILE /test/dir/zowe.test.yaml +$$ +//CMGROUT DD SYSOUT=* +//SYSPRINT DD SYSOUT=* +//SYSTSPRT DD SYSOUT=* +//* +//* Change 'generate' to 'nogenerate' if you only +//* want to validate your configuration. The default +//* option, 'generate', will validate and then generate +//* jobs based on your configuration. +//* +//* - generate +//* - nogenerate +//* +//* Change 'noverbose' to 'verbose' below for +//* advanced logging. This is not needed unless +//* there is an error. +//* +//* - verbose +//* - noverbose +//* +//SYSTSIN DD * +ISPSTART CMD(%ZWEGEN00 - +generate - +noverbose - +) + +--- End of JCL --- +Submitting Job ZWEGENER +Job ZWEGENER(JOB00000) completed with RC=2 +Zowe JCL generated with errors, check job log. Job completion code=8, Job completion text=COMPLETED +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWEISTC) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWEISTC) +--- JCL Content --- +//ZWEISTC JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html +//* +//* SPDX-License-Identifier: EPL-2.0 +//* +//* Copyright Contributors to the Zowe Project. 2020, 2020 +//* +//********************************************************************* +//* +//* This job is used to add proclib members +//* Used to start a Zowe "instance" +//* Instances represent a configuration of Zowe, different from the +//* "runtime" datasets that are created upon install of Zowe / SMPE. +//* +//********************************************************************* +//* +//MCOPY EXEC PGM=IEBCOPY +//SYSPRINT DD SYSOUT=A +//SYSUT1 DD DSN=TEST.DATASET.PFX.JCLLIB,DISP=SHR +//SYSUT2 DD DSN=TEST.DATASET.PFX.TEST.PROCLIB,DISP=OLD +//SYSIN DD * + COPY OUTDD=SYSUT2,INDD=SYSUT1 + SELECT MEMBER=((ZWESLSTC,,R)) + + COPY OUTDD=SYSUT2,INDD=SYSUT1 + SELECT MEMBER=((ZWESISTC,,R)) + + COPY OUTDD=SYSUT2,INDD=SYSUT1 + SELECT MEMBER=((ZWESASTC,,R)) +//* +--- End of JCL --- +Submitting Job ZWEISTC +ERROR: Error ZWEL0162E: Failed to find job JOB00000 result." +`; diff --git a/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/vsam.test.ts.snap b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/vsam.test.ts.snap index c2171bf573..8c83f914bd 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/vsam.test.ts.snap +++ b/tests/zwe-remote-integration/src/__tests__/init/__snapshots__/vsam.test.ts.snap @@ -185,9 +185,76 @@ Job ZWECSVSM(JOB00000) completed with RC=0 " `; -exports[`init-vsam (SHORT) invalid NONRLS configurationsabc 1`] = ` -" -$ Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +exports[`init-vsam (SHORT) invalid NONRLS configurations 1`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/vsam + type 'null' not permitted at /zowe/setup/vsam/volume; expecting type 'string'" +`; + +exports[`init-vsam (SHORT) invalid NONRLS configurations 2`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x103b chunk=0x1000 extend=0x103b +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.volume) is not defined in Zowe YAML configuration file." +`; + +exports[`init-vsam (SHORT) invalid NONRLS configurations 3`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x1036 chunk=0x1000 extend=0x1036 +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.name) is not defined in Zowe YAML configuration file." +`; + +exports[`init-vsam (SHORT) invalid NONRLS configurations 4`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x1034 chunk=0x1000 extend=0x1034 +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.name) is not defined in Zowe YAML configuration file." +`; + +exports[`init-vsam (SHORT) invalid NONRLS configurations 5`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/vsam + type 'null' not permitted at /zowe/setup/vsam/volume; expecting type 'string'" +`; + +exports[`init-vsam (SHORT) invalid NONRLS configurations 6`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x102d chunk=0x1000 extend=0x102d +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.volume) is not defined in Zowe YAML configuration file." +`; + +exports[`init-vsam (SHORT) invalid NONRLS configurations 7`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x103f chunk=0x1000 extend=0x103f +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.volume) is not defined in Zowe YAML configuration file." +`; + +exports[`init-vsam (SHORT) invalid RLS configurations 1`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data Validity Exceptions(s) with object at Validity Exceptions(s) with object at /zowe Validity Exceptions(s) with object at /zowe/setup @@ -195,19 +262,18 @@ Validity Exceptions(s) with object at type 'null' not permitted at /zowe/setup/vsam/storageClass; expecting type 'string'" `; -exports[`init-vsam (SHORT) invalid NONRLS configurationsabc 2`] = ` -" -$ Temporary directory '/tmp/.zweenv-0000' created. +exports[`init-vsam (SHORT) invalid RLS configurations 2`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x103e chunk=0x1000 extend=0x103e ------------------------------------------------------------------------------- >> Initialize Zowe custom data sets ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.storageClass) is not defined in Zowe YAML configuration file." `; -exports[`init-vsam (SHORT) invalid NONRLS configurationsabc 3`] = ` -" -$ Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +exports[`init-vsam (SHORT) invalid RLS configurations 3`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data Validity Exceptions(s) with object at Validity Exceptions(s) with object at /zowe Validity Exceptions(s) with object at /zowe/setup @@ -215,22 +281,327 @@ Validity Exceptions(s) with object at type 'null' not permitted at /zowe/setup/vsam/storageClass; expecting type 'string'" `; -exports[`init-vsam (SHORT) invalid NONRLS configurationsabc 4`] = ` -" -$ Temporary directory '/tmp/.zweenv-0000' created. +exports[`init-vsam (SHORT) invalid RLS configurations 4`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x1030 chunk=0x1000 extend=0x1030 ------------------------------------------------------------------------------- >> Initialize Zowe custom data sets ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.storageClass) is not defined in Zowe YAML configuration file." `; -exports[`init-vsam (SHORT) invalid NONRLS configurationsabc 5`] = ` -" -$ Temporary directory '/tmp/.zweenv-0000' created. +exports[`init-vsam (SHORT) invalid RLS configurations 5`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x103f chunk=0x1000 extend=0x103f ------------------------------------------------------------------------------- >> Initialize Zowe custom data sets ERROR: Error ZWEL0157E: VSAM parameter (zowe.setup.vsam.storageClass) is not defined in Zowe YAML configuration file." `; + +exports[`init-vsam (SHORT) simple --dry-run 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x104b chunk=0x1000 extend=0x104b +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWECSVSM) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWECSVSM) +--- JCL Content --- +//ZWECSVSM JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html +//* +//* SPDX-License-Identifier: EPL-2.0 +//* +//* Copyright Contributors to the Zowe Project. 2020, 2020 +//* +//********************************************************************* +//* +//* Zowe Open Source Project +//* This JCL creates the VSAM data set for the Caching Service. +//* +//* +//* CAUTION: This is neither a JCL procedure nor a complete job. +//* Before using this JCL, you will have to make the following +//* modifications: +//* +//* 1) Add job name and job parameters to the JOB statement, to +//* meet your system requirements. +//* +//* When using RLS, customize the definitions in the RLS DD: +//* +//* 2) Optionally, change LOG option NONE to UNDO or ALL to set the +//* desired recovery options for the RLS VSAM. +//* +//* +//* Note(s): +//* +//* 1. This job should complete with return code 0. +//* +//******************************************************************** +//* +//ALLOC EXEC PGM=IDCAMS,REGION=0M +//SYSPRINT DD SYSOUT=* +//SYSIN DD * + DEFINE CLUSTER - + (NAME(TEST.DATASET.PFX.VSAM) - +// DD DDNAME=NONRLS +// DD * + REC(80 20) - + INDEXED) - + DATA(NAME(TEST.DATASET.PFX.VSAM.DATA) - + RECSZ(4096 4096) - + UNIQUE - + KEYS(128 0)) - + INDEX(NAME(TEST.DATASET.PFX.VSAM.INDEX) - + UNIQUE) +//RLS DD * + STORCLAS() - + LOG(NONE) - +//NONRLS DD * + VOLUME(TSTVOL) - + SHAREOPTIONS(2 3) - +//* +--- End of JCL --- +JCL not submitted, command run with "--dry-run" flag. +To perform command, re-run command without "--dry-run" flag, or submit the JCL directly + +>> Command run successfully. + + +>> Zowe Caching Service VSAM storage is created successfully." +`; + +exports[`init-vsam (SHORT) skip non-vsam caching service 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x1051 chunk=0x1000 extend=0x1051 +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +ERROR: Warning ZWEL0301W: Zowe Caching Service is not configured to use VSAM. Command skipped." +`; + +exports[`init-vsam (SHORT) skip undefined caching service 1`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + type 'null' not permitted at /components; expecting type 'object'" +`; + +exports[`init-vsam (SHORT) unset ds prefix 1`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/dataset + type 'null' not permitted at /zowe/setup/dataset/prefix; expecting type 'string'" +`; + +exports[`init-vsam (SHORT) unset ds prefix 2`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/dataset + Validity Exceptions(s) with string at /zowe/setup/dataset/prefix + string too short (len=0) '' 0 < MIN=3 at /zowe/setup/dataset/prefix + string pattern match fail s='', pat='^([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}(\\.([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}){0,11}$', at /zowe/setup/dataset/prefix" +`; + +exports[`init-vsam (SHORT) unset jcllib 1`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/dataset + type 'null' not permitted at /zowe/setup/dataset/prefix; expecting type 'string'" +`; + +exports[`init-vsam (SHORT) unset jcllib 2`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/dataset + Validity Exceptions(s) with string at /zowe/setup/dataset/prefix + string too short (len=0) '' 0 < MIN=3 at /zowe/setup/dataset/prefix + string pattern match fail s='', pat='^([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}(\\.([A-Z\\$\\#\\@]){1}([A-Z0-9\\$\\#\\@\\-]){0,7}){0,11}$', at /zowe/setup/dataset/prefix" +`; + +exports[`init-vsam (SHORT) unset vsam mode 1`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/vsam + no matching enum value at /zowe/setup/vsam/mode; expecting one of values '[NONRLS, RLS]' of type 'string'" +`; + +exports[`init-vsam (SHORT) unset vsam mode 2`] = ` +"Error: Validation of FILE(/test/dir/zowe.test.yaml):FILE(/test/dir/files/defaults.yaml) against schema /test/dir/schemas/zowe-yaml-schema.json:/test/dir/schemas/server-common.json found invalid JSON Schema data +Validity Exceptions(s) with object at + Validity Exceptions(s) with object at /zowe + Validity Exceptions(s) with object at /zowe/setup + Validity Exceptions(s) with object at /zowe/setup/vsam + no matching enum value at /zowe/setup/vsam/mode; expecting one of values '[NONRLS, RLS]' of type 'string'" +`; + +exports[`init-vsam (SHORT) valid NONRLS configurations 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x1041 chunk=0x1000 extend=0x1041 +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWECSVSM) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWECSVSM) +--- JCL Content --- +//ZWECSVSM JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html +//* +//* SPDX-License-Identifier: EPL-2.0 +//* +//* Copyright Contributors to the Zowe Project. 2020, 2020 +//* +//********************************************************************* +//* +//* Zowe Open Source Project +//* This JCL creates the VSAM data set for the Caching Service. +//* +//* +//* CAUTION: This is neither a JCL procedure nor a complete job. +//* Before using this JCL, you will have to make the following +//* modifications: +//* +//* 1) Add job name and job parameters to the JOB statement, to +//* meet your system requirements. +//* +//* When using RLS, customize the definitions in the RLS DD: +//* +//* 2) Optionally, change LOG option NONE to UNDO or ALL to set the +//* desired recovery options for the RLS VSAM. +//* +//* +//* Note(s): +//* +//* 1. This job should complete with return code 0. +//* +//******************************************************************** +//* +//ALLOC EXEC PGM=IDCAMS,REGION=0M +//SYSPRINT DD SYSOUT=* +//SYSIN DD * + DEFINE CLUSTER - + (NAME(TEST.DATASET.PFX.VSAM) - +// DD DDNAME=NONRLS +// DD * + REC(80 20) - + INDEXED) - + DATA(NAME(TEST.DATASET.PFX.VSAM.DATA) - + RECSZ(4096 4096) - + UNIQUE - + KEYS(128 0)) - + INDEX(NAME(TEST.DATASET.PFX.VSAM.INDEX) - + UNIQUE) +//RLS DD * + STORCLAS() - + LOG(NONE) - +//NONRLS DD * + VOLUME(TSTVOL) - + SHAREOPTIONS(2 3) - +//* +--- End of JCL --- +JCL not submitted, command run with "--dry-run" flag. +To perform command, re-run command without "--dry-run" flag, or submit the JCL directly + +>> Command run successfully. + + +>> Zowe Caching Service VSAM storage is created successfully." +`; + +exports[`init-vsam (SHORT) valid RLS configuration 1`] = ` +"Temporary directory '/tmp/.zweenv-0000' created. +Zowe will remove it on success, but if zwe exits with a non-zero code manual cleanup would be needed. +bos extend currSize=0x0 dataSize=0x1044 chunk=0x1000 extend=0x1044 +------------------------------------------------------------------------------- +>> Initialize Zowe custom data sets + +Template JCL: TEST.DATASET.PFX.SZWESAMP(ZWECSVSM) , Executable JCL: TEST.DATASET.PFX.JCLLIB(ZWECSVSM) +--- JCL Content --- +//ZWECSVSM JOB +//* +//* This program and the accompanying materials are made available +//* under the terms of the Eclipse Public License v2.0 which +//* accompanies this distribution, and is available at +//* https://www.eclipse.org/legal/epl-v20.html +//* +//* SPDX-License-Identifier: EPL-2.0 +//* +//* Copyright Contributors to the Zowe Project. 2020, 2020 +//* +//********************************************************************* +//* +//* Zowe Open Source Project +//* This JCL creates the VSAM data set for the Caching Service. +//* +//* +//* CAUTION: This is neither a JCL procedure nor a complete job. +//* Before using this JCL, you will have to make the following +//* modifications: +//* +//* 1) Add job name and job parameters to the JOB statement, to +//* meet your system requirements. +//* +//* When using RLS, customize the definitions in the RLS DD: +//* +//* 2) Optionally, change LOG option NONE to UNDO or ALL to set the +//* desired recovery options for the RLS VSAM. +//* +//* +//* Note(s): +//* +//* 1. This job should complete with return code 0. +//* +//******************************************************************** +//* +//ALLOC EXEC PGM=IDCAMS,REGION=0M +//SYSPRINT DD SYSOUT=* +//SYSIN DD * + DEFINE CLUSTER - + (NAME(TEST.DATASET.PFX.VSAM) - +// DD DDNAME=NONRLS +// DD * + REC(80 20) - + INDEXED) - + DATA(NAME(TEST.DATASET.PFX.VSAM.DATA) - + RECSZ(4096 4096) - + UNIQUE - + KEYS(128 0)) - + INDEX(NAME(TEST.DATASET.PFX.VSAM.INDEX) - + UNIQUE) +//RLS DD * + STORCLAS() - + LOG(NONE) - +//NONRLS DD * + VOLUME(TSTVOL) - + SHAREOPTIONS(2 3) - +//* +--- End of JCL --- +JCL not submitted, command run with "--dry-run" flag. +To perform command, re-run command without "--dry-run" flag, or submit the JCL directly + +>> Command run successfully. + + +>> Zowe Caching Service VSAM storage is created successfully." +`; diff --git a/tests/zwe-remote-integration/src/__tests__/init/apfauth.test.ts b/tests/zwe-remote-integration/src/__tests__/init/apfauth.test.ts index 4f6e083778..d50789a2a1 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/apfauth.test.ts +++ b/tests/zwe-remote-integration/src/__tests__/init/apfauth.test.ts @@ -10,6 +10,7 @@ import { REMOTE_SYSTEM_INFO } from '../../config/TestConfig'; import ZoweYamlType from '../../config/ZoweYamlType'; +import * as zosfiles from '../../zos/Files'; import { RemoteTestRunner } from '../../zos/RemoteTestRunner'; import { ZoweConfig } from '../../config/ZoweConfig'; import { FileType, TestFileActions, TestFile } from '../../zos/TestFileActions'; @@ -34,6 +35,10 @@ describe(`${testSuiteName}`, () => { cleanupDatasets = []; }); + afterAll(() => { + testRunner.shutdown(); + }); + describe('(LONG)', () => { beforeEach(async () => { // re-created in every `init` subcommand based on changes to zowe yaml command... @@ -79,15 +84,54 @@ describe(`${testSuiteName}`, () => { expect(result.rc).toBe(1); }); - /* - // not working, not covered - it('apf sms-managed authLoadLib', async () => { - cfgYaml.zowe.setup.dataset.authLoadlib = smsDataset; - const result = await testRunner.runZweTest(cfgYaml, 'init apfauth --dry-run'); - expect(result.stdout).not.toBeNull(); - expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(0); - });*/ + if (REMOTE_SYSTEM_INFO?.storclas.length > 0) { + it('apf sms-managed authLoadLib', async () => { + const smsDs = `${REMOTE_SYSTEM_INFO.prefix}.APF.LOADLIB`; + await zosfiles.createPds(smsDs, { + storclass: REMOTE_SYSTEM_INFO.storclas, + }); + cleanupDatasets.push({ name: smsDs, type: FileType.DS_NON_CLUSTER }); + cfgYaml.zowe.setup.dataset.authLoadlib = smsDs; + const result = await testRunner.runZweTest(cfgYaml, 'init apfauth --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + it('apf sms-managed authPluginLib', async () => { + const smsDs = `${REMOTE_SYSTEM_INFO.prefix}.APF.PLUGLIB`; + await zosfiles.createPds(smsDs, { + storclass: REMOTE_SYSTEM_INFO.storclas, + }); + cleanupDatasets.push({ name: smsDs, type: FileType.DS_NON_CLUSTER }); + cfgYaml.zowe.setup.dataset.authPluginLib = smsDs; + const result = await testRunner.runZweTest(cfgYaml, 'init apfauth --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + it('apf sms-managed authLoadLib and authPluginLib', async () => { + const loadSmsDs = `${REMOTE_SYSTEM_INFO.prefix}.APF.LOADLIB`; + const plugSmsDs = `${REMOTE_SYSTEM_INFO.prefix}.APF.PLUGLIB`; + await zosfiles.createPds(loadSmsDs, { + storclass: REMOTE_SYSTEM_INFO.storclas, + }); + await zosfiles.createPds(plugSmsDs, { + storclass: REMOTE_SYSTEM_INFO.storclas, + }); + cleanupDatasets.push({ name: loadSmsDs, type: FileType.DS_NON_CLUSTER }); + cleanupDatasets.push({ name: plugSmsDs, type: FileType.DS_NON_CLUSTER }); + cfgYaml.zowe.setup.dataset.authLoadlib = loadSmsDs; + cfgYaml.zowe.setup.dataset.authPluginLib = plugSmsDs; + const result = await testRunner.runZweTest(cfgYaml, 'init apfauth --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + } else { + it.skip('apf sms-managed authLoadLib'); + it.skip('apf sms-managed authPluginLib'); + it.skip('apf sms-managed authLoadLib and authPluginLib'); + } it('apf bad authLoadLib', async () => { cfgYaml.zowe.setup.dataset.authLoadlib = 'DOES.NOT.EXIST'; diff --git a/tests/zwe-remote-integration/src/__tests__/init/canary.test.ts b/tests/zwe-remote-integration/src/__tests__/init/canary.test.ts index 20269474af..96896c7ba5 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/canary.test.ts +++ b/tests/zwe-remote-integration/src/__tests__/init/canary.test.ts @@ -21,6 +21,10 @@ describe(testSuiteName, () => { testRunner = new RemoteTestRunner('canary'); }); + afterAll(() => { + testRunner.shutdown(); + }); + it('run echo', async () => { const cfgYaml = ZoweConfig.getZoweYaml(); cfgYaml.java.home = '/ZOWE/node/J21.0_64/'; diff --git a/tests/zwe-remote-integration/src/__tests__/init/certificate.test.ts b/tests/zwe-remote-integration/src/__tests__/init/certificate.test.ts index 60201841e7..32aefbb456 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/certificate.test.ts +++ b/tests/zwe-remote-integration/src/__tests__/init/certificate.test.ts @@ -18,7 +18,7 @@ const testSuiteName = 'init-cert'; describe(`${testSuiteName}`, () => { let testRunner: RemoteTestRunner; let cfgYaml: ZoweYamlType; - const cleanupFiles: TestFile[] = []; // a list of datasets deleted after every test + let cleanupFiles: TestFile[] = []; // a list of datasets deleted after every test beforeAll(() => { testRunner = new RemoteTestRunner(testSuiteName); @@ -29,8 +29,12 @@ describe(`${testSuiteName}`, () => { afterEach(async () => { await testRunner.postTest(); - await TestFileActions.deleteAll(cleanupDatasets); - cleanupDatasets = []; + await TestFileActions.deleteAll(cleanupFiles); + cleanupFiles = []; + }); + + afterAll(() => { + testRunner.shutdown(); }); describe('(SHORT)', () => { @@ -44,29 +48,6 @@ describe(`${testSuiteName}`, () => { expect(result.cleanedStdout).toMatchSnapshot(); expect(result.rc).toBe(231); // 231 is expected error code...? }); - - /* - it('cert bad ds prefix', async () => { - cfgYaml.zowe.setup.dataset.prefix = 'ZOWEAD3.ZWETEST.NOEXIST'; - const result = await testRunner.runZweTest(cfgYaml, 'init certificate --dry-run'); - expect(result.stdout).not.toBeNull(); - expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(231); - }); - - it('cert simple --dry-run', async () => { - const result = await testRunner.runZweTest(cfgYaml, 'init certificate --dry-run'); - expect(result.stdout).not.toBeNull(); - expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(0); // 60 is expected... - }); - - /* it('apf security-dry-run', async () => { - const result = await testRunner.runZweTest(cfgYaml, 'init apfauth --security-dry-run'); - expect(result.stdout).not.toBeNull(); - expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(0); // 60 is expected... }); - });*/ }); describe('(LONG)', () => { diff --git a/tests/zwe-remote-integration/src/__tests__/init/generate.test.ts b/tests/zwe-remote-integration/src/__tests__/init/generate.test.ts index 320da91091..8b4c59c621 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/generate.test.ts +++ b/tests/zwe-remote-integration/src/__tests__/init/generate.test.ts @@ -40,6 +40,10 @@ describe(`${testSuiteName}`, () => { cleanupDatasets = []; }); + afterAll(() => { + testRunner.shutdown(); + }); + describe('(SHORT)', () => { it('disable cfgmgr', async () => { cfgYaml.zowe.useConfigmgr = false; @@ -91,5 +95,13 @@ describe(`${testSuiteName}`, () => { }); }); - describe('(LONG)', () => {}); + describe('(LONG)', () => { + it('missing proclib with valid stcs abc', async () => { + cfgYaml.zowe.setup.dataset.proclib = `${REMOTE_SYSTEM_INFO.prefix}.NOEXIST.PROC`; + const result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + }); + }); }); diff --git a/tests/zwe-remote-integration/src/__tests__/init/stc.test.ts b/tests/zwe-remote-integration/src/__tests__/init/stc.test.ts new file mode 100644 index 0000000000..d0fe530884 --- /dev/null +++ b/tests/zwe-remote-integration/src/__tests__/init/stc.test.ts @@ -0,0 +1,234 @@ +/* + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + */ + +import { REMOTE_SYSTEM_INFO } from '../../config/TestConfig'; +import ZoweYamlType from '../../config/ZoweYamlType'; +import { RemoteTestRunner } from '../../zos/RemoteTestRunner'; +import * as zosfiles from '../../zos/Files'; +import { ZoweConfig } from '../../config/ZoweConfig'; +import { FileType, TestFileActions, TestFile } from '../../zos/TestFileActions'; + +const testSuiteName = 'init-stc'; +describe(`${testSuiteName}`, () => { + let testRunner: RemoteTestRunner; + let cfgYaml: ZoweYamlType; + let cleanupDatasets: TestFile[] = []; // a list of datasets deleted after every test + + beforeAll(() => { + testRunner = new RemoteTestRunner(testSuiteName); + cfgYaml = ZoweConfig.getZoweYaml(); + }); + beforeEach(() => { + cfgYaml = ZoweConfig.getZoweYaml(); + // customizations for all vsam tests + cfgYaml.zowe.setup.vsam.name = REMOTE_SYSTEM_INFO.prefix + '.VSAMTEST'; + cfgYaml.zowe.setup.vsam.volume = REMOTE_SYSTEM_INFO.volume; + }); + + afterEach(async () => { + await testRunner.postTest(); + await TestFileActions.deleteAll(cleanupDatasets); + cleanupDatasets = []; + }); + + afterAll(() => { + testRunner.shutdown(); + }); + + describe('(LONG)', () => { + beforeEach(async () => { + // re-created in every `init` subcommand based on changes to zowe yaml command... + const jcllib: TestFile = { name: REMOTE_SYSTEM_INFO.jcllib, type: FileType.DS_NON_CLUSTER }; + // try to delete everything we know about + await TestFileActions.deleteAll([jcllib]); + }); + + it('run setup with defaults abc', async () => { + const proc: string = cfgYaml.zowe.setup.dataset.proclib as string; + const stcs = cfgYaml.zowe.setup.security.stcs; + cleanupDatasets.push({ name: `${proc}(${stcs.zowe})`, type: FileType.DS_NON_CLUSTER }); + cleanupDatasets.push({ name: `${proc}(${stcs.aux})`, type: FileType.DS_NON_CLUSTER }); + cleanupDatasets.push({ name: `${proc}(${stcs.zis})`, type: FileType.DS_NON_CLUSTER }); + const result = await testRunner.runZweTest(cfgYaml, 'init stc'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + + it('run stc setup with overwrite', async () => { + const proc: string = cfgYaml.zowe.setup.dataset.proclib as string; + const stcs = cfgYaml.zowe.setup.security.stcs; + await zosfiles.uploadMember(proc, stcs.zowe as string, 'DUMMY'); + cleanupDatasets.push({ name: `${proc}(${stcs.zowe})`, type: FileType.DS_NON_CLUSTER }); + let result = await testRunner.runZweTest(cfgYaml, 'init stc'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + + result = await testRunner.runZweTest(cfgYaml, 'init stc --allow-overwrite'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + }); + + describe('(SHORT)', () => { + beforeAll(async () => { + await testRunner.runZweTest(cfgYaml, 'init generate'); + }); + + it('wrong ds prefix', async () => { + cfgYaml.zowe.setup.dataset.prefix = null; + let result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.dataset.prefix = ''; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + }); + + it('wrong proclib', async () => { + cfgYaml.zowe.setup.dataset.proclib = null; + let result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.dataset.proclib = ''; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.dataset.proclib = 'INVALID.PROCLIB.DEFINITION1'; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + }); + + it('wrong jcllib', async () => { + cfgYaml.zowe.setup.dataset.jcllib = null; + let result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.dataset.jcllib = ''; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + }); + + it('invalid stc configurations', async () => { + cfgYaml.zowe.setup.security.stcs.aux = null; + let result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.security.stcs.aux = ''; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.security.stcs.aux = 'TOOLONGTOO'; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.security.stcs.zis = null; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.security.stcs.zis = ''; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.security.stcs.zowe = null; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.security.stcs.zowe = ''; + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + }); + + it('zos stc exists', async () => { + const proc: string = cfgYaml.zowe.setup.dataset.proclib as string; + const stcs = cfgYaml.zowe.setup.security.stcs; + await zosfiles.uploadMember(proc, stcs.zowe as string, 'DUMMY'); + cleanupDatasets.push({ name: `${proc}(${stcs.zowe})`, type: FileType.DS_NON_CLUSTER }); + let result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run --allow-overwrite'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + + it('zis stc exists', async () => { + const proc: string = cfgYaml.zowe.setup.dataset.proclib as string; + const stcs = cfgYaml.zowe.setup.security.stcs; + await zosfiles.uploadMember(proc, stcs.zis as string, 'DUMMY'); + cleanupDatasets.push({ name: `${proc}(${stcs.zis})`, type: FileType.DS_NON_CLUSTER }); + let result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run --allow-overwrite'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + + it('aux stc exists', async () => { + const proc: string = cfgYaml.zowe.setup.dataset.proclib as string; + const stcs = cfgYaml.zowe.setup.security.stcs; + await zosfiles.uploadMember(proc, stcs.aux as string, 'DUMMY'); + cleanupDatasets.push({ name: `${proc}(${stcs.aux})`, type: FileType.DS_NON_CLUSTER }); + let result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + + result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run --allow-overwrite'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + + it('valid config empty proclib', async () => { + const result = await testRunner.runZweTest(cfgYaml, 'init stc --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(0); + }); + }); +}); diff --git a/tests/zwe-remote-integration/src/__tests__/init/vsam.test.ts b/tests/zwe-remote-integration/src/__tests__/init/vsam.test.ts index 027fc12ea7..0e75618131 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/vsam.test.ts +++ b/tests/zwe-remote-integration/src/__tests__/init/vsam.test.ts @@ -37,6 +37,10 @@ describe(`${testSuiteName}`, () => { cleanupDatasets = []; }); + afterAll(() => { + testRunner.shutdown(); + }); + describe('(LONG)', () => { beforeEach(async () => { // re-created in every `init` subcommand based on changes to zowe yaml command... @@ -78,18 +82,30 @@ describe(`${testSuiteName}`, () => { it('unset ds prefix', async () => { cfgYaml.zowe.setup.dataset.prefix = null; - const result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); + let result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); expect(result.stdout).not.toBeNull(); expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(143); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.dataset.prefix = ''; + result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); }); it('unset jcllib', async () => { - cfgYaml.zowe.setup.dataset.prefix = null; - const result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); + cfgYaml.zowe.setup.dataset.jcllib = null; + let result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); + expect(result.stdout).not.toBeNull(); + expect(result.cleanedStdout).toMatchSnapshot(); + expect(result.rc).toBe(1); + + cfgYaml.zowe.setup.dataset.jcllib = ''; + result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); expect(result.stdout).not.toBeNull(); expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(143); + expect(result.rc).toBe(1); }); it('invalid NONRLS configurations', async () => { @@ -225,14 +241,14 @@ describe(`${testSuiteName}`, () => { let result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); expect(result.stdout).not.toBeNull(); expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(143); + expect(result.rc).toBe(1); // @ts-expect-error forced schema error cfgYaml.zowe.setup.vsam.mode = ''; result = await testRunner.runZweTest(cfgYaml, 'init vsam --dry-run'); expect(result.stdout).not.toBeNull(); expect(result.cleanedStdout).toMatchSnapshot(); - expect(result.rc).toBe(143); + expect(result.rc).toBe(1); }); it('simple --dry-run', async () => { diff --git a/tests/zwe-remote-integration/src/config/TestConfig.ts b/tests/zwe-remote-integration/src/config/TestConfig.ts index 516f469bcc..ddee9160bd 100644 --- a/tests/zwe-remote-integration/src/config/TestConfig.ts +++ b/tests/zwe-remote-integration/src/config/TestConfig.ts @@ -37,6 +37,7 @@ const configFields: ConfigItem[] = [ new ConfigItem('test_ds_hlq', true), new ConfigItem('test_stgclass', true), new ConfigItem('test_volume', true), + new ConfigItem('test_storclas', false), new ConfigItem('zosmf_reject_unauthorized', false, false), new ConfigItem('download_configmgr', false, true), new ConfigItem('download_zowe_tools', false, true), @@ -61,7 +62,6 @@ export const LINGERING_REMOTE_FILES_FILE = path.resolve(THIS_TEST_ROOT_DIR, '.bu export const TEST_JOBS_RUN_FILE = path.resolve(THIS_TEST_ROOT_DIR, '.build', 'jobs-run.txt'); export const DOWNLOAD_ZOWE_TOOLS = yn(configData.download_zowe_tools, { default: true }); export const DOWNLOAD_CONFIGMGR = yn(configData.download_configmgr, { default: true }); -export const TEST_DATASETS_HLQ = configData.test_ds_hlq || configData.zos_user + '.ZWETESTS'; export const REMOTE_SETUP = yn(configData.remote_setup, { default: true }); export const REMOTE_TEARDOWN = yn(configData.remote_teardown, { default: true }); export const ZOWE_YAML_OVERRIDES = configData.zowe_yaml_overrides; @@ -72,17 +72,20 @@ export const JFROG_CREDENTIALS = { }; const ru = yn(configData.zosmf_reject_unauthorized, { default: false }); +const testPrefix = `${configData.test_ds_hlq}.ZWETEST`; export const REMOTE_SYSTEM_INFO = { zosJavaHome: configData.zos_java_home, zosNodeHome: configData.zos_node_home, volume: configData.test_volume, - prefix: configData.test_ds_hlq, - szweexec: `${configData.test_ds_hlq}.SZWEEXEC`, - szwesamp: `${configData.test_ds_hlq}.SZWESAMP`, - jcllib: `${configData.test_ds_hlq}.JCLLIB`, - szweload: `${configData.test_ds_hlq}.SZWELOAD`, - authLoadLib: `${configData.test_ds_hlq}.SZWELOAD`, - authPluginLib: `${configData.test_ds_hlq}.ZWESAPL`, + storclas: configData.test_storclas, + prefix: testPrefix, + szweexec: `${testPrefix}.SZWEEXEC`, + szwesamp: `${testPrefix}.SZWESAMP`, + jcllib: `${testPrefix}.JCLLIB`, + proclib: `${testPrefix}.TEST.PROCLIB`, + szweload: `${testPrefix}.SZWELOAD`, + authLoadLib: `${testPrefix}.SZWELOAD`, + authPluginLib: `${testPrefix}.ZWESAPL`, ussTestDir: configData.remote_test_dir, hostname: configData.zos_host, zosmfPort: configData.zosmf_port, @@ -109,6 +112,7 @@ type TestConfigData = { remote_test_dir: string; test_ds_hlq: string; test_volume: string; + test_storclas: string; zosmf_reject_unauthorized: string; download_configmgr: string; download_zowe_tools: boolean; diff --git a/tests/zwe-remote-integration/src/config/ZoweYamlType.ts b/tests/zwe-remote-integration/src/config/ZoweYamlType.ts index b054053b75..bec77042bb 100644 --- a/tests/zwe-remote-integration/src/config/ZoweYamlType.ts +++ b/tests/zwe-remote-integration/src/config/ZoweYamlType.ts @@ -1018,10 +1018,22 @@ const zoweSchema = zoweYamlSchema as { }; }; }; - tlsSettings: { - $anchor: 'tlsSettings'; + nativeTlsSettings: { + $anchor: 'nativeTlsSettings'; type: 'object'; + additionalProperties: false; properties: { + attls: { + anyOf: [ + { + type: 'string'; + enum: ['', 'false']; + }, + { + const: false; + }, + ]; + }; ciphers: { type: 'array'; description: 'Acceptable TLS cipher suites for network connections, in IANA format.'; @@ -1050,6 +1062,16 @@ const zoweSchema = zoweYamlSchema as { }; }; }; + attlsSetting: { + type: 'object'; + additionalProperties: false; + properties: { + attls: { + const: true; + description: 'Enables AT-TLS for client or server operations. AT-TLS should only be enabled in a z/OS host environment. Servers will be switched into HTTP mode to accomodate z/OS the specific AT-TLS feature which wraps network calls in TLS.'; + }; + }; + }; networkSettings: { type: 'object'; $anchor: 'networkSettings'; @@ -1058,12 +1080,8 @@ const zoweSchema = zoweYamlSchema as { properties: { server: { type: 'object'; - additionalProperties: false; description: 'Optional, advanced network configuration parameters for Zowe servers'; properties: { - tls: { - $ref: '#/$defs/tlsSettings'; - }; listenAddresses: { type: 'array'; description: 'The IP addresses which all of the Zowe servers will be binding on and listening to. Some servers may only support listening on the first element.'; @@ -1080,6 +1098,9 @@ const zoweSchema = zoweYamlSchema as { default: true; description: 'Whether or not to ensure that the port a server is about to use is available. Usually, servers will know this when they attempt to bind to a port, so this option allows you to disable the additional verification step.'; }; + tls: { + anyOf: [{ $ref: '#/$defs/attlsSetting' }, { $ref: '#/$defs/nativeTlsSettings' }]; + }; }; }; client: { @@ -1088,7 +1109,7 @@ const zoweSchema = zoweYamlSchema as { description: 'Optional, advanced network configuration parameters for Zowe servers when sending requests as clients.'; properties: { tls: { - $ref: '#/$defs/tlsSettings'; + anyOf: [{ $ref: '#/$defs/attlsSetting' }, { $ref: '#/$defs/nativeTlsSettings' }]; }; }; }; diff --git a/tests/zwe-remote-integration/src/globalSetup.ts b/tests/zwe-remote-integration/src/globalSetup.ts index b1186e288a..32fdf60708 100644 --- a/tests/zwe-remote-integration/src/globalSetup.ts +++ b/tests/zwe-remote-integration/src/globalSetup.ts @@ -47,6 +47,7 @@ function setupBaseYaml() { zoweYaml.zowe.runtimeDirectory = REMOTE_SYSTEM_INFO.ussTestDir; zoweYaml.zowe.setup.dataset.prefix = REMOTE_SYSTEM_INFO.prefix; zoweYaml.zowe.setup.dataset.jcllib = REMOTE_SYSTEM_INFO.jcllib; + zoweYaml.zowe.setup.dataset.proclib = REMOTE_SYSTEM_INFO.proclib; zoweYaml.zowe.setup.vsam.name = REMOTE_SYSTEM_INFO.prefix + '.VSAM'; zoweYaml.zowe.setup.vsam.volume = REMOTE_SYSTEM_INFO.volume; zoweYaml.zowe.setup.certificate.pkcs12.directory = REMOTE_SYSTEM_INFO.ussTestDir; @@ -264,28 +265,38 @@ module.exports = async () => { await createPds(REMOTE_SYSTEM_INFO.szweexec, { primary: 5, secondary: 1, + volser: REMOTE_SYSTEM_INFO.volume, }); await createPds(REMOTE_SYSTEM_INFO.szwesamp, { primary: 5, secondary: 1, + volser: REMOTE_SYSTEM_INFO.volume, }); await createPds(REMOTE_SYSTEM_INFO.szweload, { primary: 5, recfm: 'U', lrecl: 0, secondary: 1, + volser: REMOTE_SYSTEM_INFO.volume, + }); + await createPds(REMOTE_SYSTEM_INFO.proclib, { + primary: 5, + secondary: 1, + volser: REMOTE_SYSTEM_INFO.volume, }); await createPds(REMOTE_SYSTEM_INFO.authLoadLib, { primary: 5, recfm: 'U', lrecl: 0, secondary: 1, + volser: REMOTE_SYSTEM_INFO.volume, }); await createPds(REMOTE_SYSTEM_INFO.authPluginLib, { primary: 5, recfm: 'U', lrecl: 0, secondary: 1, + volser: REMOTE_SYSTEM_INFO.volume, }); console.log(`Unpacking configmgr and placing it in bin/utils ...`); diff --git a/tests/zwe-remote-integration/src/zos/Files.ts b/tests/zwe-remote-integration/src/zos/Files.ts index b2600d7592..b2a2577e41 100644 --- a/tests/zwe-remote-integration/src/zos/Files.ts +++ b/tests/zwe-remote-integration/src/zos/Files.ts @@ -8,11 +8,25 @@ * Copyright Contributors to the Zowe Project. */ -import { REMOTE_SYSTEM_INFO } from '../config/TestConfig'; import * as files from '@zowe/zos-files-for-zowe-sdk'; import { getSession } from './ZosmfSession'; import _ from 'lodash'; +export async function uploadMember(pdsName: string, memberName: string, content: string) { + const listPdsResp = await files.List.dataSet(getSession(), pdsName, { + pattern: pdsName, + }); + const respItems: { [key: string]: string }[] = listPdsResp.apiResponse?.items; + if (respItems?.find((item) => item.dsname === pdsName) == null) { + console.log(`Couldn't find dataset to upload member to, aborting...`); + throw new Error(`Uploading member to dataset which doesn't exist`); + } + const uplResp = await files.Upload.bufferToDataSet(getSession(), Buffer.from(content, 'utf-8'), `${pdsName}(${memberName})`); + if (!uplResp.success) { + throw new Error(`Failed to upload content to ${pdsName}(${memberName}), details: ${uplResp.apiResponse}`); + } +} + export async function createPds(pdsName: string, createOpts: Partial) { const defaultPdsOpts: files.ICreateDataSetOptions = { lrecl: 80, @@ -23,7 +37,6 @@ export async function createPds(pdsName: string, createOpts: Partial = _.merge({}, defaultPdsOpts, createOpts); console.log(`Creating ${pdsName}`); @@ -39,7 +52,6 @@ export async function createDataset( const listPdsResp = await files.List.dataSet(getSession(), dsName, { pattern: dsName, }); - console.log(JSON.stringify(listPdsResp)); const respItems: { [key: string]: string }[] = listPdsResp.apiResponse?.items; if (respItems?.find((item) => item.dsname === dsName) != null) { console.log(`Pds exists, cleaning up...`); diff --git a/tests/zwe-remote-integration/src/zos/RemoteTestRunner.ts b/tests/zwe-remote-integration/src/zos/RemoteTestRunner.ts index 53412026a5..10d7f2abfd 100644 --- a/tests/zwe-remote-integration/src/zos/RemoteTestRunner.ts +++ b/tests/zwe-remote-integration/src/zos/RemoteTestRunner.ts @@ -10,7 +10,7 @@ import { Session } from '@zowe/imperative'; import { getSession } from './ZosmfSession'; -import * as uss from './Uss'; +import { UssSession } from './UssSession'; import ZoweYamlType from '../config/ZoweYamlType'; import { REMOTE_SYSTEM_INFO, TEST_COLLECT_SPOOL, TEST_JOBS_RUN_FILE, TEST_OUTPUT_DIR } from '../config/TestConfig'; import * as files from '@zowe/zos-files-for-zowe-sdk'; @@ -35,16 +35,28 @@ export class RemoteTestRunner { private trackedFiles: TrackedFile[] = []; private trackedJobs: jobs.IDownloadAllSpoolContentParms[] = []; private cleanFns: ((stdout: string) => string)[] = []; + private readonly uss: UssSession; + private totalRuns: number = 0; + private totalRuntime: number = 0; + private maxRuntime: number = -1; constructor(testGroup: string) { this.session = getSession(); + this.uss = UssSession.sharedSession(); this.tmpDir = `${TEST_OUTPUT_DIR}/${testGroup}/tmp`; this.yamlOutputTemplate = `${TEST_OUTPUT_DIR}/${testGroup}/{{ testInstance }}/yaml`; this.spoolOutputTemplate = `${TEST_OUTPUT_DIR}/${testGroup}//{{ testInstance }}/spool`; } + public shutdown() { + console.log(`Total time spent in uss commands: ${this.totalRuntime / 1000} seconds`); + console.log(`Max time spent in a single uss command: ${this.maxRuntime / 1000} seconds`); + console.log(`Avg time spent per uss command: ${this.totalRuntime / this.totalRuns / 1000} seconds`); + this.uss.shutdown(); + } + public async runRaw(command: string, cwd: string = REMOTE_SYSTEM_INFO.ussTestDir): Promise { - const output = await uss.runCommand(`${command}`, cwd); + const output = await this.uss.runCommand(`${command}`, cwd); // Any non-deterministic output should be cleaned up for test snapshots. const cleanedOutput = this.cleanOutput(output.data); return { @@ -144,6 +156,7 @@ export class RemoteTestRunner { const yamlOutputDir = this.yamlOutputTemplate.replace('{{ testInstance }}', testName); await this.removeFileForTest('files/defaults.yaml'); fs.writeFileSync(`${yamlOutputDir}/defaults.yaml.${testName}`, stringDefaultYaml); + await files.Upload.fileToUssFile( this.session, `${yamlOutputDir}/defaults.yaml.${testName}`, @@ -184,9 +197,13 @@ export class RemoteTestRunner { binary: false, }, ); - - const output = await uss.runCommand(`./bin/zwe ${command} --config ${REMOTE_SYSTEM_INFO.ussTestDir}/zowe.test.yaml`, cwd); - + const start = performance.now(); + const output = await this.uss.runCommand(`./bin/zwe ${command} --config ${REMOTE_SYSTEM_INFO.ussTestDir}/zowe.test.yaml`, cwd); + const end = performance.now(); + const duration = end - start; + this.totalRuntime += duration; + this.totalRuns++; + this.maxRuntime = Math.max(this.maxRuntime, duration); const matches = output.data.matchAll(/([A-Za-z0-9]{4,8})\((JOB[0-9]{1,5})\) completed with RC=(.*)$/gim); // for each match, 0=full matched string, 1=jobname, 2=jobid, 3=rc diff --git a/tests/zwe-remote-integration/src/__tests__/init/stc.tests.ts b/tests/zwe-remote-integration/src/zos/SshResponse.ts similarity index 73% rename from tests/zwe-remote-integration/src/__tests__/init/stc.tests.ts rename to tests/zwe-remote-integration/src/zos/SshResponse.ts index e73229917d..8de2905044 100644 --- a/tests/zwe-remote-integration/src/__tests__/init/stc.tests.ts +++ b/tests/zwe-remote-integration/src/zos/SshResponse.ts @@ -8,6 +8,8 @@ * Copyright Contributors to the Zowe Project. */ -const testSuiteName = 'init-stc'; -describe(`${testSuiteName}`, () => {}); -export {}; // remove when tests are written +export type SshResponse = { + rc: number; + error: string | undefined; + data: string | undefined; +}; diff --git a/tests/zwe-remote-integration/src/zos/Uss.ts b/tests/zwe-remote-integration/src/zos/Uss.ts index b195e102e8..9e564d3d32 100644 --- a/tests/zwe-remote-integration/src/zos/Uss.ts +++ b/tests/zwe-remote-integration/src/zos/Uss.ts @@ -10,8 +10,9 @@ import { REMOTE_CONNECTION_CFG } from '../config/TestConfig'; import { Shell, SshSession } from '@zowe/zos-uss-for-zowe-sdk'; +import { SshResponse } from './SshResponse'; -export async function runCommand(command: string, cwd: string = '~') { +export async function runCommand(command: string, cwd: string = '~'): Promise { const session = new SshSession({ hostname: REMOTE_CONNECTION_CFG.host, port: REMOTE_CONNECTION_CFG.ssh_port, @@ -25,5 +26,5 @@ export async function runCommand(command: string, cwd: string = '~') { stdout += data; } }); - return { data: stdout, rc: rc }; + return { data: stdout, rc: rc, error: null }; } diff --git a/tests/zwe-remote-integration/src/zos/UssSession.ts b/tests/zwe-remote-integration/src/zos/UssSession.ts new file mode 100644 index 0000000000..89d24bcb2a --- /dev/null +++ b/tests/zwe-remote-integration/src/zos/UssSession.ts @@ -0,0 +1,74 @@ +/* + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + */ + +import { REMOTE_CONNECTION_CFG } from '../config/TestConfig'; +import { NodeSSH } from 'node-ssh'; +import { SshResponse } from './SshResponse'; +import { sleep } from '../utils'; + +export class UssSession { + private static shrSess: UssSession; + private sessionInit: boolean = false; + private readonly ssh = new NodeSSH(); + + private constructor() { + this.ssh + .connect({ + host: REMOTE_CONNECTION_CFG.host, + username: REMOTE_CONNECTION_CFG.user, + port: REMOTE_CONNECTION_CFG.ssh_port, + password: REMOTE_CONNECTION_CFG.password, + tryKeyboard: true, + onKeyboardInteractive: (name, instructions, instructionsLang, prompts, finish) => { + if (prompts.length > 0 && prompts[0].prompt.toLowerCase().includes('password')) { + finish([REMOTE_CONNECTION_CFG.password]); + } + }, + }) + .then(() => { + console.log('uss session connected'); + this.sessionInit = true; + }); + } + + public shutdown() { + this.ssh.dispose(); + } + + /** + * Re-uses an existing SSH session context to run commands. + */ + public static sharedSession() { + if (this.shrSess == null) { + this.shrSess = new UssSession(); + } + return this.shrSess; + } + + /** + * Creates a new SSH session, ignoring any existing shared session contexts. + */ + public static newSession() { + return new UssSession(); + } + + public async runCommand(command: string, cwd: string = '~'): Promise { + let tries = 10; + while (!this.sessionInit && tries > 0) { + await sleep(500); + tries--; + } + if (!this.sessionInit) { + console.log(`Could not run command, SSH session couldn't be established.`); + } + const response = await this.ssh.execCommand(command, { cwd: cwd }); + return { data: response.stdout, rc: response.code, error: response.stderr }; + } +}