add docker compose
This commit is contained in:
4
http-api/.gitignore
vendored
4
http-api/.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
.env
|
.env
|
||||||
samlocal.json
|
env.json
|
||||||
|
dynamodb_volume/
|
||||||
|
elastic_volume/
|
||||||
|
|||||||
@@ -16,3 +16,9 @@ pytest:
|
|||||||
|
|
||||||
htmlcov: pytest
|
htmlcov: pytest
|
||||||
uv run python -m http.server 80 -d htmlcov
|
uv run python -m http.server 80 -d htmlcov
|
||||||
|
|
||||||
|
up:
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
down:
|
||||||
|
docker compose down
|
||||||
|
|||||||
34
http-api/compose.yaml
Normal file
34
http-api/compose.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
services:
|
||||||
|
dynamodb:
|
||||||
|
image: amazon/dynamodb-local:latest
|
||||||
|
container_name: dynamodb
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
volumes:
|
||||||
|
- ./dynamodb_volume:/home/dynamodblocal/data
|
||||||
|
working_dir: /home/dynamodblocal
|
||||||
|
command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data"
|
||||||
|
|
||||||
|
elastic:
|
||||||
|
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.3
|
||||||
|
container_name: elastic
|
||||||
|
environment:
|
||||||
|
- discovery.type=single-node
|
||||||
|
- bootstrap.memory_lock=true
|
||||||
|
- xpack.security.enabled=false
|
||||||
|
- xpack.security.http.ssl.enabled=false
|
||||||
|
- xpack.security.transport.ssl.enabled=false
|
||||||
|
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||||
|
- http.cors.allow-origin="*"
|
||||||
|
- http.cors.enabled=true
|
||||||
|
- http.cors.allow-credentials=true
|
||||||
|
- http.cors.allow-methods=OPTIONS, HEAD, GET, POST, PUT, DELETE
|
||||||
|
- http.cors.allow-headers=X-Requested-With, X-Auth-Token, Content-Type, Content-Length, Authorization, Access-Control-Allow-Headers, Accept, x-elastic-client-meta
|
||||||
|
ulimits:
|
||||||
|
memlock:
|
||||||
|
soft: -1
|
||||||
|
hard: -1
|
||||||
|
volumes:
|
||||||
|
- ./elastic_volume:/usr/share/elasticsearch/data
|
||||||
|
ports:
|
||||||
|
- 9200:9200
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
"USER_TABLE": "test-users",
|
"USER_TABLE": "test-users",
|
||||||
"ORDER_TABLE": "test-orders",
|
"ORDER_TABLE": "test-orders",
|
||||||
"ENROLLMENT_TABLE": "test-enrollments"
|
"ENROLLMENT_TABLE": "test-enrollments"
|
||||||
|
"COURSE_TABLE": "test-courses"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
|
||||||
import boto3
|
|
||||||
from aws_lambda_powertools.event_handler import Response, content_types
|
from aws_lambda_powertools.event_handler import Response, content_types
|
||||||
from aws_lambda_powertools.event_handler.api_gateway import Router
|
from aws_lambda_powertools.event_handler.api_gateway import Router
|
||||||
from elasticsearch import Elasticsearch
|
from elasticsearch import Elasticsearch
|
||||||
@@ -9,19 +8,23 @@ from layercake.dynamodb import DynamoDBPersistenceLayer
|
|||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
import elastic
|
import elastic
|
||||||
|
from boto3clients import dynamodb_client
|
||||||
from course import create_course
|
from course import create_course
|
||||||
from models import Course, Org
|
from models import Course, Org
|
||||||
from settings import COURSE_TABLE, ELASTIC_CONN
|
from settings import COURSE_TABLE, ELASTIC_CONN
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
dynamodb_client = boto3.client('dynamodb')
|
|
||||||
elastic_client = Elasticsearch(**ELASTIC_CONN)
|
elastic_client = Elasticsearch(**ELASTIC_CONN)
|
||||||
course_layer = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
|
course_layer = DynamoDBPersistenceLayer(COURSE_TABLE, dynamodb_client)
|
||||||
|
|
||||||
|
|
||||||
@router.get('/', compress=True, tags=['Course'])
|
@router.get(
|
||||||
|
'/',
|
||||||
|
compress=True,
|
||||||
|
tags=['Course'],
|
||||||
|
summary='Get courses',
|
||||||
|
)
|
||||||
def get_courses():
|
def get_courses():
|
||||||
"""Get a list of courses based on the query parameters."""
|
|
||||||
event = router.current_event
|
event = router.current_event
|
||||||
query = event.get_query_string_value('query', '{}')
|
query = event.get_query_string_value('query', '{}')
|
||||||
page_size = event.get_query_string_value('page_size', '25')
|
page_size = event.get_query_string_value('page_size', '25')
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ image_repositories = []
|
|||||||
|
|
||||||
[default.local_start_api.parameters]
|
[default.local_start_api.parameters]
|
||||||
debug = true
|
debug = true
|
||||||
env_vars = "samlocal.json"
|
env_vars = "env.json"
|
||||||
warm_containers = "EAGER"
|
warm_containers = "EAGER"
|
||||||
|
|||||||
2
http-api/uv.lock
generated
2
http-api/uv.lock
generated
@@ -444,7 +444,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "layercake"
|
name = "layercake"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
source = { directory = "../layercake" }
|
source = { directory = "../layercake" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "aws-lambda-powertools", extra = ["all"] },
|
{ name = "aws-lambda-powertools", extra = ["all"] },
|
||||||
|
|||||||
@@ -106,14 +106,22 @@ if TYPE_CHECKING:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class PrefixKey(str):
|
class PrefixKey(str):
|
||||||
prefix: str
|
prefix: str
|
||||||
|
delimiter: str | None = '#'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
class PrefixKey(str):
|
class PrefixKey(str):
|
||||||
def __init__(self, prefix: str | None = None) -> None:
|
def __new__(cls, prefix: str, delimiter: str | None = '#') -> str:
|
||||||
|
if not delimiter:
|
||||||
|
return super().__new__(cls, prefix)
|
||||||
|
|
||||||
|
return super().__new__(cls, prefix + delimiter)
|
||||||
|
|
||||||
|
def __init__(self, prefix: str, delimiter: str = '#') -> None:
|
||||||
# __init__ is used to store the parameters for later reference.
|
# __init__ is used to store the parameters for later reference.
|
||||||
# For immutable types like str, __init__ cannot change the instance's value.
|
# For immutable types like str, __init__ cannot change the instance's value.
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
|
self.delimiter = delimiter
|
||||||
|
|
||||||
|
|
||||||
class Key(ABC, dict):
|
class Key(ABC, dict):
|
||||||
@@ -672,10 +680,9 @@ class DynamoDBCollection:
|
|||||||
|
|
||||||
match key.get(PK), key.get(SK):
|
match key.get(PK), key.get(SK):
|
||||||
case ComposeKey(), _: # Remove prefix from Partition Key
|
case ComposeKey(), _: # Remove prefix from Partition Key
|
||||||
prefix = key[PK].prefix + key[PK].delimiter
|
items = _remove_prefix(items, PK, key[PK].prefix + key[PK].delimiter)
|
||||||
items = _remove_prefix(items, PK, prefix)
|
|
||||||
case _, PrefixKey(): # Remove prefix from Sort Key
|
case _, PrefixKey(): # Remove prefix from Sort Key
|
||||||
items = _remove_prefix(items, SK, key[SK].prefix)
|
items = _remove_prefix(items, SK, key[SK])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'items': items,
|
'items': items,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "layercake"
|
name = "layercake"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
description = "Add your description here"
|
description = "Add your description here"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [
|
authors = [
|
||||||
|
|||||||
@@ -58,9 +58,12 @@ def test_keypair():
|
|||||||
|
|
||||||
def test_prefixkey():
|
def test_prefixkey():
|
||||||
key = PrefixKey('emails')
|
key = PrefixKey('emails')
|
||||||
assert key == 'emails'
|
assert key == 'emails#'
|
||||||
assert isinstance(key, PrefixKey)
|
assert isinstance(key, PrefixKey)
|
||||||
|
|
||||||
|
delimiter = PrefixKey('emails', None)
|
||||||
|
assert delimiter == 'emails'
|
||||||
|
|
||||||
|
|
||||||
def test_transact_write_items(
|
def test_transact_write_items(
|
||||||
dynamodb_seeds,
|
dynamodb_seeds,
|
||||||
@@ -195,7 +198,7 @@ def test_collection_get_items(
|
|||||||
|
|
||||||
# This data was added from seeds
|
# This data was added from seeds
|
||||||
emails = collect.get_items(
|
emails = collect.get_items(
|
||||||
KeyPair('5OxmMjL-ujoR5IMGegQz', PrefixKey('emails#')),
|
KeyPair('5OxmMjL-ujoR5IMGegQz', PrefixKey('emails')),
|
||||||
)
|
)
|
||||||
assert emails == {
|
assert emails == {
|
||||||
'items': [
|
'items': [
|
||||||
|
|||||||
2
layercake/uv.lock
generated
2
layercake/uv.lock
generated
@@ -417,7 +417,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "layercake"
|
name = "layercake"
|
||||||
version = "0.1.1"
|
version = "0.1.4"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "aws-lambda-powertools", extra = ["all"] },
|
{ name = "aws-lambda-powertools", extra = ["all"] },
|
||||||
|
|||||||
Reference in New Issue
Block a user