diff --git a/README.md b/README.md index 658bc54..2445581 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,15 @@ The goal of this project is to build, configure, and automate the deployment of a simple serverless application on AWS. Created a health check endpoint that logs requests and stores them in a database, with a CI/CD pipeline to manage deployments for both staging and production environments, fully provisioned via Terraform and deployed automatically using GitHub Actions. +## Prerequisites +- An AWS account and IAM user with rights to create IAM, Lambda, API Gateway, DynamoDB, CloudWatch. +- Local toolchain: + - Terraform v1.2+ +- GitHub repo secrets (Repository > Settings > Secrets): + - `AWS_ACCESS_KEY_ID` + - `AWS_SECRET_ACCESS_KEY` + - `AWS_REGION` (e.g. `us-east-1`) + ## Architectural desig ### Core Components @@ -14,6 +23,8 @@ The goal of this project is to build, configure, and automate the deployment of Each environment (staging, prod) is isolated by naming convention and Terraform variables. +[Live Demo Link](https://www.loom.com/share/3b1a44b435724293b7be8953ed51ae27) + ### Runtime Request Flow 1. _Client_: sends a GET or POST request to: @@ -60,6 +71,7 @@ https://.execute-api..amazonaws.com/health | Terraform vars | `staging.tfvars` | `prod.tfvars` | | Lambda | `staging-health-check-function` | `prod-health-check-function` | | DynamoDB | `staging-requests-db` | `prod-requests-db` | +| S3 Bucket | `serverless-health-check-api/staging/tfstate` | `serverless-health-check-api/prod/tfstate`| | API Gateway | `staging-health-check-api` | `prod-health-check-api` | | Approval | None | Required | @@ -80,50 +92,76 @@ Each Lambda function has one dedicated IAM role with: - No credentials committed to repository - - - - - - -create hello lambda funtion using Python - +![](/svrhecheck.drawio.png) + +## Setup + +_Repository Structure_ + +```text +. +├── .github +│ └── workflows +│ ├── deploy.yml +│ └── destroy.yml +├── lambda +│ └── lambda_function.py +├── terraform +│ ├── provider.tf +│ ├── variables.tf +│ ├── main.tf +│ ├── iam.tf +│ ├── lambda.tf +│ ├── apigw.tf +│ ├── outputs.tf +│ ├── staging.tfvars +│ ├── prod.tfvars +│ ├── backend-prod.tfvars +│ └── backend-staging.tfvars +└── README.md + +- Create the lambda function, run the python funtion locally using VS Code Run Button, import boto3, logging,json, os, uuid. +- Resource names follows _env-resource-name_ + +## How to trigger deployments + +_Manual for test_ +- terraform init -backend-config=backend-staging.tfvars for staging environment +- terraform init -backend-config=backend-prod.tfvars for prod environment +- terraform plan -backend-config=backend-staging.tfvars for staging environment +- terraform plan -backend-config=backend-prod.tfvars for prod environment +- terraform apply -var-file="staging.tfvars" +- terraform apply -var-file="prod.tfvars" +- terraform destroy -backend-config=backend-staging.tfvars for staging environment +- terraform destroy -backend-config=backend-prod.tfvars for prod environment + +_GitHub Action CICD_ +### Staging +1. Push to branch `staging` (or open a PR merging into `staging` and merge). +2. GitHub Action will automatically: + - `terraform init` + - `terraform plan -var-file="staging.tfvars"` + - `terraform apply` (auto-approved) + +### Production +1. Push to branch `main` (or merge PR into `main`). +2. Workflow will run and wait for **manual approval** in the `production` environment (configure environment reviewers in Settings). +3. Approve in GitHub UI → workflow will `apply` the `prod.tfvars` plan. + +### Trigger Destroy CICD pipeline +Manually trigger the terraform destroy workflow in GitHub UI -> actions -> destroy.yaml + +## Testing the /health endpoint + +After deployment, Terraform outputs the API endpoint. You can fetch it: +- From the Actions run logs (last step runs `terraform output -json`) + +Example curl (replace `` with the `api_endpoint` output): ``` -# Hello lambda function -def lambda_handler(event, context): - name = event.get("name", "World") - message = f"Hello, {name}!" - - return { - "statusCode": 200, - "body": message - } - -# Run the funtion locally for testing -if __name__ == "__main__": - test_event = {"name": "Emmanuel Ogah"} - result = lambda_handler(test_event, None) - print(result) -``` - -Run the python funtion locally using VS Code Run Button -- Click the “Run Python File” button in the top right corner. +# GET +curl "https://nrbefv9bcj.execute-api.us-east-1.amazonaws.com/health" -``` # Output +{"status": "healthy", "message": "Request processed and saved.", "id": "0fb4fa88-64a1-440d-84b1-5a6d4354364b"} -{'statusCode': 200, 'body': 'Hello, Emmanuel Ogah!'}" -``` - -- Create the terraform folder structure - -- Deploy with: terraform init then terraform apply -var-file="staging.tfvars" (or prod.tfvars) - - -endpoint - https://nrbefv9bcj.execute-api.us-east-1.amazonaws.com/health - - - -terraform init -backend-config=backend-staging.tfvars for staging environment - -terraform init -backend-config=backend-prod.tfvars for prod environment +``` \ No newline at end of file diff --git a/svrhecheck.drawio.png b/svrhecheck.drawio.png new file mode 100644 index 0000000..c14af39 Binary files /dev/null and b/svrhecheck.drawio.png differ diff --git a/terraform/lambda_package/staging-lambda.zip b/terraform/lambda_package/staging-lambda.zip deleted file mode 100644 index fade241..0000000 Binary files a/terraform/lambda_package/staging-lambda.zip and /dev/null differ