diff --git a/apps/TCPB_-_JSON_Builder/.gitignore b/apps/TCPB_-_JSON_Builder/.gitignore new file mode 100644 index 0000000..f917d54 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/.gitignore @@ -0,0 +1,47 @@ +#================================================= +# Python App Template +# Version: 1.0.0 +# Last Updated: 2017/10/04 +#================================================= + +#------------------------------------------------- +# Language Exclusions +#------------------------------------------------- +__pycache__ +*.pyc + +#------------------------------------------------- +# App Specific Exclusions +#------------------------------------------------- +*.log +log +sample-*.json + +#------------------------------------------------- +# Build Exclusions +#------------------------------------------------- +build +lib_* +target +temp + +#------------------------------------------------- +# IDE Exclusions +#------------------------------------------------- +.c9 +.idea +.project +.python-version +.settings +.vscode +nbproject + +#------------------------------------------------- +# Other Nonsense +#------------------------------------------------- +bcs* + +#************************************************* +# Custom Exclusion (per App exclusions) +#************************************************* +sample.json \ No newline at end of file diff --git a/apps/TCPB_-_JSON_Builder/README.md b/apps/TCPB_-_JSON_Builder/README.md new file mode 100644 index 0000000..f8f9ace --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/README.md @@ -0,0 +1,35 @@ +# Release Notes +## 1.0.0 +* Initial Release + +--- + +# Summary +This playbook App will take a JSON formatted String with embedded variables and output a JSON String. + +> Note: String value must be wrapped in double quotes. All other values should **not** have double quotes. + +# Dependencies +* tcex>=0.7,<0.8 + +# Input Definitions +* JSON Data - The JSON string to resolve embedded variables. + +# Output Definitions +* json.data - The JSON String with all embedded variables resolved. + +# Building + +``` +pip install tcex +tclib +tcpackage +``` + +# Local Testing + +All the environment variables in `tcex.d/profiles/json_builder.json` file must be set on the local system. + +``` +tcrun --group qa-build +``` \ No newline at end of file diff --git a/apps/TCPB_-_JSON_Builder/__main__.py b/apps/TCPB_-_JSON_Builder/__main__.py new file mode 100644 index 0000000..07dc156 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/__main__.py @@ -0,0 +1,73 @@ +"""Set lib directory for current version of Python""" +import os +import subprocess +import sys + +__version__ = '1.0.1' + + +def main(): + """Main""" + lib_directory = None + + # All Python Version that will be searched + lib_major_version = 'lib_{}'.format(sys.version_info.major) + lib_minor_version = '{}.{}'.format(lib_major_version, sys.version_info.minor) + lib_micro_version = '{}.{}'.format(lib_minor_version, sys.version_info.micro) + + # Get all "lib" directories + app_path = os.getcwd() + contents = os.listdir(app_path) + lib_directories = [] + for c in contents: + # ensure content starts with lib, is directory, and is readable + if c.startswith('lib') and os.path.isdir(c) and (os.access(c, os.R_OK)): + lib_directories.append(c) + # reverse sort directories + lib_directories.sort(reverse=True) + + # Find most appropriate FULL version + lib_directory = None + if lib_micro_version in lib_directories: + lib_directory = lib_micro_version + elif lib_minor_version in lib_directories: + lib_directory = lib_minor_version + elif lib_major_version in lib_directories: + lib_directory = lib_major_version + else: + for lv in [lib_micro_version, lib_minor_version, lib_major_version]: + for ld in lib_directories: + if lv in ld: + lib_directory = ld + break + else: + continue + break + + # No reason to continue if no valid lib directory found + if lib_directory is None: + print('Failed to find lib directory ({}).'.format(lib_directories)) + sys.exit(1) + + # Use this if you want to include modules from a subfolder + # lib_path = os.path.realpath( + # os.path.abspath( + # os.path.join( + # os.path.split(inspect.getfile(inspect.currentframe()))[0], lib_directory))) + lib_path = os.path.join(app_path, lib_directory) + if 'PYTHONPATH' in os.environ: + os.environ['PYTHONPATH'] = '{}{}{}'.format(lib_path, os.pathsep, os.environ['PYTHONPATH']) + else: + os.environ['PYTHONPATH'] = '{}'.format(lib_path) + + # Update system arguments + sys.argv[0] = sys.executable + sys.argv[1] = '{}.py'.format(sys.argv[1]) + + # Make sure to exit with the return value from the subprocess call + ret = subprocess.call(sys.argv) + sys.exit(ret) + + +if __name__ == '__main__': + main() diff --git a/apps/TCPB_-_JSON_Builder/docs/screenshot_1.jpg b/apps/TCPB_-_JSON_Builder/docs/screenshot_1.jpg new file mode 100644 index 0000000..02c217c Binary files /dev/null and b/apps/TCPB_-_JSON_Builder/docs/screenshot_1.jpg differ diff --git a/apps/TCPB_-_JSON_Builder/install.json b/apps/TCPB_-_JSON_Builder/install.json new file mode 100644 index 0000000..9b63a09 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/install.json @@ -0,0 +1,31 @@ +{ + "allowOnDemand": true, + "displayName": "JSON Builder", + "languageVersion": "3.6", + "listDelimiter": "|", + "note": "Take data of multiple types and output a JSON String.", + "params": [{ + "label": "JSON Data", + "name": "json_data", + "note": "The JSON data including variables types. String variables must be manually wrapped in double quotes. All other Types should not have double quotes. Binary/BinaryArray values are not supported.", + "playbookDataType": [ + "Any" + ], + "required": true, + "sequence": 1, + "type": "String", + "validValues": ["${TEXT}"], + "viewRows": 20 + }], + "playbook": { + "outputVariables": [{ + "name": "json.data", + "type": "String" + }], + "type": "Utility" + }, + "programLanguage": "PYTHON", + "programMain": "json_builder", + "programVersion": "1.0.0", + "runtimeLevel": "Playbook" +} \ No newline at end of file diff --git a/apps/TCPB_-_JSON_Builder/json_builder.py b/apps/TCPB_-_JSON_Builder/json_builder.py new file mode 100644 index 0000000..e409bfe --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/json_builder.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +""" JSON Pretty Playbook App """ +import codecs +import json +import traceback +import sys + +from tcex import TcEx + +# Python 2 unicode +if sys.version_info[0] == 2: + reload(sys) + sys.setdefaultencoding('utf-8') + +tcex = TcEx() + +# App args +tcex.parser.add_argument('--json_data', required=True) +args = tcex.args + + +def main(): + """Main App Logic""" + json_data = tcex.playbook.read(args.json_data) + + try: + json.loads(json_data) + except Exception as e: + err = 'JSON data was not properly formatted ({}).'.format(e) + tcex.log.error(err) + tcex.message_tc(err) + tcex.playbook.exit(1) + + # create output + tcex.log.info('JSON data: {}'.format(json_data)) + tcex.playbook.create_output('json.data', json_data) + + tcex.message_tc('JSON data has been created.') + tcex.exit() + + +if __name__ == '__main__': + try: + main() + except Exception as e: + main_err = 'Generic Error. See logs for more details ({}).'.format(e) + tcex.log.error(traceback.format_exc()) + tcex.message_tc(main_err) + tcex.playbook.exit(1) diff --git a/apps/TCPB_-_JSON_Builder/requirements.txt b/apps/TCPB_-_JSON_Builder/requirements.txt new file mode 100644 index 0000000..0341530 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/requirements.txt @@ -0,0 +1 @@ +tcex>=0.7,<0.8 diff --git a/apps/TCPB_-_JSON_Builder/setup.cfg b/apps/TCPB_-_JSON_Builder/setup.cfg new file mode 100644 index 0000000..abca849 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/setup.cfg @@ -0,0 +1,7 @@ +[flake8] +max-line-length = 100 +ignore = E402 + +[pep8] +max-line-length = 100 +ignore = E402 \ No newline at end of file diff --git a/apps/TCPB_-_JSON_Builder/tcex.d/data/json_builder.json b/apps/TCPB_-_JSON_Builder/tcex.d/data/json_builder.json new file mode 100644 index 0000000..bbfe9c7 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/tcex.d/data/json_builder.json @@ -0,0 +1,29 @@ +[{ + "data": "\"one\"", + "variable": "#App:0001:name!String" + }, + { + "data": ["#App:0001:name!String", "two", "three"], + "variable": "#App:0001:counts!StringArray" + }, + { + "data": { + "key": "numbers", + "value": "#App:0001:counts!StringArray" + }, + "variable": "#App:0002:numbers!KeyValue" + }, + { + "data": [{ + "key": "alias", + "value": "ace" + }, { + "key": "alias", + "value": "#App:0001:name!String" + }, { + "key": "counts", + "value": "#App:0001:counts!StringArray" + }], + "variable": "#App:0002:aliases!KeyValueArray" + } +] \ No newline at end of file diff --git a/apps/TCPB_-_JSON_Builder/tcex.d/profiles/json_builder.json b/apps/TCPB_-_JSON_Builder/tcex.d/profiles/json_builder.json new file mode 100644 index 0000000..806b7fe --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/tcex.d/profiles/json_builder.json @@ -0,0 +1,50 @@ +[ + { + "args": { + "api_default_org": "$env.API_DEFAULT_ORG", + "api_access_id": "$env.API_ACCESS_ID", + "api_secret_key": "$envs.API_SECRET_KEY", + "tc_api_path": "$env.TC_API_PATH", + "tc_log_level": "debug", + "tc_log_path": "log", + "tc_log_to_api": false, + "tc_out_path": "log", + "tc_proxy_external": false, + "tc_proxy_tc": false, + "tc_temp_path": "log", + "tc_playbook_db_type": "Redis", + "tc_playbook_db_context": "686be118-ff9a-4d05-bb14-4c1c6a0c9b87", + "tc_playbook_db_path": "$env.DB_PATH", + "tc_playbook_db_port": "$env.DB_PORT", + "tc_playbook_out_variables": "#App:3681:json.data!String", + "json_data": "{\"name\": \"#App:0001:name!String\", \"counts\": #App:0001:counts!StringArray, \"numbers\": #App:0002:numbers!KeyValue, \"aliases\": #App:0002:aliases!KeyValueArray}" + }, + "data_files": [ + "tcex.d/data/json_builder.json" + ], + "description": "Pass test of JSON Builder playbook App.", + "exit_codes": [ + 0 + ], + "groups": [ + "local" + ], + "install_json": "install.json", + "profile_name": "json-builder", + "quiet": false, + "validations": [ + { + "data": null, + "data_type": "redis", + "operator": "ne", + "variable": "#App:3681:json.data!String" + }, + { + "data": "string", + "data_type": "redis", + "operator": "it", + "variable": "#App:3681:json.data!String" + } + ] + } +] \ No newline at end of file diff --git a/apps/TCPB_-_JSON_Builder/tcex.json b/apps/TCPB_-_JSON_Builder/tcex.json new file mode 100644 index 0000000..add7811 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/tcex.json @@ -0,0 +1,15 @@ +{ + "package": { + "app_name": "TCPB_-_JSON_Create", + "bundle": false, + "excludes": [ + "requirements.txt", + "tcex.d" + ], + "outdir": "target" + }, + "profiles": [], + "profile_include_dirs": [ + "tcex.d/profiles" + ] +} \ No newline at end of file diff --git a/apps/TCPB_-_JSON_Builder/tcex_json_schema.json b/apps/TCPB_-_JSON_Builder/tcex_json_schema.json new file mode 100644 index 0000000..1464161 --- /dev/null +++ b/apps/TCPB_-_JSON_Builder/tcex_json_schema.json @@ -0,0 +1,240 @@ +{ + "additionalProperties": false, + "properties": { + "allowOnDemand": { + "type": "boolean" + }, + "allowRunAsUser": { + "type": "boolean" + }, + "apiUserTokenParam": { + "type": "boolean" + }, + "displayName": { + "type": "string" + }, + "feeds": { + "items": { + "additionalProperties": false, + "properties": { + "attributesFile": { + "type": "string" + }, + "enableBulkJson": { + "type": "boolean" + }, + "documentStorageLimitMb": { + "type": "integer" + }, + "indicatorLimit": { + "type": "integer" + }, + "jobFile": { + "type": "string" + }, + "sourceCategory": { + "type": "string" + }, + "sourceDescription": { + "type": "string" + }, + "sourceName": { + "type": "string" + } + } + } + }, + "languageVersion": { + "type": "string" + }, + "listDelimiter": { + "type": "string" + }, + "minServerVersion": { + "type": "string" + }, + "note": { + "type": "string" + }, + "params": { + "items": { + "additionalProperties": false, + "properties": { + "allowMultiple": { + "type": "boolean" + }, + "default": { + "type": [ + "boolean", + "integer", + "string" + ] + }, + "encrypt": { + "type": "boolean" + }, + "exposePlaybookKeyAs": { + "items": { + "enum": [ + "Binary", + "BinaryArray", + "KeyValue", + "KeyValueArray", + "String", + "StringArray", + "TCEntity", + "TCEntityArray" + ] + } + }, + "hidden": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "name": { + "type": "string" + }, + "note": { + "type": "string" + }, + "playbookDataType": { + "items": { + "enum": [ + "Any", + "Binary", + "BinaryArray", + "KeyValue", + "KeyValueArray", + "String", + "StringArray", + "TCEntity", + "TCEntityArray" + ] + }, + "type": "array" + }, + "required": { + "type": "boolean" + }, + "sequence": { + "type": "integer" + }, + "type": { + "enum": [ + "Boolean", + "Choice", + "KeyValueList", + "MultiChoice", + "String", + "StringMixed" + ], + "type": "string" + }, + "validValues": { + "type": "array" + }, + "viewRows": { + "type": "integer" + } + }, + "required": [ + "label", + "name", + "type" + ], + "type": "object" + }, + "type": "array", + "uniqueItems": true + }, + "playbook": { + "properties": { + "outputVariables": { + "items": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "type": { + "enum": [ + "Binary", + "BinaryArray", + "KeyValue", + "KeyValueArray", + "String", + "StringArray", + "TCEntity", + "TCEntityArray" + ], + "type": "string" + } + }, + "required": [ + "name", + "type" + ], + "type": "object" + }, + "type": "array", + "uniqueItems": false + }, + "retry": { + "additionalProperties": false, + "properties": { + "allowed": { + "type": "boolean" + }, + "defaultDelayMinutes": { + "type": "integer" + }, + "defaultMaxRetries": { + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "programIcon": { + "type": "string" + }, + "programLanguage": { + "type": "string" + }, + "programMain": { + "type": "string" + }, + "programVersion": { + "type": "string" + }, + "publishOutFiles": { + "type": "array" + }, + "repeatingMinutes": { + "type": "array" + }, + "runtimeContext": { + "type": "array" + }, + "runtimeLevel": { + "type": [ + "array", + "string" + ] + } + }, + "required": [ + "allowOnDemand", + "displayName", + "params", + "programLanguage", + "programMain", + "programVersion", + "runtimeLevel" + ], + "type": "object" +} \ No newline at end of file