From a1b9c85b936483f3a3ba9ecbc647d4c48341d7b6 Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Wed, 3 Jul 2024 17:00:20 +0300 Subject: [PATCH 1/8] Add Transform Data example --- README.md | 7 + transform-data/README.md | 66 ++++++ transform-data/catalog.json | 412 ++++++++++++++++++++++++++++++++++++ 3 files changed, 485 insertions(+) create mode 100644 transform-data/README.md create mode 100644 transform-data/catalog.json diff --git a/README.md b/README.md index 932f0a4..2611485 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Table of Contents * [Neo](#neo) * [Scripting](#scripting) * [Automation Pilot](#automation-pilot) + * [Utility Commands](#utility-commands) * [Resources](#resources) * [Known Issues](#known-issues) * [How to obtain support](#how-to-obtain-support) @@ -117,6 +118,12 @@ After importing, you'll see a new catalog tile - **Automation Pilot Examples**. |---------|-------------| | [Backup Catalog to GitHub](backup-catalog) | Backup catalog's content to GitHub | +### Utility Commands + +| Example | Description | +|---------|-------------| +| [Transform Data](transform-data) | Transform Data between different formats | + ## Resources Check out the following resources if you want to get familiar with Automation Pilot: diff --git a/transform-data/README.md b/transform-data/README.md new file mode 100644 index 0000000..5912a07 --- /dev/null +++ b/transform-data/README.md @@ -0,0 +1,66 @@ +# Utility Commands + +Table of Contents + +* [Description](#description) +* [Requirements](#requirements) +* [How to use](#how-to-use) +* [Expected result](#expected-result) + +## Description + +The commands attempts to transform data from the source data type to the target data type. + +## Requirements + +There are no requirements to use this command. + +## How to use + +Enter the required input keys: +* data +* sourceFormat +* targetFormat + +## Expected result + +The expected result is to received the output data in the target format. + +### Examples + +* Transforming XML to JSON +Input: +``` +Hello +``` +Output: +``` +{ + "xml": { + "@name": "John", + "@age": 25, + "$": "Hello" + } +} +``` + +* Transforming JSON to CSV +Input: +``` +[ + { + "name": "John", + "age": 25 + }, + { + "name": "Monica", + "age": 23 + } +] +``` +Output: +``` +name,age +John,25 +Monica,23 +``` \ No newline at end of file diff --git a/transform-data/catalog.json b/transform-data/catalog.json new file mode 100644 index 0000000..e24f2ba --- /dev/null +++ b/transform-data/catalog.json @@ -0,0 +1,412 @@ +{ + "id": "examples-<<>>", + "technicalName": "examples", + "name": "Automation Pilot Examples", + "description": "Source: https://github.com/SAP-samples/automation-pilot-examples", + "owner": "<<>>", + "inputs": [], + "commands": [ + { + "configuration": { + "values": [], + "output": { + "output": "$(if .toXml.executed then .toXml.output.output | join(\"\\n\") elif .fromXmltoXml.executed then .fromXmltoXml.output.message elif .toYaml.executed then .toYaml.output.message elif .toCsv.executed then .toCsv.output.message elif .execution.input.targetFormat == \"JSON\" then .inputAsJson.output.message else .toXml.output.output | join(\"\\n\") end)" + }, + "executors": [ + { + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(if .execution.input.data | toObject != null then .execution.input.data else .execution.input.data | toArray end)" + }, + "alias": "toJsonFromJson", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "AND", + "cases": [ + { + "expression": "$(.execution.input.sourceFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "JSON" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(.execution.input.data | fromXml)" + }, + "alias": "toJsonFromXml", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.input.sourceFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "XML" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(.execution.input.data | fromYaml)" + }, + "alias": "toJsonFromYaml", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.input.sourceFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "YAML" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "scripts-sapcp:ExecutePythonScript:1", + "input": { + "stdin": "$(.execution.input.data)", + "script": "import csv\nimport json\nimport sys\n\n# create a list\ndata = []\n\n# read from standard input\nreader = csv.DictReader(sys.stdin)\n\n# for each row in the CSV, add it to the list\nfor row in reader:\n data.append(row)\n\n# write to standard output\njson.dump(data, sys.stdout, indent=2)" + }, + "alias": "toJsonFromCSV", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.input.sourceFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "CSV" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(if .toJsonFromJson.executed then .toJsonFromJson.output.message elif .toJsonFromXml.executed then .toJsonFromXml.output.message elif .toJsonFromYaml.executed then .toJsonFromYaml.output.message elif .toJsonFromYaml.executed then .toJsonFromYaml.output.message else .toJsonFromCSV.output.result | join(\"\\n\") | toArray end)" + }, + "alias": "inputAsJson", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "scripts-sapcp:ExecuteScript:2", + "input": { + "stdin": "$(.inputAsJson.output.message)", + "script": "jq -r '\n def toxml:\n . as $in |\n if type == \"object\" then\n $in | to_entries | map(\"<\\(.key)>\" + (.value | toxml) + \"\") | join(\"\")\n elif type == \"array\" then\n map(\"\" + (toxml) + \"\") | join(\"\")\n else\n tostring\n end;\n\n if type == \"array\" then\n \"\" + (map(toxml) | join(\"\")) + \"\"\n else\n toxml\n end\n'" + }, + "alias": "toXml", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "AND", + "cases": [ + { + "expression": "$(.execution.input.targetFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "XML" + ] + }, + { + "expression": "$(.inputAsJson.output.message | length)", + "operator": "GREATER_THAN", + "semantic": "OR", + "values": [ + "0" + ] + }, + { + "expression": "$(.execution.input.sourceFormat)", + "operator": "NOT_EQUALS", + "semantic": "OR", + "values": [ + "XML" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(if .execution.input.data | fromXml != null then .execution.input.data else null end)" + }, + "alias": "fromXmltoXml", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "AND", + "cases": [ + { + "expression": "$(.execution.input.targetFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "XML" + ] + }, + { + "expression": "$(.execution.input.sourceFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "XML" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(.inputAsJson.output.message | if . | toObject then . | toObject else . | toArray end | toYaml)" + }, + "alias": "toYaml", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.input.targetFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "YAML" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(.inputAsJson.output.message | toArray | [.[0] | [to_entries[].key] | join(\",\")] + (. | map(. | [to_entries[].value] | join(\",\")))| join(\"\\n\"))" + }, + "alias": "toCsv", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.input.targetFormat)", + "operator": "EQUALS", + "semantic": "OR", + "values": [ + "CSV" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:TransformData:1", + "name": "TransformData", + "description": "Transforms data between different formats", + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "data": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "targetFormat": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": [ + "JSON", + "XML", + "YAML", + "CSV" + ], + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "sourceFormat": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": [ + "JSON", + "XML", + "YAML", + "CSV" + ], + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "output": { + "type": "string", + "sensitive": false, + "description": null + } + }, + "tags": { + "feature:logs": "", + "feature:priority": "medium" + } + } + ] +} \ No newline at end of file From a9cc1ca02b17e4d803be9eae39753cb441b2b4ea Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Wed, 3 Jul 2024 17:10:42 +0300 Subject: [PATCH 2/8] Remove execution logs --- transform-data/catalog.json | 1 - 1 file changed, 1 deletion(-) diff --git a/transform-data/catalog.json b/transform-data/catalog.json index e24f2ba..c67aa37 100644 --- a/transform-data/catalog.json +++ b/transform-data/catalog.json @@ -404,7 +404,6 @@ } }, "tags": { - "feature:logs": "", "feature:priority": "medium" } } From 581dd5e88f2e04183133b12aa45cef7f309b27e6 Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Wed, 3 Jul 2024 18:13:19 +0300 Subject: [PATCH 3/8] Fix --- README.md | 2 +- transform-data/README.md | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2611485..f1bf4ad 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ After importing, you'll see a new catalog tile - **Automation Pilot Examples**. | Example | Description | |---------|-------------| -| [Transform Data](transform-data) | Transform Data between different formats | +| [Transform Data](transform-data) | Transform Data between different formats - JSON, XML, YAML, and CSV | ## Resources diff --git a/transform-data/README.md b/transform-data/README.md index 5912a07..c03170d 100644 --- a/transform-data/README.md +++ b/transform-data/README.md @@ -1,4 +1,4 @@ -# Utility Commands +# Transform Data Table of Contents @@ -10,6 +10,11 @@ Table of Contents ## Description The commands attempts to transform data from the source data type to the target data type. +Currently this commands transforming data from and to: +* JSON +* XML +* YAML +* CSV ## Requirements From c948471c12b25c9d9270f24e7d73de1b321155de Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Thu, 4 Jul 2024 08:36:55 +0300 Subject: [PATCH 4/8] Add --- README.md | 1 + .../README.md | 37 ++ .../catalog.json | 620 ++++++++++++++++++ 3 files changed, 658 insertions(+) create mode 100644 trigger-and-collect-outputs-batching/README.md create mode 100644 trigger-and-collect-outputs-batching/catalog.json diff --git a/README.md b/README.md index f1bf4ad..d679d8e 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,7 @@ After importing, you'll see a new catalog tile - **Automation Pilot Examples**. | Example | Description | |---------|-------------| | [Transform Data](transform-data) | Transform Data between different formats - JSON, XML, YAML, and CSV | +| [Trigger and Collect Outputs Batching](trigger-and-collect-outputs-batching) | Trigger Multiple Executions in Batches and Collect their Outputs | ## Resources diff --git a/trigger-and-collect-outputs-batching/README.md b/trigger-and-collect-outputs-batching/README.md new file mode 100644 index 0000000..477d263 --- /dev/null +++ b/trigger-and-collect-outputs-batching/README.md @@ -0,0 +1,37 @@ + + +# Trigger Multiple Executions and Collect their Outputs + +Table of Contents + +* [Description](#description) +* [Requirements](#requirements) +* [How to use](#how-to-use) +* [Expected result](#expected-result) + +## Description + +This example contains commands that achieve the following +1. Execute a command with configured input values in batches +2. Collect the created executions' output values +3. Delete the created executions + +## Requirements + +To use this example you'll need the following: + +The user and password of a SAP Automation Pilot service account with Read, Write, and Execute permissions. + +## How to use + +1. Import the catalog +2. Trigger the `TriggerAndCollectOutputsBatching` command +3. View the output of the execution + +## Expected result + +By default the command will trigger and delete one execution of the Void command in SAP Automation Pilot. +The output for the default input values will be: +``` +[{"message":"Hello"}] +``` diff --git a/trigger-and-collect-outputs-batching/catalog.json b/trigger-and-collect-outputs-batching/catalog.json new file mode 100644 index 0000000..03819e4 --- /dev/null +++ b/trigger-and-collect-outputs-batching/catalog.json @@ -0,0 +1,620 @@ +{ + "id": "examples-<<>>", + "technicalName": "examples", + "name": "Automation Pilot Examples", + "description": "Source: https://github.com/SAP-samples/automation-pilot-examples", + "owner": "<<>>", + "inputs": [], + "commands": [ + { + "configuration": { + "values": [], + "output": {}, + "executors": [ + { + "execute": "http-sapcp:HttpRequest:1", + "input": { + "password": "$(.execution.input.password)", + "method": "DELETE", + "user": "$(.execution.input.user)", + "url": "$(.execution.metadata.autoPiUrl)/api/v1/executions/$(.execution.input.execution)" + }, + "alias": "deleteExecution", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:DeleteExecution:1", + "name": "DeleteExecution", + "description": "Triggers a command for execution", + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "execution": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": "The id of the execution" + }, + "password": { + "type": "string", + "sensitive": true, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": "Password of a service account with 'Write' permissions" + }, + "user": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": "Name of a service account with 'Write' permissions" + } + }, + "outputKeys": {}, + "tags": {} + }, + { + "configuration": { + "values": [], + "output": { + "outputs": "$(.getExecutionOutputs.output.outputs | map(.output))" + }, + "executors": [ + { + "execute": "utils-sapcp:ForEach:1", + "input": { + "inputs": "$([range(.execution.input.executions) | {\"values\": $.execution.input.inputValues // {}, \"sensitiveValues\": $.execution.input.sensitiveInputValues // {}}])", + "defaultValues": "{\"user\": \"$(.execution.input.user)\", \"password\": \"$(.execution.input.password)\", \"command\": \"$(.execution.input.command)\", \"inputs\": $(.execution.input.inputs // [])}", + "command": "autopi-sapcp:TriggerExecution:1" + }, + "alias": "generateExecutions", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": { + "maxCount": 10, + "delay": "5s", + "logic": "FIXED", + "applyOnValidation": false, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.error.originalMessage)", + "operator": "CONTAINS", + "semantic": "OR", + "values": [ + "Reason: Connectivity timeout issue" + ] + } + ] + } + ] + } + }, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:ForEach:1", + "input": { + "inputs": "$([.generateExecutions.output.outputs[] | {\"execution\": .execution}])", + "defaultValues": "{\"user\": \"$(.execution.input.user)\", \"password\": \"$(.execution.input.password)\"}", + "command": "autopi-sapcp:WaitExecutionStatus:1" + }, + "alias": "waitExecutions", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": { + "maxCount": 10, + "delay": "5s", + "logic": "FIXED", + "applyOnValidation": false, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.error.originalMessage)", + "operator": "CONTAINS", + "semantic": "OR", + "values": [ + "Reason: Connectivity timeout issue" + ] + } + ] + } + ] + } + }, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:ForEach:1", + "input": { + "inputs": "$([.generateExecutions.output.outputs[] | {\"execution\": .execution}])", + "defaultValues": "{\"user\": \"$(.execution.input.user)\", \"password\": \"$(.execution.input.password)\"}", + "command": "autopi-sapcp:GetExecutionOutput:1" + }, + "alias": "getExecutionOutputs", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": { + "maxCount": 10, + "delay": "5s", + "logic": "FIXED", + "applyOnValidation": false, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.error.originalMessage)", + "operator": "CONTAINS", + "semantic": "OR", + "values": [ + "Reason: Connectivity timeout issue" + ] + } + ] + } + ] + } + }, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "utils-sapcp:ForEach:1", + "input": { + "inputs": "$(.generateExecutions.output.outputs | map({execution}))", + "defaultValues": "{\"user\": \"$(.execution.input.user)\", \"password\": \"$(.execution.input.password)\"}", + "command": "examples-<<>>:DeleteExecution:1" + }, + "alias": "deleteExecutions", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": { + "maxCount": 10, + "delay": "5s", + "logic": "FIXED", + "applyOnValidation": false, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.error.originalMessage)", + "operator": "CONTAINS", + "semantic": "OR", + "values": [ + "Reason: Connectivity timeout issue" + ] + } + ] + } + ] + } + }, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:TriggerAndCollectOutputs:1", + "name": "TriggerAndCollectOutputs", + "description": null, + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "password": { + "type": "string", + "sensitive": true, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "executions": { + "type": "number", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": 1, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": "1", + "defaultValueFromInput": null, + "description": null + }, + "inputs": { + "type": "array", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "user": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "command": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": "utils-sapcp:Void:1", + "defaultValueFromInput": null, + "description": null + }, + "inputValues": { + "type": "object", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "sensitiveInputValues": { + "type": "string", + "sensitive": true, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "outputs": { + "type": "array", + "sensitive": false, + "description": null + } + }, + "tags": { + "feature:logs": "", + "feature:priority": "medium" + } + }, + { + "configuration": { + "values": [], + "output": { + "outputs": "$((if .generateExecutionBatches.output.outputs then [.generateExecutionBatches.output.outputs | map(.outputs)[][]] else [] end) + (.remainderExecutions.output.outputs // []))" + }, + "executors": [ + { + "execute": "utils-sapcp:ForEach:1", + "input": { + "inputs": "$([range((.execution.input.executions / .execution.input.batchSize) | split(\".\")[0] | toNumber) | {\"executions\": \"\\($.execution.input.batchSize)\"}])", + "defaultValues": "{\"user\": \"$(.execution.input.user)\", \"password\": \"$(.execution.input.password)\", \"command\": \"$(.execution.input.command)\", \"inputValues\": $(.execution.input.inputValues // {}), \"sensitiveInputValues\": $(.execution.input.sensitiveInputValues // {}), \"inputs\": $(.execution.input.inputs // [])}", + "command": "examples-<<>>:TriggerAndCollectOutputs:1" + }, + "alias": "generateExecutionBatches", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + }, + { + "execute": "examples-<<>>:TriggerAndCollectOutputs:1", + "input": { + "password": "$(.execution.input.password)", + "executions": "$(.execution.input.executions % .execution.input.batchSize)", + "user": "$(.execution.input.user)", + "command": "$(.execution.input.command)", + "inputValues": "$(.execution.input.inputValues)", + "sensitiveInputValues": "$(.execution.input.sensitiveInputValues)" + }, + "alias": "remainderExecutions", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": { + "semantic": "OR", + "conditions": [ + { + "semantic": "OR", + "cases": [ + { + "expression": "$(.execution.input.executions % .execution.input.batchSize)", + "operator": "GREATER_THAN_OR_EQUAL", + "semantic": "OR", + "values": [ + "1" + ] + } + ] + } + ] + }, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:TriggerAndCollectOutputsBatching:1", + "name": "TriggerAndCollectOutputsBatching", + "description": null, + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "password": { + "type": "string", + "sensitive": true, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "executions": { + "type": "number", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": 1, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": "1", + "defaultValueFromInput": null, + "description": null + }, + "inputs": { + "type": "array", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "batchSize": { + "type": "number", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": 1, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": "50", + "defaultValueFromInput": null, + "description": null + }, + "user": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + }, + "command": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": "utils-sapcp:Void:1", + "defaultValueFromInput": null, + "description": null + }, + "inputValues": { + "type": "object", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": "{\"message\": \"Hello\"}", + "defaultValueFromInput": null, + "description": null + }, + "sensitiveInputValues": { + "type": "object", + "sensitive": true, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "outputs": { + "type": "array", + "sensitive": false, + "description": null + } + }, + "tags": { + "feature:logs": "", + "feature:priority": "medium" + } + } + ] +} \ No newline at end of file From 0fe4a55c06b1c33f006952c2e7484df8e6bca399 Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Thu, 4 Jul 2024 08:49:51 +0300 Subject: [PATCH 5/8] Add pretty print xml --- pretty-print-xml/README.md | 25 +++++++++++++ pretty-print-xml/catalog.json | 70 +++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 pretty-print-xml/README.md create mode 100644 pretty-print-xml/catalog.json diff --git a/pretty-print-xml/README.md b/pretty-print-xml/README.md new file mode 100644 index 0000000..35d13f1 --- /dev/null +++ b/pretty-print-xml/README.md @@ -0,0 +1,25 @@ +# Pretty Print XML + +Table of Contents + +* [Description](#description) +* [Requirements](#requirements) +* [How to use](#how-to-use) +* [Expected result](#expected-result) + +## Description + +The command uses a python script to pretty print xml. + +## Requirements + +There are no requirements to use this command. + +## How to use + +1. Trigger the PrettyPrintXml command +2. Enter the XML you want to pretty print in the required input key `xml` + +## Expected result + +The expected result is to receive the pretty printed XML in the `xml` output key. \ No newline at end of file diff --git a/pretty-print-xml/catalog.json b/pretty-print-xml/catalog.json new file mode 100644 index 0000000..a45dd4b --- /dev/null +++ b/pretty-print-xml/catalog.json @@ -0,0 +1,70 @@ +{ + "id": "examples-<<>>", + "technicalName": "examples", + "name": "Automation Pilot Examples", + "description": "Source: https://github.com/SAP-samples/automation-pilot-examples", + "owner": "<<>>", + "inputs": [], + "commands": [ + { + "configuration": { + "values": [], + "output": { + "xml": "$(.prettyPrintXml.output.output | join(\"\\n\"))" + }, + "executors": [ + { + "execute": "scripts-sapcp:ExecuteScript:2", + "input": { + "environment": "{\"XML\":\"$(.execution.input.xml | toEscapedJson)\"}", + "script": "printf \"%s\" \"${XML}\" > data.xml\n\necho 'import xml.dom.minidom\n\ndom = xml.dom.minidom.parse(\"data.xml\")\npretty_xml_as_string = dom.toprettyxml()\nprint(pretty_xml_as_string)\n' > program.py\n\npython3 program.py" + }, + "alias": "prettyPrintXml", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [] + }, + "id": "examples-<<>>:PrettyPrintXml:1", + "name": "PrettyPrintXml", + "description": null, + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "xml": { + "type": "string", + "sensitive": false, + "required": true, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": null, + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "xml": { + "type": "string", + "sensitive": false, + "description": null + } + }, + "tags": {} + } + ] +} \ No newline at end of file From 68d04d2aa22655e8a61aae5332090d24039b155b Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Thu, 4 Jul 2024 09:02:01 +0300 Subject: [PATCH 6/8] Add --- README.md | 1 + pretty-print-xml/catalog.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d679d8e..4b4e1bc 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ After importing, you'll see a new catalog tile - **Automation Pilot Examples**. |---------|-------------| | [Transform Data](transform-data) | Transform Data between different formats - JSON, XML, YAML, and CSV | | [Trigger and Collect Outputs Batching](trigger-and-collect-outputs-batching) | Trigger Multiple Executions in Batches and Collect their Outputs | +| [Pretty Print XML](pretty-print-xml) | Pretty Print XML Data | ## Resources diff --git a/pretty-print-xml/catalog.json b/pretty-print-xml/catalog.json index a45dd4b..c6c669e 100644 --- a/pretty-print-xml/catalog.json +++ b/pretty-print-xml/catalog.json @@ -10,7 +10,7 @@ "configuration": { "values": [], "output": { - "xml": "$(.prettyPrintXml.output.output | join(\"\\n\"))" + "xml": "$(.prettyPrintXml.output.output | filter(length != 0 and . != \"\\t\" and . != \"\\t\\t\") | join(\"\\n\"))" }, "executors": [ { From d1ace55f8ed4ed477d46a549c44902ae09ad1bfa Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Fri, 5 Jul 2024 14:43:34 +0300 Subject: [PATCH 7/8] Add Terraform Example --- terraform-with-btp-provider/README.md | 28 ++++++++ terraform-with-btp-provider/catalog.json | 81 ++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 terraform-with-btp-provider/README.md create mode 100644 terraform-with-btp-provider/catalog.json diff --git a/terraform-with-btp-provider/README.md b/terraform-with-btp-provider/README.md new file mode 100644 index 0000000..22955ba --- /dev/null +++ b/terraform-with-btp-provider/README.md @@ -0,0 +1,28 @@ + + +# Terraform with BTP Provider + +Table of Contents + +* [Description](#description) +* [Requirements](#requirements) +* [How to use](#how-to-use) +* [Expected result](#expected-result) + +## Description + +This examples demonstrates how you can use SAP Automation Pilot sandbox environment with the Execute Script command to install and run terraform with a sample terraform configuration that install the BTP Provider for Terraform. + +## Requirements + +There are no requirements. + +## How to use + +* Import the catalog +* Execute the TerraformWithBTPProvider command +* See the output of the execution + +## Expected result + +The command outputs the terraform installation and the output from the `terraform init` command. diff --git a/terraform-with-btp-provider/catalog.json b/terraform-with-btp-provider/catalog.json new file mode 100644 index 0000000..71dd21f --- /dev/null +++ b/terraform-with-btp-provider/catalog.json @@ -0,0 +1,81 @@ +{ + "id": "examples-<<>>", + "technicalName": "examples", + "name": "Automation Pilot Examples", + "description": "Source: https://github.com/SAP-samples/automation-pilot-examples", + "owner": "<<>>", + "inputs": [], + "commands": [ + { + "configuration": { + "values": [], + "output": { + "output": "$(.terraformInit.output.output | join(\"\\n\"))" + }, + "executors": [ + { + "execute": "scripts-sapcp:ExecuteScript:2", + "input": { + "environment": "{\"MAIN\":\"$(.execution.input.main | toEscapedJson)\"}", + "script": "# Set the Terraform version and URL\nTF_VERSION=\"1.9.1\"\nTF_URL=\"https://releases.hashicorp.com/terraform/${TF_VERSION}/terraform_${TF_VERSION}_linux_amd64.zip\"\n\n# Download Terraform\necho \"Downloading Terraform ${TF_VERSION}\"\ncurl -sSL \"${TF_URL}\" -o /tmp/terraform.zip\n\n# Extract the Terraform binary\necho \"Extracting Terraform binary...\"\nunzip -o /tmp/terraform.zip -d /tmp\n\n# Moving terraform\nmv /tmp/terraform ./terraform\nchmod +x terraform\n\necho \"Terraform ${TF_VERSION} has been installed.\"\n\n# Create Terraform Config Files\necho \"${MAIN}\" > main.tf\n\n# Execute Terraform\n./terraform init" + }, + "alias": "terraformInit", + "description": null, + "progressMessage": null, + "initialDelay": null, + "pause": null, + "when": null, + "validate": null, + "autoRetry": null, + "repeat": null, + "errorMessages": [], + "dryRun": null + } + ], + "listeners": [ + { + "status": "FAILED", + "execute": "utils-sapcp:Void:1", + "input": { + "message": "$(.execution.error)" + }, + "when": null + } + ] + }, + "id": "examples-<<>>:TerraformWithBTPProvider:1", + "name": "TerraformWithBTPProvider", + "description": null, + "catalog": "examples-<<>>", + "version": 1, + "inputKeys": { + "main": { + "type": "string", + "sensitive": false, + "required": false, + "minSize": null, + "maxSize": null, + "minValue": null, + "maxValue": null, + "allowedValues": null, + "allowedValuesFromInputKeys": null, + "suggestedValues": null, + "suggestedValuesFromInputKeys": null, + "defaultValue": "terraform {\n required_providers {\n btp = {\n source = \"sap/btp\"\n }\n }\n}\n\nprovider \"btp\" {\n# You can leave this block empty for now, as we're not configuring any resources yet.\n# The provider will still be installed.\n}", + "defaultValueFromInput": null, + "description": null + } + }, + "outputKeys": { + "output": { + "type": "string", + "sensitive": false, + "description": null + } + }, + "tags": { + "feature:priority": "medium" + } + } + ] +} \ No newline at end of file From 7326bddd05a8f013964484bb2a9f92aad388aa09 Mon Sep 17 00:00:00 2001 From: Aleksandar Aytov Date: Fri, 5 Jul 2024 14:45:45 +0300 Subject: [PATCH 8/8] Update --- README.md | 1 + terraform-with-btp-provider/README.md | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b4e1bc..978a3b4 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ After importing, you'll see a new catalog tile - **Automation Pilot Examples**. | [Use Custom Python Package](use-custom-python-package) | Install and use custom Python package in a script | | [Use Custom NPM Package](use-custom-npm-package) | Install and use custom NPM package in a NodeJS script | | [Use make and helm](use-make-and-helm) | Pull git repo and use make and helm to deploy the helm chart to kubernetes cluster | +| [Terraform with BTP Provider](terraform-with-btp-provider) | Use Terraform with the BTP Provider | ### Automation Pilot diff --git a/terraform-with-btp-provider/README.md b/terraform-with-btp-provider/README.md index 22955ba..de58e45 100644 --- a/terraform-with-btp-provider/README.md +++ b/terraform-with-btp-provider/README.md @@ -1,5 +1,3 @@ - - # Terraform with BTP Provider Table of Contents