Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Install nodejs
uses: actions/setup-node@v4
with:
node-version: "20.x"
node-version: "22.x"

- name: Install node dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .labrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const globalsAsArray = [
'__asyncGenerator', '__asyncDelegator', '__asyncValues', '__makeTemplateObject',
'__importStar', '__importDefault', '__classPrivateFieldGet', '__classPrivateFieldSet',
'__classPrivateFieldIn', '__addDisposableResource', '__disposeResources',
'__rewriteRelativeImportExtension'
'__rewriteRelativeImportExtension', 'awslambda'
]

const globals = globalsAsArray.toString()
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v20.18.3
v22.21.1
3 changes: 0 additions & 3 deletions capAlert.json

This file was deleted.

2 changes: 1 addition & 1 deletion docker/.env
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ LAMBDA_IGNORE_ARCHITECTURE=1
# debugging when cloning the remote repository into a container volume.
DEBUG_HOST_ADDRESS=192.168.0.5
CPX_DB_HOST=capxmldb
NODEJS_VERSION=20
NODEJS_VERSION=22
PGADMIN_DEFAULT_EMAIL=ubuntu@localhost.localdomain

# Database associated values including well known secrets for local development
Expand Down
2 changes: 1 addition & 1 deletion docker/dev-tools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ services:
- capxmlliquibase:/capxmldb
networks:
ls:
command: update
command: /bin/sh -c "lpm add postgresql && liquibase update"
volumes:
capxmlpgadmin:
external: true
Expand Down
8 changes: 4 additions & 4 deletions docker/scripts/initialize-named-volumes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ set -e

# The macOS version of realpath does not support the -m switch so the GNU version
# is needed.
if [ `uname` = "Darwin" ] && [ x`command -v grealpath` = "x" ]; then
if [ $(uname) = "Darwin" ] && [ x$(command -v grealpath) = "x" ]; then
echo "GNU coreutils need to be installed to use realpath with the -m switch"
exit 1
fi

# If running on macOS use the GNU version of realpath.
if [ `uname` = "Darwin" ]; then
if [ $(uname) = "Darwin" ]; then
alias realpath="grealpath"
fi

Expand Down Expand Up @@ -74,7 +74,7 @@ fi
docker container create --name capxmlpgbootstraptemp -v capxmlpgbootstrap:/docker-entrypoint-initdb.d -v capxmlpgtmp:/tmp alpine
echo Created capxmlpgbootstraptemp container
docker cp ${CAP_XML_HOST_DIR}/docker/cap-xml-db/bootstrap-cap-xml-db.sh capxmlpgbootstraptemp:/docker-entrypoint-initdb.d/bootstrap-cap-xml-db.sh
(cd `realpath -m ${CAP_XML_HOST_DIR}`/../cap-xml-db && docker cp ./cx/0.0.1/setup.sql capxmlpgbootstraptemp:/tmp/setup.sql)
(cd $(realpath -m ${CAP_XML_HOST_DIR})/../cap-xml-db && docker cp ./cx/0.0.1/setup.sql capxmlpgbootstraptemp:/tmp/setup.sql)
docker rm capxmlpgbootstraptemp
echo Removed capxmlpgbootstraptemp container

Expand All @@ -90,6 +90,6 @@ fi
# https://stackoverflow.com/questions/37468788/what-is-the-right-way-to-add-data-to-an-existing-named-volume-in-docker
docker container create --name capxmlliquibasetemp -v capxmlliquibase:/capxmldb alpine
echo Created capxmlliquibasetemp container
(cd `realpath -m ${CAP_XML_HOST_DIR}`/../cap-xml-db/cx && docker cp . capxmlliquibasetemp:/capxmldb)
(cd $(realpath -m ${CAP_XML_HOST_DIR})/../cap-xml-db/cx && docker cp . capxmlliquibasetemp:/capxmldb)
docker rm capxmlliquibasetemp
echo Removed capxmlliquibasetemp container
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@
# This script MUST be run on the host before attempting to create a development container.
set -e

if [ `whoami` != root ]; then
if [ $(whoami) != root ]; then
echo This script must be run as root
exit 1
fi

