Use descriptive test and executable names so implementation surfaces do not depend on journal organization. Consolidate the unreleased migration history into the authoritative initial schema because no deployed database requires an upgrade path.
176 lines
6.2 KiB
Shell
Executable file
176 lines
6.2 KiB
Shell
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
source "$ROOT/tests/kind/lib.sh"
|
|
|
|
USER_KUBECONFIG_BEFORE="$(user_kubeconfig_digest)"
|
|
SUCCEEDED=false
|
|
OWNS_FIXTURE=false
|
|
APP_IMAGE=nuthatch-product-matrix:local
|
|
|
|
cleanup() {
|
|
local status=$?
|
|
trap - EXIT INT TERM
|
|
if [[ "${NUTHATCH_TESTBED_RETAIN:-0}" = 1 ]] && [[ "$SUCCEEDED" != true ]]; then
|
|
printf 'retained kubeconfig: %s\n' "$KUBECONFIG_PATH"
|
|
printf 'retained context: %s\n' "$CONTEXT"
|
|
exit "$status"
|
|
fi
|
|
if [[ "$OWNS_FIXTURE" = true ]]; then
|
|
destroy_fixture || status=1
|
|
fi
|
|
if [[ "$(user_kubeconfig_digest)" != "$USER_KUBECONFIG_BEFORE" ]]; then
|
|
printf 'user kubeconfig changed unexpectedly\n' >&2
|
|
status=1
|
|
fi
|
|
exit "$status"
|
|
}
|
|
|
|
trap cleanup EXIT
|
|
trap 'exit 130' INT
|
|
trap 'exit 143' TERM
|
|
|
|
render_application() {
|
|
local lane="$1"
|
|
local profile_file="$2"
|
|
local pg_conn
|
|
local redis_url
|
|
local oidc_issuer
|
|
local oidc_client_id
|
|
local oidc_additional_audiences
|
|
local oidc_client_secret
|
|
local s3_endpoint
|
|
local s3_region
|
|
local s3_bucket
|
|
local s3_access_key
|
|
local s3_secret_key
|
|
pg_conn="$(sed -n 's/^NUTHATCH_PG_CONN=//p' "$profile_file")"
|
|
redis_url="$(sed -n 's/^NUTHATCH_REDIS_URL=//p' "$profile_file")"
|
|
oidc_issuer="$(sed -n 's/^NUTHATCH_OIDC_ISSUER=//p' "$profile_file")"
|
|
oidc_client_id="$(sed -n 's/^NUTHATCH_OIDC_CLIENT_ID=//p' "$profile_file")"
|
|
oidc_additional_audiences="$(
|
|
sed -n 's/^NUTHATCH_OIDC_ADDITIONAL_AUDIENCES=//p' "$profile_file"
|
|
)"
|
|
oidc_client_secret="$(<"$profile_file.oidc-secret")"
|
|
s3_endpoint="$(sed -n 's/^NUTHATCH_S3_ENDPOINT=//p' "$profile_file")"
|
|
s3_region="$(sed -n 's/^NUTHATCH_S3_REGION=//p' "$profile_file")"
|
|
s3_bucket="$(sed -n 's/^NUTHATCH_S3_BUCKET=//p' "$profile_file")"
|
|
s3_access_key="$(sed -n 's/^NUTHATCH_S3_ACCESS_KEY=//p' "$profile_file")"
|
|
s3_secret_key="$(sed -n 's/^NUTHATCH_S3_SECRET_KEY=//p' "$profile_file")"
|
|
sed \
|
|
-e "s|@@LANE@@|$lane|g" \
|
|
-e "s|@@APP_IMAGE@@|$APP_IMAGE|g" \
|
|
-e "s|@@PG_CONN@@|$pg_conn|g" \
|
|
-e "s|@@REDIS_URL@@|$redis_url|g" \
|
|
-e "s|@@OIDC_ISSUER@@|$oidc_issuer|g" \
|
|
-e "s|@@OIDC_CLIENT_ID@@|$oidc_client_id|g" \
|
|
-e "s|@@OIDC_ADDITIONAL_AUDIENCES@@|$oidc_additional_audiences|g" \
|
|
-e "s|@@OIDC_CLIENT_SECRET@@|$oidc_client_secret|g" \
|
|
-e "s|@@S3_ENDPOINT@@|$s3_endpoint|g" \
|
|
-e "s|@@S3_REGION@@|$s3_region|g" \
|
|
-e "s|@@S3_BUCKET@@|$s3_bucket|g" \
|
|
-e "s|@@S3_ACCESS_KEY@@|$s3_access_key|g" \
|
|
-e "s|@@S3_SECRET_KEY@@|$s3_secret_key|g" \
|
|
"$ROOT/deploy/kubernetes/nuthatch.yaml.in" > "$RUNTIME/product-app-$lane.yaml"
|
|
if [[ "${NUTHATCH_PRODUCT_GATE:-0}" = 1 ]]; then
|
|
sed -i \
|
|
-e 's/NUTHATCH_BROWSE_PAGE_SIZE: "200"/NUTHATCH_BROWSE_PAGE_SIZE: "2"/' \
|
|
-e 's/NUTHATCH_SEARCH_MAX_KEYS: "500"/NUTHATCH_SEARCH_MAX_KEYS: "3"/' \
|
|
-e 's/NUTHATCH_DELETE_PAGE_SIZE: "100"/NUTHATCH_DELETE_PAGE_SIZE: "2"/' \
|
|
"$RUNTIME/product-app-$lane.yaml"
|
|
fi
|
|
}
|
|
|
|
cleanup_application() {
|
|
local lane="$1"
|
|
kube --namespace "$FIXTURE_NAMESPACE" delete \
|
|
"deployment/nuthatch-$lane" \
|
|
"service/nuthatch-$lane" \
|
|
"configmap/nuthatch-$lane" \
|
|
"secret/nuthatch-$lane" \
|
|
--ignore-not-found >/dev/null
|
|
rm -f "$RUNTIME/product-app-$lane.yaml"
|
|
}
|
|
|
|
set_product_profile() {
|
|
local profile="$1"
|
|
local mode="$2"
|
|
local profile_file="$RUNTIME/$profile.env"
|
|
sed -i '/^NUTHATCH_PRODUCT_MODE=/d' "$profile_file"
|
|
printf 'NUTHATCH_PRODUCT_MODE=%s\n' "$mode" >> "$profile_file"
|
|
kube create configmap "$profile" \
|
|
--namespace "$FIXTURE_NAMESPACE" \
|
|
--from-env-file="$profile_file" \
|
|
--dry-run=client \
|
|
--output yaml |
|
|
kube apply --filename - >/dev/null
|
|
}
|
|
|
|
acquire_fixture_lock
|
|
OWNS_FIXTURE=true
|
|
setup_fixture durable coordination oidc target
|
|
source "$RUNTIME/fixture.env"
|
|
"$NUTHATCH_REAL_NERDCTL" --namespace "$NERDCTL_NAMESPACE" build \
|
|
--file "$ROOT/Dockerfile" \
|
|
--tag "$APP_IMAGE" \
|
|
"$ROOT"
|
|
load_local_image "$APP_IMAGE" "$NERDCTL_NAMESPACE"
|
|
|
|
while IFS=$'\t' read -r lane coordination oidc target; do
|
|
profile="$(write_lane_profile "$lane" "$coordination" "$oidc" "$target")"
|
|
if [[ "${NUTHATCH_PRODUCT_GATE:-0}" = 1 ]]; then
|
|
set_product_profile "$profile" verify
|
|
fi
|
|
render_application "$lane" "$RUNTIME/$profile.env"
|
|
kube apply --filename "$RUNTIME/product-app-$lane.yaml" >/dev/null
|
|
kube --namespace "$FIXTURE_NAMESPACE" rollout status \
|
|
"deployment/nuthatch-$lane" --timeout=180s
|
|
if [[ "${NUTHATCH_APP_INTERACTIVE:-0}" = 1 ]]; then
|
|
SUCCEEDED=true
|
|
OWNS_FIXTURE=false
|
|
printf 'interactive kubeconfig: %s\n' "$KUBECONFIG_PATH"
|
|
printf 'interactive context: %s\n' "$CONTEXT"
|
|
printf 'interactive namespace: %s\n' "$FIXTURE_NAMESPACE"
|
|
printf 'interactive service: nuthatch-%s:8080\n' "$lane"
|
|
exit 0
|
|
fi
|
|
job="product-app-$lane"
|
|
render_lane_job \
|
|
"$job" \
|
|
"$TESTBED/product-matrix-job.yaml.in" \
|
|
"$CURL_LOCAL_IMAGE" \
|
|
"$profile"
|
|
sed -i "s|@@LANE@@|$lane|g" "$RUNTIME/$job.yaml"
|
|
printf 'Running lane %s: coordination=%s oidc=%s target=%s\n' \
|
|
"$lane" "$coordination" "$oidc" "$target"
|
|
run_job_manifest "$job" "$RUNTIME/$job.yaml"
|
|
if [[ "${NUTHATCH_PRODUCT_GATE:-0}" = 1 ]]; then
|
|
sed -i \
|
|
's/NUTHATCH_SEARCH_TIMEOUT_MS: "2000"/NUTHATCH_SEARCH_TIMEOUT_MS: "1"/' \
|
|
"$RUNTIME/product-app-$lane.yaml"
|
|
kube apply --filename "$RUNTIME/product-app-$lane.yaml" >/dev/null
|
|
kube --namespace "$FIXTURE_NAMESPACE" rollout restart \
|
|
"deployment/nuthatch-$lane" >/dev/null
|
|
kube --namespace "$FIXTURE_NAMESPACE" rollout status \
|
|
"deployment/nuthatch-$lane" --timeout=180s
|
|
set_product_profile "$profile" timeout
|
|
timeout_job="product-timeout-$lane"
|
|
render_lane_job \
|
|
"$timeout_job" \
|
|
"$TESTBED/product-matrix-job.yaml.in" \
|
|
"$CURL_LOCAL_IMAGE" \
|
|
"$profile"
|
|
sed -i "s|@@LANE@@|$lane|g" "$RUNTIME/$timeout_job.yaml"
|
|
run_job_manifest "$timeout_job" "$RUNTIME/$timeout_job.yaml"
|
|
kube --namespace "$FIXTURE_NAMESPACE" delete \
|
|
"job/$timeout_job" --ignore-not-found >/dev/null
|
|
rm -f "$RUNTIME/$timeout_job.yaml"
|
|
fi
|
|
cleanup_application "$lane"
|
|
cleanup_lane_state "$lane" "$coordination" "$oidc" "$target"
|
|
cleanup_lane_resources "$job" "$profile"
|
|
done < <(expand_fixture_matrix coordination oidc target)
|
|
|
|
SUCCEEDED=true
|
|
printf 'Nuthatch product matrix gate passed\n'
|