diff --git a/modules/aws/agentic-coding-sandbox/buildingblock/README.md b/modules/aws/agentic-coding-sandbox/buildingblock/README.md index 39f3df46..9b65d92c 100644 --- a/modules/aws/agentic-coding-sandbox/buildingblock/README.md +++ b/modules/aws/agentic-coding-sandbox/buildingblock/README.md @@ -19,7 +19,7 @@ Before deploying this building block: 2. ✅ Import [AWS Budget Alert Building Block](https://hub.meshcloud.io/definitions/aws-budget-alert) from meshStack Hub into your meshStack 3. ✅ Import [AWS Enable Opt-In Region building block](https://hub.meshcloud.io/definitions/aws-opt-in-region) from meshStack Hub into your meshStack 4. ✅ Configure the `composition_config_yaml` with the correct UUIDs and identifiers -5. ✅ Configure an meshStack API key for the composition with admin permissions for projects, tenants, and building blocks +5. ✅ Configure an meshStack API key for the composition with admin permissions for projects, tenants, and building blocks, and with permission to list platforms — the composition resolves the configured platform identifier to a platform reference ## What This Building Block Does @@ -40,16 +40,14 @@ The `composition_config_yaml` variable must contain: ```yaml landing_zone: - landing_zone_identifier: "your-bedrock-landing-zone-id" # From your AWS Bedrock LZ deployment - platform_identifier: "your-aws-platform-id" # Your AWS platform identifier + landing_zone_identifier: "your-bedrock-landing-zone-id" # From your AWS Bedrock LZ deployment + platform_identifier: "your-aws-platform.your-location" # Full platform identifier, . budget_alert_building_block: - definition_uuid: "uuid-from-meshstack-hub" # UUID from AWS Budget Alert BB deployment - definition_version: 1 # Version from your deployment + definition_version_uuid: "uuid-from-meshstack" # Version UUID of the AWS Budget Alert BBD enable_eu_south_2_region_building_block: - definition_uuid: "uuid-from-meshstack-hub" # UUID from AWS Enable Opt-In Region BB deployment - definition_version: 1 # Version from your deployment + definition_version_uuid: "uuid-from-meshstack" # Version UUID of the AWS Enable Opt-In Region BBD project: # Optional project configuration default_tags: @@ -60,10 +58,10 @@ project: # Optional project configurati ### How to Get the Required Values -1. **Landing Zone Identifiers**: Check your AWS platform configuration in meshStack -2. **Building Block UUIDs**: After importing building blocks from meshStack Hub, find their UUIDs in: - - meshStack Admin Area → Building Block Definitions - - Or via meshStack API: `GET /api/meshobjects/meshbuildingblockdefinitions` +1. **Landing Zone and Platform Identifiers**: Check your AWS platform configuration in meshStack. The platform identifier is the full `.`. +2. **Building Block Definition Version UUIDs**: After importing the building blocks from meshStack Hub, look up the UUID of the definition *version* you want to provision (not the UUID of the definition itself) in: + - meshStack Admin Area → Building Block Definitions → the definition's version + - Or via meshStack API: `GET /api/meshobjects/meshbuildingblockdefinitions`, and read the `uuid` of the version ## User Inputs @@ -77,7 +75,7 @@ End users provide: | Name | Version | |------|---------| -| [meshstack](#requirement\_meshstack) | >= 0.7.1 | +| [meshstack](#requirement\_meshstack) | >= 0.24.3 | ## Modules @@ -87,18 +85,19 @@ No modules. | Name | Type | |------|------| -| [meshstack_buildingblock.budget_alert](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/buildingblock) | resource | -| [meshstack_buildingblock.enable_eu_south_2_region](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/buildingblock) | resource | +| [meshstack_building_block.budget_alert](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource | +| [meshstack_building_block.enable_eu_south_2_region](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource | | [meshstack_project.sandbox](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/project) | resource | | [meshstack_tenant.sandbox](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/tenant) | resource | | [random_string.suffix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [meshstack_platforms.available](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/data-sources/platforms) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [budget\_amount](#input\_budget\_amount) | Monthly budget amount. You will receive an alert when the budget is exceeded. | `number` | n/a | yes | -| [composition\_config\_yaml](#input\_composition\_config\_yaml) | YAML configuration for landing zone and building blocks. Expected structure:
yaml
landing_zone:
landing_zone_identifier: "my-landing-zone"
platform_identifier: "my-platform"
budget_alert_building_block:
definition_uuid: "uuid-here"
definition_version: 1
enable_eu_south_2_region_building_block:
definition_uuid: "uuid-here"
definition_version: 1
project:
default_tags:
environment: "sandbox"
cost_center: "engineering"
owner_tag_key: "project_owner" # optional, if not set no project owner tag will be set
| `string` | n/a | yes | +| [composition\_config\_yaml](#input\_composition\_config\_yaml) | YAML configuration for landing zone and building blocks. Expected structure:
yaml
landing_zone:
landing_zone_identifier: "my-landing-zone"
platform_identifier: "my-platform.my-location" # full platform identifier, .
budget_alert_building_block:
definition_version_uuid: "uuid-here" # uuid of the building block definition *version* to provision
enable_eu_south_2_region_building_block:
definition_version_uuid: "uuid-here"
project:
default_tags:
environment: "sandbox"
cost_center: "engineering"
owner_tag_key: "project_owner" # optional, if not set no project owner tag will be set
| `string` | n/a | yes | | [username](#input\_username) | meshStack username of the project contact. This should be an email. | `string` | n/a | yes | | [workspace\_identifier](#input\_workspace\_identifier) | Identifier for the owning workspace | `string` | n/a | yes | diff --git a/modules/aws/agentic-coding-sandbox/buildingblock/main.tf b/modules/aws/agentic-coding-sandbox/buildingblock/main.tf index 84a08438..3b7bac33 100644 --- a/modules/aws/agentic-coding-sandbox/buildingblock/main.tf +++ b/modules/aws/agentic-coding-sandbox/buildingblock/main.tf @@ -2,10 +2,11 @@ provider "meshstack" { # configured via env vars } -## Note: all of this is arguably a not so pretty workaround for missing data objects in meshStack's terraform provider -## to locate the right BBDs and LZs. -## But for now this provides a suitable way to have a single platform operator input for configuring the BBD after -## importing it from meshStack Hub, so we'll run with this approach for now until we discover something better. +## Note: this composition is configured through a single flat YAML input so that a platform operator can +## configure it in one place right after importing it from meshStack Hub. It is written in the most +## human-readable form the provider can actually resolve: the platform and the landing zone are named by +## their identifiers, while the building block definition versions have to be uuids because the provider +## has no data source that resolves a definition (or one of its versions) by uuid or by name. locals { # Parse YAML configuration - validation is now handled at the variable level @@ -15,11 +16,8 @@ locals { landing_zone_identifier = local.config.landing_zone.landing_zone_identifier platform_identifier = local.config.landing_zone.platform_identifier - budget_alert_definition_uuid = local.config.budget_alert_building_block.definition_uuid - budget_alert_definition_version = local.config.budget_alert_building_block.definition_version - - enable_eu_south_2_region_definition_uuid = local.config.enable_eu_south_2_region_building_block.definition_uuid - enable_eu_south_2_region_definition_version = local.config.enable_eu_south_2_region_building_block.definition_version + budget_alert_definition_version_uuid = local.config.budget_alert_building_block.definition_version_uuid + enable_eu_south_2_region_definition_version_uuid = local.config.enable_eu_south_2_region_building_block.definition_version_uuid # Project configuration with safe defaults project_config = try(local.config.project, {}) @@ -64,62 +62,71 @@ resource "meshstack_project" "sandbox" { } +# meshstack_tenant runs on the meshTenant v4 API, which references its platform by uuid. Platform +# operators configure this composition with a platform identifier, so look the platform up by its +# full identifier (`.`) and reuse the ref the data source computes. +data "meshstack_platforms" "available" {} + +locals { + platform_ref = one([ + for platform in data.meshstack_platforms.available.platforms : platform.ref + if platform.identifier == local.platform_identifier + ]) +} + resource "meshstack_tenant" "sandbox" { metadata = { - owned_by_workspace = meshstack_project.sandbox.metadata.owned_by_workspace - owned_by_project = meshstack_project.sandbox.metadata.name - platform_identifier = local.platform_identifier + owned_by_workspace = meshstack_project.sandbox.metadata.owned_by_workspace + owned_by_project = meshstack_project.sandbox.metadata.name } spec = { - landing_zone_identifier = local.landing_zone_identifier + platform_ref = local.platform_ref + landing_zone_ref = { + name = local.landing_zone_identifier + } } -} - -# NOTE: must use bb v1 resource because v2 requires a tenant uuid -# but the tenant v4 api that delivers the uuid is not supported by our terraform provider yet -resource "meshstack_buildingblock" "budget_alert" { - metadata = { - definition_uuid = local.budget_alert_definition_uuid - definition_version = local.budget_alert_definition_version - tenant_identifier = "${meshstack_tenant.sandbox.metadata.owned_by_workspace}.${meshstack_tenant.sandbox.metadata.owned_by_project}.${meshstack_tenant.sandbox.metadata.platform_identifier}" + lifecycle { + precondition { + condition = local.platform_ref != null + error_message = "No platform with identifier '${local.platform_identifier}' is visible to this composition's meshStack API key. Check landing_zone.platform_identifier in composition_config_yaml and that the API key is allowed to list platforms." + } } +} + +resource "meshstack_building_block" "budget_alert" { spec = { + building_block_definition_version_ref = { + uuid = local.budget_alert_definition_version_uuid + } + display_name = "Budget Alert" + target_ref = meshstack_tenant.sandbox.ref inputs = { - budget_name = { - value_string = "Agentic Coding Budget Alert" - } - monthly_budget_amount = { - value_int = var.budget_amount - } - contact_emails = { - # just a single email for now, not a comma-separated list - value_string = var.username - } + budget_name = { value = jsonencode("Agentic Coding Budget Alert") } + monthly_budget_amount = { value = jsonencode(var.budget_amount) } + # just a single email for now, not a comma-separated list + contact_emails = { value = jsonencode(var.username) } } } } # enable spain region for the sandbox tenant because that's the only region where Anthropic's Sonnet 4 is available -resource "meshstack_buildingblock" "enable_eu_south_2_region" { - metadata = { - definition_uuid = local.enable_eu_south_2_region_definition_uuid - definition_version = local.enable_eu_south_2_region_definition_version - tenant_identifier = "${meshstack_tenant.sandbox.metadata.owned_by_workspace}.${meshstack_tenant.sandbox.metadata.owned_by_project}.${meshstack_tenant.sandbox.metadata.platform_identifier}" - } - +resource "meshstack_building_block" "enable_eu_south_2_region" { spec = { + building_block_definition_version_ref = { + uuid = local.enable_eu_south_2_region_definition_version_uuid + } + display_name = "Enable eu-south-2 region" + target_ref = meshstack_tenant.sandbox.ref inputs = { - region = { - value_single_select = "eu-south-2" - } + region = { value = jsonencode("eu-south-2") } } } } diff --git a/modules/aws/agentic-coding-sandbox/buildingblock/variables.tf b/modules/aws/agentic-coding-sandbox/buildingblock/variables.tf index 5365bd16..cc20416c 100644 --- a/modules/aws/agentic-coding-sandbox/buildingblock/variables.tf +++ b/modules/aws/agentic-coding-sandbox/buildingblock/variables.tf @@ -8,13 +8,11 @@ YAML configuration for landing zone and building blocks. Expected structure: ```yaml landing_zone: landing_zone_identifier: "my-landing-zone" - platform_identifier: "my-platform" + platform_identifier: "my-platform.my-location" # full platform identifier, . budget_alert_building_block: - definition_uuid: "uuid-here" - definition_version: 1 + definition_version_uuid: "uuid-here" # uuid of the building block definition *version* to provision enable_eu_south_2_region_building_block: - definition_uuid: "uuid-here" - definition_version: 1 + definition_version_uuid: "uuid-here" project: default_tags: environment: "sandbox" @@ -39,23 +37,13 @@ EOF } validation { - condition = can(yamldecode(var.composition_config_yaml).budget_alert_building_block.definition_uuid) && yamldecode(var.composition_config_yaml).budget_alert_building_block.definition_uuid != null - error_message = "budget_alert_building_block.definition_uuid is required in composition_config_yaml" + condition = can(yamldecode(var.composition_config_yaml).budget_alert_building_block.definition_version_uuid) && yamldecode(var.composition_config_yaml).budget_alert_building_block.definition_version_uuid != null + error_message = "budget_alert_building_block.definition_version_uuid is required in composition_config_yaml" } validation { - condition = can(yamldecode(var.composition_config_yaml).budget_alert_building_block.definition_version) && yamldecode(var.composition_config_yaml).budget_alert_building_block.definition_version != null - error_message = "budget_alert_building_block.definition_version is required in composition_config_yaml" - } - - validation { - condition = can(yamldecode(var.composition_config_yaml).enable_eu_south_2_region_building_block.definition_uuid) && yamldecode(var.composition_config_yaml).enable_eu_south_2_region_building_block.definition_uuid != null - error_message = "enable_eu_south_2_region_building_block.definition_uuid is required in composition_config_yaml" - } - - validation { - condition = can(yamldecode(var.composition_config_yaml).enable_eu_south_2_region_building_block.definition_version) && yamldecode(var.composition_config_yaml).enable_eu_south_2_region_building_block.definition_version != null - error_message = "enable_eu_south_2_region_building_block.definition_version is required in composition_config_yaml" + condition = can(yamldecode(var.composition_config_yaml).enable_eu_south_2_region_building_block.definition_version_uuid) && yamldecode(var.composition_config_yaml).enable_eu_south_2_region_building_block.definition_version_uuid != null + error_message = "enable_eu_south_2_region_building_block.definition_version_uuid is required in composition_config_yaml" } } diff --git a/modules/aws/agentic-coding-sandbox/buildingblock/versions.tf b/modules/aws/agentic-coding-sandbox/buildingblock/versions.tf index 0cc33709..c8c287c1 100644 --- a/modules/aws/agentic-coding-sandbox/buildingblock/versions.tf +++ b/modules/aws/agentic-coding-sandbox/buildingblock/versions.tf @@ -2,7 +2,7 @@ terraform { required_providers { meshstack = { source = "meshcloud/meshstack" - version = ">= 0.7.1" + version = ">= 0.24.3" } } } \ No newline at end of file