diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..d9f986d --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,23 @@ +FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04 + +# 1. Define the arguments to accept them from devcontainer.json +ARG HTTP_PROXY +ARG HTTPS_PROXY +ARG NO_PROXY +ARG http_proxy +ARG https_proxy +ARG no_proxy + +# 2. Export them as environment variables +ENV HTTP_PROXY=$HTTP_PROXY +ENV HTTPS_PROXY=$HTTPS_PROXY +ENV NO_PROXY=$NO_PROXY +ENV http_proxy=$http_proxy +ENV https_proxy=$https_proxy +ENV no_proxy=$no_proxy + +# 3. Ensure sudo keeps these variables (crucial for features that use sudo) +RUN echo 'Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy"' >> /etc/sudoers + +# 4. Prime the apt cache with proxy settings active +RUN apt-get update diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..5841678 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,64 @@ +{ + "name": "Cloud Deployment Dev Container", + "build": { + "dockerfile": "Dockerfile", + "args": { + "HTTP_PROXY": "${localEnv:HTTP_PROXY:}", + "HTTPS_PROXY": "${localEnv:HTTPS_PROXY:}", + "NO_PROXY": "${localEnv:NO_PROXY:}", + "http_proxy": "${localEnv:http_proxy:}", + "https_proxy": "${localEnv:https_proxy:}", + "no_proxy": "${localEnv:no_proxy:}" + } + }, + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { + "version": "latest", + "enableNonRootDocker": "true", + "moby": "true" + }, + "ghcr.io/devcontainers/features/node:1": { + "version": "lts" + }, + "ghcr.io/devcontainers/features/go:1": { + "version": "latest" + }, + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": true, + "configureZshAsDefaultShell": true, + "installOhMyZsh": true, + "upgradePackages": true + } + }, + "containerEnv": { + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}", + "HTTP_PROXY": "${localEnv:HTTP_PROXY:}", + "HTTPS_PROXY": "${localEnv:HTTPS_PROXY:}", + "NO_PROXY": "${localEnv:NO_PROXY:}", + "http_proxy": "${localEnv:http_proxy:}", + "https_proxy": "${localEnv:https_proxy:}", + "no_proxy": "${localEnv:no_proxy:}" + }, + "forwardPorts": [ + 4200, + 3000, + 8081, + 8003 + ], + "customizations": { + "vscode": { + "extensions": [ + "ms-azuretools.vscode-docker", + "dbaeumer.vscode-eslint", + "golang.go", + "ms-vscode.cpptools", + "ryu1kn.text-marker", + "shardulm94.trailing-spaces", + "waderyan.gitblame", + "esbenp.prettier-vscode" + ] + } + }, + "initializeCommand": "sed -i 's/\\r$//' .devcontainer/post-create.sh && /bin/bash .devcontainer/pre-create.sh", + "postCreateCommand": "sed -i 's/\\r$//' .devcontainer/post-create.sh && /bin/bash .devcontainer/post-create.sh" +} \ No newline at end of file diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh new file mode 100755 index 0000000..33d0b78 --- /dev/null +++ b/.devcontainer/post-create.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e + +# Unset empty proxy variables +for var in HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy; do + eval v="\${$var}" + if [ -z "$v" ]; then unset $var; fi +done + +# Strip all trailing '/' or '\\' from proxy URLs for apt config +strip_trailing_slash() { + local url="$1" + # Remove all trailing / or \ + url="${url%%*(/|\\)}" + # Fallback for Bash < 4.0 (no extglob): use sed + echo "$url" | sed 's%[\\/]*$%%' +} + +if [ -n "$HTTP_PROXY" ] || [ -n "$http_proxy" ] || [ -n "$HTTPS_PROXY" ] || [ -n "$https_proxy" ]; then + echo "Configuring apt to use proxy..." + sudo mkdir -p /etc/apt/apt.conf.d + # Remove all trailing / or \\ from proxy URLs + apt_http_proxy="$(strip_trailing_slash "${HTTP_PROXY:-${http_proxy:-}}")" + apt_https_proxy="$(strip_trailing_slash "${HTTPS_PROXY:-${https_proxy:-}}")" + sudo tee /etc/apt/apt.conf.d/99proxy > /dev/null </**" + ] + }, + { + "type": "pwa-node", + "request": "launch", + "name": "Debug RPS (Node.js)", + "program": "${workspaceFolder}/rps/dist/Index.js", + "cwd": "${workspaceFolder}/rps", + "envFile": "${workspaceFolder}/.env", + "sourceMaps": true, + "outFiles": [ + "${workspaceFolder}/rps/dist/**/*.js" + ], + "skipFiles": [ + "/**" + ] + }, + { + "name": "Debug MPS Router (Go)", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/mps-router/cmd/main.go", + "cwd": "${workspaceFolder}/mps-router", + "envFile": "${workspaceFolder}/.env" + }, + { + "name": "Debug Web UI (Chrome)", + "type": "pwa-chrome", + "request": "launch", + "url": "http://localhost:4200", + "webRoot": "${workspaceFolder}/sample-web-ui" + } + ], + "compounds": [ + { + "name": "Debug All Services", + "configurations": ["Debug MPS (Node.js)", "Debug RPS (Node.js)", "Debug MPS Router (Go)", "Debug Web UI (Chrome)"] + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..a5707bc --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,73 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Start Infrastructure", + "type": "shell", + "command": "docker-compose up -d db vault kong mosquitto consul", + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "group": "build", + "problemMatcher": [] + }, + { + "label": "Stop Infrastructure", + "type": "shell", + "command": "docker-compose stop db vault kong mosquitto consul", + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "label": "Restart Infrastructure", + "type": "shell", + "command": "docker-compose restart db vault kong mosquitto consul", + "problemMatcher": [] + }, + { + "label": "Connect DevContainer to Network", + "type": "shell", + "command": "docker network connect $(docker network ls --filter name=openamtnetwork --format '{{.Name}}') $HOSTNAME || echo 'Already connected or network not found'", + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": [] + }, + { + "label": "Build MPS", + "type": "typescript", + "tsconfig": "mps/tsconfig.build.json", + "group": "build" + }, + { + "label": "Build RPS", + "type": "typescript", + "tsconfig": "rps/tsconfig.build.json", + "group": "build" + }, + { + "label": "Serve WebUI (Angular)", + "type": "shell", + "command": "cd sample-web-ui && npm install && npm start -- --host 0.0.0.0", + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "Compiling..." + }, + "endsPattern": { + "regexp": "Compiled successfully" + } + } + } + } + ] +} diff --git a/DEVELOPER_DEVCONTAINER.md b/DEVELOPER_DEVCONTAINER.md new file mode 100644 index 0000000..50c853b --- /dev/null +++ b/DEVELOPER_DEVCONTAINER.md @@ -0,0 +1,116 @@ +# Cloud Deployment Developer Guide + +This guide describes how to develop and debug the Open AMT Cloud Toolkit components using the provided VS Code Dev Container environment. + +## Architecture Overview + +The development environment uses a **Hybrid** approach: +1. **Code & Services**: Your application code (MPS, RPS, Router, WebUI) runs *inside* the Dev Container as standard processes. This gives you full IDE support (IntelliSense, Debuggers). +2. **Infrastructure**: External dependencies (Postgres, Vault, Kong, etc.) run as *Docker containers* alongside the Dev Container, using the host's Docker daemon (Docker-outside-of-Docker). + +```mermaid +flowchart TD + %% Styles + classDef host fill:#f5f5f5,stroke:#333,stroke-width:2px,color:#000; + classDef docker fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#000; + classDef devcontainer fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,stroke-dasharray: 5 5,color:#000; + classDef infra fill:#fff3e0,stroke:#ef6c00,stroke-width:2px,color:#000; + classDef service fill:#ffffff,stroke:#333,stroke-width:1px,color:#000; + classDef database fill:#ffffff,stroke:#333,stroke-width:1px,shape:cylinder,color:#000; + + subgraph Host ["Host Machine (Windows/Linux/Mac)"] + Browser["Web Browser (Chrome/Edge)"]:::service + VSCode["VS Code"]:::service + + subgraph DockerEngine ["Docker Engine"] + DockerDaemon[[Docker Daemon]]:::service + + subgraph DevContainer ["Dev Container (VS Code Remote)"] + direction TB + MPS["MPS Service (Node.js)
:3000"]:::service + RPS["RPS Service (Node.js)
:8081"]:::service + Router["MPS Router (Go)
:8003"]:::service + WebUI["Sample Web UI (Angular)
:4200"]:::service + + Debugger["VS Code Debugger"]:::service + Debugger -.-> MPS + Debugger -.-> RPS + Debugger -.-> Router + Debugger -.-> WebUI + end + + subgraph Infra ["Infrastructure (Docker Compose)"] + DB[("Postgres DB
:5432")]:::database + Vault[("Vault
:8200")]:::database + Kong["Kong Gateway"]:::service + Consul["Consul"]:::service + Mosquitto["Mosquitto MQTT"]:::service + end + + %% Connections + DevContainer -- "Docker Socket" --> DockerDaemon + MPS --> DB + MPS --> Vault + RPS --> DB + RPS --> Vault + WebUI -- "HTTP" --> MPS + + %% Networking + DevContainer <== "Shared Network (openamtnetwork)" ==> Infra + end + end + + VSCode -- "Remote Connection" --> DevContainer + Browser -- "Forwarded Port 4200" --> WebUI + + %% Apply Formatting + class Host host + class DockerEngine docker + class DevContainer devcontainer + class Infra infra +``` + +## Getting Started + +### Prerequisites +* Docker Desktop (or Docker Engine on Linux) +* VS Code with **Dev Containers** extension installed. + +### Initial Setup +1. Open this folder in VS Code. +2. When prompted, click **Reopen in Container**. (Or run command: `Dev Containers: Reopen in Container`). + +## Running the Environment + +### 1. Start Infrastructure +Before running the services, you need the database and other tools up. +* Open the Command Palette (`Ctrl+Shift+P`). +* Run **Tasks: Run Task** -> **Start Infrastructure**. + * *This spins up Postgres, Vault, Kong, etc.* + +### 2. Connect Network +Ensure your Dev Container can talk to the infrastructure containers. +* Run **Tasks: Run Task** -> **Connect DevContainer to Network**. + +### 3. Start Web UI (Optional) +If you are working on the frontend: +* Run **Tasks: Run Task** -> **Serve WebUI (Angular)**. +* Wait for compilation to finish. + +### 4. Debug Services +* Go to the **Run and Debug** view (`Ctrl+Shift+D`). +* Select **"Debug All Services"**. +* Press **F5**. + * This will launch MPS, RPS, and the Router in debug mode. + * If Web UI task is running, it will also launch a Chrome window attached to the frontend. + +## Configuration Files + +* **.devcontainer/devcontainer.json**: Defines the environment (tools, extensions, port forwarding). +* **.vscode/launch.json**: Debugger configurations for Node.js (MPS/RPS), Go (Router), and Chrome (WebUI). +* **.vscode/tasks.json**: Helper scripts to manage Docker containers and build processes. + +## Troubleshooting + +* **Database connection failed**: Ensure you ran the "Start Infrastructure" task and the "Connect DevContainer to Network" task. The services look for a host named `db`. +* **Web UI not accessible**: Make sure the ports are forwarded in the **Ports** view (Ctrl+J -> Ports). Port 4200 should be pointing to localhost:4200. diff --git a/docker-compose.yml b/docker-compose.yml index eebf52c..69bc44a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,7 @@ services: MPS_SERVER: https://${MPS_COMMON_NAME}/mps VAULT_SERVER: https://${MPS_COMMON_NAME}/vault volumes: - - ./nginx.conf:/etc/nginx/conf.d/default.conf + - ${LOCAL_WORKSPACE_FOLDER:-.}/nginx.conf:/etc/nginx/conf.d/default.conf rps: restart: always image: intel/oact-rps:latest @@ -109,7 +109,7 @@ services: ports: - 5432:5432 volumes: - - ./data:/docker-entrypoint-initdb.d + - ${LOCAL_WORKSPACE_FOLDER:-.}/data:/docker-entrypoint-initdb.d vault: restart: always image: hashicorp/vault @@ -169,7 +169,7 @@ services: networks: - openamtnetwork volumes: - - ./kong.yaml:/home/kong/kong.yml + - ${LOCAL_WORKSPACE_FOLDER:-.}/kong.yaml:/home/kong/kong.yml ports: - 443:8443 - 8001:8001 @@ -179,7 +179,7 @@ services: ports: - 8883:8883 volumes: - - ./mosquitto.conf:/mosquitto/config/mosquitto.conf + - ${LOCAL_WORKSPACE_FOLDER:-.}/mosquitto.conf:/mosquitto/config/mosquitto.conf networks: - openamtnetwork profiles: