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
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.terraform/
*.tfstate
*.tfstate.*
terraform.tfvars
override.tf
override.tf.json
crash.log
43 changes: 43 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
backend "azurerm" {
resource_group_name = "tfstate"
storage_account_name = "terra5"
container_name = "tfstate"
key = "terraform.tfstate"
}
}
80 changes: 80 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
terraform {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The terraform {} block is present here but the task requires a remote backend configured in backend.tf with storage_account_name = "yourstorageaccount" (literal), container tfstate, resource group mate-azure-task-12, and key terraform.tfstate. Make sure you have a separate backend.tf file with those exact values. If you have backend code elsewhere, confirm storage_account_name is exactly yourstorageaccount (this is a high-priority literal requirement).

required_version = ">= 1.5.0, < 2.0.0"

required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.75"
}
random = {
source = "hashicorp/random"
version = "~> 3.5"
}
}
}

provider "azurerm" {
features {}
subscription_id = var.subscription_id
}

resource "random_integer" "dns_suffix" {
min = 1000
max = 9999
}

locals {
dns_label = "${var.dns_label}${random_integer.dns_suffix.result}"

common_tags = merge(
{
environment = var.environment
project = var.resource_group_name
managed_by = "terraform"
},
var.tags
)
}

resource "azurerm_resource_group" "rg" {
name = var.resource_group_name

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resource group is created from var.resource_group_name. Per the task checklist the resource group must be named mate-azure-task-12 (or that exact literal must be the default in the root variables). Ensure variables.tf sets resource_group_name = "mate-azure-task-12" so this resource matches the checklist (checklist: resource group name requirement).

location = var.location
tags = local.common_tags
}

module "network" {
source = "./modules/network"

resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
virtual_network_name = var.virtual_network_name
vnet_address_prefix = var.vnet_address_prefix # fixed: was [var.vnet_address_prefix]
subnet_name = var.subnet_name
subnet_address_prefix = var.subnet_address_prefix # fixed: was [var.subnet_address_prefix]
network_security_group_name = var.network_security_group_name
public_ip_address_name = var.public_ip_address_name
dns_label = local.dns_label # fixed: now globally unique
}

module "storage" {
source = "./modules/storage"

resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
storage_account_name = var.storage_account_name # fixed: matched to variable name below
storage_container_name = var.storage_container_name # fixed: matched to variable name below
}

module "compute" {
source = "./modules/compute"

resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
vm_name = var.vm_name
vm_size = var.vm_size
ssh_key_public = var.ssh_key_public
subnet_id = module.network.subnet_id
public_ip_id = module.network.public_ip_id

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compute module expects subnet_id, public_ip_id, and nsg_id from the network module (you pass module.network.subnet_id, module.network.public_ip_id, module.network.nsg_id). Confirm modules/network/outputs.tf exports outputs with these exact names (subnet_id, public_ip_id, nsg_id) and that they refer to the Terraform resources used by compute (otherwise the compute module will fail to attach the NIC, NSG or Public IP).

Comment on lines +76 to +77

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify the network module implements the outputs that the compute module expects (subnet_id, public_ip_id, nsg_id). The compute module here uses module.network.subnet_id, module.network.public_ip_id, and module.network.nsg_id so those outputs must exist and be named exactly in modules/network/outputs.tf (I see outputs expecting azurerm_public_ip.pip.id etc. in the network outputs file; ensure the network resources are named accordingly in modules/network/main.tf) .

nsg_id = module.network.nsg_id
script_url = module.storage.script_url
}
70 changes: 70 additions & 0 deletions modules/compute/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Creates the Network Interface for the VM and associates the NSG.
resource "azurerm_network_interface" "main" {
name = "${var.vm_name}-nic"
location = var.location
resource_group_name = var.resource_group_name

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NIC resource currently does not associate the Network Security Group. The checklist requires the NIC to be associated with the provided NSG. Add an NSG association (for example by adding network_security_group_id = var.nsg_id or using the appropriate association resource) and ensure var.nsg_id is provided to the module. This prevents the NIC from being protected/filtered by the required defaultnsg.

ip_configuration {
name = "internal"
subnet_id = var.subnet_id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = var.public_ip_id

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NIC's ip_configuration sets public_ip_address_id = var.public_ip_id. The network module must export public_ip_id (the Public IP resource id) so this receives a valid resource id; the required output is output "public_ip_id" { value = azurerm_public_ip.pip.id }. Make sure modules/network/outputs.tf provides that output exactly so the NIC can be associated to the public IP as expected by the checklist .

}
}

