feat(meshstack): add composition building block - #247
Conversation
Reference implementation of the composition pattern: a building block that provisions meshObjects through the meshStack API with its run's ephemeral API key rather than cloud resources. It creates a building block definition and a building block from it, which meshStack attributes to the creating block, so it doubles as an end-to-end check of that provenance with no cloud platform involved. The created definition runs the hub's `link` building block instead of an implementation of its own — `link` provisions nothing but a terraform_data and needs neither a cloud provider nor an operator, which keeps the whole chain automatic. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Scorecard Check
📊 meshstack-hub Module Scorecard
📋 Per-Module Category SummaryScore per category per building block.
Core Structure — ✅ all passingBasic module file structure and documentation — applies to 1 modules
Core Structure — Summary
Integration — ✅ all passingmeshstack_integration.tf conventions — applies to 1 modules
Integration — Summary
Azure Backplane — not applicableAzure UAMI-based automation principal conventions — applies to 0 modules No applicable modules. STACKIT Backplane — not applicableSTACKIT WIF-based automation principal conventions — applies to 0 modules No applicable modules. Testing — some checks failingEnd-to-end test coverage — applies to 1 modules
Testing — Summary
|
|
This pull request is automatically being deployed by Amplify Hosting (learn more). |
The created definition's version stays DRAFT: releasing needs admin approval, which the run's ephemeral key — a plain workspace key — cannot obtain. So draft = false left the version DRAFT anyway and version_latest_release null, failing the apply with "Attempt to get attribute from null value". Declare the draft honestly and reference version_latest instead, which a draft permits because the definition and the building block's target are the same workspace (BuildingBlockCreationValidator.requireAccess's selfOwning branch). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…tinctly The composition and the objects it created were both called "Composition Demo", which made the two building block definitions in the panel hard to tell apart. Name the composition "Composition Demo" and the objects it creates after their implementation, "Link", via a link_name input defaulting to that. Renames the `name` input to `link_name` so it pairs with `link_url` and reads as belonging to the created objects rather than to the composition itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two teardown failures. link_name had no default, so a destroy run of a building block whose stored inputs predate the rename from `name` aborted with "No value for required variable". A destroy only has to delete the created meshObjects, and their display names have no bearing on that, so default it. The created definition used deletion_mode = DELETE, which schedules a deprovisioning run for the created building block on teardown. That run cannot start until the composition's own destroy run returns, deadlocking wherever the runner pool has a single worker. PURGE skips it and leaks nothing, since `link` provisions no infrastructure. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
||
| spec = { | ||
| display_name = var.link_name | ||
| description = "Link building block definition created by the Composition Demo building block." |
There was a problem hiding this comment.
d: parameterize this already so that it shows some dummy link, for example "this is an element of a composition"
| # which satisfies BuildingBlockCreationValidator.requireAccess's `selfOwning` branch. | ||
| draft = true | ||
|
|
||
| # PURGE, not DELETE: DELETE would schedule a deprovisioning run for the building block below when |
There was a problem hiding this comment.
d: I think that's not fully correct, and just a matter of correct depends_on because tofu doesn't know the BBD -> BB topology inside meshStack
| @@ -0,0 +1,96 @@ | |||
| --- | |||
| name: Composition Demo | |||
There was a problem hiding this comment.
d: actually this is a demo of an "architecture composition" which is an advanced use case of compositions. A plain composition is sth like the AKS StarterKit that only deploys application team resources (projects, tenants, building blocks)
This is a "reference architecture" composition that also deploys platform team artifacts like BBDs, (LZs forthcomming) etc.
Adds
modules/meshstack/composition— a reference implementation of the composition pattern: a building block that provisions meshObjects through the meshStack API with its run's ephemeral API key, rather than cloud resources.It creates a
meshBuildingBlockDefinitionin the consuming workspace and ameshBuildingBlockfrom that definition. Because both are created with the ephemeral key, meshStack records the composition as their creator and surfaces "created by building block" provenance on each — so this module doubles as an end-to-end check of that provenance with no cloud platform involved.Reuses
linkrather than inventing an implementationThe created definition runs the hub's
linkbuilding block.linkprovisions nothing but aterraform_dataand needs neither a cloud provider nor an operator, which keeps the whole chain automatic — no manual step anywhere.It declares
link's input/output wiring inline instead of sourcingmodules/meshstack/linkas a submodule: a submodulesourceneeds?ref=${...}interpolation, which requires aconstvariable, andconstvalues may not come from a runtime building-block input.hub_git_refis passed as a static input from the composition's ownvar.hub.git_refso the created definition cloneslinkfrom the same hub revision.Notes for review
wait_for_completion = falseon the created building block is deliberate. That run is itself a terraform run, and a stack with a single terraform runner cannot start it before this run returns — waiting would deadlock. Provenance is recorded at creation time, so nothing depends on the result.permissions, keeping it within meshStack's privilege escalation guard.e2e/tier is missing. Happy to add one if you'd like it covered by hub CI.tofu fmtandtofu validateclean;terraform-docsgenerated.Status
Draft — exercised against a local dev stack, not yet against a shared environment.
🤖 Generated with Claude Code