if [ ! -d "$LOCAL_CAP_XML_DIR"/.git ] && [ x`echo $"$LOCAL_CAP_XML_DIR" | grep -E /cap-xml/?$` = "x" ]; then
if [ ! -d "$LOCAL_CAP_XML_DIR"/.git ] && [ x$(echo $"$LOCAL_CAP_XML_DIR" | grep -E /cap-xml/?$) = "x" ]; then
echo LOCAL_CAP_XML_DIR must be set to the absolute path of the root of a local cap-xml repository
exit 1
fi

if [ `uname` != "Linux" ] && [ `uname` != "Darwin" ]; then
echo "Unsupported operating system `uname` detected - Linux and macOS are supported"
if [ $(uname) != "Linux" ] && [ $(uname) != "Darwin" ]; then
echo "Unsupported operating system $(uname) detected - Linux and macOS are supported"
exit 1
fi


# The macOS version of realpath does not support the -m switch so the GNU version
# is needed.
if [ `uname` = "Darwin" ] && [ x`command -v grealpath` = "x" ]; then
if [ $(uname) = "Darwin" ] && [ x$(command -v grealpath) = "x" ]; then
echo "GNU coreutils need to be installed to use realpath with the -m switch"
exit 1
fi

# If running on macOS use the GNU version of realpath.
if [ `uname` = "Darwin" ]; then
if [ $(uname) = "Darwin" ]; then
alias realpath="grealpath"
fi

Expand Down Expand Up @@ -65,11 +65,11 @@ CAP_XML_VOLUME_WORKSPACE_DIR=/workspaces/cap-xml
# (see https://apple.stackexchange.com/questions/388236/unable-to-create-folder-in-root-of-macintosh-hd),
# /workspaces/cap-xml cannot be created. Container volume based running/debugging is NOT supported using default
# macOS configuration accordingly.
if [ `uname` = "Linux" ] && [ ! -L "$CAP_XML_VOLUME_WORKSPACE_DIR" ] && [ $(realpath -m "$CAP_XML_VOLUME_WORKSPACE_DIR") != $(realpath -m "$CAP_XML_WORKSPACE_DIR") ]; then
if [ $(uname) = "Linux" ] && [ ! -L "$CAP_XML_VOLUME_WORKSPACE_DIR" ] && [ $(realpath -m "$CAP_XML_VOLUME_WORKSPACE_DIR") != $(realpath -m "$CAP_XML_WORKSPACE_DIR") ]; then
mkdir -p /workspaces
ln -s "$CAP_XML_WORKSPACE_DIR" "$CAP_XML_VOLUME_WORKSPACE_DIR"
echo Created symbolic link from "$CAP_XML_VOLUME_WORKSPACE_DIR" to "$CAP_XML_WORKSPACE_DIR"
elif [ `uname` = "Darwin" ]; then
elif [ $(uname) = "Darwin" ]; then
echo "macOS detected - WARNING - Running/debugging is only supported when creating a development container from a local cap-xml repository"
fi

Expand Down
7 changes: 5 additions & 2 deletions docker/scripts/load-dummy-data.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ set -e
# Constants
BASE_GUID="4eb3b7350ab7aa443650fc9351f02940E"
BASE_AREA="TESTAREA"
DATA_FILE="capAlert.json"
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

# Calculate tomorrow's date
TOMORROW=$(date -u -d "+1 day" +"%Y-%m-%dT%H:%M:%S+00:00")

# Loop 10 times
i=1
while [ $i -le 10 ]; do
Expand All @@ -21,7 +24,7 @@ while [ $i -le 10 ]; do
# Perform find and replace, then send with curl
curl -X POST "$LAMBDA_URL" \
-H "Content-Type: text/xml" \
-d "$(sed -e "s/${BASE_GUID}/${NEW_GUID}/g" -e "s/${BASE_AREA}/${NEW_AREA}/g" "$DATA_FILE")"
-d "$(sed -e "s/${BASE_GUID}/${NEW_GUID}/g" -e "s/${BASE_AREA}/${NEW_AREA}/g" -e "s|<expires>2025-11-16T08:00:27+00:00</expires>|<expires>${TOMORROW}</expires>|g" "$DATA_FILE")"

