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
10 changes: 1 addition & 9 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "LocalStack DooD setup",
"name": "Floci DooD setup",
"dockerComposeFile": [
"../docker/networks.yml",
"../docker/infrastructure.yml",
Expand All @@ -13,14 +13,6 @@
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
"upgradePackages": true
},
"ghcr.io/localstack/devcontainer-feature/localstack-cli:latest": {
"version": "latest",
"awslocal": true, // if true, add in features manually: ghcr.io/devcontainers/features/aws-cli
"cdklocal": false, // if true, add in features manually: ghcr.io/devcontainers-contrib/features/aws-cdk
"pulumilocal": false, // if true, add in features manually: ghcr.io/devcontainers-contrib/features/pulumi
"samlocal": false, // if true, add in features manually: ghcr.io/customink/codespaces-features/sam-cli
"tflocal": false // if true, add in features manually: ghcr.io/devcontainers-contrib/features/terraform-asdf
},
"ghcr.io/devcontainers/features/aws-cli:1": {}
},
"customizations": {
Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ services:
env_file:
- .env
dns:
# Set the DNS server to be the LocalStack container
# Set the DNS server to be the Floci container
- 192.168.0.20
networks:
- ls
11 changes: 0 additions & 11 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
{
"version": "0.2.0",
"configurations": [
{
// # The address of the host running the Lambda function to be debugged.
"address": "${env:DEBUG_HOST_ADDRESS}",
"localRoot": "${workspaceFolder}",
"name": "Attach to Remote Node.js",
"port": 9229,
"remoteRoot": "/var/task/",
"request": "attach",
"type": "node",
"preLaunchTask": "Wait Remote Debugger Server"
},
{
"type": "node",
"request": "launch",
Expand Down
8 changes: 1 addition & 7 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Wait Remote Debugger Server",
"type": "shell",
"command": "while [[ -z $(docker ps | grep :9229) ]]; do sleep 1; done; sleep 1;"
}
]
"tasks": []
}
51 changes: 9 additions & 42 deletions docker/.env
Original file line number Diff line number Diff line change
@@ -1,47 +1,14 @@
# Activate LocalStack Pro: https://docs.localstack.cloud/getting-started/auth-token/
LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:-} # required for Pro, not processed via template due to security reasons
LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY:-}
# LocalStack configuration: https://docs.localstack.cloud/references/configuration/
ACTIVATE_PRO=false
DEBUG=false
LS_LOG=info
PERSISTENCE=false
AWS_ENDPOINT_URL=http://localhost.localstack.cloud:4566
LOCALSTACK_HOST=localhost.localstack.cloud:4566
AUTO_LOAD_POD=
ENFORCE_IAM=false
AWS_REGION=eu-west-2
FLOCI_SERVICES_LAMBDA_HOT_RELOAD_ENABLED=true
# FLOCI_STORAGE_MODE=memory
AWS_ENDPOINT_URL=http://localhost:4566
AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test
AWS_DEFAULT_REGION=eu-west-2
# LocalStack community edition is sufficient
IMAGE_NAME=localstack/localstack:latest
AWS_REGION=eu-west-2
AWS_PAGER=
# FLOCI_HOSTNAME=floci
FLOCI_DEFAULT_REGION=eu-west-2
LAMBDA_TIMEOUT=9999999
# Comment the line below and create a new containerised development environment to disable debugging of Lambda functions.
# IMPORTANT - If cloning the remote repository into a container volume, the change must be pushed to a pull request
# branch from which a new containerised development environment is created. If a new containerised development environment
# is not created, running multiple Lambda functions without remote debug limitations will not be possible.
LAMBDA_DOCKER_FLAGS="-e NODE_OPTIONS=--inspect-brk=0.0.0.0:9229 -p 9229:9229"
# Let Docker select a matching image based on the host operating system and architecture.
LAMBDA_IGNORE_ARCHITECTURE=1

