Skip to content

Add multi-service-app sample: URL shortener composing seven Azure services - #111

Draft
lazarkanelov wants to merge 4 commits into
mainfrom
add-multi-service-app-sample
Draft

Add multi-service-app sample: URL shortener composing seven Azure services#111
lazarkanelov wants to merge 4 commits into
mainfrom
add-multi-service-app-sample

Conversation

@lazarkanelov

@lazarkanelov lazarkanelov commented Jul 30, 2026

Copy link
Copy Markdown

Motivation

The existing samples each exercise one or two services in isolation. This adds a composite sample — Linklet, a URL shortener with an event-driven worker — that chains seven services into a single causal chain: Web App, Functions (Service Bus trigger + Queue Storage trigger), Storage (table/queue/blob), Key Vault, Service Bus, PostgreSQL flexible server, plus a shared user-assigned managed identity and Log Analytics. Every shortened link crosses 4–6 services before it renders on the page, so a regression in any one service breaks an observable user outcome — making the sample a realistic end-to-end workout for the emulator that single-service samples structurally cannot provide. Building and validating it surfaced several emulator parity findings that are being fixed separately (localstack/localstack-pro#8135).

Changes

  • New sample samples/multi-service-app/python with all three deployment variants, following the sibling samples' layout and naming conventions (local-msa-* resource names on the eventhubs sample-infix precedent):
    • scripts/ — idempotent Azure CLI deploy, an 8-step validate.sh that walks the full causal chain, and a call-web-app.sh smoke test
    • terraform/ — flat configuration with variables.tf/terraform.tfvars, provider pinned to =4.81.0 like the siblings
    • bicep/main.bicep + main.bicepparam (secrets via readEnvironmentVariable), role assignments using built-in role GUIDs verified against the Azure role-definitions API
    • src/ (Flask web app) and function/ (Python v2-model worker with identity-based Service Bus trigger and queue trigger)
  • Registered in run-samples.sh (SAMPLES, TERRAFORM_SAMPLES, BICEP_SAMPLES) and in the root README outline table

Tests

All three variants were run against the LocalStack Azure emulator (image built from current main), each on a fresh emulator instance matching CI's one-shard-per-test isolation:

  • scripts: full deploy + validate.sh all green — web app health (Table + Key Vault + PostgreSQL via managed identity), AbuseScan verdicts for benign and suspicious links via the Service Bus trigger, QR SVG rendered via the queue trigger and fetched from the public blob container, two redirects logging two click rows in PostgreSQL, hit counter in Table Storage, Log Analytics + diagnostic settings — plus the call-web-app.sh smoke test (shorten → 302 redirect)
  • terraform: full deploy green, web app health OK
  • bicep: validate + deploy green, web app health OK

Note for local testing: running the variants sequentially against one emulator instance trips a known emulator issue where a deleted Key Vault's name remains held until restart (fix in localstack/localstack-pro#8135); restarting the emulator between variants (as CI's isolation effectively does) avoids it.

Note: CI runs the released emulator image, which still follows the short link's 302 at the gateway (fix pending in localstack/localstack-pro#8135). The smoke test therefore accepts the followed response when the click is verifiably recorded, and asserts the strict 302 on emulator builds that include the fix.

Related

  • localstack/localstack-pro#8135 — emulator parity fixes surfaced while building this sample

…vices

Linklet, a Flask URL shortener with an event-driven Functions worker, wired
through Web App, Functions, Storage (table/queue/blob), Key Vault, Service
Bus, PostgreSQL flexible server, a shared user-assigned managed identity and
Log Analytics. Every shortened link crosses 4-6 services in one causal chain,
so a regression in any one service breaks an observable user outcome.

Ships all three deployment variants (Azure CLI scripts, Terraform, Bicep),
an 8-step validation script that walks the full chain, and registration in
run-samples.sh and the README outline.
scripts/deploy.sh persists the generated PostgreSQL admin password to
scripts/.last_deploy.env for validate.sh and re-runs; the existing .env
patterns do not match that filename, so an accidental 'git add -A' after
a deploy would commit a credential. The pattern also covers the
function-app-front-door sample's .last_deploy_all.env for future runs
(its already-tracked copy contains only resource names).
CI runs the released emulator image, which follows the short link's 302
at the gateway (fixed in localstack/localstack-pro#8135) so the client
sees the followed response instead of the redirect. Accept that in the
smoke test as long as the click was recorded on the link; the strict 302
path applies on emulator builds that include the fix. validate.sh already
asserted the effect (click rows in PostgreSQL) rather than the status
code; document why.
@localstack/lstk 0.20.0 (published 2026-07-30 11:10 UTC) fails its
emulator probe against the Azure emulator image: 'lstk az
start-interception' reports 'LocalStack Azure Emulator is not running'
while the container is healthy and serving requests. Since the workflow
installed lstk unpinned, every shard after the publish rolled the dice
on the new probe, failing ~60% of jobs across all PRs (runs green
yesterday on 0.19.0 fail today unchanged; the emulator image boots
cleanly outside CI). Pin to 0.19.0 until lstk fixes the detection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant