使用Robot Framework、ArgoCD和完整KinD生命周期实现自动化Kubernetes测试
高级
这是一个DevOps领域的自动化工作流,包含 73 个节点。主要使用 If, Set, Gitlab, Switch, Webhook 等节点。 基于 Robot Framework、ArgoCD 和完整 KinD 生命周期的自动化 Kubernetes 测试
前置要求
- •GitLab Personal Access Token
- •HTTP Webhook 端点(n8n 会自动生成)
- •Telegram Bot Token
使用的节点 (73)
分类
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "gxs56vcXTIHjKDlf",
"meta": {
"instanceId": "5c7ce220523e8664f49208a8be668a8dc6fab5f747ce4de865fa1309727919f1",
"templateCredsSetupCompleted": true
},
"name": "使用Robot Framework、ArgoCD和完整KinD生命周期实现自动化Kubernetes测试",
"tags": [],
"nodes": [
{
"id": "3eedbba8-b070-4f4c-b752-f997880ac0f7",
"name": "当点击\"执行工作流\"时",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-352,
480
],
"parameters": {},
"typeVersion": 1
},
{
"id": "606d3f93-213c-46ca-aa68-fcd50a42f0ca",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-352,
336
],
"webhookId": "9cd9d4e9-79cb-4430-8b7b-c9d8843d4499",
"parameters": {
"path": "gitlab-commit",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 2.1
},
{
"id": "4095dc2e-75df-4f26-8ff6-c2c20691706e",
"name": "计划触发器",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-352,
192
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 1
}
]
}
},
"typeVersion": 1.2
},
{
"id": "caab1bc5-d6dc-4634-bf40-08f893075842",
"name": "获取文件 - ROBOT脚本",
"type": "n8n-nodes-base.gitlab",
"position": [
560,
352
],
"parameters": {
"owner": "n8n",
"filePath": "={{ $('Set Parameters').item.json.ROBOT_SCRIPT }}",
"resource": "file",
"operation": "get",
"repository": "testing",
"authentication": "oAuth2",
"binaryPropertyName": "process_it.robot",
"additionalParameters": {
"reference": "main"
}
},
"credentials": {
"gitlabOAuth2Api": {
"id": "Uvbl0nXUj63Ldscx",
"name": "GitLab account"
}
},
"typeVersion": 1
},
{
"id": "3b88f0a7-f384-4ad2-bdd4-0aefce909042",
"name": "设置参数",
"type": "n8n-nodes-base.set",
"position": [
0,
336
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "0339db45-ae7f-461c-b89c-bb5c31b47178",
"name": "target_host",
"type": "string",
"value": "target_host_ip"
},
{
"id": "a98775c9-d110-4e77-a17e-bdec61c543f2",
"name": "target_port",
"type": "string",
"value": "target_host_ssh_port"
},
{
"id": "42debc80-9b3e-4b05-ad5e-4a8f4f6f1655",
"name": "target_user",
"type": "string",
"value": "target_host_username"
},
{
"id": "afeb1cba-cea7-455c-a519-e158628e524e",
"name": "target_password",
"type": "string",
"value": "target_host_password"
},
{
"id": "b220bff0-46de-430e-b7c3-3014151d1aff",
"name": "progress",
"type": "string",
"value": "INIT"
},
{
"id": "f4e0a984-d39a-4092-95ba-fd64884de843",
"name": "progress_only",
"type": "string",
"value": "false"
},
{
"id": "717c7fba-515e-4b47-9862-ee83a6c4d4e8",
"name": "KIND_CONFIG",
"type": "string",
"value": "config.yaml"
},
{
"id": "4dd919fe-b9ea-4c2d-bfba-0e458fa54c38",
"name": "ROBOT_SCRIPT",
"type": "string",
"value": "test.robot"
},
{
"id": "ed490c1b-92a9-472a-a5bb-188c094309c9",
"name": "ARGOCD_APPSET",
"type": "string",
"value": "demo-applicationSet.yaml"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "07caf13e-4f09-43aa-b253-52236dfab04c",
"name": "Robot Framework",
"type": "n8n-nodes-robotframework.robotFramework",
"position": [
1696,
352
],
"parameters": {
"robotScript": "={{ $json.stdout }}",
"includeLogHtml": true
},
"typeVersion": 1
},
{
"id": "4e7e8d45-f5e2-430d-aa91-bf33b8779465",
"name": "便签",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
288
],
"parameters": {
"color": 2,
"width": 2096,
"height": 432,
"content": ""
},
"typeVersion": 1
},
{
"id": "2e5c6a83-4da1-4370-912e-c61e811338ec",
"name": "切换",
"type": "n8n-nodes-base.switch",
"position": [
208,
320
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "init",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "05d26e07-8a5f-4cc1-8d7e-4235631d4299",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.progress }}",
"rightValue": "INIT"
}
]
},
"renameOutput": true
},
{
"outputKey": "test",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "2d3905d1-0182-4426-9e40-260c02453c40",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.progress }}",
"rightValue": "TEST"
}
]
},
"renameOutput": true
},
{
"outputKey": "destroy",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "17cfb80d-7424-4abb-a19a-fd29bf5b4be8",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.progress }}",
"rightValue": "DESTROY"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "c9903a44-5877-49cd-969c-d7e8a1591d17",
"name": "便签1",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
-720
],
"parameters": {
"color": 5,
"width": 2096,
"height": 800,
"content": "测试KinD和部署与Robot Framework"
},
"typeVersion": 1
},
{
"id": "976bedbe-55d3-4f40-b270-994bb1625ebc",
"name": "便签2",
"type": "n8n-nodes-base.stickyNote",
"position": [
496,
896
],
"parameters": {
"color": 3,
"width": 2096,
"height": 624,
"content": "在目标中安装Docker并使用可测试部署初始化KinD集群"
},
"typeVersion": 1
},
{
"id": "a44d76ec-8070-46e0-8ea0-aa64cde68850",
"name": "销毁KinD集群与已测试部署并在目标中卸载Docker",
"type": "n8n-nodes-base.set",
"position": [
2432,
-160
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b220bff0-46de-430e-b7c3-3014151d1aff",
"name": "progress",
"type": "string",
"value": "TEST"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "ec172786-0c6d-42a1-b1b3-4dc613bf2b7c",
"name": "设置已初始化",
"type": "n8n-nodes-base.set",
"position": [
2432,
480
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b220bff0-46de-430e-b7c3-3014151d1aff",
"name": "progress",
"type": "string",
"value": "DESTROY"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "d3259144-6d39-4a56-be29-907386a2563b",
"name": "设置已测试",
"type": "n8n-nodes-base.set",
"position": [
2192,
1312
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b220bff0-46de-430e-b7c3-3014151d1aff",
"name": "progress",
"type": "string",
"value": "CLEAR"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "cd48e173-0ed3-4f65-9cdf-35e713aa2414",
"name": "便签3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1680,
144
],
"parameters": {
"color": 7,
"width": 304,
"height": 176,
"content": "设置已销毁"
},
"typeVersion": 1
},
{
"id": "edeabedf-e0be-477f-886b-1a54904bd4bf",
"name": "## 重要!",
"type": "n8n-nodes-base.readWriteFile",
"position": [
768,
352
],
"parameters": {
"options": {},
"fileName": "/tmp/process_it.robot",
"operation": "write",
"dataPropertyName": "process_it.robot"
},
"typeVersion": 1
},
{
"id": "232d3d9b-ceb6-445e-8de2-1c55ad418e4f",
"name": "写入下载的ROBOT脚本",
"type": "n8n-nodes-base.executeCommand",
"position": [
976,
352
],
"parameters": {
"command": "=apk update\n\napk add --no-cache python3 py3-pip gcc musl-dev python3-dev libffi-dev openssl-dev cargo make nodejs npm\n\napk add --no-cache chromium chromium-chromedriver harfbuzz nss freetype ttf-freefont font-noto-emoji wqy-zenhei glib gobject-introspection at-spi2-core cups-libs libxcomposite libxdamage libxext libxfixes libxrandr libxrender libxtst pango cairo dbus-libs mesa-gl mesa-dri-gallium\n\npip3 install --break-system-packages --root-user-action=ignore robotframework\n\npip3 install --break-system-packages --root-user-action=ignore robotframework-seleniumlibrary robotframework-browser robotframework-requests robotframework-sshlibrary robotframework-databaselibrary\n\nrfbrowser init\n\npython3 -m Browser.entry init chromium\n\nexport PLAYWRIGHT_BROWSERS_PATH=/root/.cache/ms-playwright\nexport CHROMIUM_FLAGS=\"--no-sandbox --disable-setuid-sandbox --disable-dev-shm-usage\"\n"
},
"typeVersion": 1
},
{
"id": "7bdbe27a-bb4d-4445-9f98-9885331cee27",
"name": "添加Robot Framework、浏览器库、Chromium驱动",
"type": "n8n-nodes-base.readWriteFile",
"position": [
1328,
352
],
"parameters": {
"options": {
"fileName": "={{ $('Write Dowloaded ROBOT Script').item.json.fileName }}",
"dataPropertyName": "process_it.robot"
},
"fileSelector": "={{ $('Write Dowloaded ROBOT Script').item.json.fileName }}"
},
"typeVersion": 1
},
{
"id": "a394d031-70b4-4267-a068-b21bae80726d",
"name": "读取要执行的ROBOT脚本",
"type": "n8n-nodes-base.executeCommand",
"position": [
1872,
352
],
"parameters": {
"command": "=cd /tmp\npacking=$(tar -czvf testing-export-pack.tar.gz /root/n8n_robot_logs)\ncleaning=$(rm -rf /root/n8n_robot_logs)\necho \"/tmp/testing-export-pack.tar.gz\""
},
"typeVersion": 1
},
{
"id": "da6a48e3-5fb1-48ee-bd78-b023ff21f995",
"name": "打包ROBOT脚本导出",
"type": "n8n-nodes-base.readWriteFile",
"position": [
2048,
352
],
"parameters": {
"options": {
"fileName": "={{ $json.stdout }}",
"dataPropertyName": "testing-export-pack.tar.gz"
},
"fileSelector": "={{ $json.stdout }}"
},
"typeVersion": 1
},
{
"id": "bb5d31e3-3183-4f17-aa6b-331c5944eab9",
"name": "读取要发送的ROBOT脚本导出",
"type": "n8n-nodes-base.telegram",
"position": [
2224,
352
],
"webhookId": "88c2b04a-b6d3-4bb1-838d-851fef0d9c01",
"parameters": {
"chatId": "-1003104908315",
"operation": "sendDocument",
"binaryData": true,
"additionalFields": {},
"binaryPropertyName": "=testing-export-pack.tar.gz"
},
"credentials": {
"telegramApi": {
"id": "FUXl519hpM0FsK8j",
"name": "Telegram account"
}
},
"typeVersion": 1.2
},
{
"id": "9806fc1e-1d94-4208-b41a-5c22ea802746",
"name": "便签4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1680,
528
],
"parameters": {
"color": 7,
"width": 384,
"height": 112,
"content": "发送ROBOT脚本导出包"
},
"typeVersion": 1
},
{
"id": "3cc7cd5c-96bc-4534-86af-bb46311b120b",
"name": "## 重要!",
"type": "n8n-nodes-base.executeCommand",
"position": [
544,
-688
],
"parameters": {
"command": "which sshpass"
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "33907525-976e-48e3-92e6-4b94fc41e05e",
"name": "检查本地Sshpass是否存在",
"type": "n8n-nodes-base.if",
"position": [
736,
-688
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.exitCode }}",
"operation": "smallerEqual"
}
],
"string": [
{
"value1": "={{ $json.error }}",
"value2": "sshpass",
"operation": "notContains"
}
]
}
},
"typeVersion": 1
},
{
"id": "5a8750e9-fd35-4128-9fab-0e3abd75d274",
"name": "本地是否已安装?",
"type": "n8n-nodes-base.executeCommand",
"position": [
992,
-640
],
"parameters": {
"command": "=if command -v apt-get &> /dev/null; then\n apt-get update && apt-get install -y sshpass rsync\nelif command -v yum &> /dev/null; then\n yum install -y epel-release && yum install -y sshpass rsync\nelif command -v dnf &> /dev/null; then\n dnf install -y sshpass rsync\nelif command -v apk &> /dev/null; then\n apk add sshpass rsync\nelse\n echo \"Unsupported package manager\"\n exit 1\nfi"
},
"typeVersion": 1
},
{
"id": "09350879-6eae-42af-94f3-f5735dd83473",
"name": "在本地安装Sshpass",
"type": "n8n-nodes-base.executeCommand",
"position": [
1216,
-688
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"which docker\""
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "9bbc3483-90f4-47dd-9934-8c8db45188e3",
"name": "检查目标上的Docker",
"type": "n8n-nodes-base.if",
"position": [
1440,
-688
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.exitCode }}",
"operation": "smallerEqual"
}
],
"string": [
{
"value1": "={{ $json.error }}",
"value2": "docker",
"operation": "notContains"
}
]
}
},
"typeVersion": 1
},
{
"id": "d7967b95-3295-4972-9de1-ee3d7d353d6c",
"name": "目标上是否安装了Docker?",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
1648,
-624
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -f /etc/apt/sources.list.d/docker.list && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -f /etc/apt/keyrings/docker.gpg && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get update && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get autoremove -y && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get autoclean\"\n\nsshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"if command -v apt-get &> /dev/null; then . /etc/os-release && if [ \\\"\\$ID\\\" = \\\"ubuntu\\\" ]; then DOCKER_REPO=\\\"ubuntu\\\"; else DOCKER_REPO=\\\"debian\\\"; fi && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get update && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get install -y ca-certificates curl gnupg && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S install -m 0755 -d /etc/apt/keyrings && curl -fsSL https://download.docker.com/linux/\\$DOCKER_REPO/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S chmod a+r /etc/apt/keyrings/docker.gpg && echo \\\"deb [arch=\\$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/\\$DOCKER_REPO \\$VERSION_CODENAME stable\\\" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get update && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl start docker && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl enable docker; elif command -v yum &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S yum install -y yum-utils && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl start docker && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl enable docker; elif command -v dnf &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S dnf -y install dnf-plugins-core && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl start docker && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl enable docker; elif command -v apk &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apk add --no-cache docker docker-cli docker-compose && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rc-update add docker boot && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S service docker start; else echo 'Unsupported package manager'; exit 1; fi\""
},
"typeVersion": 1
},
{
"id": "cfd28b6f-3cfa-4f64-a572-334a7ea27625",
"name": "在目标上安装Docker",
"type": "n8n-nodes-base.executeCommand",
"position": [
2304,
-592
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"if command -v apt-get &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get update && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get install -y curl && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-amd64 && chmod +x ./kind && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S mv ./kind /usr/local/bin/kind; elif command -v yum &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S yum install -y curl && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-amd64 && chmod +x ./kind && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S mv ./kind /usr/local/bin/kind; elif command -v dnf &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S dnf install -y curl && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-amd64 && chmod +x ./kind && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S mv ./kind /usr/local/bin/kind; elif command -v apk &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apk add --no-cache curl && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.24.0/kind-linux-amd64 && chmod +x ./kind && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S mv ./kind /usr/local/bin/kind; else echo 'Unsupported package manager'; exit 1; fi\""
},
"typeVersion": 1
},
{
"id": "cca6856b-6e6f-414d-83ba-3de47ab7afdc",
"name": "在目标上安装KinD",
"type": "n8n-nodes-base.if",
"position": [
2080,
-688
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.exitCode }}",
"operation": "smallerEqual"
}
],
"string": [
{
"value1": "={{ $json.error }}",
"value2": "kind",
"operation": "notContains"
}
]
}
},
"typeVersion": 1
},
{
"id": "f2c9d96f-e5f7-4b0f-815e-26ca8ec76718",
"name": "目标上是否安装了KinD?",
"type": "n8n-nodes-base.executeCommand",
"position": [
1856,
-688
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"which kind\""
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "6afe2a50-53dc-4647-910a-e7cbac67037e",
"name": "检查目标上的KinD",
"type": "n8n-nodes-base.gitlab",
"position": [
560,
-368
],
"parameters": {
"owner": "n8n",
"filePath": "={{ $('Set Parameters').item.json.KIND_CONFIG }}",
"resource": "file",
"operation": "get",
"repository": "testing",
"authentication": "oAuth2",
"binaryPropertyName": "config.yaml",
"additionalParameters": {
"reference": "main"
}
},
"credentials": {
"gitlabOAuth2Api": {
"id": "Uvbl0nXUj63Ldscx",
"name": "GitLab account"
}
},
"typeVersion": 1
},
{
"id": "0b205c63-1bea-4602-b6b6-a0d22c52a012",
"name": "获取文件 - KinD配置",
"type": "n8n-nodes-base.readWriteFile",
"position": [
784,
-368
],
"parameters": {
"options": {},
"fileName": "/tmp/config.yaml",
"operation": "write",
"dataPropertyName": "config.yaml"
},
"typeVersion": 1
},
{
"id": "767099dd-8b50-4b29-bc1d-a35456c3ff32",
"name": "写入下载的KinD配置",
"type": "n8n-nodes-base.executeCommand",
"position": [
992,
-368
],
"parameters": {
"command": "=cat {{ $json.fileName }}"
},
"typeVersion": 1
},
{
"id": "99091217-262f-4589-b0f4-38ae2ac74026",
"name": "打开KinD配置",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
1200,
-368
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"cat > /tmp/config.yaml << 'EOF'\n{{ $json.stdout }}\nEOF\nkind create cluster --name automate-tst --config /tmp/config.yaml\""
},
"typeVersion": 1
},
{
"id": "96cbb13c-ff1e-4a07-90c3-71dfb619ff87",
"name": "在目标上创建KinD集群",
"type": "n8n-nodes-base.if",
"position": [
784,
1296
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.exitCode }}",
"operation": "smallerEqual"
}
],
"string": [
{
"value1": "={{ $json.error }}",
"value2": "docker",
"operation": "notContains"
}
]
}
},
"typeVersion": 1
},
{
"id": "a2224dd5-6460-4064-9b35-a0fb3c87ecc3",
"name": "目标上是否安装了Docker?1",
"type": "n8n-nodes-base.if",
"position": [
1888,
928
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.exitCode }}",
"operation": "smallerEqual"
}
],
"string": [
{
"value1": "={{ $json.error }}",
"value2": "kind",
"operation": "notContains"
}
]
}
},
"typeVersion": 1
},
{
"id": "c8244168-25ad-4704-b1df-863e4a9c7f4c",
"name": "目标上是否安装了KinD?1",
"type": "n8n-nodes-base.executeCommand",
"position": [
576,
928
],
"parameters": {
"command": "which sshpass"
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "917cbbc3-4900-4914-87ee-ec5691fe5c3e",
"name": "检查本地Sshpass是否存在 (D)",
"type": "n8n-nodes-base.if",
"position": [
768,
928
],
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.exitCode }}",
"operation": "smallerEqual"
}
]
}
},
"typeVersion": 1
},
{
"id": "33ec5f41-f4df-42d4-a6db-a1515d43b6a3",
"name": "本地是否已安装? (D)",
"type": "n8n-nodes-base.executeCommand",
"position": [
1008,
976
],
"parameters": {
"command": "=if command -v apt-get &> /dev/null; then\n apt-get update && apt-get install -y sshpass rsync\nelif command -v yum &> /dev/null; then\n yum install -y epel-release && yum install -y sshpass rsync\nelif command -v dnf &> /dev/null; then\n dnf install -y sshpass rsync\nelif command -v apk &> /dev/null; then\n apk add sshpass rsync\nelse\n echo \"Unsupported package manager\"\n exit 1\nfi"
},
"typeVersion": 1
},
{
"id": "e7dc7914-8352-4060-844b-daa561b01aea",
"name": "在本地安装Sshpass (D)",
"type": "n8n-nodes-base.executeCommand",
"position": [
576,
1296
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"which docker\""
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "465c84d3-b0ba-45df-999a-2c29fca75ede",
"name": "检查目标上的Docker (D)",
"type": "n8n-nodes-base.executeCommand",
"position": [
1440,
912
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"kind delete cluster --name automate-tst\""
},
"typeVersion": 1
},
{
"id": "83511d71-310c-4be4-8765-a9cd40859807",
"name": "删除目标上的KinD集群",
"type": "n8n-nodes-base.executeCommand",
"position": [
1664,
928
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"which kind\""
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "ae9ecbe9-58b7-4080-8496-f5c4763c24e1",
"name": "检查目标上的KinD (D)",
"type": "n8n-nodes-base.executeCommand",
"position": [
2128,
976
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -rf /usr/local/bin/kind\""
},
"typeVersion": 1
},
{
"id": "502870b0-31ba-4bb6-b7ea-87d7d0846249",
"name": "在目标上卸载KinD",
"type": "n8n-nodes-base.executeCommand",
"position": [
992,
1200
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"if command -v apt-get &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -f /etc/apt/sources.list.d/docker.list && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -f /etc/apt/keyrings/docker.gpg && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get update && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get autoremove -y && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get autoclean; elif command -v yum &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl stop docker 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl disable docker 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S yum remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 2>/dev/null || true; elif command -v dnf &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl stop docker 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl disable docker 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S dnf remove -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 2>/dev/null || true; elif command -v apk &> /dev/null; then echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S service docker stop 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rc-update del docker boot 2>/dev/null || true && echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apk del docker docker-cli docker-compose 2>/dev/null || true; else echo 'Unsupported package manager'; exit 1; fi && rm -rf $(which docker)\""
},
"typeVersion": 1
},
{
"id": "b8079542-34e2-4fae-87aa-04539df7066c",
"name": "在目标上卸载Docker",
"type": "n8n-nodes-base.executeCommand",
"onError": "continueRegularOutput",
"position": [
2416,
1312
],
"parameters": {
"command": "=apk add curl\n\nexport TOKEN=\"6395628144:AAGYh1d9ZohaK14Tymw7n-5lA6LSC9e3oEo\"\nexport CHAT_ID=\"-1234567890123\"\nexport MESSAGE=\"Automate KinD Build and Application Test Ended! Testing Resource Pack Sent!\"\n\ncurl -s -X POST \"https://api.telegram.org/bot$TOKEN/sendMessage\" -d chat_id=\"$CHAT_ID\" -d text=\"$MESSAGE\"\n\nNUMBERS=\"+36301234567\"\n\nfor PHONE in $NUMBERS; do\n # curl -X POST https://textbelt.com/text --data-urlencode phone=\"$PHONE\" --data-urlencode message=\"$MESSAGE\" -d key=YOUR-TEXTBELT-API-KEY\ndone"
},
"typeVersion": 1
},
{
"id": "ac243f29-13f8-4e18-84b7-f3f53a6f6704",
"name": "处理完成报告 --- Telegram和SMS1",
"type": "n8n-nodes-base.executeCommand",
"position": [
1424,
-368
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\n\ndocker exec -i automate-tst-control-plane bash << 'DOCKEREOF'\n\ncurl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 > gethelmfile\n\nchmod +x ./gethelmfile\n\nwhile ! command -v helm &> /dev/null; do\n timeout 10s bash -c './gethelmfile'\n sleep 5\ndone\n\nhelm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx\nhelm repo update\n\nhelm install ingress-nginx ingress-nginx/ingress-nginx \\\n --namespace ingress-nginx \\\n --create-namespace \\\n --set controller.service.type=NodePort \\\n --set controller.service.nodePorts.http=30080 \\\n --set controller.service.nodePorts.https=30443 \\\n --wait \\\n --timeout 5m\n\nkubectl get pods -n ingress-nginx\nkubectl get svc -n ingress-nginx\n\nDOCKEREOF\n\""
},
"typeVersion": 1
},
{
"id": "fe9eac0d-749f-4553-89e3-2f831d020761",
"name": "在KinD集群中安装Helm和Nginx-Ingress",
"type": "n8n-nodes-base.executeCommand",
"position": [
1648,
-368
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\n\nif command -v apt-get &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get update\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get install -y haproxy\nelif command -v yum &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S yum install -y haproxy\nelif command -v dnf &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S dnf install -y haproxy\nelif command -v apk &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apk add --no-cache haproxy\nelse\n echo 'Unsupported package manager'\n exit 1\nfi\n\n\necho '{{ $('Set Parameters').item.json.target_password }}' | sudo -S tee /etc/haproxy/haproxy.cfg > /dev/null << 'EOF'\nglobal\n log /dev/log local0\n log /dev/log local1 notice\n chroot /var/lib/haproxy\n stats socket /run/haproxy/admin.sock mode 660 level admin\n stats timeout 30s\n user haproxy\n group haproxy\n daemon\n\ndefaults\n log global\n mode http\n option httplog\n option dontlognull\n timeout connect 5000\n timeout client 50000\n timeout server 50000\n\nfrontend http_front\n bind *:80\n mode tcp\n default_backend http_back\n\nbackend http_back\n mode tcp\n server kind_ingress 127.0.0.1:60080 check\nEOF\n\n\nif command -v systemctl &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl restart haproxy\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl enable haproxy\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl status haproxy\nelif command -v service &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S service haproxy restart\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rc-update add haproxy default 2>/dev/null || true\nfi\n\"\n\nsshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\n\nif ! grep -qE '^127\\.0\\.0\\.1[[:space:]]+autotest\\.innersite([[:space:]]|$)' /etc/hosts; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S sh -c 'echo \\\"\\\" >> /etc/hosts && echo \\\"127.0.0.1 autotest.innersite\\\" >> /etc/hosts'\n echo 'Host entry added: 127.0.0.1 autotest.innersite'\nelse\n echo 'Host entry already exists: 127.0.0.1 autotest.innersite'\nfi\n\necho '---'\necho 'Current /etc/hosts content:'\ngrep -E '^127\\.0\\.0\\.1' /etc/hosts\n\""
},
"typeVersion": 1
},
{
"id": "19bd956a-395d-4210-9d9d-e4980311403b",
"name": "无操作,不执行任何操作",
"type": "n8n-nodes-base.noOp",
"position": [
2432,
112
],
"parameters": {},
"typeVersion": 1
},
{
"id": "6c314b47-9578-4564-8a9c-d208dbe2a6a0",
"name": "在目标上安装HAProxy并配置端口80到KinD",
"type": "n8n-nodes-base.if",
"position": [
2224,
-160
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $('Set Parameters').item.json.progress_only }}",
"value2": "false"
}
]
}
},
"typeVersion": 1
},
{
"id": "9f10a302-78e6-4fc1-9e9e-1d07acd71f98",
"name": "仅初始化?",
"type": "n8n-nodes-base.if",
"position": [
2432,
336
],
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $('Set Parameters').item.json.progress_only }}",
"value2": "false"
}
]
}
},
"typeVersion": 1
},
{
"id": "38397b70-ff06-4295-bf96-ffdc6db9cf26",
"name": "仅测试?",
"type": "n8n-nodes-base.executeCommand",
"position": [
1216,
912
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\n\nif command -v apt-get &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl stop haproxy 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl disable haproxy 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get remove -y haproxy\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get purge -y haproxy\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apt-get autoremove -y\nelif command -v yum &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl stop haproxy 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl disable haproxy 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S yum remove -y haproxy\nelif command -v dnf &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl stop haproxy 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S systemctl disable haproxy 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S dnf remove -y haproxy\nelif command -v apk &> /dev/null; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S service haproxy stop 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rc-update del haproxy default 2>/dev/null || true\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S apk del haproxy\nelse\n echo 'Unsupported package manager'\n exit 1\nfi\n\n\necho '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -rf /etc/haproxy 2>/dev/null || true\necho '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -rf /var/lib/haproxy 2>/dev/null || true\necho '{{ $('Set Parameters').item.json.target_password }}' | sudo -S rm -rf /run/haproxy 2>/dev/null || true\n\necho 'HAProxy successfully removed'\n\"\n\nsshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\n\nif grep -qE '^127\\.0\\.0\\.1[[:space:]]+autotest\\.innersite([[:space:]]|$)' /etc/hosts; then\n echo '{{ $('Set Parameters').item.json.target_password }}' | sudo -S sed -i '/^127\\.0\\.0\\.1[[:space:]]\\+autotest\\.innersite\\([[:space:]]\\|$\\)/d' /etc/hosts\n echo 'Host entry removed: 127.0.0.1 autotest.innersite'\nelse\n echo 'Host entry not found: 127.0.0.1 autotest.innersite'\nfi\n\necho '{{ $('Set Parameters').item.json.target_password }}' | sudo -S sed -i -e :a -e '/^\\n*$/{$d;N;ba' -e '}' /etc/hosts\n\necho '---'\necho 'Current /etc/hosts content:'\ngrep -E '^127\\.0\\.0\\.1' /etc/hosts || echo 'No 127.0.0.1 entries found'\n\""
},
"typeVersion": 1
},
{
"id": "3d976844-91c3-41c9-9d0a-1c9e8521fa8c",
"name": "删除目标上的HAProxy",
"type": "n8n-nodes-base.executeCommand",
"position": [
1520,
352
],
"parameters": {
"command": "=cat {{ $json.fileName }}"
},
"typeVersion": 1
},
{
"id": "fcc0449e-fe7f-4788-a37e-263a2fb30f9e",
"name": "打开ROBOT脚本到Framework",
"type": "n8n-nodes-base.executeCommand",
"position": [
1152,
352
],
"parameters": {
"command": "=TARGET_IP='{{ $('Set Parameters').item.json.target_host }}'\n\nif ! grep -qE \"^${TARGET_IP}[[:space:]]+autotest\\.innersite([[:space:]]|$)\" /etc/hosts; then\n echo \"\" | tee -a /etc/hosts > /dev/null\n echo \"${TARGET_IP} autotest.innersite\" | tee -a /etc/hosts > /dev/null\n echo \"Host entry added: ${TARGET_IP} autotest.innersite\"\nelse\n echo \"Host entry already exists: ${TARGET_IP} autotest.innersite\"\nfi\n\necho '---'\necho 'Current /etc/hosts relevant entries:'\ngrep -E 'autotest\\.innersite' /etc/hosts || echo 'No autotest.innersite entries found'"
},
"typeVersion": 1
},
{
"id": "fbcd1a7d-1ada-41a7-95ae-9f019e89ce77",
"name": "添加目标到主机",
"type": "n8n-nodes-base.executeCommand",
"position": [
1312,
1312
],
"parameters": {
"command": "=TARGET_IP='{{ $('Set Parameters').item.json.target_host }}'\n\nif grep -qE \"^${TARGET_IP}[[:space:]]+autotest\\.innersite([[:space:]]|$)\" /etc/hosts; then\n sed -i \"/^${TARGET_IP}[[:space:]]\\+autotest\\.innersite\\([[:space:]]\\|$\\)/d\" /etc/hosts\n echo \"Host entry removed: ${TARGET_IP} autotest.innersite\"\nelse\n echo \"Host entry not found: ${TARGET_IP} autotest.innersite\"\nfi\n\nsed -i -e :a -e '/^\\n*$/{$d;N;ba' -e '}' /etc/hosts\n\necho '---'\necho 'Current /etc/hosts content:'\ngrep -E \"^${TARGET_IP}\" /etc/hosts || echo \"No ${TARGET_IP} entries found\""
},
"typeVersion": 1
},
{
"id": "3885b7b3-5528-4407-9934-ecd24e95c24f",
"name": "从主机中移除目标",
"type": "n8n-nodes-base.executeCommand",
"position": [
1856,
-368
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\ndocker exec -i automate-tst-control-plane bash << 'DOCKEREOF'\n\nhelm repo add argo https://argoproj.github.io/argo-helm\nhelm repo update\n\nhelm install argocd argo/argo-cd \\\n --namespace argocd \\\n --create-namespace \\\n --set server.insecure=true \\\n --set server.extraArgs[0]=--insecure \\\n --set configs.params.server\\\\.insecure=true \\\n --set configs.cm.url=http://autotest.innersite \\\n --set server.service.type=ClusterIP \\\n --wait \\\n --timeout 10m\n\nkubectl wait --for=condition=ready pod -l app.kubernetes.io/name=argocd-server -n argocd --timeout=300s\n\nkubectl apply -f - << 'INGRESSEOF'\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: argocd-server-ingress\n namespace: argocd\n annotations:\n nginx.ingress.kubernetes.io/force-ssl-redirect: \\\"false\\\"\n nginx.ingress.kubernetes.io/ssl-redirect: \\\"false\\\"\n nginx.ingress.kubernetes.io/backend-protocol: \\\"HTTP\\\"\nspec:\n ingressClassName: nginx\n rules:\n - host: autotest.innersite\n http:\n paths:\n - path: /\n pathType: Prefix\n backend:\n service:\n name: argocd-server\n port:\n number: 80\nINGRESSEOF\n\nif ! command -v htpasswd &> /dev/null; then\n apt-get update && apt-get install -y apache2-utils\nfi\n\nkubectl -n argocd rollout restart deployment argocd-server\nkubectl -n argocd rollout status deployment argocd-server --timeout=300s\n\nDOCKEREOF\n\"\n\n\nsshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\ndocker exec -i automate-tst-control-plane bash << 'ADDUSEROFF'\n\nUSERNAME='autotest'\nPASSWORD='autotest'\nROLE='admin'\nNAMESPACE='argocd'\nMTIME='2025-09-25T10:00:00Z'\n\nPASSWORD_HASH=\\`htpasswd -bnBC 10 '' \\\"\\$PASSWORD\\\" | tr -d ':\\\\n' | sed 's/\\$2y/\\$2a/'\\`\nPASSWORD_B64=\\`echo -n \\\"\\$PASSWORD_HASH\\\" | base64 -w0\\`\nMTIME_B64=\\`echo -n \\\"\\$MTIME\\\" | base64 -w0\\`\n\nkubectl patch secret argocd-secret -n \\$NAMESPACE --type=json -p='[\n {\\\"op\\\":\\\"add\\\",\\\"path\\\":\\\"/data/accounts.'\\$USERNAME'.password\\\",\\\"value\\\":\\\"'\\$PASSWORD_B64'\\\"},\n {\\\"op\\\":\\\"add\\\",\\\"path\\\":\\\"/data/accounts.'\\$USERNAME'.passwordMtime\\\",\\\"value\\\":\\\"'\\$MTIME_B64'\\\"}\n]'\n\nkubectl patch configmap argocd-cm -n \\$NAMESPACE --type=merge -p='{\\\"data\\\":{\\\"accounts.'\\$USERNAME'\\\":\\\"login\\\"}}'\n\nkubectl patch configmap argocd-rbac-cm -n \\$NAMESPACE --type=merge -p='{\\\"data\\\":{\\\"policy.csv\\\":\\\"g, '\\$USERNAME', role:'\\$ROLE'\\\"}}'\n\necho \\\"---\\\"\necho \\\"ArgoCD Pods:\\\"\nkubectl get pods -n argocd\n\necho \\\"---\\\"\necho \\\"ArgoCD Services:\\\"\nkubectl get svc -n argocd\n\necho \\\"---\\\"\necho \\\"ArgoCD Ingress:\\\"\nkubectl get ingress -n argocd\n\necho \\\"---\\\"\necho \\\"ArgoCD available at: http://autotest.innersite\\\"\necho \\\"Username: \\$USERNAME\\\"\necho \\\"Password: \\$PASSWORD\\\"\n\nADDUSEROFF\n\""
},
"typeVersion": 1
},
{
"id": "5b139746-1c91-431c-b293-2586d8adbbe8",
"name": "安装ArgoCD到KinD集群",
"type": "n8n-nodes-base.gitlab",
"position": [
560,
-160
],
"parameters": {
"owner": "n8n",
"filePath": "={{ $('Set Parameters').item.json.ARGOCD_APPSET }}",
"resource": "file",
"operation": "get",
"repository": "testing",
"authentication": "oAuth2",
"binaryPropertyName": "demo-applicationSet.yaml",
"additionalParameters": {
"reference": "main"
}
},
"credentials": {
"gitlabOAuth2Api": {
"id": "Uvbl0nXUj63Ldscx",
"name": "GitLab account"
}
},
"typeVersion": 1
},
{
"id": "42e32eaf-f604-400b-8511-a6e4682d318e",
"name": "获取文件 - ArgoCD ApplicationSet",
"type": "n8n-nodes-base.readWriteFile",
"position": [
784,
-160
],
"parameters": {
"options": {},
"fileName": "/tmp/demo-applicationSet.yaml",
"operation": "write",
"dataPropertyName": "demo-applicationSet.yaml"
},
"typeVersion": 1
},
{
"id": "b8a4e1c5-bb96-4efe-b70e-c7dfd7d83821",
"name": "写入下载的ArgoCD ApplicationSet",
"type": "n8n-nodes-base.executeCommand",
"position": [
992,
-160
],
"parameters": {
"command": "=cat {{ $json.fileName }}"
},
"typeVersion": 1
},
{
"id": "1c585a8c-1a89-4f38-8ac2-c54f0d1926b9",
"name": "打开ArgoCD ApplicationSet",
"type": "n8n-nodes-base.executeCommand",
"position": [
1200,
-160
],
"parameters": {
"command": "=sshpass -p '{{ $('Set Parameters').item.json.target_password }}' ssh -o StrictHostKeyChecking=no -p {{ $('Set Parameters').item.json.target_port }} {{ $('Set Parameters').item.json.target_user }}@{{ $('Set Parameters').item.json.target_host }} \"\ndocker exec -i automate-tst-control-plane bash << 'APPLYEOF'\nkubectl apply -n argocd -f - << 'YAMLEOF'\n{{ $json.stdout }}\nYAMLEOF\n\nkubectl get applicationsets -n argocd\nAPPLYEOF\n\""
},
"typeVersion": 1
},
{
"id": "3f49e20c-b627-4066-828e-7a2f15a4e4ab",
"name": "应用ArgoCD ApplicationSet",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
16
],
"parameters": {
"color": 7,
"width": 450,
"height": 344,
"content": "工作流概述便签"
},
"typeVersion": 1
},
{
"id": "9d2efdf4-fee9-4950-874a-629c4104ccfd",
"name": "## 工作流概述",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
416
],
"parameters": {
"color": 7,
"width": 448,
"height": 328,
"content": "触发器配置便签"
},
"typeVersion": 1
},
{
"id": "a24a6219-9704-4cfe-bb25-da4146997c16",
"name": "## 触发器配置",
"type": "n8n-nodes-base.stickyNote",
"position": [
-144,
512
],
"parameters": {
"color": 7,
"width": 380,
"height": 360,
"content": "配置指南便签"
},
"typeVersion": 1
},
{
"id": "51a455f4-c8b3-4bcc-88b9-c29127f61b94",
"name": "## 必需配置",
"type": "n8n-nodes-base.stickyNote",
"position": [
16,
-464
],
"parameters": {
"color": 7,
"width": 450,
"height": 276,
"content": "GitLab设置便签"
},
"typeVersion": 1
},
{
"id": "7fe8456d-8a20-43bf-9a8d-aa087a7f5857",
"name": "## GitLab集成",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-48
],
"parameters": {
"color": 7,
"width": 420,
"height": 348,
"content": "阶段控制便签"
},
"typeVersion": 1
},
{
"id": "18604e04-a554-40be-a167-fc7b4a7fb151",
"name": "## 阶段控制逻辑",
"type": "n8n-nodes-base.stickyNote",
"position": [
2080,
528
],
"parameters": {
"color": 7,
"width": 496,
"height": 332,
"content": "Telegram配置便签"
},
"typeVersion": 1
},
{
"id": "3a9ca7b8-fd69-4953-b93b-dad70e982640",
"name": "## Telegram通知",
"type": "n8n-nodes-base.stickyNote",
"position": [
2608,
-720
],
"parameters": {
"color": 5,
"width": 450,
"height": 332,
"content": "初始化阶段摘要便签"
},
"typeVersion": 1
},
{
"id": "32dd93fe-8243-4e28-b28f-6b0703806580",
"name": "## 初始化阶段摘要",
"type": "n8n-nodes-base.stickyNote",
"position": [
2608,
288
],
"parameters": {
"color": 2,
"width": 450,
"height": 312,
"content": "测试阶段摘要便签"
},
"typeVersion": 1
},
{
"id": "0fd0bfbe-12da-49e3-b512-f91eb19422bc",
"name": "## 测试阶段摘要",
"type": "n8n-nodes-base.stickyNote",
"position": [
2608,
896
],
"parameters": {
"color": 3,
"width": 450,
"height": 328,
"content": "销毁阶段摘要便签"
},
"typeVersion": 1
},
{
"id": "46d9310d-656b-418c-8ca0-cb4ca6391381",
"name": "## 销毁阶段摘要",
"type": "n8n-nodes-base.stickyNote",
"position": [
2272,
1472
],
"parameters": {
"color": 7,
"width": 350,
"height": 246,
"content": "最终通知便签"
},
"typeVersion": 1
},
{
"id": "81d81c7d-0501-456c-abf1-e3600e209f27",
"name": "便签5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1504,
272
],
"parameters": {
"width": 512,
"height": 608,
"content": "## 最终通知"
},
"typeVersion": 1
},
{
"id": "26a4e51d-5130-43ee-bc37-0557d1da82a4",
"name": "便签6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2256,
-432
],
"parameters": {
"width": 1264,
"height": 688,
"content": "## KinD配置 - 示例"
},
"typeVersion": 1
},
{
"id": "95522c65-f7c6-4c0e-a7e1-ca2edc567542",
"name": "便签7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2256,
272
],
"parameters": {
"width": 736,
"height": 384,
"content": "## Robot Framework脚本 - 示例"
},
"typeVersion": 1
},
{
"id": "983eea52-5245-46f8-a9c7-faa4b67e48a9",
"name": "便签8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2256,
672
],
"parameters": {
"width": 736,
"height": 208,
"content": "## ArgoCD ApplicationSet - 示例"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "69f5b826-e657-4634-8ecc-16f63dddcac3",
"connections": {
"Switch": {
"main": [
[
{
"node": "Check Sshpass Exist Local",
"type": "main",
"index": 0
}
],
[
{
"node": "Get a file - ROBOT Script",
"type": "main",
"index": 0
}
],
[
{
"node": "Check Sshpass Exist Local (D)",
"type": "main",
"index": 0
}
]
]
},
"Webhook": {
"main": [
[
{
"node": "Set Parameters",
"type": "main",
"index": 0
}
]
]
},
"Set Tested": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Is INIT Only?": {
"main": [
[
{
"node": "Set Initialized",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Is TEST Only?": {
"main": [
[
{
"node": "Set Tested",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Set Destroyed": {
"main": [
[
{
"node": "Process Finish Report --- Telegam & SMS1",
"type": "main",
"index": 0
}
]
]
},
"Set Parameters": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Robot Framework": {
"main": [
[
{
"node": "Pack ROBOT Script Exports",
"type": "main",
"index": 0
}
]
]
},
"Set Initialized": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Open KinD Config": {
"main": [
[
{
"node": "Create KinD Cluster on Target",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Set Parameters",
"type": "main",
"index": 0
}
]
]
},
"Add Target to Hosts": {
"main": [
[
{
"node": "Read ROBOT Script to Execute",
"type": "main",
"index": 0
}
]
]
},
"Is Installed Local?": {
"main": [
[
{
"node": "Check Docker on Target",
"type": "main",
"index": 0
}
],
[
{
"node": "Install Sshpass Local",
"type": "main",
"index": 0
}
]
]
},
"Check KinD on Target": {
"main": [
[
{
"node": "Is KinD Installed on Target?",
"type": "main",
"index": 0
}
]
]
},
"Install Sshpass Local": {
"main": [
[
{
"node": "Check Docker on Target",
"type": "main",
"index": 0
}
]
]
},
"Check Docker on Target": {
"main": [
[
{
"node": "Is Docker Installed on Target?",
"type": "main",
"index": 0
}
]
]
},
"Install KinD on Target": {
"main": [
[
{
"node": "Get a file - KinD Config",
"type": "main",
"index": 0
}
]
]
},
"Is Installed Local? (D)": {
"main": [
[
{
"node": "Delete HAProxy on Target",
"type": "main",
"index": 0
}
],
[
{
"node": "Install Sshpass Local (D)",
"type": "main",
"index": 0
}
]
]
},
"Check KinD on Target (D)": {
"main": [
[
{
"node": "Is KinD Installed on Target?1",
"type": "main",
"index": 0
}
]
]
},
"Delete HAProxy on Target": {
"main": [
[
{
"node": "Delete KinD Cluster on Target",
"type": "main",
"index": 0
}
]
]
},
"Get a file - KinD Config": {
"main": [
[
{
"node": "Write Dowloaded KinD Config",
"type": "main",
"index": 0
}
]
]
},
"Install Docker on Target": {
"main": [
[
{
"node": "Check KinD on Target",
"type": "main",
"index": 0
}
]
]
},
"Remove Target from Hosts": {
"main": [
[
{
"node": "Set Destroyed",
"type": "main",
"index": 0
}
]
]
},
"UnInstall KinD on Target": {
"main": [
[
{
"node": "Check Docker on Target (D)",
"type": "main",
"index": 0
}
]
]
},
"Check Sshpass Exist Local": {
"main": [
[
{
"node": "Is Installed Local?",
"type": "main",
"index": 0
}
]
]
},
"Get a file - ROBOT Script": {
"main": [
[
{
"node": "Write Dowloaded ROBOT Script",
"type": "main",
"index": 0
}
]
]
},
"Install Sshpass Local (D)": {
"main": [
[
{
"node": "Delete HAProxy on Target",
"type": "main",
"index": 0
}
]
]
},
"Pack ROBOT Script Exports": {
"main": [
[
{
"node": "Read ROBOT Script Exports to Send",
"type": "main",
"index": 0
}
]
]
},
"Check Docker on Target (D)": {
"main": [
[
{
"node": "Is Docker Installed on Target?1",
"type": "main",
"index": 0
}
]
]
},
"Open ArgoCD ApplicationSet": {
"main": [
[
{
"node": "Apply ArgoCD ApplicationSet",
"type": "main",
"index": 0
}
]
]
},
"UnInstall Docker on Target": {
"main": [
[
{
"node": "Remove Target from Hosts",
"type": "main",
"index": 0
}
]
]
},
"Apply ArgoCD ApplicationSet": {
"main": [
[
{
"node": "Is INIT Only?",
"type": "main",
"index": 0
}
]
]
},
"Write Dowloaded KinD Config": {
"main": [
[
{
"node": "Open KinD Config",
"type": "main",
"index": 0
}
]
]
},
"Is KinD Installed on Target?": {
"main": [
[
{
"node": "Get a file - KinD Config",
"type": "main",
"index": 0
}
],
[
{
"node": "Install KinD on Target",
"type": "main",
"index": 0
}
]
]
},
"Read ROBOT Script to Execute": {
"main": [
[
{
"node": "Open ROBOT Script to Framework",
"type": "main",
"index": 0
}
]
]
},
"Write Dowloaded ROBOT Script": {
"main": [
[
{
"node": "Add Robot Framework, Browser Library, Chromium Driver",
"type": "main",
"index": 0
}
]
]
},
"Check Sshpass Exist Local (D)": {
"main": [
[
{
"node": "Is Installed Local? (D)",
"type": "main",
"index": 0
}
]
]
},
"Create KinD Cluster on Target": {
"main": [
[
{
"node": "Install Helm and Nginx-Ingress in KinD Cluster",
"type": "main",
"index": 0
}
]
]
},
"Delete KinD Cluster on Target": {
"main": [
[
{
"node": "Check KinD on Target (D)",
"type": "main",
"index": 0
}
]
]
},
"Is KinD Installed on Target?1": {
"main": [
[
{
"node": "UnInstall KinD on Target",
"type": "main",
"index": 0
}
],
[
{
"node": "Check Docker on Target (D)",
"type": "main",
"index": 0
}
]
]
},
"Send ROBOT Script Export Pack": {
"main": [
[
{
"node": "Is TEST Only?",
"type": "main",
"index": 0
}
]
]
},
"Install ArgoCD to KinD Cluster": {
"main": [
[
{
"node": "Get a file - ArgoCD ApplicationSet",
"type": "main",
"index": 0
}
]
]
},
"Is Docker Installed on Target?": {
"main": [
[
{
"node": "Check KinD on Target",
"type": "main",
"index": 0
}
],
[
{
"node": "Install Docker on Target",
"type": "main",
"index": 0
}
]
]
},
"Open ROBOT Script to Framework": {
"main": [
[
{
"node": "Robot Framework",
"type": "main",
"index": 0
}
]
]
},
"Is Docker Installed on Target?1": {
"main": [
[
{
"node": "UnInstall Docker on Target",
"type": "main",
"index": 0
}
],
[
{
"node": "Remove Target from Hosts",
"type": "main",
"index": 0
}
]
]
},
"Read ROBOT Script Exports to Send": {
"main": [
[
{
"node": "Send ROBOT Script Export Pack",
"type": "main",
"index": 0
}
]
]
},
"Get a file - ArgoCD ApplicationSet": {
"main": [
[
{
"node": "Write Dowloaded ArgoCD ApplicationSet",
"type": "main",
"index": 0
}
]
]
},
"When clicking ‘Execute workflow’": {
"main": [
[
{
"node": "Set Parameters",
"type": "main",
"index": 0
}
]
]
},
"Write Dowloaded ArgoCD ApplicationSet": {
"main": [
[
{
"node": "Open ArgoCD ApplicationSet",
"type": "main",
"index": 0
}
]
]
},
"Install Helm and Nginx-Ingress in KinD Cluster": {
"main": [
[
{
"node": "Install HAProxy on Target and Config Port-80 to KinD",
"type": "main",
"index": 0
}
]
]
},
"Install HAProxy on Target and Config Port-80 to KinD": {
"main": [
[
{
"node": "Install ArgoCD to KinD Cluster",
"type": "main",
"index": 0
}
]
]
},
"Add Robot Framework, Browser Library, Chromium Driver": {
"main": [
[
{
"node": "Add Target to Hosts",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
高级 - 开发运维
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
Telegram AI频道机器人 - 支持文本和图像响应的TGPT生成器
使用GPT-4和TGPT在Telegram频道中生成文本和图像响应
If
Set
Code
+8
22 节点Vigh Sandor
灵活新闻聚合器 - 多源集成、AI分析和可设置频道
多源新闻策展系统,集成Mistral AI分析、摘要和自定义频道
If
Set
Xml
+32
120 节点Hybroht
内容创作
符合PAdES标准的PDF数字签名API
使用X.509证书按照PAdES标准签署PDF文档
If
Set
Switch
+7
65 节点Vigh Sandor
文档提取
基于密码认证和警报系统的自动化Rsync备份
密码认证与警报系统的自动化Rsync备份
If
Set
Manual Trigger
+3
21 节点Vigh Sandor
高级 n8n 工作流与 GitHub 同步
使用 GitHub 的智能变更检测自动化工作流备份
If
N8n
Set
+10
38 节点Maksym Brashenko
开发运维
自动化n8n工作流备份至GitHub并追踪删除
自动化n8n工作流备份至GitHub并追踪删除
If
N8n
Set
+13
31 节点Marcial Ambriz
开发运维
工作流信息
难度等级
高级
节点数量73
分类1
节点类型13
作者
Vigh Sandor
@vighsandorI'm a DevOps engineer and automation enthusiast who builds smart, practical workflows using n8n.io. I focus on creating reliable, open-source solutions that connect tools and simplify everyday operations — whether it’s infrastructure management, workflow automation, or integrating AI into existing systems.
外部链接
在 n8n.io 查看 →
分享此工作流