# The address of the host running the Lambda function to be debugged.
#
# IMPORTANT
# When using a development container based local development environment, if the address does not match
# the address of the container running the Lambda function to be debugged, the debugger will NOT attach.
# The default value is for use in a development container based local development environment running
# four containers on the host machine BEFORE the container running the Lambda function to be debugged.
# - Dev container
# - LocalStack container
# - Postgres container
# - PgAdmin4 container
#
# When not using a development container the Lambda function to be debugged will run on the host machine
# (IP address 127.0.0.1). When not using a development container and using Visual Studio Code for debugging,
# this environment variable MUST be set to 127.0.0.1 and available to the session used to launch Visual Studio
# Code WITHOUT modifying this file.
# IMPORTANT - A change to this value MUST NOT be pushed to the remote repository as it will prevent
# debugging when cloning the remote repository into a container volume.
DEBUG_HOST_ADDRESS=192.168.0.5
CPX_DB_HOST=capxmldb
NODEJS_VERSION=24
[email protected]
Expand Down
9 changes: 4 additions & 5 deletions docker/infrastructure.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
services:
localstack:
container_name: "localstack-main"
image: localstack/localstack:4.14.0
floci:
container_name: "floci-main"
image: floci/floci:2.0.1
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
- "127.0.0.1:4566:4566" # Floci AWS Gateway
- "127.0.0.1:4510-4559:4510-4559" # external services port range
env_file:
- .env
volumes:
- "${DOCKER_SOCK:-/run/user/1000/docker.sock}:/var/run/docker.sock"
- "./.volume:/var/lib/localstack"
networks:
ls:
# Set the container IP address in the 192.168.0.0/24 subnet
Expand Down
4 changes: 1 addition & 3 deletions docker/networks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ networks:
ipam:
config:
# Specify the subnet range for IP address allocation
# This differs from the default subnet in LocalStack networking documentation
# (see https://blog.localstack.cloud/2024-03-04-making-connecting-to-localstack-easier/)
# to avoid conflicts with Oracle VirtualBox networking.
# This differs from common default emulator subnets to avoid conflicts with Oracle VirtualBox networking.
# If using a different virtualization platform, the subnet range might need to be adjusted.
- subnet: 192.168.0.0/24
4 changes: 3 additions & 1 deletion docker/scripts/load-dummy-data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

set -e

. docker/scripts/set-local-aws-environment.sh

# Constants
BASE_GUID="4eb3b7350ab7aa443650fc9351f02940E"
BASE_AREA="TESTAREA"
DATA_FILE="test/lib/functions/data/nws-alert.xml"
LAMBDA_URL=http://$(awslocal apigateway get-rest-apis | jq -r ".items[0].id").execute-api.localhost.localstack.cloud:4566/local/message
LAMBDA_URL="$AWS_ENDPOINT_URL/restapis/$(aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway get-rest-apis --query "items[?name=='CPX API Gateway'].id | [0]" --output text)/local/_user_request_/message"

Comment thread
teddmason marked this conversation as resolved.
# Calculate tomorrow's date
TOMORROW=$(date -u -d "+1 day" +"%Y-%m-%dT%H:%M:%S+00:00")
Expand Down
58 changes: 39 additions & 19 deletions docker/scripts/register-api-gateway.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
# See https://containers.dev/implementors/json_reference/.
set -e

. docker/scripts/set-local-aws-environment.sh

