feat(10-05): extract logs flow to Container Logs sub-workflow
Created n8n-container-logs.json: - Execute Workflow Trigger entry point - Parse and validate input (containerId/Name, lineCount, chatId, messageId) - Query Docker to find container by name if needed - Execute docker logs command - Format output for Telegram (HTML escape, truncate, add header) - Return success/message/containerName/lineCount Updated main workflow: - Add Prepare Text Logs Input (text command path) - Add Execute Text Logs sub-workflow node - Add Prepare Inline Logs Input (inline keyboard path) - Add Execute Inline Logs sub-workflow node - Add Format Inline Logs Result (adds keyboard) - Remove 14 obsolete inline logs nodes - Node count: 208 -> 199 (-9) Sub-workflow has placeholder ID - will be updated after n8n import in Task 4.
This commit is contained in:
+133
-458
@@ -1900,184 +1900,12 @@
|
||||
600
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"command": "curl -s --max-time 5 'http://docker-socket-proxy:2375/v1.47/containers/json?all=true'",
|
||||
"options": {}
|
||||
},
|
||||
"id": "exec-docker-list-logs",
|
||||
"name": "Docker List for Logs",
|
||||
"type": "n8n-nodes-base.executeCommand",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
1120,
|
||||
600
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Get Docker API response and logs info from Parse Logs\nconst dockerOutput = $input.item.json.stdout;\nconst logsData = $('Parse Logs Command').item.json;\nconst containerQuery = logsData.containerQuery;\nconst lines = logsData.lines;\nconst chatId = logsData.chatId;\n\n// Parse JSON response\nlet containers;\ntry {\n if (!dockerOutput || dockerOutput.trim() === '') {\n throw new Error('Empty response');\n }\n containers = JSON.parse(dockerOutput);\n} catch (e) {\n return [{\n json: {\n matchCount: -1,\n error: true,\n chatId: chatId,\n text: \"Cannot connect to Docker\"\n }\n }];\n}\n\n// Function to normalize container names\nfunction normalizeName(name) {\n return name\n .replace(/^\\//, '') // Remove leading slash\n .replace(/^(linuxserver[-_]|binhex[-_])/i, '') // Remove common prefixes\n .toLowerCase();\n}\n\nconst normalized = containerQuery.toLowerCase();\n\n// First check for exact match\nconst exactMatch = containers.find(c => normalizeName(c.Names[0]) === normalized);\nif (exactMatch) {\n return [{\n json: {\n matches: [{ Id: exactMatch.Id, Name: exactMatch.Names[0].replace(/^\\//, ''), State: exactMatch.State }],\n matchCount: 1,\n containerQuery: containerQuery,\n lines: lines,\n chatId: chatId\n }\n }];\n}\n\n// Fall back to substring matching (container name contains query)\nconst matches = containers.filter(c => {\n const containerName = normalizeName(c.Names[0]);\n return containerName.includes(normalized);\n});\n\n// Return match results with all necessary context\nreturn [{\n json: {\n matches: matches.map(c => ({\n Id: c.Id,\n Name: c.Names[0].replace(/^\\//, ''),\n State: c.State\n })),\n matchCount: matches.length,\n containerQuery: containerQuery,\n lines: lines,\n chatId: chatId\n }\n}];"
|
||||
},
|
||||
"id": "code-match-logs-container",
|
||||
"name": "Match Logs Container",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1340,
|
||||
600
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"rules": {
|
||||
"values": [
|
||||
{
|
||||
"id": "logs-docker-error",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "loose"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "count-negative",
|
||||
"leftValue": "={{ $json.matchCount }}",
|
||||
"rightValue": 0,
|
||||
"operator": {
|
||||
"type": "number",
|
||||
"operation": "lt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": false
|
||||
},
|
||||
{
|
||||
"id": "logs-no-match",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "loose"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "count-zero",
|
||||
"leftValue": "={{ $json.matchCount }}",
|
||||
"rightValue": 0,
|
||||
"operator": {
|
||||
"type": "number",
|
||||
"operation": "equals"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": false
|
||||
},
|
||||
{
|
||||
"id": "logs-single-match",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "loose"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "count-one",
|
||||
"leftValue": "={{ $json.matchCount }}",
|
||||
"rightValue": 1,
|
||||
"operator": {
|
||||
"type": "number",
|
||||
"operation": "equals"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": false
|
||||
},
|
||||
{
|
||||
"id": "logs-multiple-matches",
|
||||
"conditions": {
|
||||
"options": {
|
||||
"caseSensitive": true,
|
||||
"typeValidation": "loose"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"id": "count-many",
|
||||
"leftValue": "={{ $json.matchCount }}",
|
||||
"rightValue": 1,
|
||||
"operator": {
|
||||
"type": "number",
|
||||
"operation": "gt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"combinator": "and"
|
||||
},
|
||||
"renameOutput": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "switch-logs-match-count",
|
||||
"name": "Check Logs Match Count",
|
||||
"type": "n8n-nodes-base.switch",
|
||||
"typeVersion": 3.2,
|
||||
"position": [
|
||||
1560,
|
||||
600
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Build Docker logs API curl command\nconst matchData = $input.item.json;\nconst container = matchData.matches[0]; // Single match verified by switch\nconst lines = matchData.lines;\n\nconst cmd = `curl -s --max-time 5 \"http://docker-socket-proxy:2375/v1.47/containers/${container.Id}/logs?stdout=1&stderr=1&tail=${lines}×tamps=1\"`;\n\nreturn {\n json: {\n command: cmd,\n containerName: container.Name,\n containerId: container.Id,\n lines: lines,\n chatId: matchData.chatId\n }\n};"
|
||||
},
|
||||
"id": "code-build-logs-cmd",
|
||||
"name": "Build Logs Command",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1780,
|
||||
500
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"command": "={{ $json.command }}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "exec-logs",
|
||||
"name": "Execute Logs",
|
||||
"type": "n8n-nodes-base.executeCommand",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
2000,
|
||||
500
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Format Docker logs for Telegram\nconst rawOutput = $input.item.json.stdout || '';\nconst containerName = $('Build Logs Command').item.json.containerName;\nconst requestedLines = $('Build Logs Command').item.json.lines;\nconst chatId = $('Build Logs Command').item.json.chatId;\n\n// HTML escape function for log content\nfunction escapeHtml(text) {\n return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\n// Handle empty logs\nif (!rawOutput || rawOutput.trim() === '') {\n return {\n json: {\n chatId: chatId,\n text: `No logs available for <b>${containerName}</b>`\n }\n };\n}\n\n// Docker API with timestamps returns text lines when using tail parameter\n// But may have 8-byte binary headers we need to strip\nconst lines = rawOutput.split('\\n')\n .filter(line => line.length > 0)\n .map(line => {\n // Check if line starts with binary header (non-printable chars in first 8 bytes)\n if (line.length > 8 && line.charCodeAt(0) <= 2) {\n return line.substring(8);\n }\n return line;\n })\n .join('\\n');\n\n// Truncate for Telegram (4096 char limit, leave room for header)\nconst maxLen = 3800;\nconst truncated = lines.length > maxLen\n ? lines.substring(0, maxLen) + '\\n... (truncated)'\n : lines;\n\n// Escape HTML entities in log content to prevent parse errors\nconst escaped = escapeHtml(truncated);\n\nconst lineCount = lines.split('\\n').length;\nconst header = `Logs for <b>${containerName}</b> (last ${lineCount} lines):\\n\\n`;\n\nreturn {\n json: {\n chatId: chatId,\n text: header + '<pre>' + escaped + '</pre>'\n }\n};"
|
||||
},
|
||||
"id": "code-format-logs",
|
||||
"name": "Format Logs",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
2220,
|
||||
500
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "message",
|
||||
"operation": "sendMessage",
|
||||
"chatId": "={{ $json.chatId }}",
|
||||
"text": "={{ $json.text }}",
|
||||
"text": "={{ $json.message }}",
|
||||
"additionalFields": {
|
||||
"parse_mode": "HTML"
|
||||
}
|
||||
@@ -2097,57 +1925,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "message",
|
||||
"operation": "sendMessage",
|
||||
"chatId": "={{ $json.chatId }}",
|
||||
"text": "={{ $json.text || 'Error retrieving logs' }}",
|
||||
"additionalFields": {
|
||||
"parse_mode": "HTML"
|
||||
}
|
||||
},
|
||||
"id": "telegram-send-logs-error",
|
||||
"name": "Send Logs Error",
|
||||
"type": "n8n-nodes-base.telegram",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
1780,
|
||||
700
|
||||
],
|
||||
"credentials": {
|
||||
"telegramApi": {
|
||||
"id": "I0xTTiASl7C1NZhJ",
|
||||
"name": "Telegram account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const data = $input.item.json;\nreturn {\n json: {\n chatId: data.chatId,\n text: `No container found matching \"<b>${data.containerQuery}</b>\".\\n\\nTry \"status\" to see all containers.`\n }\n};"
|
||||
},
|
||||
"id": "code-format-logs-no-match",
|
||||
"name": "Format Logs No Match",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1780,
|
||||
650
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const data = $input.item.json;\nconst names = data.matches.map(m => m.Name).join('\\n- ');\nreturn {\n json: {\n chatId: data.chatId,\n text: `Found ${data.matches.length} containers matching \"<b>${data.containerQuery}</b>\":\\n\\n- ${names}\\n\\nPlease be more specific.`\n }\n};"
|
||||
},
|
||||
"id": "code-format-logs-multiple",
|
||||
"name": "Format Logs Multiple",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1780,
|
||||
600
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "message",
|
||||
@@ -2731,74 +2508,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Prepare logs action\nconst data = $('Parse Callback Data').item.json;\nreturn {\n json: {\n containerName: data.containerName,\n chatId: data.chatId,\n messageId: data.messageId,\n lines: 30\n }\n};"
|
||||
},
|
||||
"id": "code-prepare-logs-action",
|
||||
"name": "Prepare Logs Action",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1780,
|
||||
1300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "GET",
|
||||
"url": "=http://docker-socket-proxy:2375/containers/json?all=true",
|
||||
"options": {}
|
||||
},
|
||||
"id": "http-get-container-for-logs",
|
||||
"name": "Get Container For Logs",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.2,
|
||||
"position": [
|
||||
2000,
|
||||
1300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Find container and build logs command\nconst containers = $input.all().map(item => item.json);\nconst prevData = $('Prepare Logs Action').item.json;\nconst containerName = prevData.containerName.toLowerCase();\nconst lines = prevData.lines;\nconst chatId = prevData.chatId;\nconst messageId = prevData.messageId;\n\n// Function to normalize container names\nfunction normalizeName(name) {\n return name\n .replace(/^\\//, '')\n .replace(/^(linuxserver[-_]|binhex[-_])/i, '')\n .toLowerCase();\n}\n\n// Find the matching container\nconst container = containers.find(c => normalizeName(c.Names[0]) === containerName);\n\nif (!container) {\n return {\n json: {\n error: true,\n chatId,\n messageId,\n text: `Container \"${containerName}\" not found`\n }\n };\n}\n\nconst containerId = container.Id;\n\nreturn {\n json: {\n cmd: `curl -s --max-time 10 'http://docker-socket-proxy:2375/v1.47/containers/${containerId}/logs?stdout=true&stderr=true&tail=${lines}'`,\n containerId,\n containerName: normalizeName(container.Names[0]),\n containerState: container.State,\n lines,\n chatId,\n messageId\n }\n};"
|
||||
},
|
||||
"id": "code-build-logs-action-cmd",
|
||||
"name": "Build Logs Action Command",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
2220,
|
||||
1300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"command": "={{ $json.cmd }}",
|
||||
"options": {}
|
||||
},
|
||||
"id": "exec-logs-action",
|
||||
"name": "Execute Logs Action",
|
||||
"type": "n8n-nodes-base.executeCommand",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
2440,
|
||||
1300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Parse and format logs output\nconst stdout = $input.item.json.stdout || '';\nconst prevData = $('Build Logs Action Command').item.json;\nconst containerName = prevData.containerName;\nconst containerState = prevData.containerState;\nconst lines = prevData.lines;\nconst chatId = prevData.chatId;\nconst messageId = prevData.messageId;\n\n// Docker logs API returns binary stream with 8-byte header per line\n// Strip non-printable characters and clean up\nlet logs = stdout\n .split('\\n')\n .map(line => {\n // Remove Docker stream header (first 8 bytes of each frame)\n // The header contains stream type and length info\n if (line.length > 8) {\n const cleaned = line.substring(8).replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n return cleaned;\n }\n return line.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F]/g, '');\n })\n .filter(line => line.trim().length > 0)\n .slice(-lines)\n .join('\\n');\n\nif (!logs || logs.trim().length === 0) {\n logs = '(no recent logs)';\n}\n\n// Truncate if too long for Telegram (max ~4096 chars)\nif (logs.length > 3800) {\n logs = '...' + logs.slice(-3800);\n}\n\n// Build keyboard for navigation\nconst keyboard = [];\nif (containerState === 'running') {\n keyboard.push([\n { text: '\\u23F9\\uFE0F Stop', callback_data: `action:stop:${containerName}` },\n { text: '\\u{1F504} Restart', callback_data: `action:restart:${containerName}` }\n ]);\n} else {\n keyboard.push([\n { text: '\\u25B6\\uFE0F Start', callback_data: `action:start:${containerName}` }\n ]);\n}\n\nkeyboard.push([\n { text: '\\u{1F4CB} Refresh Logs', callback_data: `action:logs:${containerName}` },\n { text: '\\u2B06\\uFE0F Update', callback_data: `action:update:${containerName}` }\n]);\n\nkeyboard.push([\n { text: '\\u25C0\\uFE0F Back to List', callback_data: 'list:0' }\n]);\n\nconst stateIcon = containerState === 'running' ? '\\u{1F7E2}' : '\\u26AA';\nconst timestamp = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit' });\nlet text = `${stateIcon} <b>${containerName}</b> - Logs <i>(${timestamp})</i>\\n\\n<pre>${logs}</pre>`;\n\nreturn {\n json: {\n chatId,\n messageId,\n text,\n reply_markup: { inline_keyboard: keyboard }\n }\n};"
|
||||
},
|
||||
"id": "code-format-logs-action-result",
|
||||
"name": "Format Logs Action Result",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
2660,
|
||||
1300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"method": "POST",
|
||||
@@ -5168,6 +4877,81 @@
|
||||
4440,
|
||||
-200
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Prepare input for Container Logs sub-workflow (text command)\nconst data = $json;\n\n// Check if there's an error from Parse Logs Command\nif (data.error) {\n return {\n json: {\n error: true,\n chatId: data.chatId,\n text: data.text\n }\n };\n}\n\nreturn {\n json: {\n containerName: data.containerQuery,\n lineCount: data.lines,\n chatId: data.chatId,\n messageId: data.messageId || 0,\n responseMode: \"text\"\n }\n};"
|
||||
},
|
||||
"id": "a895bb2d-1f61-4466-b475-b32ec5f0e83a",
|
||||
"name": "Prepare Text Logs Input",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1120,
|
||||
600
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"workflowId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "PLACEHOLDER_LOGS_ID"
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "926c7683-c0e4-41a4-a983-e3f7ecb6ff41",
|
||||
"name": "Execute Text Logs",
|
||||
"type": "n8n-nodes-base.executeWorkflow",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
1340,
|
||||
600
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Prepare input for Container Logs sub-workflow (inline action)\nconst data = $('Parse Callback Data').item.json;\n\nreturn {\n json: {\n containerName: data.containerName,\n lineCount: 30,\n chatId: data.chatId,\n messageId: data.messageId,\n responseMode: \"inline\"\n }\n};"
|
||||
},
|
||||
"id": "16b24086-5b5d-4980-82c7-4fb37b4e8f6c",
|
||||
"name": "Prepare Inline Logs Input",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1780,
|
||||
1300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"workflowId": {
|
||||
"__rl": true,
|
||||
"mode": "list",
|
||||
"value": "PLACEHOLDER_LOGS_ID"
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "a88974bd-45c0-401e-b50a-c6171cfe06d4",
|
||||
"name": "Execute Inline Logs",
|
||||
"type": "n8n-nodes-base.executeWorkflow",
|
||||
"typeVersion": 1.2,
|
||||
"position": [
|
||||
2000,
|
||||
1300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "// Format logs result for inline keyboard display\nconst result = $json;\nconst data = $('Prepare Inline Logs Input').item.json;\n\n// Get container state (need to fetch from Docker)\n// For now, build basic keyboard\nconst containerName = result.containerName;\n\n// Build inline keyboard\nconst keyboard = [\n [\n { text: '\ud83d\udd04 Refresh Logs', callback_data: `action:logs:${containerName}` },\n { text: '\u2b06\ufe0f Update', callback_data: `action:update:${containerName}` }\n ],\n [\n { text: '\u25c0\ufe0f Back to List', callback_data: 'list:0' }\n ]\n];\n\nreturn {\n json: {\n chatId: data.chatId,\n messageId: data.messageId,\n text: result.message,\n reply_markup: { inline_keyboard: keyboard }\n }\n};"
|
||||
},
|
||||
"id": "b1800598-1ff6-4da3-8506-4e4e8127f902",
|
||||
"name": "Format Inline Logs Result",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
2220,
|
||||
1300
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
@@ -5914,116 +5698,7 @@
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Docker List for Logs",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Docker List for Logs": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Match Logs Container",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Match Logs Container": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Check Logs Match Count",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Check Logs Match Count": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Logs Error",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Format Logs No Match",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Build Logs Command",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Format Logs Multiple",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Build Logs Command": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Execute Logs",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Execute Logs": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Format Logs",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Format Logs": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Logs Response",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Format Logs No Match": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Logs Error",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Format Logs Multiple": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Logs Error",
|
||||
"node": "Prepare Text Logs Input",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
@@ -6372,7 +6047,7 @@
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Prepare Logs Action",
|
||||
"node": "Prepare Inline Logs Input",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
@@ -6434,61 +6109,6 @@
|
||||
]
|
||||
]
|
||||
},
|
||||
"Prepare Logs Action": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Container For Logs",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Container For Logs": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Build Logs Action Command",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Build Logs Action Command": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Execute Logs Action",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Execute Logs Action": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Format Logs Action Result",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Format Logs Action Result": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Logs Result",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Build Stop Confirmation": {
|
||||
"main": [
|
||||
[
|
||||
@@ -7410,6 +7030,61 @@
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Prepare Text Logs Input": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Execute Text Logs",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Execute Text Logs": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Logs Response",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Prepare Inline Logs Input": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Execute Inline Logs",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Execute Inline Logs": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Format Inline Logs Result",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Format Inline Logs Result": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Send Logs Result",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"pinData": {},
|
||||
|
||||
Reference in New Issue
Block a user