Skip to content

feat: meshstack_building_block resource + meshstack_building_blocks data source (building block v3)#208

Merged
grubmeshi merged 8 commits into
mainfrom
feature/building-block-v3
Jul 2, 2026
Merged

feat: meshstack_building_block resource + meshstack_building_blocks data source (building block v3)#208
grubmeshi merged 8 commits into
mainfrom
feature/building-block-v3

Conversation

@grubmeshi

@grubmeshi grubmeshi commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Adds the meshstack_building_block resource (v3, preview API) for managing Building Blocks via the meshObject API.

What it delivers

  • Generic, typed inputs via jsonencode(...); sensitive inputs via a sensitive block with secret_version-controlled rotation.
  • In-place version upgrade by changing building_block_definition_version_ref.uuid.
  • moved support from meshstack_buildingblock (v1) and meshstack_building_block_v2.
  • Status surfaced — status.latest_run_uuid (latest modifying run) and the new computed status.latest_dry_run_uuid; runs awaited with run-log diagnostics on failure, with a configurable timeouts block (create/update/delete).

Behavior contract

  • Replacement: only target_ref.* forces replacement (you cannot move a Building Block to another tenant/workspace). display_name and inputs update in place. parent_building_blocks change only as part of a version upgrade — changing them on their own forces replacement.
  • Reruns: a run is triggered on a version change, an input change, a sensitive-input rotation (secret_version bump), a content_hash change, or a parent change carried by a version upgrade; a rename or a no-op does not. An update that supplies a previously-missing input (unblocking a block parked in WAITING_FOR_OPERATOR_INPUT) awaits the resulting run instead of returning early.
  • Partial / shared input ownership: a configuration manages only the inputs it declares in spec.inputs; an input set by another party but omitted is preserved server-side and surfaced read-only in all_inputs, not as drift. This lets a platform operator manage operator inputs while the consumer owns user inputs, each declaring only its own.
  • Upgrades: only to the latest released version of the same definition.
  • Sensitive inputs: use the sensitive block iff the definition declares the input sensitive; a moved migration warns to re-supply the secret (it cannot travel through state).
  • A version change on a non-completed block, and operator inputs set by a non-operator key, surface clear errors instead of raw conflicts or silent drift.

Data source: meshstack_building_blocks

