Skip to content

Commit

Permalink
Merge pull request #1 from localstack/localstack_template
Browse files Browse the repository at this point in the history
Add localstack templates
  • Loading branch information
lakkeger authored Aug 8, 2024
2 parents ae2b349 + 8c51ecb commit f983ec1
Show file tree
Hide file tree
Showing 43 changed files with 1,184 additions and 186 deletions.
7 changes: 6 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// More info: https://containers.dev/implementors/json_reference/
{
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bullseye",
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bookworm",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
Expand All @@ -12,5 +12,10 @@
]
}
},
"remoteEnv": {
// Activate LocalStack Pro: https://docs.localstack.cloud/getting-started/auth-token/
"LOCALSTACK_AUTH_TOKEN": "${localEnv:LOCALSTACK_AUTH_TOKEN}", // required for Pro, not processed via template due to security reasons
"LOCALSTACK_API_KEY": "${localEnv:LOCALSTACK_API_KEY}"
},
"postCreateCommand": "npm install -g @devcontainers/cli"
}
17 changes: 17 additions & 0 deletions .github/actions/scenario-test/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: 'Scenario test(s)'
inputs:
template:
description: 'Template to test'
required: true

runs:
using: composite
steps:
- name: Checkout main
id: checkout_release
uses: actions/checkout@v3

- name: Test scenario templates
id: test_template
shell: bash
run: ${{ github.action_path }}/controller.sh ${{ inputs.template }}
99 changes: 99 additions & 0 deletions .github/actions/scenario-test/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/bin/bash
TEMPLATE_ID="$1"
SCENARIO="$2"
SRC_DIR="/tmp/${TEMPLATE_ID}-${SCENARIO}"

set -e

shopt -s dotglob

function remove_comments {
sed -i -re 's/[[:blank:]]*(\/\/\s.*)//' ${1}
}

function merge {
cp .devcontainer/devcontainer.json .devcontainer/devcontainer.json.bak
remove_comments .devcontainer/devcontainer.json.bak

if [ -f inputs.json ] ; then
jq -s ".[0] * .[1]" .devcontainer/devcontainer.json.bak ./inputs.json > .devcontainer/devcontainer.json
cp -f .devcontainer/devcontainer.json .devcontainer/devcontainer.json.bak
fi

jq -s ".[0] * .[1].${SCENARIO}" .devcontainer/devcontainer.json.bak test-project/scenarios.json > .devcontainer/devcontainer.json
cp -f .devcontainer/devcontainer.json .devcontainer/devcontainer.json.bak

# Clean up unneeded keys
printf -v tmp_str '.%s,' "${OPTIONS[@]}"
jq "del($(echo "${tmp_str%,}"))" .devcontainer/devcontainer.json.bak > .devcontainer/devcontainer.json

rm .devcontainer/devcontainer.json.bak
}

function gen_config {
echo "(*) Generating config files"
# Configure templates only if `devcontainer-template.json` contains the `options` property.
OPTIONS=( $(jq -r '.options | keys[]' devcontainer-template.json) )

if [ "${OPTIONS[0]}" != "" ] && [ "${OPTIONS[0]}" != "null" ] ; then
echo "(!) Configuring template options for '${TEMPLATE_ID}-${SCENARIO}'"
for OPTION in "${OPTIONS[@]}"
do
OPTION_KEY="\${templateOption:$OPTION}"

OPTION_VALUE=$( jq -r ".${SCENARIO}.${OPTION}" test-project/scenarios.json)

if ( [ "${OPTION_VALUE}" = "" ] || [ "${OPTION_VALUE}" = "null" ] ) && [ -f inputs.json ] ; then
OPTION_VALUE=$(jq -r ".${OPTION}" inputs.json)
fi

if [ "${OPTION_VALUE}" = "" ] || [ "${OPTION_VALUE}" = "null" ] ; then
OPTION_VALUE=$(jq -r ".options | .${OPTION} | .default" devcontainer-template.json)
fi

# For empty default values use " "
if [ "${OPTION_VALUE}" = "" ] || [ "${OPTION_VALUE}" = "null" ] ; then
echo "Template '${TEMPLATE_ID}-${SCENARIO}' is missing a default value for option '${OPTION}'"
exit 1
fi

echo "(!) Replacing '${OPTION_KEY}' with '${OPTION_VALUE}'"
OPTION_VALUE_ESCAPED=$(sed -e 's/[]\/$*.^[]/\\&/g' <<<"${OPTION_VALUE}")
find ./ -type f -print0 | xargs -0 sed -i "s/${OPTION_KEY}/${OPTION_VALUE_ESCAPED}/g"

if [ "${OPTION}" == "volumePath" ] ; then
mkdir -p ${SRC_DIR}/${OPTION_VALUE}
fi

unset OPTION_VALUE
done

merge
fi
}

