Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .agents/skills/e2e-test/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,19 @@ locals {
}
```

- Create a `meshstack_building_block_v2` resource that exercises the building block end-to-end.
- Create a `meshstack_building_block` resource that exercises the building block end-to-end.
Reference `test_context` directly (it is non-null in both modes). The provider's
`building_block_definition_version_ref` takes `{ uuid }` only — extract it explicitly.

- **Always add `depends_on = [module.<integration_module>]`** to `meshstack_building_block_v2.this`.
- **Always add `depends_on = [module.<integration_module>]`** to `meshstack_building_block.this`.
WIF federated identity providers have no Terraform dependents (nothing references their outputs),
so OpenTofu schedules their destruction in parallel with the BB delete run. This causes the BB
delete run to fail with 401s because the cloud WIF trust is already gone before the delete run
can authenticate. The explicit `depends_on` forces the BB resource (including its delete run) to
be fully destroyed before any backplane resources are torn down.

```hcl
resource "meshstack_building_block_v2" "this" {
resource "meshstack_building_block" "this" {
depends_on = [module.<integration_module>] # prevents teardown race with WIF providers
wait_for_completion = true
spec = {
Expand All @@ -158,6 +158,9 @@ resource "meshstack_building_block_v2" "this" {
kind = "meshWorkspace"
name = var.test_context.workspace
}
# inputs: one `value = jsonencode(...)` per input (jsonencode strings too, e.g.
# jsonencode("x"), jsonencode(1), jsonencode(true)). Sensitive inputs instead use
# `sensitive = { secret_value = ... }`.
inputs = { ... }
}
}
Expand Down Expand Up @@ -188,7 +191,8 @@ target_ref = {
- Name the file `<cloud>_<service>_hub.tftest.hcl` (e.g. `building_block_noop_hub.tftest.hcl`).
- Always assert `status.status == "SUCCEEDED"` as the first check.
- Assert meaningful output values (URLs, strings, booleans) to validate the building block executed
correctly.
correctly. Every output `value` is a `jsonencode`d string — read it with
`jsondecode(<res>.status.outputs["<name>"].value)` (a CODE/JSON output decodes twice).
- The same test file runs in **both** invocation modes (smoke-test via `tofu test`, foundation via
`terragrunt test`). Reference **`output.<name>`**, never `var.test_context.*` — `test_context` is
null in foundation mode and would crash the assertion.
Expand Down Expand Up @@ -255,7 +259,7 @@ node tools/debug/get-bb-run-logs.mjs "$BB_UUID"

To get the UUID from an errored test state:
```bash
tofu state show -state=errored_test.tfstate 'meshstack_building_block_v2.this' | grep uuid
tofu state show -state=errored_test.tfstate 'meshstack_building_block.this' | grep uuid
```


Expand Down Expand Up @@ -318,6 +322,6 @@ source setup-override-provider.sh
- [ ] `hub.git_ref = var.test_context.hub_git_ref` — no hardcoded `"main"`
- [ ] Version ref resolved in a `local` (`bbd_version_ref` in foundation mode, else the built module)
- [ ] `building_block_definition_version_ref = { uuid = local.version_ref.uuid }` — provider only accepts `{ uuid }`, extract it explicitly
- [ ] `meshstack_building_block_v2` has `depends_on = [module.<integration_module>]` to prevent WIF teardown race (delete run must finish before backplane resources are destroyed)
- [ ] `meshstack_building_block_v2` has `wait_for_completion = true`
- [ ] `meshstack_building_block` has `depends_on = [module.<integration_module>]` to prevent WIF teardown race (delete run must finish before backplane resources are destroyed)
- [ ] `meshstack_building_block` has `wait_for_completion = true`
- [ ] tftest asserts `status.status == "SUCCEEDED"` and key outputs (references `var.test_context.*` directly — non-null in both modes)
8 changes: 4 additions & 4 deletions modules/aks/starterkit/buildingblock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This documentation is intended as a reference documentation for cloud foundation

| Name | Version |
|------|---------|
| <a name="requirement_meshstack"></a> [meshstack](#requirement\_meshstack) | >= 0.21.0 |
| <a name="requirement_meshstack"></a> [meshstack](#requirement\_meshstack) | >= 0.23.0 |

## Modules

Expand All @@ -25,9 +25,9 @@ No modules.

| Name | Type |
|------|------|
| [meshstack_building_block_v2.github_actions_dev](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block_v2) | resource |
| [meshstack_building_block_v2.github_actions_prod](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block_v2) | resource |
| [meshstack_building_block_v2.repo](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block_v2) | resource |
| [meshstack_building_block.github_actions_dev](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource |
| [meshstack_building_block.github_actions_prod](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource |
| [meshstack_building_block.repo](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource |
| [meshstack_project.dev](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/project) | resource |
| [meshstack_project.prod](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/project) | resource |
| [meshstack_project_user_binding.creator_dev_admin](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/project_user_binding) | resource |
Expand Down
54 changes: 36 additions & 18 deletions modules/aks/starterkit/buildingblock/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ resource "meshstack_tenant_v4" "prod" {
depends_on = [meshstack_project_user_binding.creator_prod_admin]
}

resource "meshstack_building_block_v2" "repo" {
resource "meshstack_building_block" "repo" {
spec = {
building_block_definition_version_ref = {
uuid = var.github_repo_definition_version_uuid
Expand All @@ -117,31 +117,31 @@ resource "meshstack_building_block_v2" "repo" {

inputs = {
repo_name = {
value_string = local.repo_name
value = jsonencode(local.repo_name)
}
archive_repo_on_destroy = {
value_bool = var.archive_repo_on_destroy
value = jsonencode(var.archive_repo_on_destroy)
}
repo_owner = {
value_string = var.repo_admin != null ? var.repo_admin : "null"
value = jsonencode(var.repo_admin != null ? var.repo_admin : "null")
}
repo_visibility = {
value_string = var.github_repo_input_repo_visibility != null ? var.github_repo_input_repo_visibility : "private"
value = jsonencode(var.github_repo_input_repo_visibility != null ? var.github_repo_input_repo_visibility : "private")
}
use_template = {
value_bool = true
value = jsonencode(true)
}
template_owner = {
value_string = split("/", var.github_template_repo_path)[0]
value = jsonencode(split("/", var.github_template_repo_path)[0])
}
template_repo = {
value_string = split("/", var.github_template_repo_path)[1]
value = jsonencode(split("/", var.github_template_repo_path)[1])
}
}
}
}

resource "meshstack_building_block_v2" "github_actions_dev" {
resource "meshstack_building_block" "github_actions_dev" {
spec = {
building_block_definition_version_ref = {
uuid = var.github_actions_connector_definition_version_uuid
Expand All @@ -152,24 +152,24 @@ resource "meshstack_building_block_v2" "github_actions_dev" {
}
display_name = "GHA Connector Dev"
parent_building_blocks = [{
buildingblock_uuid = meshstack_building_block_v2.repo.metadata.uuid
buildingblock_uuid = meshstack_building_block.repo.metadata.uuid
definition_uuid = var.github_repo_definition_uuid
}]
inputs = {
github_environment_name = {
value_string = "development"
value = jsonencode("development")
}
additional_environment_variables = {
value_code = jsonencode({
value = jsonencode(jsonencode({
"DOMAIN_NAME" = "${local.identifier}-dev"
"AKS_NAMESPACE_NAME" = meshstack_tenant_v4.dev.spec.platform_tenant_id
})
}))
}
}
}
}

resource "meshstack_building_block_v2" "github_actions_prod" {
resource "meshstack_building_block" "github_actions_prod" {
spec = {
display_name = "GHA Connector Prod"
building_block_definition_version_ref = {
Expand All @@ -180,19 +180,37 @@ resource "meshstack_building_block_v2" "github_actions_prod" {
uuid = meshstack_tenant_v4.prod.metadata.uuid
}
parent_building_blocks = [{
buildingblock_uuid = meshstack_building_block_v2.repo.metadata.uuid
buildingblock_uuid = meshstack_building_block.repo.metadata.uuid
definition_uuid = var.github_repo_definition_uuid
}]
inputs = {
github_environment_name = {
value_string = "production"
value = jsonencode("production")
}
additional_environment_variables = {
value_code = jsonencode({
value = jsonencode(jsonencode({
"DOMAIN_NAME" = local.identifier
"AKS_NAMESPACE_NAME" = meshstack_tenant_v4.prod.spec.platform_tenant_id
})
}))
}
}
}
}

# Migrate the app-team-managed child building blocks from the deprecated
# meshstack_building_block_v2 resource to meshstack_building_block in place —
# no destroy/recreate of the live blocks.
moved {
from = meshstack_building_block_v2.repo
to = meshstack_building_block.repo
}

moved {
from = meshstack_building_block_v2.github_actions_dev
to = meshstack_building_block.github_actions_dev
}

moved {
from = meshstack_building_block_v2.github_actions_prod
to = meshstack_building_block.github_actions_prod
}
12 changes: 6 additions & 6 deletions modules/aks/starterkit/buildingblock/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ output "prod-link" {

output "github_repo_url" {
description = "URL of the created GitHub repository"
value = meshstack_building_block_v2.repo.status.outputs.repo_html_url.value_string
value = jsondecode(meshstack_building_block.repo.status.outputs.repo_html_url.value)
}

output "summary" {
Expand All @@ -23,15 +23,15 @@ output "summary" {

This starter kit has set up the following resources in workspace `${var.workspace_identifier}`:

@buildingblock[${meshstack_building_block_v2.repo.metadata.uuid}]
@buildingblock[${meshstack_building_block.repo.metadata.uuid}]

@project[${meshstack_project.dev.metadata.owned_by_workspace}.${meshstack_project.dev.metadata.name}]\
&nbsp;&nbsp;&nbsp;&nbsp;@tenant[${meshstack_tenant_v4.dev.metadata.uuid}]\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buildingblock[${meshstack_building_block_v2.github_actions_dev.metadata.uuid}]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buildingblock[${meshstack_building_block.github_actions_dev.metadata.uuid}]

@project[${meshstack_project.prod.metadata.owned_by_workspace}.${meshstack_project.prod.metadata.name}]\
&nbsp;&nbsp;&nbsp;&nbsp;@tenant[${meshstack_tenant_v4.prod.metadata.uuid}]\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buildingblock[${meshstack_building_block_v2.github_actions_prod.metadata.uuid}]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buildingblock[${meshstack_building_block.github_actions_prod.metadata.uuid}]

---

Expand All @@ -52,7 +52,7 @@ Trigger a deployment by:
- Pushing to the **main** branch (deploys to **dev**)
- Merging **main** into **release** via PR (deploys to **prod**)

View deployment status: [GitHub Actions](${meshstack_building_block_v2.repo.status.outputs.repo_html_url.value_string}/actions/workflows/k8s-deploy.yml)
View deployment status: [GitHub Actions](${jsondecode(meshstack_building_block.repo.status.outputs.repo_html_url.value)}/actions/workflows/k8s-deploy.yml)

- **Dev**: [${local.identifier}-dev.${var.apps_base_domain}](https://${local.identifier}-dev.${var.apps_base_domain})
- **Prod**: [${local.identifier}.${var.apps_base_domain}](https://${local.identifier}.${var.apps_base_domain})
Expand All @@ -66,7 +66,7 @@ View deployment status: [GitHub Actions](${meshstack_building_block_v2.repo.stat
- Merge PR from **main → release** → deploys to **prod**

### 2. Monitor
- Check workflow status in the [Actions tab](<${meshstack_building_block_v2.repo.status.outputs.repo_html_url.value_string}/actions>)
- Check workflow status in the [Actions tab](<${jsondecode(meshstack_building_block.repo.status.outputs.repo_html_url.value)}/actions>)

### 3. Access AKS Namespaces
- [Dev Namespace](/#/w/${var.workspace_identifier}/p/${meshstack_project.dev.metadata.name}/i/${meshstack_tenant_v4.dev.spec.platform_identifier}/overview/azure_kubernetes_service)
Expand Down
2 changes: 1 addition & 1 deletion modules/aks/starterkit/buildingblock/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
meshstack = {
source = "meshcloud/meshstack"
version = ">= 0.21.0"
version = ">= 0.23.0"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ The Azure VM Starterkit building block automates the creation of a complete Azur

| Name | Version |
|------|---------|
| <a name="requirement_meshstack"></a> [meshstack](#requirement\_meshstack) | >= 0.9.0 |
| <a name="requirement_meshstack"></a> [meshstack](#requirement\_meshstack) | >= 0.23.0 |

## Modules

Expand All @@ -49,7 +49,7 @@ No modules.

| Name | Type |
|------|------|
| [meshstack_building_block_v2.azure_vm](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block_v2) | resource |
| [meshstack_building_block.azure_vm](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/building_block) | resource |
| [meshstack_project.vm_project](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/project) | resource |
| [meshstack_project_user_binding.creator_admin](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/project_user_binding) | resource |
| [meshstack_tenant_v4.vm_tenant](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/resources/tenant_v4) | resource |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ resource "meshstack_tenant_v4" "vm_tenant" {
}
}

resource "meshstack_building_block_v2" "azure_vm" {
resource "meshstack_building_block" "azure_vm" {
spec = {
building_block_definition_version_ref = {
uuid = var.azure_vm_definition_version_uuid
Expand All @@ -61,31 +61,47 @@ resource "meshstack_building_block_v2" "azure_vm" {
uuid = meshstack_tenant_v4.vm_tenant.metadata.uuid
}
display_name = "Azure Virtual Machine"
inputs = {
vm_name = {
value_string = local.identifier
}
location = {
value_string = var.vm_location
}
os_type = {
value_string = var.vm_os_type
}
vm_size = {
value_string = var.vm_size
}
admin_username = {
value_string = var.vm_admin_username
}
enable_public_ip = {
value_bool = var.vm_enable_public_ip
}
ssh_public_key = {
value_string = var.vm_os_type == "Linux" ? var.vm_ssh_public_key : null
}
admin_password = {
value_string = var.vm_os_type == "Windows" ? var.vm_admin_password : null
}
}
inputs = merge(
{
vm_name = {
value = jsonencode(local.identifier)
}
location = {
value = jsonencode(var.vm_location)
}
os_type = {
value = jsonencode(var.vm_os_type)
}
vm_size = {
value = jsonencode(var.vm_size)
}
admin_username = {
value = jsonencode(var.vm_admin_username)
}
enable_public_ip = {
value = jsonencode(var.vm_enable_public_ip)
}
},
# Only send the OS-specific credential input for the matching OS. This mirrors
# the pre-v3 behavior where a null `value_string` omitted the input entirely;
# under v3 a `jsonencode(... : null)` would instead send an explicit JSON null.
var.vm_os_type == "Linux" ? {
ssh_public_key = {
value = jsonencode(var.vm_ssh_public_key)
}
} : {},
var.vm_os_type == "Windows" ? {
admin_password = {
value = jsonencode(var.vm_admin_password)
}
} : {},
)
}
}

# Migrate the child building block from the deprecated meshstack_building_block_v2
# resource to meshstack_building_block in place.
moved {
from = meshstack_building_block_v2.azure_vm
to = meshstack_building_block.azure_vm
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ output "tenant_uuid" {

output "vm_building_block_uuid" {
description = "UUID of the Azure VM building block"
value = meshstack_building_block_v2.azure_vm.metadata.uuid
value = meshstack_building_block.azure_vm.metadata.uuid
}

output "summary" {
Expand All @@ -24,7 +24,7 @@ This starter kit has set up the following resources in workspace `${var.workspac

@project[${meshstack_project.vm_project.metadata.owned_by_workspace}.${meshstack_project.vm_project.metadata.name}]\
&nbsp;&nbsp;&nbsp;&nbsp;@tenant[${meshstack_tenant_v4.vm_tenant.metadata.uuid}]\
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buildingblock[${meshstack_building_block_v2.azure_vm.metadata.uuid}]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buildingblock[${meshstack_building_block.azure_vm.metadata.uuid}]

---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ terraform {
required_providers {
meshstack = {
source = "meshcloud/meshstack"
version = ">= 0.9.0"
version = ">= 0.23.0"
}
}
}
Loading
Loading