# Associates the Network Security Group with the Network Interface.
resource "azurerm_network_interface_security_group_association" "main" {
network_interface_id = azurerm_network_interface.main.id
network_security_group_id = var.nsg_id
Comment on lines +16 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You associate the NSG to the NIC using var.nsg_id. Confirm the network module creates a Network Security Group named defaultnsg and exports nsg_id (azurerm_network_security_group.nsg.id). Also ensure that NSG contains inbound rules to allow SSH (port 22) and the application port (e.g., HTTP 80) so the VM is reachable from the Internet (the compute module relies on that association) .

}

# Creates the SSH public key resource as required by the task.
resource "azurerm_ssh_public_key" "main" {
name = "linuxboxsshkey"
resource_group_name = var.resource_group_name
location = var.location
public_key = var.ssh_key_public
}

# Creates the Linux Virtual Machine.
resource "azurerm_linux_virtual_machine" "main" {
name = var.vm_name

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VM name is set to var.vm_name. The task requires the VM be named matebox. That is acceptable if var.vm_name is set to matebox in root variables/terraform.tfvars (confirm that default/value exists). If you want to guarantee the exact required name regardless of variable overrides, consider setting name = "matebox" or ensure the root vm_name variable default/value is matebox .

resource_group_name = var.resource_group_name
location = var.location
size = var.vm_size
admin_username = "azureuser"
network_interface_ids = [azurerm_network_interface.main.id]

admin_ssh_key {
username = "azureuser"
public_key = azurerm_ssh_public_key.main.public_key
}

os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}

source_image_reference {
publisher = "Canonical"
offer = "0001-com-ubuntu-server-jammy"
sku = "22_04-lts"
version = "latest"
}
Comment on lines +48 to +53

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double-check that the source_image_reference matches the explicit task requirement Ubuntu2204. The current values (publisher = "Canonical", offer = "0001-com-ubuntu-server-jammy", sku = "22_04-lts") will provision Ubuntu 22.04 and are acceptable, but confirm the root-level variable vm_size is set to Standard_B1s (that value is used from var.vm_size).

}

# Creates the VM extension to download and execute the installation script.
resource "azurerm_virtual_machine_extension" "main" {
name = "${var.vm_name}-install-app"
virtual_machine_id = azurerm_linux_virtual_machine.main.id
publisher = "Microsoft.Azure.Extensions"
type = "CustomScript"
type_handler_version = "2.0"

settings = <<SETTINGS
{
"fileUris": ["${var.script_url}"],
Comment on lines +64 to +66

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CustomScript extension uses fileUris with ${var.script_url} and commandToExecute to run install-app.sh. Make sure the storage module uploads install-app.sh and outputs script_url (a URL accessible to the VM) — e.g. azurerm_storage_blob.app_script.url. Also verify the blob/container access settings make the blob reachable (modules/storage sets container_access_type = "blob" which allows blob read access). If the blob is private you must supply a SAS URL instead. See modules/storage main/outputs for the expected script_url output .

"commandToExecute": "bash install-app.sh"
}
SETTINGS
Comment on lines +64 to +69

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Custom Script extension settings block is not using the format required to download and execute install-app.sh. "script": "${var.script_url}" is not a valid settings payload for the Linux CustomScript extension. Use a JSON payload with fileUris (list of URLs) and commandToExecute. Example:

settings = <<SETTINGS
{
  "fileUris": ["${var.script_url}"],
  "commandToExecute": "bash install-app.sh"
}
SETTINGS

Ensure var.script_url points to the install-app.sh location and that the command executes it so the ToDo app is installed as required by the checklist.

}
22 changes: 22 additions & 0 deletions modules/compute/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
output "vm_id" {
value = azurerm_linux_virtual_machine.main.id

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The referenced resources (azurerm_linux_virtual_machine.main and azurerm_network_interface.main) do not exist in this module. You must define these resources in main.tf for these outputs to work.

description = "The ID of the virtual machine."
Comment on lines +1 to +3

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This output references azurerm_linux_virtual_machine.main.id. The compute module must actually define an azurerm_linux_virtual_machine resource with the resource name main for this to work. If your VM resource in modules/compute/main.tf is named differently (for example azurerm_linux_virtual_machine.matebox), update this output to reference that name. Per the checklist, outputs must reference real resources defined in the compute module.

}