echo "Done with POST $i"
i=$((i + 1))
Expand Down
46 changes: 40 additions & 6 deletions docker/scripts/register-api-gateway.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,27 @@ main() {
cap_xml_rest_api_root_resource_id=$(awslocal apigateway get-resources --rest-api-id $cap_xml_rest_api_id | jq -r '.items[0].id')
lambda_functions_dir="lib/functions"

for lambda_function in "$lambda_functions_dir"/*; do
find "$lambda_functions_dir" -type f -name "*.js" | while read -r lambda_function; do
relative_path="${lambda_function#$lambda_functions_dir/}"
dir_prefix=$(dirname "$relative_path")
lambda_function_name=$(basename "$lambda_function" .js)
http_method=$(get_http_method $lambda_function_name)

case "$dir_prefix" in
v[0-9]*)
lambda_function_name="${lambda_function_name}_${dir_prefix}"
;;
*)
echo "No version prefix"
;;
esac

if [ $lambda_function_name = "archiveMessages" ]; then
echo Skipping $lambda_function because it is not accessed through an API Gateway
continue
fi

# Convert the Lambda function name from camel case to undersore case to call the correct API gateway registration function.
# Convert the Lambda function name from camel case to undersore case to call the correct API gateway registration function.
$(echo register_api_gateway_support_for_$lambda_function_name | sed -E "s/([a-z0-9])([A-Z])/\1_\2/g; s/([A-Z])([A-Z][a-z])/\1_\2/g" | tr "[:upper:]" "[:lower:]")
echo "API Gateway support added for $lambda_function_name"

Expand All @@ -47,11 +58,30 @@ register_api_gateway_support_for_get_message() {
put_method_and_integration $message_resource_id
}

register_api_gateway_support_for_get_message_v2() {
if [ -z "$v2_resource_id" ]; then
v2_resource_id=$(create_resource "$cap_xml_rest_api_root_resource_id" "v2")
fi
get_message_v2_resource_id=$(create_resource $v2_resource_id "message")
message_v2_resource_id=$(create_resource $get_message_v2_resource_id "{id}")
put_method_and_integration $message_v2_resource_id
return 0
}

register_api_gateway_support_for_get_messages_atom() {
get_messages_atom_resource_id=$(create_resource $cap_xml_rest_api_root_resource_id "messages.atom")
put_method_and_integration $get_messages_atom_resource_id
}

register_api_gateway_support_for_get_messages_atom_v2() {
if [ -z "$v2_resource_id" ]; then
v2_resource_id=$(create_resource "$cap_xml_rest_api_root_resource_id" "v2")
fi
get_messages_atom_v2_resource_id=$(create_resource $v2_resource_id "messages.atom")
put_method_and_integration $get_messages_atom_v2_resource_id
return 0
}

register_api_gateway_support_for_process_message() {
process_message_resource_id=$(create_resource $cap_xml_rest_api_root_resource_id "message")
put_method_and_integration $process_message_resource_id
Expand Down Expand Up @@ -90,7 +120,7 @@ put_integration() {
# by a function. This results in some duplication.

case $lambda_function_name in
getMessage)
getMessage|getMessage_v2)
awslocal apigateway put-integration \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
Expand All @@ -104,7 +134,7 @@ put_integration() {

put_responses_for_get_message
;;
getMessagesAtom)
getMessagesAtom|getMessagesAtom_v2)
awslocal apigateway put-integration \
--rest-api-id $cap_xml_rest_api_id \
--resource-id $resource_id \
Expand All @@ -127,7 +157,11 @@ put_integration() {
--uri arn:aws:apigateway:eu-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-west-2:000000000000:function:$lambda_function_name/invocations \
--passthrough-behavior WHEN_NO_TEMPLATES \
--content-handling CONVERT_TO_TEXT \
--request-templates '{"text/html": "{\"bodyXml\": $input.json(\"$.message\")}", "text/xml": "{\"bodyXml\": $input.json(\"$.message\")}"}'
--request-templates '{
"text/html": "{\"bodyXml\": \"$util.escapeJavaScript($input.body)\"}",
"text/xml": "{\"bodyXml\": \"$util.escapeJavaScript($input.body)\"}"
}'


put_responses_for_process_message
;;
Expand Down
21 changes: 18 additions & 3 deletions docker/scripts/register-lambda-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,33 @@ set -- $cpx_db_username $cpx_db_password $cpx_db_name $cpx_db_host $cpx_agw_url
custom_environment_variables=$(printf '%s,' "$@" | sed 's/,*$//g')

# Iterate over each file in lambda_functions_dir
for lambda_function in "$lambda_functions_dir"/*; do
find "$lambda_functions_dir" -type f -name "*.js" | while read -r lambda_function; do
if [ -f "$lambda_function" ]; then
relative_path="${lambda_function#$lambda_functions_dir/}"
dir_prefix=$(dirname "$relative_path")
function_name=$(basename "$lambda_function" .js)
handler_path="lib/functions/$function_name.$function_name" # default

# If the directory matches v{number}, update function name and handler path
case "$dir_prefix" in
v[0-9]*)
handler_path="lib/functions/$dir_prefix/$function_name.$function_name"
function_name="${function_name}_${dir_prefix}"
;;
*)
echo "No version prefix"
;;
esac

echo Registering $function_name with LocalStack

awslocal lambda create-function \
--function-name "$function_name" \
--code S3Bucket="hot-reload",S3Key="$(pwd)/" \
--runtime nodejs20.x \
--runtime nodejs${NODEJS_VERSION}.x \
--timeout $LAMBDA_TIMEOUT \
--role arn:aws:iam::000000000000:role/lambda-role \
--handler lib/functions/$function_name.$function_name \
--handler "$handler_path" \
--environment "Variables={$custom_environment_variables}" \
--no-cli-pager
sleep 1
Expand Down
18 changes: 9 additions & 9 deletions docker/scripts/setup-for-rootless-docker-with-dev-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# This script MUST be run on the host before attempting to create a dev container using rootless Docker.
set -e

if [ `whoami` != root ]; then
if [ $(whoami) != root ]; then
echo This script must be run as root
exit 1
fi

HOST_UID=$(id -u "$CAP_XML_HOST_USERNAME")
HOST_GID=$(id -g "$CAP_XML_HOST_USERNAME")
HOST_SUBUID=$(echo $(cat /etc/subuid | grep `echo $CAP_XML_HOST_USERNAME` | cut -d ':' -f 2))
HOST_SUBGID=$(echo $(cat /etc/subgid | grep `echo $CAP_XML_HOST_USERNAME` | cut -d ':' -f 2))
HOST_SUBUID=$(echo $(cat /etc/subuid | grep $(echo $CAP_XML_HOST_USERNAME) | cut -d ':' -f 2))
HOST_SUBGID=$(echo $(cat /etc/subgid | grep $(echo $CAP_XML_HOST_USERNAME) | cut -d ':' -f 2))

if [ x"$HOST_SUBUID" = "x" ]; then
echo The host user $CAP_XML_HOST_USERNAME does not have a subuid entry in /etc/subuid
Expand All @@ -22,17 +22,17 @@ if [ x"$HOST_SUBGID" = "x" ]; then
exit 1
fi

DEV_CONTAINER_UID_ON_HOST=`echo $((($HOST_SUBUID + $HOST_UID) - 1))`
DEV_CONTAINER_GID_ON_HOST=`echo $((($HOST_SUBGID + $HOST_GID) - 1))`
DEV_CONTAINER_DOCKER_GID_ON_HOST=$((($HOST_SUBGID + `getent group docker | cut -d ':' -f 3`) - 1))
DEV_CONTAINER_UID_ON_HOST=$(echo $((($HOST_SUBUID + $HOST_UID) - 1)))
DEV_CONTAINER_GID_ON_HOST=$(echo $((($HOST_SUBGID + $HOST_GID) - 1)))
DEV_CONTAINER_DOCKER_GID_ON_HOST=$((($HOST_SUBGID + $(getent group docker | cut -d ':' -f 3)) - 1))
DOCKER_SOCKET=/var/run/docker.sock
ROOTLESS_DOCKER_SOCKET=/run/user/$HOST_UID/docker.sock
CAP_XML_WORKSPACE_DIR=/workspaces/cap-xml/
CAP_XML_WORKSPACE_DOCKER_DIR=${CAP_XML_WORKSPACE_DIR}docker
WORKSPACE_FOLDER_HOST_OWNERSHIP=$DEV_CONTAINER_UID_ON_HOST:$DEV_CONTAINER_GID_ON_HOST
WORKSPACE_DOCKER_FOLDER_HOST_OWNERSHIP=$HOST_UID:$HOST_GID

if [ ! -d "$LOCAL_CAP_XML_DIR"/.git ] && [ x`echo $"$LOCAL_CAP_XML_DIR" | grep -E /cap-xml/?$` = "x" ]; then
if [ ! -d "$LOCAL_CAP_XML_DIR"/.git ] && [ x$(echo $"$LOCAL_CAP_XML_DIR" | grep -E /cap-xml/?$) = "x" ]; then
echo LOCAL_CAP_XML_DIR must be set to the absolute path of the root of a local cap-xml repository
exit 1
fi
Expand Down Expand Up @@ -64,7 +64,7 @@ fi
#
# If creating a dev container by cloning the cap-xml repository into a container volume, the dev container user has ownership
# of items in the volume without risk of git reporting dubious ownership.
if [ `stat -c "%u:%g" $CAP_XML_WORKSPACE_DIR` != $WORKSPACE_FOLDER_HOST_OWNERSHIP ]; then
if [ $(stat -c "%u:%g" $CAP_XML_WORKSPACE_DIR) != $WORKSPACE_FOLDER_HOST_OWNERSHIP ]; then
chown -R $WORKSPACE_FOLDER_HOST_OWNERSHIP $CAP_XML_WORKSPACE_DIR
echo Changed UID:GID for $CAP_XML_WORKSPACE_DIR to $WORKSPACE_FOLDER_HOST_OWNERSHIP
else
Expand All @@ -73,7 +73,7 @@ fi

# Ensure the local cap-xml repository docker directory hierarchy UID:GID is set to HOST_UID:HOST_GID so that
# named Docker volumes can be created.
if [ `stat -c "%u:%g" $CAP_XML_WORKSPACE_DOCKER_DIR` != $WORKSPACE_DOCKER_FOLDER_HOST_OWNERSHIP ]; then
if [ $(stat -c "%u:%g" $CAP_XML_WORKSPACE_DOCKER_DIR) != $WORKSPACE_DOCKER_FOLDER_HOST_OWNERSHIP ]; then
chown -R $WORKSPACE_DOCKER_FOLDER_HOST_OWNERSHIP $CAP_XML_WORKSPACE_DOCKER_DIR
echo Changed UID:GID for $CAP_XML_WORKSPACE_DOCKER_DIR to $WORKSPACE_DOCKER_FOLDER_HOST_OWNERSHIP
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

set -e

if [ `whoami` != root ]; then
if [ $(whoami) != root ]; then
echo This script must be run as root
exit 1
fi
Expand All @@ -13,7 +13,7 @@ HOST_UID=$(id -u "$CAP_XML_HOST_USERNAME")
DOCKER_SOCKET=/var/run/docker.sock
ROOTLESS_DOCKER_SOCKET=/run/user/$HOST_UID/docker.sock

if [ ! -d "$LOCAL_CAP_XML_DIR"/.git ] && [ x`echo $"$LOCAL_CAP_XML_DIR" | grep -E /cap-xml/?$` = "x" ]; then
if [ ! -d "$LOCAL_CAP_XML_DIR"/.git ] && [ x$(echo $"$LOCAL_CAP_XML_DIR" | grep -E /cap-xml/?$) = "x" ]; then
echo LOCAL_CAP_XML_DIR must be set to the absolute path of the root of a local cap-xml repository
exit 1
fi
Expand Down
Loading