Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KataOps Engine banner

KataOps Engine

A production-grade, cloud-native demonstration of full-stack engineering, IaC, and automated CI/CD on AWS.

Live demo CI/CD IaC Cloud


Overview

KataOps Engine is a portfolio-grade demonstration of modern cloud engineering, originally developed during the EPAM Systems Cloud & DevOps specialization and evolved beyond it into a fully reproducible, IaC-managed deployment. The project intentionally exercises every layer of a contemporary web platform — from algorithmic backend logic to serverless container orchestration — to surface decisions that mirror real production environments rather than tutorial-grade simplifications.

The application takes three classical algorithmic challenges (katas) and exposes them through a typed Python API and a reactive frontend, deployed end-to-end on AWS via a fully automated pipeline. Every piece of infrastructure is described in code, every commit is gated by tests, and every artifact is built and shipped without manual intervention.

Live deploymenthttp://54.173.65.121:8000//


Architecture

architecture

The system follows a layered, immutable-infrastructure model: developer pushes trigger a GitHub Actions pipeline that authenticates to AWS via OIDC federation (no static credentials), provisions infrastructure with Terraform, validates code through pytest + FastAPI TestClient, builds a multistage Docker image, and pushes it to Amazon ECR. ECS Fargate pulls the image and runs the FastAPI + React 19 SPA container behind tightly scoped security groups, with all persistence delegated to a managed Amazon RDS PostgreSQL 16 instance.

Key architectural decisions:

Concern Decision Rationale
Compute ECS Fargate (serverless) Zero EC2 management overhead; pay-per-task billing
Persistence Amazon RDS PostgreSQL 16 Managed backups, patching, and HA without ops burden
Image registry Amazon ECR (private, scan-on-push) Native IAM integration with ECS; vulnerability scanning on every push
IaC Terraform ≥ 1.5, AWS provider ~> 5.0 Declarative, version-controlled, reproducible
CI/CD auth OIDC federation (no static keys) Short-lived STS credentials per workflow run; no secrets in repo
CI/CD structure 3 sequential jobs with needs: gating Test failure blocks build; build failure blocks deploy
Network egress Single public endpoint on Fargate task Demo-grade; production would front this with ALB + ACM + Route 53
Networking Default VPC + default subnets Deliberate cost/simplicity tradeoff for demo (documented in Roadmap)

Core Challenges (The Katas)

The application implements three distinct algorithmic challenges sourced from Codewars, each exposing a different cross-cutting concern of a real backend.

1. Persistent Dictionary System

A data management subsystem for inserting and querying terms, designed to demonstrate the migration from volatile state to durable persistence.

  • Persistence layer — Migrated from in-memory dictionaries to a managed PostgreSQL instance via SQLAlchemy ORM, with database sessions injected per-request through FastAPI's Depends() dependency injection.
  • Audit trail — Every write captures created_at server-side timestamps (PostgreSQL func.now()) and the originating User-Agent HTTP header, enabling forensic traceability of every entry.
  • Idempotency — Duplicate inserts are detected at the application layer (SELECT before INSERT) and rejected with HTTP 400 before reaching the database constraint level.

2. Tax Calculator

A financial calculation engine that processes itemized lists against a predefined cost catalog.

  • Business logic — Filters non-existent items defensively and applies dynamic tax rates without coupling rate values to source code.
  • Frontend feedback — React state management surfaces calculation results immediately, with controlled inputs preventing malformed submissions.
  • Pure functions — The tax engine is implemented as side-effect-free pure functions, making it trivially testable in isolation.

3. Pattern Concatenator

A string manipulation algorithm that extracts the nth character of the nth word across a list, concatenating them into a single string (e.g., ["yoda","best","has"]"yes").

  • Defense in depth — Frontend validation in App.jsx enforces word.length > index before the request leaves the browser; backend re-validates and returns HTTP 400 on IndexError (never trust the client).
  • Data transformation — Plain-text comma-separated input is parsed into typed arrays for backend processing, with explicit error responses on malformed payloads.