Adds a read-only, filterable companion list data source (backed by the same v2-preview list endpoint). Each returned block mirrors the resource schema (metadata/spec/status/all_inputs); sensitive inputs are surfaced as a hash only.

  • Filters: workspace_identifier, project_identifier, platform_identifier, name, definition_uuid, version_uuid, version_number (lenient v1/1), tenant_uuid, target_kind, status, lifecycle_states (repeated param; empty ⇒ all), and the platform-operator scope selectors managed_by_definition_uuid / managed_by_workspace_identifier (MANAGED_BUILDINGBLOCK_LIST).
  • version_number filtering requires the paired meshfed change (meshcloud/meshfed-release#10063).

What it enables — app team & operator use cases

A local end-to-end demo (operator → app team → cross-workspace upgrade) exercises the new building blocks this resource unlocks:

App team (workspace-scoped consumer)

  • Self-serves a building block from a released definition discovered by name (meshstack_building_blocks / meshstack_building_block_definitions data sources), pinning to a chosen version.
  • Owns only its own inputs: it declares user inputs; operator inputs and any inputs set by others are preserved server-side and surfaced read-only in all_inputs, never as drift.
  • Cannot change the definition version (operator/admin-only — a self-attempted upgrade is rejected 403) and cannot see run logs when the definition has run_transparency = false (status.latest_run_uuid comes back null).
  • Reconciles an external upgrade: when the operator bumps the version cross-workspace, the app team sees it as drift and accepts it by repinning — the block is updated in place, not destroyed/recreated.

Platform operator (definition owner)

  • Authors and tests a definition in its own workspace with a real sensitive input decrypted end-to-end before exposing it.
  • Editing a draft's module re-runs the existing test block in place via content_hash (no replace, no teardown), surfacing the failing run's logs as the definition owner even when transparency is off.
  • Adopts and upgrades app-team blocks cross-workspace with a MANAGED_… key: import blocks keyed off the data source pull each block made from its definition into operator state, then a pure version bump upgrades them — without owning, and never deleting them (teardown uses lifecycle { destroy = false } to forget, not delete).
  • A defaulted operator input lands automatically on upgrade (empty inputs = {} → backend fills the default), and the app team's user inputs (including the sensitive one) are left untouched.

Also includes

  • meshstack_landingzone: spec.platform_ref and spec.mandatory_building_block_refs/spec.recommended_building_block_refs now accept a referenced resource's computed ref directly (e.g. platform_ref = meshstack_platform.example.ref); kind is optional rather than read-only, so assigning a full ref object no longer fails.
  • meshObject UUID references now validate at plan time: a ref object that is provided but missing its uuid is rejected up front (instead of only failing against the backend), while an assigned computed .ref — whose uuid is unknown until apply — keeps working. Applies to the landingzone building-block refs and the building block definition's dependencies / integration_ref.

Backend counterpart: meshcloud/meshfed-release#10063.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

📊 Test Coverage

Scope Coverage
Unit tests (mock client) 74.8%
Combined (unit + acceptance) 80.4% — ✅ acceptance passed
Uncovered functions (combined run)
github.com/meshcloud/terraform-provider-meshstack/client/api_key_permissions.go:225:							AllApiKeyPermissions				0.0%
github.com/meshcloud/terraform-provider-meshstack/client/buildingblock.go:97:								Delete						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/client.go:48:									NewApiTokenAuthorization			0.0%
github.com/meshcloud/terraform-provider-meshstack/client/internal/logging.go:27:							Debug						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/internal/logging.go:31:							Info						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/internal/logging.go:35:							Warn						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/internal/retry.go:225:								Close						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/internal/retry.go:246:								Write						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/project_group_binding.go:27:							Read						0.0%
github.com/meshcloud/terraform-provider-meshstack/client/project_group_binding.go:31:							Create						0.0%

Combined with go tool covdata merge over the unit and acceptance coverage data. The acceptance suite runs ./internal/provider against the live backend; coverage is attributed across all packages (-coverpkg=./...).

@grubmeshi grubmeshi force-pushed the feature/docker-acceptance-tests branch from 373210e to d6be974 Compare June 24, 2026 12:15
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch from c2be4be to afc625e Compare June 24, 2026 12:15
@grubmeshi grubmeshi force-pushed the feature/docker-acceptance-tests branch from d6be974 to 40e598c Compare June 24, 2026 12:32
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch from afc625e to 492b794 Compare June 24, 2026 12:32
Base automatically changed from feature/docker-acceptance-tests to main June 24, 2026 19:39
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch 3 times, most recently from 6666c94 to 1aab4ae Compare June 25, 2026 05:55
@grubmeshi grubmeshi requested a review from Copilot June 25, 2026 06:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the new preview meshstack_building_block (v3) Terraform resource backed by the meshObject API, including run awaiting/diagnostics, sensitive input rotation semantics, and state migration from legacy building block resources. It also refactors the client HTTP layer and expands test/mocking infrastructure to support the new building block workflows.

Changes:

  • Introduces meshstack_building_block resource with run await + rerun gating (inputs, content hash, parents, secret rotation) and moved-state migrations from v1/v2.
  • Adds supporting validators, secret hash-only type/schema, and shared converters for polymorphic JSON (clientTypes.Any) handling.
  • Updates landing zone ref handling, client HTTP internals, mocks, examples, docs, and changelog.

Reviewed changes

Copilot reviewed 67 out of 81 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/validators/discriminated_attributes_validator.go New object validator for discriminator-selected attributes.
internal/types/secret/secret.go Adds HashOnly + secret rotation detection helpers.
internal/types/secret/secret_schema_resource.go Adds read-only secret (hash-only) schema helper.
internal/provider/testdata/tf-building-block/refs/heads/main Bare git repo fixture ref for acc tests.
internal/provider/testdata/tf-building-block/README.md Documents bare git repo fixture usage/editing.
internal/provider/testdata/tf-building-block/info/exclude Bare git repo metadata fixture.
internal/provider/testdata/tf-building-block/HEAD Bare git repo HEAD fixture.
internal/provider/testdata/tf-building-block/config Bare git repo config fixture.
internal/provider/service_instance_data_source.go Switches to shared clientTypes.Any converter helper.
internal/provider/schema_utils.go Removes now-unused BB definition ref helper.
internal/provider/provider.go Registers v1/v2/v3 building block resources.
internal/provider/provider_test.go Adds helper skip functions for mixed-mode steps.
internal/provider/landingzone_resource.go Accepts full ref objects; kind optional+validated.
internal/provider/git_http_server_test.go Smart-HTTP server for git-based module fixture.
internal/provider/converter_client_type_any.go Shared bidirectional converter for clientTypes.Any.
internal/provider/buildingblock_resource.go Renames legacy v1 resource impl + deprecates it.
internal/provider/buildingblock_resource_test.go Renames v1 acc test to match legacy resource symbol.
internal/provider/building_block_v2_resource.go Deprecates v2; aligns schema + IO typing changes.
internal/provider/building_block_v2_data_source.go Aligns v2 DS status docs + input handling.
internal/provider/building_block_v2_data_source_test.go Adds subtests + sensitive-input hash assertion.
internal/provider/building_block_resource.go New v3 meshstack_building_block resource implementation.
internal/provider/building_block_resource_await_test.go Unit tests for await-run behavior (polling/warnings).
internal/provider/building_block_definition_resource_model.go Reuses shared SecretOrAny converters; cleanup.
internal/provider/acctest/testconfig/build_landingzone.go Uses computed ref objects in test builders.
internal/provider/acctest/testconfig/build_building_block.go New test builder for v3 building blocks.
internal/clientmock/mock_client.go Adds run client; shares stores across BB clients.
internal/clientmock/mock_buildingblock.go Reworks v1 mock to map onto shared v2/v3 store.
internal/clientmock/mock_buildingblock_v2.go Removes old v2 mock client implementation.
internal/clientmock/mock_building_block_v2.go New v2/v3 mock with patch semantics + runs.
internal/clientmock/mock_building_block_run.go Mock run log retrieval client.
internal/clientmock/mock_building_block_definition.go Mock building block definition client.
internal/clientmock/mock_building_block_definition_version.go Mock BBD version client incl. manual output behavior.
go.sum Adds timeouts module checksums.
go.mod Adds terraform-plugin-framework-timeouts dependency.
examples/resources/meshstack_building_block/test-support_tenant_migration_bbd.tf Fixture BBD for v1→v3 migration test.
examples/resources/meshstack_building_block/test-support_tenant_migration_bb.tf Fixture BB for v1→v3 migration test.
examples/resources/meshstack_building_block/test-support_other_provider.tf Test-only secondary provider config.
examples/resources/meshstack_building_block/test-support_moved_from_v2.tf Moved-block fixture for v2→v3 migration.
examples/resources/meshstack_building_block/test-support_moved_from_v1.tf Moved-block fixture for v1→v3 migration.
examples/resources/meshstack_building_block/test-support_07_non_updateable.tf Fixture BBD for non-updateable input behavior.
examples/resources/meshstack_building_block/test-support_04_sensitive_user_input.tf Fixture BB with sensitive inputs.
examples/resources/meshstack_building_block/test-support_04_sensitive_user_input_bbd.tf Fixture BBD for sensitive input scenarios.
examples/resources/meshstack_building_block/test-support_03_operator_inputs.tf Fixture BBD covering operator inputs.
examples/resources/meshstack_building_block/test-support_02_tenant.tf Tenant-level BBD fixture for tests.
examples/resources/meshstack_building_block/test-support_01_workspace.tf Workspace-level BBD fixture for tests.
examples/resources/meshstack_building_block/resource_02_tenant.tf Registry example: tenant-level v3 BB.
examples/resources/meshstack_building_block/resource_01_workspace.tf Registry example: workspace-level v3 BB.
examples/resources/meshstack_building_block/import-by-string-id.tf Import example for v3 BB.
docs/resources/landingzone.md Regenerated docs reflecting ref/kind changes.
docs/resources/building_block.md New generated registry docs for v3 BB.
docs/resources/building_block_v2.md Regenerated v2 docs with updated status enum text.
docs/data-sources/building_block_v2.md Regenerated v2 DS docs with updated status enum text.
client/types/clienttypes.go Clarifies secret plaintext/hash semantics.
client/internal/options.go Adds WithPathElems, exports WithAccept.
client/internal/mesh_object_client.go Refactors to DoAuthorizedRequest + options support.
client/internal/http_error.go Adds IsConflict() helper.
client/internal/http_client.go Introduces DoRequest/DoAuthorizedRequest, path elems.
client/internal/http_client_test.go Updates tests for new request helpers and semantics.
client/internal/auth.go Switches auth flow to new DoRequest.
client/client.go Extracts mesh version check + adds run client.
client/client_kind.go Adds meshObject kind for building block runs.
client/buildingblock_v2.go Removes legacy v2 building block client/types.
client/buildingblock_v2_test.go Removes legacy v2 tests.
client/building_block_v2.go New v2-preview building block client/types + enums.
client/building_block_v2_test.go New tests for create/deletion success semantics.
client/building_block_runner.go Adds runner client/types (preview).
client/building_block_run.go Adds run log retrieval client/types.
client/building_block_definition.go Adds definition client/types (preview).
client/building_block_definition_version.go Adds version client/types + enums (preview).
client/building_block_definition_version_test.go Adds JSON unmarshal tests for sensitive variants.
client/building_block_definition_version_implementation.go Adds implementation polymorphism (manual/terraform/etc.).
CHANGELOG.md Adds v0.23.0 release notes for BB v3 + landingzone changes.
.golangci.yml Allows framework-timeouts dependency.
.agents/skills/new-resource-datasource/SKILL.md Documents review conventions (response pointers, secret mock behavior).

Comment thread client/building_block_v2.go
Comment thread internal/types/secret/secret.go
Comment thread internal/provider/git_http_server_test.go
Comment thread internal/provider/acctest/testconfig/build_building_block.go
Comment thread internal/provider/acctest/testconfig/build_building_block.go Outdated
@grubmeshi grubmeshi requested a review from nroi June 25, 2026 07:11
@grubmeshi grubmeshi changed the title feat: meshstack_building_block resource (building block v3) feat: meshstack_building_block resource + meshstack_building_blocks data source (building block v3) Jun 25, 2026
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch 5 times, most recently from f36ac15 to 5ab60ac Compare June 25, 2026 20:04
@grubmeshi grubmeshi requested a review from Copilot June 25, 2026 20:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 77 out of 90 changed files in this pull request and generated 1 comment.

Comment thread internal/provider/landingzone_resource.go
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch 2 times, most recently from 2def267 to a0a3364 Compare June 26, 2026 10:10
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
Comment thread docs/resources/building_block.md Outdated
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch from a0a3364 to 115b81f Compare June 26, 2026 15:39
Comment thread internal/clientmock/mock_building_block_v2.go Outdated
Comment thread internal/clientmock/mock_buildingblock.go Outdated
Comment thread internal/provider/building_block_resource.go Outdated
Comment thread internal/provider/building_block_resource.go Outdated
Comment thread internal/provider/building_block_resource.go Outdated
Comment thread CHANGELOG.md
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch from 115b81f to ed46c05 Compare July 2, 2026 08:51
grubmeshi and others added 4 commits July 2, 2026 11:47
The landing zone's spec.platform_ref and mandatory/recommended
building_block_refs declared `kind` as read-only (Computed only), so
assigning a referenced resource's computed `ref` inline — e.g.
`platform_ref = meshstack_platform.example.ref` — failed with "Cannot set
value for this attribute as the provider has marked it as read-only".

Make `kind` optional+computed with its single valid value as default and a
OneOf validator, matching location_ref / platform_type_ref. The building
block refs now reuse the shared meshUuidRefAttribute helper (uuid
optional+computed) so a full ref object also works as a set element whose
referenced resource is created in the same apply; the bespoke
meshBuildingBlockDefinitionRefAttribute is removed. The landing zone test
builder now assigns the platform and definition refs inline as a regression
guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
meshUuidRefAttribute keeps uuid Optional+Computed so a whole computed .ref object
(whose uuid is unknown until apply) can be assigned and the backend can default an
omitted ref — which also let a ref be provided without a uuid, failing only later
against the backend.

Guard such refs with meshUuidRefValidators (objectvalidator.AlsoRequires on uuid): a
provided ref object must carry its uuid, while an assigned computed .ref still passes
(AlsoRequires treats an unknown value as configured). Wire it into the user-supplied
ref sites — landingzone mandatory/recommended_building_block_refs and the building
block definition's dependencies and integration_ref; runner refs keep optional uuid
(the backend fills the shared-runner default).

Also reuse the shared kind+uuid ref helpers more widely (addressing the helper TODO):
the platform and tenant_v4 resources' computed .ref outputs now use
meshUuidRefOutputAttribute. Bespoke refs (the discriminated target_ref, the
RequiresReplace platform_ref, the uuid-only version_ref) keep their own schema; data
source refs use the datasource schema package and are out of scope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces doRequest/doAuthorizedRequest + GetMeshInfo/unmarshalBody helpers
with a generic DoRequest[R]/DoAuthorizedRequest[R] API and adds WithPathElems
JoinPath support. Strengthens the PATCH non-retry test to assert exactly one
attempt against a retryable 502 response.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rename all non-v1 building-block files from buildingblock_* to
building_block_* to match the resource name meshstack_building_block.
De-collide v1 symbols (NewBuildingblockResource / buildingblockResource)
to free the CamelCase names for the new resource, and update the v1
deprecation message target from meshstack_building_block_v3 to
meshstack_building_block. Rename-only; no behaviour change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch from ed46c05 to b18a09e Compare July 2, 2026 09:47
grubmeshi and others added 4 commits July 2, 2026 13:09
… topology

The acceptance suite gained real terraform-implementation BBDs (the committed
tf-building-block fixture served over git smart-HTTP) plus an end-to-end
sensitive-input decryption proof, so it now requires the full multiplexer
fan-out — exactly what local-dev-stack and CI (.github/workflows/test.yml) run.

- meshstack-services: drop the obsolete "run a single manual no-op runner"
  topology; defer to local-dev-stack's mux + tf + manual fan-out and explain
  why both real runners are required.
- scratch-config-testing: the tf-block-runner already runs behind the mux as
  part of the standard fan-out, so terraform-impl BBDs need no runner swap;
  sensitive inputs decrypt out of the box (drop the stale decrypt gotcha).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the meshstack_building_block resource (v3), superseding v2 with:
- In-place updates via PUT + explicit trigger-run; no destroy+recreate.
  Changes to content_hash, inputs, or parent_building_blocks trigger a
  rerun; in-place version upgrades are supported via PUT
- Sensitive input support (value_string_sensitive/value_code_sensitive),
  preserving secrets across upgrades and avoiding phantom drift from
  null USER_INPUT rows
- wait_for_completion: polls up to 30 min; WAITING_FOR_* states produce
  actionable warnings; preserved across reads/import (null vs false)
- run-log diagnostics: on poll failure addRunFailureDiagnostics surfaces
  step-level logs as Terraform warnings
- MoveState from meshstack_buildingblock (v1) and meshstack_building_block_v2
- target_ref validators (meshTenant requires uuid, meshWorkspace requires name)
- Soft-delete-aware Read: a deleted building block is removed from state
- Hardens the building_block_v2 client/mock/data-source: nil-pointer
  guards, ABORTED + nil Status handling in CreateSuccessful, sensitive
  input reads in the v2 data source, mock deep-copy fidelity
- Fixes CHANGELOG, truncated all_inputs.value doc, purge description,
  operator-input test assertions, secret docs version reference
- Regenerates provider docs (building_block.md replaces building_block_v3.md)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a read-only, filterable list data source backed by the v2-preview
building block list endpoint. Each entry mirrors the meshstack_building_block
resource (metadata/spec/status/all_inputs); sensitive inputs are surfaced as a
hash only, reusing the secret data-source schema.

Filters: workspace/project/platform identifier, name, definition_uuid,
version_uuid, version_number (lenient "v1"/"1"), tenant_uuid, target_kind,
status, lifecycle_states (repeated query param; empty => all), and the
platform-operator scope selectors managed_by_definition_uuid /
managed_by_workspace_identifier (MANAGED_BUILDINGBLOCK_LIST).

Adds a List method + filter struct on the building block v2 client, a
WithUrlQueryValues option for repeated query params, and a mock List
implementation. Reuses the resource's all_inputs mapping via an extracted
buildAllInput helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sensitive user inputs (STRING and CODE) sent by the deprecated
meshstack_building_block_v2 resource omitted IsSensitive on the outbound
MeshBuildingBlockInput. Because MeshBuildingBlockInput.UnmarshalJSON demotes a
secret from SecretOrAny.X to a plain SecretOrAny.Y when IsSensitive is false,
the secret was stripped on the mock client's JSON round-trip and the plaintext
leaked into value_string as a raw map instead of surfacing the backend hash.

Set IsSensitive on sensitive inputs so the secret stays in the X variant,
matching what the v3 resource does symmetrically via buildingBlockConverterOptions.
The real backend re-derives sensitivity from the definition, so this is a
correctness/mock-fidelity fix with no user-facing behavior change (no CHANGELOG
entry). Re-enables the previously mock-skipped v2 sensitive-input tests to run
in both mock and acceptance modes, asserting the surfaced value is the hash and
not the plaintext.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@grubmeshi grubmeshi force-pushed the feature/building-block-v3 branch from b18a09e to a90d7be Compare July 2, 2026 11:11
@grubmeshi grubmeshi merged commit 11af8ef into main Jul 2, 2026
5 checks passed
@grubmeshi grubmeshi deleted the feature/building-block-v3 branch July 2, 2026 12:58
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.

3 participants