From 7c6eb5c0c0335149a5fb25facf91560b319c91c1 Mon Sep 17 00:00:00 2001 From: YATIN JAMWAL Date: Fri, 6 Feb 2026 19:26:30 +0530 Subject: [PATCH] setup dockerized development environment and fix dependency conflicts (#34) Adds Docker setup, patches dependencies to align Vert.x versions, and includes validation scripts for a reproducible local sandbox. Signed-off-by: YATIN JAMWAL --- DEVELOPMENT.md | 36 ++++++++++++++++++++++ Dockerfile | 49 ++++++++++++++++++++++++++++++ docker-compose.yml | 40 +++++++++++++++++++++++++ emulator.Dockerfile | 8 +++++ patches/apis-bom-pom.xml | 58 ++++++++++++++++++++++++++++++++++++ patches/apis-common-pom.xml | 59 +++++++++++++++++++++++++++++++++++++ validate_env.py | 55 ++++++++++++++++++++++++++++++++++ 7 files changed, 305 insertions(+) create mode 100644 DEVELOPMENT.md create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 emulator.Dockerfile create mode 100644 patches/apis-bom-pom.xml create mode 100644 patches/apis-common-pom.xml create mode 100644 validate_env.py diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..e81a710 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,36 @@ +# APIS Development Environment Setup + +## Prerequisites +* Docker & Docker Compose +* Git + +## Setup Steps + +1. **Clone Dependencies** + Ensure all sub-repositories are cloned into the root structure: + * apis-bom + * apis-common + * apis-main + * apis-web + * apis-emulator + +2. **Start Sandbox Environment** + ```bash + docker-compose up --build + ``` + +3. **Services** + * **Dashboard (Web)**: Endpoints available at `localhost:43900` and `localhost:9999`. + * **Grid Master (Main)**: Running autonomously. + * **Hardware (Emulator)**: Simulating 4 battery units. + +## Testing APIs +See `validate_env.py` for automated testing. + +* **Energy Balance Check**: `GET http://localhost:43900/get/log` +* **Power Allocation**: `POST http://localhost:9999/deal` + +## Troubleshooting +* **Build Fails**: Ensure `apis-bom` and `apis-common` are using version 3.0.0 in `pom.xml`. +* **Ports in Use**: Stop native services if running (`make stop`). +* **Hazelcast Errors**: Docker Compose uses `hostname -i` to discover peers. Ensure firewall allows port 5701. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e3f4e07 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,49 @@ +# Stage 1: Build All Java Components +FROM maven:3.9-eclipse-temurin-11 AS builder +WORKDIR /build + +# Copy and install BOM +COPY apis-bom /build/apis-bom +# APPLY PATCH: Fix dependency versions +COPY patches/apis-bom-pom.xml /build/apis-bom/pom.xml +WORKDIR /build/apis-bom +RUN mvn install -DskipTests + +# Copy and install Common +COPY apis-common /build/apis-common +# APPLY PATCH: Fix dependency versions +COPY patches/apis-common-pom.xml /build/apis-common/pom.xml +WORKDIR /build/apis-common +RUN mvn install -DskipTests + +# Build apis-main +COPY apis-main /build/apis-main +WORKDIR /build/apis-main +RUN mvn package -DskipTests + +# Build apis-web +COPY apis-web /build/apis-web +WORKDIR /build/apis-web +RUN mvn package -DskipTests + +# Stage 2: APIS Main Runtime +FROM eclipse-temurin:11-jre AS apis-main +WORKDIR /app +COPY --from=builder /build/apis-main/target/apis-main-*-fat.jar /app/apis-main.jar +# Default config files will be mounted via Volume or use defaults +COPY apis-main/exe/logging.properties /app/ +COPY apis-main/exe/config.json /app/ +COPY apis-main/exe/cluster.xml /app/ +ENV CLUSTER_HOST_IP=127.0.0.1 +# Entrypoint to dynamically set cluster host IP +CMD ["sh", "-c", "java -Djava.net.preferIPv4Stack=true -Djava.util.logging.config.file=./logging.properties -Dvertx.hazelcast.config=./cluster.xml -jar apis-main.jar -conf ./config.json -cluster -cluster-host $(hostname -i)"] + +# Stage 3: APIS Web Runtime +FROM eclipse-temurin:11-jre AS apis-web +WORKDIR /app +COPY --from=builder /build/apis-web/target/apis-web-*-fat.jar /app/apis-web.jar +COPY apis-web/exe/logging.properties /app/ +COPY apis-web/exe/config.json /app/ +COPY apis-web/exe/cluster.xml /app/ +ENV CLUSTER_HOST_IP=127.0.0.1 +CMD ["sh", "-c", "java -Djava.net.preferIPv4Stack=true -Djava.util.logging.config.file=./logging.properties -jar apis-web.jar -conf ./config.json -cp ./ -cluster -cluster-host $(hostname -i)"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5fc44e6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,40 @@ +version: '3.8' + +services: + mongodb: + image: mongo:4.4 + container_name: apis-mongo + ports: + - "27017:27017" + + apis-main: + build: + context: . + dockerfile: Dockerfile + target: apis-main + container_name: apis-main + depends_on: + - mongodb + ports: + - "5701:5701" # Hazelcast + + apis-web: + build: + context: . + dockerfile: Dockerfile + target: apis-web + container_name: apis-web + depends_on: + - apis-main + ports: + - "43830:43830" # Budo Emulator + - "43900:43900" # Emulator Emulator + - "9999:9999" # API Server (Deals/Errors) + + apis-emulator: + build: + context: . + dockerfile: emulator.Dockerfile + container_name: apis-emulator + command: python3 startEmul.py 4 + network_mode: service:apis-main # Run in same net namespace to simulate local Hardware connection if using multicast, simplifed for now diff --git a/emulator.Dockerfile b/emulator.Dockerfile new file mode 100644 index 0000000..81af311 --- /dev/null +++ b/emulator.Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.9-slim +WORKDIR /app +COPY apis-emulator/requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY apis-emulator/ . +# Fix line endings if cloned on Windows +RUN apt-get update && apt-get install -y dos2unix && dos2unix *.py *.sh +CMD ["python3", "startEmul.py", "4"] diff --git a/patches/apis-bom-pom.xml b/patches/apis-bom-pom.xml new file mode 100644 index 0000000..68d2858 --- /dev/null +++ b/patches/apis-bom-pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + + + UTF-8 + 3.7.1 + 4.12 + 2.4 + + + jp.co.sony.csl.dcoes.apis + apis-bom + 3.0.0 + pom + + APIS BOM + + + + + jp.co.sony.csl.dcoes.apis + apis-common + ${project.version} + + + io.vertx + vertx-core + ${vertx.version} + + + io.vertx + vertx-mongo-client + ${vertx.version} + + + io.vertx + vertx-hazelcast + ${vertx.version} + + + io.vertx + vertx-unit + ${vertx.version} + + + junit + junit + ${junit.version} + + + commons-io + commons-io + ${commons-io.version} + + + + + diff --git a/patches/apis-common-pom.xml b/patches/apis-common-pom.xml new file mode 100644 index 0000000..6c18f48 --- /dev/null +++ b/patches/apis-common-pom.xml @@ -0,0 +1,59 @@ + + 4.0.0 + + + UTF-8 + 3.7.1 + + + jp.co.sony.csl.dcoes.apis + apis-common + 3.0.0 + + APIS COMMON + + + + + jp.co.sony.csl.dcoes.apis + apis-bom + ${project.version} + pom + import + + + + + + + io.vertx + vertx-core + + + io.vertx + vertx-unit + test + + + junit + junit + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 1.8 + 1.8 + + + + + + diff --git a/validate_env.py b/validate_env.py new file mode 100644 index 0000000..63fb1da --- /dev/null +++ b/validate_env.py @@ -0,0 +1,55 @@ +import requests +import json +import time + +print("Waiting for services to start...") +time.sleep(10) # Simple wait, or use retry logic + +# 1. Energy Balance Check (Get Hardware Logs) +try: + print("\n--- Testing Energy Balance Check API ---") + url = "http://localhost:43900/get/log" + print(f"GET {url}") + response = requests.get(url, timeout=5) + print(f"Status: {response.status_code}") + if response.status_code == 200: + data = response.json() + print("Success! Received hardware telemetry.") + # Check first key (usually 'apis' or specific unit ID) + print(f"Keys: {list(data.keys())[:3]}...") + else: + print("Failed to get logs.") +except Exception as e: + print(f"Error: {e}") + +# 2. Power Allocation (Deal Generation) +try: + print("\n--- Testing Power Allocation API ---") + url = "http://localhost:9999/deal" + + # Mock OpenPAYGO Deal Payload (Example shape based on code) + payload = { + "dealId": "test-deal-001", + "requestUnitId": "unit1", + "acceptUnitId": "unit2", + "amountWh": 100, + "type": "charge" + } + + # The API expects form-data with a 'json' field containing the stringified JSON + files = { + 'json': (None, json.dumps(payload)) + } + + print(f"POST {url} with payload: {payload}") + response = requests.post(url, files=files, timeout=5) + print(f"Status: {response.status_code}") + print(f"Response: {response.text}") + + if response.status_code == 200: + print("Success! Deal request submitted.") + else: + print("Deal submission failed.") + +except Exception as e: + print(f"Error: {e}")