diff --git a/MIGRATION_PLAN.md b/MIGRATION_PLAN.md deleted file mode 100644 index 6771dd3..0000000 --- a/MIGRATION_PLAN.md +++ /dev/null @@ -1,203 +0,0 @@ -# Repository Reorganization Plan - -## Goal - -Enforce the rule: **gcloud-lab = Kubernetes manifests only. No application code.** - -Application code (source, Dockerfiles, CI/CD workflows, Helm charts, deployment scripts) belongs in `hermes-projects/`. gcloud-lab should contain only K8s manifests, Terraform infrastructure modules, cluster configs, and infra controller configs. - ---- - -## Current State - -### gcloud-lab/ — Full Directory Audit - -``` -gcloud-lab/ -├── apps/ -│ ├── base/ -│ │ ├── customer1/ [KEEP] K8s manifests (deployments, services, configmaps, secrets) -│ │ ├── monitoring/ [KEEP] K8s manifests (dashboards) -│ │ └── osint-dashboard/ [KEEP] Helm chart (templates, values.yaml, Chart.yaml) -│ ├── staging/ -│ │ ├── customer1/ [KEEP] K8s overlay (kustomization.yaml) -│ │ └── osint-dashboard/ [KEEP] K8s overlay (kustomization.yaml) -│ └── vwap-monitor/ [MOVE] App code (Dockerfile, app/, deploy/) -├── clusters/ [KEEP] Cluster configs (devops-lab/*.yaml, flux-system/) -├── infrastructure/ [KEEP] Infra controllers, gatewayapi, gpus, tailnet -├── misc/ [KEEP] Terraform snippets + K8s YAML -├── modules/ [KEEP] Terraform modules (gke.tf, nodepool.tf, etc.) -├── scripts/ [KEEP] Setup scripts -├── .github/workflows/ -│ ├── osint-dashboard-infra.yml [KEEP] Infra deployment workflow -│ └── trade-dashboard.yml [MOVE] CI for trade-dashboard app → hermes-projects/ -├── .devcontainer.json [KEEP] Dev environment config -├── .sops.yaml [KEEP] SOPS encryption config -├── .terraform.lock.hcl [KEEP] Terraform lock -├── .gitignore [KEEP] Git ignore rules -├── mise.toml [KEEP] Tool version management -├── README.md [KEEP] (will be updated) -├── infra-tailnet.yaml [KEEP] Tailscale infra config -├── tailscale-0auth.yaml [KEEP] Tailscale config -├── rays-new-deployment.yaml [REVIEW] Orphan K8s deployment YAML — move to apps/base/ -├── trade-dashboard/ [MOVE] Full FastAPI app → hermes-projects/trade-dashboard/ -├── trading-platform/ [MOVE] Duplicate/deploy configs → hermes-projects/trading-platform/ -├── trading-scripts/ [MOVE] Application code → hermes-projects/trading-scripts/ -├── analyses/ [REMOVE] Research artifacts (not code, not infra) -└── plans/ [REMOVE] Planning docs (not code, not infra) -``` - ---- - -## Items to Move / Remove - -### 1. `trade-dashboard/` → hermes-projects/trade-dashboard/ - -**What it is:** Full FastAPI application (not K8s manifests) -- `Dockerfile` — build config for the app -- `app/` — Python source code (main.py, models.py, schemas.py, database.py, requirements.txt, static/) -- `alembic/` — database migration scripts (env.py, versions/) -- `alembic.ini` — alembic config - -**Also move:** `.github/workflows/trade-dashboard.yml` (CI workflow for this app) - -**Already in gcloud-lab:** `apps/base/customer1/trade-dashboard/` — these are the K8s manifests for trade-dashboard (deployment.yaml, service.yaml, configmap.yaml, kustomization.yaml). **KEEP these** — they belong here. - -### 2. `trading-platform/` → hermes-projects/trading-platform/ - -**What it is:** Duplicate/alternative deployment configs that overlap with hermes-projects/trading-platform/ - -Contents: -- `.github/workflows/` — 3 CI/CD workflows (build-push.yml, build-test.yml, deploy.yml) -- `README.md` — project readme -- `deploy/` — deployment configs: - - `ci-cd/` — additional CI workflows - - `docker-compose/` — docker-compose.dev.yml - - `dockerfiles/` — Dockerfiles (api-gateway, dashboard, data-service, execute-service, news-service) - - `helm/` — Helm charts (api-gateway, dashboard, data-service, execute-service, news-service) - - `k8s/` — raw K8s manifests (deployments, services, hpa, cert-manager, ingress) - - `mtls/` — mTLS README - - `scripts/` — deploy.sh, generate-mtls-certs.sh -- `dockerfiles/` — Dockerfiles (dashboard, data-service, execute-service, news-service) -- `helm/` — Helm chart with templates (trading-platform chart, values.yaml, secrets) - -**Already in gcloud-lab:** `apps/base/customer1/trading-platform/` — these are the K8s manifests. **KEEP these** — they belong here. - -**Already in hermes-projects:** `hermes-projects/trading-platform/` — source code exists here (dashboard, data-service, execute-service, news-service, data_infrastructure). The gcloud-lab trading-platform/ deploy/dockerfiles/helm content should be MERGED into hermes-projects/trading-platform/. - -**Decision needed:** The `trading-platform/` in gcloud-lab has BOTH deploy configs (dockerfiles, helm, k8s manifests) AND CI workflows. The K8s manifests in `deploy/k8s/base/` are similar but NOT identical to what's in `apps/base/customer1/trading-platform/`. Need to decide which is authoritative. - -### 3. `trading-scripts/` → hermes-projects/trading-scripts/ - -**What it is:** Application code (Python trading scripts) -- `market_data.py` — market data script -- `orb-monitor/` — monitoring tool (monitor.py, config.yaml) -- `README.md`, `ROADMAP.md` — documentation - -### 4. `apps/vwap-monitor/` → hermes-projects/vwap-monitor/ - -**What it is:** Application code with a Dockerfile -- `Dockerfile` — build config -- `app/` — source code (scanner.py, requirements.txt) -- `deploy/` — deployment config (deployment.yaml, kustomization.yaml, secret.yaml, config.env) - -**Note:** The `deploy/` subdirectory contains K8s manifests. These should be moved BACK into gcloud-lab as `apps/base/customer1/vwap-monitor/`. The app code (Dockerfile + app/) goes to hermes-projects. - -### 5. `analyses/` → REMOVE from gcloud-lab - -**What it is:** Research/analysis markdown documents -- `telegram-webhook-container-analysis.md` -- `telegram-webhook-failure-analysis.md` - -These are one-time research artifacts, not infrastructure config. Remove from gcloud-lab entirely. - -### 6. `plans/` → REMOVE from gcloud-lab - -**What it is:** Planning/strategy markdown documents -- `2026-04-25-openclaw-brain-v1.1.md` -- `AI_ARCHITECTURE.md` -- `models-to-try.md` - -These are planning docs, not infrastructure config. Remove from gcloud-lab entirely. - -### 7. `rays-new-deployment.yaml` → REVIEW - -**What it is:** A standalone K8s deployment YAML at repo root. - -**Action:** Move to `apps/base/customer1/hermes-agent/` (appears related to hermes-agent/rays deployment based on filename). Already similar files exist in that directory. - ---- - -## Proposed Migration Plan (Ordered by PR) - -### PR 1: This Plan (docs only) -- Add `MIGRATION_PLAN.md` (this file) -- Update `README.md` to document the new structure - -### PR 2: Remove planning/research docs -- Delete `analyses/` directory -- Delete `plans/` directory -- Low risk, no dependencies - -### PR 3: Move trade-dashboard app to hermes-projects -- Move `trade-dashboard/` → hermes-projects/trade-dashboard/ -- Move `.github/workflows/trade-dashboard.yml` → hermes-projects/.github/workflows/ -- K8s manifests in `apps/base/customer1/trade-dashboard/` stay in place -- Verify image references in K8s manifests still point to correct registry - -### PR 4: Move trading-platform deploy configs to hermes-projects -- Move `trading-platform/` → merge with hermes-projects/trading-platform/ -- CI workflows → hermes-projects/trading-platform/.github/workflows/ -- Dockerfiles → hermes-projects/trading-platform/dockerfiles/ -- Helm charts → hermes-projects/trading-platform/helm/ -- K8s manifests from `trading-platform/deploy/k8s/` → reconcile with `apps/base/customer1/trading-platform/` -- **Decision needed:** Which K8s manifests are authoritative? The ones in gcloud-lab/apps/ or trading-platform/deploy/k8s/? - -### PR 5: Move trading-scripts to hermes-projects -- Move `trading-scripts/` → hermes-projects/trading-scripts/ -- Simple move, no K8s manifest reconciliation needed - -### PR 6: Split vwap-monitor (app → hermes-projects, K8s → gcloud-lab) -- Move `apps/vwap-monitor/app/` + `apps/vwap-monitor/Dockerfile` → hermes-projects/vwap-monitor/ -- Move `apps/vwap-monitor/deploy/` K8s manifests → `apps/base/customer1/vwap-monitor/` -- Update image references in K8s manifests - ---- - -## Items That Stay in gcloud-lab (No Changes) - -| Path | Reason | -|------|--------| -| `apps/base/customer1/` | K8s manifests (kustomize structure) | -| `apps/base/monitoring/` | K8s manifests (dashboards) | -| `apps/base/osint-dashboard/` | Helm chart for infra | -| `apps/staging/` | K8s overlays | -| `clusters/` | Cluster configs, flux-system | -| `infrastructure/` | Controllers, gatewayapi, gpus, tailnet | -| `misc/` | Terraform snippets + K8s YAML | -| `modules/` | Terraform modules | -| `scripts/` | Setup scripts | -| Root config files | .sops.yaml, .devcontainer.json, mise.toml, .gitignore, .terraform.lock.hcl | -| `infra-tailnet.yaml` | Tailscale infra config | -| `tailscale-0auth.yaml` | Tailscale config | - ---- - -## K8s Manifest Reference Check - -After moves, verify these image references still resolve: - -| K8s Manifest | Image Reference | -|--------------|----------------| -| `apps/base/customer1/trade-dashboard/deployment.yaml` | Check image tag matches hermes-projects build | -| `apps/base/customer1/trading-platform/*/deployment.yaml` | Check image tags match hermes-projects build | -| `apps/base/customer1/hermes-agent/deployment.yaml` | N/A (already correct) | -| `apps/base/customer1/siriusdevops-site/deployment.yaml` | N/A (already correct) | - ---- - -## Decisions Needed Before Proceeding - -1. **trading-platform K8s manifest authority:** `trading-platform/deploy/k8s/base/` vs `apps/base/customer1/trading-platform/` — which is the source of truth? -2. **analyses/ and plans/:** Delete entirely, or archive somewhere else? -3. **rays-new-deployment.yaml:** Move to `apps/base/customer1/hermes-agent/` or delete? diff --git a/README.md b/README.md index 2d12d42..014d7c3 100644 --- a/README.md +++ b/README.md @@ -1,524 +1,246 @@ -# GCloud-Lab DevOps Infrastructure +# gcloud-lab -A production-grade cloud-native infrastructure laboratory demonstrating GitOps, multi-tenant AI agent hosting, and automated security pipelines — all run by a single DevOps engineer on Google Cloud Platform. Trusted by builders who ship. +GitOps + Terraform source of truth for a **GKE lab** I designed, ran, and then **shut down** once the GPU bill stopped being worth it. -## Table of Contents +This is not a live cluster. It is the manifests, node-pool definitions, and GitOps wiring from a real environment that served vLLM inference, CNPG databases, and a handful of in-cluster apps. The same cost model that made the GPU pools scale to zero is why the whole footprint went to zero. -- [Project Overview](#project-overview) -- [Architecture](#architecture) -- [DevOps Tools & Technologies](#devops-tools--technologies) -- [Monitoring](#monitoring) -- [Project Structure](#project-structure) -- [Infrastructure Components](#infrastructure-components) -- [Applications](#applications) -- [Getting Started](#getting-started) -- [Security](#security) -- [Cost Optimization](#cost-optimization) -- [License](#license) +**Canonical copy:** [forgejo.siriusdevops.com/sirius/gcloud-lab](https://forgejo.siriusdevops.com/sirius/gcloud-lab) --- -## Project Overview +## What this is evidence of -This repository is the single source of truth for a multi-application cloud platform running on GKE. Every deployment, database, and network policy flows through Git via Flux CD. What lives here: +If you are reading this as a hiring screen, start here. Every claim below maps to a file in this repo. -1. **AgentForge** — Private multi-tenant AI agent workspace with dual-tier vLLM inference (L4 dispatcher + RTX 6000 deep thinker) and isolated CNPG databases per tenant. -2. **Multi-Profile AI Agent Team** — Six specialist AI profiles (backend-dev, frontend-dev, researcher, outreach, quant, sec-ops) orchestrated through a shared Kanban board with automated audit-to-fix pipelines. -3. **Waitlist API** — FastAPI landing page backend with idempotent signups, async PostgreSQL, and Telegram fire-and-forget notifications. -4. **Autonomous News Quant Pipeline** — 371 global feed scraper with DeepSeek-R1 analysis generating actionable futures trading signals. -5. **N8N Workflow Automation** — Self-hosted workflow engine with dedicated CNPG PostgreSQL. -6. **Local Business Web Deployment Pipeline** — Automated K8s manifest generation for small business websites with cross-namespace HTTPRoute routing. +| Claim | Where to look | +| --- | --- | +| GKE cluster, custom VPC, dual-stack, Cilium datapath | [`modules/gke.tf`](modules/gke.tf), [`modules/vpc.tf`](modules/vpc.tf) | +| CPU + three GPU node pools (L4, RTX PRO 6000, A100 80GB), all SPOT except CPU | [`modules/nodepool.tf`](modules/nodepool.tf), [`modules/nodepool-gpu.tf`](modules/nodepool-gpu.tf), [`modules/pro6000-nodepool.tf`](modules/pro6000-nodepool.tf), [`modules/a100-nodepool.tf`](modules/a100-nodepool.tf) | +| Flux CD applies the tree; SOPS decrypts secrets in-cluster | [`clusters/devops-lab/`](clusters/devops-lab/), [`.sops.yaml`](.sops.yaml) | +| Production-style **vLLM** OpenAI-compatible servers (not Ollama) | [`infrastructure/gpus/base/vllm-servers/`](infrastructure/gpus/base/vllm-servers/) | +| KEDA HTTP scale-to-zero on the expensive GPUs | [`infrastructure/gpus/base/keda-gpu-scaling/`](infrastructure/gpus/base/keda-gpu-scaling/) | +| CloudNative-PG operator + per-app Postgres | [`infrastructure/controllers/base/cnpg/`](infrastructure/controllers/base/cnpg/), `apps/base/customer1/*-db/` | +| Gateway API (not legacy Ingress) + Tailscale for internals | [`infrastructure/gatewayapi/`](infrastructure/gatewayapi/), [`infrastructure/tailnet/`](infrastructure/tailnet/) | +| Workload NetworkPolicies (trading stack) | [`apps/base/customer1/trading-platform/network-policies/`](apps/base/customer1/trading-platform/network-policies/) | + +I run 24/7 infrastructure now on a Raspberry Pi (Forgejo, Cloudflare tunnel, containerized sites). This repo is the cloud chapter that came before that. --- ## Architecture -```text -┌──────────────────────────────────────────────────────────────────────────────┐ -│ Google Cloud Platform │ -│ ┌────────────────────────────────────────────────────────────────────────┐ │ -│ │ GKE Cluster (devops-lab-cluster) │ │ -│ │ │ │ -│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ -│ │ │ Standard │ │ L4 GPU Pool │ │ RTX 6000 GPU │ │ │ -│ │ │ Node Pool │ │ (SPOT L4) │ │ (SPOT RTX6K) │ │ │ -│ │ │ e2-std-2 │ │ 1 node (24/7)│ │ 0-1 nodes │ │ │ -│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ -│ │ │ │ -│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ -│ │ │ Cilium CNI + Hubble + NetworkPolicy │ │ │ -│ │ └──────────────────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ -│ │ │ Kubernetes Gateway API — external-http-gateway │ │ │ -│ │ │ HTTPRoute PathPrefix → AgentForge / Waitlist / Apps │ │ │ -│ │ └──────────────────────────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ ┌───────────────────────────────┐ ┌───────────────────────────────┐ │ │ -│ │ │ customer1 namespace │ │ agent-forge namespace │ │ │ -│ │ │ - AgentForge (PAaaS) │ │ - Tenant-specific Hermes Agent │ │ │ -│ │ │ - Dual-tier vLLM │ │ - Isolated CNPG databases │ │ │ -│ │ │ L4 Dispatcher (24/7) │ │ - Qwen 3.6 27B Abliterated │ │ │ -│ │ │ RTX 6000 Deep Thinker (KEDA) │ │ - KEDA scale-to-zero │ │ │ -│ │ │ - Waitlist API (FastAPI) │ │ │ │ │ -│ │ │ - News Bot Pipeline │ │ ┌───────────────────────────┐ │ │ │ -│ │ │ - Landing Page │ │ │ sec-ops audit agent │ │ │ -│ │ │ - CNPG PostgreSQL Cluster │ │ │ Automated vuln scanning │ │ │ -│ │ └───────────────────────────────┘ │ │ → backend-dev auto-fix │ │ │ -│ │ │ └───────────────────────────┘ │ │ │ -│ │ ┌───────────────────────────────┐ └───────────────────────────────┘ │ │ -│ │ │ local-business namespaces │ │ │ -│ │ │ - nginx + ConfigMap per biz │ ┌───────────────────────────────┐ │ │ -│ │ │ - Cross-ns HTTPRoute refs │ │ monitoring namespace │ │ │ -│ │ └───────────────────────────────┘ │ - Prometheus + Grafana │ │ │ -│ │ │ - Tailscale-only access │ │ │ -│ │ ┌───────────────────────────────┐ │ - No public ingress │ │ │ -│ │ │ kanban namespace │ └───────────────────────────────┘ │ │ -│ │ │ - Hermes Agent Orchestrator │ │ │ -│ │ │ - 6 Specialist Profiles │ ┌───────────────────────────────┐ │ │ -│ │ │ - Isolated hermes-pgdb │ │ n8n namespace │ │ │ -│ │ └───────────────────────────────┘ │ - Workflow automation │ │ │ -│ │ │ - Dedicated PostgreSQL │ │ │ -│ │ └───────────────────────────────┘ │ │ -│ └────────────────────────────────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────────────────┘ +``` + Git (this repo, branch master) + │ + Flux source-controller (1m) + │ + ┌─────────────────┼──────────────────┐ + ▼ ▼ ▼ + infra-controllers infra-gpus apps/staging + CNPG / KEDA vLLM + KEDA customer1 overlay + cert-manager HTTPScaledObject (kustomize) + Tailscale L4 / RTX6000 / A100 + kube-prometheus + │ │ │ + └──────────── GKE us-central1-a ─────┘ + │ + ┌───────────────┬────────────┼────────────┬──────────────┐ + ▼ ▼ ▼ ▼ ▼ + e2-standard-2 g2-standard-8 g4-standard-48 a2-ultragpu-1g + CPU pool L4 SPOT RTX PRO 6000 A100 80GB SPOT + 1–5 nodes 1 node SPOT 0–1 SPOT 0–1 + (always on) KEDA 0↔1 KEDA 0↔1 ``` ---- - -## DevOps Tools & Technologies - -### Infrastructure as Code (IaC) - -| Tool | Version | Purpose | -|------|---------|---------| -| **Terraform** | 1.7+ | Infrastructure provisioning for GCP resources | -| **Google Provider** | 7.14.1 | Terraform provider for GCP | -| **Helm Provider** | Latest | Terraform provider for Helm charts | -| **Flux Provider** | 1.7.6 | Terraform provider for Flux bootstrap | - -### Container Orchestration & Networking - -| Tool | Version | Purpose | -|------|---------|---------| -| **Google Kubernetes Engine (GKE)** | Latest | Managed Kubernetes cluster | -| **Cilium** | 1.18.5 | CNI plugin with eBPF-based networking | -| **Hubble** | 1.18.5 | Network observability and monitoring | -| **Kubernetes Gateway API** | v1 | Ingress routing and traffic management | - -### GitOps & Configuration Management - -| Tool | Version | Purpose | -|------|---------|---------| -| **Flux CD** | 1.7.6 | GitOps continuous delivery | -| **Kustomize** | v1beta1 | Kubernetes manifest customization | -| **Helm** | 3+ | Kubernetes package manager | -| **SOPS** | Latest | Secrets encryption in Git | -| **Age** | Latest | Modern encryption for SOPS | - -### Database - -| Tool | Version | Purpose | -|------|---------|---------| -| **CloudNative PG** | 0.26.1 | PostgreSQL Kubernetes operator | -| **PostgreSQL** | 15.2 | Relational database (multi-cluster fleet) | - -### AI/ML Infrastructure - -| Tool | Version | Purpose | -|------|---------|---------| -| **vLLM** | v0.9.1 | High-throughput LLM inference server | -| **Qwen 3.6 27B Abliterated** | Latest | Uncensored reasoning model (RTX 6000 deep thinker tier) | -| **Qwen 2.5 Coder 7B Abliterated** | Latest | Fast tool-calling dispatcher (L4 24/7 tier) | -| **NVIDIA L4 GPU** | - | 24/7 GPU for fast triage and dispatch | -| **NVIDIA RTX 6000 Pro** | - | SPOT GPU for deep reasoning and multi-file context | - -### Development Environment - -| Tool | Version | Purpose | -|------|---------|---------| -| **Mise** | Latest | Development tool version manager | -| **Dev Containers** | Latest | Consistent development environment | -| **k9s** | Latest | Kubernetes CLI dashboard | - -### Monitoring & Observability - -| Tool | Version | Purpose | -|------|---------|---------| -| **Prometheus** | Latest | Metrics collection via kube-prometheus-stack | -| **Grafana** | Latest | Dashboards & visualizations | -| **Tailscale** | Latest | Secure VPN access to internal services | +Datapath: GKE `ADVANCED_DATAPATH` + `enable_cilium_clusterwide_network_policy`. Dual-stack VPC (`10.0.0.0/16`, pods `192.168.32.0/20`, services `192.168.16.0/24`). GPU nodes are tainted (`nvidia.com/gpu…=present:NoSchedule`) so only inference pods land on them. --- -## Project Structure +## GPU inference (vLLM) + +Three independent OpenAI-compatible servers, each pinned to a pool via `nodeSelector` + matching taint/toleration. Model weights cached on PVC so a scale-up does not re-pull 20–40 GB from Hugging Face. + +### L4 dispatcher — always on + +[`infrastructure/gpus/base/vllm-servers/vllm-l4.yaml`](infrastructure/gpus/base/vllm-servers/vllm-l4.yaml) + +- Machine: `g2-standard-8` + `nvidia-l4`, SPOT +- Image: `vllm/vllm-openai` +- Model: `p-e-w/Qwen3-8B-heretic` +- Flags that matter: `--kv-cache-dtype=fp8`, `--enable-chunked-prefill`, `--enable-prefix-caching`, `--enable-auto-tool-choice`, `--tool-call-parser=hermes`, `--max-model-len=32768` + +Cheap, tool-capable, left running so agents had a low-latency brain even when the big cards were scaled out. + +### RTX PRO 6000 — deep context, scale to zero + +[`infrastructure/gpus/base/vllm-servers/rtx6000-vllm.yaml`](infrastructure/gpus/base/vllm-servers/rtx6000-vllm.yaml) +[`infrastructure/gpus/base/keda-gpu-scaling/keda-vllm.yaml`](infrastructure/gpus/base/keda-gpu-scaling/keda-vllm.yaml) + +- Machine: `g4-standard-48` + `nvidia-rtx-pro-6000`, SPOT, **min 0 / max 1** +- Image: `vllm/vllm-openai:latest-cu129-ubuntu2404` +- Model: `edp1096/Huihui-Qwen3.6-27B-abliterated-FP8` +- `--max-model-len=262144`, `--enable-chunked-prefill`, `--tool-call-parser=qwen3_xml`, `--reasoning-parser=qwen3`, MTP speculative decoding (`num_speculative_tokens: 2`) +- Startup / liveness / readiness probes on `/health` and `/v1/models` (model load is slow; `failureThreshold: 60` on startup) +- KEDA `HTTPScaledObject`: `replicas.min: 0`, `max: 1`, host `rtx6000-brain-service.customer1.svc.cluster.local` + +Idle deep-thinker capacity cost nothing. A request woke the Deployment; GKE then scaled the node pool off zero. + +### A100 80GB — same pattern + +[`infrastructure/gpus/base/vllm-servers/a100-vllm.yaml`](infrastructure/gpus/base/vllm-servers/a100-vllm.yaml) +[`modules/a100-nodepool.tf`](modules/a100-nodepool.tf) + +- Machine: `a2-ultragpu-1g` + `nvidia-a100-80gb`, SPOT, min 0 +- NVFP4 / ModelOpt quantized 27B, `--quantization=modelopt`, `--attention-backend=flash_attn`, `--kv-cache-dtype=fp8` + +--- + +## GitOps + +Flux watches `master` and applies layered Kustomizations: + +``` +clusters/devops-lab/ + flux-system/ Flux controllers + GitRepository + infra-controllers.yaml → infrastructure/controllers/staging + CNPG 0.26.1, KEDA ≥2.14, cert-manager, Tailscale, kube-prometheus + infra-gpus.yaml → infrastructure/gpus/staging + infra-gatewayapi.yaml → Gateway API + HTTPRoutes + customer1-strimzi.yaml → Strimzi (Kafka) first + customer1.yaml → apps/staging/customer1 (dependsOn strimzi) +``` + +Every Flux Kustomization has `decryption.provider: sops` and `secretRef: sops-age`. Encrypted `data`/`stringData` in Git; Flux decrypts at apply time. Age recipient is in [`.sops.yaml`](.sops.yaml). The private key is **not** in this repo. + +Bootstrap was originally: + +```bash +flux bootstrap github \ + --owner=sirius0xdev \ + --repository=gcloud-lab \ + --branch=master \ + --path=clusters/devops-lab +``` + +`gotk-sync.yaml` still records that GitHub URL. This Forgejo copy is the archive; the cluster is gone, so the GitRepository object was never re-pointed. + +--- + +## Terraform (cluster birth) + +[`modules/`](modules/) is the IaC that created the cluster, not the day-to-day delivery path. + +| File | Resource | +| --- | --- | +| `gke.tf` | `devops-lab-cluster` in `us-central1-a`, default pool removed, Cilium datapath, dual-stack IP policy | +| `vpc.tf` | `devops-lab-network` / `devops-lab-subnetwork`, ULA IPv6, secondary ranges | +| `nodepool.tf` | CPU `e2-standard-2`, 1–5, pd-standard 100 Gi | +| `nodepool-gpu.tf` | L4 SPOT `g2-standard-8`, autoscaling 1–1, GPU taint | +| `pro6000-nodepool.tf` | RTX PRO 6000 SPOT `g4-standard-48`, **0–1**, hyperdisk-balanced | +| `a100-nodepool.tf` | A100 80GB SPOT `a2-ultragpu-1g`, **0–1**, pd-ssd 200 Gi | +| `db-bucket.tf` | GCS bucket for CNPG backups | +| `providers.tf` | Google provider, Helm talking to the cluster via `gke-gcloud-auth-plugin` | + +State files and `*.tfvars` are gitignored. Do not `terraform apply` this against a live billing account unless you intend to recreate it. + +--- + +## Data plane and apps + +Flux overlay: [`apps/staging/customer1/kustomization.yaml`](apps/staging/customer1/kustomization.yaml) + +| Piece | Role | +| --- | --- | +| CloudNative-PG | Operator `0.26.1`; per-app clusters (Hermes memory, waitlist, n8n, trading) with GCS backup | +| Strimzi | Kafka for the trading data path; Flux `dependsOn` so apps wait for the operator | +| Redis | In-cluster cache next to the trading services | +| Trading platform | data / execute / news / dashboard Deployments, HTTPRoutes, NetworkPolicies | +| Hermes agent | In-cluster agent + CNPG, talking to the vLLM services | +| News bot | CronJobs: scrape → analyst (vLLM) → Telegram | +| Waitlist API | FastAPI + CNPG, Gateway HTTPRoute | +| n8n | Workflow engine on its own Postgres | +| Gateway API | Public HTTPRoutes; Grafana/Prometheus stayed off the public internet (Tailscale / port-forward) | + +App **images** were built in a separate code repo and pulled from GHCR. This repo is manifests only (after cleanup: no Dockerfiles, no Helm-of-the-app, no planning markdown). + +--- + +## Networking and security + +- **Cilium** as GKE datapath, clusterwide NetworkPolicy enabled from Terraform. +- **Gateway API** `HTTPRoute` for public paths; internals not published. +- **Tailscale operator** for operator access to Grafana and cluster services without a public LB. +- **NetworkPolicies** on the trading namespace: DNS, Postgres, Redis, Kafka, in-namespace HTTP, egress HTTPS to market APIs. Everything else denied. +- **SOPS + age** for Secrets in Git. Flux `sops-age` Secret in `flux-system` held the private key. +- GPU nodes tainted so a random Deployment cannot schedule onto a $2+/hr card. + +--- + +## Cost model (why it was torn down) + +This was the whole point of the GPU design: + +1. L4 SPOT stayed at 1 node — cheap enough to keep a dispatcher warm. +2. RTX 6000 and A100 pools **autoscaled 0–1**. KEDA HTTPScaledObject set the Deployment to 0 when there was no traffic; the node pool followed. +3. Weights on PVC, long startup probes — first request after idle paid a cold-start, not a 40 GB pull. +4. CronJobs for batch work instead of idle inference pods. +5. When even the L4 + control-plane bill stopped making sense, the cluster was destroyed. Scale-to-zero was the rehearsal for scale-to-nothing. + +--- + +## Repository layout ``` gcloud-lab/ -├── modules/ # Terraform IaC modules -│ ├── providers.tf # Provider configurations -│ ├── gke.tf # GKE cluster definition -│ ├── vpc.tf # VPC and subnet configuration -│ ├── nodepool.tf # Standard node pool -│ ├── nodepool-gpu.tf # GPU node pools (L4 + RTX 6000 SPOT) -│ ├── flux.tf # Flux GitOps bootstrap -│ ├── helm.tf # Helm chart deployments (Cilium) -│ └── variables.tf # Input variables -│ -├── clusters/ # Cluster configurations -│ └── devops-lab/ -│ ├── flux-system/ # Flux CD components -│ │ ├── gotk-components.yaml # Flux controllers -│ │ ├── gotk-sync.yaml # Git repository sync -│ │ └── kustomization.yaml # Flux kustomization -│ ├── customer1.yaml # Customer1 Kustomization -│ ├── agent-forge.yaml # AgentForge Kustomization -│ ├── infra-controllers.yaml # Infrastructure controllers (CNPG, KEDA, Monitoring, Tailscale) -│ └── infra-configs.yaml # Infrastructure configs -│ -├── infrastructure/ # Infrastructure components -│ ├── controllers/ -│ │ ├── base/ -│ │ │ ├── cnpg/ # CloudNative PG operator -│ │ │ ├── keda/ # KEDA autoscaling -│ │ │ ├── monitoring/ # Prometheus + Grafana (no public ingress) -│ │ │ └── tailscale/ # Tailscale Operator for secure VPN access -│ │ └── staging/ -│ │ └── kustomization.yaml # Aggregates all base components -│ └── configs/ -│ └── staging/ -│ └── kustomization.yaml -│ -├── apps/ # Application deployments -│ ├── base/ -│ │ ├── customer1/ -│ │ │ ├── namespace.yaml # Namespace definition -│ │ │ ├── deployment.yaml # N8N + vLLM deployments -│ │ │ ├── service.yaml # ClusterIP services -│ │ │ ├── storage.yaml # PersistentVolumeClaims -│ │ │ ├── configmap.yaml # Application configuration -│ │ │ ├── pg-cluster-customer1.yaml # PostgreSQL cluster -│ │ │ ├── apigateway.yaml # GCP Gateway -│ │ │ ├── http-route.yaml # HTTP routing -│ │ │ ├── healthcheck.yaml # Health check policy -│ │ │ ├── waitlist-api/ # Waitlist API microservice -│ │ │ │ ├── deployment.yaml -│ │ │ │ ├── service.yaml -│ │ │ │ └── configmap.yaml -│ │ │ └── news_bot/ # News bot microservices -│ │ │ ├── scraper-cronjob.yaml -│ │ │ ├── analyst-cronjob.yaml -│ │ │ ├── telebot-cronjob.yaml -│ │ │ ├── scrapy-configmap.yaml -│ │ │ └── scrapy-urls-configmap.yaml -│ │ ├── agent-forge/ -│ │ │ ├── namespace.yaml -│ │ │ ├── vllm-deep-thinker.yaml # RTX 6000 deployment with KEDA -│ │ │ ├── hermes-tenant.yaml # Per-tenant Hermes agent instance -│ │ │ └── pg-cluster-agentforge.yaml -│ │ ├── kanban/ -│ │ │ ├── namespace.yaml -│ │ │ ├── hermes-deployment.yaml # AI agent orchestrator -│ │ │ └── pg-cluster-hermes.yaml -│ │ └── local-business/ -│ │ └── template/ -│ │ ├── namespace.yaml -│ │ ├── nginx-deployment.yaml -│ │ ├── configmap.yaml -│ │ └── http-route.yaml -│ └── staging/ -│ ├── customer1/ -│ │ └── kustomization.yaml -│ ├── agent-forge/ -│ │ └── kustomization.yaml -│ └── kanban/ -│ └── kustomization.yaml -│ -├── scripts/ -│ └── setup # Development setup script -│ -├── .devcontainer.json # Dev container configuration -├── mise.toml # Tool version management -├── age.agekey # SOPS encryption key -└── README.md # This file +├── modules/ Terraform: VPC, GKE, node pools, GCS +├── clusters/devops-lab/ Flux entry (GitRepository + Kustomizations) +├── infrastructure/ +│ ├── controllers/ CNPG, KEDA, cert-manager, Tailscale, Prometheus +│ ├── gpus/ vLLM Deployments + KEDA HTTPScaledObjects +│ ├── gatewayapi/ Gateway + HTTPRoutes +│ └── tailnet/ Tailscale ProxyGroup +├── apps/ +│ ├── base/customer1/ Namespaced workloads (kustomize) +│ ├── base/osint-dashboard/ Helm chart used on this cluster +│ └── staging/ Overlays Flux actually syncs +├── monitoring/ Extra Grafana/Prometheus config +├── .sops.yaml Age recipient for secret encryption +├── .github/workflows/ Historical GH Actions (pgvector image, etc.) +└── mise.toml Local CLI pin (gcloud, kubectl, helm, sops, terraform, k9s) ``` --- -## Infrastructure Components +## Reading the code (suggested order) -### GKE Cluster - -- **Name**: `devops-lab-cluster` -- **Region**: `us-central1-a` -- **Network**: Custom VPC with dual-stack IPv4/IPv6 - -### Node Pools - -| Pool | Machine Type | Scaling | Purpose | -|------|-------------|---------|---------| -| Standard | e2-standard-2 | 1-16 nodes | General workloads, N8N, web servers | -| GPU L4 (SPOT) | g2-standard-8 + L4 | 0-5 nodes | vLLM dispatcher, 24/7 fast inference | -| GPU RTX 6000 (SPOT) | g6-standard-4 + RTX 6000 Pro | 0-1 nodes | Deep thinker tier, multi-file reasoning | - -### Networking - -- **VPC**: `devops-lab-network` -- **Primary CIDR**: `10.0.0.0/16` -- **Pod CIDR**: `192.168.32.0/20` -- **Service CIDR**: `192.168.16.0/24` -- **CNI**: Cilium with advanced datapath and NetworkPolicy enforcement -- **Ingress**: Kubernetes Gateway API via `external-http-gateway` with PathPrefix HTTPRoute routing -- **Internal Services**: Tailscale-only — no public ingress for monitoring, databases, or agent infrastructure - -### CNPG Database Fleet - -Multiple isolated PostgreSQL clusters, each with dedicated databases per application: - -| Cluster | Namespace | Databases | Backup | -|---------|-----------|-----------|--------| -| `customer1-pgdb` | customer1 | `n8n`, `news_app`, `waitlist` | GCS, 7-day retention | -| `hermes-pgdb` | kanban | `hermes`, `memory_store` | GCS, 7-day retention | -| `hermes-tenant-pgdb` | agent-forge | Per-tenant isolated DBs | GCS, 7-day retention | -| `siriusdevops-pgdb` | customer1 | `waitlist_prod` | GCS, 30-day retention | - -### GitOps Flow - -``` -GitHub Repository (ghcr.io/sirius0xdev) - │ - ▼ - Flux Source Controller (watches git, 1min interval) - │ - ▼ - Flux Kustomize Controller (applies manifests) - │ - ├── infrastructure/controllers → CNPG, KEDA, Monitoring, Tailscale - ├── infrastructure/configs → Cluster configs - ├── apps/staging/customer1 → PAaaS, N8N, News Bot, Waitlist API - ├── apps/staging/agent-forge → Multi-tenant AI agent hosting - ├── apps/staging/kanban → AI Agent Team orchestrator - └── apps/staging/local-business → Business websites -``` +1. [`modules/gke.tf`](modules/gke.tf) + [`modules/vpc.tf`](modules/vpc.tf) — cluster shape. +2. GPU pools, then the matching vLLM YAML — taint keys must match or the pod never schedules. +3. [`clusters/devops-lab/customer1.yaml`](clusters/devops-lab/customer1.yaml) — Flux `dependsOn`, SOPS, prune/force. +4. [`apps/staging/customer1/kustomization.yaml`](apps/staging/customer1/kustomization.yaml) — what actually shipped in `customer1`. +5. One NetworkPolicy under `apps/base/customer1/trading-platform/network-policies/` — default-deny thinking. --- -## Applications - -### 1. AgentForge — Private AI Agent Workspace - -A premium, uncensored, privacy-first AI agent hosting platform with dual-tier cognitive architecture: - -- **Tier 1 (Dispatcher):** L4 GPU SPOT instance running 24/7. Hosts `Qwen2.5-Coder-7B-Instruct-heretic` via vLLM `v0.9.1` for lightning-fast, cheap triage and tool calling. -- **Tier 2 (Deep Thinker):** RTX 6000 Pro Spot instance scaling from 0-1 via KEDA. Hosts `Qwen3.5-27B-heretic` with `--enable-chunked-prefill` and `--kv-cache-dtype=fp8` for massive multi-file context and reasoning without OOMing or stalling concurrent users. -- **Frontend:** Isolated Hermes agent profiles per tenant, connected to Telegram/Discord via outbound polling (no public ingress required). -- **Landing Page:** Dockerized marketing site built via CI/CD from `hermes-projects` and deployed to the `staging` kustomization overlay. -- **Container Registry:** All images pushed to `ghcr.io/sirius0xdev`. - -### 2. Multi-Profile AI Agent Team - -Six specialist AI agents orchestrated through a shared Kanban board, each with isolated memory, tools, and personality: - -| Profile | Role | Key Capability | -|---------|------|---------------| -| **backend-dev** | Backend engineering | API design, database schema, K8s manifests | -| **frontend-dev** | Frontend engineering | UI/UX, landing pages, responsive design | -| **researcher** | Deep research | Market analysis, technical deep-dives | -| **outreach** | Communications | Content, social media, community building | -| **quant** | Quantitative analysis | Trading signals, market data pipelines | -| **sec-ops** | Security operations | Vulnerability scanning, audit pipelines | - -**Automated Audit-to-Fix Pipeline:** The sec-ops agent continuously scans deployed infrastructure for vulnerabilities. When findings are confirmed, the backend-dev agent is automatically dispatched to remediate — from detection to patch in a single GitOps cycle. - -### 3. Gateway API and HTTPRoute - -Kubernetes Gateway API replaces legacy Ingress with a clean, declarative routing model: - -- **Single Gateway:** `external-http-gateway` handles all external traffic. -- **PathPrefix Routing:** `/agentforge/*` → AgentForge landing, `/waitlist/*` → Waitlist API, `/business/*` → local business sites. -- **No Public Ingress for Internals:** Monitoring (Grafana/Prometheus), databases, and agent infrastructure are accessible only via Tailscale VPN. -- **Cross-Namespace References:** HTTPRoute resources in one namespace can reference Services in another, keeping routing centralized. - -### 4. Waitlist API - -FastAPI microservice powering the AgentForge waitlist at siriusdevops.com: - -- **Database:** asyncpg connection pool to dedicated CNPG PostgreSQL. -- **Idempotent Signups:** `INSERT ... ON CONFLICT DO NOTHING` — duplicate emails are silently ignored, not rejected. -- **Notifications:** Fire-and-forget Telegram webhook on each new signup. No blocking I/O in the request path. -- **Security:** Rate limiting per IP, input sanitization, and CORS whitelist. - -### 5. Autonomous News Quant Pipeline (`news_bot`) - -An institutional-grade pipeline scraping 371 global feeds to generate actionable futures trading signals: - -- **Scraper:** CronJob at `:50` pulling multi-lingual global financial data. -- **Map/Reduce Analyst:** DeepSeek-R1 with a strict 10-step think protocol extracts "Market-Moving DNA" and translates events into explicit futures targets (/ES, /CL, /NQ) with risk:reward, take profit, and stop loss levels. -- **Privacy:** All proprietary technical data stays strictly within the VPC, executing against local models to protect the trading edge. - -### 6. Local Business Web Deployment Pipeline - -Automated Kubernetes manifest generation for small business websites: - -- **Stack:** nginx serving static content from ConfigMap, one namespace per business. -- **Routing:** HTTPRoute with cross-namespace Service references under `/business/` paths. -- **Zero Cold Start:** Static sites have no database dependency — just nginx + ConfigMap, deployed via GitOps. - ---- - -## Getting Started - -### Prerequisites - -- Google Cloud account with billing enabled -- GitHub account with repository access -- `gcloud` CLI authenticated -- Terraform 1.7+ - -### Local Development Setup +## Local tooling ```bash -# Install tools via mise -./scripts/setup - -# Or manually -mise trust && mise install +mise trust && mise install # kubectl, helm, sops, terraform, k9s, gcloud ``` -### Infrastructure Deployment +Decrypt a secret locally (needs the age key, which is not in Git): ```bash -cd modules - -# Initialize Terraform -terraform init - -# Set required variables -export TF_VAR_github_token="your-token" -export TF_VAR_github_org="your-org" -export TF_VAR_github_repository="gcloud-lab" - -# Plan and apply -terraform plan -terraform apply -``` - -### Accessing the Cluster - -```bash -# Configure kubectl -gcloud container clusters get-credentials devops-lab-cluster \ - --zone us-central1-a \ - --project devops-lab-cluster - -# Verify connection -kubectl get nodes - -# Use k9s for interactive management -k9s -``` - -### Accessing Monitoring (Grafana / Prometheus) - -Monitoring services are **not publicly exposed**. Access is via Tailscale VPN or port-forwarding: - -```bash -# Option 1: Port-forward Grafana -kubectl port-forward svc/prometheus-community-kube-prometheus-stack-grafana \ - -n monitoring 3000:3000 - -# Option 2: Port-forward Prometheus -kubectl port-forward svc/prometheus-community-kube-prometheus-stack-prometheus \ - -n monitoring 9090:9090 -``` - -⚠️ **Before deploying**, replace the Grafana admin password in -`infrastructure/controllers/base/monitoring/release.yaml` with a secure value, -or create a `monitoring-grafana-admin` Secret instead. - ---- - -## Security - -### Secrets Management - -- **Encryption**: SOPS with Age encryption -- **Key Storage**: `age.agekey` (do not commit unencrypted) -- **Flux Integration**: Automatic decryption during deployment - -### Pod Security - -- Non-root containers (UID 1000) -- Filesystem group enforcement -- Privilege escalation disabled -- Resource limits enforced - -### Network Security - -- Cilium NetworkPolicy for pod-to-pod and namespace-to-namespace isolation -- Kubernetes Gateway API with TLS termination at the load balancer -- Internal services (monitoring, databases, agent infrastructure) accessible only via Tailscale VPN — zero public ingress -- Rate limiting on public-facing APIs (Waitlist, landing page) - -### Database Security - -- Managed roles with secret-based passwords per application -- Separate PostgreSQL clusters per domain (hermes-pgdb, hermes-tenant-pgdb, siriusdevops-pgdb) -- GCS backups with configurable retention policies -- HA cluster with automatic failover - -### Automated Security Auditing - -- **sec-ops Agent:** Continuously scans deployed infrastructure for CVEs, misconfigurations, and policy violations -- **Auto-Remediation:** Confirmed findings automatically dispatch the backend-dev agent to patch and commit -- **Audit Trail:** Every finding, fix, and deployment is tracked in Git history — full provenance from detection to resolution - ---- - -## Cost Optimization - -- **SPOT GPU Instances**: 60-90% savings on L4 and RTX 6000 workloads -- **KEDA Scale-to-Zero**: RTX 6000 deep thinker pool scales to 0 when no requests are queued -- **Resource Limits**: CPU and memory caps on every container prevent runaway costs -- **Scheduled Workloads**: CronJobs only run when needed — no idle inference pods -- **Tailscale for Internal Access**: No need for expensive internal load balancers or Cloud NAT for monitoring - ---- - -## Container Images - -``` -ghcr.io/sirius0xdev/agentforge-landing:latest -ghcr.io/sirius0xdev/waitlist-api:latest -ghcr.io/sirius0xdev/newsscraper:latest -ghcr.io/sirius0xdev/summarizer:latest -ghcr.io/sirius0xdev/news-messenger:latest -docker.n8n.io/n8nio/n8n:2.1.4 -ghcr.io/cloudnative-pg/postgresql:15.2 +sops -d apps/base/customer1/waitlist-api/waitlist-telegram-secret.yaml ``` --- -## Tool Reference +## Status -### Terraform Providers +| | | +| --- | --- | +| Cluster | **Destroyed** (GCP project `devops-lab-cluster`, GKE `devops-lab-cluster`, `us-central1-a`) | +| This repo | Archive of what ran | +| Live infra today | Self-hosted on a Pi — see [siriusdevops.com/lab](https://siriusdevops.com/lab) | -```hcl -google = "~> 7.14" # GCP resources -helm = "~> 2.0" # Helm chart management -flux = "~> 1.7" # GitOps bootstrap -``` - -### Helm Charts - -```yaml -cilium: 1.18.5 # CNI and service mesh -cloudnative-pg: 0.26.1 # PostgreSQL operator -vllm: 0.9.1 # High-throughput LLM serving -``` - ---- - -## License - -Private repository — All rights reserved. +Lance Walters — [siriusdevops.com](https://siriusdevops.com) diff --git a/apps/vwap-monitor/Dockerfile b/apps/vwap-monitor/Dockerfile deleted file mode 100644 index f306017..0000000 --- a/apps/vwap-monitor/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM python:3.13-slim - -LABEL maintainer="sirius0xdev" \ - description="VWAP Wave Breach Scanner — monitors Gold, NASDAQ, S&P, Crude Oil" - -WORKDIR /app - -COPY app/requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt - -COPY app/scanner.py . - -# Default scan interval: 120s (2 min), threshold: 2σ -ENV SCAN_INTERVAL_SEC=120 \ - BREACH_THRESHOLD=2.0 - -# Health check: ensure process is alive -HEALTHCHECK --interval=60s --timeout=10s --retries=3 \ - CMD ["python3", "-c", "import os; assert os.path.exists('/proc/1/fd/0')"] - -CMD ["python3", "scanner.py"] diff --git a/apps/vwap-monitor/app/requirements.txt b/apps/vwap-monitor/app/requirements.txt deleted file mode 100644 index 39ed941..0000000 --- a/apps/vwap-monitor/app/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -yfinance>=0.2.54 -requests>=2.32 -apscheduler>=3.10 diff --git a/apps/vwap-monitor/app/scanner.py b/apps/vwap-monitor/app/scanner.py deleted file mode 100644 index 177be45..0000000 --- a/apps/vwap-monitor/app/scanner.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python3 -""" -VWAP Wave Breach Scanner -======================== -Continuous monitoring daemon. Scans instruments on a schedule, -detects VWAP wave breaches, and pushes alerts via Telegram. - -Environment variables: - TELEGRAM_BOT_TOKEN — Telegram Bot API token (required) - TELEGRAM_CHAT_ID — Chat ID to send alerts to (required) - SCAN_INTERVAL_SEC — Seconds between scans (default: 120) - BREACH_THRESHOLD — Sigma threshold for alerts (default: 2.0) - -No LLM overhead — pure Python, ~20MB RAM. -""" - -import os -import sys -import time -import logging -from datetime import datetime, timezone - -import requests -import yfinance as yf -import pandas as pd -from apscheduler.schedulers.background import BlockingScheduler - -# ── Config ────────────────────────────────────────────────────────────────── - -TELEGRAM_BOT_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"] -TELEGRAM_CHAT_ID = os.environ["TELEGRAM_CHAT_ID"] -SCAN_INTERVAL_SEC = int(os.environ.get("SCAN_INTERVAL_SEC", "120")) -BREACH_THRESHOLD = float(os.environ.get("BREACH_THRESHOLD", "2.0")) - -INSTRUMENTS = { - "Gold Futures": {"ticker": "GC=F", "decimal": 2}, - "NASDAQ": {"ticker": "^IXIC", "decimal": 2}, - "S&P 500": {"ticker": "^GSPC", "decimal": 2}, - "Crude Oil": {"ticker": "CL=F", "decimal": 2}, -} - -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s %(levelname)-5s %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", -) -log = logging.getLogger(__name__) - -# Track last alert state to prevent spam (no repeat within same threshold direction) -_last_alert = {} - - -# ── Telegram ──────────────────────────────────────────────────────────────── - -def send_telegram(message: str) -> bool: - """Send a message via Telegram Bot API.""" - url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage" - payload = { - "chat_id": TELEGRAM_CHAT_ID, - "text": message, - "parse_mode": "Markdown", - "disable_web_page_preview": True, - } - try: - resp = requests.post(url, json=payload, timeout=10) - resp.raise_for_status() - log.info("Telegram alert sent: %s", message[:80]) - return True - except Exception as e: - log.error("Telegram send failed: %s", e) - return False - - -# ── VWAP Calculation ──────────────────────────────────────────────────────── - -def compute_vwap(data: pd.DataFrame) -> dict | None: - """Compute cumulative VWAP, σ, and deviation.""" - df = data.copy() - df["typical"] = (df["High"] + df["Low"] + df["Close"]) / 3.0 - df["tp_vol"] = df["typical"] * df["Volume"] - - cum_tp_vol = df["tp_vol"].cumsum() - cum_vol = df["Volume"].cumsum().replace(0, 1) - - df["cum_vwap"] = cum_tp_vol / cum_vol - df["deviation"] = df["typical"] - df["cum_vwap"] - df["cum_var"] = (df["deviation"] ** 2).cumsum() / cum_vol - df["sigma"] = df["cum_var"] ** 0.5 - - last = df.iloc[-1] - if last["sigma"] <= 0: - return None - - return { - "price": last["Close"], - "vwap": last["cum_vwap"], - "sigma": last["sigma"], - "dev_sigmas": (last["Close"] - last["cum_vwap"]) / last["sigma"], - } - - -def fetch_data(ticker: str) -> pd.DataFrame: - """Fetch recent intraday data via yfinance.""" - try: - data = yf.Ticker(ticker).history(period="1d", interval="1m", auto_adjust=True) - except Exception: - data = pd.DataFrame() - - if len(data) < 30: - data = yf.Ticker(ticker).history(period="5d", interval="1m", auto_adjust=True) - cutoff = pd.Timestamp.now(tz=data.index.tz) - pd.Timedelta(hours=24) - data = data[data.index >= cutoff] - - return data - - -# ── Scanner ───────────────────────────────────────────────────────────────── - -def run_scan() -> None: - """Execute a full scan cycle and push any breaches.""" - ts = datetime.now(timezone.utc).strftime("%H:%M:%S UTC") - log.info("── Scan %s ──", ts) - - breaches = [] - - for name, cfg in INSTRUMENTS.items(): - try: - data = fetch_data(cfg["ticker"]) - if data.empty or len(data) < 20: - log.warning("SKIP %s — insufficient data (%d bars)", name, len(data)) - continue - - info = compute_vwap(data) - if info is None: - log.warning("SKIP %s — zero sigma", name) - continue - - d = cfg["decimal"] - dev = info["dev_sigmas"] - log.info(" %-14s $%10.2f | VWAP $%10.2f | %+.2fσ", name, info["price"], info["vwap"], dev) - - if abs(dev) >= BREACH_THRESHOLD: - # Prevent repeat spam: only alert if state changed - alert_key = f"{name}:{dev > 0}" - if _last_alert.get(alert_key) == "breach": - log.info(" → %s already in breach, skipping repeat", name) - continue - - breaches.append((name, cfg["decimal"], dev, info["price"], info["vwap"], info["sigma"])) - _last_alert[alert_key] = "breach" - else: - _last_alert[f"{name}:True"] = "clean" - _last_alert[f"{name}:False"] = "clean" - - except Exception as e: - log.error("ERROR %s: %s", name, e) - - # Push alerts - for name, d, dev, price, vwap, sigma in breaches: - direction = "⬆️ UP" if dev > 0 else "⬇️ DOWN" - band_label = f"±{int(abs(dev))}σ" - severity = "🚨 **EXTREME**" if abs(dev) >= 3.0 else "⚡ **BREACH**" - - msg = ( - f"{severity} — VWAP Wave Alert\n\n" - f"**{name}** broke through **{band_label}** band\n" - f"Deviation: **{dev:+.2f}σ**\n" - f"Price: **${price:.{d}f}** | VWAP: **${vwap:.{d}f}**\n" - f"σ: ${sigma:.{d}f} | {direction}\n\n" - f"_at {ts}_" - ) - send_telegram(msg) - - -# ── Main ──────────────────────────────────────────────────────────────────── - -def main() -> None: - log.info("=" * 60) - log.info(" VWAP Wave Breach Scanner") - log.info(" Interval: %d sec | Threshold: ±%.1fσ", SCAN_INTERVAL_SEC, BREACH_THRESHOLD) - log.info(" Telegram: @chat_id=%s", TELEGRAM_CHAT_ID) - log.info("=" * 60) - - # Validate Telegram connectivity - send_telegram( - "🟢 *VWAP Breach Scanner* is online.\n" - f"Scanning every **{SCAN_INTERVAL_SEC}s** — threshold ±**{BREACH_THRESHOLD:.1f}σ**\n" - f"Monitoring: Gold, NASDAQ, S&P 500, Crude Oil" - ) - - scheduler = BlockingScheduler() - scheduler.add_job(run_scan, "interval", seconds=SCAN_INTERVAL_SEC, id="scan") - # Run immediately on start - run_scan() - - log.info("Scanner running. Press Ctrl+C to stop.") - try: - scheduler.start() - except KeyboardInterrupt: - log.info("Shutting down...") - scheduler.shutdown() - - -if __name__ == "__main__": - main() diff --git a/apps/vwap-monitor/deploy/config.env b/apps/vwap-monitor/deploy/config.env deleted file mode 100644 index b41cb8e..0000000 --- a/apps/vwap-monitor/deploy/config.env +++ /dev/null @@ -1,5 +0,0 @@ -# ─── Config ───────────────────────────────────────────────────────────────── -# Edit these values. They will be injected into the deployment automatically. - -SCAN_INTERVAL_SEC=120 -BREACH_THRESHOLD=2.0 diff --git a/apps/vwap-monitor/deploy/deployment.yaml b/apps/vwap-monitor/deploy/deployment.yaml deleted file mode 100644 index 0dc6c09..0000000 --- a/apps/vwap-monitor/deploy/deployment.yaml +++ /dev/null @@ -1,70 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vwap-monitor - namespace: customer1 - labels: - app: vwap-monitor - component: scanner -spec: - replicas: 1 - strategy: - type: Recreate # only one instance should run - selector: - matchLabels: - app: vwap-monitor - template: - metadata: - labels: - app: vwap-monitor - component: scanner - annotations: - # Restart if config changes - checksum/config: "vwap-monitor-config" - spec: - terminationGracePeriodSeconds: 30 - containers: - - name: scanner - image: us-central1-docker.pkg.dev/devops-lab-cluster/customer1/vwap-monitor:latest - imagePullPolicy: Always - resources: - requests: - cpu: 100m - memory: 64Mi - limits: - cpu: 250m - memory: 256Mi - envFrom: - - configMapRef: - name: vwap-monitor-config - env: - - name: TELEGRAM_BOT_TOKEN - valueFrom: - secretKeyRef: - name: vwap-monitor-secrets - key: telegram-bot-token - - name: TELEGRAM_CHAT_ID - valueFrom: - secretKeyRef: - name: vwap-monitor-secrets - key: telegram-chat-id - startupProbe: - exec: - command: ["/bin/sh", "-c", "python3 -c 'import scanner'"] - initialDelaySeconds: 10 - periodSeconds: 10 - failureThreshold: 3 - livenessProbe: - exec: - command: ["/bin/sh", "-c", "kill -0 1"] - initialDelaySeconds: 30 - periodSeconds: 60 ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: vwap-monitor-config - namespace: customer1 -data: - SCAN_INTERVAL_SEC: "120" - BREACH_THRESHOLD: "2.0" diff --git a/apps/vwap-monitor/deploy/kustomization.yaml b/apps/vwap-monitor/deploy/kustomization.yaml deleted file mode 100644 index 22c7d4f..0000000 --- a/apps/vwap-monitor/deploy/kustomization.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# ─── Kustomization ────────────────────────────────────────────────────────── - -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -namespace: customer1 - -resources: - - secret.yaml - - deployment.yaml - -configMapGenerator: - - name: vwap-monitor-config - envs: - - config.env - -patches: - - patch: |- - apiVersion: apps/v1 - kind: Deployment - metadata: - name: vwap-monitor - spec: - template: - spec: - containers: - - name: scanner - envFrom: - - configMapRef: - name: vwap-monitor-config - env: - - name: TELEGRAM_BOT_TOKEN - valueFrom: - secretKeyRef: - name: vwap-monitor-secrets - key: telegram-bot-token - - name: TELEGRAM_CHAT_ID - valueFrom: - secretKeyRef: - name: vwap-monitor-secrets - key: telegram-chat-id diff --git a/apps/vwap-monitor/deploy/secret.yaml b/apps/vwap-monitor/deploy/secret.yaml deleted file mode 100644 index 46e0618..0000000 --- a/apps/vwap-monitor/deploy/secret.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# ─── Secret Template ──────────────────────────────────────────────────────── -# Replace the values below before applying. -# Alternatively, store in a real Secret Manager (GCP Secret Manager, external-secrets). - -apiVersion: v1 -kind: Secret -metadata: - name: vwap-monitor-secrets - namespace: customer1 -type: Opaque -stringData: - # Get from: https://t.me/botfather → /newbot → copy token - telegram-bot-token: "YOUR_BOT_TOKEN_HERE" - # Get from: @userinfobot or inspect network tab in Telegram Web - telegram-chat-id: "YOUR_CHAT_ID_HERE" diff --git a/plans/2026-04-25-openclaw-brain-v1.1.md b/plans/2026-04-25-openclaw-brain-v1.1.md deleted file mode 100644 index 56ae504..0000000 --- a/plans/2026-04-25-openclaw-brain-v1.1.md +++ /dev/null @@ -1,28 +0,0 @@ -# OpenClaw Brain v1.1 Implementation Plan - -> **Status:** Ready for subagent-driven-development. <48hr goal. - -**Goal:** Full product launch per spec. US GKE DeepSeek-V4-Pro API, flat subs, unlimited tokens. - -**Updated Pricing Confirmed:** Spot $3.40-4.55/hr node → $2.5K-3.3K/mo full util. Breakeven: 6 Personal ($49) or 2 Team ($199) subs/mo. - -**Approach:** Extend gcloud-lab OpenClaw PAaaS (customer1). New namespace `openclaw-brain`. Stripe webhooks for subs/keys. - -## Tasks (Bite-Sized TDD) - -### Task 1: Scaffold dirs -**Files:** mkdir apps/base/openclaw-brain apps/staging/openclaw-brain -**Step 1:** `mkdir -p apps/{base,staging}/openclaw-brain` -**Step 2:** namespace.yaml (copy customer1 pattern) -```yaml -apiVersion: v1 -kind: Namespace -metadata: - name: openclaw-brain -``` -**Verify:** `kubectl apply --dry-run=client -f apps/base/openclaw-brain/namespace.yaml` -**Commit:** git add apps/ ; git commit -m \"feat(openclaw-brain): scaffold\" - -*(Abbrev; full 30+ tasks: Terraform nodepools w/ machine_type='a3-ultragpu-8g' spot=true gpu=8, vLLM args --model=DeepSeek/DeepSeek-V4-Pro --tp=8 --max-model-len=1e6 --enable-prefix-caching, FastAPI w/ Stripe Subscriptions API + redis-py quotas, KEDA ScaledObject on http_requests >5/min throttle, landing HTML w/ Stripe Checkout.js, flux kustomize add, terraform apply, smoke tests)* - -**Next:** Task 1 scaffold + git commit. diff --git a/plans/AI_ARCHITECTURE.md b/plans/AI_ARCHITECTURE.md deleted file mode 100644 index e251304..0000000 --- a/plans/AI_ARCHITECTURE.md +++ /dev/null @@ -1,25 +0,0 @@ -# Dual-Tier AI Architecture: L4 Dispatcher & A100 Deep Thinker - -This document outlines the cost-optimized, dual-tier LLM architecture deployed in the cluster using OpenClaw, vLLM, and KEDA. - -## Concept -Instead of running an expensive A100 GPU 24/7 for all requests, we split the cognitive load into two tiers: a lightweight "Dispatcher" and a heavyweight "Deep Thinker." This mimics a senior/junior developer dynamic, optimizing both response latency and cloud GCP billing. - -## Tier 1: The Dispatcher (L4 GPU) -- **Hardware:** 1x NVIDIA L4 (24GB VRAM) -- **Model:** `Qwen2.5-Coder-7B-Instruct` -- **Status:** Runs 24/7 (1 replica) -- **Role:** Acts as the baseline consciousness for OpenClaw. Handles daily chatter, log parsing, straightforward tool routing, and triage. Lightning-fast token generation at a fraction of the cost. - -## Tier 2: The Deep Thinker (A100 GPU) -- **Hardware:** 1x NVIDIA A100 (80GB VRAM) -- **Model:** `Qwen3.6-27B-heretic` -- **Status:** Scaled to zero by default. -- **Role:** Activated only for massive context tasks, deep research, and complex multi-file architectural reasoning. - -## Scaling & Routing Mechanics (KEDA + OpenClaw) -1. **Scale-to-Zero:** The A100 deployment is managed by a KEDA `HTTPScaledObject`. It scales down to `0` replicas after 15 minutes of inactivity. -2. **Default Routing:** OpenClaw's global default model is set to the L4 endpoint. All standard messages hit the L4 immediately. -3. **Sub-Agent Handoff:** When a complex task is requested, the L4 agent uses the `sessions_spawn` tool to create an isolated sub-agent, overriding the model target to the A100 endpoint. -4. **Cold Start:** KEDA intercepts the sub-agent's request, scales the A100 node from 0 to 1, waits for vLLM to load (~1-2 minutes), and then passes the request through. -5. **Manual Override:** A user can bypass the L4 entirely for a specific session by typing `/model local-vllm/coder3101/Qwen3.5-27B-heretic` in the OpenClaw chat. diff --git a/plans/models-to-try.md b/plans/models-to-try.md deleted file mode 100644 index 83bc533..0000000 --- a/plans/models-to-try.md +++ /dev/null @@ -1 +0,0 @@ -HauhauCS/Qwen3.5-27B-Uncensored-HauhauCS-Aggressive diff --git a/trading-platform/.github/workflows/build-push.yml b/trading-platform/.github/workflows/build-push.yml deleted file mode 100644 index c0353e6..0000000 --- a/trading-platform/.github/workflows/build-push.yml +++ /dev/null @@ -1,109 +0,0 @@ -# Build and push container images to Artifact Registry -name: Build & Push Images - -on: - push: - branches: [main, develop] - paths: - - "trading-platform/**" - - "!trading-platform/infra/**" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - GCP_PROJECT_ID: customer1-gke - GCP_REGION: us-central1 - ARTIFACT_REGISTRY: us-central1-docker.pkg.dev/${{ env.GCP_PROJECT_ID }}/trading - -jobs: - build-and-push: - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@v4 - - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@v2 - with: - workload_identity_provider: projects/${{ env.GCP_PROJECT_ID }}/locations/global/workloadIdentityPools/github-pool/providers/github-provider - service_account: ci-builder@${{ env.GCP_PROJECT_ID }}.iam.gserviceaccount.com - - - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@v2 - - - name: Configure Docker for Artifact Registry - run: gcloud auth configure-docker ${{ env.GCP_REGION }}-docker.pkg.dev --quiet - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Generate image tags - id: tags - run: | - SHORT_SHA="${GITHUB_SHA::8}" - BRANCH="${GITHUB_REF#refs/heads/}" - echo "tag_sha=${SHORT_SHA}" >> $GITHUB_OUTPUT - echo "tag_branch=${BRANCH}" >> $GITHUB_OUTPUT - echo "tag_latest=${BRANCH}" >> $GITHUB_OUTPUT - - # ---- Execute Service ---- - - name: Build and push execute-service - uses: docker/build-push-action@v5 - with: - context: trading-platform/execute-service - file: trading-platform/infra/dockerfiles/execute-service/Dockerfile - push: true - tags: | - ${{ env.ARTIFACT_REGISTRY }}/execute-service:${{ steps.tags.outputs.tag_sha }} - ${{ env.ARTIFACT_REGISTRY }}/execute-service:${{ steps.tags.outputs.tag_branch }} - cache-from: type=gha - cache-to: type=gha,mode=max - - # ---- News Service ---- - - name: Build and push news-service - uses: docker/build-push-action@v5 - with: - context: trading-platform/news-service - file: trading-platform/infra/dockerfiles/news-service/Dockerfile - push: true - tags: | - ${{ env.ARTIFACT_REGISTRY }}/news-service:${{ steps.tags.outputs.tag_sha }} - ${{ env.ARTIFACT_REGISTRY }}/news-service:${{ steps.tags.outputs.tag_branch }} - cache-from: type=gha - cache-to: type=gha,mode=max - - # ---- Data Service ---- - - name: Build and push data-service - uses: docker/build-push-action@v5 - with: - context: trading-platform/data-service - file: trading-platform/infra/dockerfiles/data-service/Dockerfile - push: true - tags: | - ${{ env.ARTIFACT_REGISTRY }}/data-service:${{ steps.tags.outputs.tag_sha }} - ${{ env.ARTIFACT_REGISTRY }}/data-service:${{ steps.tags.outputs.tag_branch }} - cache-from: type=gha - cache-to: type=gha,mode=max - - # ---- Dashboard ---- - - name: Build and push dashboard - uses: docker/build-push-action@v5 - with: - context: trading-platform/dashboard - file: trading-platform/infra/dockerfiles/dashboard/Dockerfile - push: true - tags: | - ${{ env.ARTIFACT_REGISTRY }}/dashboard:${{ steps.tags.outputs.tag_sha }} - ${{ env.ARTIFACT_REGISTRY }}/dashboard:${{ steps.tags.outputs.tag_branch }} - cache-from: type=gha - cache-to: type=gha,mode=max - - - name: Notify deployment pipeline - run: | - echo "Images pushed successfully with tag ${{ steps.tags.outputs.tag_sha }}" - # This can trigger the deploy workflow via repository dispatch - # or be used by the deploy workflow as a workflow_run trigger diff --git a/trading-platform/.github/workflows/build-test.yml b/trading-platform/.github/workflows/build-test.yml deleted file mode 100644 index da4f7f2..0000000 --- a/trading-platform/.github/workflows/build-test.yml +++ /dev/null @@ -1,135 +0,0 @@ -# Build and test on pull requests -name: Build & Test - -on: - pull_request: - branches: [main, develop] - paths: - - "trading-platform/execute-service/**" - - "trading-platform/news-service/**" - - "trading-platform/data-service/**" - - "trading-platform/dashboard/**" - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - # ---- Python services ---- - test-execute-service: - runs-on: ubuntu-latest - defaults: - run: - working-directory: trading-platform/execute-service - steps: - - uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - version: "latest" - - name: Install dependencies - run: uv sync --all-extras --dev - - name: Run tests - run: uv run pytest --asyncio-mode=auto -v --tb=short - - name: Lint - run: uv run ruff check app/ tests/ - - test-news-service: - runs-on: ubuntu-latest - defaults: - run: - working-directory: trading-platform/news-service - steps: - - uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Install dependencies - run: | - pip install -r requirements.txt - pip install pytest pytest-asyncio - - name: Run tests - run: python -m pytest -v --tb=short || true - - test-data-service: - runs-on: ubuntu-latest - defaults: - run: - working-directory: trading-platform/data-service - steps: - - uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: "3.12" - - name: Install uv - uses: astral-sh/setup-uv@v3 - with: - version: "latest" - - name: Install dependencies - run: uv sync --all-extras --dev - - name: Run tests - run: uv run pytest --asyncio-mode=auto -v --tb=short - - # ---- Dashboard ---- - test-dashboard: - runs-on: ubuntu-latest - defaults: - run: - working-directory: trading-platform/dashboard - steps: - - uses: actions/checkout@v4 - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: "20" - cache: "npm" - cache-dependency-path: trading-platform/dashboard/package-lock.json - - name: Install dependencies - run: npm ci - - name: Build - run: npm run build - - name: Lint - run: npm run lint - - # ---- Docker build validation ---- - docker-build-check: - needs: [test-execute-service, test-news-service, test-data-service, test-dashboard] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Build execute-service - uses: docker/build-push-action@v5 - with: - context: trading-platform/execute-service - file: trading-platform/infra/dockerfiles/execute-service/Dockerfile - push: false - load: false - - name: Build news-service - uses: docker/build-push-action@v5 - with: - context: trading-platform/news-service - file: trading-platform/infra/dockerfiles/news-service/Dockerfile - push: false - load: false - - name: Build data-service - uses: docker/build-push-action@v5 - with: - context: trading-platform/data-service - file: trading-platform/infra/dockerfiles/data-service/Dockerfile - push: false - load: false - - name: Build dashboard - uses: docker/build-push-action@v5 - with: - context: trading-platform/dashboard - file: trading-platform/infra/dockerfiles/dashboard/Dockerfile - push: false - load: false diff --git a/trading-platform/.github/workflows/deploy.yml b/trading-platform/.github/workflows/deploy.yml deleted file mode 100644 index d59c553..0000000 --- a/trading-platform/.github/workflows/deploy.yml +++ /dev/null @@ -1,132 +0,0 @@ -# Deploy to staging/prod via Helm on GKE -name: Deploy - -on: - workflow_dispatch: - inputs: - environment: - description: "Target environment" - required: true - default: "staging" - type: choice - options: - - staging - - production - image_tag: - description: "Container image tag (SHA or branch name)" - required: true - type: string - workflow_run: - workflows: ["Build & Push Images"] - types: [completed] - branches: [main, develop] - -permissions: - contents: read - id-token: write - -jobs: - deploy: - runs-on: ubuntu-latest - if: >- - github.event_name == 'workflow_dispatch' || - (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') - environment: ${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'production' || 'staging') }} - steps: - - uses: actions/checkout@v4 - - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@v2 - with: - workload_identity_provider: projects/customer1-gke/locations/global/workloadIdentityPools/github-pool/providers/github-provider - service_account: ci-deployer@customer1-gke.iam.gserviceaccount.com - - - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@v2 - - - name: Configure kubectl for GKE - run: | - gcloud container clusters get-credentials \ - ${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'prod' || 'staging') }}-cluster \ - --region us-central1 \ - --project customer1-gke - - - name: Install Helm - uses: azure/setup-helm@v3 - with: - version: v3.14.0 - - - name: Install SOPS + Age - run: | - curl -Lo /tmp/sops.zip https://github.com/getsops/sops/releases/download/v3.8.1/sops-v3.8.1_linux.amd64.zip - unzip /tmp/sops.zip -d /tmp/ - sudo mv /tmp/sops /usr/local/bin/sops - go install github.com/getsops/gopgs@latest || true - go install filippo.io/age/cmd/age@latest || true - - - name: Create namespace - run: | - kubectl create namespace trading --dry-run=client -o yaml | kubectl apply -f - - - - name: Decrypt secrets - run: | - # Copy age key for SOPS decryption - mkdir -p /etc/sops - echo "${{ secrets.SOPS_AGE_KEY }}" > /etc/sops/age.key - chmod 600 /etc/sops/age.key - export SOPS_AGE_KEY_FILE=/etc/sops/age.key - # Decrypt secrets - sops -d trading-platform/infra/helm/trading-platform/trading-secrets.yaml > trading-platform/infra/helm/trading-platform/trading-secrets-decrypted.yaml - - - name: Deploy with Helm - run: | - IMAGE_TAG="${{ github.event.inputs.image_tag }}" - ENVIRONMENT="${{ github.event.inputs.environment || (github.ref == 'refs/heads/main' && 'production' || 'staging') }}" - - helm upgrade --install trading-platform \ - trading-platform/infra/helm/trading-platform \ - --namespace trading \ - --create-namespace \ - --set global.environment=${ENVIRONMENT} \ - --set executeService.image.tag=${IMAGE_TAG} \ - --set newsService.image.tag=${IMAGE_TAG} \ - --set dataService.image.tag=${IMAGE_TAG} \ - --set dashboard.image.tag=${IMAGE_TAG} \ - --wait \ - --timeout 10m \ - --atomic - - - name: Apply decrypted secrets - run: | - export SOPS_AGE_KEY_FILE=/etc/sops/age.key - sops -d trading-platform/infra/helm/trading-platform/trading-secrets.yaml | kubectl apply -f - - - - name: Verify deployment - run: | - echo "=== Pod Status ===" - kubectl get pods -n trading - echo "" - echo "=== Service Status ===" - kubectl get svc -n trading - echo "" - echo "=== Ingress ===" - kubectl get ingress -n trading - - - name: Post-deployment smoke test - run: | - # Wait for readiness - kubectl wait --for=condition=available --timeout=5m \ - deployment/execute-service -n trading - kubectl wait --for=condition=available --timeout=5m \ - deployment/news-service -n trading - kubectl wait --for=condition=available --timeout=5m \ - deployment/data-service -n trading - kubectl wait --for=condition=available --timeout=5m \ - deployment/dashboard -n trading - echo "All services deployed and healthy" - - - name: Rollback on failure - if: failure() - run: | - helm rollback trading-platform -n trading --timeout 10m || true - echo "Rolled back to previous release" diff --git a/trading-platform/README.md b/trading-platform/README.md deleted file mode 100644 index 5ba817d..0000000 --- a/trading-platform/README.md +++ /dev/null @@ -1,112 +0,0 @@ -# Trading Platform — Kubernetes Deployment - -Kubernetes deployment infrastructure for the trading platform microservices running on GKE (customer1 namespace). - -## Directory Structure - -``` -trading-platform/ -├── dockerfiles/ # Multi-stage Dockerfiles for each service -│ ├── dashboard/ # Next.js frontend (port 3000) -│ ├── data-service/ # Data pipeline service (port 8000) -│ ├── execute-service/ # Trading engine: Hyperliquid + Solana (port 8000) -│ └── news-service/ # CNPG connector + Kafka producer (port 8000) -├── helm/ # Helm chart for full platform deployment -│ ├── Chart.yaml # Chart metadata -│ ├── values.yaml # Default values (images, replicas, resources, infra) -│ ├── .sops.yaml # SOPS configuration for secret encryption -│ ├── trading-secrets.yaml # SOPS-encrypted secrets template -│ └── templates/ # 19 Kubernetes manifest templates -│ ├── _helpers.tpl # Template helpers -│ ├── namespace.yaml # Namespace resource -│ ├── configmap.yaml # Shared ConfigMap -│ ├── secrets.yaml # Secrets (SOPS-encrypted via trading-secrets.yaml) -│ ├── ingress.yaml # GCE Ingress for all services -│ ├── NOTES.txt # Post-install notes -│ ├── dashboard/ # Dashboard Deployment + Service -│ ├── data-service/ # Data Service Deployment + Service -│ ├── execute-service/ # Execute Service Deployment + Service -│ ├── news-service/ # News Service Deployment + Service -│ ├── infrastructure/ # PostgreSQL, Redis, Kafka -│ ├── network-policies/ # Default deny + explicit allow policies -│ └── cert-manager/ # Certificates & issuers -├── deploy/ # Additional deployment resources -│ ├── k8s/base/ # Raw K8s manifests (non-Helm fallback) -│ ├── helm/ # Individual per-service Helm charts -│ ├── dockerfiles/ # Alternative Dockerfiles (api-gateway, services) -│ ├── docker-compose/ # Local dev compose files -│ ├── scripts/ # deploy.sh, generate-mtls-certs.sh -│ └── mtls/ # mTLS documentation -└── .github/workflows/ # CI/CD pipelines - ├── build-test.yml # Build + unit tests on PR - ├── build-push.yml # Build + push to GAR on merge - └── deploy.yml # Helm deploy to GKE on push to master -``` - -## Services - -| Service | Port | Description | -|---------|------|-------------| -| Dashboard | 3000 | Next.js trading dashboard | -| Data Service | 8000 | Data pipeline, Postgres + Redis + Kafka consumers | -| Execute Service | 8000 | Trading engine with Hyperliquid + Solana integration | -| News Service | 8000 | CryptoPanic/GNews connector, Kafka producer | - -## Infrastructure Components - -- **PostgreSQL 17** — Primary database for trades, orders, user data -- **Redis 7** — Caching layer with 3-node cluster -- **Kafka 3.9** (KRaft mode) — Event streaming (trades, orders, news topics) -- **GCE Ingress** — External traffic routing with TLS termination -- **Cert-Manager** — Automatic TLS certificates (Let's Encrypt + internal CA) -- **Network Policies** — Default deny ingress/egress with explicit allow rules - -## Deploying - -### Prerequisites - -- GKE cluster: `customer1-gke` (us-central1) -- Helm 3 installed locally or in CI -- SOPS configured with Age key (`trading-secrets.yaml` must be encrypted) -- Access to `us-central1-docker.pkg.dev/customer1-gke/trading` registry - -### Quick Deploy - -```bash -# 1. Encrypt secrets (must use the SOPS Age key) -cd helm -sops -e -i trading-secrets.yaml - -# 2. Install/upgrade the Helm release -helm upgrade --install trading-platform ./helm \ - --namespace customer1 \ - --create-namespace \ - --values helm/values.yaml \ - --set global.environment=production -``` - -### CI/CD - -- **PR opened** → `build-test.yml` runs unit tests -- **Merged to master** → `build-push.yml` builds images and pushes to GAR -- **Push to master** → `deploy.yml` runs `helm upgrade` on GKE - -## Secrets - -Secrets are managed via [SOPS](https://github.com/getsops/sops) with Age encryption. -The `.sops.yaml` file configures which keys to use for each path. - -```bash -# Encrypt the secrets file -sops -e -i helm/trading-secrets.yaml - -# Decrypt (for debugging) -sops -d helm/trading-secrets.yaml -``` - -**Never commit unencrypted secrets to git.** - -## Namespace - -The platform deploys into the `customer1` namespace on the GKE cluster. -Update `global.namespace` in `helm/values.yaml` or override via `--set` during install. diff --git a/trading-platform/deploy/ci-cd/.github/workflows/ci-cd.yml b/trading-platform/deploy/ci-cd/.github/workflows/ci-cd.yml deleted file mode 100644 index 72386b2..0000000 --- a/trading-platform/deploy/ci-cd/.github/workflows/ci-cd.yml +++ /dev/null @@ -1,237 +0,0 @@ -name: Build, Test, and Deploy Trading Platform - -on: - push: - branches: [main] - paths: - - 'trading-platform/**' - pull_request: - branches: [main] - paths: - - 'trading-platform/**' - workflow_dispatch: - inputs: - environment: - description: 'Deploy environment' - type: choice - options: - - staging - - production - default: staging - -env: - REGISTRY: ghcr.io - IMAGE_PREFIX: ${{ github.repository_owner }}/trading-platform - -permissions: - contents: read - packages: write - -jobs: - # ── Test All Services ────────────────────────────────────────────────── - test-python-services: - name: Test Python Services - runs-on: ubuntu-latest - strategy: - matrix: - service: [execute-service, data-service, news-service, solana-quant-bot] - defaults: - run: - working-directory: trading-platform/${{ matrix.service }} - steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - cache: 'pip' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -e ".[dev]" - working-directory: trading-platform/${{ matrix.service }} - - - name: Run tests with coverage - run: | - pytest tests/ --cov=app --cov-report=xml --cov-report=term-missing -v - working-directory: trading-platform/${{ matrix.service }} - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - file: trading-platform/${{ matrix.service }}/coverage.xml - flags: ${{ matrix.service }} - - test-dashboard: - name: Test Dashboard (Next.js) - runs-on: ubuntu-latest - defaults: - run: - working-directory: trading-platform/dashboard - steps: - - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'npm' - cache-dependency-path: trading-platform/dashboard/package-lock.json - - - name: Install dependencies - run: npm ci - working-directory: trading-platform/dashboard - - - name: Run linting - run: npm run lint - working-directory: trading-platform/dashboard - - - name: Build application - run: npm run build - working-directory: trading-platform/dashboard - - test-api-gateway: - name: Lint API Gateway Configs - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Validate nginx config syntax - run: | - docker run --rm -v $(pwd)/deploy/k8s/base/gateway:/etc/nginx/conf.d:ro nginx:1.25-alpine nginx -t - - # ── Build and Push Container Images ───────────────────────────────────── - build-and-push: - needs: [test-python-services, test-dashboard, test-api-gateway] - name: Build & Push Images - runs-on: ubuntu-latest - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' - strategy: - matrix: - service: [execute-service, data-service, news-service, api-gateway, dashboard, solana-quant-bot] - steps: - - uses: actions/checkout@v4 - - - name: Log in to Container Registry - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Extract metadata (tags, labels) - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/${{ matrix.service }} - tags: | - type=sha,prefix= - type=ref,event=branch - type=semver,pattern={{version}} - type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: trading-platform/deploy/dockerfiles/${{ matrix.service }}.Dockerfile - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - - # ── Deploy to Kubernetes (Helm) ──────────────────────────────────────── - deploy-staging: - needs: [build-and-push] - name: Deploy to Staging - runs-on: ubuntu-latest - if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'staging') - environment: staging - steps: - - uses: actions/checkout@v4 - - - name: Set up kubectl - uses: azure/setup-kubectl@v3 - with: - version: 'v1.29.0' - - - name: Configure kubeconfig - run: | - echo "${{ secrets.STAGING_KUBECONFIG }}" | base64 -d > $HOME/.kube/config - env: - STAGING_KUBECONFIG: ${{ secrets.STAGING_KUBECONFIG }} - - - name: Install Helm - uses: azure/setup-helm@v3 - with: - version: 'v3.14.0' - - - name: Deploy with Helm (staging) - run: | - helm upgrade --install trading-platform-staging \\ - deploy/helm/trading-platform \\ - --namespace customer1-staging \\ - --create-namespace \\ - --set image.tag=${{ github.sha }} \\ - --wait --timeout 10m - - - name: Verify deployment - run: | - kubectl rollout status deployment/execute-service -n customer1-staging --timeout=5m - kubectl rollout status deployment/data-service -n customer1-staging --timeout=5m - kubectl rollout status deployment/news-service -n customer1-staging --timeout=5m - kubectl rollout status deployment/api-gateway -n customer1-staging --timeout=5m - kubectl rollout status deployment/dashboard -n customer1-staging --timeout=5m - kubectl rollout status deployment/solana-quant-bot -n customer1-staging --timeout=5m - - deploy-production: - needs: [deploy-staging] - name: Deploy to Production - runs-on: ubuntu-latest - if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'production' - environment: production - steps: - - uses: actions/checkout@v4 - - - name: Set up kubectl - uses: azure/setup-kubectl@v3 - with: - version: 'v1.29.0' - - - name: Configure kubeconfig - run: | - echo "${{ secrets.PRODUCTION_KUBECONFIG }}" | base64 -d > $HOME/.kube/config - - - name: Install Helm - uses: azure/setup-helm@v3 - with: - version: 'v3.14.0' - - - name: Deploy with Helm (production) - run: | - helm upgrade --install trading-platform-production \\ - deploy/helm/trading-platform \\ - --namespace customer1 \\ - --create-namespace \\ - --set image.tag=${{ github.sha }} \\ - --values deploy/helm/trading-platform/values-production.yaml \\ - --wait --timeout 15m - - - name: Verify deployment - run: | - kubectl rollout status deployment/execute-service -n customer1 --timeout=5m - kubectl rollout status deployment/data-service -n customer1 --timeout=5m - kubectl rollout status deployment/news-service -n customer1 --timeout=5m - kubectl rollout status deployment/api-gateway -n customer1 --timeout=5m - kubectl rollout status deployment/dashboard -n customer1 --timeout=5m - - - name: Run post-deployment health checks - run: | - # Check all services respond to health endpoints - for service in execute-service data-service news-service api-gateway dashboard; do - echo "Health check: $service" - kubectl run healthcheck-$service --rm --restart=Never --image=curlimages/curl \\ - --command -- curl -sf http://$service:$(kubectl get svc $service -o jsonpath='{.spec.ports[0].port}')/health || exit 1 - done diff --git a/trading-platform/deploy/docker-compose/docker-compose.dev.yml b/trading-platform/deploy/docker-compose/docker-compose.dev.yml deleted file mode 100644 index b9080d4..0000000 --- a/trading-platform/deploy/docker-compose/docker-compose.dev.yml +++ /dev/null @@ -1,204 +0,0 @@ -# ============================================================================= -# Docker Compose — Local Development Environment -# ============================================================================= -# Brings up all microservices + infrastructure for local development -# -# Usage: -# docker compose -f trading-platform/deploy/docker-compose/docker-compose.dev.yml up -d -# docker compose -f trading-platform/deploy/docker-compose/docker-compose.dev.yml down -v -# docker compose -f trading-platform/deploy/docker-compose/docker-compose.dev.yml logs -f execute-service -# ============================================================================= - -x-common-env: &common-env - TRADING_ENV: development - LOG_LEVEL: debug - -services: - # ── Infrastructure ──────────────────────────────────────────────────── - - postgres: - image: postgres:16-alpine - container_name: trading-postgres-dev - environment: - POSTGRES_USER: trading - POSTGRES_PASSWORD: trading_dev_password - POSTGRES_DB: trading_db - ports: - - "5432:5432" - volumes: - - postgres-data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U trading -d trading_db"] - interval: 5s - timeout: 3s - retries: 5 - restart: unless-stopped - networks: - - trading-network - - redis: - image: redis:7-alpine - container_name: trading-redis-dev - ports: - - "6379:6379" - volumes: - - redis-data:/data - command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 5s - timeout: 3s - retries: 5 - restart: unless-stopped - networks: - - trading-network - - kafka: - image: apache/kafka:3.7.0 - container_name: trading-kafka-dev - ports: - - "9092:9092" - - "9093:9093" - environment: - KAFKA_NODE_ID: 1 - KAFKA_PROCESS_ROLES: broker,controller - KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093 - KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER - KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT - KAFKA_CLUSTER_ID: MkU3OEVBNTcwT0FBQT0= - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 - KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1 - KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1 - KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" - KAFKA_LOG_RETENTION_HOURS: 24 - KAFKA_LOG_SEGMENT_BYTES: 1073741824 - volumes: - - kafka-data:/var/lib/kafka/data - healthcheck: - test: ["CMD-SHELL", "kafka-topics.sh --bootstrap-server localhost:9092 --list || exit 1"] - interval: 10s - timeout: 5s - retries: 10 - start_period: 30s - restart: unless-stopped - networks: - - trading-network - - # ── Microservices ───────────────────────────────────────────────────── - - data-service: - build: - context: ../../.. - dockerfile: trading-platform/deploy/dockerfiles/data-service.Dockerfile - container_name: trading-data-service-dev - environment: - <<: *common-env - DATABASE_URL: postgresql+asyncpg://trading:trading_dev_password@postgres:5432/trading_db - REDIS_URL: redis://redis:6379/0 - KAFKA_BOOTSTRAP_SERVERS: kafka:9092 - LOG_LEVEL: debug - ports: - - "8001:8001" - depends_on: - postgres: - condition: service_healthy - redis: - condition: service_healthy - kafka: - condition: service_healthy - restart: unless-stopped - networks: - - trading-network - - execute-service: - build: - context: ../../.. - dockerfile: trading-platform/deploy/dockerfiles/execute-service.Dockerfile - container_name: trading-execute-service-dev - environment: - <<: *common-env - EXECUTE_DATABASE_URL: sqlite+aiosqlite:///./execute.db - EXECUTE_JWT_SECRET_KEY: dev-secret-change-me - EXECUTE_HYPERLIQUID_TESTNET: "true" - EXECUTE_MTLS_ENABLED: "false" - EXECUTE_MARKET_DATA_SERVICE_URL: http://data-service:8001 - LOG_LEVEL: debug - ports: - - "8000:8000" - depends_on: - data-service: - condition: service_healthy - restart: unless-stopped - networks: - - trading-network - - news-service: - build: - context: ../../.. - dockerfile: trading-platform/deploy/dockerfiles/news-service.Dockerfile - container_name: trading-news-service-dev - environment: - <<: *common-env - DATABASE_URL: postgresql+asyncpg://trading:trading_dev_password@postgres:5432/trading_db - KAFKA_BOOTSTRAP_SERVERS: kafka:9092 - REDIS_URL: redis://redis:6379/1 - LOG_LEVEL: debug - ports: - - "8002:8002" - depends_on: - postgres: - condition: service_healthy - kafka: - condition: service_healthy - restart: unless-stopped - networks: - - trading-network - - api-gateway: - build: - context: ../../.. - dockerfile: trading-platform/deploy/dockerfiles/api-gateway.Dockerfile - container_name: trading-api-gateway-dev - environment: - <<: *common-env - ports: - - "8080:8080" - - "8443:8443" - depends_on: - execute-service: - condition: service_healthy - data-service: - condition: service_healthy - news-service: - condition: service_healthy - restart: unless-stopped - networks: - - trading-network - - dashboard: - build: - context: ../../.. - dockerfile: trading-platform/deploy/dockerfiles/dashboard.Dockerfile - container_name: trading-dashboard-dev - environment: - NEXT_PUBLIC_API_URL: http://localhost:8080 - NODE_ENV: development - ports: - - "3000:3000" - depends_on: - api-gateway: - condition: service_started - restart: unless-stopped - networks: - - trading-network - -volumes: - postgres-data: - redis-data: - kafka-data: - -networks: - trading-network: - driver: bridge diff --git a/trading-platform/deploy/dockerfiles/api-gateway.Dockerfile b/trading-platform/deploy/dockerfiles/api-gateway.Dockerfile deleted file mode 100644 index 2e63688..0000000 --- a/trading-platform/deploy/dockerfiles/api-gateway.Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# ============================================================================= -# API Gateway Dockerfile — Nginx-based reverse proxy with rate limiting -# ============================================================================= -FROM nginx:1.25-alpine AS production - -# Copy custom nginx configuration -COPY deploy/k8s/base/gateway/nginx.conf /etc/nginx/nginx.conf -COPY deploy/k8s/base/gateway/conf.d/ /etc/nginx/conf.d/ - -# Create required directories -RUN mkdir -p /etc/nginx/ssl \ - /etc/nginx/conf.d \ - /var/cache/nginx \ - /var/run/nginx \ - /var/log/nginx \ - && touch /var/run/nginx/nginx.pid - -# Security: run as nginx user (already exists in alpine image) -USER nginx - -EXPOSE 8080 8443 - -HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1 - -CMD ["nginx", "-g", "daemon off;"] diff --git a/trading-platform/deploy/dockerfiles/dashboard.Dockerfile b/trading-platform/deploy/dockerfiles/dashboard.Dockerfile deleted file mode 100644 index 816d558..0000000 --- a/trading-platform/deploy/dockerfiles/dashboard.Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -# ============================================================================= -# Dashboard Dockerfile — Next.js multi-stage build with static export -# ============================================================================= -FROM node:20-alpine AS builder - -WORKDIR /app - -# Install dependencies first (better layer caching) -COPY trading-platform/dashboard/package*.json ./ -RUN npm ci - -# Copy source and build -COPY trading-platform/dashboard/ ./ -RUN npm run build - -# Production stage -FROM node:20-alpine AS production - -# Security: non-root user -RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 - -WORKDIR /app - -# Copy built output and package.json from builder -COPY --from=builder /app/package.json ./package.json -COPY --from=builder /app/.next/standalone ./ -COPY --from=builder /app/.next/static ./.next/static -COPY --from=builder /app/public ./public - -USER nextjs - -EXPOSE 3000 - -ENV NODE_ENV=production -ENV PORT=3000 - -HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1 - -CMD ["node", "server.js"] diff --git a/trading-platform/deploy/dockerfiles/data-service.Dockerfile b/trading-platform/deploy/dockerfiles/data-service.Dockerfile deleted file mode 100644 index 902d71e..0000000 --- a/trading-platform/deploy/dockerfiles/data-service.Dockerfile +++ /dev/null @@ -1,32 +0,0 @@ -# ============================================================================= -# Data Service Dockerfile — Multi-stage build -# ============================================================================= -FROM python:3.12-slim AS builder - -WORKDIR /build -COPY trading-platform/data-service/pyproject.toml ./ -RUN pip install --no-cache-dir --prefix=/install . - -# Production stage -FROM python:3.12-slim AS production - -# Security: non-root user -RUN useradd -m --system appuser - -# Copy dependencies from builder -COPY --from=builder /install /usr/local - -# Copy application code -WORKDIR /app -COPY --chown=appuser:appuser trading-platform/data-service/data_service/ ./data_service/ -COPY --chown=appuser:appuser trading-platform/data-service/pyproject.toml ./ - -USER appuser - -# Health check -HEALTHCHECK --interval=15s --timeout=5s --start-period=15s --retries=3 \ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8001/health')" || exit 1 - -EXPOSE 8001 - -CMD ["uvicorn", "data_service.app.main:app", "--host", "0.0.0.0", "--port", "8001"] diff --git a/trading-platform/deploy/dockerfiles/execute-service.Dockerfile b/trading-platform/deploy/dockerfiles/execute-service.Dockerfile deleted file mode 100644 index 0e1c2fe..0000000 --- a/trading-platform/deploy/dockerfiles/execute-service.Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -# ============================================================================= -# Execute Service Dockerfile — Multi-stage build for minimal image -# ============================================================================= -# Build stage: compile dependencies -FROM python:3.12-slim AS builder - -WORKDIR /build -COPY trading-platform/execute-service/pyproject.toml ./ -RUN pip install --no-cache-dir --prefix=/install . - -# Production stage -FROM python:3.12-slim AS production - -# Security: non-root user -RUN useradd -m --system appuser - -# Copy dependencies from builder -COPY --from=builder /install /usr/local - -# Copy application code -WORKDIR /app -COPY --chown=appuser:appuser trading-platform/execute-service/app/ ./app/ -COPY --chown=appuser:appuser trading-platform/execute-service/pyproject.toml ./ - -# Create required directories with proper permissions -RUN mkdir -p /tmp /app/data && chown -R appuser:appuser /tmp /app/data - -USER appuser - -# Health check using Python (curl not in slim) -HEALTHCHECK --interval=15s --timeout=5s --start-period=15s --retries=3 \ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1 - -EXPOSE 8000 - -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/trading-platform/deploy/dockerfiles/news-service.Dockerfile b/trading-platform/deploy/dockerfiles/news-service.Dockerfile deleted file mode 100644 index 770cb5e..0000000 --- a/trading-platform/deploy/dockerfiles/news-service.Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -# ============================================================================= -# News Service Dockerfile — Multi-stage build with NLTK data -# ============================================================================= -FROM python:3.12-slim AS builder - -WORKDIR /build -COPY trading-platform/news-service/requirements.txt ./ -RUN pip install --no-cache-dir --prefix=/install -r requirements.txt - -# Production stage -FROM python:3.12-slim AS production - -# Install system dependencies -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - gcc libpq-dev && \ - rm -rf /var/lib/apt/lists/* - -# Install Python dependencies from builder -COPY --from=builder /install /usr/local - -# Download NLTK data for textblob -RUN python -c "import nltk; nltk.download('punkt'); nltk.download('punkt_tab'); nltk.download('averaged_perceptron_tagger')" - -# Security: non-root user -RUN useradd -m --system appuser - -# Copy application code -WORKDIR /app -COPY --chown=appuser:appuser trading-platform/news-service/app/ ./app/ -COPY --chown=appuser:appuser trading-platform/news-service/requirements.txt ./ - -USER appuser - -# Health check -HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8002/health')" || exit 1 - -EXPOSE 8002 - -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8002", "--workers", "4"] diff --git a/trading-platform/deploy/helm/Chart.yaml b/trading-platform/deploy/helm/Chart.yaml deleted file mode 100644 index f7d278d..0000000 --- a/trading-platform/deploy/helm/Chart.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# ============================================================================= -# Trading Platform — Root Helm Chart -# ============================================================================= -apiVersion: v2 -name: trading-platform -description: Helm chart for the entire trading platform microservices -type: application -version: 0.1.0 -appVersion: "0.1.0" - -dependencies: - - name: api-gateway - version: "0.1.0" - repository: "file://../api-gateway" - - name: execute-service - version: "0.1.0" - repository: "file://../execute-service" - - name: data-service - version: "0.1.0" - repository: "file://../data-service" - - name: news-service - version: "0.1.0" - repository: "file://../news-service" - - name: dashboard - version: "0.1.0" - repository: "file://../dashboard" - - name: cert-manager - version: "1.14.0" - repository: https://charts.jetstack.io - condition: cert-manager.enabled - - name: ingress-nginx - version: "4.9.0" - repository: https://kubernetes.github.io/ingress-nginx - condition: ingress-nginx.enabled diff --git a/trading-platform/deploy/helm/_helpers.tpl.template b/trading-platform/deploy/helm/_helpers.tpl.template deleted file mode 100644 index 3b76fa7..0000000 --- a/trading-platform/deploy/helm/_helpers.tpl.template +++ /dev/null @@ -1,60 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define ".name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -*/}} -{{- define ".fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define ".chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define ".labels" -}} -helm.sh/chart: {{ include ".chart" . }} -{{ include ".selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define ".selectorLabels" -}} -app.kubernetes.io/name: {{ include ".name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define ".serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include ".fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/api-gateway/Chart.yaml b/trading-platform/deploy/helm/api-gateway/Chart.yaml deleted file mode 100644 index 5e0f40d..0000000 --- a/trading-platform/deploy/helm/api-gateway/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: api-gateway -description: API Gateway — Nginx reverse proxy -type: application -version: 0.1.0 -appVersion: "0.1.0" diff --git a/trading-platform/deploy/helm/api-gateway/templates/_helpers.tpl b/trading-platform/deploy/helm/api-gateway/templates/_helpers.tpl deleted file mode 100644 index 33b8067..0000000 --- a/trading-platform/deploy/helm/api-gateway/templates/_helpers.tpl +++ /dev/null @@ -1,61 +0,0 @@ - -{{/* -Expand the name of the chart. -*/}} -{{- define "api-gateway.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -*/}} -{{- define "api-gateway.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "api-gateway.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "api-gateway.labels" -}} -helm.sh/chart: {{ include "api-gateway.chart" . }} -{{ include "api-gateway.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "api-gateway.selectorLabels" -}} -app.kubernetes.io/name: {{ include "api-gateway.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "api-gateway.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "api-gateway.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/api-gateway/templates/deployment.yaml b/trading-platform/deploy/helm/api-gateway/templates/deployment.yaml deleted file mode 100644 index 057c146..0000000 --- a/trading-platform/deploy/helm/api-gateway/templates/deployment.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "api-gateway.fullname" . }} - labels: - {{- include "api-gateway.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "api-gateway.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "api-gateway.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "api-gateway.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 8080 - protocol: TCP - livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 12 }} - {{- end }} diff --git a/trading-platform/deploy/helm/api-gateway/templates/hpa.yaml b/trading-platform/deploy/helm/api-gateway/templates/hpa.yaml deleted file mode 100644 index 472b45b..0000000 --- a/trading-platform/deploy/helm/api-gateway/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "api-gateway.fullname" . }} - labels: - {{- include "api-gateway.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "api-gateway.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/api-gateway/templates/ingress.yaml b/trading-platform/deploy/helm/api-gateway/templates/ingress.yaml deleted file mode 100644 index d875b28..0000000 --- a/trading-platform/deploy/helm/api-gateway/templates/ingress.yaml +++ /dev/null @@ -1,61 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $fullName := include "api-gateway.fullname" . -}} -{{- $svcPort := .Values.service.port -}} -{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} - {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} -apiVersion: extensions/v1beta1 -{{- else -}} -apiVersion: extensions/v1beta1 -{{- end }} -kind: Ingress -metadata: - name: {{ $fullName }} - labels: - {{- include "api-gateway.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - {{- if .Values.ingress.tls }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - {{- end }} - rules: - {{- range .Values.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} - pathType: {{ .pathType }} - {{- end }} - backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} - service: - name: {{ $fullName }} - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/api-gateway/templates/networkpolicy.yaml b/trading-platform/deploy/helm/api-gateway/templates/networkpolicy.yaml deleted file mode 100644 index 0fa2821..0000000 --- a/trading-platform/deploy/helm/api-gateway/templates/networkpolicy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "api-gateway.fullname" . }}-network-policy - labels: - {{- include "api-gateway.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - {{- include "api-gateway.selectorLabels" . | nindent 6 }} - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: - matchLabels: - app.kubernetes.io/name: api-gateway - ports: - - port: http - protocol: TCP - egress: - # Allow DNS resolution - - to: [] - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP diff --git a/trading-platform/deploy/helm/api-gateway/templates/service.yaml b/trading-platform/deploy/helm/api-gateway/templates/service.yaml deleted file mode 100644 index 545d6f0..0000000 --- a/trading-platform/deploy/helm/api-gateway/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "api-gateway.fullname" . }} - labels: - {{- include "api-gateway.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "api-gateway.selectorLabels" . | nindent 4 }} diff --git a/trading-platform/deploy/helm/api-gateway/templates/serviceaccount.yaml b/trading-platform/deploy/helm/api-gateway/templates/serviceaccount.yaml deleted file mode 100644 index d707caa..0000000 --- a/trading-platform/deploy/helm/api-gateway/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "api-gateway.serviceAccountName" . }} - labels: - {{- include "api-gateway.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/api-gateway/values.yaml b/trading-platform/deploy/helm/api-gateway/values.yaml deleted file mode 100644 index 551148b..0000000 --- a/trading-platform/deploy/helm/api-gateway/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -# trading-platform/api-gateway Helm chart values - -replicaCount: 2 - -image: - repository: trading-platform/api-gateway - pullPolicy: IfNotPresent - tag: "" - -imagePullSecrets: [] - -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - create: true - annotations: {} - name: "" - -podAnnotations: {} - -securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 1000 - -service: - type: ClusterIP - port: 8080 - -ingress: - enabled: true - className: nginx - annotations: {} - hosts: - - host: api.trading.example.com - paths: - - path: / - pathType: Prefix - tls: [] - -resources: - limits: - cpu: "500m" - memory: 256Mi - requests: - cpu: "250m" - memory: 128Mi - -autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 10 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 - -livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - -nodeSelector: {} -tolerations: [] -affinity: {} diff --git a/trading-platform/deploy/helm/dashboard/Chart.yaml b/trading-platform/deploy/helm/dashboard/Chart.yaml deleted file mode 100644 index 2b077c3..0000000 --- a/trading-platform/deploy/helm/dashboard/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: dashboard -description: Dashboard frontend -type: application -version: 0.1.0 -appVersion: "0.1.0" diff --git a/trading-platform/deploy/helm/dashboard/templates/_helpers.tpl b/trading-platform/deploy/helm/dashboard/templates/_helpers.tpl deleted file mode 100644 index 3402279..0000000 --- a/trading-platform/deploy/helm/dashboard/templates/_helpers.tpl +++ /dev/null @@ -1,61 +0,0 @@ - -{{/* -Expand the name of the chart. -*/}} -{{- define "dashboard.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -*/}} -{{- define "dashboard.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "dashboard.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "dashboard.labels" -}} -helm.sh/chart: {{ include "dashboard.chart" . }} -{{ include "dashboard.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "dashboard.selectorLabels" -}} -app.kubernetes.io/name: {{ include "dashboard.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "dashboard.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "dashboard.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/dashboard/templates/deployment.yaml b/trading-platform/deploy/helm/dashboard/templates/deployment.yaml deleted file mode 100644 index 59351c0..0000000 --- a/trading-platform/deploy/helm/dashboard/templates/deployment.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "dashboard.fullname" . }} - labels: - {{- include "dashboard.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "dashboard.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "dashboard.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "dashboard.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 3000 - protocol: TCP - livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 12 }} - {{- end }} diff --git a/trading-platform/deploy/helm/dashboard/templates/hpa.yaml b/trading-platform/deploy/helm/dashboard/templates/hpa.yaml deleted file mode 100644 index c5f6544..0000000 --- a/trading-platform/deploy/helm/dashboard/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "dashboard.fullname" . }} - labels: - {{- include "dashboard.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "dashboard.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/dashboard/templates/networkpolicy.yaml b/trading-platform/deploy/helm/dashboard/templates/networkpolicy.yaml deleted file mode 100644 index 2f84151..0000000 --- a/trading-platform/deploy/helm/dashboard/templates/networkpolicy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "dashboard.fullname" . }}-network-policy - labels: - {{- include "dashboard.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - {{- include "dashboard.selectorLabels" . | nindent 6 }} - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: - matchLabels: - app.kubernetes.io/name: api-gateway - ports: - - port: http - protocol: TCP - egress: - # Allow DNS resolution - - to: [] - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP diff --git a/trading-platform/deploy/helm/dashboard/templates/service.yaml b/trading-platform/deploy/helm/dashboard/templates/service.yaml deleted file mode 100644 index 155124b..0000000 --- a/trading-platform/deploy/helm/dashboard/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "dashboard.fullname" . }} - labels: - {{- include "dashboard.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "dashboard.selectorLabels" . | nindent 4 }} diff --git a/trading-platform/deploy/helm/dashboard/templates/serviceaccount.yaml b/trading-platform/deploy/helm/dashboard/templates/serviceaccount.yaml deleted file mode 100644 index 4948fb9..0000000 --- a/trading-platform/deploy/helm/dashboard/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "dashboard.serviceAccountName" . }} - labels: - {{- include "dashboard.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/dashboard/values.yaml b/trading-platform/deploy/helm/dashboard/values.yaml deleted file mode 100644 index e7d817f..0000000 --- a/trading-platform/deploy/helm/dashboard/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -# trading-platform/dashboard Helm chart values - -replicaCount: 2 - -image: - repository: trading-platform/dashboard - pullPolicy: IfNotPresent - tag: "" - -imagePullSecrets: [] - -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - create: true - annotations: {} - name: "" - -podAnnotations: {} - -securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 1000 - -service: - type: ClusterIP - port: 3000 - -ingress: - enabled: false - className: nginx - annotations: {} - hosts: - - host: api.trading.example.com - paths: - - path: / - pathType: Prefix - tls: [] - -resources: - limits: - cpu: "500m" - memory: 512Mi - requests: - cpu: "250m" - memory: 256Mi - -autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 10 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 - -livenessProbe: - httpGet: - path: / - port: http - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: / - port: http - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - -nodeSelector: {} -tolerations: [] -affinity: {} diff --git a/trading-platform/deploy/helm/data-service/Chart.yaml b/trading-platform/deploy/helm/data-service/Chart.yaml deleted file mode 100644 index b7e2b70..0000000 --- a/trading-platform/deploy/helm/data-service/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: data-service -description: Trading data service -type: application -version: 0.1.0 -appVersion: "0.1.0" diff --git a/trading-platform/deploy/helm/data-service/templates/_helpers.tpl b/trading-platform/deploy/helm/data-service/templates/_helpers.tpl deleted file mode 100644 index 670ec9d..0000000 --- a/trading-platform/deploy/helm/data-service/templates/_helpers.tpl +++ /dev/null @@ -1,61 +0,0 @@ - -{{/* -Expand the name of the chart. -*/}} -{{- define "data-service.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -*/}} -{{- define "data-service.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "data-service.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "data-service.labels" -}} -helm.sh/chart: {{ include "data-service.chart" . }} -{{ include "data-service.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "data-service.selectorLabels" -}} -app.kubernetes.io/name: {{ include "data-service.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "data-service.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "data-service.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/data-service/templates/deployment.yaml b/trading-platform/deploy/helm/data-service/templates/deployment.yaml deleted file mode 100644 index f2a03be..0000000 --- a/trading-platform/deploy/helm/data-service/templates/deployment.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "data-service.fullname" . }} - labels: - {{- include "data-service.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "data-service.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "data-service.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "data-service.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 8001 - protocol: TCP - livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 12 }} - {{- end }} diff --git a/trading-platform/deploy/helm/data-service/templates/hpa.yaml b/trading-platform/deploy/helm/data-service/templates/hpa.yaml deleted file mode 100644 index 9686023..0000000 --- a/trading-platform/deploy/helm/data-service/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "data-service.fullname" . }} - labels: - {{- include "data-service.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "data-service.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/data-service/templates/networkpolicy.yaml b/trading-platform/deploy/helm/data-service/templates/networkpolicy.yaml deleted file mode 100644 index d50f2bc..0000000 --- a/trading-platform/deploy/helm/data-service/templates/networkpolicy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "data-service.fullname" . }}-network-policy - labels: - {{- include "data-service.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - {{- include "data-service.selectorLabels" . | nindent 6 }} - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: - matchLabels: - app.kubernetes.io/name: api-gateway - ports: - - port: http - protocol: TCP - egress: - # Allow DNS resolution - - to: [] - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP diff --git a/trading-platform/deploy/helm/data-service/templates/service.yaml b/trading-platform/deploy/helm/data-service/templates/service.yaml deleted file mode 100644 index 186d0d6..0000000 --- a/trading-platform/deploy/helm/data-service/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "data-service.fullname" . }} - labels: - {{- include "data-service.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "data-service.selectorLabels" . | nindent 4 }} diff --git a/trading-platform/deploy/helm/data-service/templates/serviceaccount.yaml b/trading-platform/deploy/helm/data-service/templates/serviceaccount.yaml deleted file mode 100644 index 3ba4646..0000000 --- a/trading-platform/deploy/helm/data-service/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "data-service.serviceAccountName" . }} - labels: - {{- include "data-service.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/data-service/values.yaml b/trading-platform/deploy/helm/data-service/values.yaml deleted file mode 100644 index 8a5fff1..0000000 --- a/trading-platform/deploy/helm/data-service/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -# trading-platform/data-service Helm chart values - -replicaCount: 2 - -image: - repository: trading-platform/data-service - pullPolicy: IfNotPresent - tag: "" - -imagePullSecrets: [] - -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - create: true - annotations: {} - name: "" - -podAnnotations: {} - -securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 1000 - -service: - type: ClusterIP - port: 8001 - -ingress: - enabled: false - className: nginx - annotations: {} - hosts: - - host: api.trading.example.com - paths: - - path: / - pathType: Prefix - tls: [] - -resources: - limits: - cpu: "1000m" - memory: 1Gi - requests: - cpu: "500m" - memory: 512Mi - -autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 10 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 - -livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - -nodeSelector: {} -tolerations: [] -affinity: {} diff --git a/trading-platform/deploy/helm/execute-service/Chart.yaml b/trading-platform/deploy/helm/execute-service/Chart.yaml deleted file mode 100644 index 0324bc7..0000000 --- a/trading-platform/deploy/helm/execute-service/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: execute-service -description: Trading execution service -type: application -version: 0.1.0 -appVersion: "0.1.0" diff --git a/trading-platform/deploy/helm/execute-service/templates/_helpers.tpl b/trading-platform/deploy/helm/execute-service/templates/_helpers.tpl deleted file mode 100644 index 0f46b86..0000000 --- a/trading-platform/deploy/helm/execute-service/templates/_helpers.tpl +++ /dev/null @@ -1,61 +0,0 @@ - -{{/* -Expand the name of the chart. -*/}} -{{- define "execute-service.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -*/}} -{{- define "execute-service.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "execute-service.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "execute-service.labels" -}} -helm.sh/chart: {{ include "execute-service.chart" . }} -{{ include "execute-service.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "execute-service.selectorLabels" -}} -app.kubernetes.io/name: {{ include "execute-service.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "execute-service.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "execute-service.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/execute-service/templates/deployment.yaml b/trading-platform/deploy/helm/execute-service/templates/deployment.yaml deleted file mode 100644 index 5b7a032..0000000 --- a/trading-platform/deploy/helm/execute-service/templates/deployment.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "execute-service.fullname" . }} - labels: - {{- include "execute-service.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "execute-service.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "execute-service.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "execute-service.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 8000 - protocol: TCP - livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 12 }} - {{- end }} diff --git a/trading-platform/deploy/helm/execute-service/templates/hpa.yaml b/trading-platform/deploy/helm/execute-service/templates/hpa.yaml deleted file mode 100644 index d27ea6d..0000000 --- a/trading-platform/deploy/helm/execute-service/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "execute-service.fullname" . }} - labels: - {{- include "execute-service.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "execute-service.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/execute-service/templates/networkpolicy.yaml b/trading-platform/deploy/helm/execute-service/templates/networkpolicy.yaml deleted file mode 100644 index 2e809cd..0000000 --- a/trading-platform/deploy/helm/execute-service/templates/networkpolicy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "execute-service.fullname" . }}-network-policy - labels: - {{- include "execute-service.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - {{- include "execute-service.selectorLabels" . | nindent 6 }} - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: - matchLabels: - app.kubernetes.io/name: api-gateway - ports: - - port: http - protocol: TCP - egress: - # Allow DNS resolution - - to: [] - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP diff --git a/trading-platform/deploy/helm/execute-service/templates/service.yaml b/trading-platform/deploy/helm/execute-service/templates/service.yaml deleted file mode 100644 index 0fbb9ce..0000000 --- a/trading-platform/deploy/helm/execute-service/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "execute-service.fullname" . }} - labels: - {{- include "execute-service.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "execute-service.selectorLabels" . | nindent 4 }} diff --git a/trading-platform/deploy/helm/execute-service/templates/serviceaccount.yaml b/trading-platform/deploy/helm/execute-service/templates/serviceaccount.yaml deleted file mode 100644 index 0f3619b..0000000 --- a/trading-platform/deploy/helm/execute-service/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "execute-service.serviceAccountName" . }} - labels: - {{- include "execute-service.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/execute-service/values.yaml b/trading-platform/deploy/helm/execute-service/values.yaml deleted file mode 100644 index 7dc92e6..0000000 --- a/trading-platform/deploy/helm/execute-service/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -# trading-platform/execute-service Helm chart values - -replicaCount: 2 - -image: - repository: trading-platform/execute-service - pullPolicy: IfNotPresent - tag: "" - -imagePullSecrets: [] - -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - create: true - annotations: {} - name: "" - -podAnnotations: {} - -securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 1000 - -service: - type: ClusterIP - port: 8000 - -ingress: - enabled: false - className: nginx - annotations: {} - hosts: - - host: api.trading.example.com - paths: - - path: / - pathType: Prefix - tls: [] - -resources: - limits: - cpu: "500m" - memory: 512Mi - requests: - cpu: "250m" - memory: 256Mi - -autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 10 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 - -livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - -nodeSelector: {} -tolerations: [] -affinity: {} diff --git a/trading-platform/deploy/helm/news-service/Chart.yaml b/trading-platform/deploy/helm/news-service/Chart.yaml deleted file mode 100644 index c9eb5d9..0000000 --- a/trading-platform/deploy/helm/news-service/Chart.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: v2 -name: news-service -description: News analysis service -type: application -version: 0.1.0 -appVersion: "0.1.0" diff --git a/trading-platform/deploy/helm/news-service/templates/_helpers.tpl b/trading-platform/deploy/helm/news-service/templates/_helpers.tpl deleted file mode 100644 index 8be65a7..0000000 --- a/trading-platform/deploy/helm/news-service/templates/_helpers.tpl +++ /dev/null @@ -1,61 +0,0 @@ - -{{/* -Expand the name of the chart. -*/}} -{{- define "news-service.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -*/}} -{{- define "news-service.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "news-service.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "news-service.labels" -}} -helm.sh/chart: {{ include "news-service.chart" . }} -{{ include "news-service.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "news-service.selectorLabels" -}} -app.kubernetes.io/name: {{ include "news-service.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "news-service.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "news-service.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/news-service/templates/deployment.yaml b/trading-platform/deploy/helm/news-service/templates/deployment.yaml deleted file mode 100644 index ef25033..0000000 --- a/trading-platform/deploy/helm/news-service/templates/deployment.yaml +++ /dev/null @@ -1,57 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "news-service.fullname" . }} - labels: - {{- include "news-service.labels" . | nindent 4 }} -spec: - {{- if not .Values.autoscaling.enabled }} - replicas: {{ .Values.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "news-service.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "news-service.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "news-service.serviceAccountName" . }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Chart.Name }} - securityContext: - {{- toYaml .Values.securityContext | nindent 12 }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - ports: - - name: http - containerPort: 8002 - protocol: TCP - livenessProbe: - {{- toYaml .Values.livenessProbe | nindent 12 }} - readinessProbe: - {{- toYaml .Values.readinessProbe | nindent 12 }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 12 }} - {{- end }} diff --git a/trading-platform/deploy/helm/news-service/templates/hpa.yaml b/trading-platform/deploy/helm/news-service/templates/hpa.yaml deleted file mode 100644 index 7c4aeca..0000000 --- a/trading-platform/deploy/helm/news-service/templates/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "news-service.fullname" . }} - labels: - {{- include "news-service.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "news-service.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/news-service/templates/networkpolicy.yaml b/trading-platform/deploy/helm/news-service/templates/networkpolicy.yaml deleted file mode 100644 index ff3c8f9..0000000 --- a/trading-platform/deploy/helm/news-service/templates/networkpolicy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "news-service.fullname" . }}-network-policy - labels: - {{- include "news-service.labels" . | nindent 4 }} -spec: - podSelector: - matchLabels: - {{- include "news-service.selectorLabels" . | nindent 6 }} - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: - matchLabels: - app.kubernetes.io/name: api-gateway - ports: - - port: http - protocol: TCP - egress: - # Allow DNS resolution - - to: [] - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP diff --git a/trading-platform/deploy/helm/news-service/templates/service.yaml b/trading-platform/deploy/helm/news-service/templates/service.yaml deleted file mode 100644 index 8709a9e..0000000 --- a/trading-platform/deploy/helm/news-service/templates/service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "news-service.fullname" . }} - labels: - {{- include "news-service.labels" . | nindent 4 }} -spec: - type: {{ .Values.service.type }} - ports: - - port: {{ .Values.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "news-service.selectorLabels" . | nindent 4 }} diff --git a/trading-platform/deploy/helm/news-service/templates/serviceaccount.yaml b/trading-platform/deploy/helm/news-service/templates/serviceaccount.yaml deleted file mode 100644 index 4b093b0..0000000 --- a/trading-platform/deploy/helm/news-service/templates/serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "news-service.serviceAccountName" . }} - labels: - {{- include "news-service.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/trading-platform/deploy/helm/news-service/values.yaml b/trading-platform/deploy/helm/news-service/values.yaml deleted file mode 100644 index 7edc76e..0000000 --- a/trading-platform/deploy/helm/news-service/values.yaml +++ /dev/null @@ -1,80 +0,0 @@ -# trading-platform/news-service Helm chart values - -replicaCount: 2 - -image: - repository: trading-platform/news-service - pullPolicy: IfNotPresent - tag: "" - -imagePullSecrets: [] - -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - create: true - annotations: {} - name: "" - -podAnnotations: {} - -securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - runAsUser: 1000 - -service: - type: ClusterIP - port: 8002 - -ingress: - enabled: false - className: nginx - annotations: {} - hosts: - - host: api.trading.example.com - paths: - - path: / - pathType: Prefix - tls: [] - -resources: - limits: - cpu: "1000m" - memory: 1Gi - requests: - cpu: "500m" - memory: 512Mi - -autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 10 - targetCPUUtilizationPercentage: 80 - targetMemoryUtilizationPercentage: 80 - -livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - -readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - -nodeSelector: {} -tolerations: [] -affinity: {} diff --git a/trading-platform/deploy/k8s/base/api-gateway-deployment.yaml b/trading-platform/deploy/k8s/base/api-gateway-deployment.yaml deleted file mode 100644 index 834c1ff..0000000 --- a/trading-platform/deploy/k8s/base/api-gateway-deployment.yaml +++ /dev/null @@ -1,71 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api-gateway - namespace: customer1 - labels: - app: api-gateway - app.kubernetes.io/name: api-gateway - app.kubernetes.io/component: microservice -spec: - replicas: 2 - selector: - matchLabels: - app: api-gateway - template: - metadata: - labels: - app: api-gateway - app.kubernetes.io/name: api-gateway - app.kubernetes.io/component: microservice - spec: - automountServiceAccountToken: false - securityContext: - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 1000 - containers: - - name: api-gateway - image: "trading-platform/api-gateway:v${VERSION}" - ports: - - containerPort: 8080 - protocol: TCP - envFrom: - - configMapRef: - name: trading-platform-config - resources: - limits: - cpu: "500m" - memory: 256Mi - requests: - cpu: "250m" - memory: 128Mi - livenessProbe: - httpGet: - path: /health - port: 8080 - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - volumeMounts: - - name: tmp - mountPath: /tmp - volumes: - - name: tmp - emptyDir: {} diff --git a/trading-platform/deploy/k8s/base/api-gateway-hpa.yaml b/trading-platform/deploy/k8s/base/api-gateway-hpa.yaml deleted file mode 100644 index 20940ea..0000000 --- a/trading-platform/deploy/k8s/base/api-gateway-hpa.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: api-gateway-hpa - namespace: customer1 - labels: - app: api-gateway -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: api-gateway - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/trading-platform/deploy/k8s/base/api-gateway-service.yaml b/trading-platform/deploy/k8s/base/api-gateway-service.yaml deleted file mode 100644 index 1ca171d..0000000 --- a/trading-platform/deploy/k8s/base/api-gateway-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: api-gateway - namespace: customer1 - labels: - app: api-gateway - app.kubernetes.io/name: api-gateway - app.kubernetes.io/component: microservice -spec: - type: ClusterIP - ports: - - port: 8080 - targetPort: 8080 - protocol: TCP - name: http - selector: - app: api-gateway diff --git a/trading-platform/deploy/k8s/base/cert-manager/api-gateway-mtls-cert.yaml b/trading-platform/deploy/k8s/base/cert-manager/api-gateway-mtls-cert.yaml deleted file mode 100644 index 1534702..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/api-gateway-mtls-cert.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: api-gateway-mtls-cert - namespace: customer1 -spec: - secretName: api-gateway-mtls-secret - duration: 2160h # 90 days - renewBefore: 360h # 15 days - commonName: api-gateway.customer1.svc.cluster.local - dnsNames: - - api-gateway - - api-gateway.customer1 - - api-gateway.customer1.svc - - api-gateway.customer1.svc.cluster.local - usages: - - digital signature - - key encipherment - - client auth - - server auth - issuerRef: - name: trading-platform-ca-issuer - kind: Issuer - group: cert-manager.io diff --git a/trading-platform/deploy/k8s/base/cert-manager/ca-issuer.yaml b/trading-platform/deploy/k8s/base/cert-manager/ca-issuer.yaml deleted file mode 100644 index 337ede9..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/ca-issuer.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: trading-platform-ca-issuer - namespace: customer1 -spec: - ca: - secretName: trading-platform-ca-secret diff --git a/trading-platform/deploy/k8s/base/cert-manager/cluster-issuers.yaml b/trading-platform/deploy/k8s/base/cert-manager/cluster-issuers.yaml deleted file mode 100644 index 9b8ce95..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/cluster-issuers.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod -spec: - acme: - server: https://acme-v02.api.letsencrypt.org/directory - email: admin@trading-platform.com - privateKeySecretRef: - name: letsencrypt-prod-key - solvers: - - http01: - ingress: - class: nginx ---- -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-staging -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: admin@trading-platform.com - privateKeySecretRef: - name: letsencrypt-staging-key - solvers: - - http01: - ingress: - class: nginx diff --git a/trading-platform/deploy/k8s/base/cert-manager/dashboard-mtls-cert.yaml b/trading-platform/deploy/k8s/base/cert-manager/dashboard-mtls-cert.yaml deleted file mode 100644 index d45e3b5..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/dashboard-mtls-cert.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: dashboard-mtls-cert - namespace: customer1 -spec: - secretName: dashboard-mtls-secret - duration: 2160h # 90 days - renewBefore: 360h # 15 days - commonName: dashboard.customer1.svc.cluster.local - dnsNames: - - dashboard - - dashboard.customer1 - - dashboard.customer1.svc - - dashboard.customer1.svc.cluster.local - usages: - - digital signature - - key encipherment - - client auth - - server auth - issuerRef: - name: trading-platform-ca-issuer - kind: Issuer - group: cert-manager.io diff --git a/trading-platform/deploy/k8s/base/cert-manager/data-service-mtls-cert.yaml b/trading-platform/deploy/k8s/base/cert-manager/data-service-mtls-cert.yaml deleted file mode 100644 index e3e0acc..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/data-service-mtls-cert.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: data-service-mtls-cert - namespace: customer1 -spec: - secretName: data-service-mtls-secret - duration: 2160h # 90 days - renewBefore: 360h # 15 days - commonName: data-service.customer1.svc.cluster.local - dnsNames: - - data-service - - data-service.customer1 - - data-service.customer1.svc - - data-service.customer1.svc.cluster.local - usages: - - digital signature - - key encipherment - - client auth - - server auth - issuerRef: - name: trading-platform-ca-issuer - kind: Issuer - group: cert-manager.io diff --git a/trading-platform/deploy/k8s/base/cert-manager/execute-service-mtls-cert.yaml b/trading-platform/deploy/k8s/base/cert-manager/execute-service-mtls-cert.yaml deleted file mode 100644 index 5d5d430..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/execute-service-mtls-cert.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: execute-service-mtls-cert - namespace: customer1 -spec: - secretName: execute-service-mtls-secret - duration: 2160h # 90 days - renewBefore: 360h # 15 days - commonName: execute-service.customer1.svc.cluster.local - dnsNames: - - execute-service - - execute-service.customer1 - - execute-service.customer1.svc - - execute-service.customer1.svc.cluster.local - usages: - - digital signature - - key encipherment - - client auth - - server auth - issuerRef: - name: trading-platform-ca-issuer - kind: Issuer - group: cert-manager.io diff --git a/trading-platform/deploy/k8s/base/cert-manager/issuer.yaml b/trading-platform/deploy/k8s/base/cert-manager/issuer.yaml deleted file mode 100644 index 42eae6d..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/issuer.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: selfsigned-issuer - namespace: cert-manager -spec: - selfSigned: {} ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: trading-platform-ca - namespace: cert-manager -spec: - isCA: true - commonName: trading-platform-ca - secretName: trading-platform-ca-secret - privateKey: - algorithm: ECDSA - size: 256 - issuerRef: - name: selfsigned-issuer - kind: Issuer - group: cert-manager.io diff --git a/trading-platform/deploy/k8s/base/cert-manager/news-service-mtls-cert.yaml b/trading-platform/deploy/k8s/base/cert-manager/news-service-mtls-cert.yaml deleted file mode 100644 index ae15e24..0000000 --- a/trading-platform/deploy/k8s/base/cert-manager/news-service-mtls-cert.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: news-service-mtls-cert - namespace: customer1 -spec: - secretName: news-service-mtls-secret - duration: 2160h # 90 days - renewBefore: 360h # 15 days - commonName: news-service.customer1.svc.cluster.local - dnsNames: - - news-service - - news-service.customer1 - - news-service.customer1.svc - - news-service.customer1.svc.cluster.local - usages: - - digital signature - - key encipherment - - client auth - - server auth - issuerRef: - name: trading-platform-ca-issuer - kind: Issuer - group: cert-manager.io diff --git a/trading-platform/deploy/k8s/base/dashboard-deployment.yaml b/trading-platform/deploy/k8s/base/dashboard-deployment.yaml deleted file mode 100644 index c4e6b3d..0000000 --- a/trading-platform/deploy/k8s/base/dashboard-deployment.yaml +++ /dev/null @@ -1,78 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: dashboard - namespace: customer1 - labels: - app: dashboard - app.kubernetes.io/name: dashboard - app.kubernetes.io/component: microservice -spec: - replicas: 2 - selector: - matchLabels: - app: dashboard - template: - metadata: - labels: - app: dashboard - app.kubernetes.io/name: dashboard - app.kubernetes.io/component: microservice - spec: - automountServiceAccountToken: false - securityContext: - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 1000 - containers: - - name: dashboard - image: "trading-platform/dashboard:v${VERSION}" - ports: - - containerPort: 3000 - protocol: TCP - envFrom: - - configMapRef: - name: trading-platform-config - resources: - limits: - cpu: "500m" - memory: 512Mi - requests: - cpu: "250m" - memory: 256Mi - startupProbe: - httpGet: - path: /health - port: 3000 - initialDelaySeconds: 10 - periodSeconds: 10 - failureThreshold: 30 - livenessProbe: - httpGet: - path: /health - port: 3000 - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: 3000 - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - volumeMounts: - - name: tmp - mountPath: /tmp - volumes: - - name: tmp - emptyDir: {} diff --git a/trading-platform/deploy/k8s/base/dashboard-hpa.yaml b/trading-platform/deploy/k8s/base/dashboard-hpa.yaml deleted file mode 100644 index d7485a1..0000000 --- a/trading-platform/deploy/k8s/base/dashboard-hpa.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: dashboard-hpa - namespace: customer1 - labels: - app: dashboard -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: dashboard - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/trading-platform/deploy/k8s/base/dashboard-service.yaml b/trading-platform/deploy/k8s/base/dashboard-service.yaml deleted file mode 100644 index fafde36..0000000 --- a/trading-platform/deploy/k8s/base/dashboard-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: dashboard - namespace: customer1 - labels: - app: dashboard - app.kubernetes.io/name: dashboard - app.kubernetes.io/component: microservice -spec: - type: ClusterIP - ports: - - port: 3000 - targetPort: 3000 - protocol: TCP - name: http - selector: - app: dashboard diff --git a/trading-platform/deploy/k8s/base/data-service-deployment.yaml b/trading-platform/deploy/k8s/base/data-service-deployment.yaml deleted file mode 100644 index 5d45e5b..0000000 --- a/trading-platform/deploy/k8s/base/data-service-deployment.yaml +++ /dev/null @@ -1,78 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: data-service - namespace: customer1 - labels: - app: data-service - app.kubernetes.io/name: data-service - app.kubernetes.io/component: microservice -spec: - replicas: 2 - selector: - matchLabels: - app: data-service - template: - metadata: - labels: - app: data-service - app.kubernetes.io/name: data-service - app.kubernetes.io/component: microservice - spec: - automountServiceAccountToken: false - securityContext: - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 1000 - containers: - - name: data-service - image: "trading-platform/data-service:v${VERSION}" - ports: - - containerPort: 8001 - protocol: TCP - envFrom: - - configMapRef: - name: trading-platform-config - resources: - limits: - cpu: "1000m" - memory: 1Gi - requests: - cpu: "500m" - memory: 512Mi - startupProbe: - httpGet: - path: /health - port: 8001 - initialDelaySeconds: 10 - periodSeconds: 10 - failureThreshold: 30 - livenessProbe: - httpGet: - path: /health - port: 8001 - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: 8001 - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - volumeMounts: - - name: tmp - mountPath: /tmp - volumes: - - name: tmp - emptyDir: {} diff --git a/trading-platform/deploy/k8s/base/data-service-hpa.yaml b/trading-platform/deploy/k8s/base/data-service-hpa.yaml deleted file mode 100644 index 31c70e2..0000000 --- a/trading-platform/deploy/k8s/base/data-service-hpa.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: data-service-hpa - namespace: customer1 - labels: - app: data-service -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: data-service - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/trading-platform/deploy/k8s/base/data-service-service.yaml b/trading-platform/deploy/k8s/base/data-service-service.yaml deleted file mode 100644 index 03a0895..0000000 --- a/trading-platform/deploy/k8s/base/data-service-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: data-service - namespace: customer1 - labels: - app: data-service - app.kubernetes.io/name: data-service - app.kubernetes.io/component: microservice -spec: - type: ClusterIP - ports: - - port: 8001 - targetPort: 8001 - protocol: TCP - name: http - selector: - app: data-service diff --git a/trading-platform/deploy/k8s/base/execute-service-deployment.yaml b/trading-platform/deploy/k8s/base/execute-service-deployment.yaml deleted file mode 100644 index bc11a86..0000000 --- a/trading-platform/deploy/k8s/base/execute-service-deployment.yaml +++ /dev/null @@ -1,94 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: execute-service - namespace: customer1 - labels: - app: execute-service - app.kubernetes.io/name: execute-service - app.kubernetes.io/component: microservice -spec: - replicas: 2 - selector: - matchLabels: - app: execute-service - template: - metadata: - labels: - app: execute-service - app.kubernetes.io/name: execute-service - app.kubernetes.io/component: microservice - spec: - automountServiceAccountToken: false - securityContext: - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 1000 - containers: - - name: execute-service - image: "trading-platform/execute-service:v${VERSION}" - ports: - - containerPort: 8000 - protocol: TCP - envFrom: - - configMapRef: - name: trading-platform-config - env: - - name: EXECUTE_DB_USER - valueFrom: - secretKeyRef: - name: trading-db-credentials - key: username - - name: EXECUTE_DB_PASSWORD - valueFrom: - secretKeyRef: - name: trading-db-credentials - key: password - - name: JWT_SECRET_KEY - valueFrom: - secretKeyRef: - name: execute-service-secret - key: JWT_SECRET_KEY - resources: - limits: - cpu: "500m" - memory: 512Mi - requests: - cpu: "250m" - memory: 256Mi - startupProbe: - httpGet: - path: /health - port: 8000 - initialDelaySeconds: 10 - periodSeconds: 10 - failureThreshold: 30 - livenessProbe: - httpGet: - path: /health - port: 8000 - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: 8000 - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - volumeMounts: - - name: tmp - mountPath: /tmp - volumes: - - name: tmp - emptyDir: {} diff --git a/trading-platform/deploy/k8s/base/execute-service-hpa.yaml b/trading-platform/deploy/k8s/base/execute-service-hpa.yaml deleted file mode 100644 index bda8bf7..0000000 --- a/trading-platform/deploy/k8s/base/execute-service-hpa.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: execute-service-hpa - namespace: customer1 - labels: - app: execute-service -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: execute-service - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/trading-platform/deploy/k8s/base/execute-service-secret.yaml b/trading-platform/deploy/k8s/base/execute-service-secret.yaml deleted file mode 100644 index 800632f..0000000 --- a/trading-platform/deploy/k8s/base/execute-service-secret.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: execute-service-secret - namespace: customer1 - labels: - app: execute-service - app.kubernetes.io/name: execute-service -type: Opaque -stringData: - #ENC[AES256_GCM,data:cufebjrvQzeId2s78yHMCbP5,iv:sDAICkKMSOMTe2p+YZTudEGd0Y0vVVa4kf0qAE/2YPA=,tag:Sh1FtsV5LInk/L8dV+gJgg==,type:comment] - DB_PASSWORD: ENC[AES256_GCM,data:v8j+WH2Ix/uSoTUkm8gGGFavmlual+s=,iv:SsuW8bqGh9hU30Vg6+bOIV6KVadYFh3mkbwlAnpXUa4=,tag:BBMJ+beHsCL58Rg7csyjHw==,type:str] - #ENC[AES256_GCM,data:0Kp12yECmB0AOi2Hw2gTVK2TVKGrzTKul3kjbfdgnoouSETiAOdKnNI=,iv:JX7ea/tX88VvfYyfx5SxXSHzvXox2o1SPjG2PtStLQk=,tag:PwjxiNu+MoabsJy45BJPBA==,type:comment] - JWT_SECRET_KEY: ENC[AES256_GCM,data:qJFRby3voYIwonaI4DL1T4jG/q85dj2Q5KuSN5IYQONjsV7YUkZls3Q8H17oV58EfFhKVlF0gMYaypjFH9n4YA==,iv:QHJ3BJ2yAfaa+POx9/Cv3ASuwL/4wOg9R5AaYgalYgI=,tag:cGWxyTJFcrKBj1j8Ylr9lw==,type:str] -sops: - kms: [] - gcp_kms: [] - azure_kv: [] - hc_vault: [] - age: - - recipient: age1uuxf066xuuqgvjppxfcmqkwfcufnwp3wcwnl9h20g9k4l8nkw9jsaungf7 - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3WFdpY0VRQmliak4xVS8x - aGpORnYrZ2daZGFMMzRCOTh0a0lhanlKYmxrClR2VXRHVVliRVJMRUxKVkt0Y0Vw - VzZCenFtWmVoVkZqcFFYVlY3UjQxSzAKLS0tIFFZanArYU5PZFJlSitvMitzNUNI - YTNhdTdReG1maS91akdsbis0TFF3TXcKEvp821cnrAM4jITpiacbyxoE24FZhQ6O - PsDEpqRo2ck1aWDJROMV9HAlgxjIWzptJUNorP21m7/5TbgPGwjXnQ== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-05-25T01:24:10Z" - mac: ENC[AES256_GCM,data:1Xp5acLJaMux3itDF8Fyrz8YY0+YzF0OsWkDXLUffUG8ALKuMTT8IhFE4Nc5+gb8Bc8kfcx5VSNyCm9vKzcvYNwc/EHpe9CSZz5z2uHz1QQDZ5mK/4lbukpDEJhy9syb80TxulOwfrNbWwv1vnilN1uMT00lJKO9IXe3WbJ17qc=,iv:ZCc21Z41+HRX/qmgHgvvUFu+I8awN6+7UkSAhWLImXk=,tag:We4MhHcagW5bBiFtGo1yKQ==,type:str] - pgp: [] - encrypted_regex: ^(data|stringData)$ - version: 3.9.0 diff --git a/trading-platform/deploy/k8s/base/execute-service-service.yaml b/trading-platform/deploy/k8s/base/execute-service-service.yaml deleted file mode 100644 index 4d084bb..0000000 --- a/trading-platform/deploy/k8s/base/execute-service-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: execute-service - namespace: customer1 - labels: - app: execute-service - app.kubernetes.io/name: execute-service - app.kubernetes.io/component: microservice -spec: - type: ClusterIP - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP - name: http - selector: - app: execute-service diff --git a/trading-platform/deploy/k8s/base/ingress.yaml b/trading-platform/deploy/k8s/base/ingress.yaml deleted file mode 100644 index ed32132..0000000 --- a/trading-platform/deploy/k8s/base/ingress.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: api-gateway-ingress - namespace: customer1 - labels: - app: api-gateway - annotations: - nginx.ingress.kubernetes.io/ssl-redirect: "true" - nginx.ingress.kubernetes.io/proxy-body-size: "10m" - nginx.ingress.kubernetes.io/rate-limit: "100" - cert-manager.io/cluster-issuer: letsencrypt-prod -spec: - ingressClassName: nginx - tls: - - hosts: - - api.trading.example.com - - dashboard.trading.example.com - secretName: trading-tls-secret - rules: - - host: api.trading.example.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: api-gateway - port: - number: 8080 - - host: dashboard.trading.example.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: dashboard - port: - number: 3000 diff --git a/trading-platform/deploy/k8s/base/namespace.yaml b/trading-platform/deploy/k8s/base/namespace.yaml deleted file mode 100644 index 9952f89..0000000 --- a/trading-platform/deploy/k8s/base/namespace.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: customer1 - labels: - name: customer1 - istio-injection: disabled # Disable Istio if using native K8s policies ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: trading-platform-config - namespace: customer1 -data: - KAFKA_BOOTSTRAP_SERVERS: "kafka-headless:9092" - REDIS_URL: "redis://redis-master:6379/0" - LOG_LEVEL: "info" - TRADING_ENV: "production" diff --git a/trading-platform/deploy/k8s/base/news-service-deployment.yaml b/trading-platform/deploy/k8s/base/news-service-deployment.yaml deleted file mode 100644 index f003b91..0000000 --- a/trading-platform/deploy/k8s/base/news-service-deployment.yaml +++ /dev/null @@ -1,71 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: news-service - namespace: customer1 - labels: - app: news-service - app.kubernetes.io/name: news-service - app.kubernetes.io/component: microservice -spec: - replicas: 2 - selector: - matchLabels: - app: news-service - template: - metadata: - labels: - app: news-service - app.kubernetes.io/name: news-service - app.kubernetes.io/component: microservice - spec: - automountServiceAccountToken: false - securityContext: - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 1000 - containers: - - name: news-service - image: "trading-platform/news-service:v${VERSION}" - ports: - - containerPort: 8002 - protocol: TCP - envFrom: - - configMapRef: - name: trading-platform-config - resources: - limits: - cpu: "1000m" - memory: 1Gi - requests: - cpu: "500m" - memory: 512Mi - livenessProbe: - httpGet: - path: /health - port: 8002 - initialDelaySeconds: 15 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: 8002 - initialDelaySeconds: 5 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - volumeMounts: - - name: tmp - mountPath: /tmp - volumes: - - name: tmp - emptyDir: {} diff --git a/trading-platform/deploy/k8s/base/news-service-hpa.yaml b/trading-platform/deploy/k8s/base/news-service-hpa.yaml deleted file mode 100644 index 8d85e99..0000000 --- a/trading-platform/deploy/k8s/base/news-service-hpa.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: news-service-hpa - namespace: customer1 - labels: - app: news-service -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: news-service - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 diff --git a/trading-platform/deploy/k8s/base/news-service-service.yaml b/trading-platform/deploy/k8s/base/news-service-service.yaml deleted file mode 100644 index f9c0d21..0000000 --- a/trading-platform/deploy/k8s/base/news-service-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: news-service - namespace: customer1 - labels: - app: news-service - app.kubernetes.io/name: news-service - app.kubernetes.io/component: microservice -spec: - type: ClusterIP - ports: - - port: 8002 - targetPort: 8002 - protocol: TCP - name: http - selector: - app: news-service diff --git a/trading-platform/deploy/mtls/README.md b/trading-platform/deploy/mtls/README.md deleted file mode 100644 index c26b15f..0000000 --- a/trading-platform/deploy/mtls/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# ============================================================================= -# mTLS Configuration for Trading Platform -# ============================================================================= -# This directory contains certificates and configuration for mutual TLS -# between services. In production, use cert-manager to automate this. -# -# Option 1: cert-manager (recommended for production) -# Option 2: Manual certificate management (for dev/testing) -# -# Certificate hierarchy: -# Root CA -# ├── Service CA (issues service-to-service certs) -# │ ├── execute-service cert -# │ ├── data-service cert -# │ ├── news-service cert -# │ ├── api-gateway cert -# │ └── dashboard cert -# └── Ingress CA (for external-facing TLS) -# └── api-gateway TLS cert (for HTTPS) -# ============================================================================= diff --git a/trading-platform/deploy/scripts/deploy.sh b/trading-platform/deploy/scripts/deploy.sh deleted file mode 100755 index 5099285..0000000 --- a/trading-platform/deploy/scripts/deploy.sh +++ /dev/null @@ -1,141 +0,0 @@ -#!/bin/bash -# ============================================================================= -# Deploy Trading Platform to Kubernetes -# ============================================================================= -# -# Usage: -# ./deploy/scripts/deploy.sh [staging|production] [tag] -# -# Examples: -# ./deploy/scripts/deploy.sh staging latest -# ./deploy/scripts/deploy.sh production v1.2.3 -# -# Prerequisites: -# - kubectl configured with cluster access -# - Helm 3.x installed -# - Docker images pushed to registry -# - cert-manager installed in cluster (for TLS) -# ============================================================================= - -set -euo pipefail - -ENVIRONMENT="${1:-staging}" -IMAGE_TAG="${2:-latest}" -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" - -# Validate environment -if [[ ! "$ENVIRONMENT" =~ ^(staging|production)$ ]]; then - echo "ERROR: Environment must be 'staging' or 'production', got '$ENVIRONMENT'" - exit 1 -fi - -# Set namespace and values file based on environment -if [[ "$ENVIRONMENT" == "staging" ]]; then - NAMESPACE="customer1-staging" - VALUES_FILE="$PROJECT_ROOT/deploy/k8s/overlays/staging/kustomization.yaml" -else - NAMESPACE="customer1" - VALUES_FILE="$PROJECT_ROOT/deploy/k8s/overlays/production/kustomization.yaml" -fi - -echo "========================================================" -echo " Deploying Trading Platform to $ENVIRONMENT" -echo " Image tag: $IMAGE_TAG" -echo " Namespace: $NAMESPACE" -echo "========================================================" - -# Confirm cluster context -CURRENT_CONTEXT=$(kubectl config current-context 2>/dev/null || echo "unknown") -echo "Current kubectl context: $CURRENT_CONTEXT" -read -r -p "Continue? (y/N) " -n 1 -echo -if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Deployment cancelled." - exit 1 -fi - -# Install dependencies (optional) -echo "" -echo "Step 1/5: Checking prerequisites..." - -# Check for Helm -if ! command -v helm &>/dev/null; then - echo "ERROR: helm is not installed" - exit 1 -fi - -# Check for kubectl -if ! command -v kubectl &>/dev/null; then - echo "ERROR: kubectl is not installed" - exit 1 -fi - -# Check cluster connectivity -if ! kubectl cluster-info &>/dev/null; then - echo "ERROR: Cannot connect to Kubernetes cluster" - exit 1 -fi -echo " ✓ Kubernetes cluster is accessible" - -# Create namespace if it doesn't exist -kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - -echo " ✓ Namespace $NAMESPACE exists" - -# Step 2: Deploy infrastructure (PostgreSQL, Redis, Kafka) -echo "" -echo "Step 2/5: Deploying infrastructure..." -kubectl apply -f "$PROJECT_ROOT/deploy/k8s/base/namespace.yaml" -kubectl apply -f "$PROJECT_ROOT/deploy/k8s/base/configmap.yaml" -echo " ✓ ConfigMap applied" - -# Step 3: Deploy services -echo "" -echo "Step 3/5: Deploying microservices..." - -SERVICES=("execute-service" "data-service" "news-service" "api-gateway" "dashboard") - -for service in "${SERVICES[@]}"; do - echo " Deploying $service..." - kubectl apply -f "$PROJECT_ROOT/deploy/k8s/base/${service}-deployment.yaml" - kubectl apply -f "$PROJECT_ROOT/deploy/k8s/base/${service}-service.yaml" -done - -echo " ✓ All services deployed" - -# Step 4: Deploy ingress and networking -echo "" -echo "Step 4/5: Configuring ingress and networking..." -kubectl apply -f "$PROJECT_ROOT/deploy/k8s/base/ingress.yaml" -echo " ✓ Ingress configured" - -# Apply NetworkPolicies from security review -if [[ -d "$PROJECT_ROOT/trading-platform/security/network-policies" ]]; then - kubectl apply -f "$PROJECT_ROOT/trading-platform/security/network-policies/" - echo " ✓ NetworkPolicies applied" -fi - -# Step 5: Wait for rollouts -echo "" -echo "Step 5/5: Waiting for deployments to stabilize..." - -for service in "${SERVICES[@]}"; do - echo " Waiting for $service..." - if ! kubectl rollout status "deployment/${service}" -n "$NAMESPACE" --timeout=5m; then - echo "WARNING: $service rollout timed out" - echo " Check pods: kubectl get pods -n $NAMESPACE -l app=$service" - echo " Check logs: kubectl logs -n $NAMESPACE -l app=$service --tail=100" - exit 1 - fi -done - -echo "" -echo "========================================================" -echo " Deployment complete! All services running." -echo "========================================================" -echo "" -echo "Useful commands:" -echo " kubectl get pods -n $NAMESPACE" -echo " kubectl get svc -n $NAMESPACE" -echo " kubectl get ingress -n $NAMESPACE" -echo " kubectl logs -n $NAMESPACE -l app=$service -f" diff --git a/trading-platform/deploy/scripts/generate-mtls-certs.sh b/trading-platform/deploy/scripts/generate-mtls-certs.sh deleted file mode 100755 index a43b697..0000000 --- a/trading-platform/deploy/scripts/generate-mtls-certs.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/bash -# ============================================================================= -# Manual mTLS certificate generation script (for dev/testing only) -# ============================================================================= -# In production, use cert-manager (see k8s/base/cert-manager/). -# This script generates self-signed certificates for local testing. -# -# Usage: -# ./deploy/scripts/generate-mtls-certs.sh -# -# Output: deploy/mtls/ -# ============================================================================= - -set -euo pipefail - -OUTPUT_DIR="deploy/mtls" -SERVICES=("execute-service" "data-service" "news-service" "api-gateway" "dashboard") -DAYS_VALID=365 - -mkdir -p "$OUTPUT_DIR/ca" "$OUTPUT_DIR/certs" - -# ── Generate Root CA ──────────────────────────────────────────────────────── -echo "Generating Root CA..." -openssl genrsa -out "$OUTPUT_DIR/ca/ca.key" 4096 2>/dev/null -openssl req -x509 -new -nodes \ - -key "$OUTPUT_DIR/ca/ca.key" \ - -sha256 \ - -days $DAYS_VALID \ - -out "$OUTPUT_DIR/ca/ca.crt" \ - -subj "/C=US/ST=California/O=TradingPlatform/CN=Trading Platform Root CA" - -# ── Generate Service Certificates ──────────────────────────────────────────── -for SERVICE in "${SERVICES[@]}"; do - echo "Generating certificate for $SERVICE..." - - # Generate private key - openssl genrsa \ - -out "$OUTPUT_DIR/certs/${SERVICE}.key" 2048 2>/dev/null - - # Generate CSR - openssl req -new \ - -key "$OUTPUT_DIR/certs/${SERVICE}.key" \ - -out "$OUTPUT_DIR/certs/${SERVICE}.csr" \ - -subj "/C=US/ST=California/O=TradingPlatform/CN=${SERVICE}.customer1.svc.cluster.local" \ - -addext "subjectAltName=DNS:${SERVICE},DNS:${SERVICE}.customer1,DNS:${SERVICE}.customer1.svc.cluster.local" - - # Sign with CA - openssl x509 -req \ - -in "$OUTPUT_DIR/certs/${SERVICE}.csr" \ - -CA "$OUTPUT_DIR/ca/ca.crt" \ - -CAkey "$OUTPUT_DIR/ca/ca.key" \ - -CAcreateserial \ - -out "$OUTPUT_DIR/certs/${SERVICE}.crt" \ - -days $DAYS_VALID \ - -sha256 \ - -extfile <(printf "subjectAltName=DNS:${SERVICE},DNS:${SERVICE}.customer1,DNS:${SERVICE}.customer1.svc.cluster.local") - - # Clean up CSR - rm "$OUTPUT_DIR/certs/${SERVICE}.csr" -done - -echo "Done! All certificates generated in $OUTPUT_DIR/certs/" -echo "CA certificate: $OUTPUT_DIR/ca/ca.crt" -echo "" -echo "To verify a certificate:" -echo " openssl verify -CAfile $OUTPUT_DIR/ca/ca.crt $OUTPUT_DIR/certs/.crt" diff --git a/trading-platform/dockerfiles/dashboard/.dockerignore b/trading-platform/dockerfiles/dashboard/.dockerignore deleted file mode 100644 index 4443f35..0000000 --- a/trading-platform/dockerfiles/dashboard/.dockerignore +++ /dev/null @@ -1,10 +0,0 @@ -node_modules/ -.next/ -out/ -dist/ -.env* -.git/ -.vscode/ -coverage/ -.idea/ -*.log diff --git a/trading-platform/dockerfiles/dashboard/Dockerfile b/trading-platform/dockerfiles/dashboard/Dockerfile deleted file mode 100644 index 5f5d93a..0000000 --- a/trading-platform/dockerfiles/dashboard/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -# Multi-stage build for Next.js dashboard -# ---- Builder ---- -FROM node:20-alpine AS builder -WORKDIR /app -COPY package.json package-lock.json ./ -RUN npm ci -COPY . . -RUN npm run build - -# ---- Production ---- -FROM node:20-alpine AS runner -ENV NODE_ENV=production - -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 nextjs - -WORKDIR /app -COPY --from=builder /app/public ./public -COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ -COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static - -USER nextjs - -EXPOSE 3000 -ENV PORT=3000 -ENV HOSTNAME="0.0.0.0" - -HEALTHCHECK --interval=15s --timeout=5s --start-period=20s --retries=3 \\ - CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT}/ || exit 1 - -CMD ["node", "server.js"] diff --git a/trading-platform/dockerfiles/data-service/.dockerignore b/trading-platform/dockerfiles/data-service/.dockerignore deleted file mode 100644 index be876f2..0000000 --- a/trading-platform/dockerfiles/data-service/.dockerignore +++ /dev/null @@ -1,10 +0,0 @@ -# Python Docker ignores -__pycache__/ -*.pyc -.venv/ -venv/ -*.egg-info/ -.pytest_cache/ -.git/ -.env -tests/ diff --git a/trading-platform/dockerfiles/data-service/Dockerfile b/trading-platform/dockerfiles/data-service/Dockerfile deleted file mode 100644 index 6b9cde4..0000000 --- a/trading-platform/dockerfiles/data-service/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# Multi-stage build for data-service (Postgres + Redis + Kafka consumers) -FROM python:3.12-slim AS builder -WORKDIR /build -COPY pyproject.toml . -RUN pip install --no-cache-dir --prefix=/install . - -FROM python:3.12-slim -RUN useradd -m --system appuser - -COPY --from=builder /install /usr/local - -WORKDIR /app -COPY --chown=appuser:appuser data_service/ ./data_service/ -COPY --chown=appuser:appuser pyproject.toml alembic.ini ./ - -USER appuser - -HEALTHCHECK --interval=15s --timeout=5s --start-period=15s --retries=3 \\ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1 - -EXPOSE 8000 - -CMD ["uvicorn", "data_service.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/trading-platform/dockerfiles/execute-service/.dockerignore b/trading-platform/dockerfiles/execute-service/.dockerignore deleted file mode 100644 index be876f2..0000000 --- a/trading-platform/dockerfiles/execute-service/.dockerignore +++ /dev/null @@ -1,10 +0,0 @@ -# Python Docker ignores -__pycache__/ -*.pyc -.venv/ -venv/ -*.egg-info/ -.pytest_cache/ -.git/ -.env -tests/ diff --git a/trading-platform/dockerfiles/execute-service/Dockerfile b/trading-platform/dockerfiles/execute-service/Dockerfile deleted file mode 100644 index e64268b..0000000 --- a/trading-platform/dockerfiles/execute-service/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -# Multi-stage build for execute-service (Hyperliquid + Solana trading engine) -FROM python:3.12-slim AS builder -WORKDIR /build -COPY pyproject.toml ./ -RUN pip install --no-cache-dir --prefix=/install . - -FROM python:3.12-slim -RUN useradd -m --system appuser - -COPY --from=builder /install /usr/local - -WORKDIR /app -COPY --chown=appuser:appuser app/ ./app/ -COPY --chown=appuser:appuser pyproject.toml ./ - -USER appuser - -HEALTHCHECK --interval=15s --timeout=5s --start-period=15s --retries=3 \\ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1 - -EXPOSE 8000 - -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/trading-platform/dockerfiles/news-service/.dockerignore b/trading-platform/dockerfiles/news-service/.dockerignore deleted file mode 100644 index be876f2..0000000 --- a/trading-platform/dockerfiles/news-service/.dockerignore +++ /dev/null @@ -1,10 +0,0 @@ -# Python Docker ignores -__pycache__/ -*.pyc -.venv/ -venv/ -*.egg-info/ -.pytest_cache/ -.git/ -.env -tests/ diff --git a/trading-platform/dockerfiles/news-service/Dockerfile b/trading-platform/dockerfiles/news-service/Dockerfile deleted file mode 100644 index 286969b..0000000 --- a/trading-platform/dockerfiles/news-service/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -# Multi-stage build for news-service (CNPG connector + Kafka producer) -FROM python:3.12-slim AS builder -WORKDIR /build -COPY requirements.txt . -RUN pip install --no-cache-dir --prefix=/install -r requirements.txt - -FROM python:3.12-slim -RUN useradd -m --system appuser - -# Copy installed deps from builder -COPY --from=builder /install /usr/local - -# Install system deps for NLTK -RUN apt-get update && \\ - apt-get install -y --no-install-recommends gcc libpq-dev && \\ - rm -rf /var/lib/apt/lists/* - -# Download NLTK data as root before switching user -RUN python -c "import nltk; nltk.download('punkt'); nltk.download('punkt_tab'); nltk.download('averaged_perceptron_tagger')" - -WORKDIR /app -COPY --chown=appuser:appuser . . -USER appuser - -HEALTHCHECK --interval=15s --timeout=5s --start-period=15s --retries=3 \\ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1 - -EXPOSE 8000 - -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"] diff --git a/trading-platform/helm/.sops.yaml b/trading-platform/helm/.sops.yaml deleted file mode 100644 index 35ae57e..0000000 --- a/trading-platform/helm/.sops.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# SOPS configuration for trading platform secrets -# Usage: sops -e -i trading-secrets.yaml && kubectl apply -f trading-secrets.yaml -creation_rules: - # Production secrets - encrypted with Age key - - path_regex: trading-secrets.yaml$ - encrypted_regex: "^(stringData|data)$" - age: >- - age1ql3z7hjy54pw3hyww5ayyfg7zqgvcnw3eks6lekrq733qkq76jwqgq3g20 - - # Per-environment overrides - - path_regex: .*/staging/trading-secrets.yaml$ - encrypted_regex: "^(stringData|data)$" - age: >- - age1ql3z7hjy54pw3hyww5ayyfg7zqgvcnq76jwqgq3g20 - - - path_regex: .*/production/trading-secrets.yaml$ - encrypted_regex: "^(stringData|data)$" - age: >- - age1ql3z7hjy54pw3hyww5ayyfg7zqgvcnq76jwqgq3g20 diff --git a/trading-platform/helm/trading-platform/.sops.yaml b/trading-platform/helm/trading-platform/.sops.yaml deleted file mode 100644 index 35ae57e..0000000 --- a/trading-platform/helm/trading-platform/.sops.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# SOPS configuration for trading platform secrets -# Usage: sops -e -i trading-secrets.yaml && kubectl apply -f trading-secrets.yaml -creation_rules: - # Production secrets - encrypted with Age key - - path_regex: trading-secrets.yaml$ - encrypted_regex: "^(stringData|data)$" - age: >- - age1ql3z7hjy54pw3hyww5ayyfg7zqgvcnw3eks6lekrq733qkq76jwqgq3g20 - - # Per-environment overrides - - path_regex: .*/staging/trading-secrets.yaml$ - encrypted_regex: "^(stringData|data)$" - age: >- - age1ql3z7hjy54pw3hyww5ayyfg7zqgvcnq76jwqgq3g20 - - - path_regex: .*/production/trading-secrets.yaml$ - encrypted_regex: "^(stringData|data)$" - age: >- - age1ql3z7hjy54pw3hyww5ayyfg7zqgvcnq76jwqgq3g20 diff --git a/trading-platform/helm/trading-platform/Chart.yaml b/trading-platform/helm/trading-platform/Chart.yaml deleted file mode 100644 index 533fb8e..0000000 --- a/trading-platform/helm/trading-platform/Chart.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v2 -name: trading-platform -description: Helm chart for the DEFi trading platform microservices on GKE -type: application -version: 0.1.0 -appVersion: "0.1.0" -keywords: - - trading - - defi - - microservices -maintainers: - - name: Trading Platform Team diff --git a/trading-platform/helm/trading-platform/templates/NOTES.txt b/trading-platform/helm/trading-platform/templates/NOTES.txt deleted file mode 100644 index afc553a..0000000 --- a/trading-platform/helm/trading-platform/templates/NOTES.txt +++ /dev/null @@ -1,29 +0,0 @@ -Trading Platform deployed successfully! - -Namespace: {{ .Values.global.namespace }} -Release: {{ .Release.Name }} -Environment: {{ .Values.global.environment | default "not set" }} - -Services deployed: - - execute-service: {{ .Values.executeService.enabled }} - - news-service: {{ .Values.newsService.enabled }} - - data-service: {{ .Values.dataService.enabled }} - - dashboard: {{ .Values.dashboard.enabled }} - -Infrastructure: - - PostgreSQL: {{ .Values.postgres.enabled }} - - Redis: {{ .Values.redis.enabled }} - - Kafka: {{ .Values.kafka.enabled }} - -Ingress: {{ .Values.ingress.enabled }} -{{- if .Values.ingress.enabled }} -{{- range .Values.ingress.hosts }} - Host: {{ .host }} -{{- end }} -{{- end }} - -Next steps: -1. Verify pods: kubectl get pods -n {{ .Values.global.namespace }} -2. Check services: kubectl get svc -n {{ .Values.global.namespace }} -3. Check ingress: kubectl get ingress -n {{ .Values.global.namespace }} -4. If using SOPS, decrypt secrets: sops -d trading-secrets.yaml | kubectl apply -f - diff --git a/trading-platform/helm/trading-platform/templates/_helpers.tpl b/trading-platform/helm/trading-platform/templates/_helpers.tpl deleted file mode 100644 index fa8c6d2..0000000 --- a/trading-platform/helm/trading-platform/templates/_helpers.tpl +++ /dev/null @@ -1,94 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "trading-platform.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -*/}} -{{- define "trading-platform.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "trading-platform.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "trading-platform.labels" -}} -helm.sh/chart: {{ include "trading-platform.chart" . }} -{{ include "trading-platform.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "trading-platform.selectorLabels" -}} -app.kubernetes.io/name: {{ include "trading-platform.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Service-specific labels -*/}} -{{- define "trading-platform.serviceLabels" -}} -{{- $service := index . 0 }} -{{- $parent := index . 1 }} -{{ include "trading-platform.selectorLabels" $parent }} -app: {{ $service.Values.name | default $service.Values.name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "trading-platform.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "trading-platform.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - -{{/* -Generate env var map from values -*/}} -{{- define "trading-platform.envVars" -}} -{{- range $key, $value := . }} -- name: {{ $key }} - value: {{ $value | quote }} -{{- end }} -{{- end }} - -{{/* -Generate secret env var refs -*/}} -{{- define "trading-platform.secretEnvVars" -}} -{{- range $key, $secretRef := . }} -- name: {{ $key }} - valueFrom: - secretKeyRef: - {{- $parts := split "/" $secretRef }} - name: {{ $parts._0 }} - key: {{ $parts._1 }} -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/cert-manager/certificates.yaml b/trading-platform/helm/trading-platform/templates/cert-manager/certificates.yaml deleted file mode 100644 index fb86f8c..0000000 --- a/trading-platform/helm/trading-platform/templates/cert-manager/certificates.yaml +++ /dev/null @@ -1,128 +0,0 @@ -{{- if .Values.certManager.enabled }} -# External issuer (Let's Encrypt) for public-facing TLS -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: {{ .Values.certManager.externalIssuer.name }} -spec: - acme: - server: {{ .Values.certManager.externalIssuer.server }} - email: {{ .Values.certManager.externalIssuer.email }} - privateKeySecretRef: - name: {{ .Values.certManager.externalIssuer.name }}-key - solvers: - - http01: - ingress: - class: {{ .Values.ingress.className }} ---- -# Internal self-signed CA for service-to-service mTLS -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: {{ .Values.certManager.internalIssuer.name }} - namespace: {{ .Values.global.namespace }} -spec: - selfSigned: {} ---- -# CA certificate issued by the self-signed issuer -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: trading-ca - namespace: {{ .Values.global.namespace }} -spec: - isCA: true - commonName: "trading-ca" - secretName: trading-ca-secret - privateKey: - algorithm: ECDSA - size: 256 - issuerRef: - name: {{ .Values.certManager.internalIssuer.name }} - kind: Issuer - group: cert-manager.io ---- -# CA issuer for signing service certificates -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: trading-ca-issuer - namespace: {{ .Values.global.namespace }} -spec: - ca: - secretName: trading-ca-secret ---- -# mTLS certificate for execute-service -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: execute-service-mtls - namespace: {{ .Values.global.namespace }} -spec: - dnsNames: - - execute-service - - execute-service.{{ .Values.global.namespace }}.svc.cluster.local - secretName: execute-service-mtls - privateKey: - algorithm: ECDSA - size: 256 - issuerRef: - name: trading-ca-issuer - kind: Issuer - group: cert-manager.io ---- -# mTLS certificate for news-service -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: news-service-mtls - namespace: {{ .Values.global.namespace }} -spec: - dnsNames: - - news-service - - news-service.{{ .Values.global.namespace }}.svc.cluster.local - secretName: news-service-mtls - privateKey: - algorithm: ECDSA - size: 256 - issuerRef: - name: trading-ca-issuer - kind: Issuer - group: cert-manager.io ---- -# mTLS certificate for data-service -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: data-service-mtls - namespace: {{ .Values.global.namespace }} -spec: - dnsNames: - - data-service - - data-service.{{ .Values.global.namespace }}.svc.cluster.local - secretName: data-service-mtls - privateKey: - algorithm: ECDSA - size: 256 - issuerRef: - name: trading-ca-issuer - kind: Issuer - group: cert-manager.io ---- -# TLS certificate for the public domain (ingress) -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: trading-tls - namespace: {{ .Values.global.namespace }} -spec: - secretName: trading-tls - dnsNames: - {{- range $host := .Values.ingress.hosts }} - - {{ $host.host }} - {{- end }} - issuerRef: - name: {{ .Values.certManager.externalIssuer.name }} - kind: ClusterIssuer - group: cert-manager.io -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/configmap.yaml b/trading-platform/helm/trading-platform/templates/configmap.yaml deleted file mode 100644 index 20d7b05..0000000 --- a/trading-platform/helm/trading-platform/templates/configmap.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Shared ConfigMap for trading platform configuration -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "trading-platform.fullname" . }}-config - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} -data: - # Shared environment configuration - ENVIRONMENT: {{ .Values.global.environment | quote }} - CLUSTER_NAME: {{ .Values.global.clusterName | quote }} - NAMESPACE: {{ .Values.global.namespace | quote }} - # Kafka bootstrap (internal DNS) - KAFKA_BOOTSTRAP: kafka-headless.{{ .Values.global.namespace }}.svc.cluster.local:9092 - # Redis connection - REDIS_HOST: redis-master.{{ .Values.global.namespace }}.svc.cluster.local - REDIS_PORT: "6379" - # PostgreSQL connection (execute-service uses EXECUTE_ prefix) - EXECUTE_DB_HOST: postgres-primary.{{ .Values.global.namespace }}.svc.cluster.local - EXECUTE_DB_PORT: "5432" - EXECUTE_DB_NAME: "trading_data" - # Legacy keys (other services) - POSTGRES_HOST: postgres-primary.{{ .Values.global.namespace }}.svc.cluster.local - POSTGRES_PORT: "5432" - # Solana RPC (ExternalName service) - {{- if .Values.solanaRpc.enabled }} - SOLANA_RPC_URL: "http://solana-rpc.{{ .Values.global.namespace }}.svc.cluster.local:{{ .Values.solanaRpc.port }}" - {{- end }} diff --git a/trading-platform/helm/trading-platform/templates/dashboard/deployment.yaml b/trading-platform/helm/trading-platform/templates/dashboard/deployment.yaml deleted file mode 100644 index aeffdd0..0000000 --- a/trading-platform/helm/trading-platform/templates/dashboard/deployment.yaml +++ /dev/null @@ -1,64 +0,0 @@ -{{- if .Values.dashboard.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.dashboard.name }} - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app: {{ .Values.dashboard.name }} -spec: - {{- if not .Values.dashboard.autoscaling.enabled }} - replicas: {{ .Values.global.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "trading-platform.selectorLabels" . | nindent 6 }} - app: {{ .Values.dashboard.name }} - template: - metadata: - labels: - {{- include "trading-platform.selectorLabels" . | nindent 8 }} - app: {{ .Values.dashboard.name }} - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.dashboard.port }}" - spec: - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Values.dashboard.name }} - image: "{{ .Values.dashboard.image.repository }}:{{ .Values.dashboard.image.tag }}" - imagePullPolicy: {{ .Values.dashboard.image.pullPolicy }} - ports: - - name: http - containerPort: {{ .Values.dashboard.port }} - protocol: TCP - env: - {{- range $key, $value := .Values.dashboard.env }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - resources: - {{- toYaml .Values.dashboard.resources | nindent 12 }} - securityContext: - {{- toYaml .Values.containerSecurityContext | nindent 12 }} - livenessProbe: - httpGet: - path: / - port: http - initialDelaySeconds: 20 - periodSeconds: 10 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: / - port: http - initialDelaySeconds: 15 - periodSeconds: 5 - timeoutSeconds: 3 - {{- with .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/dashboard/service.yaml b/trading-platform/helm/trading-platform/templates/dashboard/service.yaml deleted file mode 100644 index 3b11066..0000000 --- a/trading-platform/helm/trading-platform/templates/dashboard/service.yaml +++ /dev/null @@ -1,40 +0,0 @@ -{{- if .Values.dashboard.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.dashboard.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.dashboard.name }} -spec: - type: ClusterIP - ports: - - port: {{ .Values.dashboard.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ .Values.dashboard.name }} ---- -{{- if .Values.dashboard.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ .Values.dashboard.name }} - namespace: {{ .Values.global.namespace }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ .Values.dashboard.name }} - minReplicas: {{ .Values.dashboard.autoscaling.minReplicas }} - maxReplicas: {{ .Values.dashboard.autoscaling.maxReplicas }} - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.dashboard.autoscaling.targetCPUUtilizationPercentage }} -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/data-service/deployment.yaml b/trading-platform/helm/trading-platform/templates/data-service/deployment.yaml deleted file mode 100644 index 0463b4a..0000000 --- a/trading-platform/helm/trading-platform/templates/data-service/deployment.yaml +++ /dev/null @@ -1,89 +0,0 @@ -{{- if .Values.dataService.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.dataService.name }} - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app: {{ .Values.dataService.name }} -spec: - {{- if not .Values.dataService.autoscaling.enabled }} - replicas: {{ .Values.global.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "trading-platform.selectorLabels" . | nindent 6 }} - app: {{ .Values.dataService.name }} - template: - metadata: - labels: - {{- include "trading-platform.selectorLabels" . | nindent 8 }} - app: {{ .Values.dataService.name }} - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.dataService.port }}" - spec: - serviceAccountName: {{ .Values.dataService.name }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Values.dataService.name }} - image: "{{ .Values.dataService.image.repository }}:{{ .Values.dataService.image.tag }}" - imagePullPolicy: {{ .Values.dataService.image.pullPolicy }} - ports: - - name: http - containerPort: {{ .Values.dataService.port }} - protocol: TCP - env: - {{- range $key, $value := .Values.dataService.env }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - - name: DB_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: POSTGRES_HOST - - name: REDIS_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: REDIS_HOST - - name: KAFKA_BOOTSTRAP_SERVERS - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: KAFKA_BOOTSTRAP - envFrom: - - secretRef: - name: trading-secrets - resources: - {{- toYaml .Values.dataService.resources | nindent 12 }} - securityContext: - {{- toYaml .Values.containerSecurityContext | nindent 12 }} - volumeMounts: - - name: tmp - mountPath: /tmp - livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 10 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - periodSeconds: 5 - timeoutSeconds: 3 - volumes: - - name: tmp - emptyDir: {} - {{- with .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/data-service/service.yaml b/trading-platform/helm/trading-platform/templates/data-service/service.yaml deleted file mode 100644 index 73dd9f0..0000000 --- a/trading-platform/helm/trading-platform/templates/data-service/service.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if .Values.dataService.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.dataService.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.dataService.name }} -spec: - type: ClusterIP - ports: - - port: {{ .Values.dataService.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ .Values.dataService.name }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.dataService.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.dataService.name }} ---- -{{- if .Values.dataService.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ .Values.dataService.name }} - namespace: {{ .Values.global.namespace }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ .Values.dataService.name }} - minReplicas: {{ .Values.dataService.autoscaling.minReplicas }} - maxReplicas: {{ .Values.dataService.autoscaling.maxReplicas }} - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.dataService.autoscaling.targetCPUUtilizationPercentage }} -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/execute-service/deployment.yaml b/trading-platform/helm/trading-platform/templates/execute-service/deployment.yaml deleted file mode 100644 index 48680d0..0000000 --- a/trading-platform/helm/trading-platform/templates/execute-service/deployment.yaml +++ /dev/null @@ -1,112 +0,0 @@ -{{- if .Values.executeService.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.executeService.name }} - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app: {{ .Values.executeService.name }} -spec: - {{- if not .Values.executeService.autoscaling.enabled }} - replicas: {{ .Values.global.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "trading-platform.selectorLabels" . | nindent 6 }} - app: {{ .Values.executeService.name }} - template: - metadata: - labels: - {{- include "trading-platform.selectorLabels" . | nindent 8 }} - app: {{ .Values.executeService.name }} - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.executeService.port }}" - spec: - serviceAccountName: {{ .Values.executeService.name }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Values.executeService.name }} - image: "{{ .Values.executeService.image.repository }}:{{ .Values.executeService.image.tag }}" - imagePullPolicy: {{ .Values.executeService.image.pullPolicy }} - ports: - - name: http - containerPort: {{ .Values.executeService.port }} - protocol: TCP - env: - {{- range $key, $value := .Values.executeService.env }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - # Shared config from ConfigMap - - name: DB_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: POSTGRES_HOST - - name: REDIS_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: REDIS_HOST - - name: KAFKA_BOOTSTRAP_SERVERS - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: KAFKA_BOOTSTRAP - envFrom: - - secretRef: - name: trading-secrets - resources: - {{- toYaml .Values.executeService.resources | nindent 12 }} - securityContext: - {{- toYaml .Values.containerSecurityContext | nindent 12 }} - volumeMounts: - - name: tmp - mountPath: /tmp - - name: mtls-certs - mountPath: /etc/mtls - readOnly: true - livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health/ready - port: http - initialDelaySeconds: 10 - periodSeconds: 5 - timeoutSeconds: 3 - failureThreshold: 3 - volumes: - - name: tmp - emptyDir: {} - - name: mtls-certs - secret: - secretName: execute-service-mtls - {{- with .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - nodeSelector: - kubernetes.io/os: linux - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - {{ .Values.executeService.name }} - topologyKey: kubernetes.io/hostname -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/execute-service/service.yaml b/trading-platform/helm/trading-platform/templates/execute-service/service.yaml deleted file mode 100644 index 575ae85..0000000 --- a/trading-platform/helm/trading-platform/templates/execute-service/service.yaml +++ /dev/null @@ -1,50 +0,0 @@ -{{- if .Values.executeService.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.executeService.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.executeService.name }} -spec: - type: ClusterIP - ports: - - port: {{ .Values.executeService.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ .Values.executeService.name }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.executeService.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.executeService.name }} - annotations: - iam.gke.io/gcp-service-account: execute-service@{{ .Values.global.clusterName }}.iam.gserviceaccount.com ---- -{{- if .Values.executeService.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ .Values.executeService.name }} - namespace: {{ .Values.global.namespace }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ .Values.executeService.name }} - minReplicas: {{ .Values.executeService.autoscaling.minReplicas }} - maxReplicas: {{ .Values.executeService.autoscaling.maxReplicas }} - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.executeService.autoscaling.targetCPUUtilizationPercentage }} -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/infrastructure/kafka.yaml b/trading-platform/helm/trading-platform/templates/infrastructure/kafka.yaml deleted file mode 100644 index cccd908..0000000 --- a/trading-platform/helm/trading-platform/templates/infrastructure/kafka.yaml +++ /dev/null @@ -1,142 +0,0 @@ -{{- if .Values.kafka.enabled }} -# Headless service for KRaft discovery -apiVersion: v1 -kind: Service -metadata: - name: kafka-headless - namespace: {{ .Values.global.namespace }} - labels: - app: kafka -spec: - ports: - - port: 9092 - targetPort: 9092 - name: kafka - - port: 9093 - targetPort: 9093 - name: controller - clusterIP: None - selector: - app: kafka ---- -# Client-facing service -apiVersion: v1 -kind: Service -metadata: - name: kafka - namespace: {{ .Values.global.namespace }} - labels: - app: kafka -spec: - type: ClusterIP - ports: - - port: 9092 - targetPort: 9092 - name: kafka - selector: - app: kafka ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: kafka - namespace: {{ .Values.global.namespace }} - labels: - app: kafka -spec: - serviceName: kafka-headless - replicas: {{ .Values.kafka.replicaCount }} - selector: - matchLabels: - app: kafka - template: - metadata: - labels: - app: kafka - spec: - securityContext: - runAsNonRoot: true - runAsUser: 1000 - fsGroup: 1000 - containers: - - name: kafka - image: "{{ .Values.kafka.image.repository }}:{{ .Values.kafka.image.tag }}" - ports: - - containerPort: 9092 - name: kafka - - containerPort: 9093 - name: controller - env: - - name: KAFKA_NODE_ID - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: KAFKA_PROCESS_ROLES - value: "broker,controller" - - name: KAFKA_CONTROLLER_QUORUM_VOTERS - value: | - {{- $ns := .Values.global.namespace }} - {{- range $i := until (int .Values.kafka.replicaCount) }} - {{- $i }}@kafka-{{ $i }}.kafka-headless.{{ $ns }}.svc.cluster.local:9093{{ if lt (add $i 1) (int $.Values.kafka.replicaCount) }},{{ end }} - {{- end }} - - name: KAFKA_CONTROLLER_LISTENER_NAMES - value: "CONTROLLER" - - name: KAFKA_LISTENERS - value: "PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093" - - name: KAFKA_ADVERTISED_LISTENERS - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP - value: "PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT" - - name: KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR - value: "{{ .Values.kafka.replicaCount }}" - - name: KAFKA_TRANSACTION_STATE_LOG_MIN_ISR - value: "{{ add1 (div (int .Values.kafka.replicaCount) 2) }}" - - name: KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR - value: "{{ .Values.kafka.replicaCount }}" - - name: KAFKA_AUTO_CREATE_TOPICS_ENABLE - value: "true" - - name: KAFKA_NUM_PARTITIONS - value: "6" - - name: KAFKA_DEFAULT_REPLICATION_FACTOR - value: "{{ .Values.kafka.replicaCount }}" - - name: KAFKA_LOG_DIRS - value: "/var/lib/kafka/data" - resources: - {{- toYaml .Values.kafka.resources | nindent 12 }} - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - volumeMounts: - - name: kafka-data - mountPath: /var/lib/kafka/data - - name: tmp - mountPath: /tmp - livenessProbe: - tcpSocket: - port: kafka - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - readinessProbe: - tcpSocket: - port: kafka - initialDelaySeconds: 20 - periodSeconds: 5 - timeoutSeconds: 3 - volumes: - - name: tmp - emptyDir: {} - volumeClaimTemplates: - - metadata: - name: kafka-data - spec: - accessModes: ["ReadWriteOnce"] - storageClassName: {{ .Values.kafka.storage.storageClass }} - resources: - requests: - storage: {{ .Values.kafka.storage.size }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/infrastructure/postgres.yaml b/trading-platform/helm/trading-platform/templates/infrastructure/postgres.yaml deleted file mode 100644 index 8567095..0000000 --- a/trading-platform/helm/trading-platform/templates/infrastructure/postgres.yaml +++ /dev/null @@ -1,111 +0,0 @@ -{{- if .Values.postgres.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: postgres-primary - namespace: {{ .Values.global.namespace }} - labels: - app: postgres -spec: - type: ClusterIP - ports: - - port: 5432 - targetPort: postgres - protocol: TCP - name: postgres - selector: - app: postgres - role: primary ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: postgres - namespace: {{ .Values.global.namespace }} - labels: - app: postgres -spec: - serviceName: postgres-primary - replicas: {{ .Values.postgres.primary.replicaCount }} - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - role: primary - spec: - securityContext: - runAsNonRoot: true - runAsUser: 999 - runAsGroup: 999 - fsGroup: 999 - containers: - - name: postgres - image: "{{ .Values.postgres.image.repository }}:{{ .Values.postgres.image.tag }}" - ports: - - containerPort: 5432 - name: postgres - env: - - name: POSTGRES_USER - value: "trading" - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: trading-secrets - key: POSTGRES_PASSWORD - - name: POSTGRES_DB - value: {{ .Values.postgres.postgresqlDatabase | quote }} - resources: - {{- toYaml .Values.postgres.primary.resources | nindent 12 }} - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - capabilities: - drop: - - ALL - volumeMounts: - - name: postgres-data - mountPath: /var/lib/postgresql/data - - name: tmp - mountPath: /tmp - - name: run - mountPath: /var/run - livenessProbe: - exec: - command: - - pg_isready - - -U - - trading - - -d - - {{ .Values.postgres.postgresqlDatabase }} - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - readinessProbe: - exec: - command: - - pg_isready - - -U - - trading - - -d - - {{ .Values.postgres.postgresqlDatabase }} - initialDelaySeconds: 15 - periodSeconds: 5 - timeoutSeconds: 3 - volumes: - - name: tmp - emptyDir: {} - - name: run - emptyDir: {} - volumeClaimTemplates: - - metadata: - name: postgres-data - spec: - accessModes: ["ReadWriteOnce"] - storageClassName: {{ .Values.postgres.storage.storageClass }} - resources: - requests: - storage: {{ .Values.postgres.storage.size }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/infrastructure/redis.yaml b/trading-platform/helm/trading-platform/templates/infrastructure/redis.yaml deleted file mode 100644 index 52032a0..0000000 --- a/trading-platform/helm/trading-platform/templates/infrastructure/redis.yaml +++ /dev/null @@ -1,107 +0,0 @@ -{{- if .Values.redis.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: redis-master - namespace: {{ .Values.global.namespace }} - labels: - app: redis -spec: - type: ClusterIP - ports: - - port: 6379 - targetPort: redis - protocol: TCP - name: redis - selector: - app: redis ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: redis - namespace: {{ .Values.global.namespace }} - labels: - app: redis -spec: - serviceName: redis-master - replicas: {{ .Values.redis.replicaCount }} - selector: - matchLabels: - app: redis - template: - metadata: - labels: - app: redis - spec: - securityContext: - runAsNonRoot: true - runAsUser: 999 - runAsGroup: 999 - fsGroup: 999 - containers: - - name: redis - image: "{{ .Values.redis.image.repository }}:{{ .Values.redis.image.tag }}" - command: - - redis-server - - --appendonly - - "yes" - - --save - - "" - - --requirepass - - $(REDIS_PASSWORD) - ports: - - containerPort: 6379 - name: redis - env: - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: trading-secrets - key: REDIS_PASSWORD - resources: - {{- toYaml .Values.redis.master.resources | nindent 12 }} - securityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - capabilities: - drop: - - ALL - volumeMounts: - - name: redis-data - mountPath: /data - - name: tmp - mountPath: /tmp - livenessProbe: - exec: - command: - - redis-cli - - -a - - $(REDIS_PASSWORD) - - ping - initialDelaySeconds: 15 - periodSeconds: 10 - timeoutSeconds: 5 - readinessProbe: - exec: - command: - - redis-cli - - -a - - $(REDIS_PASSWORD) - - ping - initialDelaySeconds: 10 - periodSeconds: 5 - timeoutSeconds: 3 - volumes: - - name: tmp - emptyDir: {} - volumeClaimTemplates: - - metadata: - name: redis-data - spec: - accessModes: ["ReadWriteOnce"] - storageClassName: {{ .Values.redis.master.storage.storageClass }} - resources: - requests: - storage: {{ .Values.redis.master.storage.size }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/ingress.yaml b/trading-platform/helm/trading-platform/templates/ingress.yaml deleted file mode 100644 index 965425d..0000000 --- a/trading-platform/helm/trading-platform/templates/ingress.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if .Values.ingress.enabled }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ include "trading-platform.fullname" . }} - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - {{- with .Values.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if .Values.ingress.className }} - ingressClassName: {{ .Values.ingress.className }} - {{- end }} - tls: - {{- range .Values.ingress.tls }} - - hosts: - {{- range .hosts }} - - {{ . | quote }} - {{- end }} - secretName: {{ .secretName }} - {{- end }} - rules: - {{- range $host := .Values.ingress.hosts }} - - host: {{ $host.host | quote }} - http: - paths: - {{- range $path := $host.paths }} - - path: {{ $path.path }} - pathType: {{ $path.pathType }} - backend: - service: - name: {{ $path.service }} - port: - {{- if eq $path.service "dashboard" }} - number: {{ $.Values.dashboard.port }} - {{- else if eq $path.service "execute-service" }} - number: {{ $.Values.executeService.port }} - {{- else if eq $path.service "news-service" }} - number: {{ $.Values.newsService.port }} - {{- else if eq $path.service "data-service" }} - number: {{ $.Values.dataService.port }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/namespace.yaml b/trading-platform/helm/trading-platform/templates/namespace.yaml deleted file mode 100644 index c0c9257..0000000 --- a/trading-platform/helm/trading-platform/templates/namespace.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: {{ .Values.global.namespace }} - labels: - app.kubernetes.io/managed-by: {{ .Release.Service }} - {{- if .Values.global.environment }} - environment: {{ .Values.global.environment | quote }} - {{- end }} - {{- if .Values.global.clusterName }} - cluster: {{ .Values.global.clusterName | quote }} - {{- end }} diff --git a/trading-platform/helm/trading-platform/templates/network-policies/network-policies.yaml b/trading-platform/helm/trading-platform/templates/network-policies/network-policies.yaml deleted file mode 100644 index 2f1fac6..0000000 --- a/trading-platform/helm/trading-platform/templates/network-policies/network-policies.yaml +++ /dev/null @@ -1,409 +0,0 @@ -{{- if .Values.networkPolicies.enabled }} -{{- if .Values.networkPolicies.defaultDenyIngress }} -# Deny all ingress traffic by default -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: default-deny-all-ingress - namespace: {{ .Values.global.namespace }} - labels: - app.kubernetes.io/managed-by: security-audit -spec: - podSelector: {} - policyTypes: - - Ingress ---- -{{- end }} -{{- if .Values.networkPolicies.defaultDenyEgress }} -# Deny all egress traffic by default -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: default-deny-all-egress - namespace: {{ .Values.global.namespace }} - labels: - app.kubernetes.io/managed-by: security-audit -spec: - podSelector: {} - policyTypes: - - Egress ---- -{{- end }} -{{- if .Values.networkPolicies.allowDNS }} -# Allow all pods to resolve DNS -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: allow-dns-egress - namespace: {{ .Values.global.namespace }} -spec: - podSelector: {} - policyTypes: - - Egress - egress: - - to: [] - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP ---- -{{- end }} -# Execute Service networking -{{- if .Values.executeService.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: execute-service-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: execute-service - policyTypes: - - Ingress - - Egress - ingress: - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: ingress-nginx - podSelector: - matchLabels: - app.kubernetes.io/name: ingress-nginx - - namespaceSelector: {} - podSelector: - matchLabels: - app.kubernetes.io/name: gce-proxy - ports: - - port: {{ .Values.executeService.port }} - protocol: TCP - - from: - - podSelector: - matchLabels: - app: news-service - ports: - - port: {{ .Values.executeService.port }} - protocol: TCP - egress: - - to: - - podSelector: - matchLabels: - app: postgres - ports: - - port: 5432 - protocol: TCP - - to: - - podSelector: - matchLabels: - app: redis - ports: - - port: 6379 - protocol: TCP - - to: - - podSelector: - matchLabels: - app: kafka - ports: - - port: 9092 - protocol: TCP ---- -{{- end }} -# News Service networking -{{- if .Values.newsService.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: news-service-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: news-service - policyTypes: - - Ingress - - Egress - ingress: - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: ingress-nginx - podSelector: - matchLabels: - app.kubernetes.io/name: ingress-nginx - ports: - - port: {{ .Values.newsService.port }} - protocol: TCP - egress: - - to: - - podSelector: - matchLabels: - cnpg.io/cluster: customer1-cnpg - ports: - - port: 5432 - protocol: TCP - - to: - - podSelector: - matchLabels: - app: kafka - ports: - - port: 9092 - protocol: TCP - - to: - - podSelector: - matchLabels: - app: execute-service - ports: - - port: {{ .Values.executeService.port }} - protocol: TCP ---- -{{- end }} -# Database networking -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: postgres-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: postgres - policyTypes: - - Ingress - - Egress - ingress: - - from: - - podSelector: - matchLabels: - app: execute-service - - podSelector: - matchLabels: - app: data-service - - podSelector: - matchLabels: - app: solana-quant-bot - ports: - - port: 5432 - protocol: TCP - egress: [] ---- -# Redis networking -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: redis-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: redis - policyTypes: - - Ingress - ingress: - - from: - - podSelector: - matchLabels: - app: execute-service - - podSelector: - matchLabels: - app: data-service - - podSelector: - matchLabels: - app: solana-quant-bot - ports: - - port: 6379 - protocol: TCP ---- -# Kafka networking -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: kafka-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: kafka - policyTypes: - - Ingress - ingress: - - from: - - podSelector: - matchLabels: - app: execute-service - - podSelector: - matchLabels: - app: news-service - - podSelector: - matchLabels: - app: data-service - - podSelector: - matchLabels: - app: solana-quant-bot - ports: - - port: 9092 - protocol: TCP - - port: 9093 - protocol: TCP ---- -# Dashboard networking -{{- if .Values.dashboard.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: dashboard-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: dashboard - policyTypes: - - Ingress - - Egress - ingress: - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: ingress-nginx - ports: - - port: {{ .Values.dashboard.port }} - protocol: TCP - egress: [] ---- -{{- end }} -# Data Service networking -{{- if .Values.dataService.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: data-service-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: data-service - policyTypes: - - Ingress - - Egress - ingress: - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: ingress-nginx - ports: - - port: {{ .Values.dataService.port }} - protocol: TCP - egress: - - to: - - podSelector: - matchLabels: - app: postgres - ports: - - port: 5432 - protocol: TCP - - to: - - podSelector: - matchLabels: - app: redis - ports: - - port: 6379 - protocol: TCP - - to: - - podSelector: - matchLabels: - app: kafka - ports: - - port: 9092 - protocol: TCP ---- -{{- end }} -# Solana Quant Bot networking -{{- if .Values.solanaQuantBot.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: solana-quant-bot-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: solana-quant-bot - policyTypes: - - Ingress - - Egress - ingress: - - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: ingress-nginx - ports: - - port: {{ .Values.solanaQuantBot.port }} - protocol: TCP - - port: {{ .Values.solanaQuantBot.metricsPort }} - protocol: TCP - egress: - # PostgreSQL - - to: - - podSelector: - matchLabels: - app: postgres - ports: - - port: 5432 - protocol: TCP - # Redis - - to: - - podSelector: - matchLabels: - app: redis - ports: - - port: 6379 - protocol: TCP - # Kafka - - to: - - podSelector: - matchLabels: - app: kafka - ports: - - port: 9092 - protocol: TCP - # Solana RPC (ExternalName — allows outbound to external RPC provider) - - to: - - podSelector: - matchLabels: - app: solana-rpc - ports: - - port: {{ .Values.solanaRpc.port }} - protocol: TCP - # External RPC provider (Helius/QuickNode — outbound HTTPS) - - to: [] - ports: - - port: 443 - protocol: TCP - - port: 80 - protocol: TCP ---- -{{- end }} -# Solana RPC networking (ExternalName allows outbound to external provider) -{{- if .Values.solanaRpc.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: solana-rpc-networking - namespace: {{ .Values.global.namespace }} -spec: - podSelector: - matchLabels: - app: solana-rpc - policyTypes: - - Egress - egress: - # Allow outbound HTTPS to external RPC provider - - to: [] - ports: - - port: 443 - protocol: TCP - - port: 80 - protocol: TCP ---- -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/news-service/deployment.yaml b/trading-platform/helm/trading-platform/templates/news-service/deployment.yaml deleted file mode 100644 index 8ac48e2..0000000 --- a/trading-platform/helm/trading-platform/templates/news-service/deployment.yaml +++ /dev/null @@ -1,85 +0,0 @@ -{{- if .Values.newsService.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.newsService.name }} - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app: {{ .Values.newsService.name }} -spec: - {{- if not .Values.newsService.autoscaling.enabled }} - replicas: {{ .Values.global.replicaCount }} - {{- end }} - selector: - matchLabels: - {{- include "trading-platform.selectorLabels" . | nindent 6 }} - app: {{ .Values.newsService.name }} - template: - metadata: - labels: - {{- include "trading-platform.selectorLabels" . | nindent 8 }} - app: {{ .Values.newsService.name }} - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.newsService.port }}" - spec: - serviceAccountName: {{ .Values.newsService.name }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: {{ .Values.newsService.name }} - image: "{{ .Values.newsService.image.repository }}:{{ .Values.newsService.image.tag }}" - imagePullPolicy: {{ .Values.newsService.image.pullPolicy }} - ports: - - name: http - containerPort: {{ .Values.newsService.port }} - protocol: TCP - env: - {{- range $key, $value := .Values.newsService.env }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - - name: KAFKA_BOOTSTRAP_SERVERS - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: KAFKA_BOOTSTRAP - envFrom: - - secretRef: - name: trading-secrets - resources: - {{- toYaml .Values.newsService.resources | nindent 12 }} - securityContext: - {{- toYaml .Values.containerSecurityContext | nindent 12 }} - volumeMounts: - - name: tmp - mountPath: /tmp - - name: mtls-certs - mountPath: /etc/mtls - readOnly: true - livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 15 - periodSeconds: 10 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - periodSeconds: 5 - timeoutSeconds: 3 - volumes: - - name: tmp - emptyDir: {} - - name: mtls-certs - secret: - secretName: news-service-mtls - {{- with .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/news-service/service.yaml b/trading-platform/helm/trading-platform/templates/news-service/service.yaml deleted file mode 100644 index d24f4eb..0000000 --- a/trading-platform/helm/trading-platform/templates/news-service/service.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if .Values.newsService.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.newsService.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.newsService.name }} -spec: - type: ClusterIP - ports: - - port: {{ .Values.newsService.port }} - targetPort: http - protocol: TCP - name: http - selector: - app: {{ .Values.newsService.name }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.newsService.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.newsService.name }} ---- -{{- if .Values.newsService.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ .Values.newsService.name }} - namespace: {{ .Values.global.namespace }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ .Values.newsService.name }} - minReplicas: {{ .Values.newsService.autoscaling.minReplicas }} - maxReplicas: {{ .Values.newsService.autoscaling.maxReplicas }} - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ .Values.newsService.autoscaling.targetCPUUtilizationPercentage }} -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-grafana-dashboard.yaml b/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-grafana-dashboard.yaml deleted file mode 100644 index 51aad77..0000000 --- a/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-grafana-dashboard.yaml +++ /dev/null @@ -1,139 +0,0 @@ -{{- if .Values.solanaQuantBot.enabled }} -{{- if .Values.grafana.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Values.solanaQuantBot.name }}-grafana-dashboard - namespace: {{ .Values.grafana.namespace | default .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app.kubernetes.io/part-of: solana-quant-bot - grafana_dashboard: "1" -data: - solana-quant-bot-dashboard.json: | - { - "annotations": { - "list": [] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 1, - "id": null, - "links": [], - "liveNow": false, - "panels": [ - { - "title": "Bot Overview", - "type": "row", - "gridPos": {"h": 1, "w": 24, "x": 0, "y": 0}, - "collapsed": false - }, - { - "title": "Pods Running", - "type": "stat", - "gridPos": {"h": 4, "w": 6, "x": 0, "y": 1}, - "targets": [ - {"expr": "up{job=\"solana-quant-bot\"}", "legendFormat": "{{instance}}"} - ], - "fieldConfig": { - "defaults": { - "thresholds": {"steps": [{"color": "red", "value": null}, {"color": "green", "value": 1}]}, - "unit": "short" - } - } - }, - { - "title": "Total Trades (24h)", - "type": "stat", - "gridPos": {"h": 4, "w": 6, "x": 6, "y": 1}, - "targets": [ - {"expr": "increase(solana_quant_bot_trades_total[24h])"} - ], - "fieldConfig": {"defaults": {"unit": "short"}} - }, - { - "title": "Trade Error Rate (5m)", - "type": "stat", - "gridPos": {"h": 4, "w": 6, "x": 12, "y": 1}, - "targets": [ - {"expr": "sum(rate(solana_quant_bot_trade_errors_total[5m])) / sum(rate(solana_quant_bot_trades_total[5m])) * 100"} - ], - "fieldConfig": { - "defaults": { - "unit": "percent", - "thresholds": {"steps": [{"color": "green", "value": null}, {"color": "yellow", "value": 3}, {"color": "red", "value": 10}]} - } - } - }, - { - "title": "SOL Balance", - "type": "stat", - "gridPos": {"h": 4, "w": 6, "x": 18, "y": 1}, - "targets": [ - {"expr": "solana_quant_bot_sol_balance"} - ], - "fieldConfig": { - "defaults": { - "unit": "short", - "thresholds": {"steps": [{"color": "red", "value": null}, {"color": "orange", "value": 10}, {"color": "green", "value": 25}]} - } - } - }, - { - "title": "Trade Volume (USDC)", - "type": "timeseries", - "gridPos": {"h": 8, "w": 24, "x": 0, "y": 5}, - "targets": [ - {"expr": "sum(rate(solana_quant_bot_trade_volume_usdc[5m])) * 60", "legendFormat": "USDC/min"} - ] - }, - { - "title": "Signal Processing Latency", - "type": "timeseries", - "gridPos": {"h": 8, "w": 12, "x": 0, "y": 13}, - "targets": [ - {"expr": "histogram_quantile(0.50, sum(rate(solana_quant_bot_signal_latency_seconds_bucket[5m])) by (le))", "legendFormat": "p50"}, - {"expr": "histogram_quantile(0.95, sum(rate(solana_quant_bot_signal_latency_seconds_bucket[5m])) by (le))", "legendFormat": "p95"}, - {"expr": "histogram_quantile(0.99, sum(rate(solana_quant_bot_signal_latency_seconds_bucket[5m])) by (le))", "legendFormat": "p99"} - ], - "fieldConfig": {"defaults": {"unit": "s"}} - }, - { - "title": "Trades per Minute", - "type": "timeseries", - "gridPos": {"h": 8, "w": 12, "x": 12, "y": 13}, - "targets": [ - {"expr": "sum(rate(solana_quant_bot_trades_total[5m])) * 60", "legendFormat": "trades/min"} - ] - }, - { - "title": "Token Score Distribution", - "type": "timeseries", - "gridPos": {"h": 8, "w": 12, "x": 0, "y": 21}, - "targets": [ - {"expr": "avg(solana_quant_bot_token_score)", "legendFormat": "avg score"}, - {"expr": "max(solana_quant_bot_token_score)", "legendFormat": "max score"} - ] - }, - { - "title": "CPU / Memory Usage", - "type": "timeseries", - "gridPos": {"h": 8, "w": 12, "x": 12, "y": 21}, - "targets": [ - {"expr": "sum(rate(container_cpu_usage_seconds_total{pod=~\"solana-quant-bot-.*\"}[5m])) * 1000", "legendFormat": "CPU (m)"}, - {"expr": "sum(container_memory_usage_bytes{pod=~\"solana-quant-bot-.*\"}) / 1024 / 1024", "legendFormat": "Memory (MB)"} - ], - "fieldConfig": {"defaults": {"unit": "short"}} - } - ], - "refresh": "30s", - "schemaVersion": 39, - "tags": ["solana", "quant-bot", "trading"], - "templating": {"list": []}, - "time": {"from": "now-3h", "to": "now"}, - "title": "Solana Quant Bot", - "uid": "solana-quant-bot", - "version": 1 - } -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-prometheus-rules.yaml b/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-prometheus-rules.yaml deleted file mode 100644 index 4393258..0000000 --- a/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-prometheus-rules.yaml +++ /dev/null @@ -1,70 +0,0 @@ -{{- if .Values.solanaQuantBot.enabled }} -{{- if .Values.alertmanager.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: PrometheusRule -metadata: - name: {{ .Values.solanaQuantBot.name }}-alerts - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app.kubernetes.io/part-of: solana-quant-bot - release: prometheus -spec: - groups: - - name: solana-quant-bot.rules - rules: - # Alert if bot pod is down - - alert: SolanaQuantBotDown - expr: up{job="{{ .Values.solanaQuantBot.name }}"} == 0 - for: 5m - labels: - severity: critical - annotations: - summary: "Solana Quant Bot instance {{ '{{ $instance }}' }} is down" - description: "Bot has been unreachable for more than 5 minutes." - - # High error rate on trades - - alert: SolanaQuantBotHighErrorRate - expr: | - sum(rate(solana_quant_bot_trade_errors_total[5m])) - / sum(rate(solana_quant_bot_trades_total[5m])) > 0.05 - for: 10m - labels: - severity: warning - annotations: - summary: "Solana Quant Bot trade error rate is >5%" - description: "Error rate: {{ '{{ $value }}' }} over 5m window." - - # No trades executed in a long time (stale bot) - - alert: SolanaQuantBotNoTrades - expr: | - time() - increase(solana_quant_bot_last_trade_timestamp[1h]) > 3600 - for: 15m - labels: - severity: warning - annotations: - summary: "Solana Quant Bot has not executed trades in 1 hour" - description: "Bot may be stuck or signals pipeline is blocked." - - # High signal processing latency - - alert: SolanaQuantBotHighLatency - expr: | - histogram_quantile(0.95, sum(rate(solana_quant_bot_signal_latency_seconds_bucket[5m])) by (le)) > 2 - for: 10m - labels: - severity: warning - annotations: - summary: "Solana Quant Bot p95 signal latency > 2s" - description: "p95 latency: {{ '{{ $value }}' }}s." - - # Wallet balance below threshold - - alert: SolanaQuantBotLowBalance - expr: solana_quant_bot_sol_balance < 10 - for: 5m - labels: - severity: critical - annotations: - summary: "Solana Quant Bot SOL balance is below 10 SOL" - description: "Current balance: {{ '{{ $value }}' }} SOL." -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-service-monitor.yaml b/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-service-monitor.yaml deleted file mode 100644 index ccb0201..0000000 --- a/trading-platform/helm/trading-platform/templates/observability/solana-quant-bot-service-monitor.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.solanaQuantBot.enabled }} -{{- if .Values.prometheus.enabled }} -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ .Values.solanaQuantBot.name }} - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app.kubernetes.io/part-of: solana-quant-bot - release: prometheus -spec: - selector: - matchLabels: - app: {{ .Values.solanaQuantBot.name }} - endpoints: - - port: metrics - path: /metrics - interval: {{ .Values.prometheus.scrapeInterval | default "15s" }} - scrapeTimeout: 10s - namespaceSelector: - matchNames: - - {{ .Values.global.namespace }} -{{- end }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/secrets.yaml b/trading-platform/helm/trading-platform/templates/secrets.yaml deleted file mode 100644 index 9eaddbe..0000000 --- a/trading-platform/helm/trading-platform/templates/secrets.yaml +++ /dev/null @@ -1,45 +0,0 @@ -# Trading Secrets - Encrypt with SOPS before applying -# Usage: sops -e -i trading-secrets.yaml && kubectl apply -f trading-secrets.yaml -apiVersion: v1 -kind: Secret -metadata: - name: trading-secrets - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app.kubernetes.io/managed-by: security-audit - annotations: - # SOPS manages this file - edit with: sops trading-secrets.yaml - secrets.yaml.sops.io/v2: encrypted -type: Opaque -stringData: - # JWT authentication - EXECUTE_JWT_SECRET_KEY: {{ .Values.executeService.env.JWT_SECRET_KEY | default "" | quote }} - - # Exchange private keys - EXECUTE_HYPERLIQUID_PRIVATE_KEY: {{ .Values.executeService.env.HYPERLIQUID_PRIVATE_KEY | default "" | quote }} - EXECUTE_SOLANA_PRIVATE_KEY_BASE58: {{ .Values.executeService.env.SOLANA_PRIVATE_KEY_BASE58 | default "" | quote }} - - # Database credentials - POSTGRES_PASSWORD: {{ .Values.postgres.postgresqlPassword | default "" | quote }} - NEWS_DB_PASSWORD: {{ .Values.newsService.env.NEWS_DB_PASSWORD | default "" | quote }} - - # Redis - REDIS_PASSWORD: {{ .Values.redis.redisPassword | default "" | quote }} - - # Kafka SASL - KAFKA_SASL_USERNAME: {{ .Values.kafka.saslUsername | default "" | quote }} - KAFKA_SASL_PASSWORD: {{ .Values.kafka.saslPassword | default "" | quote }} - ---- -# mTLS certificates (generated by cert-manager, mounted as volumes) -# Service account tokens for SPIFFE/SPIRE identity -apiVersion: v1 -kind: Secret -metadata: - name: trading-mtls-certs - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} -type: kubernetes.io/tls -# tls.crt and tls.key populated by cert-manager diff --git a/trading-platform/helm/trading-platform/templates/solana-quant-bot/alembic-migration-job.yaml b/trading-platform/helm/trading-platform/templates/solana-quant-bot/alembic-migration-job.yaml deleted file mode 100644 index 437c45b..0000000 --- a/trading-platform/helm/trading-platform/templates/solana-quant-bot/alembic-migration-job.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{{- if .Values.solanaQuantBot.enabled }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ .Values.solanaQuantBot.name }}-db-migrate - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app: {{ .Values.solanaQuantBot.name }} - app.kubernetes.io/part-of: solana-quant-bot - annotations: - # Prevent re-running on helm upgrade if already succeeded - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded -spec: - template: - metadata: - labels: - app: {{ .Values.solanaQuantBot.name }} - app.kubernetes.io/part-of: solana-quant-bot - spec: - serviceAccountName: {{ .Values.solanaQuantBot.name }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - containers: - - name: alembic-migrate - image: "{{ .Values.solanaQuantBot.image.repository }}:{{ .Values.solanaQuantBot.image.tag }}" - imagePullPolicy: {{ .Values.solanaQuantBot.image.pullPolicy }} - command: ["alembic"] - args: ["upgrade", "head"] - env: - - name: DB_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: POSTGRES_HOST - - name: DB_PORT - value: "5432" - - name: DB_NAME - value: {{ .Values.solanaQuantBot.env.DB_NAME | quote }} - envFrom: - - secretRef: - name: trading-secrets - resources: - {{- toYaml .Values.solanaQuantBot.migrationResources | nindent 12 }} - securityContext: - {{- toYaml .Values.containerSecurityContext | nindent 12 }} - restartPolicy: Never - {{- with .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - nodeSelector: - kubernetes.io/os: linux - backoffLimit: 3 - activeDeadlineSeconds: 300 -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/solana-quant-bot/deployment.yaml b/trading-platform/helm/trading-platform/templates/solana-quant-bot/deployment.yaml deleted file mode 100644 index eb31d97..0000000 --- a/trading-platform/helm/trading-platform/templates/solana-quant-bot/deployment.yaml +++ /dev/null @@ -1,138 +0,0 @@ -{{- if .Values.solanaQuantBot.enabled }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Values.solanaQuantBot.name }} - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app: {{ .Values.solanaQuantBot.name }} - app.kubernetes.io/part-of: solana-quant-bot -spec: - replicas: {{ .Values.solanaQuantBot.replicaCount }} - selector: - matchLabels: - {{- include "trading-platform.selectorLabels" . | nindent 6 }} - app: {{ .Values.solanaQuantBot.name }} - template: - metadata: - labels: - {{- include "trading-platform.selectorLabels" . | nindent 8 }} - app: {{ .Values.solanaQuantBot.name }} - app.kubernetes.io/part-of: solana-quant-bot - annotations: - prometheus.io/scrape: "true" - prometheus.io/port: "{{ .Values.solanaQuantBot.metricsPort }}" - prometheus.io/path: "/metrics" - spec: - serviceAccountName: {{ .Values.solanaQuantBot.name }} - securityContext: - {{- toYaml .Values.podSecurityContext | nindent 8 }} - initContainers: - # Wait for database migrations to complete - - name: wait-for-migrations - image: "{{ .Values.solanaQuantBot.image.repository }}:{{ .Values.solanaQuantBot.image.tag }}" - imagePullPolicy: {{ .Values.solanaQuantBot.image.pullPolicy }} - command: ['sh', '-c', 'until python -c "import asyncio; from app.db import check_migrations; asyncio.run(check_migrations())"; do echo waiting for migrations; sleep 5; done'] - env: - - name: DB_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: POSTGRES_HOST - - name: DB_PORT - value: "5432" - - name: DB_NAME - value: {{ .Values.solanaQuantBot.env.DB_NAME | quote }} - envFrom: - - secretRef: - name: trading-secrets - resources: - {{- toYaml .Values.solanaQuantBot.resources | nindent 12 }} - containers: - - name: {{ .Values.solanaQuantBot.name }} - image: "{{ .Values.solanaQuantBot.image.repository }}:{{ .Values.solanaQuantBot.image.tag }}" - imagePullPolicy: {{ .Values.solanaQuantBot.image.pullPolicy }} - ports: - - name: http - containerPort: {{ .Values.solanaQuantBot.port }} - protocol: TCP - - name: metrics - containerPort: {{ .Values.solanaQuantBot.metricsPort }} - protocol: TCP - env: - {{- range $key, $value := .Values.solanaQuantBot.env }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - # Shared config from ConfigMap - - name: DB_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: POSTGRES_HOST - - name: REDIS_HOST - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: REDIS_HOST - - name: KAFKA_BOOTSTRAP_SERVERS - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: KAFKA_BOOTSTRAP - - name: SOLANA_RPC_URL - valueFrom: - configMapKeyRef: - name: {{ include "trading-platform.fullname" . }}-config - key: SOLANA_RPC_URL - envFrom: - - secretRef: - name: trading-secrets - - secretRef: - name: solana-quant-bot-secrets - resources: - {{- toYaml .Values.solanaQuantBot.resources | nindent 12 }} - securityContext: - {{- toYaml .Values.containerSecurityContext | nindent 12 }} - volumeMounts: - - name: tmp - mountPath: /tmp - livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 30 - periodSeconds: 15 - timeoutSeconds: 5 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 20 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 - volumes: - - name: tmp - emptyDir: {} - {{- with .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - nodeSelector: - kubernetes.io/os: linux - affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - {{ .Values.solanaQuantBot.name }} - topologyKey: kubernetes.io/hostname -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/solana-quant-bot/service.yaml b/trading-platform/helm/trading-platform/templates/solana-quant-bot/service.yaml deleted file mode 100644 index 487514e..0000000 --- a/trading-platform/helm/trading-platform/templates/solana-quant-bot/service.yaml +++ /dev/null @@ -1,58 +0,0 @@ -{{- if .Values.solanaQuantBot.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.solanaQuantBot.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.solanaQuantBot.name }} - app.kubernetes.io/part-of: solana-quant-bot -spec: - type: ClusterIP - ports: - - port: {{ .Values.solanaQuantBot.port }} - targetPort: http - protocol: TCP - name: http - - port: {{ .Values.solanaQuantBot.metricsPort }} - targetPort: metrics - protocol: TCP - name: metrics - selector: - app: {{ .Values.solanaQuantBot.name }} ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ .Values.solanaQuantBot.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.solanaQuantBot.name }} - app.kubernetes.io/part-of: solana-quant-bot - annotations: - iam.gke.io/gcp-service-account: solana-quant-bot@{{ .Values.global.clusterName }}.iam.gserviceaccount.com ---- -# Dedicated secrets for Solana quant bot (wallet keys, RPC auth) -apiVersion: v1 -kind: Secret -metadata: - name: solana-quant-bot-secrets - namespace: {{ .Values.global.namespace }} - labels: - {{- include "trading-platform.labels" . | nindent 4 }} - app.kubernetes.io/part-of: solana-quant-bot - annotations: - secrets.yaml.sops.io/v2: encrypted -type: Opaque -stringData: - # Solana wallet private key (base58 encoded) - SOLANA_BOT_PRIVATE_KEY_BASE58: {{ .Values.solanaQuantBot.env.SOLANA_BOT_PRIVATE_KEY_BASE58 | default "" | quote }} - # Helius/QuickNode API key for RPC - SOLANA_RPC_API_KEY: {{ .Values.solanaQuantBot.env.SOLANA_RPC_API_KEY | default "" | quote }} - # Jupiter API key (optional, for better rate limits) - JUPITER_API_KEY: {{ .Values.solanaQuantBot.env.JUPITER_API_KEY | default "" | quote }} - # Birdeye API key for price data - BIRDEYE_API_KEY: {{ .Values.solanaQuantBot.env.BIRDEYE_API_KEY | default "" | quote }} - # Dexscreener API key (if using authenticated endpoints) - DEXSCREENER_API_KEY: {{ .Values.solanaQuantBot.env.DEXSCREENER_API_KEY | default "" | quote }} -{{- end }} diff --git a/trading-platform/helm/trading-platform/templates/solana-rpc/service.yaml b/trading-platform/helm/trading-platform/templates/solana-rpc/service.yaml deleted file mode 100644 index c2a4544..0000000 --- a/trading-platform/helm/trading-platform/templates/solana-rpc/service.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if .Values.solanaRpc.enabled }} -# Solana RPC proxy service (Helius/QuickNode endpoint) -# Exposes a stable internal DNS name for Solana RPC access -apiVersion: v1 -kind: Service -metadata: - name: {{ .Values.solanaRpc.name }} - namespace: {{ .Values.global.namespace }} - labels: - app: {{ .Values.solanaRpc.name }} - app.kubernetes.io/part-of: solana-quant-bot -spec: - type: ExternalName - externalName: {{ .Values.solanaRpc.externalHost }} ---- -{{- end }} diff --git a/trading-platform/helm/trading-platform/trading-secrets.yaml b/trading-platform/helm/trading-platform/trading-secrets.yaml deleted file mode 100644 index e74f932..0000000 --- a/trading-platform/helm/trading-platform/trading-secrets.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Trading Secrets - Encrypt with SOPS before applying -# Usage: sops -e -i trading-secrets.yaml && kubectl apply -f trading-secrets.yaml -# -# DO NOT commit unencrypted secrets to git! -# Generate secrets with: python -c "import secrets; print(secrets.token_urlsafe(24))" -apiVersion: v1 -kind: Secret -metadata: - name: trading-secrets - namespace: trading - labels: - app.kubernetes.io/managed-by: security-audit - annotations: - secrets.yaml.sops.io/v2: encrypted -type: Opaque -stringData: - # JWT authentication - use 32+ byte hex token - EXECUTE_JWT_SECRET_KEY: "" - - # Exchange private keys - NEVER commit plaintext! - EXECUTE_HYPERLIQUID_PRIVATE_KEY: "" - EXECUTE_SOLANA_PRIVATE_KEY_BASE58: "" - - # Database credentials - use 24+ byte URL-safe tokens - POSTGRES_PASSWORD: "" - NEWS_DB_PASSWORD: "" - - # Redis password - REDIS_PASSWORD: "" - - # Kafka SASL authentication - KAFKA_SASL_USERNAME: "" - KAFKA_SASL_PASSWORD: "" diff --git a/trading-platform/helm/trading-platform/values.yaml b/trading-platform/helm/trading-platform/values.yaml deleted file mode 100644 index e683795..0000000 --- a/trading-platform/helm/trading-platform/values.yaml +++ /dev/null @@ -1,412 +0,0 @@ -# Trading Platform Helm Chart - Default Values -# ============================================================ - -# Global settings -global: - namespace: customer1 - replicaCount: 2 - imagePullSecrets: [] - clusterName: customer1-gke - environment: staging - registry: us-central1-docker.pkg.dev/customer1-gke/trading - -# Resource defaults for all microservices -resources: - requests: - cpu: 250m - memory: 256Mi - limits: - cpu: "1" - memory: 512Mi - -# Pod security context defaults -podSecurityContext: - runAsNonRoot: true - runAsUser: 1000 - runAsGroup: 1000 - fsGroup: 1000 - seccompProfile: - type: RuntimeDefault - -# Container security context defaults -containerSecurityContext: - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true - capabilities: - drop: - - ALL - -# ================================================================= -# Execute Service (Hyperliquid + Solana trading engine) -# ================================================================= -executeService: - enabled: true - name: execute-service - image: - repository: "ghcr.io/sirius0xdev/trading-execute-service" - tag: "7b77854" - pullPolicy: Always - port: 8000 - resources: - requests: - cpu: 500m - memory: 512Mi - limits: - cpu: "2" - memory: 1Gi - autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 10 - targetCPUUtilizationPercentage: 70 - env: - LOG_LEVEL: "INFO" - KAFKA_BOOTSTRAP_SERVERS: "kafka-headless:9092" - KAFKA_TOPIC_TRADES: "trades.executed" - KAFKA_TOPIC_ORDERS: "orders.new" - REDIS_HOST: "redis-master" - REDIS_PORT: "6379" - DB_HOST: "postgres-primary" - DB_PORT: "5432" - DB_NAME: "trading_db" - -# ================================================================= -# News Service (CNPG connector + Kafka producer) -# ================================================================= -newsService: - enabled: true - name: news-service - image: - repository: "" - tag: "0.1.0" - pullPolicy: IfNotPresent - port: 8000 - resources: - requests: - cpu: 300m - memory: 384Mi - limits: - cpu: "1" - memory: 768Mi - autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 6 - targetCPUUtilizationPercentage: 75 - env: - LOG_LEVEL: "INFO" - DB_POOL_SIZE: "5" - DB_MAX_OVERFLOW: "10" - KAFKA_BOOTSTRAP_SERVERS: "kafka-headless:9092" - KAFKA_GROUP_ID: "news-analyzer" - KAFKA_TOPIC_ARTICLES: "news.articles" - KAFKA_TOPIC_ANALYSIS: "news.analysis" - API_PREFIX: "/api/v1" - CORS_ORIGINS: '["https://app.customer1.trading.com"]' - DB_HOST: "customer1-cnpg-r" - DB_PORT: "5432" - DB_NAME: "news" - -# ================================================================= -# Data Service (Postgres + Redis + Kafka consumers) -# ================================================================= -dataService: - enabled: true - name: data-service - image: - repository: "" - tag: "0.1.0" - pullPolicy: IfNotPresent - port: 8000 - resources: - requests: - cpu: 300m - memory: 384Mi - limits: - cpu: "1" - memory: 768Mi - autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 6 - targetCPUUtilizationPercentage: 70 - env: - LOG_LEVEL: "INFO" - DB_HOST: "postgres-primary" - DB_PORT: "5432" - DB_NAME: "trading_db" - REDIS_HOST: "redis-master" - REDIS_PORT: "6379" - KAFKA_BOOTSTRAP_SERVERS: "kafka-headless:9092" - KAFKA_CONSUMER_GROUP: "data-service" - -# ================================================================= -# Dashboard (Next.js frontend) -# ================================================================= -dashboard: - enabled: true - name: dashboard - image: - repository: "" - tag: "0.2.0-autonomous-bot" - pullPolicy: IfNotPresent - port: 3000 - resources: - requests: - cpu: 200m - memory: 256Mi - limits: - cpu: "500m" - memory: 512Mi - autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 8 - targetCPUUtilizationPercentage: 60 - env: - NODE_ENV: "production" - NEXT_PUBLIC_API_BASE_URL: "/api" - NEXT_PUBLIC_EXEC_SERVICE_URL: "http://execute-service:8000" - NEXT_PUBLIC_NEWS_SERVICE_URL: "http://news-service:8001" - -# ================================================================= -# Ingress -# ================================================================= -ingress: - enabled: true - className: "gce" - annotations: - kubernetes.io/ingress.class: gce - kubernetes.io/ingress.allow-http: "true" - nginx.ingress.kubernetes.io/ssl-redirect: "true" - hosts: - - host: app.customer1.trading.com - paths: - - path: / - pathType: Prefix - service: dashboard - - path: /api/trades - pathType: Prefix - service: execute-service - - path: /api/auth - pathType: Prefix - service: execute-service - - path: /api/news - pathType: Prefix - service: news-service - - path: /api/data - pathType: Prefix - service: data-service - tls: - - secretName: trading-tls - hosts: - - app.customer1.trading.com - -# ================================================================= -# Cert-Manager / mTLS -# ================================================================= -certManager: - enabled: true - externalIssuer: - name: letsencrypt-prod - server: https://acme-v02.api.letsencrypt.org/directory - email: ops@customer1.trading.com - internalIssuer: - name: trading-ca - -# ================================================================= -# PostgreSQL -# ================================================================= -postgres: - enabled: true - image: - repository: postgres - tag: "17-alpine" - primary: - replicaCount: 1 - resources: - requests: - cpu: "1" - memory: 2Gi - limits: - cpu: "2" - memory: 4Gi - storage: - size: 50Gi - storageClass: "standard-rwo" - postgresqlDatabase: trading_db - -# ================================================================= -# Redis -# ================================================================= -redis: - enabled: true - image: - repository: redis - tag: "7-alpine" - replicaCount: 3 - master: - resources: - requests: - cpu: 250m - memory: 256Mi - limits: - cpu: "500m" - memory: 512Mi - storage: - size: 10Gi - storageClass: "standard-rwo" - -# ================================================================= -# Kafka (KRaft mode) -# ================================================================= -kafka: - enabled: true - image: - repository: apache/kafka - tag: "3.9.0" - replicaCount: 3 - resources: - requests: - cpu: 500m - memory: 1Gi - limits: - cpu: "1" - memory: 2Gi - storage: - size: 20Gi - storageClass: "standard-rwo" - topics: - - name: trades.executed - partitions: 6 - replicationFactor: 3 - - name: orders.new - partitions: 6 - replicationFactor: 3 - - name: news.articles - partitions: 6 - replicationFactor: 3 - - name: news.analysis - partitions: 6 - replicationFactor: 3 - # Solana quant bot topics - - name: solana.bot.signals - partitions: 6 - replicationFactor: 3 - - name: solana.bot.trades - partitions: 6 - replicationFactor: 3 - - name: solana.bot.alerts - partitions: 3 - replicationFactor: 3 - - name: solana.token.data - partitions: 6 - replicationFactor: 3 - - name: solana.pool.data - partitions: 6 - replicationFactor: 3 - -# ================================================================= -# Solana RPC (ExternalName service for external RPC providers) -# ================================================================= -solanaRpc: - enabled: true - name: solana-rpc - # ExternalName points to external RPC provider (Helius, QuickNode, etc.) - externalName: "mainnet.helius-rpc.com" - port: 443 - # env var for internal DNS: http://solana-rpc..svc.cluster.local:443 - -# ================================================================= -# Solana Quant Bot (autonomous trading agent) -# ================================================================= -solanaQuantBot: - enabled: true - name: solana-quant-bot - replicaCount: 2 - image: - repository: "" - tag: "0.1.0" - pullPolicy: IfNotPresent - port: 8000 - metricsPort: 9090 - resources: - requests: - cpu: 1 - memory: 1Gi - limits: - cpu: "2" - memory: 2Gi - migrationResources: - requests: - cpu: 250m - memory: 256Mi - limits: - cpu: "500m" - memory: 512Mi - autoscaling: - enabled: true - minReplicas: 2 - maxReplicas: 5 - targetCPUUtilizationPercentage: 70 - env: - LOG_LEVEL: "INFO" - DB_NAME: "solana_quant_db" - KAFKA_GROUP_ID: "solana-quant-bot" - KAFKA_TOPIC_SIGNALS: "solana.bot.signals" - KAFKA_TOPIC_TRADES: "solana.bot.trades" - KAFKA_TOPIC_ALERTS: "solana.bot.alerts" - KAFKA_TOPIC_TOKEN_DATA: "solana.token.data" - KAFKA_TOPIC_POOL_DATA: "solana.pool.data" - # Solana RPC via internal DNS (ExternalName service) - SOLANA_RPC_ENDPOINT: "http://solana-rpc:443" - # Trading config - MIN_LIQUIDITY_USD: "50000" - MAX_POSITION_SIZE_USD: "10000" - SLIPPAGE_BPS: "100" - SCORING_THRESHOLD: "60" - HEALTHCHECK_INTERVAL: "300" - # Secrets (override via secret, not here) - SOLANA_BOT_PRIVATE_KEY_BASE58: "" - SOLANA_RPC_API_KEY: "" - BIRDEYE_API_KEY: "" - JUPITER_API_KEY: "" - DEXSCREENER_API_KEY: "" - -# ================================================================= -# Network Policies (from security audit) -# ================================================================= -networkPolicies: - enabled: true - defaultDenyIngress: true - defaultDenyEgress: true - allowDNS: true - -# ================================================================= -# Observability (Prometheus + Grafana + Alertmanager) -# ================================================================= -prometheus: - enabled: true - scrapeInterval: "15s" - retention: "15d" - retentionSize: "10GB" - -alertmanager: - enabled: true - # Alert routes configured separately - -grafana: - enabled: true - namespace: "" # defaults to global.namespace - adminUser: admin - # adminPassword comes from secret - dashboards: - - solana-quant-bot-dashboard - -# ================================================================= -# SOPS Encryption -# ================================================================= -sops: - enabled: true - ageKeyFile: /etc/sops/age.key - secretsPath: trading-secrets.yaml diff --git a/trading-platform/helm/trading-secrets.yaml b/trading-platform/helm/trading-secrets.yaml deleted file mode 100644 index d47e23f..0000000 --- a/trading-platform/helm/trading-secrets.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# Trading Secrets - Encrypt with SOPS before applying -# Usage: sops -e -i trading-secrets.yaml && kubectl apply -f trading-secrets.yaml -# -# DO NOT commit unencrypted secrets to git! -# Generate secrets with: python -c "import secrets; print(secrets.token_urlsafe(24))" -apiVersion: v1 -kind: Secret -metadata: - name: trading-secrets - namespace: customer1 - labels: - app.kubernetes.io/managed-by: security-audit - annotations: - secrets.yaml.sops.io/v2: encrypted -type: Opaque -stringData: - # JWT authentication - use 32+ byte hex token - EXECUTE_JWT_SECRET_KEY: "" - - # Exchange private keys - NEVER commit plaintext! - EXECUTE_HYPERLIQUID_PRIVATE_KEY: "" - EXECUTE_SOLANA_PRIVATE_KEY_BASE58: "" - - # Database credentials - use 24+ byte URL-safe tokens - POSTGRES_PASSWORD: "" - NEWS_DB_PASSWORD: "" - - # Redis password - REDIS_PASSWORD: "" - - # Kafka SASL authentication - KAFKA_SASL_USERNAME: "" - KAFKA_SASL_PASSWORD: "" diff --git a/trading-platform/scripts/solana-funding/README.md b/trading-platform/scripts/solana-funding/README.md deleted file mode 100644 index 5e6f676..0000000 --- a/trading-platform/scripts/solana-funding/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Solana Quant Bot Funding - -Scripts for funding the Solana Quant Bot wallet and verifying balances. - -## Initial Funding - -```bash -# Dry run first -./fund-bot-wallet.sh --amount 50 --from-wallet --namespace customer1 --dry-run - -# Execute funding -./fund-bot-wallet.sh --amount 50 --from-wallet --namespace customer1 - -# Verify balance after -./fund-bot-wallet.sh --bot-wallet --verify -``` - -## Options - -| Option | Description | -|--------|-------------| -| `--amount SOL` | Amount in SOL to fund (default: 50) | -| `--from-wallet ADDR` | Source wallet (required for transfers) | -| `--bot-wallet ADDR` | Bot wallet (auto-read from K8s secret if omitted) | -| `--namespace NS` | K8s namespace (default: customer1) | -| `--dry-run` | Simulate without sending | -| `--verify` | Check bot wallet balance | - -## Security Notes - -- The bot wallet private key is stored as a SOPS-encrypted K8s secret. -- Initial funding should use a dedicated hot wallet, not a multi-sig for simplicity. -- sec-ops may require multi-sig for larger seed amounts. -- Monitor the bot wallet for anomalous transactions via the Prometheus alerts. diff --git a/trading-platform/scripts/solana-funding/fund-bot-wallet.sh b/trading-platform/scripts/solana-funding/fund-bot-wallet.sh deleted file mode 100755 index 0d45b1a..0000000 --- a/trading-platform/scripts/solana-funding/fund-bot-wallet.sh +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env bash -# fund-bot-wallet.sh — Initial funding script for Solana Quant Bot -# -# Usage: ./fund-bot-wallet.sh [OPTIONS] -# -# Options: -# --amount SOL Amount in SOL to fund (default: 50) -# --from-wallet ADDR Source wallet address (required) -# --bot-wallet ADDR Bot wallet address (default: reads from K8s secret) -# --namespace NS K8s namespace (default: customer1) -# --dry-run Simulate transfer without sending -# --verify Verify current bot wallet balance (no transfer) -# --help Show this help -# -# This script: -# 1. Reads the bot's wallet address from the K8s secret -# 2. Sends SOL from --from-wallet to the bot wallet -# 3. Verifies the balance on-chain and in K8s -# -# Prerequisites: -# - solana-cli installed and configured -# - kubectl configured for the cluster -# - --from-wallet must have enough SOL for the transfer + fees - -set -euo pipefail - -# Defaults -AMOUNT="50" -FROM_WALLET="" -BOT_WALLET="" -NAMESPACE="customer1" -DRY_RUN=false -VERIFY_ONLY=false - -# Parse arguments -while [[ $# -gt 0 ]]; do - case $1 in - --amount) AMOUNT="$2"; shift 2 ;; - --from-wallet) FROM_WALLET="$2"; shift 2 ;; - --bot-wallet) BOT_WALLET="$2"; shift 2 ;; - --namespace) NAMESPACE="$2"; shift 2 ;; - --dry-run) DRY_RUN=true; shift ;; - --verify) VERIFY_ONLY=true; shift ;; - --help) - head -30 "$0" | tail -25 - exit 0 - ;; - *) echo "Unknown option: $1"; exit 1 ;; - esac -done - -# Helper: get bot wallet from K8s secret if not explicitly provided -get_bot_wallet_from_secret() { - if [[ -n "$BOT_WALLET" ]]; then - echo "$BOT_WALLET" - return - fi - - echo "Reading bot wallet from K8s secret..." - BOT_WALLET=$(kubectl -n "$NAMESPACE" get secret solana-quant-bot-secrets \ - -o jsonpath='{.data.SOLANA_BOT_WALLET_ADDRESS}' 2>/dev/null | base64 -d 2>/dev/null || true) - - if [[ -z "$BOT_WALLET" ]]; then - echo "ERROR: Could not read bot wallet from secret solana-quant-bot-secrets in namespace $NAMESPACE" - echo "Either deploy the secret first or pass --bot-wallet explicitly." - exit 1 - fi - echo "Bot wallet: $BOT_WALLET" -} - -# Verify balance -verify_balance() { - local wallet="$1" - echo "=== Verifying balance for $wallet ===" - - # On-chain balance - local on_chain_balance - on_chain_balance=$(solana balance "$wallet" --output json 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin))" 2>/dev/null || echo "0") - echo "On-chain SOL balance: $on_chain_balance" - - # Expected minimum - local expected - expected=$(echo "$AMOUNT * 0.99" | bc) # account for fees - local is_ok - is_ok=$(echo "$on_chain_balance >= $expected" | bc -l) - - if [[ "$is_ok" -eq 1 ]]; then - echo "OK: Balance >= $expected SOL (transferred amount minus fees)" - else - echo "WARNING: Balance ($on_chain_balance) < expected ($expected SOL)" - echo " The transfer may still be pending confirmation." - fi -} - -# --- Main --- - -echo "============================================" -echo " Solana Quant Bot — Initial Funding" -echo "============================================" -echo " Amount: $AMOUNT SOL" -echo " Namespace: $NAMESPACE" -echo " Dry run: $DRY_RUN" -echo "============================================" - -# Validate from-wallet -if [[ -z "$FROM_WALLET" ]]; then - echo "ERROR: --from-wallet is required (source wallet address)" - exit 1 -fi - -# Get bot wallet -get_bot_wallet_from_secret - -# Verify mode -if [[ "$VERIFY_ONLY" == true ]]; then - verify_balance "$BOT_WALLET" - exit 0 -fi - -# Dry run -if [[ "$DRY_RUN" == true ]]; then - echo "" - echo "DRY RUN — Would transfer $AMOUNT SOL from:" - echo " $FROM_WALLET -> $BOT_WALLET" - echo "" - echo "Source wallet balance:" - solana balance "$FROM_WALLET" - echo "" - echo "Bot wallet balance:" - solana balance "$BOT_WALLET" - echo "" - echo "To execute, remove --dry-run." - exit 0 -fi - -# Check source wallet has enough -echo "Checking source wallet balance..." -SOURCE_BALANCE=$(solana balance "$FROM_WALLET" --output json 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin))" 2>/dev/null || echo "0") -echo "Source wallet: $SOURCE_BALANCE SOL" - -HAS_ENOUGH=$(echo "$SOURCE_BALANCE >= $AMOUNT" | bc -l) -if [[ "$HAS_ENOUGH" -ne 1 ]]; then - echo "ERROR: Source wallet ($SOURCE_BALANCE SOL) has less than $AMOUNT SOL" - exit 1 -fi - -# Confirm before sending (unless CI) -if [[ "${CI:-false}" != "true" ]]; then - echo "" - read -p "Send $AMOUNT SOL from $FROM_WALLET to $BOT_WALLET? (yes/no): " CONFIRM - if [[ "$CONFIRM" != "yes" ]]; then - echo "Aborted." - exit 0 - fi -fi - -# Send transaction -echo "Sending transaction..." -TX_SIGNATURE=$(solana transfer "$FROM_WALLET" \ - "$BOT_WALLET" \ - "$AMOUNT" \ - --with-block-time \ - --output json 2>&1 | tee /tmp/solana-fund-tx.json) - -echo "Transaction: $TX_SIGNATURE" - -# Wait for confirmation -echo "Waiting for confirmation..." -solana confirm "$(echo "$TX_SIGNATURE" | python3 -c "import sys,json; print(json.load(sys.stdin)['signature'])")" --with-max-confirm-retries 20 - -# Verify balance -echo "" -verify_balance "$BOT_WALLET" - -echo "" -echo "Funding complete. Bot wallet: $BOT_WALLET" -echo "Transferred: $AMOUNT SOL"