function create_scenario {
cp -R "src/${TEMPLATE_ID}" "${SRC_DIR}"

TEST_DIR="test/${TEMPLATE_ID}"
if [ -d "${TEST_DIR}" ] ; then
echo "(*) Copying test folder"
DEST_DIR="${SRC_DIR}/test-project"
mkdir -p ${DEST_DIR}
cp -p ${TEST_DIR}/${SCENARIO}.sh ${TEST_DIR}/scenarios.json ${DEST_DIR}
cp test/test-utils/test-utils.sh ${DEST_DIR}
fi

pushd "${SRC_DIR}"

gen_config

popd

echo
echo "🏗️ Building Dev Container - ${SCENARIO}"
ID_LABEL="test-container=${TEMPLATE_ID}-${SCENARIO}"
devcontainer up --id-label ${ID_LABEL} --workspace-folder "${SRC_DIR}" && echo "🚀 Launched container."
}

create_scenario
78 changes: 78 additions & 0 deletions .github/actions/scenario-test/controller.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash
TEMPLATE_ID="$1"
ALL_RESULTS=" ================== 📋 TEST REPORT ==================\n"
EXIT_CODE=0

set +e

function reportAllScenarioResults {
if [ ${2} -eq 0 ] ; then
RES="✅ Passed:\t"
else
RES="❌ Failed:\t"
EXIT_CODE=1
fi
ALL_RESULTS="$ALL_RESULTS\n$RES'${1}'"
}

function cleanup {
# Clean up
echo "🧹 Cleaning up..."
local ID_LABEL=${2}
CONTAINER_ID=$(docker container ls -f "label=${ID_LABEL}" -q)
if [ "${CONTAINER_ID:-x}" != "x" ]; then
docker rm -f "${CONTAINER_ID}" > /dev/null && echo "🧹 Removing container ${CONTAINER_ID}"
echo "🧹 Removing container localstack-main (if exists)" && docker rm -f "localstack-main" &> /dev/null
fi
echo "🧹 Removing container network ${ID_LABEL/*=/}_devcontainer_ls (if exists)" && docker network rm -f "${ID_LABEL/*=/}_devcontainer_ls" > /dev/null
sudo rm -rf "${1}" && echo "🧹 Removing scenario files ${SCENARIO}"
}

function no_scenarios {
echo
echo "(!) No scenarios collected. Exiting. Bye! 👋"
exit
}

echo "⏱️ Scenario tests - ${TEMPLATE_ID}"
echo -n "(*) Collecting scenarios..."

if ! [ -f test/${TEMPLATE_ID}/scenarios.json ]; then
no_scenarios
fi

SCENARIOS=( $(jq -r 'keys[]' test/${TEMPLATE_ID}/scenarios.json) )

