From bdc53975ab8162afc5349bd1ad8ad3d1c5254d90 Mon Sep 17 00:00:00 2001 From: Florian Nowarre Date: Wed, 21 Jan 2026 11:23:46 +0100 Subject: [PATCH 1/9] feat: adding bb for oracle oci --- .../buildingblock/APP_TEAM_README.md | 135 +++++++++++ .../buildingblock/README.md | 209 ++++++++++++++++++ .../buildingblock/logo.png | Bin 0 -> 11771 bytes .../buildingblock/main.tf | 105 +++++++++ .../buildingblock/outputs.tf | 49 ++++ .../buildingblock/provider.tf | 14 ++ .../buildingblock/variables.tf | 71 ++++++ modules/oci/oracle.png | Bin 0 -> 11771 bytes 8 files changed, 583 insertions(+) create mode 100644 modules/oci/application-compartment/buildingblock/APP_TEAM_README.md create mode 100644 modules/oci/application-compartment/buildingblock/README.md create mode 100644 modules/oci/application-compartment/buildingblock/logo.png create mode 100644 modules/oci/application-compartment/buildingblock/main.tf create mode 100644 modules/oci/application-compartment/buildingblock/outputs.tf create mode 100644 modules/oci/application-compartment/buildingblock/provider.tf create mode 100644 modules/oci/application-compartment/buildingblock/variables.tf create mode 100644 modules/oci/oracle.png diff --git a/modules/oci/application-compartment/buildingblock/APP_TEAM_README.md b/modules/oci/application-compartment/buildingblock/APP_TEAM_README.md new file mode 100644 index 00000000..75153be5 --- /dev/null +++ b/modules/oci/application-compartment/buildingblock/APP_TEAM_README.md @@ -0,0 +1,135 @@ +# OCI Application Compartment + +## Description +This building block creates a new Oracle Cloud Infrastructure (OCI) compartment and manages user access permissions. It provides application teams with a secure, isolated environment for deploying their workloads while ensuring proper access controls through IAM groups and policies. + +## Usage Motivation +This building block is designed for application teams that need to: +- Create isolated OCI compartments for their applications +- Manage team access with appropriate permission levels +- Ensure compliance with organizational security policies +- Automate compartment setup and user onboarding +- Deploy workloads in the correct organizational structure based on landing zone and environment + +## Usage Examples +- A development team creates a compartment for their microservices architecture with different access levels for developers, operators, and auditors. +- A platform team provisions compartments for multiple application teams with consistent access patterns across different landing zones. +- An organization sets up compartments for different environments (development, QA, test, production) within their cloud-native landing zone. +- A sandbox project gets provisioned with a simplified single-compartment setup for rapid prototyping. + +## Shared Responsibility + +| Responsibility | Platform Team | Application Team | +|------------------------|--------------|----------------| +| Provisioning and configuring compartments | ✅ | ❌ | +| Managing user access and permissions | ❌ | ✅ | +| Defining compartment naming conventions | ✅ | ❌ | +| Monitoring compartment usage and costs | ✅ | ❌ | +| Configuring landing zones and parent compartments | ✅ | ❌ | +| Managing resources within the compartment | ❌ | ✅ | + +## Recommendations for Secure and Efficient Compartment Usage +- **Follow naming conventions**: Compartment names are automatically generated following organizational patterns. +- **Use appropriate landing zones**: Select the correct landing zone based on your application's security and compliance requirements. +- **Choose the right environment**: Properly tag your project with the correct environment (dev, qa, test, prod) for proper compartment placement. +- **Grant least privilege access**: Assign users the minimum permissions they need (reader < user < admin). +- **Regular access reviews**: Periodically review and update user permissions as team composition changes. +- **Resource organization**: Use the compartment to logically organize your cloud resources. +- **Cost tracking**: Leverage compartments for cost allocation and budgeting. + +## Configuration Options + +### How Compartment Placement Works + +The building block automatically determines where to create your application compartment based on **meshStack project tags**: + +1. **Landing Zone Tag**: Determines the overall security/compliance level +2. **Environment Tag**: Determines which environment-specific compartment to use (if applicable) + +#### Landing Zone Types + +##### Sandbox Landing Zone +- **Purpose**: For experimentation, learning, and rapid prototyping +- **Behavior**: All environments (dev, qa, test, prod) use the **same parent compartment** +- **Use Case**: Quick setup for non-production workloads + +##### Cloud-Native Landing Zone +- **Purpose**: For production-ready applications with proper environment separation +- **Behavior**: Each environment gets its **own parent compartment** + - `dev` → Cloud-Native Dev compartment + - `qa` → Cloud-Native QA compartment + - `test` → Cloud-Native Test compartment + - `prod` → Cloud-Native Prod compartment +- **Use Case**: Production workloads requiring environment isolation + +##### Fallback +- If no landing zone tags match, a default parent compartment is used + +### User Roles and Permissions + +Users can be assigned one or more roles from the authoritative system: + +#### Reader Role +- **OCI Permissions**: Read-only access to all resources in the compartment +- **Use Case**: Auditors, stakeholders who need visibility but not modification rights + +#### User Role +- **OCI Permissions**: Can manage: + - Compute instances (instance-family) + - Virtual networks (virtual-network-family) + - Block and boot volumes (volume-family) + - Object storage (object-family) + - Load balancers + - Read all resources +- **Use Case**: Developers and operators who need to deploy and manage applications + +#### Admin Role +- **OCI Permissions**: Full management access to all resources in the compartment +- **Use Case**: Team leads, DevOps engineers who need complete control + +**Note**: If a user has multiple roles, the highest privilege role takes precedence (admin > user > reader). + +#### Example Scenarios + +| Landing Zone Tag | Environment Tag | Result | +|-----------------|----------------|--------| +| `sandbox` | `dev` | Parent: Sandbox compartment (ignores environment) | +| `sandbox` | `prod` | Parent: Sandbox compartment (ignores environment) | +| `cloud-native` | `dev` | Parent: Cloud-Native Dev compartment | +| `cloud-native` | `prod` | Parent: Cloud-Native Prod compartment | +| No tags | Any | Parent: Default fallback Sandbox compartment | + +### Automatic Compartment Naming + +Compartments are automatically named following this pattern: +``` +{foundation}-{workspace_id}-{project_id} +``` + +Example: `mycompany-platform-team-ecommerce-api` + +The compartment description includes helpful context: +``` +Application compartment for {workspace_id}/{project_id} [landing_zone/environment] +``` + +Example: `Application compartment for platform-team/ecommerce-api [cloud-native/prod]` + +## What Gets Created + +When you provision this building block, the following resources are created in OCI: + +1. **Application Compartment**: A new compartment under the appropriate parent compartment +2. **Three IAM Groups**: + - `{compartment-name}-readers`: Read-only access group + - `{compartment-name}-users`: Standard user access group + - `{compartment-name}-admins`: Administrator access group +3. **Group Memberships**: Automatic assignment of users to groups based on their roles +4. **IAM Policy**: Access policies defining permissions for each group + +## Outputs and Access + +After provisioning, you'll receive: +- **Compartment OCID**: The unique identifier for your compartment +- **Console URL**: Direct link to access your compartment in the OCI Console +- **Group Information**: Names and OCIDs of the created IAM groups diff --git a/modules/oci/application-compartment/buildingblock/README.md b/modules/oci/application-compartment/buildingblock/README.md new file mode 100644 index 00000000..aaf93edb --- /dev/null +++ b/modules/oci/application-compartment/buildingblock/README.md @@ -0,0 +1,209 @@ +--- +name: OCI Application Compartment +supportedPlatforms: + - oci +description: | + Creates an application compartment with IAM groups and policies for team-based access control. +--- + +# OCI Application Compartment Building Block + +Creates an application compartment with IAM groups and policies for team-based access control. + +## Features + +- **Application Compartment**: Creates a compartment for application workloads +- **Conditional Placement**: Places compartments based on meshStack project tags +- **Flexible Configuration**: Tag names and compartment mappings configurable via YAML +- **IAM Groups**: Three groups with different access levels (readers, users, admins) +- **Access Policies**: Granular permissions for each group + +## Access Levels + +### Readers +- Read-only access to all resources in the compartment + +### Users +- Manage compute instances, storage, networking, and load balancers +- Read all resources + +### Admins +- Full management access to all resources in the compartment + +## Compartment Placement Logic + +The module determines the parent compartment based on meshStack project tags configured in the `tag_relations` variable: + +1. **Sandbox Landing Zone**: Always uses sandbox compartment, regardless of environment +2. **Cloud-Native Landing Zone**: Uses environment-specific compartments (dev/qa/test/prod) +3. **Fallback**: Uses default compartment if no tags match + +## Usage + +### Basic Usage + +```hcl +module "application_compartment" { + source = "./application-compartment" + + tenancy_ocid = var.tenancy_ocid + foundation = "my-foundation" + workspace_id = "my-workspace" + project_id = "my-project" + region = "eu-frankfurt-1" + users = var.users +} +``` + +The module uses default tag names (`Environment`, `landingzone_family`) and placeholder compartment IDs. + +### Custom Configuration + +Override the `tag_relations` variable to customize tag names and compartment mappings: + +```hcl +module "application_compartment" { + source = "./application-compartment" + + tenancy_ocid = var.tenancy_ocid + foundation = "my-foundation" + workspace_id = "my-workspace" + project_id = "my-project" + region = "eu-frankfurt-1" + users = var.users + + tag_relations = <<-EOT + # meshStack tag names to read + tag_names: + environment: "Environment" + landing_zone: "landingzone_family" + + # Landing zone configurations + landing_zones: + # Sandbox: single compartment for all environments + sandbox: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...sandbox" + + # Cloud-native: per-environment compartments + cloud-native: + environments: + dev: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-dev" + qa: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-qa" + test: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-test" + prod: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-prod" + + # Fallback if no match + default_compartment_id: "ocid1.compartment.oc1..aaaaaaaa...default" + EOT +} +``` + +## Configuration Structure + +The `tag_relations` variable accepts YAML with the following structure: + +```yaml +# Which meshStack tags to read +tag_names: + environment: "Environment" # Tag name for environment + landing_zone: "landingzone_family" # Tag name for landing zone family + +# Compartment mappings per landing zone +# The landing zone names here match the values in your meshStack tags +landing_zones: + sandbox: # When landing_zone tag = "sandbox" + compartment_id: "ocid1.compartment..." # Single compartment (no environments) + + cloud-native: # When landing_zone tag = "cloud-native" + environments: # Per-environment compartments + dev: + compartment_id: "ocid1.compartment..." + qa: + compartment_id: "ocid1.compartment..." + test: + compartment_id: "ocid1.compartment..." + prod: + compartment_id: "ocid1.compartment..." + +# Default fallback compartment +default_compartment_id: "ocid1.compartment..." +``` + +**Important**: +- The keys under `landing_zones` (e.g., `sandbox`, `cloud-native`) must match the **values** in your meshStack `landingzone_family` tag +- Landing zones without an `environments` section will use the same compartment for all environments +- Landing zones with an `environments` section will route based on the environment tag value + +## meshStack Integration + +The module automatically: +1. Fetches project metadata from meshStack using `workspace_id` and `project_id` +2. Reads tags from the project (format: `map(list(string))`) +3. Extracts tag values based on `tag_names` configuration +4. Selects the appropriate compartment based on landing zone and environment + +## Example Tag Scenarios + +| meshStack Tags | Selected Compartment | +|----------------|---------------------| +| `landingzone_family: ["sandbox"]`, `Environment: ["dev"]` | `landing_zones.sandbox.compartment_id` | +| `landingzone_family: ["sandbox"]`, `Environment: ["prod"]` | `landing_zones.sandbox.compartment_id` | +| `landingzone_family: ["cloud-native"]`, `Environment: ["dev"]` | `landing_zones.cloud-native.environments.dev.compartment_id` | +| `landingzone_family: ["cloud-native"]`, `Environment: ["prod"]` | `landing_zones.cloud-native.environments.prod.compartment_id` | +| No matching tags | `default_compartment_id` | + + +## Requirements + +No requirements. + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [oci_identity_compartment.application](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_compartment) | resource | +| [oci_identity_group.admins](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_group) | resource | +| [oci_identity_group.readers](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_group) | resource | +| [oci_identity_group.users](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_group) | resource | +| [oci_identity_policy.application](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_policy) | resource | +| [oci_identity_user_group_membership.admins](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user_group_membership) | resource | +| [oci_identity_user_group_membership.readers](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user_group_membership) | resource | +| [oci_identity_user_group_membership.users](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user_group_membership) | resource | +| [meshstack_project.project](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/data-sources/project) | data source | +| [oci_identity_users.all_users](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_users) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [foundation](#input\_foundation) | Foundation name prefix | `string` | n/a | yes | +| [project\_id](#input\_project\_id) | Project identifier (e.g., application name) | `string` | n/a | yes | +| [region](#input\_region) | OCI region identifier (e.g., eu-frankfurt-1, us-ashburn-1) | `string` | n/a | yes | +| [tag\_relations](#input\_tag\_relations) | YAML configuration for tag-based compartment mapping | `string` | `"# meshStack tag names to read\ntag_names:\n environment: \"Environment\"\n landing_zone: \"landingzone_family\"\n\n# Landing zone configurations\nlanding_zones:\n # Sandbox: single compartment for all environments\n sandbox:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...sandbox\"\n \n # Cloud-native: per-environment compartments\n cloud-native:\n environments:\n dev:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-dev\"\n qa:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-qa\"\n test:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-test\"\n prod:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-prod\"\n\n# Fallback if no match\ndefault_compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...default\"\n"` | no | +| [tenancy\_ocid](#input\_tenancy\_ocid) | OCID of the OCI tenancy | `string` | n/a | yes | +| [users](#input\_users) | List of users from authoritative system |
list(object({
meshIdentifier = string
username = string
firstName = string
lastName = string
email = string
euid = string
roles = list(string)
}))
| `[]` | no | +| [workspace\_id](#input\_workspace\_id) | Workspace identifier (e.g., team name or business unit) | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [admin\_group\_id](#output\_admin\_group\_id) | OCID of the admins group | +| [admin\_group\_name](#output\_admin\_group\_name) | Name of the admins group | +| [compartment\_id](#output\_compartment\_id) | OCID of the created application compartment | +| [compartment\_name](#output\_compartment\_name) | Name of the created application compartment | +| [console\_url](#output\_console\_url) | OCI Console URL for direct access to the compartment | +| [policy\_id](#output\_policy\_id) | OCID of the access policy | +| [reader\_group\_id](#output\_reader\_group\_id) | OCID of the readers group | +| [reader\_group\_name](#output\_reader\_group\_name) | Name of the readers group | +| [user\_group\_id](#output\_user\_group\_id) | OCID of the users group | +| [user\_group\_name](#output\_user\_group\_name) | Name of the users group | + diff --git a/modules/oci/application-compartment/buildingblock/logo.png b/modules/oci/application-compartment/buildingblock/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..754b7405eb5ddf596d99e317e53af325838b73ca GIT binary patch literal 11771 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 user.id + } + + admin_users = { for user in var.users : user.email => lookup(local.user_ocid_map, user.email, null) if contains(user.roles, "admin") && lookup(local.user_ocid_map, user.email, null) != null } + user_users = { for user in var.users : user.email => lookup(local.user_ocid_map, user.email, null) if contains(user.roles, "user") && !contains(user.roles, "admin") && lookup(local.user_ocid_map, user.email, null) != null } + reader_users = { for user in var.users : user.email => lookup(local.user_ocid_map, user.email, null) if contains(user.roles, "reader") && !contains(user.roles, "admin") && !contains(user.roles, "user") && lookup(local.user_ocid_map, user.email, null) != null } +} + +resource "oci_identity_compartment" "application" { + compartment_id = local.selected_parent_compartment_id + name = local.compartment_name + description = "Application compartment for ${var.workspace_id}/${var.project_id} [${local.landing_zone}${local.environment != "" ? "/${local.environment}" : ""}]" +} + +resource "oci_identity_group" "readers" { + compartment_id = var.tenancy_ocid + name = "${local.compartment_name}-readers" + description = "Read-only access to ${local.compartment_name}" +} + +resource "oci_identity_group" "users" { + compartment_id = var.tenancy_ocid + name = "${local.compartment_name}-users" + description = "User access to ${local.compartment_name}" +} + +resource "oci_identity_group" "admins" { + compartment_id = var.tenancy_ocid + name = "${local.compartment_name}-admins" + description = "Admin access to ${local.compartment_name}" +} + +resource "oci_identity_user_group_membership" "readers" { + for_each = local.reader_users + + group_id = oci_identity_group.readers.id + user_id = each.value +} + +resource "oci_identity_user_group_membership" "users" { + for_each = local.user_users + + group_id = oci_identity_group.users.id + user_id = each.value +} + +resource "oci_identity_user_group_membership" "admins" { + for_each = local.admin_users + + group_id = oci_identity_group.admins.id + user_id = each.value +} + +resource "oci_identity_policy" "application" { + compartment_id = oci_identity_compartment.application.id + name = "${local.compartment_name}-policy" + description = "Access policies for ${local.compartment_name}" + + statements = [ + "Allow group ${oci_identity_group.readers.name} to read all-resources in compartment id ${oci_identity_compartment.application.id}", + "Allow group ${oci_identity_group.users.name} to manage instance-family in compartment id ${oci_identity_compartment.application.id}", + "Allow group ${oci_identity_group.users.name} to manage virtual-network-family in compartment id ${oci_identity_compartment.application.id}", + "Allow group ${oci_identity_group.users.name} to manage volume-family in compartment id ${oci_identity_compartment.application.id}", + "Allow group ${oci_identity_group.users.name} to manage object-family in compartment id ${oci_identity_compartment.application.id}", + "Allow group ${oci_identity_group.users.name} to manage load-balancers in compartment id ${oci_identity_compartment.application.id}", + "Allow group ${oci_identity_group.users.name} to read all-resources in compartment id ${oci_identity_compartment.application.id}", + "Allow group ${oci_identity_group.admins.name} to manage all-resources in compartment id ${oci_identity_compartment.application.id}", + ] +} diff --git a/modules/oci/application-compartment/buildingblock/outputs.tf b/modules/oci/application-compartment/buildingblock/outputs.tf new file mode 100644 index 00000000..25fa6c15 --- /dev/null +++ b/modules/oci/application-compartment/buildingblock/outputs.tf @@ -0,0 +1,49 @@ +output "compartment_id" { + description = "OCID of the created application compartment" + value = oci_identity_compartment.application.id +} + +output "compartment_name" { + description = "Name of the created application compartment" + value = oci_identity_compartment.application.name +} + +output "reader_group_id" { + description = "OCID of the readers group" + value = oci_identity_group.readers.id +} + +output "reader_group_name" { + description = "Name of the readers group" + value = oci_identity_group.readers.name +} + +output "user_group_id" { + description = "OCID of the users group" + value = oci_identity_group.users.id +} + +output "user_group_name" { + description = "Name of the users group" + value = oci_identity_group.users.name +} + +output "admin_group_id" { + description = "OCID of the admins group" + value = oci_identity_group.admins.id +} + +output "admin_group_name" { + description = "Name of the admins group" + value = oci_identity_group.admins.name +} + +output "policy_id" { + description = "OCID of the access policy" + value = oci_identity_policy.application.id +} + +output "console_url" { + description = "OCI Console URL for direct access to the compartment" + value = "https://console.${var.region}.oraclecloud.com/?region=${var.region}&compartmentId=${oci_identity_compartment.application.id}" +} diff --git a/modules/oci/application-compartment/buildingblock/provider.tf b/modules/oci/application-compartment/buildingblock/provider.tf new file mode 100644 index 00000000..fdcb3fa6 --- /dev/null +++ b/modules/oci/application-compartment/buildingblock/provider.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + meshstack = { + source = "meshcloud/meshstack" + } + oci = { + source = "oracle/oci" + } + } +} + +provider "oci" { + tenancy_ocid = var.tenancy_ocid +} diff --git a/modules/oci/application-compartment/buildingblock/variables.tf b/modules/oci/application-compartment/buildingblock/variables.tf new file mode 100644 index 00000000..434abbad --- /dev/null +++ b/modules/oci/application-compartment/buildingblock/variables.tf @@ -0,0 +1,71 @@ +variable "tenancy_ocid" { + type = string + description = "OCID of the OCI tenancy" +} + +variable "foundation" { + type = string + description = "Foundation name prefix" +} + +variable "workspace_id" { + type = string + description = "Workspace identifier (e.g., team name or business unit)" +} + +variable "project_id" { + type = string + description = "Project identifier (e.g., application name)" +} + +variable "region" { + type = string + description = "OCI region identifier (e.g., eu-frankfurt-1, us-ashburn-1)" +} + +variable "users" { + description = "List of users from authoritative system" + type = list(object({ + meshIdentifier = string + username = string + firstName = string + lastName = string + email = string + euid = string + roles = list(string) + })) + default = [] +} + +variable "tag_relations" { + type = string + description = "YAML configuration for tag-based compartment mapping" + default = <<-EOT + # meshStack tag names to read + tag_names: + environment: "Environment" + landing_zone: "landingzone_family" + + # Landing zone configurations + landing_zones: + # Sandbox: single compartment for all environments + sandbox: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...sandbox" + + # Cloud-native: per-environment compartments + cloud-native: + environments: + dev: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-dev" + qa: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-qa" + test: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-test" + prod: + compartment_id: "ocid1.compartment.oc1..aaaaaaaa...cloudnative-prod" + + # Fallback if no match + default_compartment_id: "ocid1.compartment.oc1..aaaaaaaa...default" + EOT +} + diff --git a/modules/oci/oracle.png b/modules/oci/oracle.png new file mode 100644 index 0000000000000000000000000000000000000000..754b7405eb5ddf596d99e317e53af325838b73ca GIT binary patch literal 11771 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 Date: Wed, 21 Jan 2026 11:24:06 +0100 Subject: [PATCH 2/9] feat: ignore website builds --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index ccec0980..f8212e9d 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,8 @@ yarn-error.log* *tfvars* .terraform.lock.hcl .env + +# Generated assets +website/public/assets/building-block-logos/ +website/public/assets/logos/ +website/public/assets/*.json From b5d023fda923751b0b779ae5185b1af61b154c96 Mon Sep 17 00:00:00 2001 From: Florian Nowarre Date: Wed, 21 Jan 2026 11:32:24 +0100 Subject: [PATCH 3/9] feat: adding files for hub build --- website/public/assets/platform-logos.json | 7 +- website/public/assets/templates.json | 7317 ++++++++++++++++++++- website/src/app/core/template.ts | 2 +- 3 files changed, 7012 insertions(+), 314 deletions(-) diff --git a/website/public/assets/platform-logos.json b/website/public/assets/platform-logos.json index 615a2579..b1030f6e 100644 --- a/website/public/assets/platform-logos.json +++ b/website/public/assets/platform-logos.json @@ -2,15 +2,18 @@ "aks": "assets/logos/aks.svg", "aws": "assets/logos/aws.svg", "azure": "assets/logos/azure.svg", + "azuredevops": "assets/logos/azuredevops.svg", "cloudfoundry": "assets/logos/cloudfoundry.png", "datadog": "assets/logos/datadog.png", "gcp": "assets/logos/gcp.png", "github": "assets/logos/github.png", "ionos": "assets/logos/ionos.png", - "stackit": "assets/logos/stackit.png", + "kubernetes": "assets/logos/kubernetes.png", + "oci": "assets/logos/oci.png", "openshift": "assets/logos/openshift.png", "openstack": "assets/logos/openstack.png", "ovh": "assets/logos/ovh.png", "sapbtp": "assets/logos/sapbtp.png", + "stackit": "assets/logos/stackit.png", "tencentcloud": "assets/logos/tencentcloud.png" -} +} \ No newline at end of file diff --git a/website/public/assets/templates.json b/website/public/assets/templates.json index add2ac15..7e9850ef 100644 --- a/website/public/assets/templates.json +++ b/website/public/assets/templates.json @@ -4,8 +4,8 @@ "id": "aks-github-connector", "platformType": "aks", "logo": "assets/building-block-logos/aks-github-connector.png", - "buildingBlockUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/aks/github-connector/buildingblock", - "backplaneUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/aks/github-connector/backplane", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aks/github-connector/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aks/github-connector/backplane", "name": "GitHub Actions Integration with AKS", "supportedPlatforms": [ "aks" @@ -13,6 +13,18 @@ "description": "CI/CD pipeline using GitHub Actions for secure, scalable AKS deployment.\n", "howToUse": null, "resources": [ + { + "name": "", + "description": " [additional\\_environment\\_variables](#input\\_additional\\_environment\\_variables)", + "type": "Map of additional environment variable key/value pairs to set as GitHub Actions environment variables.", + "required": false + }, + { + "name": "", + "description": " [github\\_environment\\_name](#input\\_github\\_environment\\_name)", + "type": "Name of the GitHub environment to use for deployments.", + "required": false + }, { "name": "", "description": " [github\\_repo](#input\\_github\\_repo)", @@ -27,6 +39,18 @@ } ], "inputs": [ + { + "name": "", + "description": " [additional\\_environment\\_variables](#input\\_additional\\_environment\\_variables)", + "type": "Map of additional environment variable key/value pairs to set as GitHub Actions environment variables.", + "required": false + }, + { + "name": "", + "description": " [github\\_environment\\_name](#input\\_github\\_environment\\_name)", + "type": "Name of the GitHub environment to use for deployments.", + "required": false + }, { "name": "", "description": " [github\\_repo](#input\\_github\\_repo)", @@ -46,8 +70,8 @@ "id": "aks-postgresql", "platformType": "aks", "logo": "assets/building-block-logos/aks-postgresql.png", - "buildingBlockUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/aks/postgresql/buildingblock", - "backplaneUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/aks/postgresql/backplane", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aks/postgresql/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aks/postgresql/backplane", "name": "PostgreSQL Integration with AKS", "supportedPlatforms": [ "aks" @@ -122,451 +146,3464 @@ ] }, { - "id": "aws-s3_bucket", - "platformType": "aws", - "logo": "assets/building-block-logos/aws-s3_bucket.png", - "buildingBlockUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/aws/s3_bucket/buildingblock", - "backplaneUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/aws/s3_bucket/backplane", - "name": "AWS S3 Bucket", + "id": "aks-starterkit", + "platformType": "aks", + "logo": "assets/building-block-logos/aks-starterkit.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aks/starterkit/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aks/starterkit/backplane", + "name": "AKS Starterkit", "supportedPlatforms": [ - "aws" + "aks" ], - "description": "Provides an AWS S3 bucket for object storage with access controls, lifecycle policies, and encryption.\n", + "description": "The AKS Starterkit provides application teams with a pre-configured Kubernetes environment. It includes two Kubernetes namespaces (dev&prod), a Git repository, a CI/CD pipeline using GitHub Actions, and a secure container registry integration.\n", "howToUse": null, "resources": [ { "name": "", - "description": " [bucket\\_name](#input\\_bucket\\_name)", - "type": "The name of the S3 bucket", + "description": " [archive\\_repo\\_on\\_destroy](#input\\_archive\\_repo\\_on\\_destroy)", + "type": "Whether to archive github repository when destroying the terraform resource, or delete it. Defaults to true (archive).", "required": false }, { "name": "", - "description": " [region](#input\\_region)", - "type": "The AWS region", + "description": " [creator](#input\\_creator)", + "type": "Information about the creator of the resources who will be assigned Project Admin role", "required": false }, { "name": "", - "description": " [bucket\\_arn](#output\\_bucket\\_arn)", - "type": "n/a", + "description": " [full\\_platform\\_identifier](#input\\_full\\_platform\\_identifier)", + "type": "Full platform identifier of the AKS Namespace platform.", "required": false }, { "name": "", - "description": " [bucket\\_domain\\_name](#output\\_bucket\\_domain\\_name)", - "type": "n/a", + "description": " [github\\_actions\\_connector\\_definition\\_version\\_uuid](#input\\_github\\_actions\\_connector\\_definition\\_version\\_uuid)", + "type": "UUID of the GitHub Actions connector building block definition version.", "required": false }, { "name": "", - "description": " [bucket\\_name](#output\\_bucket\\_name)", - "type": "n/a", + "description": " [github\\_org](#input\\_github\\_org)", + "type": "GitHub organization name. Used only for display purposes.", "required": false }, { "name": "", - "description": " [bucket\\_regional\\_domain\\_name](#output\\_bucket\\_regional\\_domain\\_name)", - "type": "n/a", + "description": " [github\\_repo\\_definition\\_uuid](#input\\_github\\_repo\\_definition\\_uuid)", + "type": "UUID of the GitHub repository building block definition.", "required": false }, { "name": "", - "description": " [bucket\\_uri](#output\\_bucket\\_uri)", - "type": "n/a", - "required": false - } - ], - "inputs": [ - { - "name": "", - "description": " [bucket\\_name](#input\\_bucket\\_name)", - "type": "The name of the S3 bucket", + "description": " [github\\_repo\\_definition\\_version\\_uuid](#input\\_github\\_repo\\_definition\\_version\\_uuid)", + "type": "UUID of the GitHub repository building block definition version.", "required": false }, { "name": "", - "description": " [region](#input\\_region)", - "type": "The AWS region", - "required": false - } - ], - "outputs": [ - { - "name": "", - "description": " [bucket\\_arn](#output\\_bucket\\_arn)", - "type": "n/a", + "description": " [github\\_repo\\_input\\_repo\\_visibility](#input\\_github\\_repo\\_input\\_repo\\_visibility)", + "type": "Visibility of the GitHub repository (e.g., public, private).", "required": false }, { "name": "", - "description": " [bucket\\_domain\\_name](#output\\_bucket\\_domain\\_name)", - "type": "n/a", + "description": " [landing\\_zone\\_dev\\_identifier](#input\\_landing\\_zone\\_dev\\_identifier)", + "type": "AKS Landing zone identifier for the development tenant.", "required": false }, { "name": "", - "description": " [bucket\\_name](#output\\_bucket\\_name)", - "type": "n/a", + "description": " [landing\\_zone\\_prod\\_identifier](#input\\_landing\\_zone\\_prod\\_identifier)", + "type": "AKS Landing zone identifier for the production tenant.", "required": false }, { "name": "", - "description": " [bucket\\_regional\\_domain\\_name](#output\\_bucket\\_regional\\_domain\\_name)", - "type": "n/a", + "description": " [name](#input\\_name)", + "type": "This name will be used for the created projects, app subdomain and GitHub repository.", "required": false }, { "name": "", - "description": " [bucket\\_uri](#output\\_bucket\\_uri)", - "type": "n/a", - "required": false - } - ] - }, - { - "id": "azure-budget-alert", - "platformType": "azure", - "logo": "assets/building-block-logos/azure-budget-alert.png", - "buildingBlockUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/azure/budget-alert/buildingblock", - "backplaneUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/azure/budget-alert/backplane", - "name": "Azure Subscription Budget Alert", - "supportedPlatforms": [ - "azure" - ], - "description": "Sets up budget alerts for an Azure subscription to monitor spending and prevent cost overruns.\n", - "howToUse": null, - "resources": [ - { - "name": "", - "description": " [actual\\_threshold\\_percent](#input\\_actual\\_threshold\\_percent)", - "type": "The precise percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "description": " [project\\_tags\\_yaml](#input\\_project\\_tags\\_yaml)", + "type": "YAML configuration for project tags that will be applied to dev and prod projects. Expected structure:
yaml
dev:
key1:
- \"value1\"
- \"value2\"
key2:
- \"value3\"
prod:
key1:
- \"value4\"
key2:
- \"value5\"
- \"value6\"
", "required": false }, { "name": "", - "description": " [budget\\_name](#input\\_budget\\_name)", - "type": "Name of the budget alert rule", + "description": " [repo\\_admin](#input\\_repo\\_admin)", + "type": "GitHub handle of the user who will be assigned as the repository admin. Delete building block definition input if not needed.", "required": false }, { "name": "", - "description": " [contact\\_emails](#input\\_contact\\_emails)", - "type": "Comma-separated list of emails of the users who should receive the Budget alert. e.g. 'foo@example.com, bar@example.com'", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "n/a", "required": false }, { "name": "", - "description": " [forcasted\\_threshold\\_percent](#input\\_forcasted\\_threshold\\_percent)", - "type": "The forcasted percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "description": " [dev-link](#output\\_dev-link)", + "type": "Link to the dev environment Angular app", "required": false }, { "name": "", - "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", - "type": "Set the monthly budget for this subscription in the billing currency.", + "description": " [github\\_repo\\_url](#output\\_github\\_repo\\_url)", + "type": "URL of the created GitHub repository", "required": false }, { "name": "", - "description": " [subscription\\_id](#input\\_subscription\\_id)", - "type": "The ID of the subscription at which you want to assign the budget", + "description": " [prod-link](#output\\_prod-link)", + "type": "Link to the prod environment Angular app", "required": false }, { "name": "", - "description": " [budget\\_amount](#output\\_budget\\_amount)", - "type": "n/a", + "description": " [summary](#output\\_summary)", + "type": "Summary with next steps and insights into created resources", "required": false } ], "inputs": [ { "name": "", - "description": " [actual\\_threshold\\_percent](#input\\_actual\\_threshold\\_percent)", - "type": "The precise percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "description": " [archive\\_repo\\_on\\_destroy](#input\\_archive\\_repo\\_on\\_destroy)", + "type": "Whether to archive github repository when destroying the terraform resource, or delete it. Defaults to true (archive).", "required": false }, { "name": "", - "description": " [budget\\_name](#input\\_budget\\_name)", - "type": "Name of the budget alert rule", + "description": " [creator](#input\\_creator)", + "type": "Information about the creator of the resources who will be assigned Project Admin role", "required": false }, { "name": "", - "description": " [contact\\_emails](#input\\_contact\\_emails)", - "type": "Comma-separated list of emails of the users who should receive the Budget alert. e.g. 'foo@example.com, bar@example.com'", + "description": " [full\\_platform\\_identifier](#input\\_full\\_platform\\_identifier)", + "type": "Full platform identifier of the AKS Namespace platform.", "required": false }, { "name": "", - "description": " [forcasted\\_threshold\\_percent](#input\\_forcasted\\_threshold\\_percent)", - "type": "The forcasted percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "description": " [github\\_actions\\_connector\\_definition\\_version\\_uuid](#input\\_github\\_actions\\_connector\\_definition\\_version\\_uuid)", + "type": "UUID of the GitHub Actions connector building block definition version.", "required": false }, { "name": "", - "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", - "type": "Set the monthly budget for this subscription in the billing currency.", + "description": " [github\\_org](#input\\_github\\_org)", + "type": "GitHub organization name. Used only for display purposes.", "required": false }, { "name": "", - "description": " [subscription\\_id](#input\\_subscription\\_id)", - "type": "The ID of the subscription at which you want to assign the budget", + "description": " [github\\_repo\\_definition\\_uuid](#input\\_github\\_repo\\_definition\\_uuid)", + "type": "UUID of the GitHub repository building block definition.", "required": false - } - ], - "outputs": [ + }, { "name": "", - "description": " [budget\\_amount](#output\\_budget\\_amount)", - "type": "n/a", + "description": " [github\\_repo\\_definition\\_version\\_uuid](#input\\_github\\_repo\\_definition\\_version\\_uuid)", + "type": "UUID of the GitHub repository building block definition version.", "required": false - } - ] - }, - { - "id": "azure-key-vault", - "platformType": "azure", - "logo": "assets/building-block-logos/azure-key-vault.png", - "buildingBlockUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/azure/key-vault/buildingblock", - "backplaneUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/azure/key-vault/backplane", - "name": "Azure Key Vault", - "supportedPlatforms": [ - "azure" - ], - "description": "Provides an Azure Key Vault to securely store and manage secrets, keys, and certificates with access control.\n", - "howToUse": null, - "resources": [ + }, { "name": "", - "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", - "type": "The name of the key vault.", + "description": " [github\\_repo\\_input\\_repo\\_visibility](#input\\_github\\_repo\\_input\\_repo\\_visibility)", + "type": "Visibility of the GitHub repository (e.g., public, private).", "required": false }, { "name": "", - "description": " [key\\_vault\\_resource\\_group\\_name](#input\\_key\\_vault\\_resource\\_group\\_name)", - "type": "The name of the resource group containing the key vault.", + "description": " [landing\\_zone\\_dev\\_identifier](#input\\_landing\\_zone\\_dev\\_identifier)", + "type": "AKS Landing zone identifier for the development tenant.", "required": false }, { "name": "", - "description": " [location](#input\\_location)", - "type": "The location/region where the key vault is created.", + "description": " [landing\\_zone\\_prod\\_identifier](#input\\_landing\\_zone\\_prod\\_identifier)", + "type": "AKS Landing zone identifier for the production tenant.", "required": false }, { "name": "", - "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", - "type": "n/a", + "description": " [name](#input\\_name)", + "type": "This name will be used for the created projects, app subdomain and GitHub repository.", "required": false }, { "name": "", - "description": " [subscription\\_id](#input\\_subscription\\_id)", - "type": "n/a", + "description": " [project\\_tags\\_yaml](#input\\_project\\_tags\\_yaml)", + "type": "YAML configuration for project tags that will be applied to dev and prod projects. Expected structure:
yaml
dev:
key1:
- \"value1\"
- \"value2\"
key2:
- \"value3\"
prod:
key1:
- \"value4\"
key2:
- \"value5\"
- \"value6\"
", "required": false }, { "name": "", - "description": " [users](#input\\_users)", - "type": "Users and their roles provided by meshStack (Note that users must exist in stackit)", + "description": " [repo\\_admin](#input\\_repo\\_admin)", + "type": "GitHub handle of the user who will be assigned as the repository admin. Delete building block definition input if not needed.", "required": false }, { "name": "", - "description": " [key\\_vault\\_id](#output\\_key\\_vault\\_id)", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", "type": "n/a", "required": false - }, + } + ], + "outputs": [ { "name": "", - "description": " [key\\_vault\\_name](#output\\_key\\_vault\\_name)", - "type": "n/a", + "description": " [dev-link](#output\\_dev-link)", + "type": "Link to the dev environment Angular app", "required": false }, { "name": "", - "description": " [key\\_vault\\_resource\\_group](#output\\_key\\_vault\\_resource\\_group)", - "type": "n/a", + "description": " [github\\_repo\\_url](#output\\_github\\_repo\\_url)", + "type": "URL of the created GitHub repository", "required": false - } - ], - "inputs": [ + }, { "name": "", - "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", - "type": "The name of the key vault.", + "description": " [prod-link](#output\\_prod-link)", + "type": "Link to the prod environment Angular app", "required": false }, { "name": "", - "description": " [key\\_vault\\_resource\\_group\\_name](#input\\_key\\_vault\\_resource\\_group\\_name)", - "type": "The name of the resource group containing the key vault.", + "description": " [summary](#output\\_summary)", + "type": "Summary with next steps and insights into created resources", "required": false - }, + } + ] + }, + { + "id": "aws-agentic-coding-sandbox", + "platformType": "aws", + "logo": "assets/building-block-logos/aws-agentic-coding-sandbox.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/agentic-coding-sandbox/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/agentic-coding-sandbox/backplane", + "name": "Agentic Coding Sandbox", + "supportedPlatforms": [ + "aws" + ], + "description": "A composition building block that provides developers with a sandboxed AWS environment\nto access agentic coding tools like Claude via AWS Bedrock, with automatic budget alerts\nand region enablement for AI model access.\n", + "howToUse": null, + "resources": [ { "name": "", - "description": " [location](#input\\_location)", - "type": "The location/region where the key vault is created.", + "description": " [budget\\_amount](#input\\_budget\\_amount)", + "type": "Monthly budget amount. You will receive an alert when the budget is exceeded.", "required": false }, { "name": "", - "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", - "type": "n/a", + "description": " [composition\\_config\\_yaml](#input\\_composition\\_config\\_yaml)", + "type": "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
", "required": false }, { "name": "", - "description": " [subscription\\_id](#input\\_subscription\\_id)", - "type": "n/a", + "description": " [username](#input\\_username)", + "type": "meshStack username of the project contact. This should be an email.", "required": false }, { "name": "", - "description": " [users](#input\\_users)", - "type": "Users and their roles provided by meshStack (Note that users must exist in stackit)", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "Identifier for the owning workspace", "required": false } ], - "outputs": [ + "inputs": [ { "name": "", - "description": " [key\\_vault\\_id](#output\\_key\\_vault\\_id)", - "type": "n/a", + "description": " [budget\\_amount](#input\\_budget\\_amount)", + "type": "Monthly budget amount. You will receive an alert when the budget is exceeded.", "required": false }, { "name": "", - "description": " [key\\_vault\\_name](#output\\_key\\_vault\\_name)", - "type": "n/a", + "description": " [composition\\_config\\_yaml](#input\\_composition\\_config\\_yaml)", + "type": "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
", "required": false }, { "name": "", - "description": " [key\\_vault\\_resource\\_group](#output\\_key\\_vault\\_resource\\_group)", - "type": "n/a", + "description": " [username](#input\\_username)", + "type": "meshStack username of the project contact. This should be an email.", + "required": false + }, + { + "name": "", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "Identifier for the owning workspace", "required": false } - ] + ], + "outputs": [] }, { - "id": "azure-postgresql", - "platformType": "azure", - "logo": "assets/building-block-logos/azure-postgresql.png", - "buildingBlockUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/azure/postgresql/buildingblock", - "backplaneUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/azure/postgresql/backplane", - "name": "Azure PostgreSQL Deployment", + "id": "aws-budget-alert", + "platformType": "aws", + "logo": "assets/building-block-logos/aws-budget-alert.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/budget-alert/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/budget-alert/backplane", + "name": "AWS Budget Alert", "supportedPlatforms": [ - "azure" + "aws" ], - "description": "Provides a managed Azure PostgreSQL database with scalability, security, and high availability.\n", + "description": "Sets up budget alerts for an AWS account to monitor spending and prevent cost overruns.\n", "howToUse": null, "resources": [ { "name": "", - "description": " [administrator\\_login](#input\\_administrator\\_login)", - "type": "Administrator username for PostgreSQL", + "description": " [account\\_id](#input\\_account\\_id)", + "type": "target account id where the budget alert should be created", "required": false }, { "name": "", - "description": " [auto\\_grow\\_enabled](#input\\_auto\\_grow\\_enabled)", - "type": "Enable auto-grow for storage", + "description": " [actual\\_threshold\\_percent](#input\\_actual\\_threshold\\_percent)", + "type": "The precise percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", "required": false }, { "name": "", - "description": " [backup\\_retention\\_days](#input\\_backup\\_retention\\_days)", - "type": "Backup retention in days", + "description": " [assume\\_role\\_name](#input\\_assume\\_role\\_name)", + "type": "The name of the role to assume in target account identified by account\\_id", "required": false }, { "name": "", - "description": " [geo\\_redundant\\_backup\\_enabled](#input\\_geo\\_redundant\\_backup\\_enabled)", - "type": "Enable geo-redundant backups", + "description": " [aws\\_partition](#input\\_aws\\_partition)", + "type": "The AWS partition to use. e.g. aws, aws-cn, aws-us-gov", "required": false }, { "name": "", - "description": " [location](#input\\_location)", - "type": "Azure region", + "description": " [budget\\_name](#input\\_budget\\_name)", + "type": "Name of the budget alert rule", "required": false }, { "name": "", - "description": " [postgresql\\_server\\_name](#input\\_postgresql\\_server\\_name)", - "type": "Name of the PostgreSQL server", + "description": " [contact\\_emails](#input\\_contact\\_emails)", + "type": "Comma-separated list of emails of the users who should receive the Budget alert. e.g. 'foo@example.com, bar@example.com'", "required": false }, { "name": "", - "description": " [postgresql\\_version](#input\\_postgresql\\_version)", - "type": "PostgreSQL version", + "description": " [forecasted\\_threshold\\_percent](#input\\_forecasted\\_threshold\\_percent)", + "type": "The forecasted percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", "required": false }, { "name": "", - "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", - "type": "Enable public network access", + "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", + "type": "Set the monthly budget for this account in USD.", "required": false }, { "name": "", - "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", - "type": "Name of the Azure resource group", + "description": " [budget\\_amount](#output\\_budget\\_amount)", + "type": "The amount of the budget", "required": false }, { "name": "", - "description": " [sku\\_name](#input\\_sku\\_name)", - "type": "The SKU name for the PostgreSQL server", + "description": " [budget\\_id](#output\\_budget\\_id)", + "type": "The ID of the budget", "required": false }, { "name": "", - "description": " [ssl\\_enforcement\\_enabled](#input\\_ssl\\_enforcement\\_enabled)", - "type": "Enforce SSL connection", + "description": " [budget\\_name](#output\\_budget\\_name)", + "type": "The name of the budget", "required": false - }, + } + ], + "inputs": [ { "name": "", - "description": " [ssl\\_minimal\\_tls\\_version\\_enforced](#input\\_ssl\\_minimal\\_tls\\_version\\_enforced)", - "type": "Minimum TLS version", + "description": " [account\\_id](#input\\_account\\_id)", + "type": "target account id where the budget alert should be created", "required": false }, { "name": "", - "description": " [storage\\_mb](#input\\_storage\\_mb)", - "type": "Storage size in MB", + "description": " [actual\\_threshold\\_percent](#input\\_actual\\_threshold\\_percent)", + "type": "The precise percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", "required": false }, { "name": "", - "description": " [subscription\\_id](#input\\_subscription\\_id)", - "type": "the Azure subscription id", + "description": " [assume\\_role\\_name](#input\\_assume\\_role\\_name)", + "type": "The name of the role to assume in target account identified by account\\_id", "required": false }, { "name": "", - "description": " [postgresql\\_admin\\_username](#output\\_postgresql\\_admin\\_username)", - "type": "The administrator username for PostgreSQL", + "description": " [aws\\_partition](#input\\_aws\\_partition)", + "type": "The AWS partition to use. e.g. aws, aws-cn, aws-us-gov", "required": false }, { "name": "", - "description": " [postgresql\\_fqdn](#output\\_postgresql\\_fqdn)", - "type": "The fully qualified domain name of the PostgreSQL server", + "description": " [budget\\_name](#input\\_budget\\_name)", + "type": "Name of the budget alert rule", "required": false }, { "name": "", - "description": " [postgresql\\_server\\_name](#output\\_postgresql\\_server\\_name)", - "type": "The name of the PostgreSQL server", + "description": " [contact\\_emails](#input\\_contact\\_emails)", + "type": "Comma-separated list of emails of the users who should receive the Budget alert. e.g. 'foo@example.com, bar@example.com'", + "required": false + }, + { + "name": "", + "description": " [forecasted\\_threshold\\_percent](#input\\_forecasted\\_threshold\\_percent)", + "type": "The forecasted percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "required": false + }, + { + "name": "", + "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", + "type": "Set the monthly budget for this account in USD.", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [budget\\_amount](#output\\_budget\\_amount)", + "type": "The amount of the budget", + "required": false + }, + { + "name": "", + "description": " [budget\\_id](#output\\_budget\\_id)", + "type": "The ID of the budget", + "required": false + }, + { + "name": "", + "description": " [budget\\_name](#output\\_budget\\_name)", + "type": "The name of the budget", + "required": false + } + ] + }, + { + "id": "aws-opt-in-region", + "platformType": "aws", + "logo": "assets/building-block-logos/aws-opt-in-region.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/opt-in-region/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/opt-in-region/backplane", + "name": "Enable Opt-In Regions", + "supportedPlatforms": [ + "aws" + ], + "description": "The building block enables you to enable AWS regions that require explicit opt-in for your AWS account. This is particularly useful for managing access to newer AWS regions or regions with specific compliance requirements.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [account\\_id](#input\\_account\\_id)", + "type": "The ID of the target account where the opt-in region will be managed", + "required": false + }, + { + "name": "", + "description": " [assume\\_role\\_arn](#input\\_assume\\_role\\_arn)", + "type": "The ARN of the role in the organization management account that the building block will assume to manage opt-in regions", + "required": false + }, + { + "name": "", + "description": " [enabled](#input\\_enabled)", + "type": "Whether the region is enabled", + "required": false + }, + { + "name": "", + "description": " [region](#input\\_region)", + "type": "The region name to manage (e.g., ap-southeast-3, me-central-1, af-south-1)", + "required": false + }, + { + "name": "", + "description": " [opt\\_status](#output\\_opt\\_status)", + "type": "The region opt status", + "required": false + }, + { + "name": "", + "description": " [region](#output\\_region)", + "type": "The region name", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [account\\_id](#input\\_account\\_id)", + "type": "The ID of the target account where the opt-in region will be managed", + "required": false + }, + { + "name": "", + "description": " [assume\\_role\\_arn](#input\\_assume\\_role\\_arn)", + "type": "The ARN of the role in the organization management account that the building block will assume to manage opt-in regions", + "required": false + }, + { + "name": "", + "description": " [enabled](#input\\_enabled)", + "type": "Whether the region is enabled", + "required": false + }, + { + "name": "", + "description": " [region](#input\\_region)", + "type": "The region name to manage (e.g., ap-southeast-3, me-central-1, af-south-1)", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [opt\\_status](#output\\_opt\\_status)", + "type": "The region opt status", + "required": false + }, + { + "name": "", + "description": " [region](#output\\_region)", + "type": "The region name", + "required": false + } + ] + }, + { + "id": "aws-s3_bucket", + "platformType": "aws", + "logo": "assets/building-block-logos/aws-s3_bucket.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/s3_bucket/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/aws/s3_bucket/backplane", + "name": "AWS S3 Bucket", + "supportedPlatforms": [ + "aws" + ], + "description": "Provides an AWS S3 bucket for object storage with access controls, lifecycle policies, and encryption.", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [bucket\\_name](#input\\_bucket\\_name)", + "type": "The name of the S3 bucket", + "required": false + }, + { + "name": "", + "description": " [region](#input\\_region)", + "type": "The AWS region", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "List of tags to apply to the resource", + "required": false + }, + { + "name": "", + "description": " [bucket\\_arn](#output\\_bucket\\_arn)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_domain\\_name](#output\\_bucket\\_domain\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_name](#output\\_bucket\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_regional\\_domain\\_name](#output\\_bucket\\_regional\\_domain\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_uri](#output\\_bucket\\_uri)", + "type": "n/a", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [bucket\\_name](#input\\_bucket\\_name)", + "type": "The name of the S3 bucket", + "required": false + }, + { + "name": "", + "description": " [region](#input\\_region)", + "type": "The AWS region", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "List of tags to apply to the resource", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [bucket\\_arn](#output\\_bucket\\_arn)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_domain\\_name](#output\\_bucket\\_domain\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_name](#output\\_bucket\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_regional\\_domain\\_name](#output\\_bucket\\_regional\\_domain\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_uri](#output\\_bucket\\_uri)", + "type": "n/a", + "required": false + } + ] + }, + { + "id": "azure-aks", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-aks.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/aks/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/aks/backplane", + "name": "AKS Cluster", + "supportedPlatforms": [ + "azure" + ], + "description": "Provision a production-grade Azure Kubernetes Service (AKS) cluster with Azure AD, OIDC, Workload Identity, Log Analytics and custom VNet using Terraform.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [aks\\_admin\\_group\\_object\\_id](#input\\_aks\\_admin\\_group\\_object\\_id)", + "type": "Object ID of the Azure AD group used for AKS admin access. If null, Azure AD RBAC will not be configured.", + "required": false + }, + { + "name": "", + "description": " [aks\\_cluster\\_name](#input\\_aks\\_cluster\\_name)", + "type": "Name of the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [allow\\_gateway\\_transit\\_from\\_hub](#input\\_allow\\_gateway\\_transit\\_from\\_hub)", + "type": "Allow gateway transit from hub to spoke. Set to true if hub has a gateway and you want spoke to use it.", + "required": false + }, + { + "name": "", + "description": " [dns\\_prefix](#input\\_dns\\_prefix)", + "type": "DNS prefix for the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [dns\\_service\\_ip](#input\\_dns\\_service\\_ip)", + "type": "IP address for Kubernetes DNS service (must be within service\\_cidr)", + "required": false + }, + { + "name": "", + "description": " [enable\\_auto\\_scaling](#input\\_enable\\_auto\\_scaling)", + "type": "Enable auto-scaling for the default node pool", + "required": false + }, + { + "name": "", + "description": " [existing\\_vnet\\_resource\\_group\\_name](#input\\_existing\\_vnet\\_resource\\_group\\_name)", + "type": "Resource group name of the existing VNet. Only used when vnet\\_name is provided. Defaults to the AKS resource group if not specified.", + "required": false + }, + { + "name": "", + "description": " [hub\\_resource\\_group\\_name](#input\\_hub\\_resource\\_group\\_name)", + "type": "Resource group name of the hub virtual network. Required when private\\_cluster\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_subscription\\_id](#input\\_hub\\_subscription\\_id)", + "type": "Subscription ID of the hub network. Required when private\\_cluster\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet\\_name](#input\\_hub\\_vnet\\_name)", + "type": "Name of the hub virtual network to peer with. Required when private\\_cluster\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [kubernetes\\_version](#input\\_kubernetes\\_version)", + "type": "Kubernetes version for the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [log\\_analytics\\_workspace\\_name](#input\\_log\\_analytics\\_workspace\\_name)", + "type": "Name of the Log Analytics Workspace. If null, no LAW or monitoring will be created.", + "required": false + }, + { + "name": "", + "description": " [log\\_retention\\_days](#input\\_log\\_retention\\_days)", + "type": "Number of days to retain logs in Log Analytics Workspace", + "required": false + }, + { + "name": "", + "description": " [max\\_node\\_count](#input\\_max\\_node\\_count)", + "type": "Maximum number of nodes for auto-scaling (set to enable auto-scaling)", + "required": false + }, + { + "name": "", + "description": " [min\\_node\\_count](#input\\_min\\_node\\_count)", + "type": "Minimum number of nodes for auto-scaling (set to enable auto-scaling)", + "required": false + }, + { + "name": "", + "description": " [network\\_plugin](#input\\_network\\_plugin)", + "type": "Network plugin to use (azure or kubenet)", + "required": false + }, + { + "name": "", + "description": " [network\\_policy](#input\\_network\\_policy)", + "type": "Network policy to use (azure, calico, or cilium)", + "required": false + }, + { + "name": "", + "description": " [node\\_count](#input\\_node\\_count)", + "type": "Initial number of nodes in the default node pool", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_size\\_gb](#input\\_os\\_disk\\_size\\_gb)", + "type": "OS disk size in GB for the node pool", + "required": false + }, + { + "name": "", + "description": " [private\\_cluster\\_enabled](#input\\_private\\_cluster\\_enabled)", + "type": "Enable private cluster (API server only accessible via private endpoint)", + "required": false + }, + { + "name": "", + "description": " [private\\_cluster\\_public\\_fqdn\\_enabled](#input\\_private\\_cluster\\_public\\_fqdn\\_enabled)", + "type": "Enable public FQDN for private cluster (allows public DNS resolution but API server remains private)", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#input\\_private\\_dns\\_zone\\_id)", + "type": "Private DNS Zone ID for private cluster. Use 'System' for Azure-managed zone, or provide custom zone ID. Only used when private\\_cluster\\_enabled is true.", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group to create for the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [service\\_cidr](#input\\_service\\_cidr)", + "type": "CIDR for Kubernetes services (must not overlap with VNet or subnet)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "Address prefix for the AKS subnet (only used if subnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "Name of the subnet for AKS. If not provided, a new subnet will be created.", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [vm\\_size](#input\\_vm\\_size)", + "type": "Size of the virtual machines for the default node pool", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "Address space for the AKS virtual network (only used if vnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network for AKS. If not provided, a new VNet will be created.", + "required": false + }, + { + "name": "", + "description": " [aks\\_identity\\_client\\_id](#output\\_aks\\_identity\\_client\\_id)", + "type": "Client ID of the AKS system-assigned managed identity", + "required": false + }, + { + "name": "", + "description": " [kube\\_config](#output\\_kube\\_config)", + "type": "Kubeconfig raw output", + "required": false + }, + { + "name": "", + "description": " [law\\_id](#output\\_law\\_id)", + "type": "Log Analytics Workspace ID", + "required": false + }, + { + "name": "", + "description": " [oidc\\_issuer\\_url](#output\\_oidc\\_issuer\\_url)", + "type": "OIDC issuer URL for federated identity and workload identity setup", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "Subnet ID used by AKS", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [aks\\_admin\\_group\\_object\\_id](#input\\_aks\\_admin\\_group\\_object\\_id)", + "type": "Object ID of the Azure AD group used for AKS admin access. If null, Azure AD RBAC will not be configured.", + "required": false + }, + { + "name": "", + "description": " [aks\\_cluster\\_name](#input\\_aks\\_cluster\\_name)", + "type": "Name of the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [allow\\_gateway\\_transit\\_from\\_hub](#input\\_allow\\_gateway\\_transit\\_from\\_hub)", + "type": "Allow gateway transit from hub to spoke. Set to true if hub has a gateway and you want spoke to use it.", + "required": false + }, + { + "name": "", + "description": " [dns\\_prefix](#input\\_dns\\_prefix)", + "type": "DNS prefix for the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [dns\\_service\\_ip](#input\\_dns\\_service\\_ip)", + "type": "IP address for Kubernetes DNS service (must be within service\\_cidr)", + "required": false + }, + { + "name": "", + "description": " [enable\\_auto\\_scaling](#input\\_enable\\_auto\\_scaling)", + "type": "Enable auto-scaling for the default node pool", + "required": false + }, + { + "name": "", + "description": " [existing\\_vnet\\_resource\\_group\\_name](#input\\_existing\\_vnet\\_resource\\_group\\_name)", + "type": "Resource group name of the existing VNet. Only used when vnet\\_name is provided. Defaults to the AKS resource group if not specified.", + "required": false + }, + { + "name": "", + "description": " [hub\\_resource\\_group\\_name](#input\\_hub\\_resource\\_group\\_name)", + "type": "Resource group name of the hub virtual network. Required when private\\_cluster\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_subscription\\_id](#input\\_hub\\_subscription\\_id)", + "type": "Subscription ID of the hub network. Required when private\\_cluster\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet\\_name](#input\\_hub\\_vnet\\_name)", + "type": "Name of the hub virtual network to peer with. Required when private\\_cluster\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [kubernetes\\_version](#input\\_kubernetes\\_version)", + "type": "Kubernetes version for the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [log\\_analytics\\_workspace\\_name](#input\\_log\\_analytics\\_workspace\\_name)", + "type": "Name of the Log Analytics Workspace. If null, no LAW or monitoring will be created.", + "required": false + }, + { + "name": "", + "description": " [log\\_retention\\_days](#input\\_log\\_retention\\_days)", + "type": "Number of days to retain logs in Log Analytics Workspace", + "required": false + }, + { + "name": "", + "description": " [max\\_node\\_count](#input\\_max\\_node\\_count)", + "type": "Maximum number of nodes for auto-scaling (set to enable auto-scaling)", + "required": false + }, + { + "name": "", + "description": " [min\\_node\\_count](#input\\_min\\_node\\_count)", + "type": "Minimum number of nodes for auto-scaling (set to enable auto-scaling)", + "required": false + }, + { + "name": "", + "description": " [network\\_plugin](#input\\_network\\_plugin)", + "type": "Network plugin to use (azure or kubenet)", + "required": false + }, + { + "name": "", + "description": " [network\\_policy](#input\\_network\\_policy)", + "type": "Network policy to use (azure, calico, or cilium)", + "required": false + }, + { + "name": "", + "description": " [node\\_count](#input\\_node\\_count)", + "type": "Initial number of nodes in the default node pool", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_size\\_gb](#input\\_os\\_disk\\_size\\_gb)", + "type": "OS disk size in GB for the node pool", + "required": false + }, + { + "name": "", + "description": " [private\\_cluster\\_enabled](#input\\_private\\_cluster\\_enabled)", + "type": "Enable private cluster (API server only accessible via private endpoint)", + "required": false + }, + { + "name": "", + "description": " [private\\_cluster\\_public\\_fqdn\\_enabled](#input\\_private\\_cluster\\_public\\_fqdn\\_enabled)", + "type": "Enable public FQDN for private cluster (allows public DNS resolution but API server remains private)", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#input\\_private\\_dns\\_zone\\_id)", + "type": "Private DNS Zone ID for private cluster. Use 'System' for Azure-managed zone, or provide custom zone ID. Only used when private\\_cluster\\_enabled is true.", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group to create for the AKS cluster", + "required": false + }, + { + "name": "", + "description": " [service\\_cidr](#input\\_service\\_cidr)", + "type": "CIDR for Kubernetes services (must not overlap with VNet or subnet)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "Address prefix for the AKS subnet (only used if subnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "Name of the subnet for AKS. If not provided, a new subnet will be created.", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [vm\\_size](#input\\_vm\\_size)", + "type": "Size of the virtual machines for the default node pool", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "Address space for the AKS virtual network (only used if vnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network for AKS. If not provided, a new VNet will be created.", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [aks\\_identity\\_client\\_id](#output\\_aks\\_identity\\_client\\_id)", + "type": "Client ID of the AKS system-assigned managed identity", + "required": false + }, + { + "name": "", + "description": " [kube\\_config](#output\\_kube\\_config)", + "type": "Kubeconfig raw output", + "required": false + }, + { + "name": "", + "description": " [law\\_id](#output\\_law\\_id)", + "type": "Log Analytics Workspace ID", + "required": false + }, + { + "name": "", + "description": " [oidc\\_issuer\\_url](#output\\_oidc\\_issuer\\_url)", + "type": "OIDC issuer URL for federated identity and workload identity setup", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "Subnet ID used by AKS", + "required": false + } + ] + }, + { + "id": "azure-azure-bastion", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-azure-bastion.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/azure-bastion/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/azure-bastion/backplane", + "name": "Azure Bastion Host", + "supportedPlatforms": [ + "azure" + ], + "description": "Provides secure RDP and SSH connectivity to virtual machines in Azure virtual networks without exposing them to the public internet, with comprehensive monitoring and alerting.", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [alert\\_email\\_receivers](#input\\_alert\\_email\\_receivers)", + "type": "List of email receivers for alerts provided by meshStack", + "required": false + }, + { + "name": "", + "description": " [alert\\_webhook\\_receivers](#input\\_alert\\_webhook\\_receivers)", + "type": "List of webhook receivers for alerts (Teams, Slack, etc.)", + "required": false + }, + { + "name": "", + "description": " [azure\\_delay\\_seconds](#input\\_azure\\_delay\\_seconds)", + "type": "Delay in seconds to wait for Azure resources to be ready", + "required": false + }, + { + "name": "", + "description": " [bastion\\_sku](#input\\_bastion\\_sku)", + "type": "SKU of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_subnet\\_cidr](#input\\_bastion\\_subnet\\_cidr)", + "type": "CIDR block for the AzureBastionSubnet (minimum /27)", + "required": false + }, + { + "name": "", + "description": " [enable\\_observability](#input\\_enable\\_observability)", + "type": "Enable comprehensive observability (alerts, monitoring)", + "required": false + }, + { + "name": "", + "description": " [enable\\_resource\\_locks](#input\\_enable\\_resource\\_locks)", + "type": "Enable resource locks to prevent accidental deletion/modification", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "Name of the Azure Bastion deployment", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group where Bastion will be deployed", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network where Bastion subnet will be created", + "required": false + }, + { + "name": "", + "description": " [action\\_group\\_id](#output\\_action\\_group\\_id)", + "type": "The ID of the central action group for notifications", + "required": false + }, + { + "name": "", + "description": " [action\\_group\\_name](#output\\_action\\_group\\_name)", + "type": "The name of the central action group for notifications", + "required": false + }, + { + "name": "", + "description": " [bastion\\_host\\_fqdn](#output\\_bastion\\_host\\_fqdn)", + "type": "The FQDN of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_host\\_id](#output\\_bastion\\_host\\_id)", + "type": "The ID of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_host\\_name](#output\\_bastion\\_host\\_name)", + "type": "The name of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_nsg\\_id](#output\\_bastion\\_nsg\\_id)", + "type": "The ID of the Bastion Network Security Group", + "required": false + }, + { + "name": "", + "description": " [bastion\\_public\\_ip](#output\\_bastion\\_public\\_ip)", + "type": "The public IP address of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_resource\\_health\\_alert\\_id](#output\\_bastion\\_resource\\_health\\_alert\\_id)", + "type": "The ID of the Bastion resource health alert", + "required": false + }, + { + "name": "", + "description": " [bastion\\_subnet\\_id](#output\\_bastion\\_subnet\\_id)", + "type": "The ID of the AzureBastionSubnet", + "required": false + }, + { + "name": "", + "description": " [service\\_health\\_alert\\_id](#output\\_service\\_health\\_alert\\_id)", + "type": "The ID of the service health alert", + "required": false + }, + { + "name": "", + "description": " [subscription\\_resource\\_health\\_alert\\_id](#output\\_subscription\\_resource\\_health\\_alert\\_id)", + "type": "The ID of the subscription resource health alert", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#output\\_vnet\\_address\\_space)", + "type": "The address space of the POC Virtual Network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the POC Virtual Network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#output\\_vnet\\_name)", + "type": "The name of the POC Virtual Network", + "required": false + }, + { + "name": "", + "description": " [workload\\_subnet\\_id](#output\\_workload\\_subnet\\_id)", + "type": "The ID of workload subnet", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [alert\\_email\\_receivers](#input\\_alert\\_email\\_receivers)", + "type": "List of email receivers for alerts provided by meshStack", + "required": false + }, + { + "name": "", + "description": " [alert\\_webhook\\_receivers](#input\\_alert\\_webhook\\_receivers)", + "type": "List of webhook receivers for alerts (Teams, Slack, etc.)", + "required": false + }, + { + "name": "", + "description": " [azure\\_delay\\_seconds](#input\\_azure\\_delay\\_seconds)", + "type": "Delay in seconds to wait for Azure resources to be ready", + "required": false + }, + { + "name": "", + "description": " [bastion\\_sku](#input\\_bastion\\_sku)", + "type": "SKU of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_subnet\\_cidr](#input\\_bastion\\_subnet\\_cidr)", + "type": "CIDR block for the AzureBastionSubnet (minimum /27)", + "required": false + }, + { + "name": "", + "description": " [enable\\_observability](#input\\_enable\\_observability)", + "type": "Enable comprehensive observability (alerts, monitoring)", + "required": false + }, + { + "name": "", + "description": " [enable\\_resource\\_locks](#input\\_enable\\_resource\\_locks)", + "type": "Enable resource locks to prevent accidental deletion/modification", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "Name of the Azure Bastion deployment", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group where Bastion will be deployed", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network where Bastion subnet will be created", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [terraform](#requirement\\_terraform)", + "type": ">= 1.3.0", + "required": false + }, + { + "name": "", + "description": " [azurerm](#requirement\\_azurerm)", + "type": "~> 3.116.0", + "required": false + }, + { + "name": "", + "description": " [time](#requirement\\_time)", + "type": "~> 0.11.1", + "required": false + }, + { + "name": "", + "description": " [alert\\_email\\_receivers](#input\\_alert\\_email\\_receivers)", + "type": "List of email receivers for alerts provided by meshStack", + "required": false + }, + { + "name": "", + "description": " [alert\\_webhook\\_receivers](#input\\_alert\\_webhook\\_receivers)", + "type": "List of webhook receivers for alerts (Teams, Slack, etc.)", + "required": false + }, + { + "name": "", + "description": " [azure\\_delay\\_seconds](#input\\_azure\\_delay\\_seconds)", + "type": "Delay in seconds to wait for Azure resources to be ready", + "required": false + }, + { + "name": "", + "description": " [bastion\\_sku](#input\\_bastion\\_sku)", + "type": "SKU of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_subnet\\_cidr](#input\\_bastion\\_subnet\\_cidr)", + "type": "CIDR block for the AzureBastionSubnet (minimum /27)", + "required": false + }, + { + "name": "", + "description": " [enable\\_observability](#input\\_enable\\_observability)", + "type": "Enable comprehensive observability (alerts, monitoring)", + "required": false + }, + { + "name": "", + "description": " [enable\\_resource\\_locks](#input\\_enable\\_resource\\_locks)", + "type": "Enable resource locks to prevent accidental deletion/modification", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "Name of the Azure Bastion deployment", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group where Bastion will be deployed", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network where Bastion subnet will be created", + "required": false + }, + { + "name": "", + "description": " [action\\_group\\_id](#output\\_action\\_group\\_id)", + "type": "The ID of the central action group for notifications", + "required": false + }, + { + "name": "", + "description": " [action\\_group\\_name](#output\\_action\\_group\\_name)", + "type": "The name of the central action group for notifications", + "required": false + }, + { + "name": "", + "description": " [bastion\\_host\\_fqdn](#output\\_bastion\\_host\\_fqdn)", + "type": "The FQDN of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_host\\_id](#output\\_bastion\\_host\\_id)", + "type": "The ID of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_host\\_name](#output\\_bastion\\_host\\_name)", + "type": "The name of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_nsg\\_id](#output\\_bastion\\_nsg\\_id)", + "type": "The ID of the Bastion Network Security Group", + "required": false + }, + { + "name": "", + "description": " [bastion\\_public\\_ip](#output\\_bastion\\_public\\_ip)", + "type": "The public IP address of the Azure Bastion Host", + "required": false + }, + { + "name": "", + "description": " [bastion\\_resource\\_health\\_alert\\_id](#output\\_bastion\\_resource\\_health\\_alert\\_id)", + "type": "The ID of the Bastion resource health alert", + "required": false + }, + { + "name": "", + "description": " [bastion\\_subnet\\_id](#output\\_bastion\\_subnet\\_id)", + "type": "The ID of the AzureBastionSubnet", + "required": false + }, + { + "name": "", + "description": " [service\\_health\\_alert\\_id](#output\\_service\\_health\\_alert\\_id)", + "type": "The ID of the service health alert", + "required": false + }, + { + "name": "", + "description": " [subscription\\_resource\\_health\\_alert\\_id](#output\\_subscription\\_resource\\_health\\_alert\\_id)", + "type": "The ID of the subscription resource health alert", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#output\\_vnet\\_address\\_space)", + "type": "The address space of the POC Virtual Network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the POC Virtual Network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#output\\_vnet\\_name)", + "type": "The name of the POC Virtual Network", + "required": false + }, + { + "name": "", + "description": " [workload\\_subnet\\_id](#output\\_workload\\_subnet\\_id)", + "type": "The ID of workload subnet", + "required": false + } + ] + }, + { + "id": "azure-azure-virtual-machine", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-azure-virtual-machine.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/azure-virtual-machine/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/azure-virtual-machine/backplane", + "name": "Azure Virtual Machine", + "supportedPlatforms": [ + "azure" + ], + "description": "(ALPHA) Provisions an Azure Virtual Machine (VM) with support for both Linux and Windows operating systems, including network interface, optional public IP, network security group, and optional data disk.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [admin\\_password](#input\\_admin\\_password)", + "type": "The admin password for Windows VM (required for Windows)", + "required": false + }, + { + "name": "", + "description": " [admin\\_username](#input\\_admin\\_username)", + "type": "The admin username for the VM", + "required": false + }, + { + "name": "", + "description": " [data\\_disk\\_size\\_gb](#input\\_data\\_disk\\_size\\_gb)", + "type": "The size of the data disk in GB. Set to 0 to skip data disk creation", + "required": false + }, + { + "name": "", + "description": " [data\\_disk\\_storage\\_type](#input\\_data\\_disk\\_storage\\_type)", + "type": "The storage account type for the data disk", + "required": false + }, + { + "name": "", + "description": " [enable\\_public\\_ip](#input\\_enable\\_public\\_ip)", + "type": "Whether to create and assign a public IP address to the VM", + "required": false + }, + { + "name": "", + "description": " [enable\\_spot\\_instance](#input\\_enable\\_spot\\_instance)", + "type": "Enable spot instance for significant cost savings (VM can be evicted when Azure needs capacity)", + "required": false + }, + { + "name": "", + "description": " [image\\_offer](#input\\_image\\_offer)", + "type": "The offer of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_publisher](#input\\_image\\_publisher)", + "type": "The publisher of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_sku](#input\\_image\\_sku)", + "type": "The SKU of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_version](#input\\_image\\_version)", + "type": "The version of the image", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_size\\_gb](#input\\_os\\_disk\\_size\\_gb)", + "type": "The size of the OS disk in GB", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_storage\\_type](#input\\_os\\_disk\\_storage\\_type)", + "type": "The storage account type for the OS disk", + "required": false + }, + { + "name": "", + "description": " [os\\_type](#input\\_os\\_type)", + "type": "The operating system type (Linux or Windows)", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "The name or full resource ID of the resource group (e.g., '/subscriptions/.../resourceGroups/my-rg'). If not provided, a new resource group will be created.", + "required": false + }, + { + "name": "", + "description": " [spot\\_eviction\\_policy](#input\\_spot\\_eviction\\_policy)", + "type": "Eviction policy for spot instances (Deallocate or Delete)", + "required": false + }, + { + "name": "", + "description": " [spot\\_max\\_bid\\_price](#input\\_spot\\_max\\_bid\\_price)", + "type": "Maximum price to pay for spot instance per hour. -1 means pay up to on-demand price. Default is -1 for maximum availability", + "required": false + }, + { + "name": "", + "description": " [ssh\\_public\\_key](#input\\_ssh\\_public\\_key)", + "type": "SSH public key for Linux VM authentication (required for Linux)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "The address prefix for the subnet", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [vm\\_name](#input\\_vm\\_name)", + "type": "The name of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vm\\_size](#input\\_vm\\_size)", + "type": "The size of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "The address space for the virtual network", + "required": false + }, + { + "name": "", + "description": " [azure\\_portal\\_url](#output\\_azure\\_portal\\_url)", + "type": "Direct link to the VM in Azure Portal", + "required": false + }, + { + "name": "", + "description": " [network\\_interface\\_id](#output\\_network\\_interface\\_id)", + "type": "The ID of the network interface", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "The name of the resource group", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "The ID of the subnet", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Markdown summary output of the building block with connection instructions", + "required": false + }, + { + "name": "", + "description": " [vm\\_id](#output\\_vm\\_id)", + "type": "The ID of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vm\\_identity\\_principal\\_id](#output\\_vm\\_identity\\_principal\\_id)", + "type": "The Principal ID of the system-assigned managed identity", + "required": false + }, + { + "name": "", + "description": " [vm\\_name](#output\\_vm\\_name)", + "type": "The name of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vm\\_private\\_ip](#output\\_vm\\_private\\_ip)", + "type": "The private IP address of the VM", + "required": false + }, + { + "name": "", + "description": " [vm\\_public\\_ip](#output\\_vm\\_public\\_ip)", + "type": "The public IP address of the VM (if enabled)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the virtual network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#output\\_vnet\\_name)", + "type": "The name of the virtual network", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [admin\\_password](#input\\_admin\\_password)", + "type": "The admin password for Windows VM (required for Windows)", + "required": false + }, + { + "name": "", + "description": " [admin\\_username](#input\\_admin\\_username)", + "type": "The admin username for the VM", + "required": false + }, + { + "name": "", + "description": " [data\\_disk\\_size\\_gb](#input\\_data\\_disk\\_size\\_gb)", + "type": "The size of the data disk in GB. Set to 0 to skip data disk creation", + "required": false + }, + { + "name": "", + "description": " [data\\_disk\\_storage\\_type](#input\\_data\\_disk\\_storage\\_type)", + "type": "The storage account type for the data disk", + "required": false + }, + { + "name": "", + "description": " [enable\\_public\\_ip](#input\\_enable\\_public\\_ip)", + "type": "Whether to create and assign a public IP address to the VM", + "required": false + }, + { + "name": "", + "description": " [enable\\_spot\\_instance](#input\\_enable\\_spot\\_instance)", + "type": "Enable spot instance for significant cost savings (VM can be evicted when Azure needs capacity)", + "required": false + }, + { + "name": "", + "description": " [image\\_offer](#input\\_image\\_offer)", + "type": "The offer of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_publisher](#input\\_image\\_publisher)", + "type": "The publisher of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_sku](#input\\_image\\_sku)", + "type": "The SKU of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_version](#input\\_image\\_version)", + "type": "The version of the image", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_size\\_gb](#input\\_os\\_disk\\_size\\_gb)", + "type": "The size of the OS disk in GB", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_storage\\_type](#input\\_os\\_disk\\_storage\\_type)", + "type": "The storage account type for the OS disk", + "required": false + }, + { + "name": "", + "description": " [os\\_type](#input\\_os\\_type)", + "type": "The operating system type (Linux or Windows)", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "The name or full resource ID of the resource group (e.g., '/subscriptions/.../resourceGroups/my-rg'). If not provided, a new resource group will be created.", + "required": false + }, + { + "name": "", + "description": " [spot\\_eviction\\_policy](#input\\_spot\\_eviction\\_policy)", + "type": "Eviction policy for spot instances (Deallocate or Delete)", + "required": false + }, + { + "name": "", + "description": " [spot\\_max\\_bid\\_price](#input\\_spot\\_max\\_bid\\_price)", + "type": "Maximum price to pay for spot instance per hour. -1 means pay up to on-demand price. Default is -1 for maximum availability", + "required": false + }, + { + "name": "", + "description": " [ssh\\_public\\_key](#input\\_ssh\\_public\\_key)", + "type": "SSH public key for Linux VM authentication (required for Linux)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "The address prefix for the subnet", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [vm\\_name](#input\\_vm\\_name)", + "type": "The name of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vm\\_size](#input\\_vm\\_size)", + "type": "The size of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "The address space for the virtual network", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [azure\\_portal\\_url](#output\\_azure\\_portal\\_url)", + "type": "Direct link to the VM in Azure Portal", + "required": false + }, + { + "name": "", + "description": " [network\\_interface\\_id](#output\\_network\\_interface\\_id)", + "type": "The ID of the network interface", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "The name of the resource group", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "The ID of the subnet", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Markdown summary output of the building block with connection instructions", + "required": false + }, + { + "name": "", + "description": " [vm\\_id](#output\\_vm\\_id)", + "type": "The ID of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vm\\_identity\\_principal\\_id](#output\\_vm\\_identity\\_principal\\_id)", + "type": "The Principal ID of the system-assigned managed identity", + "required": false + }, + { + "name": "", + "description": " [vm\\_name](#output\\_vm\\_name)", + "type": "The name of the virtual machine", + "required": false + }, + { + "name": "", + "description": " [vm\\_private\\_ip](#output\\_vm\\_private\\_ip)", + "type": "The private IP address of the VM", + "required": false + }, + { + "name": "", + "description": " [vm\\_public\\_ip](#output\\_vm\\_public\\_ip)", + "type": "The public IP address of the VM (if enabled)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the virtual network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#output\\_vnet\\_name)", + "type": "The name of the virtual network", + "required": false + } + ] + }, + { + "id": "azure-azure-virtual-machine-starterkit", + "platformType": "azure", + "logo": null, + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/azure-virtual-machine-starterkit/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/azure-virtual-machine-starterkit/backplane", + "name": "Azure Virtual Machine Starterkit", + "supportedPlatforms": [ + "azure" + ], + "description": "The Azure Virtual Machine Starterkit provides application teams with a pre-configured Azure environment. It includes a dedicated project, an Azure tenant, and a virtual machine for quick provisioning and testing.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [azure\\_vm\\_definition\\_version\\_uuid](#input\\_azure\\_vm\\_definition\\_version\\_uuid)", + "type": "UUID of the Azure Virtual Machine building block definition version.", + "required": false + }, + { + "name": "", + "description": " [creator](#input\\_creator)", + "type": "Information about the creator of the resources who will be assigned Project Admin role", + "required": false + }, + { + "name": "", + "description": " [full\\_platform\\_identifier](#input\\_full\\_platform\\_identifier)", + "type": "Full platform identifier of the Azure platform.", + "required": false + }, + { + "name": "", + "description": " [landing\\_zone\\_identifier](#input\\_landing\\_zone\\_identifier)", + "type": "Azure Landing zone identifier for the tenant.", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "This name will be used for the created project and VM", + "required": false + }, + { + "name": "", + "description": " [project\\_tags\\_yaml](#input\\_project\\_tags\\_yaml)", + "type": "YAML configuration for project tags. Expected structure:
yaml
key1:
- \"value1\"
- \"value2\"
key2:
- \"value3\"
", + "required": false + }, + { + "name": "", + "description": " [vm\\_admin\\_password](#input\\_vm\\_admin\\_password)", + "type": "The admin password for Windows VM (required for Windows).", + "required": false + }, + { + "name": "", + "description": " [vm\\_admin\\_username](#input\\_vm\\_admin\\_username)", + "type": "The admin username for the VM.", + "required": false + }, + { + "name": "", + "description": " [vm\\_enable\\_public\\_ip](#input\\_vm\\_enable\\_public\\_ip)", + "type": "Whether to create and assign a public IP address to the VM.", + "required": false + }, + { + "name": "", + "description": " [vm\\_location](#input\\_vm\\_location)", + "type": "The Azure region where the VM will be deployed.", + "required": false + }, + { + "name": "", + "description": " [vm\\_os\\_type](#input\\_vm\\_os\\_type)", + "type": "The operating system type (Linux or Windows).", + "required": false + }, + { + "name": "", + "description": " [vm\\_size](#input\\_vm\\_size)", + "type": "The size of the virtual machine.", + "required": false + }, + { + "name": "", + "description": " [vm\\_ssh\\_public\\_key](#input\\_vm\\_ssh\\_public\\_key)", + "type": "SSH public key for Linux VM authentication (required for Linux).", + "required": false + }, + { + "name": "", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "The identifier of the meshStack workspace", + "required": false + }, + { + "name": "", + "description": " [project\\_name](#output\\_project\\_name)", + "type": "Name of the created meshStack project", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Summary with next steps and insights into created resources", + "required": false + }, + { + "name": "", + "description": " [tenant\\_uuid](#output\\_tenant\\_uuid)", + "type": "UUID of the created Azure tenant", + "required": false + }, + { + "name": "", + "description": " [vm\\_building\\_block\\_uuid](#output\\_vm\\_building\\_block\\_uuid)", + "type": "UUID of the Azure VM building block", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [azure\\_vm\\_definition\\_version\\_uuid](#input\\_azure\\_vm\\_definition\\_version\\_uuid)", + "type": "UUID of the Azure Virtual Machine building block definition version.", + "required": false + }, + { + "name": "", + "description": " [creator](#input\\_creator)", + "type": "Information about the creator of the resources who will be assigned Project Admin role", + "required": false + }, + { + "name": "", + "description": " [full\\_platform\\_identifier](#input\\_full\\_platform\\_identifier)", + "type": "Full platform identifier of the Azure platform.", + "required": false + }, + { + "name": "", + "description": " [landing\\_zone\\_identifier](#input\\_landing\\_zone\\_identifier)", + "type": "Azure Landing zone identifier for the tenant.", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "This name will be used for the created project and VM", + "required": false + }, + { + "name": "", + "description": " [project\\_tags\\_yaml](#input\\_project\\_tags\\_yaml)", + "type": "YAML configuration for project tags. Expected structure:
yaml
key1:
- \"value1\"
- \"value2\"
key2:
- \"value3\"
", + "required": false + }, + { + "name": "", + "description": " [vm\\_admin\\_password](#input\\_vm\\_admin\\_password)", + "type": "The admin password for Windows VM (required for Windows).", + "required": false + }, + { + "name": "", + "description": " [vm\\_admin\\_username](#input\\_vm\\_admin\\_username)", + "type": "The admin username for the VM.", + "required": false + }, + { + "name": "", + "description": " [vm\\_enable\\_public\\_ip](#input\\_vm\\_enable\\_public\\_ip)", + "type": "Whether to create and assign a public IP address to the VM.", + "required": false + }, + { + "name": "", + "description": " [vm\\_location](#input\\_vm\\_location)", + "type": "The Azure region where the VM will be deployed.", + "required": false + }, + { + "name": "", + "description": " [vm\\_os\\_type](#input\\_vm\\_os\\_type)", + "type": "The operating system type (Linux or Windows).", + "required": false + }, + { + "name": "", + "description": " [vm\\_size](#input\\_vm\\_size)", + "type": "The size of the virtual machine.", + "required": false + }, + { + "name": "", + "description": " [vm\\_ssh\\_public\\_key](#input\\_vm\\_ssh\\_public\\_key)", + "type": "SSH public key for Linux VM authentication (required for Linux).", + "required": false + }, + { + "name": "", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "The identifier of the meshStack workspace", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [project\\_name](#output\\_project\\_name)", + "type": "Name of the created meshStack project", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Summary with next steps and insights into created resources", + "required": false + }, + { + "name": "", + "description": " [tenant\\_uuid](#output\\_tenant\\_uuid)", + "type": "UUID of the created Azure tenant", + "required": false + }, + { + "name": "", + "description": " [vm\\_building\\_block\\_uuid](#output\\_vm\\_building\\_block\\_uuid)", + "type": "UUID of the Azure VM building block", + "required": false + } + ] + }, + { + "id": "azure-budget-alert", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-budget-alert.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/budget-alert/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/budget-alert/backplane", + "name": "Azure Subscription Budget Alert", + "supportedPlatforms": [ + "azure" + ], + "description": "Sets up budget alerts for an Azure subscription to monitor spending and prevent cost overruns.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [actual\\_threshold\\_percent](#input\\_actual\\_threshold\\_percent)", + "type": "The precise percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "required": false + }, + { + "name": "", + "description": " [budget\\_name](#input\\_budget\\_name)", + "type": "Name of the budget alert rule", + "required": false + }, + { + "name": "", + "description": " [contact\\_emails](#input\\_contact\\_emails)", + "type": "Comma-separated list of emails of the users who should receive the Budget alert. e.g. 'foo@example.com, bar@example.com'", + "required": false + }, + { + "name": "", + "description": " [forcasted\\_threshold\\_percent](#input\\_forcasted\\_threshold\\_percent)", + "type": "The forcasted percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "required": false + }, + { + "name": "", + "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", + "type": "Set the monthly budget for this subscription in the billing currency.", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#input\\_subscription\\_id)", + "type": "The ID of the subscription at which you want to assign the budget", + "required": false + }, + { + "name": "", + "description": " [budget\\_amount](#output\\_budget\\_amount)", + "type": "n/a", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [actual\\_threshold\\_percent](#input\\_actual\\_threshold\\_percent)", + "type": "The precise percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "required": false + }, + { + "name": "", + "description": " [budget\\_name](#input\\_budget\\_name)", + "type": "Name of the budget alert rule", + "required": false + }, + { + "name": "", + "description": " [contact\\_emails](#input\\_contact\\_emails)", + "type": "Comma-separated list of emails of the users who should receive the Budget alert. e.g. 'foo@example.com, bar@example.com'", + "required": false + }, + { + "name": "", + "description": " [forcasted\\_threshold\\_percent](#input\\_forcasted\\_threshold\\_percent)", + "type": "The forcasted percentage of the monthly budget at which you wish to activate the alert upon reaching. E.g. '15' for 15% or '120' for 120%", + "required": false + }, + { + "name": "", + "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", + "type": "Set the monthly budget for this subscription in the billing currency.", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#input\\_subscription\\_id)", + "type": "The ID of the subscription at which you want to assign the budget", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [budget\\_amount](#output\\_budget\\_amount)", + "type": "n/a", + "required": false + } + ] + }, + { + "id": "azure-container-registry", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-container-registry.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/container-registry/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/container-registry/backplane", + "name": "Azure Container Registry", + "supportedPlatforms": [ + "azure" + ], + "description": "Provides a production-grade Azure Container Registry for storing and managing Docker container images and OCI artifacts with private networking support.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [acr\\_name](#input\\_acr\\_name)", + "type": "Name of the Azure Container Registry (must be globally unique, alphanumeric only)", + "required": false + }, + { + "name": "", + "description": " [admin\\_enabled](#input\\_admin\\_enabled)", + "type": "Enable admin user for basic authentication (not recommended for production)", + "required": false + }, + { + "name": "", + "description": " [aks\\_managed\\_identity\\_principal\\_id](#input\\_aks\\_managed\\_identity\\_principal\\_id)", + "type": "Principal ID of the AKS managed identity to grant AcrPull access. If provided, AcrPull role will be assigned automatically.", + "required": false + }, + { + "name": "", + "description": " [allow\\_gateway\\_transit\\_from\\_hub](#input\\_allow\\_gateway\\_transit\\_from\\_hub)", + "type": "Allow gateway transit from hub to spoke. Set to true if hub has a gateway and you want spoke to use it.", + "required": false + }, + { + "name": "", + "description": " [allowed\\_ip\\_ranges](#input\\_allowed\\_ip\\_ranges)", + "type": "List of IP ranges (CIDR) allowed to access the ACR", + "required": false + }, + { + "name": "", + "description": " [anonymous\\_pull\\_enabled](#input\\_anonymous\\_pull\\_enabled)", + "type": "Enable anonymous pull access (allows unauthenticated pulls)", + "required": false + }, + { + "name": "", + "description": " [data\\_endpoint\\_enabled](#input\\_data\\_endpoint\\_enabled)", + "type": "Enable dedicated data endpoints (Premium SKU only)", + "required": false + }, + { + "name": "", + "description": " [existing\\_vnet\\_resource\\_group\\_name](#input\\_existing\\_vnet\\_resource\\_group\\_name)", + "type": "Resource group name of the existing VNet. Only used when vnet\\_name is provided. Defaults to the ACR resource group if not specified.", + "required": false + }, + { + "name": "", + "description": " [hub\\_resource\\_group\\_name](#input\\_hub\\_resource\\_group\\_name)", + "type": "Resource group name of the hub virtual network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_subscription\\_id](#input\\_hub\\_subscription\\_id)", + "type": "Subscription ID of the hub network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet\\_name](#input\\_hub\\_vnet\\_name)", + "type": "Name of the hub virtual network to peer with. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [network\\_rule\\_bypass\\_option](#input\\_network\\_rule\\_bypass\\_option)", + "type": "Whether to allow trusted Azure services to bypass network rules (AzureServices or None)", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#input\\_private\\_dns\\_zone\\_id)", + "type": "Private DNS Zone ID for private endpoint. Use 'System' for Azure-managed zone, or provide custom zone ID. Only used when private\\_endpoint\\_enabled is true.", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_enabled](#input\\_private\\_endpoint\\_enabled)", + "type": "Enable private endpoint for ACR (Premium SKU required)", + "required": false + }, + { + "name": "", + "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", + "type": "Enable public network access to the ACR", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group to create for the ACR", + "required": false + }, + { + "name": "", + "description": " [retention\\_days](#input\\_retention\\_days)", + "type": "Number of days to retain untagged manifests (Premium SKU only, 0 to disable)", + "required": false + }, + { + "name": "", + "description": " [sku](#input\\_sku)", + "type": "SKU tier for the ACR (Basic, Standard, Premium). Premium required for private endpoints.", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "Address prefix for the private endpoint subnet (only used if subnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "Name of the subnet for private endpoint. If not provided, a new subnet will be created.", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [trust\\_policy\\_enabled](#input\\_trust\\_policy\\_enabled)", + "type": "Enable content trust policy (Premium SKU only)", + "required": false + }, + { + "name": "", + "description": " [use\\_remote\\_gateways](#input\\_use\\_remote\\_gateways)", + "type": "Use remote gateways from hub VNet. Set to true only if hub has a VPN/ExpressRoute gateway configured.", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "Address space for the VNet (only used if vnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network for private endpoint. If not provided, a new VNet will be created.", + "required": false + }, + { + "name": "", + "description": " [zone\\_redundancy\\_enabled](#input\\_zone\\_redundancy\\_enabled)", + "type": "Enable zone redundancy for the ACR (Premium SKU only, available in select regions)", + "required": false + }, + { + "name": "", + "description": " [acr\\_id](#output\\_acr\\_id)", + "type": "The ID of the Azure Container Registry", + "required": false + }, + { + "name": "", + "description": " [acr\\_login\\_server](#output\\_acr\\_login\\_server)", + "type": "The login server URL for the Azure Container Registry", + "required": false + }, + { + "name": "", + "description": " [acr\\_name](#output\\_acr\\_name)", + "type": "The name of the Azure Container Registry", + "required": false + }, + { + "name": "", + "description": " [admin\\_password](#output\\_admin\\_password)", + "type": "Admin password for the Azure Container Registry (only available when admin\\_enabled is true)", + "required": false + }, + { + "name": "", + "description": " [admin\\_username](#output\\_admin\\_username)", + "type": "Admin username for the Azure Container Registry (only available when admin\\_enabled is true)", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#output\\_private\\_dns\\_zone\\_id)", + "type": "ID of the private DNS zone (when System-managed)", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_ip](#output\\_private\\_endpoint\\_ip)", + "type": "Private IP address of the ACR private endpoint", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the ACR", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "ID of the subnet used for private endpoint", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "ID of the virtual network used for private endpoint", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [acr\\_name](#input\\_acr\\_name)", + "type": "Name of the Azure Container Registry (must be globally unique, alphanumeric only)", + "required": false + }, + { + "name": "", + "description": " [admin\\_enabled](#input\\_admin\\_enabled)", + "type": "Enable admin user for basic authentication (not recommended for production)", + "required": false + }, + { + "name": "", + "description": " [aks\\_managed\\_identity\\_principal\\_id](#input\\_aks\\_managed\\_identity\\_principal\\_id)", + "type": "Principal ID of the AKS managed identity to grant AcrPull access. If provided, AcrPull role will be assigned automatically.", + "required": false + }, + { + "name": "", + "description": " [allow\\_gateway\\_transit\\_from\\_hub](#input\\_allow\\_gateway\\_transit\\_from\\_hub)", + "type": "Allow gateway transit from hub to spoke. Set to true if hub has a gateway and you want spoke to use it.", + "required": false + }, + { + "name": "", + "description": " [allowed\\_ip\\_ranges](#input\\_allowed\\_ip\\_ranges)", + "type": "List of IP ranges (CIDR) allowed to access the ACR", + "required": false + }, + { + "name": "", + "description": " [anonymous\\_pull\\_enabled](#input\\_anonymous\\_pull\\_enabled)", + "type": "Enable anonymous pull access (allows unauthenticated pulls)", + "required": false + }, + { + "name": "", + "description": " [data\\_endpoint\\_enabled](#input\\_data\\_endpoint\\_enabled)", + "type": "Enable dedicated data endpoints (Premium SKU only)", + "required": false + }, + { + "name": "", + "description": " [existing\\_vnet\\_resource\\_group\\_name](#input\\_existing\\_vnet\\_resource\\_group\\_name)", + "type": "Resource group name of the existing VNet. Only used when vnet\\_name is provided. Defaults to the ACR resource group if not specified.", + "required": false + }, + { + "name": "", + "description": " [hub\\_resource\\_group\\_name](#input\\_hub\\_resource\\_group\\_name)", + "type": "Resource group name of the hub virtual network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_subscription\\_id](#input\\_hub\\_subscription\\_id)", + "type": "Subscription ID of the hub network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet\\_name](#input\\_hub\\_vnet\\_name)", + "type": "Name of the hub virtual network to peer with. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [network\\_rule\\_bypass\\_option](#input\\_network\\_rule\\_bypass\\_option)", + "type": "Whether to allow trusted Azure services to bypass network rules (AzureServices or None)", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#input\\_private\\_dns\\_zone\\_id)", + "type": "Private DNS Zone ID for private endpoint. Use 'System' for Azure-managed zone, or provide custom zone ID. Only used when private\\_endpoint\\_enabled is true.", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_enabled](#input\\_private\\_endpoint\\_enabled)", + "type": "Enable private endpoint for ACR (Premium SKU required)", + "required": false + }, + { + "name": "", + "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", + "type": "Enable public network access to the ACR", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group to create for the ACR", + "required": false + }, + { + "name": "", + "description": " [retention\\_days](#input\\_retention\\_days)", + "type": "Number of days to retain untagged manifests (Premium SKU only, 0 to disable)", + "required": false + }, + { + "name": "", + "description": " [sku](#input\\_sku)", + "type": "SKU tier for the ACR (Basic, Standard, Premium). Premium required for private endpoints.", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "Address prefix for the private endpoint subnet (only used if subnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "Name of the subnet for private endpoint. If not provided, a new subnet will be created.", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [trust\\_policy\\_enabled](#input\\_trust\\_policy\\_enabled)", + "type": "Enable content trust policy (Premium SKU only)", + "required": false + }, + { + "name": "", + "description": " [use\\_remote\\_gateways](#input\\_use\\_remote\\_gateways)", + "type": "Use remote gateways from hub VNet. Set to true only if hub has a VPN/ExpressRoute gateway configured.", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "Address space for the VNet (only used if vnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network for private endpoint. If not provided, a new VNet will be created.", + "required": false + }, + { + "name": "", + "description": " [zone\\_redundancy\\_enabled](#input\\_zone\\_redundancy\\_enabled)", + "type": "Enable zone redundancy for the ACR (Premium SKU only, available in select regions)", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [acr\\_id](#output\\_acr\\_id)", + "type": "The ID of the Azure Container Registry", + "required": false + }, + { + "name": "", + "description": " [acr\\_login\\_server](#output\\_acr\\_login\\_server)", + "type": "The login server URL for the Azure Container Registry", + "required": false + }, + { + "name": "", + "description": " [acr\\_name](#output\\_acr\\_name)", + "type": "The name of the Azure Container Registry", + "required": false + }, + { + "name": "", + "description": " [admin\\_password](#output\\_admin\\_password)", + "type": "Admin password for the Azure Container Registry (only available when admin\\_enabled is true)", + "required": false + }, + { + "name": "", + "description": " [admin\\_username](#output\\_admin\\_username)", + "type": "Admin username for the Azure Container Registry (only available when admin\\_enabled is true)", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#output\\_private\\_dns\\_zone\\_id)", + "type": "ID of the private DNS zone (when System-managed)", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_ip](#output\\_private\\_endpoint\\_ip)", + "type": "Private IP address of the ACR private endpoint", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the ACR", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "ID of the subnet used for private endpoint", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "ID of the virtual network used for private endpoint", + "required": false + } + ] + }, + { + "id": "azure-github-actions-terraform-setup", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-github-actions-terraform-setup.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/github-actions-terraform-setup/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/github-actions-terraform-setup/backplane", + "name": "Azure GitHub Actions Terraform Setup", + "supportedPlatforms": [ + "azure" + ], + "description": "Deploy directly to Azure using GitHub Actions and Terraform brought to you by meshStack\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [deploy\\_role\\_definition\\_id](#input\\_deploy\\_role\\_definition\\_id)", + "type": "Role definition ID to assign to the GitHub Actions App Service Managed Identity. This is used to deploy resources via Terraform.", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [project\\_identifier](#input\\_project\\_identifier)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_name](#input\\_repo\\_name)", + "type": "Name of the repository to connect.", + "required": false + }, + { + "name": "", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repository\\_html\\_url](#output\\_repository\\_html\\_url)", + "type": "n/a", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [deploy\\_role\\_definition\\_id](#input\\_deploy\\_role\\_definition\\_id)", + "type": "Role definition ID to assign to the GitHub Actions App Service Managed Identity. This is used to deploy resources via Terraform.", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [project\\_identifier](#input\\_project\\_identifier)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_name](#input\\_repo\\_name)", + "type": "Name of the repository to connect.", + "required": false + }, + { + "name": "", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "n/a", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [repository\\_html\\_url](#output\\_repository\\_html\\_url)", + "type": "n/a", + "required": false + } + ] + }, + { + "id": "azure-github-actions-terraform-setup-buildingblock", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-github-actions-terraform-setup-buildingblock.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/github-actions-terraform-setup/buildingblock/pre_role_assignment", + "backplaneUrl": null, + "name": "Role Assignments for GitHub Actions Terraform Setup", + "supportedPlatforms": [ + "azure" + ], + "description": "Helper building block used to assign the necessary Azure roles\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [deploy\\_role\\_definition\\_id](#input\\_deploy\\_role\\_definition\\_id)", + "type": "Role definition ID to assign to the GitHub Actions App Service Managed Identity. This is used to deploy resources via Terraform.", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [deploy\\_role\\_definition\\_id](#input\\_deploy\\_role\\_definition\\_id)", + "type": "Role definition ID to assign to the GitHub Actions App Service Managed Identity. This is used to deploy resources via Terraform.", + "required": false + } + ], + "outputs": [] + }, + { + "id": "azure-key-vault", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-key-vault.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/key-vault/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/key-vault/backplane", + "name": "Azure Key Vault", + "supportedPlatforms": [ + "azure" + ], + "description": "Provides an Azure Key Vault for secure storage and management of secrets, keys, and certificates with RBAC authorization, optional private endpoint support, and hub connectivity.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [allow\\_gateway\\_transit\\_from\\_hub](#input\\_allow\\_gateway\\_transit\\_from\\_hub)", + "type": "Allow gateway transit from hub to spoke. Set to true if hub has a gateway and you want spoke to use it.", + "required": false + }, + { + "name": "", + "description": " [existing\\_vnet\\_resource\\_group\\_name](#input\\_existing\\_vnet\\_resource\\_group\\_name)", + "type": "Resource group name of the existing VNet. Only used when vnet\\_name is provided. Defaults to the Key Vault resource group if not specified.", + "required": false + }, + { + "name": "", + "description": " [hub\\_resource\\_group\\_name](#input\\_hub\\_resource\\_group\\_name)", + "type": "Resource group name of the hub virtual network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_subscription\\_id](#input\\_hub\\_subscription\\_id)", + "type": "Subscription ID of the hub network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet\\_name](#input\\_hub\\_vnet\\_name)", + "type": "Name of the hub virtual network to peer with. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "The name of the key vault.", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_resource\\_group\\_name](#input\\_key\\_vault\\_resource\\_group\\_name)", + "type": "The name of the resource group containing the key vault.", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The location/region where the key vault is created.", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#input\\_private\\_dns\\_zone\\_id)", + "type": "Private DNS Zone ID for private endpoint. Use 'System' for Azure-managed zone, or provide custom zone ID. Only used when private\\_endpoint\\_enabled is true.", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_enabled](#input\\_private\\_endpoint\\_enabled)", + "type": "Enable private endpoint for Key Vault", + "required": false + }, + { + "name": "", + "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "Address prefix for the private endpoint subnet (only used if subnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "Name of the subnet for private endpoint. If not provided, a new subnet will be created.", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [use\\_remote\\_gateways](#input\\_use\\_remote\\_gateways)", + "type": "Use remote gateways from hub VNet. Set to true only if hub has a VPN/ExpressRoute gateway configured.", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "Address space for the VNet (only used if vnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network for private endpoint. If not provided, a new VNet will be created.", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_id](#output\\_key\\_vault\\_id)", + "type": "The ID of the Azure Key Vault", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#output\\_key\\_vault\\_name)", + "type": "The name of the Azure Key Vault", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_resource\\_group](#output\\_key\\_vault\\_resource\\_group)", + "type": "Name of the resource group containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_uri](#output\\_key\\_vault\\_uri)", + "type": "The URI of the Azure Key Vault", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#output\\_private\\_dns\\_zone\\_id)", + "type": "ID of the private DNS zone (when System-managed)", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_ip](#output\\_private\\_endpoint\\_ip)", + "type": "Private IP address of the Key Vault private endpoint", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "ID of the subnet used for private endpoint", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "ID of the virtual network used for private endpoint", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [allow\\_gateway\\_transit\\_from\\_hub](#input\\_allow\\_gateway\\_transit\\_from\\_hub)", + "type": "Allow gateway transit from hub to spoke. Set to true if hub has a gateway and you want spoke to use it.", + "required": false + }, + { + "name": "", + "description": " [existing\\_vnet\\_resource\\_group\\_name](#input\\_existing\\_vnet\\_resource\\_group\\_name)", + "type": "Resource group name of the existing VNet. Only used when vnet\\_name is provided. Defaults to the Key Vault resource group if not specified.", + "required": false + }, + { + "name": "", + "description": " [hub\\_resource\\_group\\_name](#input\\_hub\\_resource\\_group\\_name)", + "type": "Resource group name of the hub virtual network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_subscription\\_id](#input\\_hub\\_subscription\\_id)", + "type": "Subscription ID of the hub network. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet\\_name](#input\\_hub\\_vnet\\_name)", + "type": "Name of the hub virtual network to peer with. Required when private\\_endpoint\\_enabled is true and connecting to a hub.", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "The name of the key vault.", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_resource\\_group\\_name](#input\\_key\\_vault\\_resource\\_group\\_name)", + "type": "The name of the resource group containing the key vault.", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The location/region where the key vault is created.", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#input\\_private\\_dns\\_zone\\_id)", + "type": "Private DNS Zone ID for private endpoint. Use 'System' for Azure-managed zone, or provide custom zone ID. Only used when private\\_endpoint\\_enabled is true.", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_enabled](#input\\_private\\_endpoint\\_enabled)", + "type": "Enable private endpoint for Key Vault", + "required": false + }, + { + "name": "", + "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [subnet\\_address\\_prefix](#input\\_subnet\\_address\\_prefix)", + "type": "Address prefix for the private endpoint subnet (only used if subnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "Name of the subnet for private endpoint. If not provided, a new subnet will be created.", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [use\\_remote\\_gateways](#input\\_use\\_remote\\_gateways)", + "type": "Use remote gateways from hub VNet. Set to true only if hub has a VPN/ExpressRoute gateway configured.", + "required": false + }, + { + "name": "", + "description": " [vnet\\_address\\_space](#input\\_vnet\\_address\\_space)", + "type": "Address space for the VNet (only used if vnet\\_name is not provided)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "Name of the virtual network for private endpoint. If not provided, a new VNet will be created.", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [key\\_vault\\_id](#output\\_key\\_vault\\_id)", + "type": "The ID of the Azure Key Vault", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#output\\_key\\_vault\\_name)", + "type": "The name of the Azure Key Vault", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_resource\\_group](#output\\_key\\_vault\\_resource\\_group)", + "type": "Name of the resource group containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_uri](#output\\_key\\_vault\\_uri)", + "type": "The URI of the Azure Key Vault", + "required": false + }, + { + "name": "", + "description": " [private\\_dns\\_zone\\_id](#output\\_private\\_dns\\_zone\\_id)", + "type": "ID of the private DNS zone (when System-managed)", + "required": false + }, + { + "name": "", + "description": " [private\\_endpoint\\_ip](#output\\_private\\_endpoint\\_ip)", + "type": "Private IP address of the Key Vault private endpoint", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "ID of the subnet used for private endpoint", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "ID of the virtual network used for private endpoint", + "required": false + } + ] + }, + { + "id": "azure-postgresql", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-postgresql.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/postgresql/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/postgresql/backplane", + "name": "Azure PostgreSQL Deployment", + "supportedPlatforms": [ + "azure" + ], + "description": "Provides a managed Azure PostgreSQL database with scalability, security, and high availability.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [administrator\\_login](#input\\_administrator\\_login)", + "type": "Administrator username for PostgreSQL", + "required": false + }, + { + "name": "", + "description": " [auto\\_grow\\_enabled](#input\\_auto\\_grow\\_enabled)", + "type": "Enable auto-grow for storage", + "required": false + }, + { + "name": "", + "description": " [backup\\_retention\\_days](#input\\_backup\\_retention\\_days)", + "type": "Backup retention in days", + "required": false + }, + { + "name": "", + "description": " [geo\\_redundant\\_backup\\_enabled](#input\\_geo\\_redundant\\_backup\\_enabled)", + "type": "Enable geo-redundant backups", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_server\\_name](#input\\_postgresql\\_server\\_name)", + "type": "Name of the PostgreSQL server", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_version](#input\\_postgresql\\_version)", + "type": "PostgreSQL version", + "required": false + }, + { + "name": "", + "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", + "type": "Enable public network access", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the Azure resource group", + "required": false + }, + { + "name": "", + "description": " [sku\\_name](#input\\_sku\\_name)", + "type": "The SKU name for the PostgreSQL server", + "required": false + }, + { + "name": "", + "description": " [ssl\\_enforcement\\_enabled](#input\\_ssl\\_enforcement\\_enabled)", + "type": "Enforce SSL connection", + "required": false + }, + { + "name": "", + "description": " [ssl\\_minimal\\_tls\\_version\\_enforced](#input\\_ssl\\_minimal\\_tls\\_version\\_enforced)", + "type": "Minimum TLS version", + "required": false + }, + { + "name": "", + "description": " [storage\\_mb](#input\\_storage\\_mb)", + "type": "Storage size in MB", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#input\\_subscription\\_id)", + "type": "the Azure subscription id", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_admin\\_username](#output\\_postgresql\\_admin\\_username)", + "type": "The administrator username for PostgreSQL", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_fqdn](#output\\_postgresql\\_fqdn)", + "type": "The fully qualified domain name of the PostgreSQL server", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_server\\_name](#output\\_postgresql\\_server\\_name)", + "type": "The name of the PostgreSQL server", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_version](#output\\_postgresql\\_version)", + "type": "The PostgreSQL version", + "required": false + }, + { + "name": "", + "description": " [psql\\_admin\\_password](#output\\_psql\\_admin\\_password)", + "type": "The administrator password for PostgreSQL", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "The name of the resource group in which the PostgreSQL database is created", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [administrator\\_login](#input\\_administrator\\_login)", + "type": "Administrator username for PostgreSQL", + "required": false + }, + { + "name": "", + "description": " [auto\\_grow\\_enabled](#input\\_auto\\_grow\\_enabled)", + "type": "Enable auto-grow for storage", + "required": false + }, + { + "name": "", + "description": " [backup\\_retention\\_days](#input\\_backup\\_retention\\_days)", + "type": "Backup retention in days", + "required": false + }, + { + "name": "", + "description": " [geo\\_redundant\\_backup\\_enabled](#input\\_geo\\_redundant\\_backup\\_enabled)", + "type": "Enable geo-redundant backups", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "Azure region", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_server\\_name](#input\\_postgresql\\_server\\_name)", + "type": "Name of the PostgreSQL server", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_version](#input\\_postgresql\\_version)", + "type": "PostgreSQL version", + "required": false + }, + { + "name": "", + "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", + "type": "Enable public network access", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the Azure resource group", + "required": false + }, + { + "name": "", + "description": " [sku\\_name](#input\\_sku\\_name)", + "type": "The SKU name for the PostgreSQL server", + "required": false + }, + { + "name": "", + "description": " [ssl\\_enforcement\\_enabled](#input\\_ssl\\_enforcement\\_enabled)", + "type": "Enforce SSL connection", + "required": false + }, + { + "name": "", + "description": " [ssl\\_minimal\\_tls\\_version\\_enforced](#input\\_ssl\\_minimal\\_tls\\_version\\_enforced)", + "type": "Minimum TLS version", + "required": false + }, + { + "name": "", + "description": " [storage\\_mb](#input\\_storage\\_mb)", + "type": "Storage size in MB", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#input\\_subscription\\_id)", + "type": "the Azure subscription id", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [postgresql\\_admin\\_username](#output\\_postgresql\\_admin\\_username)", + "type": "The administrator username for PostgreSQL", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_fqdn](#output\\_postgresql\\_fqdn)", + "type": "The fully qualified domain name of the PostgreSQL server", + "required": false + }, + { + "name": "", + "description": " [postgresql\\_server\\_name](#output\\_postgresql\\_server\\_name)", + "type": "The name of the PostgreSQL server", "required": false }, { @@ -577,325 +3614,3983 @@ }, { "name": "", - "description": " [psql\\_admin\\_password](#output\\_psql\\_admin\\_password)", - "type": "The administrator password for PostgreSQL", + "description": " [psql\\_admin\\_password](#output\\_psql\\_admin\\_password)", + "type": "The administrator password for PostgreSQL", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "The name of the resource group in which the PostgreSQL database is created", + "required": false + } + ] + }, + { + "id": "azure-service-principal", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-service-principal.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/service-principal/buildingblock", + "backplaneUrl": null, + "name": "Azure Service Principal", + "supportedPlatforms": [ + "azure" + ], + "description": "Creates an Entra ID application registration and service principal with role assignment for automated access to Azure resources", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [azure\\_role](#input\\_azure\\_role)", + "type": "Azure RBAC role to assign to the service principal on the subscription", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_id](#input\\_azure\\_subscription\\_id)", + "type": "Azure Subscription ID where role assignments will be created", + "required": false + }, + { + "name": "", + "description": " [create\\_client\\_secret](#input\\_create\\_client\\_secret)", + "type": "Whether to create a client secret for the service principal (set to false for workload identity federation)", + "required": false + }, + { + "name": "", + "description": " [description](#input\\_description)", + "type": "Description for the Entra ID application", + "required": false + }, + { + "name": "", + "description": " [display\\_name](#input\\_display\\_name)", + "type": "Display name for the Entra ID application and service principal", + "required": false + }, + { + "name": "", + "description": " [owners](#input\\_owners)", + "type": "List of object IDs to set as owners of the application (defaults to current user)", + "required": false + }, + { + "name": "", + "description": " [secret\\_rotation\\_days](#input\\_secret\\_rotation\\_days)", + "type": "Number of days before the service principal secret expires (only used if create\\_client\\_secret is true)", + "required": false + }, + { + "name": "", + "description": " [application\\_id](#output\\_application\\_id)", + "type": "Application (client) ID of the Entra ID application", + "required": false + }, + { + "name": "", + "description": " [application\\_object\\_id](#output\\_application\\_object\\_id)", + "type": "Object ID of the Entra ID application", + "required": false + }, + { + "name": "", + "description": " [authentication\\_method](#output\\_authentication\\_method)", + "type": "Authentication method for the service principal", + "required": false + }, + { + "name": "", + "description": " [azure\\_role](#output\\_azure\\_role)", + "type": "Azure role assigned to the service principal", + "required": false + }, + { + "name": "", + "description": " [client\\_secret](#output\\_client\\_secret)", + "type": "Client secret for the service principal (\"null\" if create\\_client\\_secret is false)", + "required": false + }, + { + "name": "", + "description": " [secret\\_expiration\\_date](#output\\_secret\\_expiration\\_date)", + "type": "Date when the service principal secret will expire (\"null\" if create\\_client\\_secret is false)", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_id](#output\\_service\\_principal\\_id)", + "type": "Client ID of the service principal (same as application\\_id)", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_object\\_id](#output\\_service\\_principal\\_object\\_id)", + "type": "Object ID of the service principal", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#output\\_subscription\\_id)", + "type": "Azure Subscription ID where role assignment was created", + "required": false + }, + { + "name": "", + "description": " [tenant\\_id](#output\\_tenant\\_id)", + "type": "Entra ID Tenant ID", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [azure\\_role](#input\\_azure\\_role)", + "type": "Azure RBAC role to assign to the service principal on the subscription", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_id](#input\\_azure\\_subscription\\_id)", + "type": "Azure Subscription ID where role assignments will be created", + "required": false + }, + { + "name": "", + "description": " [create\\_client\\_secret](#input\\_create\\_client\\_secret)", + "type": "Whether to create a client secret for the service principal (set to false for workload identity federation)", + "required": false + }, + { + "name": "", + "description": " [description](#input\\_description)", + "type": "Description for the Entra ID application", + "required": false + }, + { + "name": "", + "description": " [display\\_name](#input\\_display\\_name)", + "type": "Display name for the Entra ID application and service principal", + "required": false + }, + { + "name": "", + "description": " [owners](#input\\_owners)", + "type": "List of object IDs to set as owners of the application (defaults to current user)", + "required": false + }, + { + "name": "", + "description": " [secret\\_rotation\\_days](#input\\_secret\\_rotation\\_days)", + "type": "Number of days before the service principal secret expires (only used if create\\_client\\_secret is true)", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [application\\_id](#output\\_application\\_id)", + "type": "Application (client) ID of the Entra ID application", + "required": false + }, + { + "name": "", + "description": " [application\\_object\\_id](#output\\_application\\_object\\_id)", + "type": "Object ID of the Entra ID application", + "required": false + }, + { + "name": "", + "description": " [authentication\\_method](#output\\_authentication\\_method)", + "type": "Authentication method for the service principal", + "required": false + }, + { + "name": "", + "description": " [azure\\_role](#output\\_azure\\_role)", + "type": "Azure role assigned to the service principal", + "required": false + }, + { + "name": "", + "description": " [client\\_secret](#output\\_client\\_secret)", + "type": "Client secret for the service principal (\"null\" if create\\_client\\_secret is false)", + "required": false + }, + { + "name": "", + "description": " [secret\\_expiration\\_date](#output\\_secret\\_expiration\\_date)", + "type": "Date when the service principal secret will expire (\"null\" if create\\_client\\_secret is false)", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_id](#output\\_service\\_principal\\_id)", + "type": "Client ID of the service principal (same as application\\_id)", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_object\\_id](#output\\_service\\_principal\\_object\\_id)", + "type": "Object ID of the service principal", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#output\\_subscription\\_id)", + "type": "Azure Subscription ID where role assignment was created", + "required": false + }, + { + "name": "", + "description": " [tenant\\_id](#output\\_tenant\\_id)", + "type": "Entra ID Tenant ID", + "required": false + } + ] + }, + { + "id": "azure-spoke-network", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-spoke-network.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/spoke-network/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/spoke-network/backplane", + "name": "Spoke VNet", + "supportedPlatforms": [ + "azure" + ], + "description": "Provides VNet for your Azure subscription that's connected on a central network hub.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [address\\_space](#input\\_address\\_space)", + "type": "Address space of the virtual network in CIDR notation", + "required": false + }, + { + "name": "", + "description": " [azure\\_delay\\_seconds](#input\\_azure\\_delay\\_seconds)", + "type": "Number of additional seconds to wait between Azure API operations to mitigate eventual consistency issues in order to increase automation reliabilty.", + "required": false + }, + { + "name": "", + "description": " [hub\\_rg](#input\\_hub\\_rg)", + "type": "value", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet](#input\\_hub\\_vnet)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "name of the virtual spoke network. This name is used as the basis to generate resource names for vnets and peerings.", + "required": false + }, + { + "name": "", + "description": " [spoke\\_owner\\_principal\\_id](#input\\_spoke\\_owner\\_principal\\_id)", + "type": "Principal id that will become owner of the spokes. Defaults to the client\\_id of the spoke azurerm provider.", + "required": false + }, + { + "name": "", + "description": " [spoke\\_rg\\_name](#input\\_spoke\\_rg\\_name)", + "type": "name of the resource group to deploy for hosting the spoke vnet", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#input\\_subscription\\_id)", + "type": "The ID of the subscription that you want to deploy the spoke to", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the virtual network created by this module.", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [address\\_space](#input\\_address\\_space)", + "type": "Address space of the virtual network in CIDR notation", + "required": false + }, + { + "name": "", + "description": " [azure\\_delay\\_seconds](#input\\_azure\\_delay\\_seconds)", + "type": "Number of additional seconds to wait between Azure API operations to mitigate eventual consistency issues in order to increase automation reliabilty.", + "required": false + }, + { + "name": "", + "description": " [hub\\_rg](#input\\_hub\\_rg)", + "type": "value", + "required": false + }, + { + "name": "", + "description": " [hub\\_vnet](#input\\_hub\\_vnet)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "name of the virtual spoke network. This name is used as the basis to generate resource names for vnets and peerings.", + "required": false + }, + { + "name": "", + "description": " [spoke\\_owner\\_principal\\_id](#input\\_spoke\\_owner\\_principal\\_id)", + "type": "Principal id that will become owner of the spokes. Defaults to the client\\_id of the spoke azurerm provider.", + "required": false + }, + { + "name": "", + "description": " [spoke\\_rg\\_name](#input\\_spoke\\_rg\\_name)", + "type": "name of the resource group to deploy for hosting the spoke vnet", + "required": false + }, + { + "name": "", + "description": " [subscription\\_id](#input\\_subscription\\_id)", + "type": "The ID of the subscription that you want to deploy the spoke to", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the virtual network created by this module.", + "required": false + } + ] + }, + { + "id": "azure-storage-account", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-storage-account.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/storage-account/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/storage-account/backplane", + "name": "Azure Storage Account", + "supportedPlatforms": [ + "azure" + ], + "description": "Provides an Azure Storage Account as a highly scalable, durable, and secure container that groups together a set of Azure Storage services.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The location/region where the storage account is created.", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_name](#input\\_storage\\_account\\_name)", + "type": "The name of the storage account. Must be unique across entire Azure Region, not just within a Subscription.", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_resource\\_group\\_name](#input\\_storage\\_account\\_resource\\_group\\_name)", + "type": "The name of the resource group containing the storage account.", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_id](#output\\_storage\\_account\\_id)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_name](#output\\_storage\\_account\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_resource\\_group](#output\\_storage\\_account\\_resource\\_group)", + "type": "n/a", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The location/region where the storage account is created.", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_name](#input\\_storage\\_account\\_name)", + "type": "The name of the storage account. Must be unique across entire Azure Region, not just within a Subscription.", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_resource\\_group\\_name](#input\\_storage\\_account\\_resource\\_group\\_name)", + "type": "The name of the resource group containing the storage account.", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [storage\\_account\\_id](#output\\_storage\\_account\\_id)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_name](#output\\_storage\\_account\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [storage\\_account\\_resource\\_group](#output\\_storage\\_account\\_resource\\_group)", + "type": "n/a", + "required": false + } + ] + }, + { + "id": "azure-vmss", + "platformType": "azure", + "logo": "assets/building-block-logos/azure-vmss.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azure/vmss/buildingblock", + "backplaneUrl": null, + "name": "Azure Virtual Machine Scale Set", + "supportedPlatforms": [ + "azure" + ], + "description": "Creates an Azure Virtual Machine Scale Set (VMSS) with comprehensive configuration options for scalable, highly available compute infrastructure.\n", + "category": "compute", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [azurerm](#requirement\\_azurerm)", + "type": "4.18.0", + "required": false + }, + { + "name": "", + "description": " [random](#requirement\\_random)", + "type": "3.6.3", + "required": false + }, + { + "name": "", + "description": " [admin\\_password](#input\\_admin\\_password)", + "type": "The admin password for Windows VM instances (required for Windows)", + "required": false + }, + { + "name": "", + "description": " [admin\\_username](#input\\_admin\\_username)", + "type": "The admin username for the VM instances", + "required": false + }, + { + "name": "", + "description": " [backend\\_port](#input\\_backend\\_port)", + "type": "Backend port for load balancer rule", + "required": false + }, + { + "name": "", + "description": " [custom\\_data](#input\\_custom\\_data)", + "type": "Custom data script to run on VM initialization (cloud-init for Linux, PowerShell for Windows)", + "required": false + }, + { + "name": "", + "description": " [enable\\_autoscaling](#input\\_enable\\_autoscaling)", + "type": "Enable autoscaling based on CPU metrics", + "required": false + }, + { + "name": "", + "description": " [enable\\_boot\\_diagnostics](#input\\_enable\\_boot\\_diagnostics)", + "type": "Enable boot diagnostics for VM instances", + "required": false + }, + { + "name": "", + "description": " [enable\\_load\\_balancer](#input\\_enable\\_load\\_balancer)", + "type": "Enable Azure Load Balancer for the scale set", + "required": false + }, + { + "name": "", + "description": " [enable\\_public\\_ip](#input\\_enable\\_public\\_ip)", + "type": "Enable public IP for the load balancer", + "required": false + }, + { + "name": "", + "description": " [enable\\_rdp\\_access](#input\\_enable\\_rdp\\_access)", + "type": "Enable RDP access (port 3389) through NSG for Windows VMs", + "required": false + }, + { + "name": "", + "description": " [enable\\_spot\\_instances](#input\\_enable\\_spot\\_instances)", + "type": "Enable spot instances for significant cost savings (VMs can be evicted)", + "required": false + }, + { + "name": "", + "description": " [enable\\_ssh\\_access](#input\\_enable\\_ssh\\_access)", + "type": "Enable SSH access (port 22) through NSG for Linux VMs", + "required": false + }, + { + "name": "", + "description": " [frontend\\_port](#input\\_frontend\\_port)", + "type": "Frontend port for load balancer rule", + "required": false + }, + { + "name": "", + "description": " [health\\_probe\\_port](#input\\_health\\_probe\\_port)", + "type": "Port for health probe - required when upgrade\\_mode is Automatic or Rolling", + "required": false + }, + { + "name": "", + "description": " [health\\_probe\\_protocol](#input\\_health\\_probe\\_protocol)", + "type": "Protocol for health probe (Http, Https, Tcp) - required when upgrade\\_mode is Automatic or Rolling", + "required": false + }, + { + "name": "", + "description": " [health\\_probe\\_request\\_path](#input\\_health\\_probe\\_request\\_path)", + "type": "Request path for HTTP/HTTPS health probe - required for Http/Https protocol", + "required": false + }, + { + "name": "", + "description": " [image\\_offer](#input\\_image\\_offer)", + "type": "The offer of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_publisher](#input\\_image\\_publisher)", + "type": "The publisher of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_sku](#input\\_image\\_sku)", + "type": "The SKU of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_version](#input\\_image\\_version)", + "type": "The version of the image", + "required": false + }, + { + "name": "", + "description": " [instances](#input\\_instances)", + "type": "The initial number of instances in the scale set", + "required": false + }, + { + "name": "", + "description": " [load\\_balancer\\_sku](#input\\_load\\_balancer\\_sku)", + "type": "SKU of the Load Balancer (Basic or Standard)", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [max\\_instances](#input\\_max\\_instances)", + "type": "Maximum number of instances when autoscaling is enabled", + "required": false + }, + { + "name": "", + "description": " [min\\_instances](#input\\_min\\_instances)", + "type": "Minimum number of instances when autoscaling is enabled", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_size\\_gb](#input\\_os\\_disk\\_size\\_gb)", + "type": "The size of the OS disk in GB", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_storage\\_type](#input\\_os\\_disk\\_storage\\_type)", + "type": "The storage account type for the OS disk", + "required": false + }, + { + "name": "", + "description": " [os\\_type](#input\\_os\\_type)", + "type": "The operating system type (Linux or Windows)", + "required": false + }, + { + "name": "", + "description": " [overprovision](#input\\_overprovision)", + "type": "Overprovision VMs to improve deployment success rate", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "The name of the resource group where resources will be created", + "required": false + }, + { + "name": "", + "description": " [scale\\_in\\_cpu\\_threshold](#input\\_scale\\_in\\_cpu\\_threshold)", + "type": "CPU percentage threshold to trigger scale in", + "required": false + }, + { + "name": "", + "description": " [scale\\_out\\_cpu\\_threshold](#input\\_scale\\_out\\_cpu\\_threshold)", + "type": "CPU percentage threshold to trigger scale out", + "required": false + }, + { + "name": "", + "description": " [single\\_placement\\_group](#input\\_single\\_placement\\_group)", + "type": "Limit scale set to single placement group (max 100 instances)", + "required": false + }, + { + "name": "", + "description": " [sku](#input\\_sku)", + "type": "The SKU of the Virtual Machine Scale Set (instance size)", + "required": false + }, + { + "name": "", + "description": " [spot\\_eviction\\_policy](#input\\_spot\\_eviction\\_policy)", + "type": "Eviction policy for spot instances (Deallocate or Delete)", + "required": false + }, + { + "name": "", + "description": " [spot\\_max\\_bid\\_price](#input\\_spot\\_max\\_bid\\_price)", + "type": "Maximum price per hour for spot instances. -1 means pay up to on-demand price", + "required": false + }, + { + "name": "", + "description": " [ssh\\_public\\_key](#input\\_ssh\\_public\\_key)", + "type": "SSH public key for Linux VM authentication (required for Linux)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "The name of the existing subnet where VMSS will be deployed", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [upgrade\\_mode](#input\\_upgrade\\_mode)", + "type": "Upgrade policy mode for the scale set (Automatic, Manual, Rolling)", + "required": false + }, + { + "name": "", + "description": " [vmss\\_name](#input\\_vmss\\_name)", + "type": "The name of the Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "The name of the existing virtual network (spoke VNet)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_resource\\_group\\_name](#input\\_vnet\\_resource\\_group\\_name)", + "type": "The name of the resource group containing the virtual network", + "required": false + }, + { + "name": "", + "description": " [zones](#input\\_zones)", + "type": "Availability zones to spread instances across (e.g., [1, 2, 3])", + "required": false + }, + { + "name": "", + "description": " [autoscaling\\_enabled](#output\\_autoscaling\\_enabled)", + "type": "Whether autoscaling is enabled", + "required": false + }, + { + "name": "", + "description": " [current\\_instances](#output\\_current\\_instances)", + "type": "The configured number of instances", + "required": false + }, + { + "name": "", + "description": " [instance\\_size](#output\\_instance\\_size)", + "type": "The SKU/size of VM instances", + "required": false + }, + { + "name": "", + "description": " [load\\_balancer\\_frontend\\_ip](#output\\_load\\_balancer\\_frontend\\_ip)", + "type": "The frontend IP address of the load balancer (public or private)", + "required": false + }, + { + "name": "", + "description": " [load\\_balancer\\_id](#output\\_load\\_balancer\\_id)", + "type": "The ID of the load balancer (if enabled)", + "required": false + }, + { + "name": "", + "description": " [location](#output\\_location)", + "type": "The Azure region where resources are deployed", + "required": false + }, + { + "name": "", + "description": " [public\\_ip\\_address](#output\\_public\\_ip\\_address)", + "type": "The public IP address of the load balancer (if enabled)", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "The name of the resource group", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "The ID of the subnet", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Markdown summary output of the building block", + "required": false + }, + { + "name": "", + "description": " [vmss\\_id](#output\\_vmss\\_id)", + "type": "The ID of the Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vmss\\_identity\\_principal\\_id](#output\\_vmss\\_identity\\_principal\\_id)", + "type": "The Principal ID of the system-assigned managed identity", + "required": false + }, + { + "name": "", + "description": " [vmss\\_name](#output\\_vmss\\_name)", + "type": "The name of the Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the virtual network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#output\\_vnet\\_name)", + "type": "The name of the virtual network", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [admin\\_password](#input\\_admin\\_password)", + "type": "The admin password for Windows VM instances (required for Windows)", + "required": false + }, + { + "name": "", + "description": " [admin\\_username](#input\\_admin\\_username)", + "type": "The admin username for the VM instances", + "required": false + }, + { + "name": "", + "description": " [backend\\_port](#input\\_backend\\_port)", + "type": "Backend port for load balancer rule", + "required": false + }, + { + "name": "", + "description": " [custom\\_data](#input\\_custom\\_data)", + "type": "Custom data script to run on VM initialization (cloud-init for Linux, PowerShell for Windows)", + "required": false + }, + { + "name": "", + "description": " [enable\\_autoscaling](#input\\_enable\\_autoscaling)", + "type": "Enable autoscaling based on CPU metrics", + "required": false + }, + { + "name": "", + "description": " [enable\\_boot\\_diagnostics](#input\\_enable\\_boot\\_diagnostics)", + "type": "Enable boot diagnostics for VM instances", + "required": false + }, + { + "name": "", + "description": " [enable\\_load\\_balancer](#input\\_enable\\_load\\_balancer)", + "type": "Enable Azure Load Balancer for the scale set", + "required": false + }, + { + "name": "", + "description": " [enable\\_public\\_ip](#input\\_enable\\_public\\_ip)", + "type": "Enable public IP for the load balancer", + "required": false + }, + { + "name": "", + "description": " [enable\\_rdp\\_access](#input\\_enable\\_rdp\\_access)", + "type": "Enable RDP access (port 3389) through NSG for Windows VMs", + "required": false + }, + { + "name": "", + "description": " [enable\\_spot\\_instances](#input\\_enable\\_spot\\_instances)", + "type": "Enable spot instances for significant cost savings (VMs can be evicted)", + "required": false + }, + { + "name": "", + "description": " [enable\\_ssh\\_access](#input\\_enable\\_ssh\\_access)", + "type": "Enable SSH access (port 22) through NSG for Linux VMs", + "required": false + }, + { + "name": "", + "description": " [frontend\\_port](#input\\_frontend\\_port)", + "type": "Frontend port for load balancer rule", + "required": false + }, + { + "name": "", + "description": " [health\\_probe\\_port](#input\\_health\\_probe\\_port)", + "type": "Port for health probe - required when upgrade\\_mode is Automatic or Rolling", + "required": false + }, + { + "name": "", + "description": " [health\\_probe\\_protocol](#input\\_health\\_probe\\_protocol)", + "type": "Protocol for health probe (Http, Https, Tcp) - required when upgrade\\_mode is Automatic or Rolling", + "required": false + }, + { + "name": "", + "description": " [health\\_probe\\_request\\_path](#input\\_health\\_probe\\_request\\_path)", + "type": "Request path for HTTP/HTTPS health probe - required for Http/Https protocol", + "required": false + }, + { + "name": "", + "description": " [image\\_offer](#input\\_image\\_offer)", + "type": "The offer of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_publisher](#input\\_image\\_publisher)", + "type": "The publisher of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_sku](#input\\_image\\_sku)", + "type": "The SKU of the image", + "required": false + }, + { + "name": "", + "description": " [image\\_version](#input\\_image\\_version)", + "type": "The version of the image", + "required": false + }, + { + "name": "", + "description": " [instances](#input\\_instances)", + "type": "The initial number of instances in the scale set", + "required": false + }, + { + "name": "", + "description": " [load\\_balancer\\_sku](#input\\_load\\_balancer\\_sku)", + "type": "SKU of the Load Balancer (Basic or Standard)", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The Azure region where resources will be deployed", + "required": false + }, + { + "name": "", + "description": " [max\\_instances](#input\\_max\\_instances)", + "type": "Maximum number of instances when autoscaling is enabled", + "required": false + }, + { + "name": "", + "description": " [min\\_instances](#input\\_min\\_instances)", + "type": "Minimum number of instances when autoscaling is enabled", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_size\\_gb](#input\\_os\\_disk\\_size\\_gb)", + "type": "The size of the OS disk in GB", + "required": false + }, + { + "name": "", + "description": " [os\\_disk\\_storage\\_type](#input\\_os\\_disk\\_storage\\_type)", + "type": "The storage account type for the OS disk", + "required": false + }, + { + "name": "", + "description": " [os\\_type](#input\\_os\\_type)", + "type": "The operating system type (Linux or Windows)", + "required": false + }, + { + "name": "", + "description": " [overprovision](#input\\_overprovision)", + "type": "Overprovision VMs to improve deployment success rate", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "The name of the resource group where resources will be created", + "required": false + }, + { + "name": "", + "description": " [scale\\_in\\_cpu\\_threshold](#input\\_scale\\_in\\_cpu\\_threshold)", + "type": "CPU percentage threshold to trigger scale in", + "required": false + }, + { + "name": "", + "description": " [scale\\_out\\_cpu\\_threshold](#input\\_scale\\_out\\_cpu\\_threshold)", + "type": "CPU percentage threshold to trigger scale out", + "required": false + }, + { + "name": "", + "description": " [single\\_placement\\_group](#input\\_single\\_placement\\_group)", + "type": "Limit scale set to single placement group (max 100 instances)", + "required": false + }, + { + "name": "", + "description": " [sku](#input\\_sku)", + "type": "The SKU of the Virtual Machine Scale Set (instance size)", + "required": false + }, + { + "name": "", + "description": " [spot\\_eviction\\_policy](#input\\_spot\\_eviction\\_policy)", + "type": "Eviction policy for spot instances (Deallocate or Delete)", + "required": false + }, + { + "name": "", + "description": " [spot\\_max\\_bid\\_price](#input\\_spot\\_max\\_bid\\_price)", + "type": "Maximum price per hour for spot instances. -1 means pay up to on-demand price", + "required": false + }, + { + "name": "", + "description": " [ssh\\_public\\_key](#input\\_ssh\\_public\\_key)", + "type": "SSH public key for Linux VM authentication (required for Linux)", + "required": false + }, + { + "name": "", + "description": " [subnet\\_name](#input\\_subnet\\_name)", + "type": "The name of the existing subnet where VMSS will be deployed", + "required": false + }, + { + "name": "", + "description": " [tags](#input\\_tags)", + "type": "Tags to apply to all resources", + "required": false + }, + { + "name": "", + "description": " [upgrade\\_mode](#input\\_upgrade\\_mode)", + "type": "Upgrade policy mode for the scale set (Automatic, Manual, Rolling)", + "required": false + }, + { + "name": "", + "description": " [vmss\\_name](#input\\_vmss\\_name)", + "type": "The name of the Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#input\\_vnet\\_name)", + "type": "The name of the existing virtual network (spoke VNet)", + "required": false + }, + { + "name": "", + "description": " [vnet\\_resource\\_group\\_name](#input\\_vnet\\_resource\\_group\\_name)", + "type": "The name of the resource group containing the virtual network", + "required": false + }, + { + "name": "", + "description": " [zones](#input\\_zones)", + "type": "Availability zones to spread instances across (e.g., [1, 2, 3])", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [autoscaling\\_enabled](#output\\_autoscaling\\_enabled)", + "type": "Whether autoscaling is enabled", + "required": false + }, + { + "name": "", + "description": " [current\\_instances](#output\\_current\\_instances)", + "type": "The configured number of instances", + "required": false + }, + { + "name": "", + "description": " [instance\\_size](#output\\_instance\\_size)", + "type": "The SKU/size of VM instances", + "required": false + }, + { + "name": "", + "description": " [load\\_balancer\\_frontend\\_ip](#output\\_load\\_balancer\\_frontend\\_ip)", + "type": "The frontend IP address of the load balancer (public or private)", + "required": false + }, + { + "name": "", + "description": " [load\\_balancer\\_id](#output\\_load\\_balancer\\_id)", + "type": "The ID of the load balancer (if enabled)", + "required": false + }, + { + "name": "", + "description": " [location](#output\\_location)", + "type": "The Azure region where resources are deployed", + "required": false + }, + { + "name": "", + "description": " [public\\_ip\\_address](#output\\_public\\_ip\\_address)", + "type": "The public IP address of the load balancer (if enabled)", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "The name of the resource group", + "required": false + }, + { + "name": "", + "description": " [subnet\\_id](#output\\_subnet\\_id)", + "type": "The ID of the subnet", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Markdown summary output of the building block", + "required": false + }, + { + "name": "", + "description": " [vmss\\_id](#output\\_vmss\\_id)", + "type": "The ID of the Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vmss\\_identity\\_principal\\_id](#output\\_vmss\\_identity\\_principal\\_id)", + "type": "The Principal ID of the system-assigned managed identity", + "required": false + }, + { + "name": "", + "description": " [vmss\\_name](#output\\_vmss\\_name)", + "type": "The name of the Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vnet\\_id](#output\\_vnet\\_id)", + "type": "The ID of the virtual network", + "required": false + }, + { + "name": "", + "description": " [vnet\\_name](#output\\_vnet\\_name)", + "type": "The name of the virtual network", + "required": false + } + ] + }, + { + "id": "azuredevops-agent-pool", + "platformType": "azuredevops", + "logo": "assets/building-block-logos/azuredevops-agent-pool.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/agent-pool/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/agent-pool/backplane", + "name": "Azure DevOps Agent Pool", + "supportedPlatforms": [ + "azuredevops" + ], + "description": "Creates an Azure DevOps agent pool connected to an existing Azure VMSS for elastic scaling of build agents.\n", + "category": "devops", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [agent\\_interactive\\_ui](#input\\_agent\\_interactive\\_ui)", + "type": "Enable agents to run with interactive UI", + "required": false + }, + { + "name": "", + "description": " [agent\\_pool\\_name](#input\\_agent\\_pool\\_name)", + "type": "Name of the Azure DevOps agent pool", + "required": false + }, + { + "name": "", + "description": " [auto\\_provision](#input\\_auto\\_provision)", + "type": "Automatically provision projects with this agent pool", + "required": false + }, + { + "name": "", + "description": " [auto\\_update](#input\\_auto\\_update)", + "type": "Automatically update agents in this pool", + "required": false + }, + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [desired\\_idle](#input\\_desired\\_idle)", + "type": "Number of agents to keep idle and ready to run jobs", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [max\\_capacity](#input\\_max\\_capacity)", + "type": "Maximum number of virtual machines in the scale set", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the Azure DevOps PAT Token stored in the KeyVault", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps project ID to authorize the agent pool (optional)", + "required": false + }, + { + "name": "", + "description": " [recycle\\_after\\_each\\_use](#input\\_recycle\\_after\\_each\\_use)", + "type": "Tear down the virtual machine after each use", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Resource group name containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [service\\_endpoint\\_id](#input\\_service\\_endpoint\\_id)", + "type": "ID of the Azure service connection for the elastic pool", + "required": false + }, + { + "name": "", + "description": " [service\\_endpoint\\_scope](#input\\_service\\_endpoint\\_scope)", + "type": "Project ID where the service endpoint is defined", + "required": false + }, + { + "name": "", + "description": " [time\\_to\\_live\\_minutes](#input\\_time\\_to\\_live\\_minutes)", + "type": "Time in minutes to keep idle agents before removing them", + "required": false + }, + { + "name": "", + "description": " [vmss\\_name](#input\\_vmss\\_name)", + "type": "Name of the existing Azure Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vmss\\_resource\\_group\\_name](#input\\_vmss\\_resource\\_group\\_name)", + "type": "Resource group name containing the VMSS", + "required": false + }, + { + "name": "", + "description": " [agent\\_pool\\_id](#output\\_agent\\_pool\\_id)", + "type": "ID of the created Azure DevOps agent pool", + "required": false + }, + { + "name": "", + "description": " [agent\\_pool\\_name](#output\\_agent\\_pool\\_name)", + "type": "Name of the created Azure DevOps agent pool", + "required": false + }, + { + "name": "", + "description": " [agent\\_queue\\_id](#output\\_agent\\_queue\\_id)", + "type": "ID of the agent queue in the project", + "required": false + }, + { + "name": "", + "description": " [desired\\_idle](#output\\_desired\\_idle)", + "type": "Number of desired idle agents", + "required": false + }, + { + "name": "", + "description": " [elastic\\_pool\\_id](#output\\_elastic\\_pool\\_id)", + "type": "ID of the elastic pool configuration", + "required": false + }, + { + "name": "", + "description": " [max\\_capacity](#output\\_max\\_capacity)", + "type": "Maximum capacity of the elastic pool", + "required": false + }, + { + "name": "", + "description": " [vmss\\_id](#output\\_vmss\\_id)", + "type": "Azure Resource ID of the VMSS", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [agent\\_interactive\\_ui](#input\\_agent\\_interactive\\_ui)", + "type": "Enable agents to run with interactive UI", + "required": false + }, + { + "name": "", + "description": " [agent\\_pool\\_name](#input\\_agent\\_pool\\_name)", + "type": "Name of the Azure DevOps agent pool", + "required": false + }, + { + "name": "", + "description": " [auto\\_provision](#input\\_auto\\_provision)", + "type": "Automatically provision projects with this agent pool", + "required": false + }, + { + "name": "", + "description": " [auto\\_update](#input\\_auto\\_update)", + "type": "Automatically update agents in this pool", + "required": false + }, + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [desired\\_idle](#input\\_desired\\_idle)", + "type": "Number of agents to keep idle and ready to run jobs", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [max\\_capacity](#input\\_max\\_capacity)", + "type": "Maximum number of virtual machines in the scale set", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the Azure DevOps PAT Token stored in the KeyVault", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps project ID to authorize the agent pool (optional)", + "required": false + }, + { + "name": "", + "description": " [recycle\\_after\\_each\\_use](#input\\_recycle\\_after\\_each\\_use)", + "type": "Tear down the virtual machine after each use", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Resource group name containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [service\\_endpoint\\_id](#input\\_service\\_endpoint\\_id)", + "type": "ID of the Azure service connection for the elastic pool", + "required": false + }, + { + "name": "", + "description": " [service\\_endpoint\\_scope](#input\\_service\\_endpoint\\_scope)", + "type": "Project ID where the service endpoint is defined", + "required": false + }, + { + "name": "", + "description": " [time\\_to\\_live\\_minutes](#input\\_time\\_to\\_live\\_minutes)", + "type": "Time in minutes to keep idle agents before removing them", + "required": false + }, + { + "name": "", + "description": " [vmss\\_name](#input\\_vmss\\_name)", + "type": "Name of the existing Azure Virtual Machine Scale Set", + "required": false + }, + { + "name": "", + "description": " [vmss\\_resource\\_group\\_name](#input\\_vmss\\_resource\\_group\\_name)", + "type": "Resource group name containing the VMSS", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [agent\\_pool\\_id](#output\\_agent\\_pool\\_id)", + "type": "ID of the created Azure DevOps agent pool", + "required": false + }, + { + "name": "", + "description": " [agent\\_pool\\_name](#output\\_agent\\_pool\\_name)", + "type": "Name of the created Azure DevOps agent pool", + "required": false + }, + { + "name": "", + "description": " [agent\\_queue\\_id](#output\\_agent\\_queue\\_id)", + "type": "ID of the agent queue in the project", + "required": false + }, + { + "name": "", + "description": " [desired\\_idle](#output\\_desired\\_idle)", + "type": "Number of desired idle agents", + "required": false + }, + { + "name": "", + "description": " [elastic\\_pool\\_id](#output\\_elastic\\_pool\\_id)", + "type": "ID of the elastic pool configuration", + "required": false + }, + { + "name": "", + "description": " [max\\_capacity](#output\\_max\\_capacity)", + "type": "Maximum capacity of the elastic pool", + "required": false + }, + { + "name": "", + "description": " [vmss\\_id](#output\\_vmss\\_id)", + "type": "Azure Resource ID of the VMSS", + "required": false + } + ] + }, + { + "id": "azuredevops-pipeline", + "platformType": "azuredevops", + "logo": "assets/building-block-logos/azuredevops-pipeline.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/pipeline/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/pipeline/backplane", + "name": "Azure DevOps Pipeline", + "supportedPlatforms": [ + "azuredevops" + ], + "description": "Provides a CI/CD pipeline in Azure DevOps linked to a repository with YAML-based configuration", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [branch\\_name](#input\\_branch\\_name)", + "type": "Default branch for the pipeline", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the secret in Key Vault that contains the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_name](#input\\_pipeline\\_name)", + "type": "Name of the pipeline to create", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_variables](#input\\_pipeline\\_variables)", + "type": "List of pipeline variables to create", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps Project ID where the pipeline will be created", + "required": false + }, + { + "name": "", + "description": " [repository\\_id](#input\\_repository\\_id)", + "type": "Repository ID or name where the pipeline YAML file is located", + "required": false + }, + { + "name": "", + "description": " [repository\\_type](#input\\_repository\\_type)", + "type": "Type of repository. Options: TfsGit, GitHub, GitHubEnterprise, Bitbucket", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [variable\\_group\\_ids](#input\\_variable\\_group\\_ids)", + "type": "List of variable group IDs to link to this pipeline", + "required": false + }, + { + "name": "", + "description": " [yaml\\_path](#input\\_yaml\\_path)", + "type": "Path to the YAML pipeline definition file in the repository", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_id](#output\\_pipeline\\_id)", + "type": "ID of the created pipeline", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_name](#output\\_pipeline\\_name)", + "type": "Name of the created pipeline", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_revision](#output\\_pipeline\\_revision)", + "type": "Revision number of the pipeline", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_url](#output\\_pipeline\\_url)", + "type": "Deep link URL to the pipeline in Azure DevOps", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#output\\_project\\_id)", + "type": "Project ID where the pipeline was created", + "required": false + }, + { + "name": "", + "description": " [repository\\_id](#output\\_repository\\_id)", + "type": "Repository ID linked to the pipeline", + "required": false + }, + { + "name": "", + "description": " [yaml\\_path](#output\\_yaml\\_path)", + "type": "Path to the YAML pipeline definition", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [branch\\_name](#input\\_branch\\_name)", + "type": "Default branch for the pipeline", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the secret in Key Vault that contains the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_name](#input\\_pipeline\\_name)", + "type": "Name of the pipeline to create", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_variables](#input\\_pipeline\\_variables)", + "type": "List of pipeline variables to create", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps Project ID where the pipeline will be created", + "required": false + }, + { + "name": "", + "description": " [repository\\_id](#input\\_repository\\_id)", + "type": "Repository ID or name where the pipeline YAML file is located", + "required": false + }, + { + "name": "", + "description": " [repository\\_type](#input\\_repository\\_type)", + "type": "Type of repository. Options: TfsGit, GitHub, GitHubEnterprise, Bitbucket", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [variable\\_group\\_ids](#input\\_variable\\_group\\_ids)", + "type": "List of variable group IDs to link to this pipeline", + "required": false + }, + { + "name": "", + "description": " [yaml\\_path](#input\\_yaml\\_path)", + "type": "Path to the YAML pipeline definition file in the repository", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [pipeline\\_id](#output\\_pipeline\\_id)", + "type": "ID of the created pipeline", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_name](#output\\_pipeline\\_name)", + "type": "Name of the created pipeline", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_revision](#output\\_pipeline\\_revision)", + "type": "Revision number of the pipeline", + "required": false + }, + { + "name": "", + "description": " [pipeline\\_url](#output\\_pipeline\\_url)", + "type": "Deep link URL to the pipeline in Azure DevOps", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#output\\_project\\_id)", + "type": "Project ID where the pipeline was created", + "required": false + }, + { + "name": "", + "description": " [repository\\_id](#output\\_repository\\_id)", + "type": "Repository ID linked to the pipeline", + "required": false + }, + { + "name": "", + "description": " [yaml\\_path](#output\\_yaml\\_path)", + "type": "Path to the YAML pipeline definition", + "required": false + } + ] + }, + { + "id": "azuredevops-project", + "platformType": "azuredevops", + "logo": "assets/building-block-logos/azuredevops-project.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/project/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/project/backplane", + "name": "Azure DevOps Project", + "supportedPlatforms": [ + "azuredevops" + ], + "description": "Creates and manages Azure DevOps projects with user entitlements, stakeholder licenses, and role-based group memberships.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [project\\_description](#input\\_project\\_description)", + "type": "Description of the Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_features](#input\\_project\\_features)", + "type": "Project features to enable/disable", + "required": false + }, + { + "name": "", + "description": " [project\\_name](#input\\_project\\_name)", + "type": "Name of the Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_visibility](#input\\_project\\_visibility)", + "type": "Visibility of the project (private or public)", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Resource group name containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + }, + { + "name": "", + "description": " [version\\_control](#input\\_version\\_control)", + "type": "Version control system for the project", + "required": false + }, + { + "name": "", + "description": " [work\\_item\\_template](#input\\_work\\_item\\_template)", + "type": "Work item process template", + "required": false + }, + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#output\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL", + "required": false + }, + { + "name": "", + "description": " [group\\_memberships](#output\\_group\\_memberships)", + "type": "Information about group memberships", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#output\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#output\\_pat\\_secret\\_name)", + "type": "Name of the Azure DevOps PAT secret in Key Vault", + "required": false + }, + { + "name": "", + "description": " [project\\_features](#output\\_project\\_features)", + "type": "Enabled/disabled project features", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#output\\_project\\_id)", + "type": "ID of the created Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_name](#output\\_project\\_name)", + "type": "Name of the created Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_url](#output\\_project\\_url)", + "type": "URL of the created Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_visibility](#output\\_project\\_visibility)", + "type": "Visibility of the project", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "Resource group name containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [user\\_assignments](#output\\_user\\_assignments)", + "type": "Map of users and their assigned roles", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [project\\_description](#input\\_project\\_description)", + "type": "Description of the Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_features](#input\\_project\\_features)", + "type": "Project features to enable/disable", + "required": false + }, + { + "name": "", + "description": " [project\\_name](#input\\_project\\_name)", + "type": "Name of the Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_visibility](#input\\_project\\_visibility)", + "type": "Visibility of the project (private or public)", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Resource group name containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + }, + { + "name": "", + "description": " [version\\_control](#input\\_version\\_control)", + "type": "Version control system for the project", + "required": false + }, + { + "name": "", + "description": " [work\\_item\\_template](#input\\_work\\_item\\_template)", + "type": "Work item process template", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#output\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL", + "required": false + }, + { + "name": "", + "description": " [group\\_memberships](#output\\_group\\_memberships)", + "type": "Information about group memberships", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#output\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#output\\_pat\\_secret\\_name)", + "type": "Name of the Azure DevOps PAT secret in Key Vault", + "required": false + }, + { + "name": "", + "description": " [project\\_features](#output\\_project\\_features)", + "type": "Enabled/disabled project features", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#output\\_project\\_id)", + "type": "ID of the created Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_name](#output\\_project\\_name)", + "type": "Name of the created Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_url](#output\\_project\\_url)", + "type": "URL of the created Azure DevOps project", + "required": false + }, + { + "name": "", + "description": " [project\\_visibility](#output\\_project\\_visibility)", + "type": "Visibility of the project", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", + "type": "Resource group name containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [user\\_assignments](#output\\_user\\_assignments)", + "type": "Map of users and their assigned roles", + "required": false + } + ] + }, + { + "id": "azuredevops-repository", + "platformType": "azuredevops", + "logo": "assets/building-block-logos/azuredevops-repository.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/repository/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/repository/backplane", + "name": "Azure DevOps Git Repository", + "supportedPlatforms": [ + "azuredevops" + ], + "description": "Provides a Git repository in Azure DevOps with optional branch protection policies", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [enable\\_branch\\_policies](#input\\_enable\\_branch\\_policies)", + "type": "Enable branch protection policies on the default branch", + "required": false + }, + { + "name": "", + "description": " [init\\_type](#input\\_init\\_type)", + "type": "Type of repository initialization. Options: Clean, Import, Uninitialized", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [minimum\\_reviewers](#input\\_minimum\\_reviewers)", + "type": "Minimum number of reviewers required for pull requests", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the secret in Key Vault that contains the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps Project ID where the repository will be created", + "required": false + }, + { + "name": "", + "description": " [repository\\_name](#input\\_repository\\_name)", + "type": "Name of the Git repository to create", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [branch\\_policies\\_enabled](#output\\_branch\\_policies\\_enabled)", + "type": "Whether branch policies are enabled", + "required": false + }, + { + "name": "", + "description": " [default\\_branch](#output\\_default\\_branch)", + "type": "Default branch of the repository", + "required": false + }, + { + "name": "", + "description": " [repository\\_id](#output\\_repository\\_id)", + "type": "ID of the created repository", + "required": false + }, + { + "name": "", + "description": " [repository\\_name](#output\\_repository\\_name)", + "type": "Name of the created repository", + "required": false + }, + { + "name": "", + "description": " [repository\\_url](#output\\_repository\\_url)", + "type": "URL of the created repository", + "required": false + }, + { + "name": "", + "description": " [ssh\\_url](#output\\_ssh\\_url)", + "type": "SSH URL of the repository", + "required": false + }, + { + "name": "", + "description": " [web\\_url](#output\\_web\\_url)", + "type": "Web URL of the repository", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [enable\\_branch\\_policies](#input\\_enable\\_branch\\_policies)", + "type": "Enable branch protection policies on the default branch", + "required": false + }, + { + "name": "", + "description": " [init\\_type](#input\\_init\\_type)", + "type": "Type of repository initialization. Options: Clean, Import, Uninitialized", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [minimum\\_reviewers](#input\\_minimum\\_reviewers)", + "type": "Minimum number of reviewers required for pull requests", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the secret in Key Vault that contains the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps Project ID where the repository will be created", + "required": false + }, + { + "name": "", + "description": " [repository\\_name](#input\\_repository\\_name)", + "type": "Name of the Git repository to create", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the Key Vault", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [branch\\_policies\\_enabled](#output\\_branch\\_policies\\_enabled)", + "type": "Whether branch policies are enabled", + "required": false + }, + { + "name": "", + "description": " [default\\_branch](#output\\_default\\_branch)", + "type": "Default branch of the repository", + "required": false + }, + { + "name": "", + "description": " [repository\\_id](#output\\_repository\\_id)", + "type": "ID of the created repository", + "required": false + }, + { + "name": "", + "description": " [repository\\_name](#output\\_repository\\_name)", + "type": "Name of the created repository", + "required": false + }, + { + "name": "", + "description": " [repository\\_url](#output\\_repository\\_url)", + "type": "URL of the created repository", + "required": false + }, + { + "name": "", + "description": " [ssh\\_url](#output\\_ssh\\_url)", + "type": "SSH URL of the repository", + "required": false + }, + { + "name": "", + "description": " [web\\_url](#output\\_web\\_url)", + "type": "Web URL of the repository", + "required": false + } + ] + }, + { + "id": "azuredevops-service-connection-subscription", + "platformType": "azuredevops", + "logo": "assets/building-block-logos/azuredevops-service-connection-subscription.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/service-connection-subscription/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/azuredevops/service-connection-subscription/backplane", + "name": "Azure DevOps Service Connection (Subscription)", + "supportedPlatforms": [ + "azuredevops" + ], + "description": "Provides an Azure subscription service connection in Azure DevOps for pipeline integration with Azure subscriptions", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [application\\_object\\_id](#input\\_application\\_object\\_id)", + "type": "Azure AD Application Object ID (not client ID) - use azuread\\_application.*.object\\_id", + "required": false + }, + { + "name": "", + "description": " [authorize\\_all\\_pipelines](#input\\_authorize\\_all\\_pipelines)", + "type": "Automatically authorize all pipelines to use this service connection", + "required": false + }, + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_id](#input\\_azure\\_subscription\\_id)", + "type": "Azure Subscription ID to connect to", + "required": false + }, + { + "name": "", + "description": " [azure\\_tenant\\_id](#input\\_azure\\_tenant\\_id)", + "type": "Azure AD Tenant ID", + "required": false + }, + { + "name": "", + "description": " [description](#input\\_description)", + "type": "Description for the service connection", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the secret in Key Vault that contains the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps Project ID where the service connection will be created", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [service\\_connection\\_name](#input\\_service\\_connection\\_name)", + "type": "Name of the service connection to create", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_id](#input\\_service\\_principal\\_id)", + "type": "Client ID of the existing Azure AD service principal", + "required": false + }, + { + "name": "", + "description": " [authentication\\_method](#output\\_authentication\\_method)", + "type": "Authentication method used", + "required": false + }, + { + "name": "", + "description": " [authorized\\_all\\_pipelines](#output\\_authorized\\_all\\_pipelines)", + "type": "Whether all pipelines are authorized to use this connection", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_id](#output\\_azure\\_subscription\\_id)", + "type": "Azure Subscription ID connected", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_name](#output\\_azure\\_subscription\\_name)", + "type": "Azure Subscription name connected", + "required": false + }, + { + "name": "", + "description": " [service\\_connection\\_id](#output\\_service\\_connection\\_id)", + "type": "ID of the created service connection", + "required": false + }, + { + "name": "", + "description": " [service\\_connection\\_name](#output\\_service\\_connection\\_name)", + "type": "Name of the created service connection", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_id](#output\\_service\\_principal\\_id)", + "type": "Client ID of the service principal", + "required": false + }, + { + "name": "", + "description": " [workload\\_identity\\_federation\\_issuer](#output\\_workload\\_identity\\_federation\\_issuer)", + "type": "Issuer URL for workload identity federation", + "required": false + }, + { + "name": "", + "description": " [workload\\_identity\\_federation\\_subject](#output\\_workload\\_identity\\_federation\\_subject)", + "type": "Subject identifier for workload identity federation", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [application\\_object\\_id](#input\\_application\\_object\\_id)", + "type": "Azure AD Application Object ID (not client ID) - use azuread\\_application.*.object\\_id", + "required": false + }, + { + "name": "", + "description": " [authorize\\_all\\_pipelines](#input\\_authorize\\_all\\_pipelines)", + "type": "Automatically authorize all pipelines to use this service connection", + "required": false + }, + { + "name": "", + "description": " [azure\\_devops\\_organization\\_url](#input\\_azure\\_devops\\_organization\\_url)", + "type": "Azure DevOps organization URL (e.g., https://dev.azure.com/myorg)", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_id](#input\\_azure\\_subscription\\_id)", + "type": "Azure Subscription ID to connect to", + "required": false + }, + { + "name": "", + "description": " [azure\\_tenant\\_id](#input\\_azure\\_tenant\\_id)", + "type": "Azure AD Tenant ID", + "required": false + }, + { + "name": "", + "description": " [description](#input\\_description)", + "type": "Description for the service connection", + "required": false + }, + { + "name": "", + "description": " [key\\_vault\\_name](#input\\_key\\_vault\\_name)", + "type": "Name of the Key Vault containing the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [pat\\_secret\\_name](#input\\_pat\\_secret\\_name)", + "type": "Name of the secret in Key Vault that contains the Azure DevOps PAT", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Azure DevOps Project ID where the service connection will be created", + "required": false + }, + { + "name": "", + "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", + "type": "Name of the resource group containing the Key Vault", + "required": false + }, + { + "name": "", + "description": " [service\\_connection\\_name](#input\\_service\\_connection\\_name)", + "type": "Name of the service connection to create", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_id](#input\\_service\\_principal\\_id)", + "type": "Client ID of the existing Azure AD service principal", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [authentication\\_method](#output\\_authentication\\_method)", + "type": "Authentication method used", + "required": false + }, + { + "name": "", + "description": " [authorized\\_all\\_pipelines](#output\\_authorized\\_all\\_pipelines)", + "type": "Whether all pipelines are authorized to use this connection", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_id](#output\\_azure\\_subscription\\_id)", + "type": "Azure Subscription ID connected", + "required": false + }, + { + "name": "", + "description": " [azure\\_subscription\\_name](#output\\_azure\\_subscription\\_name)", + "type": "Azure Subscription name connected", + "required": false + }, + { + "name": "", + "description": " [service\\_connection\\_id](#output\\_service\\_connection\\_id)", + "type": "ID of the created service connection", + "required": false + }, + { + "name": "", + "description": " [service\\_connection\\_name](#output\\_service\\_connection\\_name)", + "type": "Name of the created service connection", + "required": false + }, + { + "name": "", + "description": " [service\\_principal\\_id](#output\\_service\\_principal\\_id)", + "type": "Client ID of the service principal", + "required": false + }, + { + "name": "", + "description": " [workload\\_identity\\_federation\\_issuer](#output\\_workload\\_identity\\_federation\\_issuer)", + "type": "Issuer URL for workload identity federation", + "required": false + }, + { + "name": "", + "description": " [workload\\_identity\\_federation\\_subject](#output\\_workload\\_identity\\_federation\\_subject)", + "type": "Subject identifier for workload identity federation", + "required": false + } + ] + }, + { + "id": "gcp-budget-alert", + "platformType": "gcp", + "logo": "assets/building-block-logos/gcp-budget-alert.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/gcp/budget-alert/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/gcp/budget-alert/backplane", + "name": "GCP Project Budget Alert", + "supportedPlatforms": [ + "gcp" + ], + "description": "Sets up budget alerts for a GCP project to monitor spending and prevent cost overruns.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [alert\\_thresholds\\_yaml](#input\\_alert\\_thresholds\\_yaml)", + "type": "YAML string defining alert thresholds as a list of objects having fields 'percent' and 'basis'", + "required": false + }, + { + "name": "", + "description": " [backplane\\_project\\_id](#input\\_backplane\\_project\\_id)", + "type": "The project ID where the backplane resources will be created", + "required": false + }, + { + "name": "", + "description": " [billing\\_account\\_id](#input\\_billing\\_account\\_id)", + "type": "The ID of the billing account to which the budget will be applied", + "required": false + }, + { + "name": "", + "description": " [budget\\_currency](#input\\_budget\\_currency)", + "type": "The currency for the budget amount, e.g., EUR", + "required": false + }, + { + "name": "", + "description": " [budget\\_name](#input\\_budget\\_name)", + "type": "Display name for the budget", + "required": false + }, + { + "name": "", + "description": " [contact\\_email](#input\\_contact\\_email)", + "type": "email address to receive budget alerts", + "required": false + }, + { + "name": "", + "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", + "type": "The budget amount in the project's billing currency", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "The GCP project ID where the budget will be created", + "required": false + }, + { + "name": "", + "description": " [budget\\_id](#output\\_budget\\_id)", + "type": "The ID of the created budget", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [alert\\_thresholds\\_yaml](#input\\_alert\\_thresholds\\_yaml)", + "type": "YAML string defining alert thresholds as a list of objects having fields 'percent' and 'basis'", + "required": false + }, + { + "name": "", + "description": " [backplane\\_project\\_id](#input\\_backplane\\_project\\_id)", + "type": "The project ID where the backplane resources will be created", + "required": false + }, + { + "name": "", + "description": " [billing\\_account\\_id](#input\\_billing\\_account\\_id)", + "type": "The ID of the billing account to which the budget will be applied", + "required": false + }, + { + "name": "", + "description": " [budget\\_currency](#input\\_budget\\_currency)", + "type": "The currency for the budget amount, e.g., EUR", + "required": false + }, + { + "name": "", + "description": " [budget\\_name](#input\\_budget\\_name)", + "type": "Display name for the budget", + "required": false + }, + { + "name": "", + "description": " [contact\\_email](#input\\_contact\\_email)", + "type": "email address to receive budget alerts", + "required": false + }, + { + "name": "", + "description": " [monthly\\_budget\\_amount](#input\\_monthly\\_budget\\_amount)", + "type": "The budget amount in the project's billing currency", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "The GCP project ID where the budget will be created", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [budget\\_id](#output\\_budget\\_id)", + "type": "The ID of the created budget", + "required": false + } + ] + }, + { + "id": "gcp-storage-bucket", + "platformType": "gcp", + "logo": "assets/building-block-logos/gcp-storage-bucket.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/gcp/storage-bucket/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/gcp/storage-bucket/backplane", + "name": "GCP Storage Bucket", + "supportedPlatforms": [ + "gcp" + ], + "description": "Provides a GCP Cloud Storage bucket for object storage with access controls and lifecycle policies.", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [bucket\\_name](#input\\_bucket\\_name)", + "type": "The name of the storage bucket", + "required": false + }, + { + "name": "", + "description": " [labels](#input\\_labels)", + "type": "List of labels to apply to the resource", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The GCP location/region", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "The GCP project ID", + "required": false + }, + { + "name": "", + "description": " [bucket\\_name](#output\\_bucket\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_self\\_link](#output\\_bucket\\_self\\_link)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_url](#output\\_bucket\\_url)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Markdown summary output of the building block", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [bucket\\_name](#input\\_bucket\\_name)", + "type": "The name of the storage bucket", + "required": false + }, + { + "name": "", + "description": " [labels](#input\\_labels)", + "type": "List of labels to apply to the resource", + "required": false + }, + { + "name": "", + "description": " [location](#input\\_location)", + "type": "The GCP location/region", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "The GCP project ID", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [bucket\\_name](#output\\_bucket\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_self\\_link](#output\\_bucket\\_self\\_link)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [bucket\\_url](#output\\_bucket\\_url)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [summary](#output\\_summary)", + "type": "Markdown summary output of the building block", + "required": false + } + ] + }, + { + "id": "github-repository", + "platformType": "github", + "logo": "assets/building-block-logos/github-repository.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/github/repository/buildingblock", + "backplaneUrl": null, + "name": "GitHub Repository Creation", + "supportedPlatforms": [ + "github" + ], + "description": "Automates GitHub repository setup with predefined configurations and access control.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [archive\\_repo\\_on\\_destroy](#input\\_archive\\_repo\\_on\\_destroy)", + "type": "Whether to archive github repository when destroying the terraform resource, or delete it. Defaults to true (archive).", + "required": false + }, + { + "name": "", + "description": " [repo\\_description](#input\\_repo\\_description)", + "type": "Description of the GitHub repository", + "required": false + }, + { + "name": "", + "description": " [repo\\_name](#input\\_repo\\_name)", + "type": "Name of the GitHub repository", + "required": false + }, + { + "name": "", + "description": " [repo\\_owner](#input\\_repo\\_owner)", + "type": "Username of the GitHub user who will be set as the owner/admin of the repository. If not set, no collaborator will be added.", + "required": false + }, + { + "name": "", + "description": " [repo\\_visibility](#input\\_repo\\_visibility)", + "type": "Visibility of the GitHub repository", + "required": false + }, + { + "name": "", + "description": " [template\\_owner](#input\\_template\\_owner)", + "type": "Owner of the template repository", + "required": false + }, + { + "name": "", + "description": " [template\\_repo](#input\\_template\\_repo)", + "type": "Name of the template repository", + "required": false + }, + { + "name": "", + "description": " [use\\_template](#input\\_use\\_template)", + "type": "Flag to indicate whether to create a repo based on a Template Repository", + "required": false + }, + { + "name": "", + "description": " [repo\\_full\\_name](#output\\_repo\\_full\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_git\\_clone\\_url](#output\\_repo\\_git\\_clone\\_url)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_html\\_url](#output\\_repo\\_html\\_url)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_name](#output\\_repo\\_name)", + "type": "n/a", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [archive\\_repo\\_on\\_destroy](#input\\_archive\\_repo\\_on\\_destroy)", + "type": "Whether to archive github repository when destroying the terraform resource, or delete it. Defaults to true (archive).", + "required": false + }, + { + "name": "", + "description": " [repo\\_description](#input\\_repo\\_description)", + "type": "Description of the GitHub repository", + "required": false + }, + { + "name": "", + "description": " [repo\\_name](#input\\_repo\\_name)", + "type": "Name of the GitHub repository", + "required": false + }, + { + "name": "", + "description": " [repo\\_owner](#input\\_repo\\_owner)", + "type": "Username of the GitHub user who will be set as the owner/admin of the repository. If not set, no collaborator will be added.", + "required": false + }, + { + "name": "", + "description": " [repo\\_visibility](#input\\_repo\\_visibility)", + "type": "Visibility of the GitHub repository", + "required": false + }, + { + "name": "", + "description": " [template\\_owner](#input\\_template\\_owner)", + "type": "Owner of the template repository", + "required": false + }, + { + "name": "", + "description": " [template\\_repo](#input\\_template\\_repo)", + "type": "Name of the template repository", + "required": false + }, + { + "name": "", + "description": " [use\\_template](#input\\_use\\_template)", + "type": "Flag to indicate whether to create a repo based on a Template Repository", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [repo\\_full\\_name](#output\\_repo\\_full\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_git\\_clone\\_url](#output\\_repo\\_git\\_clone\\_url)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_html\\_url](#output\\_repo\\_html\\_url)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [repo\\_name](#output\\_repo\\_name)", + "type": "n/a", + "required": false + } + ] + }, + { + "id": "ionos-dcd", + "platformType": "ionos", + "logo": "assets/building-block-logos/ionos-dcd.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/ionos/dcd/buildingblock", + "backplaneUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/ionos/dcd/backplane", + "name": "IONOS DCD (Data Center Designer)", + "supportedPlatforms": [ + "ionos" + ], + "description": "Creates and manages IONOS Data Center Designer environments with user onboarding, role-based access control, and datacenter provisioning.", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [datacenter\\_description](#input\\_datacenter\\_description)", + "type": "Description of the datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_location](#input\\_datacenter\\_location)", + "type": "Location for the IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_name](#input\\_datacenter\\_name)", + "type": "Name of the IONOS DCD datacenter", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_id](#output\\_datacenter\\_id)", + "type": "ID of the created IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_location](#output\\_datacenter\\_location)", + "type": "Location of the created IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_name](#output\\_datacenter\\_name)", + "type": "Name of the created IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [dcd\\_url](#output\\_dcd\\_url)", + "type": "Direct URL to access the IONOS DCD datacenter", + "required": false + }, + { + "name": "", + "description": " [group\\_memberships](#output\\_group\\_memberships)", + "type": "Information about group memberships", + "required": false + }, + { + "name": "", + "description": " [user\\_assignments](#output\\_user\\_assignments)", + "type": "Map of users and their assigned roles", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [datacenter\\_description](#input\\_datacenter\\_description)", + "type": "Description of the datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_location](#input\\_datacenter\\_location)", + "type": "Location for the IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_name](#input\\_datacenter\\_name)", + "type": "Name of the IONOS DCD datacenter", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [terraform](#requirement\\_terraform)", + "type": ">= 1.0", + "required": false + }, + { + "name": "", + "description": " [ionoscloud](#requirement\\_ionoscloud)", + "type": "~> 6.4.0", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_description](#input\\_datacenter\\_description)", + "type": "Description of the datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_location](#input\\_datacenter\\_location)", + "type": "Location for the IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_name](#input\\_datacenter\\_name)", + "type": "Name of the IONOS DCD datacenter", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_id](#output\\_datacenter\\_id)", + "type": "ID of the created IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_location](#output\\_datacenter\\_location)", + "type": "Location of the created IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [datacenter\\_name](#output\\_datacenter\\_name)", + "type": "Name of the created IONOS datacenter", + "required": false + }, + { + "name": "", + "description": " [dcd\\_url](#output\\_dcd\\_url)", + "type": "Direct URL to access the IONOS DCD datacenter", + "required": false + }, + { + "name": "", + "description": " [group\\_memberships](#output\\_group\\_memberships)", + "type": "Information about group memberships", + "required": false + }, + { + "name": "", + "description": " [user\\_assignments](#output\\_user\\_assignments)", + "type": "Map of users and their assigned roles", + "required": false + } + ] + }, + { + "id": "ionos-user-management", + "platformType": "ionos", + "logo": "assets/building-block-logos/ionos-user-management.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/ionos/user-management/buildingblock", + "backplaneUrl": null, + "name": "IONOS User Management", + "supportedPlatforms": [ + "ionos" + ], + "description": "Creates and manages IONOS Cloud users with role-based access. This is a foundational module that should be deployed before DCD environments.", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [default\\_user\\_password](#input\\_default\\_user\\_password)", + "type": "Default password for created users", + "required": false + }, + { + "name": "", + "description": " [force\\_sec\\_auth](#input\\_force\\_sec\\_auth)", + "type": "Force two-factor authentication for users", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + }, + { + "name": "", + "description": " [all\\_users](#output\\_all\\_users)", + "type": "All users (existing and newly created)", + "required": false + }, + { + "name": "", + "description": " [created\\_users](#output\\_created\\_users)", + "type": "Users that were newly created", + "required": false + }, + { + "name": "", + "description": " [existing\\_users](#output\\_existing\\_users)", + "type": "Users that already existed in IONOS", + "required": false + }, + { + "name": "", + "description": " [user\\_summary](#output\\_user\\_summary)", + "type": "Summary of user management", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [default\\_user\\_password](#input\\_default\\_user\\_password)", + "type": "Default password for created users", + "required": false + }, + { + "name": "", + "description": " [force\\_sec\\_auth](#input\\_force\\_sec\\_auth)", + "type": "Force two-factor authentication for users", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [terraform](#requirement\\_terraform)", + "type": ">= 1.0", + "required": false + }, + { + "name": "", + "description": " [ionoscloud](#requirement\\_ionoscloud)", + "type": "~> 6.4.0", + "required": false + }, + { + "name": "", + "description": " [default\\_user\\_password](#input\\_default\\_user\\_password)", + "type": "Default password for created users", + "required": false + }, + { + "name": "", + "description": " [force\\_sec\\_auth](#input\\_force\\_sec\\_auth)", + "type": "Force two-factor authentication for users", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + }, + { + "name": "", + "description": " [all\\_users](#output\\_all\\_users)", + "type": "All users (existing and newly created)", + "required": false + }, + { + "name": "", + "description": " [created\\_users](#output\\_created\\_users)", + "type": "Users that were newly created", + "required": false + }, + { + "name": "", + "description": " [existing\\_users](#output\\_existing\\_users)", + "type": "Users that already existed in IONOS", + "required": false + }, + { + "name": "", + "description": " [user\\_summary](#output\\_user\\_summary)", + "type": "Summary of user management", + "required": false + } + ] + }, + { + "id": "kubernetes-service-account", + "platformType": "kubernetes", + "logo": "assets/building-block-logos/kubernetes-service-account.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/kubernetes/service-account/buildingblock", + "backplaneUrl": null, + "name": "Kubernetes Service Account", + "supportedPlatforms": [ + "kubernetes" + ], + "description": "Creates a Kubernetes service account with ClusterRole binding and generates a kubeconfig for authentication", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [cluster\\_ca\\_certificate](#input\\_cluster\\_ca\\_certificate)", + "type": "Cluster CA certificate, base64 encoded", + "required": false + }, + { + "name": "", + "description": " [cluster\\_endpoint](#input\\_cluster\\_endpoint)", + "type": "IP address of the cluster control plane", + "required": false + }, + { + "name": "", + "description": " [cluster\\_name](#input\\_cluster\\_name)", + "type": "Name of the k8s cluster hosting this service account", + "required": false + }, + { + "name": "", + "description": " [cluster\\_role](#input\\_cluster\\_role)", + "type": "ClusterRole to bind the service account with. e.g. admin, edit, view (or any custom cluster role)", + "required": false + }, + { + "name": "", + "description": " [context](#input\\_context)", + "type": "Defines which cluster to interact with. Can be any name", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "Service account name", + "required": false + }, + { + "name": "", + "description": " [namespace](#input\\_namespace)", + "type": "Namespace where the service account will be created. Recommended: Use platform tenant ID as input in meshStack", + "required": false + }, + { + "name": "", + "description": " [token](#input\\_token)", + "type": "Token for the service account executing this module (not this service account)", + "required": false + }, + { + "name": "", + "description": " [instructions](#output\\_instructions)", + "type": "Instructions for using the kubeconfig", + "required": false + }, + { + "name": "", + "description": " [kubeconfig](#output\\_kubeconfig)", + "type": "Kubeconfig file content for authenticating with the Kubernetes cluster", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [cluster\\_ca\\_certificate](#input\\_cluster\\_ca\\_certificate)", + "type": "Cluster CA certificate, base64 encoded", + "required": false + }, + { + "name": "", + "description": " [cluster\\_endpoint](#input\\_cluster\\_endpoint)", + "type": "IP address of the cluster control plane", + "required": false + }, + { + "name": "", + "description": " [cluster\\_name](#input\\_cluster\\_name)", + "type": "Name of the k8s cluster hosting this service account", + "required": false + }, + { + "name": "", + "description": " [cluster\\_role](#input\\_cluster\\_role)", + "type": "ClusterRole to bind the service account with. e.g. admin, edit, view (or any custom cluster role)", + "required": false + }, + { + "name": "", + "description": " [context](#input\\_context)", + "type": "Defines which cluster to interact with. Can be any name", + "required": false + }, + { + "name": "", + "description": " [name](#input\\_name)", + "type": "Service account name", + "required": false + }, + { + "name": "", + "description": " [namespace](#input\\_namespace)", + "type": "Namespace where the service account will be created. Recommended: Use platform tenant ID as input in meshStack", + "required": false + }, + { + "name": "", + "description": " [token](#input\\_token)", + "type": "Token for the service account executing this module (not this service account)", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [instructions](#output\\_instructions)", + "type": "Instructions for using the kubeconfig", + "required": false + }, + { + "name": "", + "description": " [kubeconfig](#output\\_kubeconfig)", + "type": "Kubeconfig file content for authenticating with the Kubernetes cluster", + "required": false + } + ] + }, + { + "id": "oci-application-compartment", + "platformType": "oci", + "logo": "assets/building-block-logos/oci-application-compartment.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/oci/application-compartment/buildingblock", + "backplaneUrl": null, + "name": "OCI Application Compartment", + "supportedPlatforms": [ + "oci" + ], + "description": "Creates an application compartment with IAM groups and policies for team-based access control.\n", + "howToUse": null, + "resources": [ + { + "name": "", + "description": " [foundation](#input\\_foundation)", + "type": "Foundation name prefix", + "required": false + }, + { + "name": "", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Project identifier (e.g., application name)", + "required": false + }, + { + "name": "", + "description": " [region](#input\\_region)", + "type": "OCI region identifier (e.g., eu-frankfurt-1, us-ashburn-1)", + "required": false + }, + { + "name": "", + "description": " [tag\\_relations](#input\\_tag\\_relations)", + "type": "YAML configuration for tag-based compartment mapping", + "required": false + }, + { + "name": "", + "description": " [tenancy\\_ocid](#input\\_tenancy\\_ocid)", + "type": "OCID of the OCI tenancy", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", + "required": false + }, + { + "name": "", + "description": " [workspace\\_id](#input\\_workspace\\_id)", + "type": "Workspace identifier (e.g., team name or business unit)", + "required": false + }, + { + "name": "", + "description": " [admin\\_group\\_id](#output\\_admin\\_group\\_id)", + "type": "OCID of the admins group", + "required": false + }, + { + "name": "", + "description": " [admin\\_group\\_name](#output\\_admin\\_group\\_name)", + "type": "Name of the admins group", + "required": false + }, + { + "name": "", + "description": " [compartment\\_id](#output\\_compartment\\_id)", + "type": "OCID of the created application compartment", + "required": false + }, + { + "name": "", + "description": " [compartment\\_name](#output\\_compartment\\_name)", + "type": "Name of the created application compartment", + "required": false + }, + { + "name": "", + "description": " [console\\_url](#output\\_console\\_url)", + "type": "OCI Console URL for direct access to the compartment", + "required": false + }, + { + "name": "", + "description": " [policy\\_id](#output\\_policy\\_id)", + "type": "OCID of the access policy", + "required": false + }, + { + "name": "", + "description": " [reader\\_group\\_id](#output\\_reader\\_group\\_id)", + "type": "OCID of the readers group", + "required": false + }, + { + "name": "", + "description": " [reader\\_group\\_name](#output\\_reader\\_group\\_name)", + "type": "Name of the readers group", "required": false }, { "name": "", - "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", - "type": "The name of the resource group in which the PostgreSQL database is created", + "description": " [user\\_group\\_id](#output\\_user\\_group\\_id)", + "type": "OCID of the users group", + "required": false + }, + { + "name": "", + "description": " [user\\_group\\_name](#output\\_user\\_group\\_name)", + "type": "Name of the users group", "required": false } ], "inputs": [ { "name": "", - "description": " [administrator\\_login](#input\\_administrator\\_login)", - "type": "Administrator username for PostgreSQL", + "description": " [foundation](#input\\_foundation)", + "type": "Foundation name prefix", "required": false }, { "name": "", - "description": " [auto\\_grow\\_enabled](#input\\_auto\\_grow\\_enabled)", - "type": "Enable auto-grow for storage", + "description": " [project\\_id](#input\\_project\\_id)", + "type": "Project identifier (e.g., application name)", "required": false }, { "name": "", - "description": " [backup\\_retention\\_days](#input\\_backup\\_retention\\_days)", - "type": "Backup retention in days", + "description": " [region](#input\\_region)", + "type": "OCI region identifier (e.g., eu-frankfurt-1, us-ashburn-1)", "required": false }, { "name": "", - "description": " [geo\\_redundant\\_backup\\_enabled](#input\\_geo\\_redundant\\_backup\\_enabled)", - "type": "Enable geo-redundant backups", + "description": " [tag\\_relations](#input\\_tag\\_relations)", + "type": "YAML configuration for tag-based compartment mapping", "required": false }, { "name": "", - "description": " [location](#input\\_location)", - "type": "Azure region", + "description": " [tenancy\\_ocid](#input\\_tenancy\\_ocid)", + "type": "OCID of the OCI tenancy", "required": false }, { "name": "", - "description": " [postgresql\\_server\\_name](#input\\_postgresql\\_server\\_name)", - "type": "Name of the PostgreSQL server", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", "required": false }, { "name": "", - "description": " [postgresql\\_version](#input\\_postgresql\\_version)", - "type": "PostgreSQL version", + "description": " [workspace\\_id](#input\\_workspace\\_id)", + "type": "Workspace identifier (e.g., team name or business unit)", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [admin\\_group\\_id](#output\\_admin\\_group\\_id)", + "type": "OCID of the admins group", "required": false }, { "name": "", - "description": " [public\\_network\\_access\\_enabled](#input\\_public\\_network\\_access\\_enabled)", - "type": "Enable public network access", + "description": " [admin\\_group\\_name](#output\\_admin\\_group\\_name)", + "type": "Name of the admins group", "required": false }, { "name": "", - "description": " [resource\\_group\\_name](#input\\_resource\\_group\\_name)", - "type": "Name of the Azure resource group", + "description": " [compartment\\_id](#output\\_compartment\\_id)", + "type": "OCID of the created application compartment", "required": false }, { "name": "", - "description": " [sku\\_name](#input\\_sku\\_name)", - "type": "The SKU name for the PostgreSQL server", + "description": " [compartment\\_name](#output\\_compartment\\_name)", + "type": "Name of the created application compartment", "required": false }, { "name": "", - "description": " [ssl\\_enforcement\\_enabled](#input\\_ssl\\_enforcement\\_enabled)", - "type": "Enforce SSL connection", + "description": " [console\\_url](#output\\_console\\_url)", + "type": "OCI Console URL for direct access to the compartment", "required": false }, { "name": "", - "description": " [ssl\\_minimal\\_tls\\_version\\_enforced](#input\\_ssl\\_minimal\\_tls\\_version\\_enforced)", - "type": "Minimum TLS version", + "description": " [policy\\_id](#output\\_policy\\_id)", + "type": "OCID of the access policy", "required": false }, { "name": "", - "description": " [storage\\_mb](#input\\_storage\\_mb)", - "type": "Storage size in MB", + "description": " [reader\\_group\\_id](#output\\_reader\\_group\\_id)", + "type": "OCID of the readers group", "required": false }, { "name": "", - "description": " [subscription\\_id](#input\\_subscription\\_id)", - "type": "the Azure subscription id", + "description": " [reader\\_group\\_name](#output\\_reader\\_group\\_name)", + "type": "Name of the readers group", + "required": false + }, + { + "name": "", + "description": " [user\\_group\\_id](#output\\_user\\_group\\_id)", + "type": "OCID of the users group", + "required": false + }, + { + "name": "", + "description": " [user\\_group\\_name](#output\\_user\\_group\\_name)", + "type": "Name of the users group", "required": false } + ] + }, + { + "id": "sapbtp-subaccounts", + "platformType": "sapbtp", + "logo": "assets/building-block-logos/sapbtp-subaccounts.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/sapbtp/subaccounts/buildingblock", + "backplaneUrl": null, + "name": "SAP BTP subaccount", + "supportedPlatforms": [ + "sapbtp" ], - "outputs": [ + "description": "This building block Creates a subaccount in SAP BTP.\n", + "howToUse": null, + "resources": [ { "name": "", - "description": " [postgresql\\_admin\\_username](#output\\_postgresql\\_admin\\_username)", - "type": "The administrator username for PostgreSQL", + "description": " [globalaccount](#input\\_globalaccount)", + "type": "The subdomain of the global account in which you want to manage resources.", "required": false }, { "name": "", - "description": " [postgresql\\_fqdn](#output\\_postgresql\\_fqdn)", - "type": "The fully qualified domain name of the PostgreSQL server", + "description": " [project\\_identifier](#input\\_project\\_identifier)", + "type": "The meshStack project identifier.", "required": false }, { "name": "", - "description": " [postgresql\\_server\\_name](#output\\_postgresql\\_server\\_name)", - "type": "The name of the PostgreSQL server", + "description": " [region](#input\\_region)", + "type": "The region of the subaccount.", "required": false }, { "name": "", - "description": " [postgresql\\_version](#output\\_postgresql\\_version)", - "type": "The PostgreSQL version", + "description": " [subfolder](#input\\_subfolder)", + "type": "The subfolder to use for the SAP BTP resources. This is used to create a folder structure in the SAP BTP cockpit.", "required": false }, { "name": "", - "description": " [psql\\_admin\\_password](#output\\_psql\\_admin\\_password)", - "type": "The administrator password for PostgreSQL", + "description": " [users](#input\\_users)", + "type": "Users and their roles provided by meshStack", "required": false }, { "name": "", - "description": " [resource\\_group\\_name](#output\\_resource\\_group\\_name)", - "type": "The name of the resource group in which the PostgreSQL database is created", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "The meshStack workspace identifier.", + "required": false + }, + { + "name": "", + "description": " [btp\\_subaccount\\_id](#output\\_btp\\_subaccount\\_id)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [btp\\_subaccount\\_login\\_link](#output\\_btp\\_subaccount\\_login\\_link)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [btp\\_subaccount\\_name](#output\\_btp\\_subaccount\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [btp\\_subaccount\\_region](#output\\_btp\\_subaccount\\_region)", + "type": "n/a", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [globalaccount](#input\\_globalaccount)", + "type": "The subdomain of the global account in which you want to manage resources.", + "required": false + }, + { + "name": "", + "description": " [project\\_identifier](#input\\_project\\_identifier)", + "type": "The meshStack project identifier.", + "required": false + }, + { + "name": "", + "description": " [region](#input\\_region)", + "type": "The region of the subaccount.", + "required": false + }, + { + "name": "", + "description": " [subfolder](#input\\_subfolder)", + "type": "The subfolder to use for the SAP BTP resources. This is used to create a folder structure in the SAP BTP cockpit.", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "Users and their roles provided by meshStack", + "required": false + }, + { + "name": "", + "description": " [workspace\\_identifier](#input\\_workspace\\_identifier)", + "type": "The meshStack workspace identifier.", + "required": false + } + ], + "outputs": [ + { + "name": "", + "description": " [btp\\_subaccount\\_id](#output\\_btp\\_subaccount\\_id)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [btp\\_subaccount\\_login\\_link](#output\\_btp\\_subaccount\\_login\\_link)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [btp\\_subaccount\\_name](#output\\_btp\\_subaccount\\_name)", + "type": "n/a", + "required": false + }, + { + "name": "", + "description": " [btp\\_subaccount\\_region](#output\\_btp\\_subaccount\\_region)", + "type": "n/a", "required": false } ] }, { - "id": "github-repository", - "platformType": "github", - "logo": "assets/building-block-logos/github-repository.png", - "buildingBlockUrl": "https://github.com/meshcloud/meshstack-hub/tree/main/modules/github/repository/buildingblock", + "id": "sapbtp-subdirectory", + "platformType": "sapbtp", + "logo": "assets/building-block-logos/sapbtp-subdirectory.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/sapbtp/subdirectory/buildingblock", "backplaneUrl": null, - "name": "GitHub Repository Creation", + "name": "SAP BTP subdirectory", "supportedPlatforms": [ - "github" + "sapbtp" ], - "description": "Automates GitHub repository setup with predefined configurations and access control.\n", + "description": "This building block Creates a subdirectory in SAP BTP.\n", "howToUse": null, "resources": [ { "name": "", - "description": " [github\\_app\\_id](#input\\_github\\_app\\_id)", - "type": "ID of the GitHub App", + "description": " [globalaccount](#input\\_globalaccount)", + "type": "The subdomain of the global account in which you want to manage resources.", "required": false }, { "name": "", - "description": " [github\\_app\\_installation\\_id](#input\\_github\\_app\\_installation\\_id)", - "type": "Installation ID of the GitHub App", + "description": " [parent\\_id](#input\\_parent\\_id)", + "type": "The ID of the parent resource.", "required": false }, { "name": "", - "description": " [github\\_app\\_pem\\_file](#input\\_github\\_app\\_pem\\_file)", - "type": "GitHub App private key content", + "description": " [project\\_identifier](#input\\_project\\_identifier)", + "type": "The meshStack project identifier.", "required": false }, { "name": "", - "description": " [github\\_org](#input\\_github\\_org)", - "type": "Name of the GitHub organization", + "description": " [subfolder](#input\\_subfolder)", + "type": "The subfolder to use for the SAP BTP resources. This is used to create a folder structure in the SAP BTP cockpit.", "required": false }, { "name": "", - "description": " [repo\\_description](#input\\_repo\\_description)", - "type": "Description of the GitHub repository", + "description": " [btp\\_subdirectory\\_id](#output\\_btp\\_subdirectory\\_id)", + "type": "n/a", "required": false }, { "name": "", - "description": " [repo\\_name](#input\\_repo\\_name)", - "type": "Name of the GitHub repository", + "description": " [btp\\_subdirectory\\_name](#output\\_btp\\_subdirectory\\_name)", + "type": "n/a", "required": false }, { "name": "", - "description": " [repo\\_visibility](#input\\_repo\\_visibility)", - "type": "Visibility of the GitHub repository", + "description": " [project\\_folder](#output\\_project\\_folder)", + "type": "n/a", "required": false - }, + } + ], + "inputs": [ { "name": "", - "description": " [template\\_owner](#input\\_template\\_owner)", - "type": "Owner of the template repository", + "description": " [globalaccount](#input\\_globalaccount)", + "type": "The subdomain of the global account in which you want to manage resources.", "required": false }, { "name": "", - "description": " [template\\_repo](#input\\_template\\_repo)", - "type": "Name of the template repository", + "description": " [parent\\_id](#input\\_parent\\_id)", + "type": "The ID of the parent resource.", "required": false }, { "name": "", - "description": " [use\\_template](#input\\_use\\_template)", - "type": "Flag to indicate whether to create a repo based on a Template Repository", + "description": " [project\\_identifier](#input\\_project\\_identifier)", + "type": "The meshStack project identifier.", "required": false }, { "name": "", - "description": " [repo\\_full\\_name](#output\\_repo\\_full\\_name)", - "type": "n/a", + "description": " [subfolder](#input\\_subfolder)", + "type": "The subfolder to use for the SAP BTP resources. This is used to create a folder structure in the SAP BTP cockpit.", "required": false - }, + } + ], + "outputs": [ { "name": "", - "description": " [repo\\_git\\_clone\\_url](#output\\_repo\\_git\\_clone\\_url)", + "description": " [btp\\_subdirectory\\_id](#output\\_btp\\_subdirectory\\_id)", "type": "n/a", "required": false }, { "name": "", - "description": " [repo\\_html\\_url](#output\\_repo\\_html\\_url)", + "description": " [btp\\_subdirectory\\_name](#output\\_btp\\_subdirectory\\_name)", "type": "n/a", "required": false }, { "name": "", - "description": " [repo\\_name](#output\\_repo\\_name)", + "description": " [project\\_folder](#output\\_project\\_folder)", "type": "n/a", "required": false } + ] + }, + { + "id": "stackit-project", + "platformType": "stackit", + "logo": "assets/building-block-logos/stackit-project.png", + "buildingBlockUrl": "git@github.com:meshcloud/meshstack-hub/tree/main/modules/stackit/project/buildingblock", + "backplaneUrl": null, + "name": "StackIt Project", + "supportedPlatforms": [ + "stackit" ], - "inputs": [ + "description": "Creates a new StackIt project and manages user access permissions with role-based access control.\n", + "howToUse": null, + "resources": [ { "name": "", - "description": " [github\\_app\\_id](#input\\_github\\_app\\_id)", - "type": "ID of the GitHub App", + "description": " [environment](#input\\_environment)", + "type": "The environment type (production, staging, development). If not set, uses parent\\_container\\_id directly.", "required": false }, { "name": "", - "description": " [github\\_app\\_installation\\_id](#input\\_github\\_app\\_installation\\_id)", - "type": "Installation ID of the GitHub App", + "description": " [labels](#input\\_labels)", + "type": "Labels to apply to the project. Use 'networkArea' to specify the STACKIT Network Area.", "required": false }, { "name": "", - "description": " [github\\_app\\_pem\\_file](#input\\_github\\_app\\_pem\\_file)", - "type": "GitHub App private key content", + "description": " [parent\\_container\\_id](#input\\_parent\\_container\\_id)", + "type": "The parent container ID (organization or folder) where the project will be created.", "required": false }, { "name": "", - "description": " [github\\_org](#input\\_github\\_org)", - "type": "Name of the GitHub organization", + "description": " [parent\\_container\\_ids](#input\\_parent\\_container\\_ids)", + "type": "Parent container IDs for different environments. If environment is set, the corresponding container ID will be used.", "required": false }, { "name": "", - "description": " [repo\\_description](#input\\_repo\\_description)", - "type": "Description of the GitHub repository", + "description": " [project\\_name](#input\\_project\\_name)", + "type": "The name of the StackIt project to create.", "required": false }, { "name": "", - "description": " [repo\\_name](#input\\_repo\\_name)", - "type": "Name of the GitHub repository", + "description": " [service\\_account\\_email](#input\\_service\\_account\\_email)", + "type": "The email address of the service account that will own this project.", "required": false }, { "name": "", - "description": " [repo\\_visibility](#input\\_repo\\_visibility)", - "type": "Visibility of the GitHub repository", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", "required": false }, { "name": "", - "description": " [template\\_owner](#input\\_template\\_owner)", - "type": "Owner of the template repository", + "description": " [container\\_id](#output\\_container\\_id)", + "type": "The user-friendly container ID of the created StackIt project.", "required": false }, { "name": "", - "description": " [template\\_repo](#input\\_template\\_repo)", - "type": "Name of the template repository", + "description": " [project\\_id](#output\\_project\\_id)", + "type": "The UUID of the created StackIt project.", "required": false }, { "name": "", - "description": " [use\\_template](#input\\_use\\_template)", - "type": "Flag to indicate whether to create a repo based on a Template Repository", + "description": " [project\\_name](#output\\_project\\_name)", + "type": "The name of the created StackIt project.", + "required": false + }, + { + "name": "", + "description": " [project\\_url](#output\\_project\\_url)", + "type": "The deep link URL to access the project in the StackIt portal.", + "required": false + } + ], + "inputs": [ + { + "name": "", + "description": " [environment](#input\\_environment)", + "type": "The environment type (production, staging, development). If not set, uses parent\\_container\\_id directly.", + "required": false + }, + { + "name": "", + "description": " [labels](#input\\_labels)", + "type": "Labels to apply to the project. Use 'networkArea' to specify the STACKIT Network Area.", + "required": false + }, + { + "name": "", + "description": " [parent\\_container\\_id](#input\\_parent\\_container\\_id)", + "type": "The parent container ID (organization or folder) where the project will be created.", + "required": false + }, + { + "name": "", + "description": " [parent\\_container\\_ids](#input\\_parent\\_container\\_ids)", + "type": "Parent container IDs for different environments. If environment is set, the corresponding container ID will be used.", + "required": false + }, + { + "name": "", + "description": " [project\\_name](#input\\_project\\_name)", + "type": "The name of the StackIt project to create.", + "required": false + }, + { + "name": "", + "description": " [service\\_account\\_email](#input\\_service\\_account\\_email)", + "type": "The email address of the service account that will own this project.", + "required": false + }, + { + "name": "", + "description": " [users](#input\\_users)", + "type": "List of users from authoritative system", "required": false } ], "outputs": [ { "name": "", - "description": " [repo\\_full\\_name](#output\\_repo\\_full\\_name)", - "type": "n/a", + "description": " [container\\_id](#output\\_container\\_id)", + "type": "The user-friendly container ID of the created StackIt project.", "required": false }, { "name": "", - "description": " [repo\\_git\\_clone\\_url](#output\\_repo\\_git\\_clone\\_url)", - "type": "n/a", + "description": " [project\\_id](#output\\_project\\_id)", + "type": "The UUID of the created StackIt project.", "required": false }, { "name": "", - "description": " [repo\\_html\\_url](#output\\_repo\\_html\\_url)", - "type": "n/a", + "description": " [project\\_name](#output\\_project\\_name)", + "type": "The name of the created StackIt project.", "required": false }, { "name": "", - "description": " [repo\\_name](#output\\_repo\\_name)", - "type": "n/a", + "description": " [project\\_url](#output\\_project\\_url)", + "type": "The deep link URL to access the project in the StackIt portal.", "required": false } ] diff --git a/website/src/app/core/template.ts b/website/src/app/core/template.ts index dab707e5..4f90176a 100644 --- a/website/src/app/core/template.ts +++ b/website/src/app/core/template.ts @@ -10,4 +10,4 @@ export interface Template { supportedPlatforms: PlatformType[]; } -export type PlatformType = 'azure' | 'aws' | 'gcp' | 'github'; \ No newline at end of file +export type PlatformType = 'aks' | 'aws' | 'azure' | 'azuredevops' | 'cloudfoundry' | 'datadog' | 'gcp' | 'github' | 'ionos' | 'kubernetes' | 'oci' | 'openshift' | 'openstack' | 'ovh' | 'sapbtp' | 'stackit' | 'tencentcloud'; \ No newline at end of file From 6110ac2ba147731078aedcefe1aec28fc42569eb Mon Sep 17 00:00:00 2001 From: Florian Nowarre Date: Wed, 21 Jan 2026 11:36:18 +0100 Subject: [PATCH 4/9] feat: pre-commit --- modules/oci/application-compartment/buildingblock/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/oci/application-compartment/buildingblock/README.md b/modules/oci/application-compartment/buildingblock/README.md index aaf93edb..2d3e054f 100644 --- a/modules/oci/application-compartment/buildingblock/README.md +++ b/modules/oci/application-compartment/buildingblock/README.md @@ -187,9 +187,9 @@ No modules. | [foundation](#input\_foundation) | Foundation name prefix | `string` | n/a | yes | | [project\_id](#input\_project\_id) | Project identifier (e.g., application name) | `string` | n/a | yes | | [region](#input\_region) | OCI region identifier (e.g., eu-frankfurt-1, us-ashburn-1) | `string` | n/a | yes | -| [tag\_relations](#input\_tag\_relations) | YAML configuration for tag-based compartment mapping | `string` | `"# meshStack tag names to read\ntag_names:\n environment: \"Environment\"\n landing_zone: \"landingzone_family\"\n\n# Landing zone configurations\nlanding_zones:\n # Sandbox: single compartment for all environments\n sandbox:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...sandbox\"\n \n # Cloud-native: per-environment compartments\n cloud-native:\n environments:\n dev:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-dev\"\n qa:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-qa\"\n test:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-test\"\n prod:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-prod\"\n\n# Fallback if no match\ndefault_compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...default\"\n"` | no | +| [tag\_relations](#input\_tag\_relations) | YAML configuration for tag-based compartment mapping | `string` | `"# meshStack tag names to read\ntag_names:\n environment: \"Environment\"\n landing_zone: \"landingzone_family\"\n\n# Landing zone configurations\nlanding_zones:\n # Sandbox: single compartment for all environments\n sandbox:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...sandbox\"\n\n # Cloud-native: per-environment compartments\n cloud-native:\n environments:\n dev:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-dev\"\n qa:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-qa\"\n test:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-test\"\n prod:\n compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...cloudnative-prod\"\n\n# Fallback if no match\ndefault_compartment_id: \"ocid1.compartment.oc1..aaaaaaaa...default\"\n"` | no | | [tenancy\_ocid](#input\_tenancy\_ocid) | OCID of the OCI tenancy | `string` | n/a | yes | -| [users](#input\_users) | List of users from authoritative system |
list(object({
meshIdentifier = string
username = string
firstName = string
lastName = string
email = string
euid = string
roles = list(string)
}))
| `[]` | no | +| [users](#input\_users) | List of users from authoritative system |
list(object({
meshIdentifier = string
username = string
firstName = string
lastName = string
email = string
euid = string
roles = list(string)
}))
| `[]` | no | | [workspace\_id](#input\_workspace\_id) | Workspace identifier (e.g., team name or business unit) | `string` | n/a | yes | ## Outputs From b07a78c5a44ac2f1c38c25a0d75468da7fb41a01 Mon Sep 17 00:00:00 2001 From: Florian Nowarre Date: Wed, 21 Jan 2026 11:42:22 +0100 Subject: [PATCH 5/9] feat: adding full name for OCI --- website/src/app/shared/platform/platform.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/src/app/shared/platform/platform.service.ts b/website/src/app/shared/platform/platform.service.ts index ac817350..22a95e00 100644 --- a/website/src/app/shared/platform/platform.service.ts +++ b/website/src/app/shared/platform/platform.service.ts @@ -80,6 +80,8 @@ export class PlatformService { return { name: 'OpenStack', logo: logoUrl }; case 'openshift': return { name: 'OpenShift', logo: logoUrl }; + case 'oci': + return { name: 'Oracle Cloud Infrastructure', logo: logoUrl }; case 'tencentcloud': return { name: 'Tencent Cloud', logo: logoUrl }; default: From 8d0624b5631421526aa9a945c13357b3c6f7c139 Mon Sep 17 00:00:00 2001 From: Florian Nowarre Date: Wed, 4 Feb 2026 17:21:27 +0100 Subject: [PATCH 6/9] chore: adding minimum provider --- .../oci/application-compartment/buildingblock/provider.tf | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/oci/application-compartment/buildingblock/provider.tf b/modules/oci/application-compartment/buildingblock/provider.tf index fdcb3fa6..441d3e00 100644 --- a/modules/oci/application-compartment/buildingblock/provider.tf +++ b/modules/oci/application-compartment/buildingblock/provider.tf @@ -1,10 +1,13 @@ terraform { required_providers { meshstack = { - source = "meshcloud/meshstack" + source = "meshcloud/meshstack" + version = "0.17.3" + } oci = { - source = "oracle/oci" + source = "oracle/oci" + version = "7.32.0" } } } From 68d9d4b08f9100c7d86deebbfb51dde9f40ea6a4 Mon Sep 17 00:00:00 2001 From: Florian Nowarre Date: Wed, 4 Feb 2026 17:39:20 +0100 Subject: [PATCH 7/9] chore: adding pipeline for creating logo.png --- .github/scripts/generate-icon-prompts.py | 243 ++++++++++++++++++ .github/workflows/icon-prompts.yml | 104 ++++++++ .../buildingblock/logo.png | Bin 11771 -> 0 bytes 3 files changed, 347 insertions(+) create mode 100644 .github/scripts/generate-icon-prompts.py create mode 100644 .github/workflows/icon-prompts.yml delete mode 100644 modules/oci/application-compartment/buildingblock/logo.png diff --git a/.github/scripts/generate-icon-prompts.py b/.github/scripts/generate-icon-prompts.py new file mode 100644 index 00000000..140e13bf --- /dev/null +++ b/.github/scripts/generate-icon-prompts.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +""" +Generate icon prompts for building blocks missing logo.png files. +Parses README.md frontmatter and creates AI image generation prompts. +""" + +import os +import sys +import yaml +import json +from pathlib import Path + +PLATFORM_COLORS = { + "aws": { + "primary": "#FF9900", + "secondary": "#232F3E", + "accent": "#7FBA00", + "name": "AWS colors: orange (#FF9900), dark blue (#232F3E), and lime green (#7FBA00)" + }, + "azure": { + "primary": "#0078D4", + "secondary": "#00BCF2", + "accent": "#50E6FF", + "name": "Azure colors: blue (#0078D4), cyan (#00BCF2), and light blue (#50E6FF)" + }, + "aks": { + "primary": "#326CE5", + "secondary": "#0078D4", + "accent": "#00BCF2", + "name": "Kubernetes/Azure colors: blue (#326CE5), Azure blue (#0078D4), and cyan (#00BCF2)" + }, + "azuredevops": { + "primary": "#0078D4", + "secondary": "#00BCF2", + "accent": "#005A9E", + "name": "Azure DevOps colors: blue (#0078D4), teal (#00BCF2), and dark blue (#005A9E)" + }, + "gcp": { + "primary": "#4285F4", + "secondary": "#EA4335", + "accent": "#FBBC04", + "name": "Google colors: blue (#4285F4), red (#EA4335), yellow (#FBBC04), and green (#34A853)" + }, + "github": { + "primary": "#6e5494", + "secondary": "#24292e", + "accent": "#8b5cf6", + "name": "GitHub colors: purple (#6e5494), dark gray (#24292e), and bright purple (#8b5cf6)" + }, + "ionos": { + "primary": "#003D7A", + "secondary": "#FF6600", + "accent": "#0096D6", + "name": "IONOS colors: blue (#003D7A), orange (#FF6600), and light blue (#0096D6)" + }, + "kubernetes": { + "primary": "#326CE5", + "secondary": "#00D3E0", + "accent": "#7AB8FF", + "name": "Kubernetes colors: blue (#326CE5), cyan (#00D3E0), and light blue (#7AB8FF)" + }, + "oci": { + "primary": "#F80000", + "secondary": "#312D2A", + "accent": "#C74634", + "name": "Oracle colors: red (#F80000), charcoal (#312D2A), and burnt orange (#C74634)" + }, + "sapbtp": { + "primary": "#0070AD", + "secondary": "#F0AB00", + "accent": "#0078D4", + "name": "SAP colors: blue (#0070AD), gold (#F0AB00), and light blue (#0078D4)" + }, + "stackit": { + "primary": "#00A859", + "secondary": "#007A3D", + "accent": "#7FBA00", + "name": "STACKIT colors: green (#00A859), dark green (#007A3D), and lime (#7FBA00)" + } +} + + + +def parse_readme_frontmatter(readme_path): + """Extract YAML frontmatter from README.md""" + with open(readme_path, 'r', encoding='utf-8') as f: + content = f.read() + + if not content.startswith('---'): + return None + + # Extract frontmatter between --- delimiters + parts = content.split('---', 2) + if len(parts) < 3: + return None + + try: + frontmatter = yaml.safe_load(parts[1]) + return frontmatter + except yaml.YAMLError: + return None + + +def get_platform_from_frontmatter(frontmatter): + """Get the primary platform from supportedPlatforms list""" + platforms = frontmatter.get('supportedPlatforms', []) + if not platforms: + return None + return platforms[0] # Use first platform + + +def generate_icon_prompt(name, platform, description): + """Generate an AI image generation prompt for an icon""" + platform_colors = PLATFORM_COLORS.get(platform) + + if not platform_colors: + # Fallback to generic bright colors + color_scheme = "bright, vibrant colors" + else: + color_scheme = platform_colors["name"] + + # Clean up description + clean_description = description.strip().replace('\n', ' ') + + # Generate AI prompt + ai_prompt = f"""Create a professional flat design icon for the meshcloud Building Block ecosystem. + +Purpose: {clean_description} + +Visual Style: +- Plain white background (#FFFFFF) for easy removal in post-processing +- Background will be converted to transparent (see post-processing steps) +- Use {color_scheme} as accent colors +- Maximum 2-3 colors total +- Simple geometric shapes with clean lines +- Flat design (no gradients, shadows, or 3D effects) +- Minimalist, modern appearance + +Composition: +- Square centered layout (NOT horizontal) +- Icon fills the entire canvas edge-to-edge (100% of area) +- No padding or margins around the icon +- Symmetrical arrangement +- Platform-appropriate symbol for {platform.upper()} (e.g., cloud, container, database, server, etc.) + +Style: Enterprise professional, instantly recognizable at small sizes, similar to app icons or logos. +Dimensions: 800x800 pixels""" + + # Generate post-processing instructions + post_processing = """**Step 1: Remove white background with GIMP (free)** + +a) Open image in GIMP +b) Right-click layer → "Add Alpha Channel" +c) Tools → "Select by Color" (Shift+O) +d) Click white background +e) Press Delete key +f) File → Export As → logo.png +g) Set Compression level to 9 → Export + +**Step 2: Resize to 800x800 pixels if needed** + +- GIMP: Image → Scale Image → 800x800px +- Or use any image editor + +**Step 3: Compress with pngquant (free command line tool)** + +- Install: `brew install pngquant` (Mac) or `apt install pngquant` (Linux) +- Run: `pngquant --quality=20-30 logo.png --ext .png --force` +- This reduces file size by 60-80% while maintaining quality + +**Target specs:** 800x800px PNG with transparent background, under 100KB""" + + return { + 'ai_prompt': ai_prompt, + 'post_processing': post_processing + } + +def find_missing_logos(modules_dir): + """Find all buildingblock directories missing logo.png""" + missing = [] + + for root, dirs, files in os.walk(modules_dir): + if 'buildingblock' in root: + buildingblock_path = Path(root) + readme_path = buildingblock_path / 'README.md' + logo_path = buildingblock_path / 'logo.png' + + if readme_path.exists() and not logo_path.exists(): + frontmatter = parse_readme_frontmatter(readme_path) + if frontmatter: + platform = get_platform_from_frontmatter(frontmatter) + name = frontmatter.get('name', 'Unknown') + description = frontmatter.get('description', '') + + # Get relative path from modules directory + rel_path = buildingblock_path.relative_to(modules_dir) + + missing.append({ + 'path': str(rel_path), + 'name': name, + 'platform': platform, + 'description': description, + 'readme_path': str(readme_path), + 'logo_path': str(logo_path) + }) + + return missing + +def main(): + # Get modules directory + repo_root = Path(__file__).parent.parent.parent + modules_dir = repo_root / 'modules' + + if not modules_dir.exists(): + print(f"ERROR: Modules directory not found: {modules_dir}", file=sys.stderr) + sys.exit(1) + + # Find missing logos + missing_logos = find_missing_logos(modules_dir) + + # Generate prompts for each missing logo + results = [] + for item in missing_logos: + prompt_data = generate_icon_prompt( + item['name'], + item['platform'] or 'generic', + item['description'] + ) + + results.append({ + 'name': item['name'], + 'platform': item['platform'], + 'path': item['path'], + 'logo_path': item['logo_path'], + 'ai_prompt': prompt_data['ai_prompt'], + 'post_processing': prompt_data['post_processing'] + }) + + # Output as JSON for GitHub Action to consume + print(json.dumps(results, indent=2)) + +if __name__ == '__main__': + main() diff --git a/.github/workflows/icon-prompts.yml b/.github/workflows/icon-prompts.yml new file mode 100644 index 00000000..fccf3943 --- /dev/null +++ b/.github/workflows/icon-prompts.yml @@ -0,0 +1,104 @@ +name: Generate Icon Prompts for Missing Logos + +on: + pull_request: + types: [opened, synchronize, reopened] + paths: + - 'modules/**/buildingblock/README.md' + +permissions: + pull-requests: write + contents: read + +jobs: + check-missing-logos: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install pyyaml + + - name: Find missing logos and generate prompts + id: generate + run: | + python .github/scripts/generate-icon-prompts.py > prompts.json + COUNT=$(jq 'length' prompts.json) + echo "has_missing=$([ "$COUNT" -gt 0 ] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT + echo "count=$COUNT" >> $GITHUB_OUTPUT + + - name: Read prompts + if: steps.generate.outputs.has_missing == 'true' + id: read_prompts + run: | + PROMPTS=$(cat prompts.json) + echo "prompts<> $GITHUB_OUTPUT + echo "$PROMPTS" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Generate PR comment + if: steps.generate.outputs.has_missing == 'true' + id: format_comment + uses: actions/github-script@v7 + env: + PROMPTS_JSON: ${{ steps.read_prompts.outputs.prompts }} + with: + result-encoding: string + script: | + const prompts = JSON.parse(process.env.PROMPTS_JSON); + + if (prompts.length === 0) { + return ''; + } + + let comment = '## 🎨 Missing Building Block Icons\n\n'; + comment += `Found **${prompts.length}** building block(s) without \`logo.png\` files.\n\n`; + comment += 'Copy the **AI Prompts** below and use them with your favorite AI image generator (Gemini, DALL-E, Midjourney, Stable Diffusion, etc.).\n\n'; + comment += 'Then follow the **Post-Processing Steps** to prepare the icons for upload.\n\n'; + comment += '---\n\n'; + + for (const item of prompts) { + comment += `### ${item.name}\n\n`; + comment += `**Platform:** \`${item.platform}\`\n\n`; + comment += `**Path:** \`${item.logo_path}\`\n\n`; + comment += '#### AI Prompt (copy this to image generator)\n\n'; + comment += '```\n'; + comment += item.ai_prompt; + comment += '\n```\n\n'; + comment += '#### Post-Processing Instructions\n\n'; + comment += item.post_processing; + comment += '\n\n'; + comment += '---\n\n'; + } + + return comment; + + - name: Find existing comment + if: steps.generate.outputs.has_missing == 'true' + uses: peter-evans/find-comment@v3 + id: find_comment + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: '🎨 Missing Building Block Icons' + + - name: Create or update comment + if: steps.generate.outputs.has_missing == 'true' + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ steps.find_comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: ${{ steps.format_comment.outputs.result }} + edit-mode: replace + + - name: Success message + if: steps.generate.outputs.has_missing == 'false' + run: | + echo "✅ All building blocks have logo.png files!" diff --git a/modules/oci/application-compartment/buildingblock/logo.png b/modules/oci/application-compartment/buildingblock/logo.png deleted file mode 100644 index 754b7405eb5ddf596d99e317e53af325838b73ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11771 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 Date: Wed, 4 Feb 2026 17:42:57 +0100 Subject: [PATCH 8/9] chore: pre-commit --- .../buildingblock/README.md | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/oci/application-compartment/buildingblock/README.md b/modules/oci/application-compartment/buildingblock/README.md index 2d3e054f..065e2cc3 100644 --- a/modules/oci/application-compartment/buildingblock/README.md +++ b/modules/oci/application-compartment/buildingblock/README.md @@ -159,7 +159,10 @@ The module automatically: ## Requirements -No requirements. +| Name | Version | +|------|---------| +| [meshstack](#requirement\_meshstack) | 0.17.3 | +| [oci](#requirement\_oci) | 7.32.0 | ## Modules @@ -169,16 +172,16 @@ No modules. | Name | Type | |------|------| -| [oci_identity_compartment.application](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_compartment) | resource | -| [oci_identity_group.admins](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_group) | resource | -| [oci_identity_group.readers](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_group) | resource | -| [oci_identity_group.users](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_group) | resource | -| [oci_identity_policy.application](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_policy) | resource | -| [oci_identity_user_group_membership.admins](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user_group_membership) | resource | -| [oci_identity_user_group_membership.readers](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user_group_membership) | resource | -| [oci_identity_user_group_membership.users](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/identity_user_group_membership) | resource | -| [meshstack_project.project](https://registry.terraform.io/providers/meshcloud/meshstack/latest/docs/data-sources/project) | data source | -| [oci_identity_users.all_users](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_users) | data source | +| [oci_identity_compartment.application](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_compartment) | resource | +| [oci_identity_group.admins](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_group) | resource | +| [oci_identity_group.readers](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_group) | resource | +| [oci_identity_group.users](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_group) | resource | +| [oci_identity_policy.application](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_policy) | resource | +| [oci_identity_user_group_membership.admins](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_user_group_membership) | resource | +| [oci_identity_user_group_membership.readers](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_user_group_membership) | resource | +| [oci_identity_user_group_membership.users](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/resources/identity_user_group_membership) | resource | +| [meshstack_project.project](https://registry.terraform.io/providers/meshcloud/meshstack/0.17.3/docs/data-sources/project) | data source | +| [oci_identity_users.all_users](https://registry.terraform.io/providers/oracle/oci/7.32.0/docs/data-sources/identity_users) | data source | ## Inputs From aa4716a5ded38d915fa36eae4841c3564f3db243 Mon Sep 17 00:00:00 2001 From: Florian Nowarre Date: Wed, 4 Feb 2026 17:51:45 +0100 Subject: [PATCH 9/9] chore: adding new logo --- .../buildingblock/logo.png | Bin 0 -> 10567 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 modules/oci/application-compartment/buildingblock/logo.png diff --git a/modules/oci/application-compartment/buildingblock/logo.png b/modules/oci/application-compartment/buildingblock/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d78a706e7f945abcd1049d281bb2130cb80a7b3f GIT binary patch literal 10567 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 AaR2}S literal 0 HcmV?d00001