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
26 changes: 24 additions & 2 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,26 @@ They are starting points that should cover the simplest use case.
A secondary purpose of these files is to serve as a ready-to-use Terraform module root that IaC runtimes can source directly.

- Must use variables for required user inputs.
- Must include `required_providers` (place the `terraform { required_providers { ... } }` block at the **bottom** of the file — resources and variables should come first so readers see the important configuration before technical boilerplate).
- Must include `required_providers` block at the **bottom** of the file — resources and variables should come first so readers see the important configuration before technical boilerplate).
- Never include `provider` configuration.
- Reference modules using Git URLs and a ref pointing to the feature branch when developing. Once merged into main, the `update-module-refs` tooling in CI pins the ref to an appropriate commit.

### Required providers

Every `meshstack_integration.tf` must declare the `meshcloud/meshstack` provider in a
`required_providers` block.

```hcl
terraform {
required_providers {
meshstack = {
source = "meshcloud/meshstack"
version = ">= 0.19.3"
}
}
}
```

### Shared Variable Conventions

The following variables must appear in every `meshstack_integration.tf`.
Expand All @@ -67,7 +83,7 @@ variable "hub" {
default = {}
description = <<-EOT
`git_ref`: Hub release reference. Set to a tag (e.g. 'v1.2.3') or branch or commit sha of the meshstack-hub repo.
`bbd_draft`: If true, the building block definition version is kept in draft mode, which allows changing it (useful during development in LCF/ICF).
`bbd_draft`: If true, the building block definition version is kept in draft mode.
EOT
}
```
Expand All @@ -92,7 +108,9 @@ Integrating with meshStack requires context, like a workspace where the resource
variable "meshstack" {
type = object({
owning_workspace_identifier = string
tags = optional(map(list(string)), {})
})
description = "Shared meshStack context. Tags are optional and propagated to building block definition metadata."
}
```