Technology Stack

Frontend   React Vite

Backend   Python FastAPI Uvicorn Postgres SQLAlchemy Pydantic

Infrastructure & DevOps   Docker GitHub Actions AWS Terraform Pytest


Technical Implementation

Containerization — Multistage Build

A two-stage Dockerfile produces a minimal, hardened production image with explicit security and observability defaults:

  • Stage 1 — node:20-slim compiles the React 19 SPA via Vite 8, producing static assets in frontend/dist/.
  • Stage 2 — python:3.12-slim copies the compiled dist/ output and installs runtime Python dependencies with pip --no-cache-dir, serving the SPA as static files through FastAPI + Uvicorn on port 8000. A catch-all route handles SPA client-side routing.

Hardening applied at image build:

  • Non-root runtime user — A dedicated appuser is created with no password and no shell privileges; the container's CMD runs under this user, eliminating root inside the container (CIS Docker Benchmark 4.1 compliant).
  • No bytecode artifactsPYTHONDONTWRITEBYTECODE=1 keeps the runtime filesystem free of .pyc cruft.
  • Unbuffered stdout/stderrPYTHONUNBUFFERED=1 ensures logs stream to CloudWatch Logs in real time rather than getting trapped in Python's default buffer (essential for Fargate observability).
  • Normalized timezoneTZ=UTC enforces consistent timestamps across the audit trail regardless of the host's locale.
  • Pinned base images — Both stages use explicit version tags (node:20-slim, python:3.12-slim) for reproducible builds.

This separation strips Node.js, build toolchains, and npm dev dependencies from the runtime image, producing a significantly smaller and lower-attack-surface artifact than a single-stage equivalent would yield.

Persistence — SQLAlchemy ORM over Amazon RDS