# Corrected the value to get the private IP from the IP configuration.
output "vm_private_ip" {
value = azurerm_network_interface.main.ip_configuration[0].private_ip_address
description = "The private IP address of the virtual machine."
Comment on lines +7 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This output references azurerm_network_interface.main.private_ip_address. Two issues to address:

  • Ensure the compute module defines an azurerm_network_interface resource named main (or change this output to the actual resource name used).
  • The network interface's private IP is typically available under ip_configuration[0].private_ip_address (e.g., azurerm_network_interface.main.ip_configuration[0].private_ip_address). Referencing .private_ip_address directly may not be valid with the AzureRM provider. Update the attribute path accordingly so the output resolves to the NIC private IP.

}

# Added public IP output for easier verification.
output "vm_public_ip" {
value = azurerm_network_interface.main.ip_configuration[0].public_ip_address_id != null ? data.azurerm_public_ip.vm_pip.ip_address : ""
Comment on lines +13 to +14

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ternary expression here depends on data.azurerm_public_ip.vm_pip succeeding, but the data block below will still be evaluated even when public_ip_address_id is null/empty. That can cause plan/apply to fail. Consider one of these safer approaches:

  • Pass the public IP name or id from the network module into the compute module and use it directly (preferred).
  • Make the data lookup conditional (use count/for_each) so it is only evaluated when a public IP id/name exists.
    This change will make the vm_public_ip output reliable and avoid errors when the NIC/public IP is not set at evaluation time.

description = "The public IP address of the virtual machine."
}

data "azurerm_public_ip" "vm_pip" {
name = split("/", azurerm_network_interface.main.ip_configuration[0].public_ip_address_id)[8]
resource_group_name = var.resource_group_name
depends_on = [azurerm_linux_virtual_machine.main]
Comment on lines +18 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This data.azurerm_public_ip block derives the public IP name with split(...)[8], which is fragile — it assumes the resource ID always has at least 9 segments and that the name is at index 8. This can break across different ID formats or if additional path segments appear. Recommended alternatives:

  • Pass the public IP name (or resource id) from the network module into compute (best), so you can look it up with data by name safely.
  • If you must parse the ID, extract the last segment dynamically, e.g. element(split("/", azurerm_network_interface.main.ip_configuration[0].public_ip_address_id), length(split("/", azurerm_network_interface.main.ip_configuration[0].public_ip_address_id)) - 1) to get the final element instead of hardcoding index 8.
    Also ensure the data block is only evaluated when the public_ip_address_id is present (see previous comment).

}
46 changes: 46 additions & 0 deletions modules/compute/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
variable "resource_group_name" {
description = "Name of the resource group"
type = string
}
Comment on lines +1 to +4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable resource_group_name (used to name the RG) is declared here. The compute module should ideally expose only compute-specific inputs. Per the checklist the compute module should accept vm_name, vm_size, ssh_key_public, subnet_id, public_ip_id, nsg_id, and script_url. Remove resource_group_name from this module unless you have a concrete reason to keep it (or document why). See checklist: modules/compute/variables.tf should expose only compute-relevant inputs.