Expand All @@ -102,6 +120,7 @@ Use these variables in the implementation block of building block definitions.
resource "meshstack_building_block_definition" "this" {
metadata = {
owned_by_workspace = var.meshstack.owning_workspace_identifier
tags = var.meshstack.tags
}
# ... other required fields ...
implementation = {
Expand Down Expand Up @@ -173,6 +192,9 @@ Do **not** commit these relative paths; switch back to the Hub GitHub URL before
- [ ] Variables in `snake_case`
- [ ] `buildingblock/README.md` with YAML front-matter
- [ ] `buildingblock/APP_TEAM_README.md` with shared responsibility matrix
- [ ] `meshstack_integration.tf` declares `meshcloud/meshstack` in `required_providers`
- [ ] `meshstack_integration.tf` uses `variable "hub" { type = object({git_ref = string}) }` and `variable "meshstack" { type = object({owning_workspace_identifier = string}) }`
- [ ] `meshstack_integration.tf` uses relative `./backplane` source (no absolute GitHub URL)
- [ ] `ref_name` uses `var.hub.git_ref` — no hardcoded `"main"`
- [ ] `version_spec.draft` uses `var.hub.bbd_draft`
- [ ] `building_block_definition_version_uuid` output uses `bbd_draft ? version_latest.uuid : version_latest_release.uuid`
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.81.0
rev: v1.105.0
hooks:
- id: terraform_docs
args:
Expand All @@ -17,7 +17,7 @@ repos:
hooks:
- id: validate-modules
name: Validate modules
entry: sh -c 'bash ci/validate_modules.sh'
entry: sh -c 'bash ci/validate_modules.sh --fix'
language: system
pass_filenames: true
always_run: true
102 changes: 102 additions & 0 deletions modules/meshstack/noop/buildingblock/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
name: meshStack NoOp Building Block
supportedPlatforms:
- meshstack
description: |
Reference building block demonstrating meshStack's complete Terraform interface:
all input types, file inputs, user permissions injection, and pre-run scripts.
---
# meshStack NoOp Building Block

This building block is a reference implementation demonstrating how meshStack interfaces with OpenTofu building blocks. It exercises every input type, file input, pre-run script capability, and output type — without provisioning any cloud resources.

Use it to:
- Understand how meshStack passes inputs to Terraform
- Learn how FILE-type inputs are written to the working directory
- See how `USER_PERMISSIONS` injects project team members into your building block
- Understand the pre-run script execution model

## Input Types

| Input | Type | Assignment | Description |
|-------|------|-----------|-------------|
| `user_permissions` | `CODE` | `USER_PERMISSIONS` | Project team members and their roles as a structured list |
| `user_permissions_json` | `CODE` | `USER_PERMISSIONS` | Same as above, as a raw JSON string |
| `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 |
| `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 |
| `sensitive_text` | `STRING` (sensitive) | `USER_INPUT` | Sensitive string, masked in UI and logs |
| `single_select` | `SINGLE_SELECT` | `USER_INPUT` | One value from a predefined list |
| `multi_select` | `MULTI_SELECT` | `USER_INPUT` | One or more values from a predefined list |
| `multi_select_json` | `MULTI_SELECT` | `USER_INPUT` | Same as above, as a raw JSON string |
| `some-file.yaml` | `FILE` | `STATIC` | Written to working directory; read via `file("some-file.yaml")` |
| `sensitive-file.yaml` | `FILE` | `STATIC` (sensitive) | Like above, encrypted at rest |

### How FILE Inputs Work

meshStack writes FILE inputs as files in the Terraform working directory before `tofu init` runs. Access them in Terraform with:

```hcl
output "some_file_yaml" {
value = yamldecode(file("some-file.yaml"))
}
<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [terraform_data.noop](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_flag"></a> [flag](#input\_flag) | n/a | `bool` | n/a | yes |
| <a name="input_multi_select"></a> [multi\_select](#input\_multi\_select) | n/a | `list(string)` | n/a | yes |
| <a name="input_multi_select_json"></a> [multi\_select\_json](#input\_multi\_select\_json) | n/a | `string` | n/a | yes |
| <a name="input_num"></a> [num](#input\_num) | n/a | `number` | n/a | yes |
| <a name="input_sensitive_text"></a> [sensitive\_text](#input\_sensitive\_text) | n/a | `string` | n/a | yes |
| <a name="input_sensitive_yaml"></a> [sensitive\_yaml](#input\_sensitive\_yaml) | n/a | `any` | n/a | yes |
| <a name="input_single_select"></a> [single\_select](#input\_single\_select) | n/a | `string` | n/a | yes |
| <a name="input_static"></a> [static](#input\_static) | n/a | `string` | n/a | yes |
| <a name="input_static_code"></a> [static\_code](#input\_static\_code) | n/a | `map(string)` | n/a | yes |
| <a name="input_text"></a> [text](#input\_text) | n/a | `string` | n/a | yes |
| <a name="input_user_permissions"></a> [user\_permissions](#input\_user\_permissions) | n/a | <pre>list(object({<br/> meshIdentifier = string<br/> username = string<br/> firstName = string<br/> lastName = string<br/> email = string<br/> euid = string<br/> roles = list(string)<br/> }))</pre> | n/a | yes |
| <a name="input_user_permissions_json"></a> [user\_permissions\_json](#input\_user\_permissions\_json) | n/a | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_debug_input_files_json"></a> [debug\_input\_files\_json](#output\_debug\_input\_files\_json) | JSON-encoded map of all input files received, including sensitive values in plaintext. |
| <a name="output_debug_input_variables_json"></a> [debug\_input\_variables\_json](#output\_debug\_input\_variables\_json) | JSON-encoded map of all input variables received, including sensitive values in plaintext. |
| <a name="output_flag"></a> [flag](#output\_flag) | n/a |
| <a name="output_multi_select"></a> [multi\_select](#output\_multi\_select) | n/a |
| <a name="output_multi_select_json"></a> [multi\_select\_json](#output\_multi\_select\_json) | n/a |
| <a name="output_num"></a> [num](#output\_num) | n/a |
| <a name="output_resource_url"></a> [resource\_url](#output\_resource\_url) | n/a |
| <a name="output_sensitive_file_yaml"></a> [sensitive\_file\_yaml](#output\_sensitive\_file\_yaml) | n/a |
| <a name="output_sensitive_text"></a> [sensitive\_text](#output\_sensitive\_text) | n/a |
| <a name="output_sensitive_yaml"></a> [sensitive\_yaml](#output\_sensitive\_yaml) | n/a |
| <a name="output_single_select"></a> [single\_select](#output\_single\_select) | n/a |
| <a name="output_some_file_yaml"></a> [some\_file\_yaml](#output\_some\_file\_yaml) | n/a |
| <a name="output_static"></a> [static](#output\_static) | n/a |
| <a name="output_static_code"></a> [static\_code](#output\_static\_code) | n/a |
| <a name="output_summary"></a> [summary](#output\_summary) | n/a |
| <a name="output_text"></a> [text](#output\_text) | n/a |
| <a name="output_user_permissions"></a> [user\_permissions](#output\_user\_permissions) | n/a |
| <a name="output_user_permissions_json"></a> [user\_permissions\_json](#output\_user\_permissions\_json) | n/a |
<!-- END_TF_DOCS -->
Binary file added modules/meshstack/noop/buildingblock/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions modules/meshstack/noop/buildingblock/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions modules/meshstack/noop/buildingblock/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
resource "terraform_data" "noop" {
# This resource does nothing and is always up-to-date.
}
123 changes: 123 additions & 0 deletions modules/meshstack/noop/buildingblock/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
output "some_file_yaml" {
value = yamldecode(file("some-file.yaml"))
}

output "sensitive_file_yaml" {
value = yamldecode(file("sensitive-file.yaml"))
}

output "user_permissions" {
value = var.user_permissions
}

output "user_permissions_json" {
value = jsondecode(var.user_permissions_json)
}

output "sensitive_yaml" {
value = var.sensitive_yaml
sensitive = true
}

output "static" {
value = var.static
}

output "static_code" {
value = var.static_code
}

output "flag" {
value = var.flag
}

output "num" {
value = var.num
}

output "text" {
value = var.text
}

output "sensitive_text" {
value = var.sensitive_text
sensitive = true
}

output "single_select" {
value = var.single_select
}

output "multi_select" {
value = var.multi_select
}

output "multi_select_json" {
value = jsondecode(var.multi_select_json)
}

output "resource_url" {
value = "https://hub.meshcloud.io/modules/meshstack/noop"
}

output "summary" {
value = <<-MARKDOWN
# NoOp Building Block — Deployment Summary

This building block was successfully deployed. It is a **reference implementation**
demonstrating meshStack's complete Terraform interface — it provisions _no real
infrastructure_.

The `SUMMARY` output assignment type allows you to provide a rich markdown summary for application teams.
This summary is rendered like a README for this building block in meshPanel.

## Example: Tables

| Input | Value |
|----------------|------------------------------|
| Text | `Hello` |
| Number | `123` |

## Example: Code blocks

You can use fenced code blocks and `inline code` for formatting.
We support syntax highlighting for common languages.

```yaml
some: input
other: value
```

## Example: Callout blocks

> **Note**: Use quote blocks to create callouts for important information.
MARKDOWN
}

output "debug_input_variables_json" {
description = "JSON-encoded map of all input variables received, including sensitive values in plaintext."
sensitive = true # For test only. Do not do this in production code.
value = jsonencode({
flag = var.flag
num = var.num
text = var.text
single_select = var.single_select
sensitive_text = var.sensitive_text
sensitive_yaml = var.sensitive_yaml
multi_select = var.multi_select
multi_select_json = var.multi_select_json
static = var.static
static_code = var.static_code
user_permissions = var.user_permissions
user_permissions_json = var.user_permissions_json
})
}

output "debug_input_files_json" {
description = "JSON-encoded map of all input files received, including sensitive values in plaintext."
sensitive = true # For test only. Do not do this in production code.
value = jsonencode({
"some-file.yaml" = file("some-file.yaml")
"sensitive-file.yaml" = file("sensitive-file.yaml")
})
}
43 changes: 43 additions & 0 deletions modules/meshstack/noop/buildingblock/prerun.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
echo "=== meshStack Building Block Pre-Run Script ==="
echo "Running after 'tofu init', before 'tofu apply'"
echo ""

echo "--- Run Modes ---"
echo "Run mode APPLY/DESTROY is passed as a positional argument"
echo "Selected run mode: $1"
echo ""

echo "--- meshBuildingBlockRun JSON input ---"
echo "# Read stdin once and extract multiple fields:"
input=$(cat)
workspace_id=$(echo "$input" | jq -r '.spec.buildingBlock.spec.workspaceIdentifier')
buildingblock_uuid=$(echo "$input" | jq -r '.spec.buildingBlock.uuid')
echo "Workspace identifier: $workspace_id"
echo "Building Block UUID: $buildingblock_uuid"
echo ""

echo "--- Working Directory ---"
echo "Working directory: $(pwd)"
ls -lah
echo ""

echo "--- Tool Installation ---"
echo "Currently not supported via apk add, but coming soon, see https://feedback.meshcloud.io/feature-requests/p/building-block-should-support-aws-cli-and-other"
# sudo apk add aws-cli
echo ""

echo "--- Terraform State Manipulation ---"
echo "The tofu backend is already initialized and a workspace selected"
tofu show -no-color
echo ""

echo "--- Capturing System Logs ---"
echo "Stdout log message from pre-run script"
echo "Stderr log message from pre-run script" >&2
echo ""

echo "--- Capturing User Messages ---"
echo "User message from pre-run script" >> "$MESHSTACK_USER_MESSAGE"

echo "=== Pre-run script completed successfully ==="
echo "'tofu apply' will now execute."
Loading
Loading