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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 0 additions & 32 deletions modules/azure/azure-virtual-machine-starterkit/backplane/README.md

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The Azure VM Starterkit building block automates the creation of a complete Azur
## Features

- Single unified project (no dev/prod separation)
- Flexible VM configuration (Linux or Windows)
- Linux VM with SSH key authentication
- Optional public IP assignment
- Automatic project admin assignment for the creator
- Customizable project tags
Expand Down Expand Up @@ -64,13 +64,11 @@ No modules.
| <a name="input_landing_zone_identifier"></a> [landing\_zone\_identifier](#input\_landing\_zone\_identifier) | Azure Landing zone identifier for the tenant. | `string` | n/a | yes |
| <a name="input_name"></a> [name](#input\_name) | This name will be used for the created project and VM | `string` | n/a | yes |
| <a name="input_project_tags_yaml"></a> [project\_tags\_yaml](#input\_project\_tags\_yaml) | YAML configuration for project tags. Expected structure:<pre>yaml<br/>key1:<br/> - "value1"<br/> - "value2"<br/>key2:<br/> - "value3"</pre> | `string` | `"{}"` | no |
| <a name="input_vm_admin_password"></a> [vm\_admin\_password](#input\_vm\_admin\_password) | The admin password for Windows VM (required for Windows). | `string` | `null` | no |
| <a name="input_vm_admin_username"></a> [vm\_admin\_username](#input\_vm\_admin\_username) | The admin username for the VM. | `string` | `"azureuser"` | no |
| <a name="input_vm_enable_public_ip"></a> [vm\_enable\_public\_ip](#input\_vm\_enable\_public\_ip) | Whether to create and assign a public IP address to the VM. | `bool` | `false` | no |
| <a name="input_vm_location"></a> [vm\_location](#input\_vm\_location) | The Azure region where the VM will be deployed. | `string` | `"westeurope"` | no |
| <a name="input_vm_os_type"></a> [vm\_os\_type](#input\_vm\_os\_type) | The operating system type (Linux or Windows). | `string` | `"Linux"` | no |
| <a name="input_vm_size"></a> [vm\_size](#input\_vm\_size) | The size of the virtual machine. | `string` | `"Standard_B1s"` | no |
| <a name="input_vm_ssh_public_key"></a> [vm\_ssh\_public\_key](#input\_vm\_ssh\_public\_key) | SSH public key for Linux VM authentication (required for Linux). | `string` | `null` | no |
| <a name="input_vm_ssh_public_key"></a> [vm\_ssh\_public\_key](#input\_vm\_ssh\_public\_key) | SSH public key used to authenticate as the VM's admin user. | `string` | n/a | yes |
| <a name="input_workspace_identifier"></a> [workspace\_identifier](#input\_workspace\_identifier) | The identifier of the meshStack workspace | `string` | n/a | yes |

## Outputs
Expand Down Expand Up @@ -106,47 +104,16 @@ module "vm_starterkit" {
username = "jdoe"
}

vm_os_type = "Linux"
vm_size = "Standard_B2s"
vm_location = "westeurope"
vm_ssh_public_key = file("~/.ssh/id_rsa.pub")
vm_enable_public_ip = true
}
```

### Windows VM

```hcl
module "vm_starterkit" {
source = "./modules/azure/azure-virtual-machine/starterkit/buildingblock"

workspace_identifier = "my-workspace"
name = "my-win-vm"
full_platform_identifier = "azure.my-platform"
landing_zone_identifier = "my-landing-zone"

# Building block UUID
azure_vm_definition_version_uuid = "..."

creator = {
type = "User"
identifier = "user456"
displayName = "Jane Smith"
username = "jsmith"
}

vm_os_type = "Windows"
vm_size = "Standard_D2s_v3"
vm_location = "northeurope"
vm_admin_password = var.windows_admin_password
vm_enable_public_ip = true
}
```

## Notes

- The resource group will be automatically created by the Azure VM building block
- Ensure SSH public key is provided for Linux VMs
- Ensure admin password is provided for Windows VMs
- An SSH public key is required (the VM uses SSH key authentication)
- Public IP is disabled by default for security
- Project tags can be customized using YAML format
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -61,41 +61,26 @@ resource "meshstack_building_block" "azure_vm" {
uuid = meshstack_tenant_v4.vm_tenant.metadata.uuid
}
display_name = "Azure Virtual Machine"
inputs = merge(
{
vm_name = {
value = jsonencode(local.identifier)
}
location = {
value = jsonencode(var.vm_location)
}
os_type = {
value = jsonencode(var.vm_os_type)
}
vm_size = {
value = jsonencode(var.vm_size)
}
admin_username = {
value = jsonencode(var.vm_admin_username)
}
enable_public_ip = {
value = jsonencode(var.vm_enable_public_ip)
}
},
# Only send the OS-specific credential input for the matching OS. This mirrors
# the pre-v3 behavior where a null `value_string` omitted the input entirely;
# under v3 a `jsonencode(... : null)` would instead send an explicit JSON null.
var.vm_os_type == "Linux" ? {
ssh_public_key = {
value = jsonencode(var.vm_ssh_public_key)
}
} : {},
var.vm_os_type == "Windows" ? {
admin_password = {
value = jsonencode(var.vm_admin_password)
}
} : {},
)
inputs = {
vm_name = {
value = jsonencode(local.identifier)
}
location = {
value = jsonencode(var.vm_location)
}
vm_size = {
value = jsonencode(var.vm_size)
}
admin_username = {
value = jsonencode(var.vm_admin_username)
}
enable_public_ip = {
value = jsonencode(var.vm_enable_public_ip)
}
ssh_public_key = {
value = jsonencode(var.vm_ssh_public_key)
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ This starter kit has set up the following resources in workspace `${var.workspac

- **Azure Project**: A dedicated project for your virtual machine resources
- **Azure Tenant**: An Azure subscription tenant with your chosen landing zone
- **Virtual Machine**: ${var.vm_os_type} VM (${var.vm_size}) in ${var.vm_location}
- **Virtual Machine**: Linux VM (${var.vm_size}) in ${var.vm_location}

---

## VM Details

- **VM Name**: ${local.identifier}
- **Operating System**: ${var.vm_os_type}
- **Operating System**: Linux
- **Size**: ${var.vm_size}
- **Region**: ${var.vm_location}
- **Public IP**: ${var.vm_enable_public_ip ? "Enabled" : "Disabled"}
Expand All @@ -50,9 +50,7 @@ This starter kit has set up the following resources in workspace `${var.workspac
## Next Steps

### 1. Access Your VM
${var.vm_os_type == "Linux" && var.vm_enable_public_ip ? "- Connect via SSH using your provided SSH key" : ""}
${var.vm_os_type == "Windows" && var.vm_enable_public_ip ? "- Connect via RDP using the admin credentials" : ""}
${!var.vm_enable_public_ip ? "- Connect through Azure Bastion or VPN (no public IP assigned)" : ""}
${var.vm_enable_public_ip ? "- Connect via SSH using your provided SSH key" : "- Connect through Azure Bastion or VPN (no public IP assigned)"}

### 2. View Azure Resources
- [Access Azure Tenant](/#/w/${var.workspace_identifier}/p/${meshstack_project.vm_project.metadata.name}/i/${var.full_platform_identifier}/overview)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,6 @@ variable "vm_location" {
default = "westeurope"
}

variable "vm_os_type" {
type = string
description = "The operating system type (Linux or Windows)."
default = "Linux"
validation {
condition = contains(["Linux", "Windows"], var.vm_os_type)
error_message = "vm_os_type must be either 'Linux' or 'Windows'"
}
}

variable "vm_size" {
type = string
description = "The size of the virtual machine."
Expand All @@ -87,15 +77,7 @@ variable "vm_admin_username" {

variable "vm_ssh_public_key" {
type = string
description = "SSH public key for Linux VM authentication (required for Linux)."
default = null
}

variable "vm_admin_password" {
type = string
description = "The admin password for Windows VM (required for Windows)."
default = null
sensitive = true
description = "SSH public key used to authenticate as the VM's admin user."
}

variable "vm_enable_public_ip" {
Expand Down
116 changes: 116 additions & 0 deletions modules/azure/azure-virtual-machine-starterkit/e2e/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
variable "test_context" {
type = object({
hub_git_ref = string
workspace = string
name_suffix = string

# Mode discriminator: set in foundation mode to order an already-deployed BBD version;
# null in build-from-source mode, which builds the child + starter-kit BBDs from hub source.
bbd_version_ref = optional(object({
uuid = string
}))

# Azure platform coordinates. Needed in build-from-source mode to provision the child VM
# backplane and to let the starter kit create its project/tenant on a landing zone.
fixtures = optional(object({
azure = object({
entra_tenant_id = string
subscription_uuid = string
full_platform_identifier = string
landing_zone_identifier = string
})
}))
})
nullable = false
}

locals {
build_from_source = var.test_context.bbd_version_ref == null

# Role definitions/assignments for the child VM backplane are scoped here. In the smoke-test
# environment this is the fixture subscription; a real foundation scopes its backplane at the
# management group that parents all landing-zone subscriptions (see the foundation deploy unit).
azure_scope = local.build_from_source ? "/subscriptions/${var.test_context.fixtures.azure.subscription_uuid}" : null

# VM project/name must satisfy ^[a-zA-Z0-9-]{0,24}$. name_suffix is a 14-digit timestamp.
vm_name = "vm${var.test_context.name_suffix}"
}

# A throwaway SSH key so the Linux VM can be created (azurerm requires a valid RSA public key and
# disables password auth for Linux). The private key is never used — the smoke test only asserts the
# building block reaches SUCCEEDED.
resource "tls_private_key" "vm" {
count = local.build_from_source ? 1 : 0
algorithm = "RSA"
rsa_bits = 4096
}

# Child Azure VM building block definition (composed by the starter kit).
module "azure_virtual_machine" {
count = local.build_from_source ? 1 : 0
source = "../../azure-virtual-machine"

meshstack = {
owning_workspace_identifier = var.test_context.workspace
tags = {}
}
hub = {
git_ref = var.test_context.hub_git_ref
bbd_draft = true
}

azure_tenant_id = var.test_context.fixtures.azure.entra_tenant_id
azure_scope = local.azure_scope

# Unique backplane name per run so role definitions don't clash across concurrent/retried runs.
backplane_name = "hub-e2e-vm-${var.test_context.name_suffix}"
}

# Azure VM starter-kit building block definition (the module under test).
module "starterkit" {
count = local.build_from_source ? 1 : 0
source = "../"

meshstack = {
owning_workspace_identifier = var.test_context.workspace
tags = {}
}
hub = {
git_ref = var.test_context.hub_git_ref
bbd_draft = true
}

full_platform_identifier = var.test_context.fixtures.azure.full_platform_identifier
landing_zone_identifier = var.test_context.fixtures.azure.landing_zone_identifier
azure_vm_definition_version_uuid = module.azure_virtual_machine[0].building_block_definition.version_ref.uuid
}

locals {
version_ref = local.build_from_source ? module.starterkit[0].building_block_definition.version_ref : var.test_context.bbd_version_ref
}

resource "meshstack_building_block" "this" {
# Force the whole composition (both BBDs + child backplane) to exist before the run, and to be
# torn down only after the building block's delete run completes.
depends_on = [module.starterkit, module.azure_virtual_machine]

wait_for_completion = true

spec = {
building_block_definition_version_ref = { uuid = local.version_ref.uuid }

display_name = "smoke-test-azure-vm-starterkit-${var.test_context.name_suffix}"
target_ref = {
kind = "meshWorkspace"
name = var.test_context.workspace
}

inputs = {
name = { value = jsonencode(local.vm_name) }
vm_location = { value = jsonencode("westeurope") }
vm_size = { value = jsonencode("Standard_B1s") }
vm_enable_public_ip = { value = jsonencode(false) }
vm_ssh_public_key = { value = jsonencode(local.build_from_source ? tls_private_key.vm[0].public_key_openssh : "") }
}
}
}
18 changes: 18 additions & 0 deletions modules/azure/azure-virtual-machine-starterkit/e2e/terraform.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
terraform {
required_version = ">= 1.0"

required_providers {
meshstack = {
source = "meshcloud/meshstack"
}
azurerm = {
source = "hashicorp/azurerm"
}
azuread = {
source = "hashicorp/azuread"
}
tls = {
source = "hashicorp/tls"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
run "azure_virtual_machine_starterkit_hub" {
assert {
condition = meshstack_building_block.this.status.status == "SUCCEEDED"
error_message = "azure/azure-virtual-machine-starterkit hub building block expected SUCCEEDED, got ${meshstack_building_block.this.status.status}"
}

assert {
condition = length(jsondecode(meshstack_building_block.this.status.outputs["summary"].value)) > 0
error_message = "expected a non-empty summary output from the starter kit"
}
}
Loading
Loading