Skip to content
Open
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
42 changes: 27 additions & 15 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,44 @@ jobs:
- name: Checkout
uses: actions/checkout@v2

- name: Start up LocalStack
- name: Install tools
run: |
pip install --pre localstack awscli-local[ver1] terraform-local pytest requests

# Terraform
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \
| sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt-get update -qq && sudo apt-get install -y terraform

- name: Start LocalStack
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
run: |
docker pull localstack/localstack-pro &

# install CLI tools
pip install --pre localstack localstack-ext awscli-local[ver1]

# start LocalStack
DEBUG=1 localstack start -d
DEBUG=1 LOCALSTACK_APPINSPECTOR_ENABLE=1 localstack start -d
localstack wait

- name: Run simple test
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
- name: Deploy infrastructure via Terraform
run: |
set -e
cd 01-serverless-app/terraform
tflocal init
tflocal apply -auto-approve

# deploy test resources
(cd 00-hello-world; ./deploy.sh)
- name: Build and push fulfillment image
run: |
ECR_REGISTRY="000000000000.dkr.ecr.us-east-1.localhost.localstack.cloud:4566"
awslocal ecr get-login-password | \
docker login --username AWS --password-stdin "$ECR_REGISTRY"
docker build -t "$ECR_REGISTRY/fulfillment:latest" 01-serverless-app/services/fulfillment
docker push "$ECR_REGISTRY/fulfillment:latest"

# run assertion
curl http://testwebsite.s3-website.localhost.localstack.cloud:4566 | grep 'You are running LocalStack'
- name: Run E2E tests
run: |
cd 02-e2e-testing && pytest tests/ -v

- name: Print LocalStack logs
if: always()
run: |
localstack logs
localstack stop
15 changes: 0 additions & 15 deletions 00-hello-world/README.md

This file was deleted.

12 changes: 0 additions & 12 deletions 00-hello-world/bucket-policy.json

This file was deleted.

13 changes: 0 additions & 13 deletions 00-hello-world/deploy.sh

This file was deleted.

27 changes: 0 additions & 27 deletions 00-hello-world/index.html

This file was deleted.

29 changes: 0 additions & 29 deletions 00-hello-world/list_s3_objects.py

This file was deleted.

21 changes: 1 addition & 20 deletions 01-serverless-app/lambdas/order_processor/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@
import boto3

dynamodb = boto3.resource("dynamodb")
s3 = boto3.client("s3")
sfn = boto3.client("stepfunctions")

TABLE_NAME = os.environ["ORDERS_TABLE"]
RECEIPTS_BUCKET = os.environ["RECEIPTS_BUCKET"]
TABLE_NAME = os.environ["ORDERS_TABLE"]
STATE_MACHINE_ARN = os.environ["STATE_MACHINE_ARN"]

TERMINAL_STATUSES = {"fulfilled", "failed"}


def now():
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
Expand Down Expand Up @@ -64,7 +60,6 @@ def handler(event, context):

if step == "validate": return validate(order)
if step == "process_payment": return process_payment(order)
if step == "fulfill": return fulfill(order)
if step == "handle_failure": return handle_failure(order)

raise ValueError(f"Unknown step: {step}")
Expand All @@ -82,20 +77,6 @@ def process_payment(order):
return order


def fulfill(order):
time.sleep(2)
set_status(order["order_id"], "fulfilled")
receipt = {k: order[k] for k in ("order_id", "item", "quantity")}
receipt["status"] = "fulfilled"
s3.put_object(
Bucket=RECEIPTS_BUCKET,
Key=f"receipts/{order['order_id']}.json",
Body=json.dumps(receipt),
ContentType="application/json",
)
return order


def handle_failure(order):
set_status(order["order_id"], "failed")
return order
5 changes: 5 additions & 0 deletions 01-serverless-app/services/fulfillment/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM python:3.12-slim
WORKDIR /app
RUN pip install --no-cache-dir boto3
COPY fulfill.py .
CMD ["python", "fulfill.py"]
49 changes: 49 additions & 0 deletions 01-serverless-app/services/fulfillment/fulfill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""ECS task: fulfill an order — update DynamoDB status and write S3 receipt."""
import json
import os
from datetime import datetime, timezone

import boto3

ORDER_ID = os.environ["ORDER_ID"]
TABLE_NAME = os.environ["ORDERS_TABLE"]
RECEIPTS_BUCKET = os.environ["RECEIPTS_BUCKET"]

endpoint = os.environ.get("AWS_ENDPOINT_URL", "")
print(f"Connecting to endpoint: {endpoint or '(default AWS)'}", flush=True)

dynamodb = boto3.resource("dynamodb")
s3 = boto3.client("s3")


def now():
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")


table = dynamodb.Table(TABLE_NAME)

resp = table.get_item(Key={"order_id": ORDER_ID})
order = resp["Item"]

table.update_item(
Key={"order_id": ORDER_ID},
UpdateExpression="SET #s = :s, fulfilled_at = :ts",
ExpressionAttributeNames={"#s": "status"},
ExpressionAttributeValues={":s": "fulfilled", ":ts": now()},
)

receipt = {
"order_id": ORDER_ID,
"item": order["item"],
"quantity": int(order["quantity"]),
"status": "fulfilled",
"fulfilled_at": now(),
}
s3.put_object(
Bucket=RECEIPTS_BUCKET,
Key=f"receipts/{ORDER_ID}.json",
Body=json.dumps(receipt),
ContentType="application/json",
)

print(f"Order {ORDER_ID} fulfilled: {order['item']} x{order['quantity']}")
Loading
Loading