diff --git a/modules/meshstack/noop/buildingblock/README.md b/modules/meshstack/noop/buildingblock/README.md index eb9e9c60..e8829278 100644 --- a/modules/meshstack/noop/buildingblock/README.md +++ b/modules/meshstack/noop/buildingblock/README.md @@ -26,6 +26,7 @@ Use it to: | `sensitive_yaml` | `CODE` | `STATIC` (sensitive) | Encrypted YAML/JSON value, decrypted at runtime | | `static` | `STRING` | `STATIC` | A platform-engineer-defined string constant | | `static_code` | `CODE` | `STATIC` | A platform-engineer-defined map | +| `tag_value` | `CODE` | `TAG` | Value of a meshStack tag, read from the target object rather than typed in by a user | | `flag` | `BOOLEAN` | `USER_INPUT` | Boolean flag chosen by the user | | `num` | `INTEGER` | `USER_INPUT` | Integer chosen by the user | | `text` | `STRING` | `USER_INPUT` | Free-text string from the user | @@ -78,6 +79,7 @@ No modules. | [single\_select](#input\_single\_select) | n/a | `string` | n/a | yes | | [static](#input\_static) | n/a | `string` | n/a | yes | | [static\_code](#input\_static\_code) | n/a | `map(string)` | n/a | yes | +| [tag\_value](#input\_tag\_value) | n/a | `list(string)` | n/a | yes | | [text](#input\_text) | n/a | `string` | n/a | yes | | [user\_permissions](#input\_user\_permissions) | n/a |
list(object({
meshIdentifier = string
username = string
firstName = string
lastName = string
email = string
euid = string
roles = list(string)
}))
| n/a | yes | | [user\_permissions\_json](#input\_user\_permissions\_json) | n/a | `string` | n/a | yes | @@ -102,6 +104,7 @@ No modules. | [static](#output\_static) | n/a | | [static\_code](#output\_static\_code) | n/a | | [summary](#output\_summary) | n/a | +| [tag\_value](#output\_tag\_value) | n/a | | [text](#output\_text) | n/a | | [user\_permissions](#output\_user\_permissions) | n/a | | [user\_permissions\_json](#output\_user\_permissions\_json) | n/a | diff --git a/modules/meshstack/noop/buildingblock/outputs.tf b/modules/meshstack/noop/buildingblock/outputs.tf index e606ea2b..5a49de02 100644 --- a/modules/meshstack/noop/buildingblock/outputs.tf +++ b/modules/meshstack/noop/buildingblock/outputs.tf @@ -27,6 +27,10 @@ output "static_code" { value = var.static_code } +output "tag_value" { + value = var.tag_value +} + output "flag" { value = var.flag } @@ -113,6 +117,7 @@ output "debug_input_variables_json" { multi_select_json = var.multi_select_json static = var.static static_code = var.static_code + tag_value = var.tag_value user_permissions = var.user_permissions user_permissions_json = var.user_permissions_json }) diff --git a/modules/meshstack/noop/buildingblock/variables.tf b/modules/meshstack/noop/buildingblock/variables.tf index 5c562a81..d403ca46 100644 --- a/modules/meshstack/noop/buildingblock/variables.tf +++ b/modules/meshstack/noop/buildingblock/variables.tf @@ -27,6 +27,12 @@ variable "static_code" { type = map(string) } +variable "tag_value" { + # meshStack sends a TAG input as a JSON array of strings; a tag with no value resolves to null. + type = list(string) + nullable = true +} + variable "flag" { type = bool } diff --git a/modules/meshstack/noop/e2e/main.tf b/modules/meshstack/noop/e2e/main.tf index d27b1d0d..43ae66e1 100644 --- a/modules/meshstack/noop/e2e/main.tf +++ b/modules/meshstack/noop/e2e/main.tf @@ -8,6 +8,30 @@ variable "test_context" { nullable = false } +# A tag input reads its value from an existing meshStack tag, so the e2e test provisions its own +# tag definition and sets it on the test workspace to exercise the input end-to-end. It cannot be +# destroyed while the building block definition below reads it, so referencing its `spec.key` from +# the module's `tag_key` input (and the workspace tag depending on the definition) gets destroy +# order right on its own. +resource "meshstack_tag_definition" "noop_e2e" { + spec = { + target_kind = "meshWorkspace" + key = "noop-e2e-tag-${var.test_context.name_suffix}" + display_name = "NoOp E2E Tag" + value_type = { string = {} } + } +} + +resource "meshstack_workspace_tag" "noop_e2e" { + metadata = { + workspace_identifier = var.test_context.workspace + key = meshstack_tag_definition.noop_e2e.spec.key + } + spec = { + values = ["e2e-tag-value"] + } +} + module "noop" { source = "../" meshstack = { @@ -18,9 +42,14 @@ module "noop" { git_ref = var.test_context.hub_git_ref bbd_draft = true } + tag_object = "WORKSPACE" + tag_key = meshstack_tag_definition.noop_e2e.spec.key } resource "meshstack_building_block" "this" { + # ensures the tag has a value before the building block run reads it + depends_on = [meshstack_workspace_tag.noop_e2e] + wait_for_completion = true spec = { building_block_definition_version_ref = module.noop.building_block_definition.version_ref @@ -40,6 +69,7 @@ resource "meshstack_building_block" "this" { single_select = { value = jsonencode("single1") } multi_select = { value = jsonencode(["multi1", "multi2"]) } multi_select_json = { value = jsonencode(["multi2", "multi1"]) } + # tag_value = -> TAG-assigned inputs are read by meshStack from the workspace tag, not supplied here. } } } diff --git a/modules/meshstack/noop/e2e/tests/building_block_noop_hub.debug_input_variables_json.expected.json b/modules/meshstack/noop/e2e/tests/building_block_noop_hub.debug_input_variables_json.expected.json index 444d5eb3..28028f6d 100644 --- a/modules/meshstack/noop/e2e/tests/building_block_noop_hub.debug_input_variables_json.expected.json +++ b/modules/meshstack/noop/e2e/tests/building_block_noop_hub.debug_input_variables_json.expected.json @@ -14,5 +14,6 @@ "static_code": { "some":"code" }, + "tag_value": ["e2e-tag-value"], "text":"Hello, World!" } diff --git a/modules/meshstack/noop/e2e/tests/building_block_noop_hub.tftest.hcl b/modules/meshstack/noop/e2e/tests/building_block_noop_hub.tftest.hcl index d18e657c..2cae4246 100644 --- a/modules/meshstack/noop/e2e/tests/building_block_noop_hub.tftest.hcl +++ b/modules/meshstack/noop/e2e/tests/building_block_noop_hub.tftest.hcl @@ -31,6 +31,13 @@ run "building_block_noop_hub" { error_message = "noop hub building block expected output resource_url to be 'https://hub.meshcloud.io/modules/meshstack/noop', got ${jsondecode(meshstack_building_block.this.status.outputs["resource_url"].value)}" } + assert { + # tag_value is sourced from the meshstack_workspace_tag set up in e2e/main.tf, not from the + # building block's own inputs. + condition = jsondecode(meshstack_building_block.this.status.outputs["tag_value"].value) == ["e2e-tag-value"] + error_message = "noop hub building block expected output tag_value to be [\"e2e-tag-value\"], got ${jsondecode(meshstack_building_block.this.status.outputs["tag_value"].value)}" + } + assert { condition = ( jsondecode(meshstack_building_block.this.status.outputs["summary"].value) diff --git a/modules/meshstack/noop/meshstack_integration.tf b/modules/meshstack/noop/meshstack_integration.tf index eeb7dd7f..f4b73292 100644 --- a/modules/meshstack/noop/meshstack_integration.tf +++ b/modules/meshstack/noop/meshstack_integration.tf @@ -7,6 +7,18 @@ variable "runner_ref" { description = "Optional reference to a meshStack building block runner. When set, building block runs are dispatched to this custom runner. Obtain the value from the backplane module's `runner_ref` output." } +variable "tag_object" { + type = string + default = "WORKSPACE" + description = "The meshStack object kind the `tag_value` input reads its value from. A WORKSPACE_LEVEL building block definition (like this one) can only read WORKSPACE tags; TENANT_LEVEL definitions can also read PROJECT, PAYMENT_METHOD, or LANDING_ZONE." +} + +variable "tag_key" { + type = string + default = "business-unit" + description = "Key of an existing meshStack tag definition (target_kind meshWorkspace) that the `tag_value` input reads its value from. The tag definition must already exist on the target meshStack instance." +} + variable "meshstack" { type = object({ owning_workspace_identifier = string @@ -177,6 +189,12 @@ resource "meshstack_building_block_definition" "this" { display_name = "Static Code" type = "CODE" } + tag_value = { + assignment_type = "TAG" + argument = jsonencode("${var.tag_object}.${var.tag_key}") + display_name = "Tag Value" + type = "CODE" + } text = { assignment_type = "USER_INPUT" default_value = jsonencode("") @@ -220,6 +238,17 @@ resource "meshstack_building_block_definition" "this" { display_name = "Static Code" type = "CODE" } + # We need to wait for TF provider release to make this work + # tag_value = { + # assignment_type = "NONE" + # display_name = "Tag Value" + # type = "CODE" + # } + tag_value = { + assignment_type = "NONE" + display_name = "Tag Value" + type = "CODE" + } resource_url = { assignment_type = "RESOURCE_URL" display_name = "Resource URL" @@ -250,7 +279,7 @@ terraform { required_providers { meshstack = { source = "meshcloud/meshstack" - version = ">= 0.21.0" + version = ">= 0.25.2" } } }