diff --git a/bin/commands/install/.parameters b/bin/commands/install/.parameters index edb8c2512c..ca535717ac 100644 --- a/bin/commands/install/.parameters +++ b/bin/commands/install/.parameters @@ -1,2 +1,3 @@ allow-overwrite,allow-overwritten||boolean|||||Allow overwritten existing MVS data set. dataset-prefix,ds-prefix||string|||||Install Zowe to this dataset prefix.\nIf you specify this value, --config is not required. +dry-run||boolean|||||Prints out existing JCL templates but does not generate resolved JCL. diff --git a/bin/commands/install/cliPrefix.ts b/bin/commands/install/cliPrefix.ts new file mode 100644 index 0000000000..0ee61fba82 --- /dev/null +++ b/bin/commands/install/cliPrefix.ts @@ -0,0 +1,22 @@ +/* + 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 * as std from 'cm_std'; +import * as index from './index'; + +const install = { + prefix: std.getenv("ZWE_CLI_PARAMETER_DATASET_PREFIX"), + yaml: false, + runtime: undefined, + jclHeader: undefined +} + +index.execute(install); \ No newline at end of file diff --git a/bin/commands/install/cliYaml.ts b/bin/commands/install/cliYaml.ts new file mode 100644 index 0000000000..bb440fffae --- /dev/null +++ b/bin/commands/install/cliYaml.ts @@ -0,0 +1,28 @@ +/* + 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 * as index from './index'; +import * as common from '../../libs/common'; +import * as config from '../../libs/config'; +import * as configmgr from '../../libs/configmgr'; + +common.requireZoweYaml(); +const zoweConfig = config.getZoweConfig(); + +const install = { + prefix: zoweConfig.zowe?.setup?.dataset?.prefix, + yaml: true, + runtime: zoweConfig.zowe?.runtimeDirectory, + jclHeader: zoweConfig.zowe.environments?.jclHeader +} + +index.execute(install); +configmgr.cleanupTempDir(); diff --git a/bin/commands/install/index.sh b/bin/commands/install/index.sh index 0fc9e7fad6..bbcfa23ba3 100644 --- a/bin/commands/install/index.sh +++ b/bin/commands/install/index.sh @@ -10,143 +10,27 @@ # # Copyright Contributors to the Zowe Project. ####################################################################### + +# zwe command allows to use parameter without value: +# zwe install --ds-prefix ---> ZWE_CLI_PARAMETER_DATASET_PREFIX="" +# To go thru "DS Prefix" code, we have to use test -n ${var+foo} -print_level0_message "Install Zowe MVS data sets" +CEE_RO="XPLINK(ON),HEAPPOOLS(OFF),HEAPPOOLS64(OFF)" -############################### -# constants -# keep in sync with workflows/templates/smpe-install/ZWE3ALOC.vtl -cust_ds_list="${ZWE_PRIVATE_DS_SZWESAMP}|Zowe sample library|dsntype(library) dsorg(po) recfm(f b) lrecl(80) unit(sysallda) space(15,15) tracks -${ZWE_PRIVATE_DS_SZWEAUTH}|Zowe authorized load library|dsntype(library) dsorg(po) recfm(u) lrecl(0) blksize(32760) unit(sysallda) space(30,15) tracks -${ZWE_PRIVATE_DS_SZWELOAD}|Zowe load library|dsntype(library) dsorg(po) recfm(u) lrecl(0) blksize(32760) unit(sysallda) space(30,15) tracks -${ZWE_PRIVATE_DS_SZWEEXEC}|Zowe executable utilities library|dsntype(library) dsorg(po) recfm(f b) lrecl(80) unit(sysallda) space(15,15) tracks" +# https://www.ibm.com/docs/en/zos/3.1.0?topic=descriptions-sh-invoke-shell +# ${parameter+word} +# Expands to word, provided that parameter is defined. -############################### -# validation -if [ -n "${ZWE_CLI_PARAMETER_DATASET_PREFIX}" ]; then - prefix="${ZWE_CLI_PARAMETER_DATASET_PREFIX}" +if [ -n "${ZWE_CLI_PARAMETER_DATASET_PREFIX+foo}" ]; then + _CEE_RUNOPTS="${CEE_RO}" ${ZWE_zowe_runtimeDirectory}/bin/utils/configmgr -script "${ZWE_zowe_runtimeDirectory}/bin/commands/install/cliPrefix.js" else - require_zowe_yaml - - # read prefix and validate - prefix=$(read_yaml "${ZWE_CLI_PARAMETER_CONFIG}" ".zowe.setup.dataset.prefix") - if [ -z "${prefix}" ]; then - print_error_and_exit "Error ZWEL0157E: Zowe dataset prefix (zowe.setup.dataset.prefix) is not defined in Zowe YAML configuration file." "" 157 + if [ -z "${ZWE_PRIVATE_TMP_MERGED_YAML_DIR}" ]; then + # user-facing command, use tmpdir to not mess up workspace permissions + export ZWE_PRIVATE_TMP_MERGED_YAML_DIR=1 fi -fi - -############################### -# create data sets if they do not exist -print_message "Create MVS data sets if they do not exist" -while read -r line; do - ds=$(echo "${line}" | awk -F"|" '{print $1}') - name=$(echo "${line}" | awk -F"|" '{print $2}') - spec=$(echo "${line}" | awk -F"|" '{print $3}') - - # check existence - ds_existence=$(is_data_set_exists "${prefix}.${ds}") - if [ "${ds_existence}" = "true" ]; then - if [ "${ZWE_CLI_PARAMETER_ALLOW_OVERWRITE}" = "true" ]; then - # warning - print_message "Warning ZWEL0300W: ${prefix}.${ds} already exists. Members in this data set will be overwritten." - else - # print_error_and_exit "Error ZWEL0158E: ${prefix}.${ds} already exists." "" 158 - # warning - print_message "Warning ZWEL0301W: ${prefix}.${ds} already exists and will not be overwritten. For upgrades, you must use --allow-overwrite." - fi + if [ -n "${ZWE_CLI_PARAMETER_CONFIG}" ]; then + _CEE_RUNOPTS="${CEE_RO}" ${ZWE_zowe_runtimeDirectory}/bin/utils/configmgr -script "${ZWE_zowe_runtimeDirectory}/bin/commands/install/cliYaml.js" else - print_message "Creating ${name} - ${prefix}.${ds}" - create_data_set "${prefix}.${ds}" "${spec}" - if [ $? -ne 0 ]; then - print_error_and_exit "Error ZWEL0111E: Command aborts with error." "" 111 - fi + print_error_and_exit "Error ZWEL0108E: Zowe YAML config file is required." "" 108 fi -done < --help\" (for example, \"zwe init stc --help\") to get more information." -print_message +fi \ No newline at end of file diff --git a/bin/commands/install/index.ts b/bin/commands/install/index.ts new file mode 100644 index 0000000000..1566b3ffe9 --- /dev/null +++ b/bin/commands/install/index.ts @@ -0,0 +1,133 @@ +/* + 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 * as std from 'cm_std'; +import * as xplatform from 'xplatform'; +import * as common from '../../libs/common'; +import * as fs from '../../libs/fs'; +import * as zosdataset from '../../libs/zos-dataset'; + +// ********************************** +// This would be moved to zos-dataset +function validDatasetName(dsn :string): boolean { + common.printTrace(`- validDatasetName for "${dsn}"`); + if (!dsn || dsn.length < 1 || dsn.length > 44) { + common.printTrace(' * dataset null, empty or > 44 chars'); + return false; + } + const result = !!dsn.match(/^([A-Z\$\#\@]){1}([A-Z0-9\$\#\@\-]){0,7}(\.([A-Z\$\#\@]){1}([A-Z0-9\$\#\@\-]){0,7}){0,11}$/g); + common.printTrace(` * regex match: ${result}`); + return result; +} +// This would be moved to zos-dataset +// ********************************** + +export function execute(install: any): void { + + common.printLevel1Message("Install Zowe MVS data sets"); + + const prefix = install.prefix; + if (install.yaml) { + if (!prefix) { + common.printErrorAndExit(`Error ZWEL0157E: Zowe dataset prefix (zowe.setup.dataset.prefix) is not defined in Zowe YAML configuration file.`, undefined, 157); + } + } else { + if (!prefix || !validDatasetName(prefix.toUpperCase())) { + common.printErrorAndExit(`Error ZWEL0102E: Invalid parameter --dataset-prefix="${prefix}".`, undefined, 102); + } + } + + let runtime = install.runtime; + const runtimeEnv = std.getenv('ZWE_zowe_runtimeDirectory'); + if (!runtime) { + runtime = runtimeEnv; + } else { + // We need clean path for xplatform.loadFileUTF8, otherwise will fail for e.g. /zowe/./files/SZWESAMP//ZWEINSTL + runtime = fs.convertToAbsolutePath(runtime); + if (runtime != runtimeEnv) { + common.printErrorAndExit(`Error ZWEL0105E: The Zowe YAML config file is associated to Zowe runtime "${runtime}", which is not same as where zwe command is located "${runtimeEnv}".`, undefined, 105); + } + } + + const ZWEINSTL=`${runtime}/files/SZWESAMP/ZWEINSTL`; + const DATASETS = [ 'SZWEAUTH', 'SZWEEXEC', 'SZWELOAD', 'SZWESAMP' ]; + const allowOverwrite = std.getenv("ZWE_CLI_PARAMETER_ALLOW_OVERWRITE") == 'true' ? true : false; + const dryRun = std.getenv("ZWE_CLI_PARAMETER_DRY_RUN") == 'true' ? true : false; + let skipJCL = false; + + for (let ds in DATASETS) { + if (zosdataset.isDatasetExists(`${prefix}.${DATASETS[ds]}`)) { + if (allowOverwrite == false) { + common.printMessage(`Warning ZWEL0301W: ${prefix}.${DATASETS[ds]} already exists and will not be overwritten. For upgrades, you must use --allow-overwrite.`); + skipJCL = true; + } else { + common.printMessage(`Warning ZWEL0300W: ${prefix}.${DATASETS[ds]} already exists. Members in this data set will be overwritten.`); + // ************************************************************** + console.log(`FAKE: tsocmd "DELETE '${prefix}.${DATASETS[ds]}'"`); + // ************************************************************** + } + } + } + + if (skipJCL) { + common.printLevel1Message("Zowe MVS data sets installation skipped."); + std.exit(0); + } + + let jclContents = xplatform.loadFileUTF8(ZWEINSTL, xplatform.AUTO_DETECT); + if (!jclContents) { + common.printErrorAndExit(`Error ZWEL0159E Failed to modify ${ZWEINSTL}.`, undefined, 159); + } + + // Make string from array or convert possible number to string + let jclHeader = install.jclHeader; + if (jclHeader !== undefined && jclHeader !== null && jclHeader !== '') { + jclHeader = Array.isArray(jclHeader) ? jclHeader.join("\n"): jclHeader.toString(); + jclContents = jclContents.replace(/\/\/ZWEINSTL JOB/gi, `//ZWEINSTL JOB ${jclHeader.replace(/[$]/g, '$$$$')}`); + } + + jclContents = jclContents.replace(/\{zowe\.setup\.dataset\.prefix\}/gi, prefix.replace(/[$]/g, '$$$$')); + jclContents = jclContents.replace(/\{zowe\.runtimeDirectory\}/gi, runtime.replace(/[$]/g, '$$$$')); + + common.printMessage(`Template JCL: ${ZWEINSTL}`); + common.printMessage('--- JCL content ---'); + common.printMessage(jclContents); + common.printMessage('--- End of JCL ---'); + + if (dryRun) { + common.printMessage('JCL not submitted, command run with "--dry-run" flag.'); + common.printMessage('To perform command, re-run command without "--dry-run" flag, or submit the JCL directly.'); + } else { + common.printMessage('Submitting Job ZWEINSTL'); + // ************************************************************** + // submitJob and waitForJob implemented in 3718 (migrate2JCL) + const result = { + rc: 0, + jobcccode: 123, + jobcctext: "JCL ESM error" + }; + // const jobid = zosJes.submitJob(jclContents, true, true); + // const result = zosJes.waitForJob(jobid); + // ************************************************************** + + common.printMessage(`Job completed with RC=${result.rc}`); + if (result.rc == 0) { + common.printLevel1Message("Zowe MVS data sets are installed successfully."); + common.printMessage("Zowe installation completed. In order to use Zowe, you need to run \"zwe init\" command to initialize Zowe instance."); + common.printMessage("- Type \"zwe init --help\" to get more information.\n\n"); + common.printMessage("You can also run individual init sub-commands: generate, mvs, certificate, security, vsam, apfauth, and stc."); + common.printMessage("- Type \"zwe init --help\" (for example, \"zwe init stc --help\") to get more information.\n\n"); + common.printMessage("Zowe JCL generated successfully"); + } else { + common.printMessage(`Zowe JCL submitted with errors, check job log. Job completion code=${result.jobcccode}, Job completion text=${result.jobcctext}`); + } + } +}