Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/terraform-modules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"modules": [
{
"name": "foundation",
"path": "terraform/foundation",
"tier": 1,
"ci_enabled": true
},
{
"name": "compute",
"path": "terraform/compute",
"tier": 2,
"ci_enabled": true
},
{
"name": "bindings",
"path": "terraform/bindings",
"tier": 3,
"ci_enabled": true
}
]
}
21 changes: 19 additions & 2 deletions charts/api-service/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,22 @@ spec:
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
# TODO: add env vars for service configuration
# TODO: add readinessProbe and livenessProbe
env:
- name: PROCESSOR_URL
value: {{ .Values.processorUrl | quote }}
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
17 changes: 16 additions & 1 deletion charts/notification-service/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,19 @@ spec:
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
# TODO: add env vars, readinessProbe, livenessProbe
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
17 changes: 16 additions & 1 deletion charts/processor-service/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,19 @@ spec:
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
# TODO: add env vars, readinessProbe, livenessProbe
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
20 changes: 20 additions & 0 deletions services/api-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Multi-stage build placeholder for api-service.
# Replace with actual build steps for your chosen language and runtime.
# Distroless base is recommended for production — minimal attack surface.

FROM python:3.12-slim

WORKDIR /app

# Non-root user — never run application containers as root.
RUN adduser --disabled-password --gecos "" appuser

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY main.py .

USER appuser
EXPOSE 8080

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
25 changes: 25 additions & 0 deletions services/api-service/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
from fastapi import FastAPI

app = FastAPI(title="api-service")

# In production this resolves to processor-service via Kubernetes DNS.
# Format: http://<service-name>.<namespace>.svc.cluster.local
# The short form http://processor-service works within the same namespace.
PROCESSOR_URL = os.getenv("PROCESSOR_URL", "http://processor-service")


@app.get("/health")
def health():
return {"status": "ok", "service": "api-service"}


@app.post("/tasks", status_code=202)
def create_task(task: dict):
# Stub: in production this calls POST processor-service/process
# and returns a task ID to the caller.
return {
"status": "accepted",
"message": "task queued for processing",
"processor_url": PROCESSOR_URL,
}
2 changes: 2 additions & 0 deletions services/api-service/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fastapi==0.111.0
uvicorn==0.30.0
17 changes: 17 additions & 0 deletions services/notification-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Multi-stage build placeholder for notification-service.

FROM python:3.12-slim

WORKDIR /app

RUN adduser --disabled-password --gecos "" appuser

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY main.py .

USER appuser
EXPOSE 8080

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
17 changes: 17 additions & 0 deletions services/notification-service/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from fastapi import FastAPI

app = FastAPI(title="notification-service")


@app.get("/health")
def health():
return {"status": "ok", "service": "notification-service"}

# This service is an async consumer — it has no inbound HTTP business routes.
# In production a background task started via @app.on_event("startup") would
# open a Service Bus receiver using workload identity (DefaultAzureCredential),
# pull messages from the notification-service subscription on the task-events
# topic, and dispatch notifications.
#
# The HTTP server exists solely to serve the /health endpoint so Kubernetes
# liveness and readiness probes have a target.
3 changes: 3 additions & 0 deletions services/notification-service/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fastapi==0.111.0
uvicorn==0.30.0

17 changes: 17 additions & 0 deletions services/processor-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Multi-stage build placeholder for processor-service.

FROM python:3.12-slim

WORKDIR /app

RUN adduser --disabled-password --gecos "" appuser

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY main.py .

USER appuser
EXPOSE 8080

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
19 changes: 19 additions & 0 deletions services/processor-service/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from fastapi import FastAPI

app = FastAPI(title="processor-service")


@app.get("/health")
def health():
return {"status": "ok", "service": "processor-service"}


@app.post("/process")
def process_task(task: dict):
# Stub: in production this validates the task payload and publishes
# an event to the Service Bus task-events topic using workload identity.
# The notification-service subscription then receives the event.
return {
"status": "processed",
"task": task,
}
2 changes: 2 additions & 0 deletions services/processor-service/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fastapi==0.111.0
uvicorn==0.30.0
8 changes: 8 additions & 0 deletions terraform/bindings/backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
backend "azurerm" {
resource_group_name = "rg-tfstate"
storage_account_name = "sttfstate7tcl"
container_name = "tfstate"
key = "taskflow-bindings.tfstate"
}
}
Loading
Loading