10.8 Terraform Outputs¶
Overview¶
Terraform outputs expose important information about the created infrastructure. This configuration provides three key outputs: resource group name, public IP address, and VM password.
Output Definitions¶
All outputs are defined in outputs.tf:
output "resource_group_name" {
value = azurerm_resource_group.example.name
}
output "public_ip_address" {
value = "http://${azurerm_public_ip.example.ip_address}"
}
output "vm_password" {
value = azurerm_linux_virtual_machine.example[0].admin_password
sensitive = true
}
Output Details¶
1. resource_group_name¶
Purpose: Displays the randomly generated resource group name
Example Output:
Why Useful: - Need the exact name for Azure CLI commands - Reference in other Terraform configurations - Documentation and tracking
Usage:
# Get the value
terraform output resource_group_name
# Use in Azure CLI
RG_NAME=$(terraform output -raw resource_group_name)
az resource list --resource-group $RG_NAME
2. public_ip_address¶
Purpose: Provides the HTTP URL to access the load-balanced web application
Example Output:
Why Useful: - Immediate access to the deployed application - Testing and verification - Sharing with team members
Usage:
# Get the URL
terraform output public_ip_address
# Open in browser (Linux)
xdg-open $(terraform output -raw public_ip_address)
# Test with curl
curl $(terraform output -raw public_ip_address)
String Interpolation:
- Automatically prependshttp:// to the IP address
- Makes it a clickable URL in terminal output
- Ready to paste into browser
3. vm_password¶
output "vm_password" {
value = azurerm_linux_virtual_machine.example[0].admin_password
sensitive = true
}
Purpose: Displays the admin password for VM access
Example Output:
Why Sensitive:
- sensitive = true prevents password from showing in normal output
- Protects credentials in logs and console output
- Must explicitly request to view
Accessing Sensitive Outputs:
# Shows <sensitive>
terraform output vm_password
# Shows actual password
terraform output -raw vm_password
# Save to variable
VM_PASSWORD=$(terraform output -raw vm_password)
echo $VM_PASSWORD
Array Index [0]:
example[0] and example[1]
Viewing Outputs¶
After Apply¶
Outputs are automatically displayed after terraform apply:
$ terraform apply
Apply complete! Resources: 15 added, 0 changed, 0 destroyed.
Outputs:
public_ip_address = "http://20.121.45.67"
resource_group_name = "rg-golden-panther"
vm_password = <sensitive>
View All Outputs¶
Output:
public_ip_address = "http://20.121.45.67"
resource_group_name = "rg-golden-panther"
vm_password = <sensitive>
View Specific Output¶
# With formatting
terraform output public_ip_address
# Raw value (no quotes)
terraform output -raw public_ip_address
View Sensitive Output¶
# Shows <sensitive>
terraform output vm_password
# Shows actual value
terraform output -raw vm_password
JSON Format¶
Output:
{
"public_ip_address": {
"sensitive": false,
"type": "string",
"value": "http://20.121.45.67"
},
"resource_group_name": {
"sensitive": false,
"type": "string",
"value": "rg-golden-panther"
},
"vm_password": {
"sensitive": true,
"type": "string",
"value": "Abc123!@#XyzDef456"
}
}
Using Outputs in Scripts¶
Bash Script Example¶
#!/bin/bash
# Get outputs
RG_NAME=$(terraform output -raw resource_group_name)
PUBLIC_IP=$(terraform output -raw public_ip_address)
VM_PASSWORD=$(terraform output -raw vm_password)
# Use in commands
echo "Resource Group: $RG_NAME"
echo "Testing endpoint: $PUBLIC_IP"
# Test the application
for i in {1..5}; do
echo "Request $i:"
curl $PUBLIC_IP
echo ""
done
# List resources
az resource list --resource-group $RG_NAME --output table
PowerShell Script Example¶
# Get outputs
$rgName = terraform output -raw resource_group_name
$publicIp = terraform output -raw public_ip_address
$vmPassword = terraform output -raw vm_password
# Use in commands
Write-Host "Resource Group: $rgName"
Write-Host "Public IP: $publicIp"
# Test the application
1..5 | ForEach-Object {
Write-Host "Request $_:"
Invoke-WebRequest -Uri $publicIp
}
Advanced Output Configurations¶
Multiple VM Passwords¶
Output passwords for all VMs:
output "vm_passwords" {
value = {
for idx, vm in azurerm_linux_virtual_machine.example :
vm.name => vm.admin_password
}
sensitive = true
}
Output:
VM Private IPs¶
output "vm_private_ips" {
value = [
for nic in azurerm_network_interface.example :
nic.private_ip_address
]
}
Output:
Complete Infrastructure Summary¶
output "infrastructure_summary" {
value = {
resource_group = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
vnet_name = azurerm_virtual_network.example.name
vnet_cidr = azurerm_virtual_network.example.address_space[0]
subnet_name = azurerm_subnet.example.name
subnet_cidr = azurerm_subnet.example.address_prefixes[0]
lb_name = azurerm_lb.example.name
public_ip = azurerm_public_ip.example.ip_address
vm_count = length(azurerm_linux_virtual_machine.example)
vm_names = [for vm in azurerm_linux_virtual_machine.example : vm.name]
}
}
Output:
infrastructure_summary = {
resource_group = "rg-golden-panther"
location = "eastus"
vnet_name = "test-vnet"
vnet_cidr = "10.0.0.0/16"
subnet_name = "test-subnet"
subnet_cidr = "10.0.1.0/24"
lb_name = "test-lb"
public_ip = "20.121.45.67"
vm_count = 2
vm_names = ["test-vm0", "test-vm1"]
}
Connection Information¶
output "connection_info" {
value = {
web_url = "http://${azurerm_public_ip.example.ip_address}"
username = azurerm_linux_virtual_machine.example[0].admin_username
vm_names = [for vm in azurerm_linux_virtual_machine.example : vm.name]
instructions = "Access the web application at the web_url. VMs are behind a load balancer and not directly accessible."
}
}
Load Balancer Details¶
output "load_balancer_info" {
value = {
name = azurerm_lb.example.name
frontend_ip = azurerm_public_ip.example.ip_address
backend_pool_name = azurerm_lb_backend_address_pool.example.name
health_probe_port = azurerm_lb_probe.example.port
lb_rule_frontend = azurerm_lb_rule.example_rule.frontend_port
lb_rule_backend = azurerm_lb_rule.example_rule.backend_port
}
}
Output Descriptions¶
Add descriptions to outputs:
output "resource_group_name" {
value = azurerm_resource_group.example.name
description = "The name of the resource group containing all infrastructure resources"
}
output "public_ip_address" {
value = "http://${azurerm_public_ip.example.ip_address}"
description = "The public URL to access the load-balanced web application"
}
output "vm_password" {
value = azurerm_linux_virtual_machine.example[0].admin_password
sensitive = true
description = "The admin password for VM access (use 'terraform output -raw vm_password' to view)"
}
Using Outputs in Other Modules¶
Root Module¶
module "infrastructure" {
source = "./modules/vnet-vm-lb"
resource_group_location = "eastus"
virtual_machine_size = "Standard_B2s"
}
output "app_url" {
value = module.infrastructure.public_ip_address
}
output "resource_group" {
value = module.infrastructure.resource_group_name
}
Chaining Modules¶
module "network" {
source = "./modules/network"
}
module "compute" {
source = "./modules/compute"
subnet_id = module.network.subnet_id
}
output "application_url" {
value = module.compute.public_ip_address
}
Saving Outputs to File¶
JSON File¶
Specific Output to File¶
terraform output -raw public_ip_address > public_ip.txt
terraform output -raw vm_password > .secrets/vm_password.txt
Environment File¶
cat > .env <<EOF
RESOURCE_GROUP=$(terraform output -raw resource_group_name)
PUBLIC_IP=$(terraform output -raw public_ip_address)
VM_PASSWORD=$(terraform output -raw vm_password)
EOF
Output Best Practices¶
- Provide Useful Information: Output what users need to access/manage resources
- Use Descriptions: Explain what each output represents
- Mark Sensitive Data: Use
sensitive = truefor passwords, keys - Format for Usability: Add
http://prefix, format URLs - Group Related Data: Use objects for related outputs
- Document Usage: Explain how to use sensitive outputs
- Avoid Over-Outputting: Only output necessary information
Common Use Cases¶
Testing After Deployment¶
#!/bin/bash
echo "Testing deployment..."
URL=$(terraform output -raw public_ip_address)
for i in {1..10}; do
echo "Request $i:"
curl -s $URL
echo ""
sleep 1
done
Automated Documentation¶
#!/bin/bash
cat > DEPLOYMENT.md <<EOF
# Deployment Information
## Resource Group
$(terraform output -raw resource_group_name)
## Application URL
$(terraform output -raw public_ip_address)
## Access Instructions
1. Open browser to: $(terraform output -raw public_ip_address)
2. You should see "Hello World from test-vm0" or "test-vm1"
## Admin Credentials
- Username: azureadmin
- Password: (stored in secrets manager)
## Deployed: $(date)
EOF
Integration with CI/CD¶
# GitHub Actions example
- name: Deploy Infrastructure
run: terraform apply -auto-approve
- name: Get Public IP
id: outputs
run: |
echo "public_ip=$(terraform output -raw public_ip_address)" >> $GITHUB_OUTPUT
- name: Test Deployment
run: |
curl ${{ steps.outputs.outputs.public_ip }}
Troubleshooting¶
Output Not Available¶
Error: "The output variable requested could not be found"
Solution: Ensure terraform apply has completed successfully
Sensitive Output Not Showing¶
Issue: Output shows <sensitive>
Solution: Use -raw flag:
Output Shows Old Value¶
Issue: Output doesn't reflect recent changes
Solution: Run terraform refresh or terraform apply
Next Steps¶
Proceed to 10.9-Deployment-Guide.md for step-by-step instructions on deploying this infrastructure.