diff --git a/README.md b/README.md index 5b66a66..ad11d07 100644 --- a/README.md +++ b/README.md @@ -1,306 +1,274 @@ -## DevOps exercise +# Beer Catalog DevOps Assignment -## Exercise -There is an app written in Python and a Terraform folder. - -The `docker` folder contains a simple Dockerfile. - -### Create the following resource: -In terraform: -- ECR resources (if you choose ECR, github registry is also fine) -- ECS Cluster -- ECS Service -- RDS Instance (postgres based) - -### For the app: -You need a local setup for the project, i.e. some readme entry showing how to run the app on your machine - -- We need to automate the build process -- Locally the app runs in a virtenv, but on prod it will run the Dockerfile - -### CD/CI -- GitHub Actions Workflows - - Pull Request Checks - - Build image - - Push image to ECR (or github registries) - - Deployment of the app into non-prod envs (or prod like envs, if you have the time) - -### Extras -- Postgres user and permission configuration in terraform -- There are intentional mistakes all over the place. Kudos if you find and solve them. - -## App -The small app in python has only two endpoints -- Get all beers -- Insert one beer -- Seed beers (for testing) - -## Considerations -- More than the TF code to be running we will check the plan it generates. -- Doesn't need to be perfect -- Avoid using open source modules for setting networking / ecs. We want to see your capabilities at writing the resources - -## What will be evaluated -- Terraform best practices -- Structure of the terraform code -- Naming conventions -- Separation of concerns -- AWS knowledge - -## How to Deploy This Infrastructure to AWS 👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻👈🏻 - -This project is ready to be deployed to AWS using Terraform. Follow these steps to connect your resources to your AWS account and provide all required variables. +## Project Overview +This project demonstrates a complete DevOps workflow for a Python web application, containerized with Docker, deployed on AWS using Terraform, and automated with GitHub Actions. The solution follows 12-factor app and SOLID principles, with a focus on security, automation, and documentation. --- -### 1. **Set Up AWS Credentials** +## Architecture +- **Flask App** (Dockerized, venv for local dev) +- **PostgreSQL** (AWS RDS) +- **ECS Fargate** (App hosting) +- **ECR** (Docker image registry) +- **VPC, Subnets, Security Groups** (Terraform-managed) +- **CloudWatch** (Logging & Alarms) +- **GitHub Actions** (CI/CD) -Terraform needs AWS credentials to create resources in your account. -You can provide credentials in several ways, but the most common is using the AWS CLI: - -```sh -aws configure -``` -- Enter your AWS Access Key ID -- Enter your AWS Secret Access Key -- Enter your default region (e.g., us-east-1) -- Enter your default output format (json is fine) - -Alternatively, you can set these as environment variables: -```sh -export AWS_ACCESS_KEY_ID=your-access-key -export AWS_SECRET_ACCESS_KEY=your-secret-key -export AWS_DEFAULT_REGION=us-east-1 -``` +![Architecture Diagram](imgs/infra.png) --- -### 2. **Set Required Terraform Variables** - -Some resources require variables that must be provided at runtime, such as your database password and the Docker image for your app. - -You can provide these variables in several ways: +## Local Development -**A. As environment variables:** +### 1. Clone the repository ```sh -export TF_VAR_db_password="yourStrongPassword" -export TF_VAR_app_image="123456789012.dkr.ecr.us-east-1.amazonaws.com/beer-catalog-app:latest" +git clone git@github.com:alex-504/devops-test-master.git +cd devops-test-master/app/beer_catalog ``` -**B. As command-line arguments:** +### 2. Set up a virtual environment and install Poetry ```sh -terraform apply -var="db_password=yourStrongPassword" -var="app_image=123456789012.dkr.ecr.us-east-1.amazonaws.com/beer-catalog-app:latest" +python3 -m venv venv +source venv/bin/activate +pip install poetry ``` -**C. In a `terraform.tfvars` file:** -```hcl -db_password = "yourStrongPassword" -app_image = "123456789012.dkr.ecr.us-east-1.amazonaws.com/beer-catalog-app:latest" +### 3. Install dependencies with Poetry +```sh +poetry install ``` --- -### 3. **Initialize and Validate Terraform** - +### 4. Run the app with SQLite (quick start, no setup needed) ```sh -terraform init -terraform validate +export DATABASE_URL="sqlite:///beers.db" +poetry run python -m flask --app beer_catalog/app run --debug ``` +- The app will be available at [http://127.0.0.1:5000](http://127.0.0.1:5000). --- -### 4. **Plan and Apply** +### 5. Run the app with PostgreSQL + +**Prerequisites:** +- PostgreSQL installed (e.g., `brew install postgresql@14` on macOS) +- Start PostgreSQL (macOS/Homebrew): + ```sh + brew services start postgresql@14 + # or for other versions: + # brew services start postgresql + ``` +- Check status: + ```sh + brew services list + ``` +- Create the database (if not already created): + ```sh + createdb beer_catalog + ``` + - If you see an error like `database "beer_catalog" already exists`, you can skip this step. + +**Set the DATABASE_URL environment variable:** +- The default user is usually your macOS username (e.g., `alexandrevieira`). +- If you use a password, add it after the username: `postgresql://:@localhost:5432/beer_catalog` -**Preview the changes:** ```sh -terraform plan +export DATABASE_URL="postgresql://@localhost:5432/beer_catalog" ``` -**Apply the changes (provision resources):** +**Run the app:** ```sh -terraform apply +poetry run python -m flask --app beer_catalog/app run --debug ``` +- The app will be available at [http://127.0.0.1:5000](http://127.0.0.1:5000). --- -### 5. **Notes** - -- You must have sufficient AWS permissions to create VPCs, subnets, ECS, RDS, ECR, and IAM roles. -- The `app_image` variable should point to a Docker image you have pushed to your ECR repository. -- The `db_password` should be a strong password for your PostgreSQL database. -- No AWS resources will be created until you run `terraform apply`. -- You can destroy all resources with: +### Testing Endpoints +- Health check: + ```sh + curl http://127.0.0.1:5000/health + ``` +- Get all beers: + ```sh + curl http://127.0.0.1:5000/beers + ``` +- Add a beer: ```sh - terraform destroy + curl -X POST http://127.0.0.1:5000/beers \ + -H "Content-Type: application/json" \ + -d '{"name": "Heineken", "style": "Lager", "abv": 5.0}' ``` --- -**If you do not have an AWS account, you can still review and validate the code with `terraform validate`.** +## Running the App with Docker -## How to test the app +You can run the app locally using Docker, just like in production (ECS). This ensures consistency and lets you test the container before deploying. -Pre-requisites: -- PostgreSQL installed (brew install postgresql@14 on macOS) -- Python 3.11+ installed -- Poetry installed (pip install poetry) +### 1. Build the Docker image +```sh +docker build -t beer-catalog-app . +``` -Step 1: Cteate a PostgreSql database -```bash -brew install postgresql@14 +### 2. Run the app with SQLite (no extra setup needed) +```sh +docker run -p 5000:5000 beer-catalog-app ``` +- The app will be available at [http://localhost:5000](http://localhost:5000). -Step 2: Create a virtual environment -```bash -cd app # if not in app already -python3 -m venv venv +### 3. Run the app with PostgreSQL (macOS/Windows) +If you want to use your local PostgreSQL database with Docker: +```sh +docker run -p 5000:5000 -e DATABASE_URL="postgresql://@host.docker.internal:5432/beer_catalog" beer-catalog-app +``` +- Replace `` with your Postgres username. +- If you use a password, add it after the username. +- The app will be available at [http://localhost:5000](http://localhost:5000). -# Activate virtual environment -source venv/bin/activate +> **Note:** This is the same Docker image that is pushed to ECR and used by ECS in production, ensuring consistency between local and cloud environments. -# Install Poetry (if not already installed) -pip install poetry +--- -# Update Poetry lock file (after dependency changes) -poetry lock +## Deploying to AWS (using Dockerfile) -# Install project dependencies -poetry install +### 1. Build & Push Docker Image +- Automated via GitHub Actions on push to `main`, `master`, `feature/*` branches. For production, we can use the `main` branch. (next updates would be added) + +### 2. Provision Infrastructure +```sh +cd terraform +terraform init +terraform plan +terraform apply ``` +- All AWS resources (ECR, ECS, RDS, VPC, etc.) are created from scratch (no prebuilt modules). -**Step 3: Test with PostGres** -```bash -export DATABASE_URL="postgresql://localhost/beer_catalog" +### 3. App Access (using ECS Public IP) +- App will be available at the `ECS public IP` (see ECS task details in AWS Console). +For example, if the ECS public IP is `123.456.789.012`, the app will be available at `http://123.456.789.012:5000`. -# Create the database -createdb beer_catalog +--- -# Run the Flask application -python -m flask --app beer_catalog/app run --debug -``` +## CI/CD Pipeline (workflows/docker-ecr.yml) +- **Pull Request Checks:** Linting and (optional) tests on every PR. +- **Docker Build & Push:** On merge to `main`, `master`, `feature/*` branches, image is built and pushed to ECR. +- **ECS Deployment:** ECS service is updated with the new image. +- **Push image to ECR:** On push, the new image is built and pushed to ECR. +- **Deploy app to ECS:** ECS service is updated with the new image. -Step 4: Test endpoints -```bash -# Health check -curl http://127.0.0.1:5000/health -# Expected: {"status": "healthy", "database": "connected"} +The workflows are define on `.github/workflows/` folder. -# Get beers (initially empty) -curl http://127.0.0.1:5000/beers -# Expected: [] +--- -# Seed the database -python seed.py -# Expected: JSON output with seeding status +## Terraform Infrastructure +- **ECR repository** for Docker images +- **ECS cluster & service** for app hosting +- **RDS PostgreSQL instance** +- **VPC, subnets, security groups** (built from scratch) +- **CloudWatch log group & alarms** +- **No prebuilt modules used for ECS or networking** -# Get beers (now populated) -curl http://127.0.0.1:5000/beers -# Expected: Array of beer objects -``` +--- -** Running the app with Sqlite** +## API Endpoints +| Method | Endpoint | Description | +|--------|------------------|--------------------| +| GET | /health | Health check | +| GET | /beers | List all beers | +| POST | /beers | Add a new beer | +| POST | /seed | Seed database | -**Step 1: Setup Python environment** -```bash -cd app -python3 -m venv venv -source venv/bin/activate -pip install poetry -poetry lock -poetry install -``` +> **Note:** No `/beers/` endpoint as per the original app. -**Step 2: Run the app with Sqlite** -```bash -export DATABASE_URL="sqlite:///beers.db" -python -m flask --app beer_catalog/app run --debug -``` +--- -**Step 3: Test endpoints** -```bash -# Health check -curl http://127.0.0.1:5000/health -# Expected: {"status": "healthy", "database": "connected"} +## Best Practices & Gotchas +- **Intentional Issues:** Documented and fixed in `ISSUES_FOUND.md`. +- **12-factor & SOLID:** Environment variables, logging, error handling, and code structure. +- **Security:** IAM roles, least privilege, no hardcoded secrets. +- **Naming & Structure:** Consistent resource names, clear separation of concerns. -# Get beers (initially empty) -curl http://127.0.0.1:5000/beers -# Expected: [] becase it is not seeded yet +--- -# Seed the database -python seed.py -# Expected: JSON output with seeding status +## Monitoring & Logging +- **CloudWatch Logs:** ECS task logs +- **CloudWatch Alarms:** RDS high CPU, ECS task failures -# Get beers (now populated) -curl http://127.0.0.1:5000/beers -# Expected: Array of beer objects +--- -``` +## Screenshots of AWS Console +(All rerouces were created from scratch and provisioned using Terraform) +### AWS Console: +* [ECS cluster](https://loom.com/i/6ef15cfc31134456a40189fdb4cdd986), +* [ECS Logs](https://loom.com/i/dbc136a6fc3c4658936bb742ad26fa3f), +* [RDS PostgreSQL DB](https://loom.com/i/02449ce6b4c049f2b55c28304dae4a30), +* [RDS Monitoring](https://loom.com/i/4140cdba78774d3c8a2e7efa9ea67176), +* [RDS User Permission Setup](https://loom.com/i/03da3cd136f541999745a76d89171b06), +* [VPC](https://loom.com/i/a03bed3225d74aebb01bbaa0044307b3), +* [CloudWatch log events](https://loom.com/i/a77189d4c7fb4de6b398535894c5cee6), +* [CloudWatch Alarms](https://loom.com/i/047193a0a7e84e81b2dd2b0b98997666) +### App endpoints tested via 'curl' +- health Check: `curl http://3.27.247.99:5000/health` -> [screenshot](https://www.loom.com/i/488f3093723d48c1945b88fae43526ae) +- get all beers: curl `http://3.27.247.99:5000/beers` -> [screenshot](https://loom.com/i/1a78218075ae481782c82a44a2862176) +- add a beer: `curl -X POST http://3.27.247.99:5000/beers -H "Content-Type: application/json" -d '{"name": "Heineken", "style": "Lager", "abv": 5.0}'` -> [screenshot](https://loom.com/i/2f445224a9ea41a79ebdce70c24ac064) +- ❌ seed the database: `curl -X POST http://3.27.247.99:5000/seed` -> [screenshot](https://loom.com/i/79f75d35e15345d381e3f7e318017c9f) + +### CI/CD pipeline runs +- [PR Checks](https://loom.com/i/6f4d55c60d0747959f1fe52062a4dbca) +- [Build and Push Docker Image to ECR](https://loom.com/i/243f707b845c4e91bed08453d95296dd) +- [ECR Repository](https://loom.com/i/56434a184635491994c211caa5c81627) +- [ECS Service](https://loom.com/i/3e1cdec272854f52b8aeff94fa1fea3e) +- [ECR Tasks Overview](https://loom.com/i/c068637d241b44b8af4b4936094e3bb7) -** Summary of DB tests: -| Step | SQLite Command/Setting | PostgreSQL Command/Setting | -|---------------------|-----------------------------------------------|---------------------------------------------------| -| **Set DB URL** | `export DATABASE_URL="sqlite:///beers.db"` | `export DATABASE_URL="postgresql://localhost/beer_catalog"` | -| **Start Flask** | `python -m flask --app beer_catalog/app run --debug` | `python -m flask --app beer_catalog/app run --debug` | -| **Seed Data** | `python seed.py` | `python seed.py` | -| **Test Endpoints** | Same for both | Same for both | - -## Useful commands - -**Adding new beers** -```bash -url -X POST http://127.0.0.1:5000/beers \ - -H "Content-Type: application/json" \ - -d '{"name": "Heineken", "style": "Lager", "abv": 5.0}' -``` -**Get all beers** -```bash -curl http://127.0.0.1:5000/beers -``` +--- -**Health check** -```bash -curl http://127.0.0.1:5000/health -``` +## Troubleshooting & Common Issues +- **Region Mismatch:** Ensure AWS CLI and Console are set to `ap-southeast-2`. +- **Resource Already Exists:** Delete or import orphaned resources. +- **App Not Responding:** Check ECS task status, security groups, and logs. +- **Terraform State Issues:** Use `terraform import` or clean up resources as needed. -**Seed the database** -- To reseed, first we need to clear the database -```bash -dropdb beer_catalog -createdb beer_catalog -python seed.py -``` +--- -## 🐳 ECS (Elastic Container Service) Setup +## Evaluation Points +- **Infrastructure design:** Built for scalability and team collaboration. +- **Naming & documentation:** Clear, standardized, and recruiter-friendly. +- **CI/CD pipeline:** Automated, reliable, and secure. +- **Resilience & security:** Follows AWS and DevOps best practices. +- **Troubleshooting:** All intentional issues found and documented. -This project uses AWS ECS Fargate to run the Beer Catalog app in a scalable, managed container environment. +--- -### What's Set Up -- **ECS Cluster**: The environment where your containers run -- **Task Definition**: The "recipe" for your app container (image, ports, env vars) -- **Task Execution Role**: Lets ECS pull images from ECR and write logs -- **ECS Service**: Keeps your app running and accessible in the public subnet +## Bonus Features (status) +- [✓] RDS user/permission automation. Refer to `aws_db_instance`, `aws_db_user`, `aws_db_parameter_group`, or `aws_db_role` +- [✓] Secret management. Refer to `terraform.tfvars` +- [X] ECS Service Auto Scaling. I did not have time to implement this since it required very specific configuration on AWS and loadbalancer. -### How to Configure the App Image -- Set the `app_image` variable to the full ECR image URL you want to deploy (e.g., `123456789012.dkr.ecr.us-east-1.amazonaws.com/beer-catalog-app:latest`). -- You can do this via environment variable, command-line flag, or `terraform.tfvars` (see AWS deployment instructions above). +--- -### How to Access the App -- After deployment, the app will be running in the public subnet on port 5000. -- You can find the public IP by checking the ECS task in the AWS console (or by adding a Terraform output for the task ENI/public IP). -- If you add a load balancer, update this section to explain how to access the app via the load balancer DNS name. +## Next Steps / Improvements +- Add `/beers/` endpoint +- Add authentication/authorization +- Use Terraform modules for larger projects +- Add automated integration tests +- ECS Service Auto Scaling +- Add ECR Lifecycle policy: to restrict the number of images in the repository. It would limit the growth of images in the repository. + +--- -### Notes -- The ECS service is set to run 1 copy of your app by default. You can scale this by changing the `desired_count` in the Terraform code. -- For production, consider adding a load balancer and auto-scaling. -## Monitoring & Alerts +## Minor Personal Notes +- Time Investment notes: ~2h to complete the full AWS Deployment. +- I would like to have tested more the CI/CD pipeline. +- Cost optimization: I created a [budget Status](https://loom.com/i/e293bf96e91d4b7799a8987bb9943d7f) on AWS Console, to avoid unexpected costs. +- I would like to have added a deletion protection on RDS instance (`deletion_protection = var.environment == "prod" ? true : false`), maybe next time. -- **CloudWatch Alarms:** - - `ECS-Task-Failures`: Triggers if any ECS task fails in the `beer-catalog-service`. - - `RDS-High-CPU`: Triggers if RDS CPU utilization exceeds 80%. -- Both alarms are provisioned via Terraform and can be viewed in the AWS CloudWatch console. -- See `cloudwatch_alarms.png` for a screenshot of the alarms in the AWS Console. +## Contact +Alexandre Vieira +[https://www.linkedin.com/in/alexandre-dev/] diff --git a/SCHEDULE.md b/SCHEDULE.md deleted file mode 100644 index 3716ce0..0000000 --- a/SCHEDULE.md +++ /dev/null @@ -1,228 +0,0 @@ -# DevOps Assignment - Strategic Schedule (Updated) - -## Overview -This schedule is designed for a 10-12 hour completion window, prioritizing learning and best practices over speed. Each phase builds upon the previous one, following DevOps principles. **Updated to address identified "gotchas" strategically.** - -## Phase 1: Foundation & Critical Fixes (2-3 hours) -**Goal**: Fix critical issues and establish working local development environment - -### 1.1 Application Analysis & Critical Fixes (1 hour) -- [ ] Examine the Python application structure -- [ ] **CRITICAL**: Fix database configuration (SQLite → PostgreSQL) -- [ ] **CRITICAL**: Add PostgreSQL driver dependency -- [ ] **CRITICAL**: Implement environment variable configuration -- [ ] **CRITICAL**: Add basic error handling and input validation -- [ ] Fix data types (ABV as Float instead of String) -- [ ] Add health check endpoint for load balancer -- [ ] Document all fixes made - -### 1.2 Local Environment Setup (1 hour) -- [ ] Set up Python virtual environment -- [ ] Install dependencies (Poetry) - fix configuration issues -- [ ] Configure local PostgreSQL database -- [ ] Test application locally with proper error handling -- [ ] Document local setup in README -- [ ] Test all endpoints including health check - -### 1.3 Docker Foundation & Security (1 hour) -- [ ] Review existing Dockerfile -- [ ] **SECURITY**: Fix root user issue (create non-root user) -- [ ] **SECURITY**: Add environment variable support -- [ ] Test Docker build locally -- [ ] Ensure 12-factor app compliance -- [ ] Test containerized application -- [ ] Validate security fixes - -**Learning Focus**: Understanding application architecture, fixing critical production issues, containerization basics, and security best practices. - ---- - -## Phase 2: Infrastructure Planning & Design (2-3 hours) -**Goal**: Design scalable, secure infrastructure that addresses identified issues - -### 2.1 Infrastructure Architecture Design (1 hour) -- [ ] Plan VPC and networking structure -- [ ] Design ECS cluster architecture with health checks -- [ ] Plan RDS PostgreSQL setup with proper security -- [ ] Design ECR/container registry strategy -- [ ] Plan secrets management for database credentials -- [ ] Document infrastructure decisions and how they address the "gotchas" - -### 2.2 Terraform Structure Planning (1 hour) -- [ ] Design Terraform module structure (networking, compute, database) -- [ ] Plan separation of concerns based on identified issues -- [ ] Design naming conventions -- [ ] Plan state management strategy -- [ ] Create Terraform directory structure -- [ ] Plan how to handle environment variables in infrastructure - -### 2.3 Security & Best Practices Planning (1 hour) -- [ ] Plan IAM roles and policies for ECS tasks -- [ ] Design security groups for RDS and ECS -- [ ] Plan secrets management approach (AWS Secrets Manager) -- [ ] Design backup and disaster recovery for RDS -- [ ] Plan monitoring and logging (CloudWatch) -- [ ] Plan how to handle the session management issues in production - -**Learning Focus**: Infrastructure as Code principles, AWS services, security best practices, and how infrastructure addresses application issues. - ---- - -## Phase 3: Terraform Implementation (3-4 hours) -**Goal**: Implement infrastructure that properly supports the fixed application - -### 3.1 Networking Foundation (1 hour) -- [ ] Implement VPC with public/private subnets -- [ ] Configure Internet Gateway and NAT Gateway -- [ ] Set up security groups with proper rules -- [ ] Configure route tables -- [ ] Test networking connectivity -- [ ] Ensure security groups allow proper database access - -### 3.2 Database Infrastructure (1 hour) -- [ ] Implement RDS PostgreSQL instance with proper configuration -- [ ] Configure database security groups -- [ ] Set up database subnet group in private subnets -- [ ] Configure backup and maintenance windows -- [ ] **BONUS**: Implement PostgreSQL user and permission setup -- [ ] Test database connectivity from local environment - -### 3.3 Container Registry (30 min) -- [ ] Implement ECR repository -- [ ] Configure repository policies -- [ ] Test image push/pull operations -- [ ] Set up lifecycle policies -- [ ] Configure ECR login for GitHub Actions - -### 3.4 ECS Infrastructure (1-1.5 hours) -- [ ] Implement ECS cluster -- [ ] Create ECS task definition with proper environment variables -- [ ] Configure ECS service with health checks -- [ ] Set up application load balancer -- [ ] Configure auto-scaling (bonus) -- [ ] Ensure proper IAM roles for ECS tasks - -**Learning Focus**: Terraform syntax, AWS resource relationships, infrastructure dependencies, and how infrastructure supports the fixed application. - ---- - -## Phase 4: CI/CD Pipeline (2-3 hours) -**Goal**: Automate deployment pipeline with proper testing and validation - -### 4.1 GitHub Actions Foundation (1 hour) -- [ ] Set up GitHub repository secrets for AWS credentials -- [ ] Create basic workflow structure -- [ ] Configure AWS credentials in GitHub Actions -- [ ] Test basic workflow execution -- [ ] Plan how to handle environment variables in CI/CD - -### 4.2 Build Pipeline (1 hour) -- [ ] Implement Docker build workflow -- [ ] Configure image tagging strategy -- [ ] Set up image push to ECR -- [ ] Add build validation and testing -- [ ] **BONUS**: Add security scanning for Docker images -- [ ] Test the complete build pipeline - -### 4.3 Deployment Pipeline (1 hour) -- [ ] Implement ECS deployment workflow -- [ ] Configure blue-green deployment strategy -- [ ] Set up deployment validation with health checks -- [ ] Add rollback capabilities -- [ ] **BONUS**: Add automated testing in deployment pipeline -- [ ] Test the complete deployment pipeline - -**Learning Focus**: CI/CD principles, GitHub Actions, deployment strategies, and automation best practices. - ---- - -## Phase 5: Testing & Optimization (1-2 hours) -**Goal**: Ensure everything works correctly and validate all fixes - -### 5.1 End-to-End Testing (1 hour) -- [ ] Test complete deployment pipeline -- [ ] Validate application functionality (all endpoints) -- [ ] Test database connectivity and data persistence -- [ ] Verify security configurations work properly -- [ ] Test error handling and validation -- [ ] Test auto-scaling (if implemented) -- [ ] Validate all "gotcha" fixes are working - -### 5.2 Documentation & Cleanup (1 hour) -- [ ] Update README with complete instructions -- [ ] Document all infrastructure decisions and why they were made -- [ ] Create troubleshooting guide -- [ ] Document all issues found and how they were resolved -- [ ] Document the "gotchas" and their fixes for the recruiter -- [ ] Clean up temporary resources -- [ ] Create final presentation of the solution - -**Learning Focus**: Testing methodologies, documentation best practices, and production readiness. - ---- - -## DevOps Principles Applied - -### 12-Factor App Compliance -- [ ] Codebase: Single codebase tracked in version control -- [ ] Dependencies: Explicitly declared and isolated -- [ ] Config: Stored in environment variables (FIXED) -- [ ] Backing Services: Treated as attached resources (PostgreSQL) -- [ ] Build, Release, Run: Strictly separated build and run stages -- [ ] Processes: Stateless and share-nothing -- [ ] Port Binding: Self-contained and export services via port binding -- [ ] Concurrency: Scale out via the process model -- [ ] Disposability: Fast startup and graceful shutdown -- [ ] Dev/Prod Parity: Keep development, staging, and production as similar as possible -- [ ] Logs: Treat logs as event streams -- [ ] Admin Processes: Run admin/management tasks as one-off processes - -### SOLID Principles in Infrastructure -- **Single Responsibility**: Each Terraform module has one clear purpose -- **Open/Closed**: Infrastructure can be extended without modification -- **Liskov Substitution**: Modules can be replaced with compatible alternatives -- **Interface Segregation**: Use specific IAM policies and security groups -- **Dependency Inversion**: Depend on abstractions (variables) not concrete implementations - -## Success Criteria -- [ ] Application runs locally with virtual environment -- [ ] Application runs in Docker container securely -- [ ] Infrastructure provisions successfully with Terraform -- [ ] CI/CD pipeline builds and deploys automatically -- [ ] Application is accessible and functional in AWS -- [ ] **ALL intentional issues are identified and resolved** -- [ ] Documentation is complete and clear -- [ ] Code follows best practices and is maintainable -- [ ] **Security issues are addressed** -- [ ] **Error handling is robust** - -## Time Allocation Summary -- **Phase 1**: 2-3 hours (Foundation + Critical Fixes) -- **Phase 2**: 2-3 hours (Planning) -- **Phase 3**: 3-4 hours (Implementation) -- **Phase 4**: 2-3 hours (Automation) -- **Phase 5**: 1-2 hours (Testing & Documentation) - -**Total Estimated Time**: 10-15 hours - -## Key Changes from Original Schedule - -### **Phase 1 Enhancements:** -- **Critical fixes first**: Address the most important issues before building infrastructure -- **Security focus**: Fix Docker and application security issues early -- **Error handling**: Add robust error handling before deployment - -### **Phase 2 Enhancements:** -- **Issue-aware planning**: Design infrastructure that specifically addresses the "gotchas" -- **Security by design**: Plan security measures from the beginning - -### **Phase 3-5 Enhancements:** -- **Validation focus**: Ensure each phase validates the fixes from previous phases -- **Documentation**: Track all issues and their resolutions - -## Notes -- Each phase now specifically addresses the identified "gotchas" -- The schedule prioritizes fixing critical issues before building infrastructure -- Security and error handling are addressed early and throughout -- Documentation includes tracking of all issues found and resolved -- Focus on quality and best practices rather than rushing to completion \ No newline at end of file diff --git a/app/beer_catalog/app.py b/app/beer_catalog/app.py index cb8ad02..72eea35 100644 --- a/app/beer_catalog/app.py +++ b/app/beer_catalog/app.py @@ -6,8 +6,9 @@ from flask import Flask, jsonify, request from beer_catalog.db import engine, session_local from beer_catalog.beer import Base, Beer +from seed import seed_database -# Load environment variables (12-factor app principle #3) +# Load environment variables load_dotenv() # Configure logging @@ -99,6 +100,15 @@ def create_beer(): return jsonify({"error": "Failed to create beer"}), 500 +@app.route("/seed", methods=["POST"]) +def seed(): + try: + seed_database() + return jsonify({"message": "Database seeded with test beers"}), 200 + except Exception as e: + return jsonify({"error": str(e)}), 500 + + @app.errorhandler(404) def not_found(error): return jsonify({"error": "Endpoint not found"}), 404 diff --git a/app/beer_catalog/seed.py b/app/beer_catalog/seed.py new file mode 100644 index 0000000..5a8300a --- /dev/null +++ b/app/beer_catalog/seed.py @@ -0,0 +1,19 @@ +from beer_catalog.db import session_local +from beer_catalog.beer import Beer + + +def seed_database(): + session = session_local() + beers = [ + Beer(name="Heineken", style="Lager", abv=5.0), + Beer(name="Guinness", style="Stout", abv=4.2), + Beer(name="Sierra Nevada", style="Pale Ale", abv=5.6), + ] + session.add_all(beers) + session.commit() + session.close() + + +if __name__ == "__main__": + seed_database() + print("Database seeded with test beers.") diff --git a/imgs/infra.png b/imgs/infra.png new file mode 100644 index 0000000..3ed14fd Binary files /dev/null and b/imgs/infra.png differ diff --git a/mindset.md b/mindset.md deleted file mode 100644 index 0a3075d..0000000 --- a/mindset.md +++ /dev/null @@ -1,24 +0,0 @@ -## Mindset -Hi, this is a coding assignment to a DevOps role. -I want your help to complete it. I prfer not get it all done, at once, since one important aspect is to be able to explain it. - -So the approach is very simple. -I have to be able to follow the instructions provided oin @instructions.md ( I added it from the email the recruiter sent), and this should be clear enough. - -Please, help me to figure out the best order of solving tasks, considering DEvOps reasoning, (for example, if it makes sense to add docker earlier to improve the different environments, let's do this first (for example), I am not very experienced in DevOps, but will try to use this task to leverage my skills at the same time I need you to share and explain what is happening while we work, clear? - -We want to use the best practices of DevOps, and the best tools for the job. - -We want to use 12-factor app principles, and the best practices of DevOps. - -We want to use SOLID priciples to write the code. - -We want to document the code, as the recruiter will asses my organization skills. - -We want to respect the Instructions file, and meet all points necesszry to get it done, and be able to explain. - - -## Let's fix the app, then deploy it porperly. -There are some issues in the app, and we need to fix them. - -