feat(10-05): wire batch actions to Container Actions sub-workflow
- Add Prepare Batch Action Input node to format sub-workflow input - Add Execute Batch Action Sub-workflow node calling Container Actions - Add Handle Batch Action Result Sub node to process results - Remove 7 obsolete inline action nodes: * Build Batch Action Command * Execute Batch Container Action * Check Batch Action Result * Needs Action Call * Execute Batch Action 2 * Parse Batch Action 2 * Handle Action Result - Node count: 212 -> 208 (-4 net) This eliminates duplicate action execution logic between single and batch paths.
This commit is contained in:
+80
-201
@@ -3950,120 +3950,6 @@
|
|||||||
-500
|
-500
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"jsCode": "// Get container ID for the action\nconst data = $(\"Build Progress Message\").item.json;\nconst container = data.container;\nconst action = data.action;\n\n// Container might have Id directly or just Name\nconst containerId = container.Id || null;\nconst containerName = container.Name || container;\n\n// Build the curl command for start/stop/restart\nconst timeout = (action === 'stop' || action === 'restart') ? '?t=10' : '';\n\nlet cmd;\nif (containerId) {\n cmd = `curl -s -o /dev/null -w \"%{http_code}\" --max-time 30 -X POST 'http://docker-socket-proxy:2375/v1.47/containers/${containerId}/${action}${timeout}'`;\n} else {\n // Need to find container by name first - use filters\n cmd = `curl -s --max-time 5 'http://docker-socket-proxy:2375/v1.47/containers/json?all=true&filters=%7B%22name%22%3A%5B%22${containerName}%22%5D%7D'`;\n}\n\nreturn {\n json: {\n ...data,\n cmd: cmd,\n needsLookup: !containerId,\n containerId: containerId\n }\n};"
|
|
||||||
},
|
|
||||||
"id": "code-build-batch-action-cmd",
|
|
||||||
"name": "Build Batch Action Command",
|
|
||||||
"type": "n8n-nodes-base.code",
|
|
||||||
"typeVersion": 2,
|
|
||||||
"position": [
|
|
||||||
3980,
|
|
||||||
-400
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"command": "={{ $json.cmd }}",
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"id": "exec-batch-action",
|
|
||||||
"name": "Execute Batch Container Action",
|
|
||||||
"type": "n8n-nodes-base.executeCommand",
|
|
||||||
"typeVersion": 1,
|
|
||||||
"position": [
|
|
||||||
4200,
|
|
||||||
-400
|
|
||||||
],
|
|
||||||
"onError": "continueRegularOutput"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"jsCode": "// Parse action result and check if we need a second call\nconst data = $('Build Batch Action Command').item.json;\nconst stdout = $json.stdout || '';\nconst stderr = $json.stderr || '';\n\nif (data.needsLookup) {\n // First call was a lookup - parse result and make action call\n let containers;\n try {\n containers = JSON.parse(stdout);\n } catch (e) {\n return {\n json: {\n ...data,\n needsAction: false,\n status: 'error',\n reason: 'Container lookup failed'\n }\n };\n }\n \n if (!containers || containers.length === 0) {\n return {\n json: {\n ...data,\n needsAction: false,\n status: 'error',\n reason: 'Container not found'\n }\n };\n }\n \n const containerId = containers[0].Id;\n const action = data.action;\n const timeout = (action === 'stop' || action === 'restart') ? '?t=10' : '';\n const cmd = `curl -s -o /dev/null -w \"%{http_code}\" --max-time 30 -X POST 'http://docker-socket-proxy:2375/v1.47/containers/${containerId}/${action}${timeout}'`;\n \n return {\n json: {\n ...data,\n needsAction: true,\n containerId: containerId,\n cmd: cmd\n }\n };\n}\n\n// Direct action result\nconst statusCode = parseInt(stdout.trim());\nlet status, reason;\n\nif (statusCode === 204) {\n status = 'success';\n reason = null;\n} else if (statusCode === 304) {\n // Already in desired state\n status = 'warning';\n const action = data.action;\n reason = action === 'start' ? 'Already running' : \n action === 'stop' ? 'Already stopped' : 'No change needed';\n} else if (stderr || statusCode >= 400) {\n status = 'error';\n reason = stderr || `HTTP ${statusCode}`;\n} else {\n status = 'error';\n reason = 'Unknown error';\n}\n\nreturn {\n json: {\n ...data,\n needsAction: false,\n status: status,\n reason: reason\n }\n};"
|
|
||||||
},
|
|
||||||
"id": "code-check-batch-action-result",
|
|
||||||
"name": "Check Batch Action Result",
|
|
||||||
"type": "n8n-nodes-base.code",
|
|
||||||
"typeVersion": 2,
|
|
||||||
"position": [
|
|
||||||
4420,
|
|
||||||
-400
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"conditions": {
|
|
||||||
"options": {
|
|
||||||
"caseSensitive": true,
|
|
||||||
"leftValue": "",
|
|
||||||
"typeValidation": "strict"
|
|
||||||
},
|
|
||||||
"conditions": [
|
|
||||||
{
|
|
||||||
"id": "needs-action",
|
|
||||||
"leftValue": "={{ $json.needsAction }}",
|
|
||||||
"rightValue": true,
|
|
||||||
"operator": {
|
|
||||||
"type": "boolean",
|
|
||||||
"operation": "equals"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"combinator": "and"
|
|
||||||
},
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"id": "if-needs-batch-action",
|
|
||||||
"name": "Needs Action Call",
|
|
||||||
"type": "n8n-nodes-base.if",
|
|
||||||
"typeVersion": 2,
|
|
||||||
"position": [
|
|
||||||
4640,
|
|
||||||
-400
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"command": "={{ $json.cmd }}",
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
"id": "exec-batch-action-2",
|
|
||||||
"name": "Execute Batch Action 2",
|
|
||||||
"type": "n8n-nodes-base.executeCommand",
|
|
||||||
"typeVersion": 1,
|
|
||||||
"position": [
|
|
||||||
4860,
|
|
||||||
-500
|
|
||||||
],
|
|
||||||
"onError": "continueRegularOutput"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"jsCode": "// Parse the final action result\nconst data = $('Check Batch Action Result').item.json;\nconst stdout = $json.stdout || '';\nconst stderr = $json.stderr || '';\n\nconst statusCode = parseInt(stdout.trim());\nlet status, reason;\n\nif (statusCode === 204) {\n status = 'success';\n reason = null;\n} else if (statusCode === 304) {\n status = 'warning';\n const action = data.action;\n reason = action === 'start' ? 'Already running' : \n action === 'stop' ? 'Already stopped' : 'No change needed';\n} else if (stderr || statusCode >= 400) {\n status = 'error';\n reason = stderr || `HTTP ${statusCode}`;\n} else {\n status = 'error';\n reason = 'Unknown error';\n}\n\nreturn {\n json: {\n ...data,\n status: status,\n reason: reason\n }\n};"
|
|
||||||
},
|
|
||||||
"id": "code-parse-batch-action-2",
|
|
||||||
"name": "Parse Batch Action 2",
|
|
||||||
"type": "n8n-nodes-base.code",
|
|
||||||
"typeVersion": 2,
|
|
||||||
"position": [
|
|
||||||
5080,
|
|
||||||
-500
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"parameters": {
|
|
||||||
"jsCode": "// Merge both paths and update running totals\n// This node receives from either direct result or second action call\nconst data = $json;\n\nconst status = data.status;\nconst containerName = data.containerName;\nconst reason = data.reason;\nconst containerIndex = data.containerIndex;\n\n// Get previous results from workflow context or start fresh\nlet results = data.results || [];\nlet successCount = data.successCount || 0;\nlet failureCount = data.failureCount || 0;\nlet warningCount = data.warningCount || 0;\n\n// Add current result\nresults.push({\n name: containerName,\n status: status,\n reason: reason\n});\n\n// Update counters\nif (status === 'success') {\n successCount++;\n} else if (status === 'error') {\n failureCount++;\n} else if (status === 'warning') {\n warningCount++;\n}\n\nreturn {\n json: {\n ...data,\n results: results,\n successCount: successCount,\n failureCount: failureCount,\n warningCount: warningCount\n }\n};"
|
|
||||||
},
|
|
||||||
"id": "code-handle-batch-result",
|
|
||||||
"name": "Handle Action Result",
|
|
||||||
"type": "n8n-nodes-base.code",
|
|
||||||
"typeVersion": 2,
|
|
||||||
"position": [
|
|
||||||
5300,
|
|
||||||
-400
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"jsCode": "// Prepare data for next iteration or completion\nconst data = $json;\n\n// Check if more containers to process\nconst currentIndex = data.currentIndex;\nconst totalCount = data.totalCount;\nconst containers = data.containers;\nconst nextIndex = currentIndex + 1;\nconst isComplete = nextIndex >= totalCount;\n\nreturn {\n json: {\n ...data,\n currentIndex: nextIndex,\n container: isComplete ? null : containers[nextIndex],\n isComplete: isComplete\n }\n};"
|
"jsCode": "// Prepare data for next iteration or completion\nconst data = $json;\n\n// Check if more containers to process\nconst currentIndex = data.currentIndex;\nconst totalCount = data.totalCount;\nconst containers = data.containers;\nconst nextIndex = currentIndex + 1;\nconst isComplete = nextIndex >= totalCount;\n\nreturn {\n json: {\n ...data,\n currentIndex: nextIndex,\n container: isComplete ? null : containers[nextIndex],\n isComplete: isComplete\n }\n};"
|
||||||
@@ -5238,6 +5124,50 @@
|
|||||||
4440,
|
4440,
|
||||||
-800
|
-800
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"jsCode": "// Prepare input for Container Actions sub-workflow\nconst data = $json;\nconst container = data.container;\nconst action = data.action;\n\n// Extract container info\nconst containerId = container.id || container.Id || '';\nconst containerName = container.name || container.Name || '';\n\nreturn {\n json: {\n containerId: containerId,\n containerName: containerName,\n action: action,\n chatId: data.chatId,\n messageId: data.progressMessageId || 0,\n responseMode: \"inline\"\n }\n};"
|
||||||
|
},
|
||||||
|
"id": "958f19ef-249b-42ca-8a29-ecb91548f1dd",
|
||||||
|
"name": "Prepare Batch Action Input",
|
||||||
|
"type": "n8n-nodes-base.code",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [
|
||||||
|
4000,
|
||||||
|
-200
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"workflowId": {
|
||||||
|
"__rl": true,
|
||||||
|
"mode": "list",
|
||||||
|
"value": "fYSZS5PkH0VSEaT5"
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"id": "3baebdc9-3cda-478a-b0cc-0fb33a542f03",
|
||||||
|
"name": "Execute Batch Action Sub-workflow",
|
||||||
|
"type": "n8n-nodes-base.executeWorkflow",
|
||||||
|
"typeVersion": 1.2,
|
||||||
|
"position": [
|
||||||
|
4220,
|
||||||
|
-200
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"jsCode": "// Handle action result from sub-workflow\nconst data = $('Build Progress Message').item.json;\nconst result = $json;\n\n// Update counters based on result\nlet successCount = data.successCount || 0;\nlet failureCount = data.failureCount || 0;\nlet warningCount = data.warningCount || 0;\n\nif (result.success) {\n successCount++;\n} else {\n failureCount++;\n}\n\n// Add to results array\nconst results = data.results || [];\nresults.push({\n container: data.containerName,\n action: data.action,\n success: result.success,\n message: result.message || ''\n});\n\nreturn {\n json: {\n ...data,\n successCount: successCount,\n failureCount: failureCount,\n warningCount: warningCount,\n results: results\n }\n};"
|
||||||
|
},
|
||||||
|
"id": "dc8db8cb-3ba8-471d-98df-c47dcdb4e6ea",
|
||||||
|
"name": "Handle Batch Action Result Sub",
|
||||||
|
"type": "n8n-nodes-base.code",
|
||||||
|
"typeVersion": 2,
|
||||||
|
"position": [
|
||||||
|
4440,
|
||||||
|
-200
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"connections": {
|
"connections": {
|
||||||
@@ -6804,105 +6734,21 @@
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"node": "Build Batch Action Command",
|
"node": "Prepare Batch Action Input",
|
||||||
"type": "main",
|
"type": "main",
|
||||||
"index": 0
|
"index": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"node": "Build Batch Action Command",
|
"node": "Prepare Batch Action Input",
|
||||||
"type": "main",
|
"type": "main",
|
||||||
"index": 0
|
"index": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"node": "Build Batch Action Command",
|
"node": "Prepare Batch Action Input",
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Build Batch Action Command": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Execute Batch Container Action",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Execute Batch Container Action": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Check Batch Action Result",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Check Batch Action Result": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Needs Action Call",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Needs Action Call": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Execute Batch Action 2",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Handle Action Result",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Execute Batch Action 2": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Parse Batch Action 2",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Parse Batch Action 2": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Handle Action Result",
|
|
||||||
"type": "main",
|
|
||||||
"index": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Handle Action Result": {
|
|
||||||
"main": [
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"node": "Prepare Next Iteration",
|
|
||||||
"type": "main",
|
"type": "main",
|
||||||
"index": 0
|
"index": 0
|
||||||
}
|
}
|
||||||
@@ -7531,6 +7377,39 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"Prepare Batch Action Input": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Execute Batch Action Sub-workflow",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Execute Batch Action Sub-workflow": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Handle Batch Action Result Sub",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Handle Batch Action Result Sub": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Prepare Next Iteration",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pinData": {},
|
"pinData": {},
|
||||||
|
|||||||
Reference in New Issue
Block a user