The application uses SQLAlchemy as the data access layer with a declarative Base model and per-request session lifecycle.

  • Typed models abstract raw SQL behind Pythonic objects (DictionaryEntry), making schema evolution a code-review concern rather than a deploy-time surprise.
  • Per-request sessionsget_db() yields a SessionLocal instance injected via FastAPI's Depends(), ensuring each request gets its own transaction scope with guaranteed db.close() in a finally block.
  • Server-side timestampscreated_at uses PostgreSQL's func.now() rather than Python's datetime.now(), eliminating clock skew between the application server and the database.
  • Engine portability — Tests run against an in-memory SQLite engine configured with StaticPool (so the database persists across the TestClient's request handling); production targets PostgreSQL via DATABASE_URL. The ORM abstracts the dialect difference, allowing the same model code to satisfy both environments.

Automated CI/CD Pipeline

Continuous integration and deployment are fully automated via GitHub Actions, structured as three sequential jobs with strict needs: gating:

  1. test — Pytest runs the full test suite (2 unit tests for pure kata functions + 9 API tests using FastAPI's TestClient against an in-memory SQLite engine with StaticPool for isolation). No cloud round-trips, zero per-run cost.
  2. build-and-push — Gated by needs: test. Builds the multistage Docker image and pushes it to Amazon ECR. Authentication to AWS uses OIDC federation — the workflow assumes an IAM role via short-lived STS credentials, with no long-lived access keys stored anywhere.
  3. deploy — Gated by needs: build-and-push. Triggers a force-deployment on the ECS service, prompting Fargate to drain the existing task and spin up a fresh one against the new image.

No green tests → no image build → no deployment. The pipeline is intentionally rigid because that's what makes it trustworthy.

Testing Strategy — FastAPI TestClient with SQLite StaticPool

The test suite (app/tests/) is split between pure unit tests for the kata logic and API integration tests for the actual endpoints:

  • conftest.py instantiates a fresh in-memory SQLite engine per test session, configured with StaticPool and connect_args={"check_same_thread": False} so the database survives across TestClient request boundaries. It overrides the get_db FastAPI dependency to inject the test session.
  • API tests exercise every endpoint: health check, dictionary CRUD (happy path + duplicate-rejection + 404 on lookup), tax calculation (with non-existent items), and pattern concatenation (happy path + short-word validation).
  • Total: 11 tests, all running in under a second, with zero infrastructure dependencies — runnable on a laptop or in CI without provisioning anything.

Infrastructure as Code — Terraform

The complete AWS landscape is declared in HCL and provisioned via terraform apply, with provider versions pinned (aws ~> 5.0) and Terraform itself constrained to >= 1.5.0 for reproducibility.

  • Amazon ECS (Fargate) — Serverless container orchestration; no EC2 instances to patch, scale, or monitor. Task sized at 256 CPU units / 512 MB memory for cost-efficient demo footprint.
  • Amazon RDS (PostgreSQL 16) — Managed db.t4g.micro (ARM-based burstable) instance with allocated_storage = 20 GB scaling up to 100 GB via max_allocated_storage. publicly_accessible = false keeps the database off the public internet.
  • Amazon ECR — Private container registry with scan_on_push = true enabling automatic vulnerability scanning of every pushed image.
  • Security Groups (zero-trust posture) — App SG accepts ingress on :8000 from 0.0.0.0/0; DB SG accepts ingress on :5432 exclusively from the App SG's security group ID (not its CIDR), making the database unreachable from anything except the running Fargate task — including the public internet.
  • IAM roles — Dedicated ecs_execution_role with AmazonECSTaskExecutionRolePolicy attached for ECR pull and CloudWatch Logs write; no inline wildcard policies. A separate GitHub OIDC provider + role enables federated authentication from CI.
  • Sensitive variablesdb_password is declared with sensitive = true, preventing accidental exposure in Terraform plan/apply output.
  • Stateful outputsecr_repository_url and rds_endpoint are exported as Terraform outputs for downstream pipeline consumption.

Cost Governance — AWS Budgets

Proactive AWS Budgets thresholds with automated email alerts monitor spend in real time, preventing runaway costs and aligning the project with FinOps best practices throughout its lifecycle.


Project Structure

kataops-engine/
├── app/
│   ├── main.py              # FastAPI app, endpoints, Pydantic models
│   ├── database.py          # SQLAlchemy engine, DictionaryEntry model, get_db
│   ├── katas/core.py        # Pure kata logic
│   └── tests/
│       ├── conftest.py      # TestClient + SQLite in-memory fixtures
│       └── test_core.py     # 11 tests (2 unit + 9 API)
├── frontend/src/App.jsx     # React 19 SPA with three kata cards
├── Dockerfile               # Multistage build
├── terraform/main.tf        # Full AWS infrastructure
└── .github/workflows/deploy.yml  # CI/CD pipeline (test → build → deploy)

API Endpoints

Method Path Purpose
GET /api/health Smoke check
POST /api/v1/dictionary/add Insert new term (audited)
GET /api/v1/dictionary/look/{word} Lookup single term
GET /api/v1/dictionary/all List all terms with metadata
POST /api/v1/costs/calculate Compute total with tax
POST /api/v1/strings/concat Run pattern concatenator

Visual Showcase

Application interface — Persistent Dictionary

Application interface — Tax Calculator

Application interface — Pattern Concatenator


Local Development

To run the project locally with Docker:

# 1. Clone the repository
git clone https://github.com/Nesthings/kataops-engine.git
cd kataops-engine

# 2. Build the multistage image
docker build -t kataops-engine:local .

# 3. Run the container (defaults to in-memory SQLite for dev)
docker run -p 8000:8000 kataops-engine:local

# 4. Open the app
open http://localhost:8000

To run the test suite without Docker:

pip install -r requirements.txt
PYTHONPATH=. pytest -v app/tests/

To provision the cloud infrastructure (requires AWS credentials and Terraform ≥ 1.5):

cd terraform/
terraform init
terraform plan -var="db_password=your-secure-password" -out=tfplan
terraform apply tfplan

Built by Néstor David Reyes Quiñones · Saltillo, México 🇲🇽

About

Project for the EPAM Systems Cloud & DevOps specialization course

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages