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
7 changes: 4 additions & 3 deletions aws-lambda-template.test-data.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
copier__project_name: test_project
copier__runtime: "python3.11"
copier__architectures: ["x86_64"]
copier__package_type: "zip"
copier__architectures: "x86_64"
copier__package_type: "image"
copier__xray_tracing: y
copier__cloudwatch_monitor: y
copier__enable_logs: y
copier__auth: y
copier__dynamo_db: y
copier__dynamo_db: y
copier__repo_url: git@github.com:organization_name/test_project.git
22 changes: 15 additions & 7 deletions copier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,15 @@ copier__runtime:
default: "python3.11"
help: "The python version of your project."
choices:
python3.8: "python3.8"
python3.9: "python3.9"
python3.10: "python3.10"
python3.11: "python3.11"
python3.12: "python3.12"
"3.9": "python3.9"
"3.10": "python3.10"
"3.11": "python3.11"
"3.12": "python3.12"

copier__architectures:
type: str
help: "The architecture of your project."
default: ["arm64"]
multiselect: true
default: "arm64"
choices:
x86_64: "x86_64"
arm64: "arm64"
Expand Down Expand Up @@ -82,3 +80,13 @@ copier__stack_name:
type: str
default: "{{ copier__project_name.lower().replace(' ', '-') }}"
when: false

copier__repo_url:
type: str
default: "git@github.com:organization_name/{{ copier__stack_name }}.git"
help: "The URL of the repository."
validator: >-
{% if not copier__repo_url.startswith("git@") or not ":" in copier__repo_url or not "/" in copier__repo_url.split(":")[1] or not ".git" in copier__repo_url %}
Value must follow the format git@provider:orgname/repo.git
{% endif %}

43 changes: 38 additions & 5 deletions tasks.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,56 @@
import os
import random
import shlex
import shutil
import string
import subprocess


TERMINATOR = "\x1b[0m"
WARNING = "\x1b[1;33m [WARNING]: "
INFO = "\x1b[1;33m [INFO]: "
HINT = "\x1b[3;33m"
SUCCESS = "\x1b[1;32m [SUCCESS]: "


def run_setup():
print("Performing initial commit.")
subprocess.run(shlex.split("git add ."))
subprocess.run(shlex.split("git commit -m 'Initial commit' --quiet"))

if not shutil.which("sam"):
print("Error: AWS SAM CLI is not installed. Please install it and try again.")
exit(1)

print("Running AWS SAM build and validate...")
subprocess.run(shlex.split("sam validate --lint"))
subprocess.run(shlex.split("sam build"))
subprocess.run(shlex.split("make validate"))
subprocess.run(shlex.split("make build"))
print("AWS Lambda template setup complete.")


def init_git_repo():
print(INFO + "Initializing git repository..." + TERMINATOR)
print(INFO + f"Current working directory: {os.getcwd()}" + TERMINATOR)
subprocess.run(shlex.split("git -c init.defaultBranch=main init . --quiet"))
print(SUCCESS + "Git repository initialized." + TERMINATOR)


def configure_git_remote():
repo_url = "{{ copier__repo_url }}"
if repo_url:
print(INFO + f"repo_url: {repo_url}" + TERMINATOR)
command = f"git remote add origin {repo_url}"
subprocess.run(shlex.split(command))
print(SUCCESS + f"Remote origin={repo_url} added." + TERMINATOR)
else:
print(
WARNING
+ "No repo_url provided. Skipping git remote configuration."
+ TERMINATOR
)


def main():
init_git_repo()
configure_git_remote()
run_setup()


Expand Down
3 changes: 3 additions & 0 deletions {{copier__project_name}}/.envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export AWS_ACCESS_KEY_ID=dummyAccessKeyId
export AWS_SECRET_ACCESS_KEY=dummySecretAccessKey
export AWS_REGION=us-east-1
12 changes: 11 additions & 1 deletion {{copier__project_name}}/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Project specific ignores

env.json
.dynamodb-container-id