if [ ${#SCENARIOS[@]} -eq 0 ] ; then
no_scenarios
fi

echo "found ${#SCENARIOS[@]}"
echo
printf '%s\n' "${SCENARIOS[@]}"
echo

type devcontainer &> /dev/null
if [ $? -ne 0 ] ; then
export DOCKER_BUILDKIT=1
set -e
echo "(*) Installing @devcontainer/cli"
npm install -g @devcontainers/cli
set +e
fi

for SCENARIO in ${SCENARIOS[@]}; do
ID_LABEL="test-container=${TEMPLATE_ID}-${SCENARIO}"
SRC_DIR="/tmp/${TEMPLATE_ID}-${SCENARIO}"

echo
echo "🔄 Running scenario - ${SCENARIO}"
$(dirname $0)/build.sh ${TEMPLATE_ID} ${SCENARIO} && \
$(dirname $0)/test.sh ${TEMPLATE_ID} ${SCENARIO}
reportAllScenarioResults ${SCENARIO} $?
cleanup ${SRC_DIR} ${ID_LABEL}
echo
done

echo -e "${ALL_RESULTS}"
exit ${EXIT_CODE}
16 changes: 16 additions & 0 deletions .github/actions/scenario-test/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash
TEMPLATE_ID="$1"
SCENARIO="$2"

set -e

function run_scenario {
local SRC_DIR="/tmp/${TEMPLATE_ID}-${SCENARIO}"
local ID_LABEL="test-container=${TEMPLATE_ID}-${SCENARIO}"
devcontainer exec --workspace-folder "${SRC_DIR}" --id-label ${ID_LABEL} /bin/sh -c "set -e && if [ -f \"test-project/${SCENARIO}.sh\" ]; then cd test-project && if [ \"$(id -u)\" = \"0\" ]; then chmod +x ${SCENARIO}.sh; else sudo chmod +x ${SCENARIO}.sh; fi && ./${SCENARIO}.sh; else ls -a; fi"
}

echo
echo "🔍 Running Scenario Test - ${SCENARIO}"
run_scenario

35 changes: 35 additions & 0 deletions .github/actions/smoke-test/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ set -e

shopt -s dotglob

function remove_comments {
sed -i -re 's/[[:blank:]]*(\/\/\s.*)//' ${1}
}

function merge {
cp .devcontainer/devcontainer.json .devcontainer/devcontainer.json.bak
remove_comments .devcontainer/devcontainer.json.bak

jq -s ".[0] * .[1]" .devcontainer/devcontainer.json.bak ./inputs.json > .devcontainer/devcontainer.json
cp -f .devcontainer/devcontainer.json .devcontainer/devcontainer.json.bak

# Clean up unneeded keys
printf -v tmp_str '.%s,' "${OPTIONS[@]}"
jq "del($(echo "${tmp_str%,}"))" .devcontainer/devcontainer.json.bak > .devcontainer/devcontainer.json

rm .devcontainer/devcontainer.json.bak
}

SRC_DIR="/tmp/${TEMPLATE_ID}"
cp -R "src/${TEMPLATE_ID}" "${SRC_DIR}"

Expand All @@ -21,8 +39,15 @@ if [ "${OPTION_PROPERTY}" != "" ] && [ "${OPTION_PROPERTY}" != "null" ] ; then
for OPTION in "${OPTIONS[@]}"
do
OPTION_KEY="\${templateOption:$OPTION}"
if [ -f inputs.json ] ; then
OPTION_VALUE=$(jq -r ".${OPTION}" inputs.json)
fi

if [ "${OPTION_VALUE}" = "" ] || [ "${OPTION_VALUE}" = "null" ] ; then
OPTION_VALUE=$(jq -r ".options | .${OPTION} | .default" devcontainer-template.json)
fi

# For empty default values use " "
if [ "${OPTION_VALUE}" = "" ] || [ "${OPTION_VALUE}" = "null" ] ; then
echo "Template '${TEMPLATE_ID}' is missing a default value for option '${OPTION}'"
exit 1
Expand All @@ -31,10 +56,20 @@ if [ "${OPTION_PROPERTY}" != "" ] && [ "${OPTION_PROPERTY}" != "null" ] ; then
echo "(!) Replacing '${OPTION_KEY}' with '${OPTION_VALUE}'"
OPTION_VALUE_ESCAPED=$(sed -e 's/[]\/$*.^[]/\\&/g' <<<"${OPTION_VALUE}")
find ./ -type f -print0 | xargs -0 sed -i "s/${OPTION_KEY}/${OPTION_VALUE_ESCAPED}/g"

if [ "${OPTION}" == "volumePath" ] ; then
mkdir -p ${SRC_DIR}/${OPTION_VALUE}
fi

unset OPTION_VALUE
done
fi
fi

if [ -f inputs.json ] ; then
merge
fi

popd

TEST_DIR="test/${TEMPLATE_ID}"
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/smoke-test/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ devcontainer exec --workspace-folder "${SRC_DIR}" --id-label ${ID_LABEL} /bin/sh

# Clean up
docker rm -f $(docker container ls -f "label=${ID_LABEL}" -q)
rm -rf "${SRC_DIR}"
sudo rm -rf "${SRC_DIR}"
33 changes: 30 additions & 3 deletions .github/workflows/test-pr.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: "CI - Test Templates"
on:
pull_request:
paths-ignore:
- '*.md'
- LICENSE
- .gitkeep
- .gitignore

jobs:
detect-changes:
Expand All @@ -12,10 +17,10 @@ jobs:
id: filter
with:
filters: |
color: ./**/color/**
hello: ./**/hello/**
localstack-dind: ./**/localstack-dind/**
localstack-dood: ./**/localstack-dood/**
test:
smoke-test:
needs: [detect-changes]
runs-on: ubuntu-latest
continue-on-error: true
Expand All @@ -26,7 +31,29 @@ jobs:
- uses: actions/checkout@v3

- name: Smoke test for '${{ matrix.templates }}'
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }}
id: smoke_test
uses: ./.github/actions/smoke-test
with:
template: "${{ matrix.templates }}"

scenario-test:
needs: [detect-changes]
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
templates: ${{ fromJSON(needs.detect-changes.outputs.templates) }}
steps:
- uses: actions/checkout@v3

- name: Scenario test(s) for '${{ matrix.templates }}'
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }}
id: scenario_test
uses: ./.github/actions/scenario-test
with:
template: "${{ matrix.templates }}"
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022 Microsoft Corporation
Copyright (c) 2024 LocalStack GmbH

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading

0 comments on commit f983ec1

Please sign in to comment.