From f5f28d82942ce47325848e4e43268e8d551e2e0b Mon Sep 17 00:00:00 2001
From: michalbil <92343355+michalbil@users.noreply.github.com>
Date: Tue, 1 Mar 2022 11:34:32 +0100
Subject: [PATCH] feat(vmseries)!: Basic config bootstrap support (#142)
* feat(vmseries)!: Add support for simple bootstrap
* feat(vmss)!: Add support for simple bootstrap in vmseries scaleset
---
examples/transit_vnet_common/README.md | 8 +--
examples/transit_vnet_common/example.tfvars | 2 +-
examples/transit_vnet_common/main.tf | 35 ++++++-----
examples/transit_vnet_common/versions.tf | 2 +-
examples/transit_vnet_dedicated/main.tf | 68 +++++++++++++--------
examples/vmseries_scaleset/main.tf | 34 ++++++++---
modules/vmseries/README.md | 4 +-
modules/vmseries/main.tf | 14 +----
modules/vmseries/variables.tf | 24 ++++----
modules/vmss/README.md | 5 +-
modules/vmss/main.tf | 12 +---
modules/vmss/variables.tf | 30 ++++-----
12 files changed, 125 insertions(+), 113 deletions(-)
diff --git a/examples/transit_vnet_common/README.md b/examples/transit_vnet_common/README.md
index 4213b574..00208a3a 100644
--- a/examples/transit_vnet_common/README.md
+++ b/examples/transit_vnet_common/README.md
@@ -17,7 +17,7 @@ $ terraform apply
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 0.13, < 2.0 |
-| [azurerm](#requirement\_azurerm) | = 2.64 |
+| [azurerm](#requirement\_azurerm) | = 2.97 |
| [random](#requirement\_random) | ~> 3.0 |
## Modules
@@ -34,9 +34,9 @@ $ terraform apply
| Name | Type |
|------|------|
-| [azurerm_network_security_rule.mgmt](https://registry.terraform.io/providers/hashicorp/azurerm/2.64/docs/resources/network_security_rule) | resource |
-| [azurerm_public_ip.public](https://registry.terraform.io/providers/hashicorp/azurerm/2.64/docs/resources/public_ip) | resource |
-| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/2.64/docs/resources/resource_group) | resource |
+| [azurerm_network_security_rule.mgmt](https://registry.terraform.io/providers/hashicorp/azurerm/2.97/docs/resources/network_security_rule) | resource |
+| [azurerm_public_ip.public](https://registry.terraform.io/providers/hashicorp/azurerm/2.97/docs/resources/public_ip) | resource |
+| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/2.97/docs/resources/resource_group) | resource |
| [random_password.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
## Inputs
diff --git a/examples/transit_vnet_common/example.tfvars b/examples/transit_vnet_common/example.tfvars
index 7772cdc4..8166b38c 100644
--- a/examples/transit_vnet_common/example.tfvars
+++ b/examples/transit_vnet_common/example.tfvars
@@ -65,7 +65,7 @@ vmseries = {
common_vmseries_version = "9.1.3"
common_vmseries_sku = "bundle1"
storage_account_name = "pantfstorage"
-storage_share_name = "ibbootstrapshare"
+storage_share_name = "bootstrapshare"
files = {
"files/authcodes" = "license/authcodes" # authcode is required only with common_vmseries_sku = "byol"
diff --git a/examples/transit_vnet_common/main.tf b/examples/transit_vnet_common/main.tf
index 0f39421c..e2f0230c 100644
--- a/examples/transit_vnet_common/main.tf
+++ b/examples/transit_vnet_common/main.tf
@@ -1,6 +1,6 @@
# Create the Resource Group.
resource "azurerm_resource_group" "this" {
- name = coalesce(var.resource_group_name, "${var.name_prefix}vmseries")
+ name = coalesce(var.resource_group_name, "${var.name_prefix}vmseries-transit-vnet-common")
location = var.location
}
@@ -115,19 +115,24 @@ module "common_vmseries" {
for_each = var.vmseries
- location = var.location
- resource_group_name = azurerm_resource_group.this.name
- name = "${var.name_prefix}${each.key}"
- avzone = try(each.value.avzone, 1)
- username = var.username
- password = coalesce(var.password, random_password.this.result)
- img_version = var.common_vmseries_version
- img_sku = var.common_vmseries_sku
- vm_size = var.common_vmseries_vm_size
- tags = var.common_vmseries_tags
- enable_zones = var.enable_zones
- bootstrap_storage_account = module.bootstrap.storage_account
- bootstrap_share_name = module.bootstrap.storage_share.name
+ location = var.location
+ resource_group_name = azurerm_resource_group.this.name
+ name = "${var.name_prefix}${each.key}"
+ avzone = try(each.value.avzone, 1)
+ username = var.username
+ password = coalesce(var.password, random_password.this.result)
+ img_version = var.common_vmseries_version
+ img_sku = var.common_vmseries_sku
+ vm_size = var.common_vmseries_vm_size
+ tags = var.common_vmseries_tags
+ enable_zones = var.enable_zones
+ bootstrap_options = join(",",
+ [
+ "storage-account=${module.bootstrap.storage_account.name}",
+ "access-key=${module.bootstrap.storage_account.primary_access_key}",
+ "file-share=${module.bootstrap.storage_share.name}",
+ "share-directory=None"
+ ])
interfaces = [
{
name = "${each.key}-mgmt"
@@ -153,5 +158,7 @@ module "common_vmseries" {
},
]
+ diagnostics_storage_uri = module.bootstrap.storage_account.primary_blob_endpoint
+
depends_on = [module.bootstrap]
}
diff --git a/examples/transit_vnet_common/versions.tf b/examples/transit_vnet_common/versions.tf
index 1c5f42c0..13881f48 100644
--- a/examples/transit_vnet_common/versions.tf
+++ b/examples/transit_vnet_common/versions.tf
@@ -3,7 +3,7 @@ terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
- version = "= 2.64"
+ version = "= 2.97"
}
random = {
source = "hashicorp/random"
diff --git a/examples/transit_vnet_dedicated/main.tf b/examples/transit_vnet_dedicated/main.tf
index 69574e0f..bac80016 100644
--- a/examples/transit_vnet_dedicated/main.tf
+++ b/examples/transit_vnet_dedicated/main.tf
@@ -1,6 +1,6 @@
# Create the Resource Group.
resource "azurerm_resource_group" "this" {
- name = coalesce(var.resource_group_name, "${var.name_prefix}vmseries")
+ name = coalesce(var.resource_group_name, "${var.name_prefix}vmseries-transit-vnet-dedicated")
location = var.location
}
@@ -124,19 +124,24 @@ module "inbound_vmseries" {
for_each = var.inbound_vmseries
- location = var.location
- resource_group_name = azurerm_resource_group.this.name
- name = "${var.name_prefix}${each.key}"
- avzone = try(each.value.avzone, 1)
- username = var.username
- password = coalesce(var.password, random_password.this.result)
- img_sku = var.common_vmseries_sku
- img_version = var.inbound_vmseries_version
- vm_size = var.inbound_vmseries_vm_size
- tags = var.inbound_vmseries_tags
- enable_zones = var.enable_zones
- bootstrap_storage_account = module.bootstrap.storage_account
- bootstrap_share_name = module.bootstrap.storage_share.name
+ location = var.location
+ resource_group_name = azurerm_resource_group.this.name
+ name = "${var.name_prefix}${each.key}"
+ avzone = try(each.value.avzone, 1)
+ username = var.username
+ password = coalesce(var.password, random_password.this.result)
+ img_sku = var.common_vmseries_sku
+ img_version = var.inbound_vmseries_version
+ vm_size = var.inbound_vmseries_vm_size
+ tags = var.inbound_vmseries_tags
+ enable_zones = var.enable_zones
+ bootstrap_options = join(",",
+ [
+ "storage-account=${module.bootstrap.storage_account.name}",
+ "access-key=${module.bootstrap.storage_account.primary_access_key}",
+ "file-share=${module.bootstrap.storage_share.name}",
+ "share-directory=None"
+ ])
interfaces = [
{
name = "${each.key}-mgmt"
@@ -160,6 +165,8 @@ module "inbound_vmseries" {
},
]
+ diagnostics_storage_uri = module.bootstrap.storage_account.primary_blob_endpoint
+
depends_on = [module.bootstrap]
}
@@ -171,19 +178,24 @@ module "outbound_vmseries" {
for_each = var.outbound_vmseries
- location = var.location
- resource_group_name = azurerm_resource_group.this.name
- name = "${var.name_prefix}${each.key}"
- avzone = try(each.value.avzone, 1)
- username = var.username
- password = coalesce(var.password, random_password.this.result)
- img_sku = var.common_vmseries_sku
- img_version = var.outbound_vmseries_version
- vm_size = var.outbound_vmseries_vm_size
- tags = var.outbound_vmseries_tags
- enable_zones = var.enable_zones
- bootstrap_storage_account = module.outbound_bootstrap.storage_account
- bootstrap_share_name = module.outbound_bootstrap.storage_share.name
+ location = var.location
+ resource_group_name = azurerm_resource_group.this.name
+ name = "${var.name_prefix}${each.key}"
+ avzone = try(each.value.avzone, 1)
+ username = var.username
+ password = coalesce(var.password, random_password.this.result)
+ img_sku = var.common_vmseries_sku
+ img_version = var.outbound_vmseries_version
+ vm_size = var.outbound_vmseries_vm_size
+ tags = var.outbound_vmseries_tags
+ enable_zones = var.enable_zones
+ bootstrap_options = join(",",
+ [
+ "storage-account=${module.outbound_bootstrap.storage_account.name}",
+ "access-key=${module.outbound_bootstrap.storage_account.primary_access_key}",
+ "file-share=${module.outbound_bootstrap.storage_share.name}",
+ "share-directory=None"
+ ])
interfaces = [
{
name = "${each.key}-mgmt"
@@ -208,5 +220,7 @@ module "outbound_vmseries" {
},
]
+ diagnostics_storage_uri = module.bootstrap.storage_account.primary_blob_endpoint
+
depends_on = [module.outbound_bootstrap]
}
diff --git a/examples/vmseries_scaleset/main.tf b/examples/vmseries_scaleset/main.tf
index af456ba7..479f1cac 100644
--- a/examples/vmseries_scaleset/main.tf
+++ b/examples/vmseries_scaleset/main.tf
@@ -240,11 +240,18 @@ module "inbound_scale_set" {
subnet_mgmt = { id = module.vnet.subnet_ids["management"] }
subnet_private = { id = module.vnet.subnet_ids["inbound_private"] }
subnet_public = { id = module.vnet.subnet_ids["inbound_public"] }
- bootstrap_storage_account = module.inbound_bootstrap.storage_account
- bootstrap_share_name = module.inbound_bootstrap.storage_share.name
- public_backend_pool_id = module.inbound_lb.backend_pool_id
- create_mgmt_pip = false
- create_public_pip = false
+ bootstrap_options = (join(",",
+ [
+ "storage-account=${module.inbound_bootstrap.storage_account.name}",
+ "access-key=${module.inbound_bootstrap.storage_account.primary_access_key}",
+ "file-share=${module.inbound_bootstrap.storage_share.name}",
+ "share-directory=None"
+ ]
+ ))
+ public_backend_pool_id = module.inbound_lb.backend_pool_id
+ create_mgmt_pip = false
+ create_public_pip = false
+ diagnostics_storage_uri = module.inbound_bootstrap.storage_account.primary_blob_endpoint
}
# Create the outbound scale set.
@@ -277,9 +284,16 @@ module "outbound_scale_set" {
subnet_mgmt = { id = module.vnet.subnet_ids["management"] }
subnet_private = { id = module.vnet.subnet_ids["outbound_private"] }
subnet_public = { id = module.vnet.subnet_ids["outbound_public"] }
- bootstrap_storage_account = module.outbound_bootstrap.storage_account
- bootstrap_share_name = module.outbound_bootstrap.storage_share.name
- private_backend_pool_id = module.outbound_lb.backend_pool_id
- create_mgmt_pip = false
- create_public_pip = false
+ bootstrap_options = (join(",",
+ [
+ "storage-account=${module.outbound_bootstrap.storage_account.name}",
+ "access-key=${module.outbound_bootstrap.storage_account.primary_access_key}",
+ "file-share=${module.outbound_bootstrap.storage_share.name}",
+ "share-directory=None"
+ ]
+ ))
+ private_backend_pool_id = module.outbound_lb.backend_pool_id
+ create_mgmt_pip = false
+ create_public_pip = false
+ diagnostics_storage_uri = module.outbound_bootstrap.storage_account.primary_blob_endpoint
}
diff --git a/modules/vmseries/README.md b/modules/vmseries/README.md
index 1cdd88dd..3a161b1e 100644
--- a/modules/vmseries/README.md
+++ b/modules/vmseries/README.md
@@ -76,9 +76,9 @@ No modules.
| [accelerated\_networking](#input\_accelerated\_networking) | Enable Azure accelerated networking (SR-IOV) for all network interfaces except the primary one (it is the PAN-OS management interface, which [does not support](https://docs.paloaltonetworks.com/pan-os/9-0/pan-os-new-features/virtualization-features/support-for-azure-accelerated-networking-sriov) acceleration). | `bool` | `true` | no |
| [avset\_id](#input\_avset\_id) | The identifier of the Availability Set to use. When using this variable, set `avzone = null`. | `string` | `null` | no |
| [avzone](#input\_avzone) | The availability zone to use, for example "1", "2", "3". Ignored if `enable_zones` is false. Conflicts with `avset_id`, in which case use `avzone = null`. | `string` | `"1"` | no |
-| [bootstrap\_share\_name](#input\_bootstrap\_share\_name) | Azure File Share holding the bootstrap data. Should reside on `bootstrap_storage_account`. Bootstrapping is omitted if `bootstrap_share_name` is left at null. | `string` | `null` | no |
-| [bootstrap\_storage\_account](#input\_bootstrap\_storage\_account) | Existing storage account object for bootstrapping and for holding small-sized boot diagnostics. Usually the object is passed from a bootstrap module's output. | `any` | `null` | no |
+| [bootstrap\_options](#input\_bootstrap\_options) | Bootstrap options to pass to VM-Series instance. | `string` | `""` | no |
| [custom\_image\_id](#input\_custom\_image\_id) | Absolute ID of your own Custom Image to be used for creating new VM-Series. If set, the `username`, `password`, `img_version`, `img_publisher`, `img_offer`, `img_sku` inputs are all ignored (these are used only for published images, not custom ones). The Custom Image is expected to contain PAN-OS software. | `string` | `null` | no |
+| [diagnostics\_storage\_uri](#input\_diagnostics\_storage\_uri) | The storage account's blob endpoint to hold diagnostic files. | `string` | `null` | no |
| [enable\_plan](#input\_enable\_plan) | Enable usage of the Offer/Plan on Azure Marketplace. Even plan sku "byol", which means "bring your own license", still requires accepting on the Marketplace (as of 2021). Can be set to `false` when using a custom image. | `bool` | `true` | no |
| [enable\_zones](#input\_enable\_zones) | If false, the input `avzone` is ignored and also all created Public IP addresses default to not to use Availability Zones (the `No-Zone` setting). It is intended for the regions that do not yet support Availability Zones. | `bool` | `true` | no |
| [identity\_ids](#input\_identity\_ids) | See the [provider documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine#identity_ids). | `list(string)` | `null` | no |
diff --git a/modules/vmseries/main.tf b/modules/vmseries/main.tf
index 7eee9acc..3deb2e3d 100644
--- a/modules/vmseries/main.tf
+++ b/modules/vmseries/main.tf
@@ -90,15 +90,7 @@ resource "azurerm_virtual_machine" "this" {
computer_name = var.name
admin_username = var.username
admin_password = var.password
- custom_data = var.bootstrap_share_name == null ? null : join(
- ",",
- [
- "storage-account=${var.bootstrap_storage_account.name}",
- "access-key=${var.bootstrap_storage_account.primary_access_key}",
- "file-share=${var.bootstrap_share_name}",
- "share-directory=None"
- ]
- )
+ custom_data = var.bootstrap_options
}
os_profile_linux_config {
@@ -108,11 +100,11 @@ resource "azurerm_virtual_machine" "this" {
# After converting to azurerm_linux_virtual_machine, an empty block boot_diagnostics {} will use managed storage. Want.
# 2.36 in required_providers per https://github.com/terraform-providers/terraform-provider-azurerm/pull/8917
dynamic "boot_diagnostics" {
- for_each = var.bootstrap_storage_account != null ? ["one"] : []
+ for_each = var.diagnostics_storage_uri != null ? ["one"] : []
content {
enabled = true
- storage_uri = var.bootstrap_storage_account.primary_blob_endpoint
+ storage_uri = var.diagnostics_storage_uri
}
}
diff --git a/modules/vmseries/variables.tf b/modules/vmseries/variables.tf
index 6e673e65..2f550219 100644
--- a/modules/vmseries/variables.tf
+++ b/modules/vmseries/variables.tf
@@ -58,18 +58,6 @@ variable "interfaces" {
EOF
}
-variable "bootstrap_storage_account" {
- description = "Existing storage account object for bootstrapping and for holding small-sized boot diagnostics. Usually the object is passed from a bootstrap module's output."
- default = null
- type = any
-}
-
-variable "bootstrap_share_name" {
- description = "Azure File Share holding the bootstrap data. Should reside on `bootstrap_storage_account`. Bootstrapping is omitted if `bootstrap_share_name` is left at null."
- default = null
- type = string
-}
-
variable "username" {
description = "Initial administrative username to use for VM-Series. Mind the [Azure-imposed restrictions](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/faq#what-are-the-username-requirements-when-creating-a-vm)."
type = string
@@ -173,3 +161,15 @@ variable "enable_zones" {
default = true
type = bool
}
+
+variable "bootstrap_options" {
+ description = "Bootstrap options to pass to VM-Series instance."
+ default = ""
+ type = string
+}
+
+variable "diagnostics_storage_uri" {
+ description = "The storage account's blob endpoint to hold diagnostic files."
+ default = null
+ type = string
+}
\ No newline at end of file
diff --git a/modules/vmss/README.md b/modules/vmss/README.md
index 3319800d..6f241e15 100644
--- a/modules/vmss/README.md
+++ b/modules/vmss/README.md
@@ -52,13 +52,12 @@ No modules.
| [autoscale\_metrics](#input\_autoscale\_metrics) | Map of objects, where each key is the metric name to be used for autoscaling.
Each value of the map has the attributes `scaleout_threshold` and `scalein_threshold`, which cause the instance count to grow by 1 when metrics are greater or equal, or decrease by 1 when lower or equal, respectively.
The thresholds are applied to results of metrics' aggregation over a time window.
Example:
{Other possible metrics include panSessionActive, panSessionThroughputKbps, panSessionThroughputPps, DataPlanePacketBufferUtilization. | `map` |
"DataPlaneCPUUtilizationPct" = {
scaleout_threshold = 80
scalein_threshold = 20
}
"panSessionUtilization" = {
scaleout_threshold = 80
scalein_threshold = 20
}
}
{| no | | [autoscale\_notification\_emails](#input\_autoscale\_notification\_emails) | List of email addresses to notify about autoscaling events. | `list(string)` | `[]` | no | | [autoscale\_webhooks\_uris](#input\_autoscale\_webhooks\_uris) | Map where each key is an arbitrary identifier and each value is a webhook URI. The URIs receive autoscaling events. | `map(string)` | `{}` | no | -| [boot\_diagnostics\_storage\_account\_uri](#input\_boot\_diagnostics\_storage\_account\_uri) | n/a | `string` | `null` | no | -| [bootstrap\_share\_name](#input\_bootstrap\_share\_name) | File share for bootstrap config | `string` | n/a | yes | -| [bootstrap\_storage\_account](#input\_bootstrap\_storage\_account) | Storage account setup for bootstrapping |
"DataPlaneCPUUtilizationPct": {
"scalein_threshold": 20,
"scaleout_threshold": 80
},
"panSessionUtilization": {
"scalein_threshold": 20,
"scaleout_threshold": 80
}
}
object({| n/a | yes | +| [bootstrap\_options](#input\_bootstrap\_options) | Bootstrap options to pass to VM-Series instance. | `string` | `""` | no | | [create\_mgmt\_pip](#input\_create\_mgmt\_pip) | n/a | `bool` | `true` | no | | [create\_public\_interface](#input\_create\_public\_interface) | If true, create the third network interface for virtual machines. | `bool` | `true` | no | | [create\_public\_pip](#input\_create\_public\_pip) | n/a | `bool` | `true` | no | | [custom\_image\_id](#input\_custom\_image\_id) | Absolute ID of your own Custom Image to be used for creating new VM-Series. The Custom Image is expected to contain PAN-OS software. | `string` | `null` | no | +| [diagnostics\_storage\_uri](#input\_diagnostics\_storage\_uri) | The storage account's blob endpoint to hold diagnostic files. | `any` | `null` | no | | [disable\_password\_authentication](#input\_disable\_password\_authentication) | If true, disables password-based authentication on VM-Series instances. | `bool` | `false` | no | | [disk\_encryption\_set\_id](#input\_disk\_encryption\_set\_id) | n/a | `string` | `null` | no | | [enable\_plan](#input\_enable\_plan) | Enable usage of the Offer/Plan on Azure Marketplace. Even plan sku "byol", which means "bring your own license", still requires accepting on the Marketplace (as of 2021). Can be set to `false` when using a custom image. | `bool` | `true` | no | diff --git a/modules/vmss/main.tf b/modules/vmss/main.tf index 5800c067..2614d2b2 100644 --- a/modules/vmss/main.tf +++ b/modules/vmss/main.tf @@ -55,15 +55,7 @@ resource "azurerm_linux_virtual_machine_scale_set" "this" { # "Automatic repairs not supported for this Virtual Machine Scale Set because a health probe or health extension was not provided." upgrade_mode = "Manual" - custom_data = base64encode(join( - ",", - [ - "storage-account=${var.bootstrap_storage_account.name}", - "access-key=${var.bootstrap_storage_account.primary_access_key}", - "file-share=${var.bootstrap_share_name}", - "share-directory=None" - ] - )) + custom_data = base64encode(var.bootstrap_options) network_interface { name = "${var.name_prefix}${var.name_mgmt_nic_profile}" @@ -132,7 +124,7 @@ resource "azurerm_linux_virtual_machine_scale_set" "this" { } boot_diagnostics { - storage_account_uri = var.boot_diagnostics_storage_account_uri + storage_account_uri = var.diagnostics_storage_uri } identity { diff --git a/modules/vmss/variables.tf b/modules/vmss/variables.tf index d869681d..ec4e2caf 100644 --- a/modules/vmss/variables.tf +++ b/modules/vmss/variables.tf @@ -54,19 +54,6 @@ variable "public_pip_domain_name_label" { type = string } -variable "bootstrap_storage_account" { - description = "Storage account setup for bootstrapping" - type = object({ - name = string - primary_access_key = string - }) -} - -variable "bootstrap_share_name" { - description = "File share for bootstrap config" - type = string -} - variable "username" { description = "Initial administrative username to use for VM-Series." default = "panadmin" @@ -144,11 +131,6 @@ variable "storage_account_type" { type = string } -variable "boot_diagnostics_storage_account_uri" { - default = null - type = string -} - variable "disk_encryption_set_id" { default = null type = string @@ -400,3 +382,15 @@ variable "name_private_nic_profile" { variable "name_private_nic_ip" { default = "nic-fw-private" } + +variable "bootstrap_options" { + description = "Bootstrap options to pass to VM-Series instance." + default = "" + type = string +} + +variable "diagnostics_storage_uri" { + description = "The storage account's blob endpoint to hold diagnostic files." + default = null + type = any +} \ No newline at end of file
name = string
primary_access_key = string
})