main() {
# Reference - https://docs.localstack.cloud/user-guide/aws/apigateway/
# Reference - https://docs.aws.amazon.com/cli/latest/reference/apigateway/
echo "Creating API Gateway"
echo $AWS_ENDPOINT_URL

cap_xml_rest_api_id=$(awslocal apigateway create-rest-api --name "FWS API Gateway" | jq -r '.id')
cap_xml_rest_api_root_resource_id=$(awslocal apigateway get-resources --rest-api-id $cap_xml_rest_api_id | jq -r '.items[0].id')
cap_xml_rest_api_id=$(aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway create-rest-api --name "CPX API Gateway" | jq -r '.id')
cap_xml_rest_api_root_resource_id=$(aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway get-resources --rest-api-id "$cap_xml_rest_api_id" | jq -r '.items[] | select(.path == "/") | .id')
lambda_functions_dir="lib/functions"
Comment thread
Copilot marked this conversation as resolved.

find "$lambda_functions_dir" -type f -name "*.js" | while read -r lambda_function; do
Expand Down Expand Up @@ -37,9 +40,13 @@ main() {

done

awslocal apigateway create-deployment \
--rest-api-id $cap_xml_rest_api_id \
--stage-name local
deployment_id=$(aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway create-deployment \
--rest-api-id $cap_xml_rest_api_id | jq -r '.id')

aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway create-stage \
--rest-api-id $cap_xml_rest_api_id \
--stage-name local \
--deployment-id $deployment_id

echo "Created API Gateway deployment"
return 0
Expand Down Expand Up @@ -94,19 +101,32 @@ register_api_gateway_support_for_process_message() {
}

create_resource() {
cap_xml_rest_api_root_resource_id=$1
cap_xml_rest_api_parent_resource_id=$1
cap_xml_rest_api_path_part=$2
Comment on lines 103 to 105

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8fd9b3f: create_resource now assigns its first argument to a separate local variable (cap_xml_rest_api_parent_resource_id) instead of cap_xml_rest_api_root_resource_id, so the global root resource id is no longer overwritten when creating nested resources.

echo $(awslocal apigateway create-resource \

# A resource with the same parent and path part may already have been created
# by another lambda function (e.g. GET /message/{id} and POST /message share /message).
existing_resource_id=$(aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway get-resources \
--rest-api-id $cap_xml_rest_api_id \
| jq -r --arg parent "$cap_xml_rest_api_parent_resource_id" --arg path "$cap_xml_rest_api_path_part" \
'.items[] | select(.parentId == $parent and .pathPart == $path) | .id')

if [ -n "$existing_resource_id" ]; then
echo $existing_resource_id
return 0
fi

echo $(aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway create-resource \
--rest-api-id $cap_xml_rest_api_id \
--parent-id $cap_xml_rest_api_root_resource_id \
--parent-id $cap_xml_rest_api_parent_resource_id \
--path-part $cap_xml_rest_api_path_part | jq -r '.id')
return 0
}

put_method_and_integration() {
resource_id=$1

awslocal apigateway put-method \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-method \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand All @@ -131,7 +151,7 @@ put_integration() {

case $lambda_function_name in
getMessage|getMessage_v2)
awslocal apigateway put-integration \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-integration \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand All @@ -145,7 +165,7 @@ put_integration() {
put_responses_for_get_message
;;
getMessagesAtom|getMessagesAtom_v2)
awslocal apigateway put-integration \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-integration \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand All @@ -158,7 +178,7 @@ put_integration() {
put_responses_for_get_messages_atom
;;
processMessage)
awslocal apigateway put-integration \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-integration \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand Down Expand Up @@ -188,15 +208,15 @@ put_method_response_for_http_200_status_code() {
# by a function. This results in some duplication.
case $lambda_function_name in
getMessage|getMessagesAtom)
awslocal apigateway put-method-response \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-method-response \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
--status-code 200 \
--response-models '{"application/xml": "Empty"}'
;;
processMessage)
awslocal apigateway put-method-response \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-method-response \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand All @@ -217,7 +237,7 @@ put_responses_for_get_message() {

put_responses_for_http_200_get

awslocal apigateway put-integration-response \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-integration-response \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand All @@ -237,7 +257,7 @@ put_responses_for_get_messages_atom() {
}

put_responses_for_process_message() {
awslocal apigateway put-integration-response \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-integration-response \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand All @@ -252,7 +272,7 @@ put_responses_for_http_200_get() {

put_method_response_for_http_200_status_code

awslocal apigateway put-integration-response \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-integration-response \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand All @@ -264,7 +284,7 @@ put_responses_for_http_200_get() {

put_integration_response_for_http_500() {

awslocal apigateway put-integration-response \
aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway put-integration-response \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
--http-method $http_method \
Expand Down
19 changes: 12 additions & 7 deletions docker/scripts/register-lambda-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
# See https://containers.dev/implementors/json_reference/.
set -e

. docker/scripts/set-local-aws-environment.sh

lambda_functions_dir="lib/functions"
deployed_cpx_agw_url=http://$(awslocal apigateway get-rest-apis | jq -r ".items[0].id").execute-api.localhost.localstack.cloud:4566/local
deployed_cpx_agw_url="$AWS_ENDPOINT_URL/restapis/$(aws --endpoint-url "$AWS_ENDPOINT_URL" apigateway get-rest-apis --query "items[?name=='CPX API Gateway'].id | [0]" --output text)/local/_user_request_"

Comment thread
teddmason marked this conversation as resolved.
# Prepare a comma separated list of custom environment variables required by
# each Lambda function.
Expand All @@ -24,6 +26,9 @@ node_tls_reject_unauthorized=$(echo NODE_TLS_REJECT_UNAUTHORIZED=$NODE_TLS_REJEC
set -- $cpx_db_username $cpx_db_password $cpx_db_name $cpx_db_host $cpx_agw_url $cpx_redis_host $cpx_redis_port $cpx_redis_tls $cpx_meteoalarm_api_url $cpx_meteoalarm_api_username $cpx_meteoalarm_api_password $node_tls_reject_unauthorized $cpx_meteoalarm_disable
custom_environment_variables=$(printf '%s,' "$@" | sed 's/,*$//g')

# Create the hot-reload bucket so Floci can serve Lambda code from the local filesystem.
aws --endpoint-url "$AWS_ENDPOINT_URL" s3 mb s3://hot-reload 2>/dev/null || true

# Iterate over each file in lambda_functions_dir
find "$lambda_functions_dir" -type f -name "*.js" | while read -r lambda_function; do
if [ -f "$lambda_function" ]; then
Expand All @@ -43,9 +48,9 @@ find "$lambda_functions_dir" -type f -name "*.js" | while read -r lambda_functio
;;
esac

echo Registering $function_name with LocalStack
echo Registering $function_name with Floci

awslocal lambda create-function \
aws --endpoint-url "$AWS_ENDPOINT_URL" lambda create-function \
--function-name "$function_name" \
--code S3Bucket="hot-reload",S3Key="$(pwd)/" \
--runtime nodejs${NODEJS_VERSION}.x \
Expand All @@ -59,12 +64,12 @@ find "$lambda_functions_dir" -type f -name "*.js" | while read -r lambda_functio
fi
done

echo "All Lambda functions have been registered with LocalStack."
echo "All Lambda functions have been registered with Floci."

awslocal lambda create-function-url-config --function-name archiveMessages --auth-type NONE
aws --endpoint-url "$AWS_ENDPOINT_URL" lambda create-function-url-config --function-name archiveMessages --auth-type NONE

echo "Created function URL config for archiveMessages function"

echo Function URL for archiveMessages is $(awslocal lambda get-function-url-config --function-name archiveMessages | jq -r .FunctionUrl)
echo API Gateway root URL is http://$(awslocal apigateway get-rest-apis | jq -r ".items[0].id").execute-api.localhost.localstack.cloud:4566/local
echo Function URL for archiveMessages is $(aws --endpoint-url "$AWS_ENDPOINT_URL" lambda get-function-url-config --function-name archiveMessages | jq -r .FunctionUrl)
echo API Gateway base URL is $deployed_cpx_agw_url

24 changes: 24 additions & 0 deletions docker/scripts/set-local-aws-environment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh
# Sourced (not executed) by scripts that call the AWS CLI, so that every call is
# guaranteed to target the local Floci emulator rather than a real AWS account.

AWS_ENDPOINT_URL="${AWS_ENDPOINT_URL:-http://localhost:4566}"

# Fail fast rather than provision resources in a real AWS account.
case "$AWS_ENDPOINT_URL" in
http://localhost:* | http://127.0.0.1:* | http://floci:* | http://floci-main:*) ;;
*)
echo "Refusing to run: AWS_ENDPOINT_URL is '$AWS_ENDPOINT_URL', which is not a local Floci endpoint." >&2
echo "Unset it, or set it to the local Floci endpoint (http://localhost:4566), before retrying." >&2
exit 1
;;
esac

# Dummy values so the CLI can never fall back to a real profile or region.
AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-test}"
AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-test}"
AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-eu-west-2}"
AWS_PROFILE=""

export AWS_ENDPOINT_URL AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_DEFAULT_REGION
unset AWS_PROFILE
1 change: 0 additions & 1 deletion docker/scripts/setup-aws-cli-command-completion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ set -e

echo "" >> ~/.bashrc
echo complete -C '/usr/local/bin/aws_completer' aws >> ~/.bashrc
echo complete -C '/usr/local/bin/aws_completer' awslocal >> ~/.bashrc
Loading
Loading