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": "Automated Kubernetes Testing with Robot Framework, ArgoCD & Complete KinD Lifecycle",
"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": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Testing KinD and deployment with Robot Framework"
},
"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": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Install Docker in Target and init KinD Custer with the testable deployment"
},
"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": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Destroy KinD Cluster with the tested deployment and uninstall Docker in Target"
},
"typeVersion": 1
},
{
"id": "a44d76ec-8070-46e0-8ea0-aa64cde68850",
"name": "초기화 설정",
"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": "## Important! \nIf you are using a script in Robot Framework that works in a browser, then in the **\"New Browser\"** line you must specify the **\"executablePath=/usr/bin/chromium-browser\"** parameter"
},
"typeVersion": 1
},
{
"id": "edeabedf-e0be-477f-886b-1a54904bd4bf",
"name": "다운로드한 ROBOT 스크립트 작성",
"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 Framework, Browser Library, Chromium Driver 추가",
"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 스크립트 읽기",
"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": "## Important! \nTo use this workflow, you MUST INSTALL the **n8n-nodes-robotframework** node in the **Community Nodes** section!"
},
"typeVersion": 1
},
{
"id": "3cc7cd5c-96bc-4534-86af-bb46311b120b",
"name": "로컬 Sshpass 존재 확인",
"type": "n8n-nodes-base.executeCommand",
"position": [
544,
-688
],
"parameters": {
"command": "which sshpass"
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "33907525-976e-48e3-92e6-4b94fc41e05e",
"name": "로컬에 설치되었는가?",
"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": "로컬에 Sshpass 설치",
"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": "대상에서 Docker 확인",
"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": "대상에 KinD 설치",
"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": "대상에 Docker가 설치되었는가?1",
"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": "대상에 KinD가 설치되었는가?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": "로컬 Sshpass 존재 확인 (D)",
"type": "n8n-nodes-base.executeCommand",
"position": [
576,
928
],
"parameters": {
"command": "which sshpass"
},
"typeVersion": 1,
"continueOnFail": true
},
{
"id": "917cbbc3-4900-4914-87ee-ec5691fe5c3e",
"name": "로컬에 설치되었는가? (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": "로컬에 Sshpass 설치 (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": "대상에서 Docker 확인 (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": "대상에서 KinD 클러스터 삭제",
"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 확인 (D)",
"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 제거",
"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": "대상에서 Docker 제거",
"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": "처리 완료 보고 --- Telegram & SMS1",
"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": "KinD 클러스터에 Helm 및 Nginx-Ingress 설치",
"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": "대상에 HAProxy 설치 및 포트-80을 KinD로 구성",
"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": "INIT만 수행하는가?",
"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": "TEST만 수행하는가?",
"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": "대상에서 HAProxy 삭제",
"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": "프레임워크에 ROBOT 스크립트 열기",
"type": "n8n-nodes-base.executeCommand",
"position": [
1520,
352
],
"parameters": {
"command": "=cat {{ $json.fileName }}"
},
"typeVersion": 1
},
{
"id": "fcc0449e-fe7f-4788-a37e-263a2fb30f9e",
"name": "호스트에 대상 추가",
"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": "KinD 클러스터에 ArgoCD 설치",
"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 ApplicationSet",
"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": "워크플로우 개요 스티키",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
16
],
"parameters": {
"color": 7,
"width": 450,
"height": 344,
"content": "## Workflow Overview\n\nThis workflow automates the complete lifecycle of Kubernetes testing:\n\nINIT Phase: Sets up Docker, KinD cluster, Helm, Ingress, HAProxy, and ArgoCD on a remote host\n\nTEST Phase: Runs automated Robot Framework tests with browser automation and sends results via Telegram\n\nDESTROY Phase: Cleans up all infrastructure and removes installed components\n\nThe workflow can run the full pipeline automatically or execute individual phases for debugging."
},
"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": "## Trigger Configuration\n\nThis workflow supports three trigger methods:\n\nManual Trigger: Click to execute on-demand for testing and debugging\n\nWebhook: Integrate with GitLab CI/CD for automated execution on commits\n\nSchedule: Run automatically at specified times (default: daily at 1 AM)\n\nConfigure the Schedule Trigger to adjust execution frequency."
},
"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": "## Required Configuration\n\nUpdate these parameters before running:\n\ntarget_host: IP address of your remote server\ntarget_port: SSH port (usually 22)\ntarget_user: SSH username\ntarget_password: SSH password (consider using credentials)\n\nprogress: Starting phase (INIT/TEST/DESTROY)\nprogress_only: false for full pipeline, true for single phase\n\nKIND_CONFIG: Path to KinD config in GitLab\nROBOT_SCRIPT: Path to test script in GitLab\nARGOCD_APPSET: Path to ApplicationSet in GitLab"
},
"typeVersion": 1
},
{
"id": "51a455f4-c8b3-4bcc-88b9-c29127f61b94",
"name": "GitLab 설정 스티키",
"type": "n8n-nodes-base.stickyNote",
"position": [
16,
-464
],
"parameters": {
"color": 7,
"width": 450,
"height": 276,
"content": "## GitLab Integration\n\nThese nodes download configuration files from your GitLab repository:\n\nconfig.yaml: KinD cluster configuration\ntest.robot: Robot Framework test script\ndemo-applicationSet.yaml: ArgoCD applications to deploy\n\nConfigure GitLab OAuth2 credentials in each GitLab node.\nUpdate the owner, repository, and branch settings to match your GitLab setup."
},
"typeVersion": 1
},
{
"id": "7fe8456d-8a20-43bf-9a8d-aa087a7f5857",
"name": "단계 제어 스티키",
"type": "n8n-nodes-base.stickyNote",
"position": [
-80,
-48
],
"parameters": {
"color": 7,
"width": 420,
"height": 348,
"content": "## Phase Control Logic\n\nThe Switch node routes execution based on the progress parameter:\n\nprogress = INIT: Starts infrastructure setup\nprogress = TEST: Runs tests (assumes infrastructure exists)\nprogress = DESTROY: Cleanup phase\n\nprogress_only controls continuation:\nfalse: Automatically progress to next phase (INIT → TEST → DESTROY)\ntrue: Stop after completing current phase\n\nUse progress_only = true for debugging individual phases."
},
"typeVersion": 1
},
{
"id": "18604e04-a554-40be-a167-fc7b4a7fb151",
"name": "Telegram 구성 스티키",
"type": "n8n-nodes-base.stickyNote",
"position": [
2080,
528
],
"parameters": {
"color": 7,
"width": 496,
"height": 332,
"content": "## Telegram Notification\n\nConfigure this node to receive test results:\n\n1. Update chatId with your Telegram chat ID\n2. Configure Telegram API credentials\n3. Results are sent as a compressed archive containing:\n - Test execution logs\n - HTML reports\n - Screenshots from browser tests\n\nTo find your chat ID:\n- Personal: Message your bot and check /getUpdates\n- Group: Add bot to group and check /getUpdates (negative number)"
},
"typeVersion": 1
},
{
"id": "3a9ca7b8-fd69-4953-b93b-dad70e982640",
"name": "INIT 단계 요약 스티키",
"type": "n8n-nodes-base.stickyNote",
"position": [
2608,
-720
],
"parameters": {
"color": 5,
"width": 450,
"height": 332,
"content": "## INIT Phase Summary\n\nThis phase prepares the complete testing infrastructure:\n\n1. Installs sshpass for SSH automation\n2. Installs Docker on remote host\n3. Installs KinD (Kubernetes in Docker)\n4. Creates KinD cluster from downloaded config\n5. Installs Helm and Nginx Ingress Controller\n6. Installs HAProxy for port 80 proxying\n7. Deploys ArgoCD with HTTP access\n8. Applies ApplicationSet to deploy test applications\n\nDuration: 15-25 minutes"
},
"typeVersion": 1
},
{
"id": "32dd93fe-8243-4e28-b28f-6b0703806580",
"name": "TEST 단계 요약 스티키",
"type": "n8n-nodes-base.stickyNote",
"position": [
2608,
288
],
"parameters": {
"color": 2,
"width": 450,
"height": 312,
"content": "## TEST Phase Summary\n\nThis phase executes automated tests:\n\n1. Downloads Robot Framework test script from GitLab\n2. Installs Python, Robot Framework, and Browser library\n3. Installs Chromium browser for web testing\n4. Adds target host to /etc/hosts for DNS resolution\n5. Executes Robot Framework tests with browser automation\n6. Packages test results (logs, reports, screenshots)\n7. Sends results package via Telegram\n\nDuration: 5-10 minutes"
},
"typeVersion": 1
},
{
"id": "0fd0bfbe-12da-49e3-b512-f91eb19422bc",
"name": "DESTROY 단계 요약 스티키",
"type": "n8n-nodes-base.stickyNote",
"position": [
2608,
896
],
"parameters": {
"color": 3,
"width": 450,
"height": 328,
"content": "## DESTROY Phase Summary\n\nThis phase removes all testing infrastructure:\n\n1. Removes HAProxy and cleans configuration\n2. Deletes KinD cluster (automate-tst)\n3. Uninstalls KinD binary\n4. Uninstalls Docker and dependencies\n5. Removes /etc/hosts entries\n6. Sends completion notification via Telegram\n\nLeaves the remote host in a clean state.\n\nDuration: 5-10 minutes"
},
"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": "## Final Notification\n\nConfigure your Telegram credentials in this node.\n\nUpdate the CHAT_ID variable in the command to match your Telegram chat ID.\n\nOptional SMS notifications are commented out - uncomment and configure TextBelt API key if needed."
},
"typeVersion": 1
},
{
"id": "81d81c7d-0501-456c-abf1-e3600e209f27",
"name": "스티키 노트5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1504,
272
],
"parameters": {
"width": 512,
"height": 608,
"content": "## KinD config - sample\n```\nkind: Cluster\napiVersion: kind.x-k8s.io/v1alpha4\nnodes:\n- role: control-plane\n image: kindest/node:v1.30.2\n kubeadmConfigPatches:\n - |\n kind: InitConfiguration\n nodeRegistration:\n kubeletExtraArgs:\n node-labels: \"ingress-ready=true\"\nextraPortMappings:\n - containerPort: 30080\n hostPort: 60080\n listenAddress: \"127.0.0.1\"\n protocol: TCP\n - containerPort: 30443\n hostPort: 60443\n listenAddress: \"127.0.0.1\"\n protocol: TCP\n - containerPort: 6443\n hostPort: 56443\n listenAddress: \"127.0.0.1\"\n protocol: TCP\n extraMounts:\n - hostPath: /mnt\n containerPath: /mnt\n- role: worker\n image: kindest/node:v1.30.2\n extraMounts:\n - hostPath: /mnt\n containerPath: /mnt\n```"
},
"typeVersion": 1
},
{
"id": "26a4e51d-5130-43ee-bc37-0557d1da82a4",
"name": "스티키 노트6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2256,
-432
],
"parameters": {
"width": 1264,
"height": 688,
"content": "## Robot Framework Script - sample\n```\n*** Settings ***\nLibrary Browser\n\n*** Variables ***\n${LOGIN_URL} http://autotest.innersite\n${USERNAME} autotest\n${PASSWORD} autotest\n${BROWSER} chromium\n${USER_AGENT} Mozilla/5.0 (X11; Debian; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.6330.194 Safari/537.36\n\n*** Keywords ***\nOpen the ArgoCD Site in Browser\n Register Keyword To Run On Failure Take Screenshot EMBED\n New Browser browser=${BROWSER} headless=True executablePath=/usr/bin/chromium-browser\n New Context userAgent=${USER_AGENT} ignoreHTTPSErrors=True\n New Page ${LOGIN_URL}\n Sleep 2s\n\nLogin to ArgoCD\n Fill Text input.argo-field:not([type=\"password\"]) ${USERNAME}\n Fill Text input[type=\"password\"].argo-field ${PASSWORD}\n Click button[type=\"submit\"]\n Sleep 2s\n\n*** Test Cases ***\nCheck the ArgoCD Site and Login\n Open the ArgoCD Site in Browser\n ${screenshot_path}= Take Screenshot return_as=path_string fullPage=True\n Login to ArgoCD\n ${screenshot_path2}= Take Screenshot return_as=path_string fullPage=True\n ${current_url}= Get Url\n ${state_file}= Save Storage State\n [Teardown] Close Browser\n Log ${current_url}\n Log ${state_file}\n Log ${screenshot_path}\n Log ${screenshot_path2}\n```"
},
"typeVersion": 1
},
{
"id": "95522c65-f7c6-4c0e-a7e1-ca2edc567542",
"name": "스티키 노트7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2256,
272
],
"parameters": {
"width": 736,
"height": 384,
"content": "## ArgoCD ApplicationSet - sample\n```\napiVersion: argoproj.io/v1alpha1\nkind: Application\nmetadata:\n name: tenant-appsets\n namespace: argocd\n finalizers:\n - resources-finalizer.argocd.argoproj.io\nspec:\n project: default\n source:\n repoURL: https://github.com/xsreality/argocd-applicationset-demo.git\n targetRevision: argocd-applicationsets\n path: applicationsets\n destination:\n server: https://kubernetes.default.svc\n namespace: argocd\n syncPolicy:\n automated: {}\n```"
},
"typeVersion": 1
},
{
"id": "983eea52-5245-46f8-a9c7-faa4b67e48a9",
"name": "스티키 노트8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2256,
672
],
"parameters": {
"width": 736,
"height": 208,
"content": "## Gitlab CI - sample\n```\ntrigger_n8n:\n script:\n - echo \"=== TRIGGER N8N Workflow Webhook ===\"\n - apk add curl\n - curl -X POST http://192.168.1.100:5678/webhook/gitlab-commit -d '{}'\n```"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "69f5b826-e657-4634-8ecc-16f63dddcac3",
"connections": {
"2e5c6a83-4da1-4370-912e-c61e811338ec": {
"main": [
[
{
"node": "3cc7cd5c-96bc-4534-86af-bb46311b120b",
"type": "main",
"index": 0
}
],
[
{
"node": "caab1bc5-d6dc-4634-bf40-08f893075842",
"type": "main",
"index": 0
}
],
[
{
"node": "c8244168-25ad-4704-b1df-863e4a9c7f4c",
"type": "main",
"index": 0
}
]
]
},
"606d3f93-213c-46ca-aa68-fcd50a42f0ca": {
"main": [
[
{
"node": "3b88f0a7-f384-4ad2-bdd4-0aefce909042",
"type": "main",
"index": 0
}
]
]
},
"ec172786-0c6d-42a1-b1b3-4dc613bf2b7c": {
"main": [
[
{
"node": "2e5c6a83-4da1-4370-912e-c61e811338ec",
"type": "main",
"index": 0
}
]
]
},
"6c314b47-9578-4564-8a9c-d208dbe2a6a0": {
"main": [
[
{
"node": "a44d76ec-8070-46e0-8ea0-aa64cde68850",
"type": "main",
"index": 0
}
],
[
{
"node": "19bd956a-395d-4210-9d9d-e4980311403b",
"type": "main",
"index": 0
}
]
]
},
"9f10a302-78e6-4fc1-9e9e-1d07acd71f98": {
"main": [
[
{
"node": "ec172786-0c6d-42a1-b1b3-4dc613bf2b7c",
"type": "main",
"index": 0
}
],
[
{
"node": "19bd956a-395d-4210-9d9d-e4980311403b",
"type": "main",
"index": 0
}
]
]
},
"d3259144-6d39-4a56-be29-907386a2563b": {
"main": [
[
{
"node": "b8079542-34e2-4fae-87aa-04539df7066c",
"type": "main",
"index": 0
}
]
]
},
"3b88f0a7-f384-4ad2-bdd4-0aefce909042": {
"main": [
[
{
"node": "2e5c6a83-4da1-4370-912e-c61e811338ec",
"type": "main",
"index": 0
}
]
]
},
"07caf13e-4f09-43aa-b253-52236dfab04c": {
"main": [
[
{
"node": "a394d031-70b4-4267-a068-b21bae80726d",
"type": "main",
"index": 0
}
]
]
},
"a44d76ec-8070-46e0-8ea0-aa64cde68850": {
"main": [
[
{
"node": "2e5c6a83-4da1-4370-912e-c61e811338ec",
"type": "main",
"index": 0
}
]
]
},
"767099dd-8b50-4b29-bc1d-a35456c3ff32": {
"main": [
[
{
"node": "99091217-262f-4589-b0f4-38ae2ac74026",
"type": "main",
"index": 0
}
]
]
},
"4095dc2e-75df-4f26-8ff6-c2c20691706e": {
"main": [
[
{
"node": "3b88f0a7-f384-4ad2-bdd4-0aefce909042",
"type": "main",
"index": 0
}
]
]
},
"fcc0449e-fe7f-4788-a37e-263a2fb30f9e": {
"main": [
[
{
"node": "7bdbe27a-bb4d-4445-9f98-9885331cee27",
"type": "main",
"index": 0
}
]
]
},
"33907525-976e-48e3-92e6-4b94fc41e05e": {
"main": [
[
{
"node": "09350879-6eae-42af-94f3-f5735dd83473",
"type": "main",
"index": 0
}
],
[
{
"node": "5a8750e9-fd35-4128-9fab-0e3abd75d274",
"type": "main",
"index": 0
}
]
]
},
"f2c9d96f-e5f7-4b0f-815e-26ca8ec76718": {
"main": [
[
{
"node": "cca6856b-6e6f-414d-83ba-3de47ab7afdc",
"type": "main",
"index": 0
}
]
]
},
"5a8750e9-fd35-4128-9fab-0e3abd75d274": {
"main": [
[
{
"node": "09350879-6eae-42af-94f3-f5735dd83473",
"type": "main",
"index": 0
}
]
]
},
"09350879-6eae-42af-94f3-f5735dd83473": {
"main": [
[
{
"node": "9bbc3483-90f4-47dd-9934-8c8db45188e3",
"type": "main",
"index": 0
}
]
]
},
"cfd28b6f-3cfa-4f64-a572-334a7ea27625": {
"main": [
[
{
"node": "6afe2a50-53dc-4647-910a-e7cbac67037e",
"type": "main",
"index": 0
}
]
]
},
"917cbbc3-4900-4914-87ee-ec5691fe5c3e": {
"main": [
[
{
"node": "38397b70-ff06-4295-bf96-ffdc6db9cf26",
"type": "main",
"index": 0
}
],
[
{
"node": "33ec5f41-f4df-42d4-a6db-a1515d43b6a3",
"type": "main",
"index": 0
}
]
]
},
"83511d71-310c-4be4-8765-a9cd40859807": {
"main": [
[
{
"node": "a2224dd5-6460-4064-9b35-a0fb3c87ecc3",
"type": "main",
"index": 0
}
]
]
},
"38397b70-ff06-4295-bf96-ffdc6db9cf26": {
"main": [
[
{
"node": "465c84d3-b0ba-45df-999a-2c29fca75ede",
"type": "main",
"index": 0
}
]
]
},
"6afe2a50-53dc-4647-910a-e7cbac67037e": {
"main": [
[
{
"node": "0b205c63-1bea-4602-b6b6-a0d22c52a012",
"type": "main",
"index": 0
}
]
]
},
"d7967b95-3295-4972-9de1-ee3d7d353d6c": {
"main": [
[
{
"node": "f2c9d96f-e5f7-4b0f-815e-26ca8ec76718",
"type": "main",
"index": 0
}
]
]
},
"fbcd1a7d-1ada-41a7-95ae-9f019e89ce77": {
"main": [
[
{
"node": "d3259144-6d39-4a56-be29-907386a2563b",
"type": "main",
"index": 0
}
]
]
},
"ae9ecbe9-58b7-4080-8496-f5c4763c24e1": {
"main": [
[
{
"node": "e7dc7914-8352-4060-844b-daa561b01aea",
"type": "main",
"index": 0
}
]
]
},
"3cc7cd5c-96bc-4534-86af-bb46311b120b": {
"main": [
[
{
"node": "33907525-976e-48e3-92e6-4b94fc41e05e",
"type": "main",
"index": 0
}
]
]
},
"caab1bc5-d6dc-4634-bf40-08f893075842": {
"main": [
[
{
"node": "edeabedf-e0be-477f-886b-1a54904bd4bf",
"type": "main",
"index": 0
}
]
]
},
"33ec5f41-f4df-42d4-a6db-a1515d43b6a3": {
"main": [
[
{
"node": "38397b70-ff06-4295-bf96-ffdc6db9cf26",
"type": "main",
"index": 0
}
]
]
},
"a394d031-70b4-4267-a068-b21bae80726d": {
"main": [
[
{
"node": "da6a48e3-5fb1-48ee-bd78-b023ff21f995",
"type": "main",
"index": 0
}
]
]
},
"e7dc7914-8352-4060-844b-daa561b01aea": {
"main": [
[
{
"node": "96cbb13c-ff1e-4a07-90c3-71dfb619ff87",
"type": "main",
"index": 0
}
]
]
},
"b8a4e1c5-bb96-4efe-b70e-c7dfd7d83821": {
"main": [
[
{
"node": "1c585a8c-1a89-4f38-8ac2-c54f0d1926b9",
"type": "main",
"index": 0
}
]
]
},
"502870b0-31ba-4bb6-b7ea-87d7d0846249": {
"main": [
[
{
"node": "fbcd1a7d-1ada-41a7-95ae-9f019e89ce77",
"type": "main",
"index": 0
}
]
]
},
"1c585a8c-1a89-4f38-8ac2-c54f0d1926b9": {
"main": [
[
{
"node": "6c314b47-9578-4564-8a9c-d208dbe2a6a0",
"type": "main",
"index": 0
}
]
]
},
"0b205c63-1bea-4602-b6b6-a0d22c52a012": {
"main": [
[
{
"node": "767099dd-8b50-4b29-bc1d-a35456c3ff32",
"type": "main",
"index": 0
}
]
]
},
"cca6856b-6e6f-414d-83ba-3de47ab7afdc": {
"main": [
[
{
"node": "6afe2a50-53dc-4647-910a-e7cbac67037e",
"type": "main",
"index": 0
}
],
[
{
"node": "cfd28b6f-3cfa-4f64-a572-334a7ea27625",
"type": "main",
"index": 0
}
]
]
},
"7bdbe27a-bb4d-4445-9f98-9885331cee27": {
"main": [
[
{
"node": "3d976844-91c3-41c9-9d0a-1c9e8521fa8c",
"type": "main",
"index": 0
}
]
]
},
"edeabedf-e0be-477f-886b-1a54904bd4bf": {
"main": [
[
{
"node": "232d3d9b-ceb6-445e-8de2-1c55ad418e4f",
"type": "main",
"index": 0
}
]
]
},
"c8244168-25ad-4704-b1df-863e4a9c7f4c": {
"main": [
[
{
"node": "917cbbc3-4900-4914-87ee-ec5691fe5c3e",
"type": "main",
"index": 0
}
]
]
},
"99091217-262f-4589-b0f4-38ae2ac74026": {
"main": [
[
{
"node": "ac243f29-13f8-4e18-84b7-f3f53a6f6704",
"type": "main",
"index": 0
}
]
]
},
"465c84d3-b0ba-45df-999a-2c29fca75ede": {
"main": [
[
{
"node": "83511d71-310c-4be4-8765-a9cd40859807",
"type": "main",
"index": 0
}
]
]
},
"a2224dd5-6460-4064-9b35-a0fb3c87ecc3": {
"main": [
[
{
"node": "ae9ecbe9-58b7-4080-8496-f5c4763c24e1",
"type": "main",
"index": 0
}
],
[
{
"node": "e7dc7914-8352-4060-844b-daa561b01aea",
"type": "main",
"index": 0
}
]
]
},
"bb5d31e3-3183-4f17-aa6b-331c5944eab9": {
"main": [
[
{
"node": "9f10a302-78e6-4fc1-9e9e-1d07acd71f98",
"type": "main",
"index": 0
}
]
]
},
"3885b7b3-5528-4407-9934-ecd24e95c24f": {
"main": [
[
{
"node": "5b139746-1c91-431c-b293-2586d8adbbe8",
"type": "main",
"index": 0
}
]
]
},
"9bbc3483-90f4-47dd-9934-8c8db45188e3": {
"main": [
[
{
"node": "f2c9d96f-e5f7-4b0f-815e-26ca8ec76718",
"type": "main",
"index": 0
}
],
[
{
"node": "d7967b95-3295-4972-9de1-ee3d7d353d6c",
"type": "main",
"index": 0
}
]
]
},
"3d976844-91c3-41c9-9d0a-1c9e8521fa8c": {
"main": [
[
{
"node": "07caf13e-4f09-43aa-b253-52236dfab04c",
"type": "main",
"index": 0
}
]
]
},
"96cbb13c-ff1e-4a07-90c3-71dfb619ff87": {
"main": [
[
{
"node": "502870b0-31ba-4bb6-b7ea-87d7d0846249",
"type": "main",
"index": 0
}
],
[
{
"node": "fbcd1a7d-1ada-41a7-95ae-9f019e89ce77",
"type": "main",
"index": 0
}
]
]
},
"da6a48e3-5fb1-48ee-bd78-b023ff21f995": {
"main": [
[
{
"node": "bb5d31e3-3183-4f17-aa6b-331c5944eab9",
"type": "main",
"index": 0
}
]
]
},
"5b139746-1c91-431c-b293-2586d8adbbe8": {
"main": [
[
{
"node": "42e32eaf-f604-400b-8511-a6e4682d318e",
"type": "main",
"index": 0
}
]
]
},
"3eedbba8-b070-4f4c-b752-f997880ac0f7": {
"main": [
[
{
"node": "3b88f0a7-f384-4ad2-bdd4-0aefce909042",
"type": "main",
"index": 0
}
]
]
},
"42e32eaf-f604-400b-8511-a6e4682d318e": {
"main": [
[
{
"node": "b8a4e1c5-bb96-4efe-b70e-c7dfd7d83821",
"type": "main",
"index": 0
}
]
]
},
"ac243f29-13f8-4e18-84b7-f3f53a6f6704": {
"main": [
[
{
"node": "fe9eac0d-749f-4553-89e3-2f831d020761",
"type": "main",
"index": 0
}
]
]
},
"fe9eac0d-749f-4553-89e3-2f831d020761": {
"main": [
[
{
"node": "3885b7b3-5528-4407-9934-ecd24e95c24f",
"type": "main",
"index": 0
}
]
]
},
"232d3d9b-ceb6-445e-8de2-1c55ad418e4f": {
"main": [
[
{
"node": "fcc0449e-fe7f-4788-a37e-263a2fb30f9e",
"type": "main",
"index": 0
}
]
]
}
}
}자주 묻는 질문
이 워크플로우를 어떻게 사용하나요?
위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.
이 워크플로우는 어떤 시나리오에 적합한가요?
고급 - 데브옵스
유료인가요?
이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.
관련 워크플로우 추천
Telegram AI 채널 로봇 - 텍스트 및 이미지 응답을 지원하는 TGPT 생성기
GPT-4와 TGPT를 사용하여 Telegram 채널에서 텍스트 및 이미지 응답 생성
If
Set
Code
+
If
Set
Code
22 노드Vigh Sandor
비밀번호 인증 및 알림 시스템 기반 자동화 Rsync 백업
비밀번호 인증 및 알림 시스템을 갖춘 자동화된 Rsync 백업
If
Set
Manual Trigger
+
If
Set
Manual Trigger
21 노드Vigh Sandor
고급 n8n 워크플로우와 GitHub 동기화
GitHub를 활용한 지능형 변경 감지 자동화 워크플로우 백업
If
N8n
Set
+
If
N8n
Set
38 노드Maksym Brashenko
데브옵스
자동화된 n8n 워크플로우 백업至 GitHub 및 삭제 추적
삭제 추적이 포함된 GitHub 자동화 n8n 워크플로우 백업
If
N8n
Set
+
If
N8n
Set
31 노드Marcial Ambriz
데브옵스
Typebot 플로우와 GitHub 양방향 동기화, Typebot API 사용
Typebot API를 활용한 Typebot 플로우와 GitHub 양방향 동기화
If
Set
Code
+
If
Set
Code
31 노드Marcial Ambriz
데브옵스
Telegram-n8n-지휘관
Telegram 로봇 명령을 통해 n8n 인스턴스를 원격 제어
If
N8n
Set
+
If
N8n
Set
67 노드Arthur Braghetto
데브옵스
워크플로우 정보
난이도
고급
노드 수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에서 보기 →
이 워크플로우 공유