diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d7ede9fa..93bdf830a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Zowe Common C Changelog ## `3.1.0` +- Enhancement: `configmgr extract` option supports simple array (#502) - Bugfix: removed "ByteOutputStream" debug message, which was part of the `zwe` command output (#491) - Bugfix: HEAPPOOLS and HEAPPOOLS64 no longer need to be set to OFF for configmgr (#497) - Enhancement: module registry (#405) diff --git a/c/configmgr.c b/c/configmgr.c index 91f2a87ca..3e72d6468 100644 --- a/c/configmgr.c +++ b/c/configmgr.c @@ -1161,29 +1161,57 @@ int cfgGetBooleanC(ConfigManager *mgr, const char *configName, bool *result, int } } -static void extractText(ConfigManager *mgr, const char *configName, JsonPointer *jp, FILE *out){ +static int printPrimitiveDataType(Json *value, FILE *out) { + if (jsonIsString(value)){ + fprintf(out,"%s",jsonAsString(value)); + } else if (jsonIsInt64(value)){ + fprintf(out,"%lld",INT64_LL(jsonAsInt64(value))); + } else if (jsonIsDouble(value)){ + fprintf(out,"%f",jsonAsDouble(value)); + } else if (jsonIsBoolean(value)){ + fprintf(out,"%s",jsonAsBoolean(value) ? "true" : "false"); + } else if (jsonIsNull(value)){ + fprintf(out,"null"); + } else { + fprintf(out,"error: unhandled type"); + return ZCFG_EXTRACT_ERROR; + } + return ZCFG_SUCCESS; +} + +static int extractText(ConfigManager *mgr, const char *configName, JsonPointer *jp, FILE *out){ Json *value = NULL; int status = cfgGetAnyJ(mgr,configName,&value,jp); + int ret = 0; if (status){ fprintf(out,"error not found, reason=%d",status); - } else { - if (jsonIsObject(value) || - jsonIsArray(value)){ - fprintf(out,"error: cannot access whole objects or arrays"); - } else if (jsonIsString(value)){ - fprintf(out,"%s",jsonAsString(value)); - } else if (jsonIsInt64(value)){ - fprintf(out,"%lld",INT64_LL(jsonAsInt64(value))); - } else if (jsonIsDouble(value)){ - fprintf(out,"%f",jsonAsDouble(value)); - } else if (jsonIsBoolean(value)){ - fprintf(out,"%s",jsonAsBoolean(value) ? "true" : "false"); - } else if (jsonIsNull(value)){ - fprintf(out,"null"); - } else { - fprintf(out,"error: unhandled type"); + return ZCFG_EXTRACT_ERROR; + } + + if (jsonIsObject(value)) { + fprintf(out,"error: cannot access whole objects"); + return ZCFG_EXTRACT_ERROR; + } + + if (jsonIsArray(value)) { + JsonArray *array = jsonAsArray(value); + for (int i = 0; i < jsonArrayGetCount(array); i++) { + Json *arrayItem = jsonArrayGetItem(array, i); + if (jsonIsObject(arrayItem) || jsonIsArray(arrayItem)) { + fprintf(out,"error: cannot access objects or arrays in arrays"); + return ZCFG_EXTRACT_ERROR; + } else { + ret = printPrimitiveDataType(arrayItem, out); + fprintf(out, "\n"); + if (ret) { + return ret; + } + } } + } else { + ret = printPrimitiveDataType(value, out); } + return ret; } #define MAX_PATH_NAME 1024 @@ -1831,9 +1859,10 @@ static int simpleMain(int argc, char **argv){ printJsonPointer(mgr->traceOut,jp); fflush(mgr->traceOut); } - extractText(mgr,configName,jp,stdout); + int extractResult = extractText(mgr,configName,jp,stdout); printf("\n"); fflush(stdout); + return extractResult; } } else if (!strcmp(command, "env")) { if (argx >= argc){ diff --git a/h/configmgr.h b/h/configmgr.h index 303c4ffaa..3cadd107e 100644 --- a/h/configmgr.h +++ b/h/configmgr.h @@ -50,6 +50,7 @@ typedef struct ConfigManager_tag{ #define ZCFG_IO_ERROR 13 #define ZCFG_VALIDATION_INTERNAL_ERROR 14 #define ZCFG_JQ_PARSE_ERROR 15 +#define ZCFG_EXTRACT_ERROR 16 /* Normal way to tell people the program succeded but their config is bad */ #define ZCFG_CONFIG_FAILED_VALIDATION 99 diff --git a/tests/configmgr/extract/extract.json b/tests/configmgr/extract/extract.json new file mode 100644 index 000000000..b0c9c7e6e --- /dev/null +++ b/tests/configmgr/extract/extract.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09", + "$id": "https://zowe.org/schema/base", + "type": "object", + "properties": { + "test": { + "type": "object", + "additionalProperties": false + } + } +} diff --git a/tests/configmgr/extract/extract.yaml b/tests/configmgr/extract/extract.yaml new file mode 100644 index 000000000..67ba95299 --- /dev/null +++ b/tests/configmgr/extract/extract.yaml @@ -0,0 +1,33 @@ +test: + number1: 0 + number2: "${{ 9 * 13 }}" + number3: 123456789 + boolean1: false + boolean2: "${{ 1 === 1 }}" + null1: ~ + null2: null + null3: + string1: 'Hello, World!' + string2: "${{ 'a'.repeat(16) }}" + array1: + - 'apple' + - 'banana' + - 'kiwi' + array2: [ 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 ] + array3: + - 'string' + - 0 + - true + - "${{ 1 + 1 }}" + - "${{ [ 1, 2, 3 ].toString() }}" + - ~ + array4: [] + array5: [ ~, ~, ~ ] + error_expected1: + - 'First item' + - [ 0, 1 ] + - [ 0, 1, 2 ] + error_expected2: + NESTED: + OBJECTS: + SUPPORTED: false diff --git a/tests/configmgr/extract/index.sh b/tests/configmgr/extract/index.sh new file mode 100755 index 000000000..7adff893f --- /dev/null +++ b/tests/configmgr/extract/index.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +####################################################################### +# 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. +####################################################################### + +if [ `uname` != "OS/390" ]; then + echo "Error: this test must run on a z/OS system." + exit 1 +fi + +if [ "${1}" = "--help" ]; then + echo "Test the configmgr with 'extract' option" + echo " no parm: tries to run configmgr from current 'zowe-common-c/bin'" + echo " path: path to configmgr" + echo " --help: this help" + exit 0 +fi + +configmgr_path="${1}" +if [ -z "${configmgr_path}" ]; then + configmgr_path="../../../bin/configmgr" +fi + +if [ ! -f "${configmgr_path}" ]; then + echo "Error: configmgr not found in '${configmgr_path}'" + exit 4 +fi + +schema="./extract.json" +yaml="./extract.yaml" +fileYaml="FILE(${yaml})" + +# To simplify this test, any property starting with lowercase will be tested, the rest is ignored +test_set=$(cat "${yaml}" | grep -E '^[\ ]+[a-z]+' | awk -F: '{ print $1 }'); + +for item in $test_set; do + + result=$(_CEE_RUNOPTS="XPLINK(ON)" "${configmgr_path}" -s "${schema}" -p "${fileYaml}" extract "/test/${item}"); + echo "rc=${?}: Item ${item} -> $result" + +done