No collectors connected
+Start a collector to see metrics
+diff --git a/.woodpecker.yml b/.woodpecker.yml index 06dd3c6..2114b84 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -1,184 +1,13 @@ -# Woodpecker CI Pipeline -# https://woodpecker-ci.org/docs/usage/pipeline-syntax +# sysmonstm Pipeline -variables: - - &python_image python:3.11-slim - - &docker_image docker:24-dind +when: + - event: push + - event: manual -# Clone settings -clone: - git: - image: woodpeckerci/plugin-git - settings: - depth: 50 - -# Pipeline steps steps: - # ========================================================================== - # Lint and Test - # ========================================================================== - - lint: - image: *python_image + - name: notify + image: alpine commands: - - pip install ruff mypy - - ruff check services/ shared/ - - ruff format --check services/ shared/ - when: - event: [push, pull_request] - - test-shared: - image: *python_image - commands: - - pip install pytest pytest-asyncio redis asyncpg - - pip install -r shared/events/requirements.txt || true - - pytest shared/ -v --tb=short - when: - event: [push, pull_request] - - test-services: - image: *python_image - commands: - - pip install pytest pytest-asyncio grpcio grpcio-tools - - | - for svc in collector aggregator gateway alerts; do - if [ -f "services/$svc/requirements.txt" ]; then - pip install -r "services/$svc/requirements.txt" - fi - done - - pytest services/ -v --tb=short || true - when: - event: [push, pull_request] - - # ========================================================================== - # Build Docker Images - # ========================================================================== - - build-aggregator: - image: *docker_image - commands: - - docker build -t sysmonstm/aggregator:${CI_COMMIT_SHA:0:7} -f services/aggregator/Dockerfile --target production . - - docker tag sysmonstm/aggregator:${CI_COMMIT_SHA:0:7} sysmonstm/aggregator:latest - volumes: - - /var/run/docker.sock:/var/run/docker.sock - when: - event: push - branch: main - - build-gateway: - image: *docker_image - commands: - - docker build -t sysmonstm/gateway:${CI_COMMIT_SHA:0:7} -f services/gateway/Dockerfile --target production . - - docker tag sysmonstm/gateway:${CI_COMMIT_SHA:0:7} sysmonstm/gateway:latest - volumes: - - /var/run/docker.sock:/var/run/docker.sock - when: - event: push - branch: main - - build-collector: - image: *docker_image - commands: - - docker build -t sysmonstm/collector:${CI_COMMIT_SHA:0:7} -f services/collector/Dockerfile --target production . - - docker tag sysmonstm/collector:${CI_COMMIT_SHA:0:7} sysmonstm/collector:latest - volumes: - - /var/run/docker.sock:/var/run/docker.sock - when: - event: push - branch: main - - build-alerts: - image: *docker_image - commands: - - docker build -t sysmonstm/alerts:${CI_COMMIT_SHA:0:7} -f services/alerts/Dockerfile --target production . - - docker tag sysmonstm/alerts:${CI_COMMIT_SHA:0:7} sysmonstm/alerts:latest - volumes: - - /var/run/docker.sock:/var/run/docker.sock - when: - event: push - branch: main - - # ========================================================================== - # Push to Registry - # ========================================================================== - - push-images: - image: *docker_image - commands: - - echo "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USER" --password-stdin "$REGISTRY_URL" - - | - for img in aggregator gateway collector alerts; do - docker tag sysmonstm/$img:latest $REGISTRY_URL/sysmonstm/$img:${CI_COMMIT_SHA:0:7} - docker tag sysmonstm/$img:latest $REGISTRY_URL/sysmonstm/$img:latest - docker push $REGISTRY_URL/sysmonstm/$img:${CI_COMMIT_SHA:0:7} - docker push $REGISTRY_URL/sysmonstm/$img:latest - done - secrets: [registry_user, registry_password, registry_url] - volumes: - - /var/run/docker.sock:/var/run/docker.sock - when: - event: push - branch: main - - # ========================================================================== - # Deploy to EC2 - # ========================================================================== - - deploy-staging: - image: appleboy/drone-ssh - settings: - host: - from_secret: deploy_host - username: - from_secret: deploy_user - key: - from_secret: deploy_key - script: - - cd /home/ec2-user/sysmonstm - - git pull origin main - - docker-compose pull - - docker-compose up -d --remove-orphans - - docker system prune -f - when: - event: push - branch: main - - # ========================================================================== - # Notifications - # ========================================================================== - - notify-success: - image: plugins/webhook - settings: - urls: - from_secret: webhook_url - content_type: application/json - template: | - { - "text": "✅ Build succeeded: ${CI_REPO_NAME}#${CI_BUILD_NUMBER}", - "commit": "${CI_COMMIT_SHA:0:7}", - "branch": "${CI_COMMIT_BRANCH}", - "author": "${CI_COMMIT_AUTHOR}" - } - when: - status: success - event: push - branch: main - - notify-failure: - image: plugins/webhook - settings: - urls: - from_secret: webhook_url - content_type: application/json - template: | - { - "text": "❌ Build failed: ${CI_REPO_NAME}#${CI_BUILD_NUMBER}", - "commit": "${CI_COMMIT_SHA:0:7}", - "branch": "${CI_COMMIT_BRANCH}", - "author": "${CI_COMMIT_AUTHOR}" - } - when: - status: failure - event: push - branch: main + - echo "=== sysmonstm ===" + - echo "Branch: $CI_COMMIT_BRANCH" + - echo "Commit: $CI_COMMIT_SHA" diff --git a/ctrl/standalone/Dockerfile b/ctrl/standalone/Dockerfile new file mode 100644 index 0000000..d3cc8d6 --- /dev/null +++ b/ctrl/standalone/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.11-slim +WORKDIR /app +RUN pip install --no-cache-dir fastapi uvicorn[standard] websockets +COPY main.py . +EXPOSE 8080 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"] diff --git a/ctrl/standalone/README.md b/ctrl/standalone/README.md new file mode 100644 index 0000000..c1bf7b0 --- /dev/null +++ b/ctrl/standalone/README.md @@ -0,0 +1,32 @@ +# sysmonstm standalone deployment + +Minimal standalone gateway for AWS deployment without Redis/TimescaleDB dependencies. + +## Status +- [x] Created standalone main.py with FastAPI + WebSocket +- [x] Created Dockerfile +- [x] Created docker-compose.yml (uses gateway network) +- [ ] Deploy to AWS +- [ ] Update nginx config (sysmonstm.mcrn.ar -> sysmonstm:8080) +- [ ] Create local collector script to push metrics + +## Deploy + +```bash +# On AWS +cd ~/sysmonstm +docker compose up -d --build + +# Add to gateway network +docker network connect gateway sysmonstm +``` + +## Architecture + +- Gateway shows "no collectors connected" until a collector pushes metrics via WebSocket +- Collectors can be run anywhere and connect to wss://sysmonstm.mcrn.ar/ws +- No Redis/TimescaleDB needed - metrics stored in memory only + +## TODO +- Create simple collector script for local machine +- Add basic auth for collector connections diff --git a/ctrl/standalone/docker-compose.yml b/ctrl/standalone/docker-compose.yml new file mode 100644 index 0000000..ba99eb0 --- /dev/null +++ b/ctrl/standalone/docker-compose.yml @@ -0,0 +1,13 @@ +services: + sysmonstm: + build: . + container_name: sysmonstm + restart: unless-stopped + ports: + - "8080:8080" + networks: + - gateway + +networks: + gateway: + external: true diff --git a/ctrl/standalone/main.py b/ctrl/standalone/main.py new file mode 100644 index 0000000..d87326d --- /dev/null +++ b/ctrl/standalone/main.py @@ -0,0 +1,198 @@ +"""Minimal sysmonstm gateway - standalone mode without dependencies.""" + +from fastapi import FastAPI, WebSocket, WebSocketDisconnect +from fastapi.responses import HTMLResponse +import json +import asyncio +from datetime import datetime + +app = FastAPI(title="sysmonstm") + +# Store connected websockets +connections: list[WebSocket] = [] +# Store latest metrics from collectors +machines: dict = {} + +HTML = """ + + +
+ + +Start a collector to see metrics
+