variable "location" {
description = "Azure region for resources"
type = string
}
Comment on lines +6 to +9

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The location variable is declared here. Location is usually provided at the root and passed into modules only when strictly required. The checklist expects the compute module to focus on compute inputs; consider removing location from the module interface and sourcing it from the root unless you need it inside the module for resource creation (if you keep it, that's fine but explain why).


variable "vm_name" {
description = "Name of the virtual machine"
type = string
}

variable "vm_size" {
description = "Size of the virtual machine"
type = string
}

variable "ssh_key_public" {
description = "Public SSH key for the virtual machine"
type = string
sensitive = true
}
Comment on lines +21 to +25

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ssh_key_public is declared and marked sensitive = true. It's fine to mark secrets as sensitive, although a public SSH key normally isn't secret. More importantly, ensure the compute module uses this value when configuring the VM SSH key and that the VM's SSH key resource/name matches the checklist requirement (the task expects the SSH key used to authenticate the VM to be named linuxboxsshkey on the VM or at least referenced accordingly in your VM resource).


variable "subnet_id" {
description = "ID of the subnet to connect the VM to"
type = string
}
Comment on lines +27 to +30

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subnet_id is present and typed as string — this is correct. Ensure the compute module uses this to create the NIC named ${var.vm_name}-nic attached to this subnet (checklist requires that NIC name).


variable "public_ip_id" {
description = "ID of the public IP address to associate with the VM"
type = string
}
Comment on lines +32 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public_ip_id is present and typed as string — this is correct. Make sure the compute module associates the NIC (or VM) with this Public IP so the VM is reachable externally (checklist: VM must be accessible via public IP/DNS).


# Added variable for the Network Security Group ID.
variable "nsg_id" {
description = "ID of the Network Security Group to associate with the NIC"
type = string
}

variable "script_url" {
description = "URL of the script to execute on the VM"
type = string
}
Comment on lines +43 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The module accepts script_url which is required so the Custom Script Extension can download and run install-app.sh. Confirm that the storage module provides a script_url that points specifically to the install-app.sh blob, and that the compute module uses it in the VM extension to execute the script on provisioning (checklist: VM Extension must execute install-app.sh).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing required variable: add variable "nsg_id" { description = "ID of the Network Security Group to associate with the NIC" type = string }. The compute module must accept nsg_id so it can associate the NIC with the defaultnsg NSG created by the network module (this was flagged as a HIGH-priority checklist item). Add this variable (e.g., after public_ip_id or script_url) and ensure the module uses it when creating the NIC.

59 changes: 59 additions & 0 deletions modules/network/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
resource "azurerm_virtual_network" "vnet" {
name = var.virtual_network_name
location = var.location
resource_group_name = var.resource_group_name
address_space = var.vnet_address_prefix

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The azurerm_virtual_network address_space attribute expects a list of CIDR strings (list(string)). Ensure var.vnet_address_prefix is declared as list(string) and that you pass a list like ["10.0.0.0/16"] so Terraform/azurerm accepts it. This ties to the checklist requirement that the VNet uses 10.0.0.0/16.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

address_space = var.vnet_address_prefix — This is correct because the network module declares vnet_address_prefix as list(string) in modules/network/variables.tf. Make sure the root module passes the variable as a list (without wrapping it in an extra []). The root currently calls vnet_address_prefix = [var.vnet_address_prefix], which would create a nested list and cause a type error; pass vnet_address_prefix = var.vnet_address_prefix from root instead .

}

resource "azurerm_subnet" "subnet" {
name = var.subnet_name
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = var.subnet_address_prefix

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The azurerm_subnet address_prefixes attribute expects a list of CIDR strings. Make sure var.subnet_address_prefix is list(string) and contains ["10.0.0.0/24"] to satisfy the checklist requirement that the subnet uses 10.0.0.0/24.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

address_prefixes = var.subnet_address_prefix — same guidance as above: the subnet variable is defined as list(string) in the module's variables, so ensure the root passes it directly (not wrapped in another list). If the root wraps it you will get a nested-list type mismatch at plan time .

}

resource "azurerm_network_security_group" "nsg" {
name = var.network_security_group_name

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NSG name is taken from var.network_security_group_name. The checklist requires the NSG name to be the literal defaultnsg. Verify the variable default (in the module or root variables) is set to defaultnsg, otherwise the created name will not meet the requirement.

location = var.location
resource_group_name = var.resource_group_name
Comment on lines +15 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Network Security Group: you defined inbound rules for SSH and HTTP which make the VM reachable — good. Note that the module does not attach the NSG to the subnet here; that’s acceptable because the compute module associates the NSG to the NIC via azurerm_network_interface_security_group_association (the compute module expects module.network.nsg_id). Ensure modules/network/outputs.tf exports nsg_id (it does) and that the compute module consumes it exactly as named (verify wiring in root main.tf) .


security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
security_rule {
name = "HTTP"
priority = 1002
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}

resource "azurerm_public_ip" "pip" {
name = var.public_ip_address_name

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Public IP name is set from var.public_ip_address_name. The task requires the Public IP name be linuxboxpip (literal). Ensure the variable default equals linuxboxpip so the resource name matches the checklist.

location = var.location
resource_group_name = var.resource_group_name
allocation_method = "Dynamic"
domain_name_label = "${var.dns_label}${random_integer.r.result}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You correctly set allocation_method = "Dynamic" and you construct domain_name_label by concatenating var.dns_label with a random integer. The checklist requires the DNS label to start with the literal matetask and include a random number. Make sure var.dns_label default is matetask (literal). Also validate the final label meets Azure DNS naming rules (lowercase, length 3-63).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

domain_name_label = "${var.dns_label}${random_integer.r.result}" — using a random suffix here satisfies the DNS-label-with-randomness requirement. However, this module uses the random provider (resource random_integer). Ensure the root required_providers includes random (or document that the root must declare it). Without the provider available you may get initialization warnings or unexpected behavior. Adding random to the root required_providers block is the usual approach.


tags = {
environment = "dev"
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The root and compute module expect outputs like subnet_id, public_ip_id, and nsg_id from this module. Confirm modules/network/outputs.tf exports those exact output names and that they reference azurerm_subnet.subnet.id, azurerm_public_ip.pip.id, and azurerm_network_security_group.nsg.id respectively — otherwise the compute module will not receive the IDs it needs (checklist: wiring between modules).


resource "random_integer" "r" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You created random_integer.r to append a suffix. That is fine — just confirm the min/max values produce a suffix length that keeps domain_name_label within Azure limits when combined with matetask and any other characters.

min = 10000
max = 99999
}
Comment on lines +56 to +59

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resource "random_integer" "r" { min = 10000 max = 99999 } — this produces a 5-digit suffix which is fine. Declaring the random resource after the public IP reference is acceptable (Terraform resolves cross-resource references), so this placement is OK if you prefer it here.

29 changes: 29 additions & 0 deletions modules/network/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# The subnet ID.
output "subnet_id" {
description = "The ID of the subnet."
value = azurerm_subnet.subnet.id

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This output references azurerm_subnet.subnet. Confirm that modules/network/main.tf defines the subnet resource with the local name subnet (for example resource "azurerm_subnet" "subnet" { ... }). If the subnet resource is named differently the output will fail — either rename the resource or update this output to match the actual resource name.

}

# The Public IP Address ID. Required for NIC association.
output "public_ip_id" {
description = "The ID of the Public IP Address."
value = azurerm_public_ip.pip.id
Comment on lines +8 to +10

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good — public_ip_id is present (this was a HIGH-priority fix). Ensure modules/network/main.tf defines the public IP as resource "azurerm_public_ip" "pip" { ... } and configures allocation_method = "Dynamic" and a DNS label that appends a random suffix (e.g. using random_integer or random_id) so the pip.id value exists and can be consumed by the NIC/compute module.

}

# The Network Security Group ID. Required for NIC association.
output "nsg_id" {
description = "The ID of the Network Security Group."
value = azurerm_network_security_group.nsg.id
Comment on lines +14 to +16

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This output uses azurerm_network_security_group.nsg.id. Ensure the network module defines the NSG with the local name nsg (resource "azurerm_network_security_group" "nsg" { ... }) and that the NSG contains inbound rules for SSH (port 22) and the application port (e.g. port 80) so the VM is reachable over the internet once associated with the NIC.

}

# The Public IP address of the Linux VM.
output "public_ip_address" {
description = "The Public IP Address of the Linux VM."
value = azurerm_public_ip.pip.ip_address
Comment on lines +20 to +22

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compute/root configuration expects module.network.public_ip_id (resource id) but this file only exports the IP address and FQDN. Add an output named public_ip_id with the value azurerm_public_ip.pip.id so the compute module can receive the Public IP resource id and attach the NIC. Without this, the NIC/VM cannot be associated with the Public IP (checklist: compute must receive public_ip_id).

}

# The FQDN of the Public IP Address.
output "public_ip_fqdn" {
description = "The FQDN of the Public IP Address."
value = azurerm_public_ip.pip.fqdn
Comment on lines +26 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public_ip_fqdn returning azurerm_public_ip.pip.fqdn is useful for accessing the app in a browser, but it does not replace the need for the Public IP resource id. Ensure you keep the FQDN output for verification but also add the public_ip_id output. Also verify that the resource name azurerm_public_ip.pip exactly matches the resource defined in modules/network/main.tf so this output references a real resource.

Comment on lines +20 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public_ip_address and public_ip_fqdn rely on attributes from azurerm_public_ip.pip. Remember that fqdn is only populated when a dns_label is set on the public IP. Verify the public IP resource sets the DNS label (and uses randomness appended to matetask) so public_ip_fqdn is valid and the FQDN can be returned here.

}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If modules/network/main.tf is missing (or defines different resource local names), these outputs will break. Double-check that the network module exists and defines azurerm_subnet.subnet, azurerm_public_ip.pip, and azurerm_network_security_group.nsg exactly as referenced here. If names differ, update either the network resources or these outputs to match.

Loading
Loading