From 35705a77071d48e6f3871019efb84f158a8d5040 Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Wed, 4 Feb 2026 13:06:38 -0500 Subject: [PATCH] feat(10-03): create container actions sub-workflow - Add n8n-container-actions.json with executeWorkflowTrigger - Input contract: containerId, containerName, action, chatId, messageId, responseMode - Routes to start/stop/restart via Switch node - Returns: success, message, action, containerName for caller to handle response --- n8n-container-actions.json | 303 +++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 n8n-container-actions.json diff --git a/n8n-container-actions.json b/n8n-container-actions.json new file mode 100644 index 0000000..e125e34 --- /dev/null +++ b/n8n-container-actions.json @@ -0,0 +1,303 @@ +{ + "name": "Container Actions", + "nodes": [ + { + "parameters": { + "inputSource": "passthrough", + "schema": { + "schemaType": "fromFields", + "inputFieldName": "", + "fields": [ + { + "fieldName": "containerId", + "fieldType": "string" + }, + { + "fieldName": "containerName", + "fieldType": "string" + }, + { + "fieldName": "action", + "fieldType": "string" + }, + { + "fieldName": "chatId", + "fieldType": "number" + }, + { + "fieldName": "messageId", + "fieldType": "number" + }, + { + "fieldName": "responseMode", + "fieldType": "string" + } + ] + } + }, + "id": "trigger-sub-workflow", + "name": "When executed by another workflow", + "type": "n8n-nodes-base.executeWorkflowTrigger", + "typeVersion": 1.1, + "position": [ + 240, + 300 + ] + }, + { + "parameters": { + "rules": { + "values": [ + { + "id": "route-start", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-start", + "leftValue": "={{ $json.action }}", + "rightValue": "start", + "operator": { + "type": "string", + "operation": "equals" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "start" + }, + { + "id": "route-stop", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-stop", + "leftValue": "={{ $json.action }}", + "rightValue": "stop", + "operator": { + "type": "string", + "operation": "equals" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "stop" + }, + { + "id": "route-restart", + "conditions": { + "options": { + "caseSensitive": true, + "typeValidation": "loose" + }, + "conditions": [ + { + "id": "is-restart", + "leftValue": "={{ $json.action }}", + "rightValue": "restart", + "operator": { + "type": "string", + "operation": "equals" + } + } + ], + "combinator": "and" + }, + "renameOutput": true, + "outputKey": "restart" + } + ] + }, + "options": { + "fallbackOutput": "none" + } + }, + "id": "switch-action-type", + "name": "Route Action", + "type": "n8n-nodes-base.switch", + "typeVersion": 3.2, + "position": [ + 460, + 300 + ] + }, + { + "parameters": { + "method": "POST", + "url": "=http://docker-socket-proxy:2375/v1.47/containers/{{ $json.containerId }}/start", + "options": { + "timeout": 15000 + } + }, + "id": "http-start-container", + "name": "Start Container", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 680, + 200 + ], + "onError": "continueRegularOutput" + }, + { + "parameters": { + "method": "POST", + "url": "=http://docker-socket-proxy:2375/v1.47/containers/{{ $json.containerId }}/stop?t=10", + "options": { + "timeout": 15000 + } + }, + "id": "http-stop-container", + "name": "Stop Container", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 680, + 300 + ], + "onError": "continueRegularOutput" + }, + { + "parameters": { + "method": "POST", + "url": "=http://docker-socket-proxy:2375/v1.47/containers/{{ $json.containerId }}/restart?t=10", + "options": { + "timeout": 15000 + } + }, + "id": "http-restart-container", + "name": "Restart Container", + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.2, + "position": [ + 680, + 400 + ], + "onError": "continueRegularOutput" + }, + { + "parameters": { + "jsCode": "// Format start action result\nconst triggerData = $('When executed by another workflow').item.json;\nconst containerId = triggerData.containerId;\nconst containerName = triggerData.containerName;\nconst action = triggerData.action;\nconst chatId = triggerData.chatId;\nconst messageId = triggerData.messageId;\nconst responseMode = triggerData.responseMode;\n\n// Check response status\nconst responseCode = $input.item.json?.statusCode || $input.item.json?.$response?.statusCode || 0;\nconst hasError = $input.item.json?.error || false;\n\n// 204: Success, 304: Already in state (also success for user)\nconst success = !hasError && (responseCode === 204 || responseCode === 304);\n\nlet message;\nif (success) {\n message = `\\u25B6\\uFE0F ${containerName} started successfully`;\n} else {\n message = `\\u274C Failed to start ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" + }, + "id": "code-format-start-result", + "name": "Format Start Result", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 900, + 200 + ] + }, + { + "parameters": { + "jsCode": "// Format stop action result\nconst triggerData = $('When executed by another workflow').item.json;\nconst containerId = triggerData.containerId;\nconst containerName = triggerData.containerName;\nconst action = triggerData.action;\nconst chatId = triggerData.chatId;\nconst messageId = triggerData.messageId;\nconst responseMode = triggerData.responseMode;\n\n// Check response status\nconst responseCode = $input.item.json?.statusCode || $input.item.json?.$response?.statusCode || 0;\nconst hasError = $input.item.json?.error || false;\n\n// 204: Success, 304: Already stopped\nconst success = !hasError && (responseCode === 204 || responseCode === 304);\n\nlet message;\nif (success) {\n message = `\\u23F9\\uFE0F ${containerName} stopped`;\n} else {\n message = `\\u274C Failed to stop ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" + }, + "id": "code-format-stop-result", + "name": "Format Stop Result", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 900, + 300 + ] + }, + { + "parameters": { + "jsCode": "// Format restart action result\nconst triggerData = $('When executed by another workflow').item.json;\nconst containerId = triggerData.containerId;\nconst containerName = triggerData.containerName;\nconst action = triggerData.action;\nconst chatId = triggerData.chatId;\nconst messageId = triggerData.messageId;\nconst responseMode = triggerData.responseMode;\n\n// Check response status\nconst responseCode = $input.item.json?.statusCode || $input.item.json?.$response?.statusCode || 0;\nconst hasError = $input.item.json?.error || false;\n\n// 204: Success, 304: No change needed\nconst success = !hasError && (responseCode === 204 || responseCode === 304);\n\nlet message;\nif (success) {\n message = `\\u{1F504} ${containerName} restarted`;\n} else {\n message = `\\u274C Failed to restart ${containerName}`;\n}\n\nreturn {\n json: {\n success,\n message,\n action,\n containerName,\n containerId,\n chatId,\n messageId,\n responseMode\n }\n};" + }, + "id": "code-format-restart-result", + "name": "Format Restart Result", + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 900, + 400 + ] + } + ], + "connections": { + "When executed by another workflow": { + "main": [ + [ + { + "node": "Route Action", + "type": "main", + "index": 0 + } + ] + ] + }, + "Route Action": { + "main": [ + [ + { + "node": "Start Container", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Stop Container", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Restart Container", + "type": "main", + "index": 0 + } + ] + ] + }, + "Start Container": { + "main": [ + [ + { + "node": "Format Start Result", + "type": "main", + "index": 0 + } + ] + ] + }, + "Stop Container": { + "main": [ + [ + { + "node": "Format Stop Result", + "type": "main", + "index": 0 + } + ] + ] + }, + "Restart Container": { + "main": [ + [ + { + "node": "Format Restart Result", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "settings": { + "executionOrder": "v1" + } +}