feat: add helm charts and cleanup

  • Added Helm charts for deploying AI2
  • Renamed OpenOP_BACKEND_OAI and OpenOP_Backend → OEG_SERVICE_URL across Helm, Docker Compose and Python code
  • Removed MCP_HOST, APP_HOST env vars from Helm and Docker Compose 
  • Added readinessProbe / livenessProbe to MCP and an initContainer to ai-agent so it waits for MCP to be healthy before starting
  • Fixed Docker Compose: Python-based healthcheck (no curl in slim image), service_healthy condition on depends_on, removed deprecated version field
  • Updated READMEs to reflect all of the above

Merge request reports

Loading
+0 −1
Changes for ai_agent/README.md: 0 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ Run the container:

The Dockerfile sets these defaults:
```
ENV APP_HOST=0.0.0.0
ENV APP_PORT=9013
ENV MCP_SERVER_URL=http://127.0.0.1:8004/mcp
...
+9 −4
Changes for deployment/docker/README.md: 9 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -8,13 +8,13 @@

This deployment relies on a `.env` file that is loaded at runtime by Docker Compose.
```
GROQ_API_KEY=your-secret-key
OpenOP_BACKEND_OAI=http://example-backend
GROQ_API_KEY=your-groq-api-key
OEG_SERVICE_URL=http://your-oeg-api-url/oeg/1.0.0
GROQ_MODEL_NAME=qwen/qwen3-32b   
```

## Run
Start services

```
docker compose --env-file .env up -d
```
@@ -25,6 +25,11 @@ docker compose down

## Additional Info
All service ports are explicitly forwarded to the host to simplify local development, testing and debugging.
This allows you to interact with APIs and MCP Servers individually, without attaching to containers or using internal Docker networking tools.
This allows you to interact with APIs and MCP servers individually, without attaching to containers or using internal Docker networking tools.

| Service   | Host Port |
|-----------|-----------|
| mcp       | 8004      |
| ai-agent  | 9013      |

---
 No newline at end of file
+10 −18
Changes for deployment/docker/docker-compose.yaml: 10 added lines, 18 removed lines.
Original line number Diff line number Diff line
version: "3.9"

services:
  api:
    image: labs.etsi.org:5050/oop/code/ai2/dummy_backend
    container_name: api
    environment:
      API_HOST: 0.0.0.0
      API_PORT: 8081
    ports:
      - "8081:8081"
    networks:
      - ai_net

  mcp:
    image: labs.etsi.org:5050/oop/code/ai2/mcp_module
    container_name: mcp
    environment:
      MCP_HOST: 0.0.0.0
      MCP_PORT: 8004
      OpenOP_BACKEND_OAI: ${OpenOP_BACKEND_OAI}
      OEG_SERVICE_URL: ${OEG_SERVICE_URL}
    ports:
      - "8004:8004"
    networks:
      - ai_net
    healthcheck:
      test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8004/health')"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  ai-agent:
    image: labs.etsi.org:5050/oop/code/ai2/ai_agent
    container_name: ai-agent
    depends_on:
      - mcp
      mcp:
        condition: service_healthy
    environment:
      APP_HOST: 0.0.0.0
      APP_PORT: 9013
      MCP_SERVER_URL: http://mcp:8004/mcp
      GROQ_API_KEY: ${GROQ_API_KEY}
      GROQ_MODEL_NAME: openai/gpt-oss-20b
      GROQ_MODEL_NAME: ${GROQ_MODEL_NAME:-qwen/qwen3-32b}
    ports:
      - "9013:9013"
    networks:
+50 −0
Changes for deployment/helm/ai2/templates/_helpers.tpl: 50 added lines, 0 removed lines.
Original line number Diff line number Diff line
{{- define "ai2.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "ai2.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 }}

{{- define "ai2.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "ai2.labels" -}}
helm.sh/chart: {{ include "ai2.chart" . }}
{{ include "ai2.selectorLabels" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
{{- end }}

{{- define "ai2.selectorLabels" -}}
app.kubernetes.io/name: {{ include "ai2.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{- define "ai2.configMapName" -}}
{{- include "ai2.fullname" . }}-config
{{- end }}

{{- define "ai2.secretName" -}}
{{- include "ai2.fullname" . }}-secrets
{{- end }}

{{- define "ai2.mcpServiceName" -}}
{{- include "ai2.fullname" . }}-mcp
{{- end }}

{{- define "ai2.aiAgentServiceName" -}}
{{- include "ai2.fullname" . }}-ai-agent
{{- end }}
+27 −50
Changes for deployment/helm/ai2/templates/ai-agent-deployment.yaml: 27 added lines, 50 removed lines.
Original line number Diff line number Diff line
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ai-agent-deployment
  namespace: ai2
  name: {{ include "ai2.fullname" . }}-ai-agent
  namespace: {{ .Release.Namespace }}
  labels:
    app: ai-agent
    component: ai-agent
    {{- include "ai2.labels" . | nindent 4 }}
    app.kubernetes.io/component: ai-agent
spec:
  replicas: 1
  replicas: {{ .Values.replicaCount.aiAgent }}
  selector:
    matchLabels:
      app: ai-agent
      {{- include "ai2.selectorLabels" . | nindent 6 }}
      app.kubernetes.io/component: ai-agent
  template:
    metadata:
      labels:
        app: ai-agent
        component: ai-agent
        {{- include "ai2.selectorLabels" . | nindent 8 }}
        app.kubernetes.io/component: ai-agent
    spec:
      initContainers:
        - name: wait-for-mcp
          image: curlimages/curl:latest
          command: ["sh", "-c"]
          command: ['sh', '-c']
          args:
            - |
              until curl -f http://mcp-service:8004/health; do
                echo "Waiting for MCP service to be ready..."
                sleep 2
              until curl -sf http://{{ include "ai2.mcpServiceName" . }}:{{ .Values.config.mcp.port }}/health; do
                echo "Waiting for MCP to be ready..."
                sleep 3
              done
              echo "MCP service is ready!"

              echo ""
              echo "MCP is ready."
      containers:
        - name: ai-agent
          image: labs.etsi.org:5050/oop/code/ai2/ai_agent:latest
          imagePullPolicy: IfNotPresent
          image: "{{ .Values.images.aiAgent.repository }}:{{ .Values.images.aiAgent.tag }}"
          imagePullPolicy: {{ .Values.images.aiAgent.pullPolicy }}
          ports:
            - containerPort: 9013
              name: http
            - name: http
              containerPort: {{ .Values.config.aiAgent.port | int }}
              protocol: TCP

          env:
            - name: APP_HOST
              valueFrom:
                configMapKeyRef:
                  name: ai2-config
                  key: APP_HOST
            - name: APP_PORT
              valueFrom:
                configMapKeyRef:
                  name: ai2-config
                  name: {{ include "ai2.configMapName" . }}
                  key: APP_PORT
            - name: MCP_SERVER_URL
              valueFrom:
                configMapKeyRef:
                  name: ai2-config
                  name: {{ include "ai2.configMapName" . }}
                  key: MCP_SERVER_URL
            - name: GROQ_API_KEY
              valueFrom:
                secretKeyRef:
                  name: ai2-secrets
                  key: GROQ_API_KEY
            - name: GROQ_MODEL_NAME
              valueFrom:
                configMapKeyRef:
                  name: ai2-config
                  name: {{ include "ai2.configMapName" . }}
                  key: GROQ_MODEL_NAME

          livenessProbe:
            httpGet:
              path: /health
              port: 9013
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3

          readinessProbe:
            httpGet:
              path: /health
              port: 9013
            initialDelaySeconds: 5
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3
 No newline at end of file
            - name: GROQ_API_KEY
              valueFrom:
                secretKeyRef:
                  name: {{ include "ai2.secretName" . }}
                  key: GROQ_API_KEY
Loading
Loading