# Created by https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode

Expand Down Expand Up @@ -241,4 +245,10 @@ $RECYCLE.BIN/

*/build/*

# End of https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode
# End of https://www.gitignore.io/api/osx,linux,python,windows,pycharm,visualstudiocode

# gitignore template for AWS Serverless Application Model project
# website: https://docs.aws.amazon.com/serverless-application-model

# Ignore build folder
.aws-sam/
75 changes: 60 additions & 15 deletions {{copier__project_name}}/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ STACK_NAME ?= {{ copier__project_name }}
REGION ?= us-east-1
TEMPLATE_FILE ?= template.yaml
BUILD_DIR ?= .aws-sam/build
{% if copier__dynamo_db %}DYNAMO_ENDPOINT ?= http://localhost:8000{% endif %}
{% if copier__dynamo_db %}DYNAMO_ENDPOINT ?= http://localhost:8000
TABLE_NAME = RequestsTable{% endif %}

# Default target
all: build

build:
sam build {% if copier__package_type != "image" %}--use-container{% endif %}

validate:
sam validate --lint

deploy:
sam deploy --guided

Expand All @@ -29,24 +33,65 @@ invoke:

{% if copier__dynamo_db %}
dynamo-up:
docker-compose up -d dynamodb-local
@if [ -f .dynamodb-container-id ] && [ -n "$$(docker ps -q -f id=$$(cat .dynamodb-container-id 2>/dev/null))" ]; then \
echo "DynamoDB local container is already running with ID: $$(cat .dynamodb-container-id)"; \
else \
echo "Starting DynamoDB local container..."; \
rm -f .dynamodb-container-id 2>/dev/null || true; \
docker run -d --rm --network lambda-local -p 8000:8000 --name dynamodb-local amazon/dynamodb-local:latest -jar DynamoDBLocal.jar -sharedDb > .dynamodb-container-id; \
echo "DynamoDB local container started with ID: $$(cat .dynamodb-container-id)"; \
fi

dynamo-down:
dokcer-compose down
@if [ -f .dynamodb-container-id ]; then \
if [ -n "$$(docker ps -q -f id=$$(cat .dynamodb-container-id 2>/dev/null))" ]; then \
echo "Stopping DynamoDB local container with ID: $$(cat .dynamodb-container-id)"; \
docker stop $$(cat .dynamodb-container-id); \
else \
echo "No running container found with saved ID"; \
fi; \
rm -f .dynamodb-container-id; \
else \
echo "No container ID file found"; \
fi

wait-for-dynamodb:
@echo "Waiting for DynamoDB Local to be ready..."
@attempts=0; \
until curl -s http://localhost:8000 >/dev/null; do \
if [ $$attempts -ge 10 ]; then \
echo "DynamoDB Local did not become ready in time"; \
exit 1; \
fi; \
echo "Waiting..."; \
sleep 1; \
attempts=$$((attempts + 1)); \
done; \
echo "DynamoDB Local is ready."

create-table:
aws dynamodb create-table \
--table-name RequestsTable \
--attribute-definitions \
AttributeName=ip_address,AttributeType=S \
AttributeName=timestamp,AttributeType=S \
--key-schema \
AttributeName=ip_address,KeyType=HASH \
AttributeName=timestamp,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST \
--endpoint-url $(DYNAMO_ENDPOINT)

setup: dynamo-up create-table{% else %}
@# Store the AWS command output in a variable
$(eval AWS_OUTPUT := $(shell aws dynamodb create-table \
--table-name $(TABLE_NAME) \
--attribute-definitions \
AttributeName=ip_address,AttributeType=S \
AttributeName=timestamp,AttributeType=S \
--key-schema \
AttributeName=ip_address,KeyType=HASH \
AttributeName=timestamp,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST \
--endpoint-url $(DYNAMO_ENDPOINT) \
--no-cli-pager))

@# Check if jq exists and use it if available
@if command -v jq > /dev/null 2>&1; then \
echo '$(AWS_OUTPUT)' | jq; \
else \
echo '$(AWS_OUTPUT)'; \
echo "\033[33mNote: Install jq for colorized JSON output\033[0m"; \
fi

setup: dynamo-up wait-for-dynamodb create-table{% else %}
setup:
pip install -r requirements.txt{% endif %}

Expand Down
36 changes: 36 additions & 0 deletions {{copier__project_name}}/samconfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# More information about the configuration file can be found here:
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
version = 0.1

[default]
[default.global.parameters]
stack_name = "{{copier__stack_name}}"

[default.build.parameters]
cached = true
parallel = true

[default.validate.parameters]
lint = true

[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true
s3_prefix = "{{copier__stack_name}}"
region = "us-east-1"
profile = "{{copier__stack_name}}"
image_repositories = []
parameter_overrides = "DynamoDbEndpoint=\"https://dynamodb.us-east-1.amazonaws.com\""

[default.package.parameters]
resolve_s3 = true

[default.sync.parameters]
watch = true

[default.local_start_api.parameters]
warm_containers = "EAGER"

[default.local_start_lambda.parameters]
warm_containers = "EAGER"
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% if copier__runtime == "python3.8" %}
FROM public.ecr.aws/lambda/python:3.8-{{copier__architectures}}
{% elif copier__runtime == "python3.9" %}
FROM public.ecr.aws/lambda/python:3.9-{{copier__architectures}}
{% elif copier__runtime == "python3.10" %}
FROM public.ecr.aws/lambda/python:3.10-{{copier__architectures}}
{% elif copier__runtime == "python3.11" %}
FROM public.ecr.aws/lambda/python:3.11-{{copier__architectures}}
{% elif copier__runtime == "python3.12" %}
FROM public.ecr.aws/lambda/python:3.12-{{copier__architectures}}
{% else %}
FROM public.ecr.aws/lambda/python:3.10-{{copier__architectures}}
{% endif %}
COPY app.py ${LAMBDA_TASK_ROOT}

# Command can be overwritten by providing a different command in the template directly.
CMD ["app.lambda_handler"]
14 changes: 5 additions & 9 deletions {{copier__project_name}}/template.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
{{ copier__project_name }}

Sample SAM Template for {{ copier__project_name }}

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Expand Down Expand Up @@ -57,14 +55,12 @@ Resources:
{% if copier__package_type == "image" %}
PackageType: Image
{% else %}
CodeUri: ./
CodeUri: ./src
Handler: app.lambda_handler
Runtime: {{ copier__runtime }}
{% endif %}
Architectures:
{%- for arch in copier__architectures %}
- {{arch}}
{%- endfor %}
- {{copier__architectures}}
{% if copier__dynamo_db %}
Environment:
Variables:
Expand All @@ -86,8 +82,8 @@ Resources:
{% if copier__package_type == "image" %}
Metadata:
Dockerfile: Dockerfile
DockerContext: ./
DockerTag: python3.13-v1
DockerContext: ./src
DockerTag: {{copier__runtime}}-v1
{% endif %}
{% if copier__cloudwatch_monitor %}
ApplicationResourceGroup:
Expand All @@ -108,7 +104,7 @@ Resources:
PassageAuthFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: ./
CodeUri: ./src
Handler: authorizer.handler
Runtime: {{ copier__runtime }}
Timeout: 10
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"HelloWorldFunction": {
"DYNAMODB_ENDPOINT": "http://dynamo-local:8000",
"DYNAMODB_ENDPOINT": "http://dynamodb-local:8000",
"DYNAMODB_TABLE_NAME": "RequestsTable"
},
"PassageAuthFunction": {
"PASSAGE_APP_ID": "CHANGEME",
"PASSAGE_API_KEY": "CHANGEME",
"DYNAMODB_ENDPOINT": "http://dynamo-local:8000",
"DYNAMODB_ENDPOINT": "http://dynamodb-local:8000",
"DYNAMODB_TABLE_NAME": "RequestsTable"
}
}

This file was deleted.