Packer and Linux: Part 2

Published: Sep 15, 2021 by Isaac Johnson

In our last article we covered getting started with Packer, Linux and Azure. Now that we have the fundamentals, let’s work out some more useful examples leveraging packer.

In this article we will cover integrating packer and terraform, using a VHD image on Hyper-V locally and lastly how to base on image on another image for chaining packer builds.

note: if you want to look at the code directly while working through the blog, you can get it from github

Setup Terraform

First we need to install Terraform if we have not done so already.

$ terraform
terraform: command not found

$ sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl
[sudo] password for builder:
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Hit:2 http://archive.ubuntu.com/ubuntu focal InRelease
Hit:3 https://apt.releases.hashicorp.com focal InRelease
Get:4 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:5 http://security.ubuntu.com/ubuntu focal-security/main amd64 Packages [830 kB]
Hit:6 https://packages.microsoft.com/repos/azure-cli focal InRelease
Hit:7 https://packages.microsoft.com/repos/microsoft-ubuntu-focal-prod focal InRelease
Hit:8 https://packages.microsoft.com/ubuntu/21.04/prod hirsute InRelease
Get:9 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
Get:10 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [1175 kB]
Get:11 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages [853 kB]
Fetched 3186 kB in 2s (1858 kB/s)
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
curl is already the newest version (7.68.0-1ubuntu2.6).
gnupg is already the newest version (2.2.19-3ubuntu2.1).
software-properties-common is already the newest version (0.98.9.5).
0 upgraded, 0 newly installed, 0 to remove and 10 not upgraded.

$ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
OK

$ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
Hit:1 https://apt.releases.hashicorp.com focal InRelease
Hit:2 http://security.ubuntu.com/ubuntu focal-security InRelease
Hit:3 http://archive.ubuntu.com/ubuntu focal InRelease
Hit:4 https://packages.microsoft.com/repos/azure-cli focal InRelease
Hit:5 http://archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:6 https://packages.microsoft.com/repos/microsoft-ubuntu-focal-prod focal InRelease
Hit:7 https://packages.microsoft.com/ubuntu/21.04/prod hirsute InRelease
Hit:8 http://archive.ubuntu.com/ubuntu focal-backports InRelease
Reading package lists... Done

$ sudo apt-get update && sudo apt-get install terraform
Hit:1 http://security.ubuntu.com/ubuntu focal-security InRelease
Hit:2 https://apt.releases.hashicorp.com focal InRelease
Hit:3 http://archive.ubuntu.com/ubuntu focal InRelease
Hit:4 http://archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:5 https://packages.microsoft.com/repos/azure-cli focal InRelease
Hit:6 http://archive.ubuntu.com/ubuntu focal-backports InRelease
Hit:7 https://packages.microsoft.com/repos/microsoft-ubuntu-focal-prod focal InRelease
Hit:8 https://packages.microsoft.com/ubuntu/21.04/prod hirsute InRelease
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  terraform
0 upgraded, 1 newly installed, 0 to remove and 10 not upgraded.
Need to get 32.7 MB of archives.
After this operation, 79.4 MB of additional disk space will be used.
Get:1 https://apt.releases.hashicorp.com focal/main amd64 terraform amd64 1.0.6 [32.7 MB]
Fetched 32.7 MB in 1s (50.3 MB/s)
Selecting previously unselected package terraform.
(Reading database ... 133607 files and directories currently installed.)
Preparing to unpack .../terraform_1.0.6_amd64.deb ...
Unpacking terraform (1.0.6) ...
Setting up terraform (1.0.6) ...

$ terraform version
Terraform v1.0.6
on linux_amd64

Basic Terraform HCL for Resource Group and Storage

For our Packer work, instead of using the AZ CLI, we’ll use a terraform block to create a resource group and storage account we can use for our managed images.

builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo02$ cat packer-infra.tf
# Configure the Azure provider
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 2.65"
    }
  }

  required_version = ">= 0.14.9"
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "packerrg" {
  name     = "packerlinux02"
  location = "East US"
}

resource "azurerm_storage_account" "packersa" {
  name                     = "idjpackersa02"
  resource_group_name      = azurerm_resource_group.packerrg.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  tags = {
    environment = "development"
  }
}

Next we setup the folder as a terraform root with terraform init

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/azurerm versions matching "~> 2.65"...
- Installing hashicorp/azurerm v2.75.0...
- Installed hashicorp/azurerm v2.75.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Validation

Next we can use validate to see if we made mistakes:

$ terraform validate
╷
│ Error: Reference to undeclared resource
│
│   on packer-infra.tf line 25, in resource "azurerm_storage_account" "packersa":
│   25:   location                 = azurerm_resource_group.example.location
│
│ A managed resource "azurerm_resource_group" "example" has not been declared in the root module.
╵

Ah-hah! we left an ‘example’ in the code on line 25:

location                 = azurerm_resource_group.example.location

Let’s correct that:

# Configure the Azure provider
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 2.65"
    }
  }

  required_version = ">= 0.14.9"
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "packerrg" {
  name     = "packerlinux02"
  location = "East US"
}

resource "azurerm_storage_account" "packersa" {
  name                     = "idjpackersa02"
  resource_group_name      = azurerm_resource_group.packerrg.name
  location                 = azurerm_resource_group.packerrg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  tags = {
    environment = "development"
  }
}

Now validate should pass:

$ terraform validate
Success! The configuration is valid.

You can now use terraform apply but i still like the older pattern of ‘plan’ then ‘apply.

By using “plan” first, i can see what it plans to do knowing it won’t go apply it just yet.

$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.packerrg will be created
  + resource "azurerm_resource_group" "packerrg" {
      + id       = (known after apply)
      + location = "eastus"
      + name     = "packerlinux02"
    }

  # azurerm_storage_account.packersa will be created
  + resource "azurerm_storage_account" "packersa" {
      + access_tier                      = (known after apply)
      + account_kind                     = "StorageV2"
      + account_replication_type         = "LRS"
      + account_tier                     = "Standard"
      + allow_blob_public_access         = false
      + enable_https_traffic_only        = true
      + id                               = (known after apply)
      + is_hns_enabled                   = false
      + large_file_share_enabled         = (known after apply)
      + location                         = "eastus"
      + min_tls_version                  = "TLS1_0"
      + name                             = "idjpackersa02"
      + nfsv3_enabled                    = false
      + primary_access_key               = (sensitive value)
      + primary_blob_connection_string   = (sensitive value)
      + primary_blob_endpoint            = (known after apply)
      + primary_blob_host                = (known after apply)
      + primary_connection_string        = (sensitive value)
      + primary_dfs_endpoint             = (known after apply)
      + primary_dfs_host                 = (known after apply)
      + primary_file_endpoint            = (known after apply)
      + primary_file_host                = (known after apply)
      + primary_location                 = (known after apply)
      + primary_queue_endpoint           = (known after apply)
      + primary_queue_host               = (known after apply)
      + primary_table_endpoint           = (known after apply)
      + primary_table_host               = (known after apply)
      + primary_web_endpoint             = (known after apply)
      + primary_web_host                 = (known after apply)
      + resource_group_name              = "packerlinux02"
      + secondary_access_key             = (sensitive value)
      + secondary_blob_connection_string = (sensitive value)
      + secondary_blob_endpoint          = (known after apply)
      + secondary_blob_host              = (known after apply)
      + secondary_connection_string      = (sensitive value)
      + secondary_dfs_endpoint           = (known after apply)
      + secondary_dfs_host               = (known after apply)
      + secondary_file_endpoint          = (known after apply)
      + secondary_file_host              = (known after apply)
      + secondary_location               = (known after apply)
      + secondary_queue_endpoint         = (known after apply)
      + secondary_queue_host             = (known after apply)
      + secondary_table_endpoint         = (known after apply)
      + secondary_table_host             = (known after apply)
      + secondary_web_endpoint           = (known after apply)
      + secondary_web_host               = (known after apply)
      + shared_access_key_enabled        = true
      + tags                             = {
          + "environment" = "development"
        }

      + blob_properties {
          + change_feed_enabled      = (known after apply)
          + default_service_version  = (known after apply)
          + last_access_time_enabled = (known after apply)
          + versioning_enabled       = (known after apply)

          + container_delete_retention_policy {
              + days = (known after apply)
            }

          + cors_rule {
              + allowed_headers    = (known after apply)
              + allowed_methods    = (known after apply)
              + allowed_origins    = (known after apply)
              + exposed_headers    = (known after apply)
              + max_age_in_seconds = (known after apply)
            }

          + delete_retention_policy {
              + days = (known after apply)
            }
        }

      + identity {
          + identity_ids = (known after apply)
          + principal_id = (known after apply)
          + tenant_id    = (known after apply)
          + type         = (known after apply)
        }

      + network_rules {
          + bypass                     = (known after apply)
          + default_action             = (known after apply)
          + ip_rules                   = (known after apply)
          + virtual_network_subnet_ids = (known after apply)

          + private_link_access {
              + endpoint_resource_id = (known after apply)
              + endpoint_tenant_id   = (known after apply)
            }
        }

      + queue_properties {
          + cors_rule {
              + allowed_headers    = (known after apply)
              + allowed_methods    = (known after apply)
              + allowed_origins    = (known after apply)
              + exposed_headers    = (known after apply)
              + max_age_in_seconds = (known after apply)
            }

          + hour_metrics {
              + enabled               = (known after apply)
              + include_apis          = (known after apply)
              + retention_policy_days = (known after apply)
              + version               = (known after apply)
            }

          + logging {
              + delete                = (known after apply)
              + read                  = (known after apply)
              + retention_policy_days = (known after apply)
              + version               = (known after apply)
              + write                 = (known after apply)
            }

          + minute_metrics {
              + enabled               = (known after apply)
              + include_apis          = (known after apply)
              + retention_policy_days = (known after apply)
              + version               = (known after apply)
            }
        }

      + routing {
          + choice                      = (known after apply)
          + publish_internet_endpoints  = (known after apply)
          + publish_microsoft_endpoints = (known after apply)
        }

      + share_properties {
          + cors_rule {
              + allowed_headers    = (known after apply)
              + allowed_methods    = (known after apply)
              + allowed_origins    = (known after apply)
              + exposed_headers    = (known after apply)
              + max_age_in_seconds = (known after apply)
            }

          + retention_policy {
              + days = (known after apply)
            }

          + smb {
              + authentication_types            = (known after apply)
              + channel_encryption_type         = (known after apply)
              + kerberos_ticket_encryption_type = (known after apply)
              + versions                        = (known after apply)
            }
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

This looks good, so let’s go ahead and apply it:

builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo02$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_resource_group.packerrg will be created
  + resource "azurerm_resource_group" "packerrg" {
      + id       = (known after apply)
      + location = "eastus"
      + name     = "packerlinux02"
    }

  # azurerm_storage_account.packersa will be created
  + resource "azurerm_storage_account" "packersa" {
      + access_tier                      = (known after apply)
      + account_kind                     = "StorageV2"
      + account_replication_type         = "LRS"
      + account_tier                     = "Standard"
      + allow_blob_public_access         = false
      + enable_https_traffic_only        = true
      + id                               = (known after apply)
      + is_hns_enabled                   = false
      + large_file_share_enabled         = (known after apply)
      + location                         = "eastus"
      + min_tls_version                  = "TLS1_0"
      + name                             = "idjpackersa02"
      + nfsv3_enabled                    = false
      + primary_access_key               = (sensitive value)
      + primary_blob_connection_string   = (sensitive value)
      + primary_blob_endpoint            = (known after apply)
      + primary_blob_host                = (known after apply)
      + primary_connection_string        = (sensitive value)
      + primary_dfs_endpoint             = (known after apply)
      + primary_dfs_host                 = (known after apply)
      + primary_file_endpoint            = (known after apply)
      + primary_file_host                = (known after apply)
      + primary_location                 = (known after apply)
      + primary_queue_endpoint           = (known after apply)
      + primary_queue_host               = (known after apply)
      + primary_table_endpoint           = (known after apply)
      + primary_table_host               = (known after apply)
      + primary_web_endpoint             = (known after apply)
      + primary_web_host                 = (known after apply)
      + resource_group_name              = "packerlinux02"
      + secondary_access_key             = (sensitive value)
      + secondary_blob_connection_string = (sensitive value)
      + secondary_blob_endpoint          = (known after apply)
      + secondary_blob_host              = (known after apply)
      + secondary_connection_string      = (sensitive value)
      + secondary_dfs_endpoint           = (known after apply)
      + secondary_dfs_host               = (known after apply)
      + secondary_file_endpoint          = (known after apply)
      + secondary_file_host              = (known after apply)
      + secondary_location               = (known after apply)
      + secondary_queue_endpoint         = (known after apply)
      + secondary_queue_host             = (known after apply)
      + secondary_table_endpoint         = (known after apply)
      + secondary_table_host             = (known after apply)
      + secondary_web_endpoint           = (known after apply)
      + secondary_web_host               = (known after apply)
      + shared_access_key_enabled        = true
      + tags                             = {
          + "environment" = "development"
        }

      + blob_properties {
          + change_feed_enabled      = (known after apply)
          + default_service_version  = (known after apply)
          + last_access_time_enabled = (known after apply)
          + versioning_enabled       = (known after apply)

          + container_delete_retention_policy {
              + days = (known after apply)
            }

          + cors_rule {
              + allowed_headers    = (known after apply)
              + allowed_methods    = (known after apply)
              + allowed_origins    = (known after apply)
              + exposed_headers    = (known after apply)
              + max_age_in_seconds = (known after apply)
            }

          + delete_retention_policy {
              + days = (known after apply)
            }
        }

      + identity {
          + identity_ids = (known after apply)
          + principal_id = (known after apply)
          + tenant_id    = (known after apply)
          + type         = (known after apply)
        }

      + network_rules {
          + bypass                     = (known after apply)
          + default_action             = (known after apply)
          + ip_rules                   = (known after apply)
          + virtual_network_subnet_ids = (known after apply)

          + private_link_access {
              + endpoint_resource_id = (known after apply)
              + endpoint_tenant_id   = (known after apply)
            }
        }

      + queue_properties {
          + cors_rule {
              + allowed_headers    = (known after apply)
              + allowed_methods    = (known after apply)
              + allowed_origins    = (known after apply)
              + exposed_headers    = (known after apply)
              + max_age_in_seconds = (known after apply)
            }

          + hour_metrics {
              + enabled               = (known after apply)
              + include_apis          = (known after apply)
              + retention_policy_days = (known after apply)
              + version               = (known after apply)
            }

          + logging {
              + delete                = (known after apply)
              + read                  = (known after apply)
              + retention_policy_days = (known after apply)
              + version               = (known after apply)
              + write                 = (known after apply)
            }

          + minute_metrics {
              + enabled               = (known after apply)
              + include_apis          = (known after apply)
              + retention_policy_days = (known after apply)
              + version               = (known after apply)
            }
        }

      + routing {
          + choice                      = (known after apply)
          + publish_internet_endpoints  = (known after apply)
          + publish_microsoft_endpoints = (known after apply)
        }

      + share_properties {
          + cors_rule {
              + allowed_headers    = (known after apply)
              + allowed_methods    = (known after apply)
              + allowed_origins    = (known after apply)
              + exposed_headers    = (known after apply)
              + max_age_in_seconds = (known after apply)
            }

          + retention_policy {
              + days = (known after apply)
            }

          + smb {
              + authentication_types            = (known after apply)
              + channel_encryption_type         = (known after apply)
              + kerberos_ticket_encryption_type = (known after apply)
              + versions                        = (known after apply)
            }
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

azurerm_resource_group.packerrg: Creating...
azurerm_resource_group.packerrg: Creation complete after 0s [id=/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02]
azurerm_storage_account.packersa: Creating...
azurerm_storage_account.packersa: Still creating... [10s elapsed]
azurerm_storage_account.packersa: Still creating... [20s elapsed]
azurerm_storage_account.packersa: Creation complete after 23s [id=/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Storage/storageAccounts/idjpackersa02]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Verification

In the Azure Portal, we can see the resources were created

/content/images/2021/09/packer-build2-01.png

If we want to output the key values we plan to use in packer, we can add an outputs section to our TF file:

output "packer_rg_name" {
  value = azurerm_resource_group.packerrg.name
}

output "packer_sa_name" {
  value = azurerm_storage_account.packersa.name
}

Then upon plan and apply we see the output:

...

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

packer_rg_name = "packerlinux02"
packer_sa_name = "idjpackersa02"

With them as outputs, we can easily get them again:

builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo02$ terraform output packer_rg_name
"packerlinux02"
builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo02$ terraform output packer_sa_name
"idjpackersa02"

Let’s say we want to use them as vars in packer. This is quite doable.

We’ll update the ubuntu-test.pkr.hcl to pull in settings from vars:


source "azure-arm" "my-example" {
  client_id = "${var.client_id}"
  client_secret = "${var.client_secret}"
  

  tenant_id= "${var.tenant_id}"
  subscription_id = "${var.subscription_id}"

  # VHD style
  # resource_group_name = "${var.myrg}"
  # storage_account = "${var.mysa}"
  # capture_container_name = "images"
  # capture_name_prefix = "packer"

  # Managed Image style
  managed_image_resource_group_name = "${var.myrg}"
  managed_image_name = "myPackerImage"

  os_type = "Linux"
  image_publisher = "Canonical"
  image_offer = "UbuntuServer"
  image_sku = "18.04-LTS"

  location = "East US"
  vm_size = "Standard_DS2_v2"

  azure_tags = {
    dept = "engineering"
  }
}

build {
  sources = ["sources.azure-arm.my-example"]
  
  provisioner "shell" {
    
    execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo {{ .Path }}"
    script          = "./setup-azcli.sh"
  }
}

# /usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync
# DEBIAN_FRONTEND=noninteractive && sudo apt-get upgrade -o Dpkg::Options::=--force-confold -o Dpkg::Options::=--force-confdef -y --allow-downgrades --allow-remove-essential --allow-change-held-packages

and then we will add some vars for myrg and mysa in the vars file

//  variables.pkr.hcl

// For those variables that you don't provide a default for, you must
// set them from the command line, a var-file, or the environment.

variable "client_secret" {
  type =  string
  default = "insertyoursecrethereforthesp"
  // Sensitive vars are hidden from output as of Packer v1.6.5
  sensitive = false
}

variable "client_id" {
  type =  string
  default = "d2390854-6661-451d-bee2-3bd9b42b14cc"
  // Sensitive vars are hidden from output as of Packer v1.6.5
  sensitive = false
}

variable "tenant_id" {
  type = string
  default = "0040020a-b598-444c-8f0b-92f82e1224c0"
}

variable "subscription_id" {
  type = string
  default = "944c019d-3e46-422b-b63a-86513f147562"
}

# required vars
variable "myrg" {
  type = string
}

variable "mysa" {
  type = string
}

Now we can invoke packer with the vars:

$ packer build -var "myrg=`terraform output -raw packer_rg_name`" -var "mysa=`terraform output -raw packer_sa_name`" .

In my case, i’ve fuddled the vars for subscription and tenant, we can override those too. First i’ll set some reusable env vars

$ export MYSUB=`az account list -o json | jq -r '.[] | select(.name=="Pay-As-You-Go") | .id' | tr -d '\n'`
$ export MYTENANT=`az account list -o json | jq -r '.[] | select(.name=="Pay-As-You-Go") | .tenantId' | tr -d '\n'`

I’ll also reset the SP (sppackertest) password and capture it

$ az ad sp create-for-rbac -n sppackertest --skip-assignment --output json > my_sp.json
WARNING: Found an existing application instance of "00433032-6780-4397-aad7-aac77964b0ad". We will patch it
WARNING: The output includes credentials that you must protect. Be sure that you do not include these credentials in your code or check the credentials into your source control. For more information, see https://aka.ms/azadsp-cli
WARNING: 'name' property in the output is deprecated and will be removed in the future. Use 'appId' instead.
$ export SP_PASS=`cat my_sp.json | jq -r .password`
$ export SP_ID=`cat my_sp.json | jq -r .appId`

so our full invokation is:

$ packer build -var "myrg=`terraform output -raw packer_rg_name`" -var "mysa=`terraform output -raw packer_sa_name`" -var "client_secret=$SP_PASS" -var "client_id=$SP_I
D" -var "tenant_id=$MYTENANT" -var "subscription_id=$MYSUB" .
azure-arm.my-example: output will be in this color.

==> azure-arm.my-example: Running builder ...
==> azure-arm.my-example: Getting tokens using client secret
==> azure-arm.my-example: Getting tokens using client secret
    azure-arm.my-example: Creating Azure Resource Manager (ARM) client ...
==> azure-arm.my-example: WARNING: Zone resiliency may not be supported in East US, checkout the docs at https://docs.microsoft.com/en-us/azure/availability-zones/
==> azure-arm.my-example: Creating resource group ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> Location          : 'East US'
==> azure-arm.my-example:  -> Tags              :
==> azure-arm.my-example:  ->> dept : engineering
==> azure-arm.my-example: Validating deployment template ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> DeploymentName    : 'pkrdpwgyajbups4'
==> azure-arm.my-example: Deploying deployment template ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> DeploymentName    : 'pkrdpwgyajbups4'
==> azure-arm.my-example:
==> azure-arm.my-example: Getting the VM's IP address ...
==> azure-arm.my-example:  -> ResourceGroupName   : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> PublicIPAddressName : 'pkripwgyajbups4'
==> azure-arm.my-example:  -> NicName             : 'pkrniwgyajbups4'
==> azure-arm.my-example:  -> Network Connection  : 'PublicEndpoint'
==> azure-arm.my-example:  -> IP Address          : '52.188.174.26'
==> azure-arm.my-example: Waiting for SSH to become available...
==> azure-arm.my-example: Connected to SSH!
==> azure-arm.my-example: Provisioning with shell script: ./setup-azcli.sh
    azure-arm.my-example: Get:1 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
    azure-arm.my-example: Hit:2 http://archive.ubuntu.com/ubuntu bionic InRelease
    azure-arm.my-example: Get:3 http://archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
    azure-arm.my-example: Get:4 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [1846 kB]
    azure-arm.my-example: Get:5 http://security.ubuntu.com/ubuntu bionic-security/main Translation-en [338 kB]
    azure-arm.my-example: Get:6 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [419 kB]
    azure-arm.my-example: Get:7 http://security.ubuntu.com/ubuntu bionic-security/restricted Translation-en [56.1 kB]
    azure-arm.my-example: Get:8 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [1137 kB]
    azure-arm.my-example: Get:9 http://security.ubuntu.com/ubuntu bionic-security/universe Translation-en [259 kB]
    azure-arm.my-example: Get:10 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [20.9 kB]
    azure-arm.my-example: Get:11 http://security.ubuntu.com/ubuntu bionic-security/multiverse Translation-en [4732 B]
    azure-arm.my-example: Get:12 http://archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
    azure-arm.my-example: Get:13 http://archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [8570 kB]
    azure-arm.my-example: Get:14 http://archive.ubuntu.com/ubuntu bionic/universe Translation-en [4941 kB]
    azure-arm.my-example: Get:15 http://archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [151 kB]
    azure-arm.my-example: Get:16 http://archive.ubuntu.com/ubuntu bionic/multiverse Translation-en [108 kB]
    azure-arm.my-example: Get:17 http://archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2192 kB]
    azure-arm.my-example: Get:18 http://archive.ubuntu.com/ubuntu bionic-updates/main Translation-en [430 kB]
    azure-arm.my-example: Get:19 http://archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [443 kB]
    azure-arm.my-example: Get:20 http://archive.ubuntu.com/ubuntu bionic-updates/restricted Translation-en [59.9 kB]
    azure-arm.my-example: Get:21 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [1748 kB]
    azure-arm.my-example: Get:22 http://archive.ubuntu.com/ubuntu bionic-updates/universe Translation-en [375 kB]
    azure-arm.my-example: Get:23 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 Packages [27.3 kB]
    azure-arm.my-example: Get:24 http://archive.ubuntu.com/ubuntu bionic-updates/multiverse Translation-en [6808 B]
    azure-arm.my-example: Get:25 http://archive.ubuntu.com/ubuntu bionic-backports/main amd64 Packages [10.0 kB]
    azure-arm.my-example: Get:26 http://archive.ubuntu.com/ubuntu bionic-backports/main Translation-en [4764 B]
    azure-arm.my-example: Get:27 http://archive.ubuntu.com/ubuntu bionic-backports/universe amd64 Packages [10.3 kB]
    azure-arm.my-example: Get:28 http://archive.ubuntu.com/ubuntu bionic-backports/universe Translation-en [4588 B]
    azure-arm.my-example: Fetched 23.4 MB in 5s (4855 kB/s)
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Building dependency tree...
    azure-arm.my-example: Reading state information...
    azure-arm.my-example: ca-certificates is already the newest version (20210119~18.04.1).
    azure-arm.my-example: ca-certificates set to manually installed.
    azure-arm.my-example: gnupg is already the newest version (2.2.4-1ubuntu1.4).
    azure-arm.my-example: gnupg set to manually installed.
    azure-arm.my-example: lsb-release is already the newest version (9.20170808ubuntu1).
    azure-arm.my-example: lsb-release set to manually installed.
    azure-arm.my-example: The following package was automatically installed and is no longer required:
    azure-arm.my-example:   linux-headers-4.15.0-151
    azure-arm.my-example: Use 'sudo apt autoremove' to remove it.
    azure-arm.my-example: The following additional packages will be installed:
    azure-arm.my-example:   libcurl4
    azure-arm.my-example: The following NEW packages will be installed:
    azure-arm.my-example:   apt-transport-https
    azure-arm.my-example: The following packages will be upgraded:
    azure-arm.my-example:   curl libcurl4
    azure-arm.my-example: 2 upgraded, 1 newly installed, 0 to remove and 26 not upgraded.
    azure-arm.my-example: Need to get 379 kB of archives.
    azure-arm.my-example: After this operation, 153 kB of additional disk space will be used.
    azure-arm.my-example: Get:1 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 apt-transport-https all 1.6.12ubuntu0.2 [1696 B]
    azure-arm.my-example: Get:2 http://security.ubuntu.com/ubuntu bionic-security/main amd64 curl amd64 7.58.0-2ubuntu3.14 [159 kB]
    azure-arm.my-example: Get:3 http://security.ubuntu.com/ubuntu bionic-security/main amd64 libcurl4 amd64 7.58.0-2ubuntu3.14 [219 kB]
    azure-arm.my-example: Fetched 379 kB in 0s (3973 kB/s)
    azure-arm.my-example: Selecting previously unselected package apt-transport-https.
    azure-arm.my-example: (Reading database ... 76951 files and directories currently installed.)
    azure-arm.my-example: Preparing to unpack .../apt-transport-https_1.6.12ubuntu0.2_all.deb ...
    azure-arm.my-example: Unpacking apt-transport-https (1.6.12ubuntu0.2) ...
    azure-arm.my-example: Preparing to unpack .../curl_7.58.0-2ubuntu3.14_amd64.deb ...
    azure-arm.my-example: Unpacking curl (7.58.0-2ubuntu3.14) over (7.58.0-2ubuntu3.13) ...
    azure-arm.my-example: Preparing to unpack .../libcurl4_7.58.0-2ubuntu3.14_amd64.deb ...
    azure-arm.my-example: Unpacking libcurl4:amd64 (7.58.0-2ubuntu3.14) over (7.58.0-2ubuntu3.13) ...
    azure-arm.my-example: Setting up apt-transport-https (1.6.12ubuntu0.2) ...
    azure-arm.my-example: Setting up libcurl4:amd64 (7.58.0-2ubuntu3.14) ...
    azure-arm.my-example: Setting up curl (7.58.0-2ubuntu3.14) ...
    azure-arm.my-example: Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
    azure-arm.my-example: Processing triggers for libc-bin (2.27-3ubuntu1.4) ...
==> azure-arm.my-example: gpg: WARNING: unsafe ownership on homedir '/home/packer/.gnupg'
    azure-arm.my-example: deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ bionic main
    azure-arm.my-example: Get:1 http://azure.archive.ubuntu.com/ubuntu bionic InRelease [242 kB]
    azure-arm.my-example: Get:2 http://azure.archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
    azure-arm.my-example: Get:3 http://azure.archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
    azure-arm.my-example: Hit:4 http://security.ubuntu.com/ubuntu bionic-security InRelease
    azure-arm.my-example: Get:5 http://azure.archive.ubuntu.com/ubuntu bionic/main amd64 Packages [1019 kB]
    azure-arm.my-example: Get:6 http://azure.archive.ubuntu.com/ubuntu bionic/main Translation-en [516 kB]
    azure-arm.my-example: Get:7 http://azure.archive.ubuntu.com/ubuntu bionic/restricted amd64 Packages [9184 B]
    azure-arm.my-example: Get:8 http://azure.archive.ubuntu.com/ubuntu bionic/restricted Translation-en [3584 B]
    azure-arm.my-example: Get:9 http://azure.archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [8570 kB]
    azure-arm.my-example: Get:10 https://packages.microsoft.com/repos/azure-cli bionic InRelease [3965 B]
    azure-arm.my-example: Get:11 http://azure.archive.ubuntu.com/ubuntu bionic/universe Translation-en [4941 kB]
    azure-arm.my-example: Get:12 http://azure.archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [151 kB]
    azure-arm.my-example: Get:13 http://azure.archive.ubuntu.com/ubuntu bionic/multiverse Translation-en [108 kB]
    azure-arm.my-example: Get:14 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2192 kB]
    azure-arm.my-example: Get:15 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main Translation-en [430 kB]
    azure-arm.my-example: Get:16 http://azure.archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [443 kB]
    azure-arm.my-example: Get:17 http://azure.archive.ubuntu.com/ubuntu bionic-updates/restricted Translation-en [59.9 kB]
    azure-arm.my-example: Get:18 http://azure.archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [1748 kB]
    azure-arm.my-example: Get:19 http://azure.archive.ubuntu.com/ubuntu bionic-updates/universe Translation-en [375 kB]
    azure-arm.my-example: Get:20 http://azure.archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 Packages [27.3 kB]
    azure-arm.my-example: Get:21 http://azure.archive.ubuntu.com/ubuntu bionic-updates/multiverse Translation-en [6808 B]
    azure-arm.my-example: Get:22 http://azure.archive.ubuntu.com/ubuntu bionic-backports/main amd64 Packages [10.0 kB]
    azure-arm.my-example: Get:23 http://azure.archive.ubuntu.com/ubuntu bionic-backports/main Translation-en [4764 B]
    azure-arm.my-example: Get:24 http://azure.archive.ubuntu.com/ubuntu bionic-backports/universe amd64 Packages [10.3 kB]
    azure-arm.my-example: Get:25 http://azure.archive.ubuntu.com/ubuntu bionic-backports/universe Translation-en [4588 B]
    azure-arm.my-example: Get:26 https://packages.microsoft.com/repos/azure-cli bionic/main amd64 Packages [15.0 kB]
    azure-arm.my-example: Fetched 21.1 MB in 4s (5512 kB/s)
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Building dependency tree...
    azure-arm.my-example: Reading state information...
    azure-arm.my-example: The following package was automatically installed and is no longer required:
    azure-arm.my-example:   linux-headers-4.15.0-151
    azure-arm.my-example: Use 'sudo apt autoremove' to remove it.
    azure-arm.my-example: The following NEW packages will be installed:
    azure-arm.my-example:   azure-cli
    azure-arm.my-example: 0 upgraded, 1 newly installed, 0 to remove and 29 not upgraded.
    azure-arm.my-example: Need to get 63.1 MB of archives.
    azure-arm.my-example: After this operation, 952 MB of additional disk space will be used.
    azure-arm.my-example: Get:1 https://packages.microsoft.com/repos/azure-cli bionic/main amd64 azure-cli all 2.27.2-1~bionic [63.1 MB]
    azure-arm.my-example: Fetched 63.1 MB in 1s (54.4 MB/s)
    azure-arm.my-example: Selecting previously unselected package azure-cli.
    azure-arm.my-example: (Reading database ... 76955 files and directories currently installed.)
    azure-arm.my-example: Preparing to unpack .../azure-cli_2.27.2-1~bionic_all.deb ...
    azure-arm.my-example: Unpacking azure-cli (2.27.2-1~bionic) ...
    azure-arm.my-example: Setting up azure-cli (2.27.2-1~bionic) ...
==> azure-arm.my-example: Querying the machine's properties ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmwgyajbups4'
==> azure-arm.my-example:  -> Managed OS Disk   : '/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Compute/disks/pkroswgyajbups4'
==> azure-arm.my-example: Querying the machine's additional disks properties ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmwgyajbups4'
==> azure-arm.my-example: Powering off machine ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmwgyajbups4'
==> azure-arm.my-example: Capturing image ...
==> azure-arm.my-example:  -> Compute ResourceGroupName : 'pkr-Resource-Group-wgyajbups4'
==> azure-arm.my-example:  -> Compute Name              : 'pkrvmwgyajbups4'
==> azure-arm.my-example:  -> Compute Location          : 'East US'
==> azure-arm.my-example:  -> Image ResourceGroupName   : 'packerlinux02'
==> azure-arm.my-example:  -> Image Name                : 'myPackerImage'
==> azure-arm.my-example:  -> Image Location            : 'East US'
==> azure-arm.my-example:
==> azure-arm.my-example: Deleting individual resources ...
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Compute/virtualMachines : 'pkrvmwgyajbups4'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/networkInterfaces : 'pkrniwgyajbups4'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/virtualNetworks : 'pkrvnwgyajbups4'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/publicIPAddresses : 'pkripwgyajbups4'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/publicIPAddresses : 'pkripwgyajbups4'
==> azure-arm.my-example: Waiting for deletion of all resources...
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/networkInterfaces : 'pkrniwgyajbups4'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Compute/virtualMachines : 'pkrvmwgyajbups4'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvnwgyajbups4'
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkripwgyajbups4
==> azure-arm.my-example: Error: network.PublicIPAddressesClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="PublicIPAddressCannotBeDeleted" Message="Public IP address /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Network/publicIPAddresses/pkripwgyajbups4 can not be deleted since it is still allocated to resource /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Network/networkInterfaces/pkrniwgyajbups4/ipConfigurations/ipconfig. In order to delete the public IP, disassociate/detach the Public IP address from the resource.  To learn how to do this, see aka.ms/deletepublicip." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkrniwgyajbups4
==> azure-arm.my-example: Error: network.InterfacesClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="NicInUse" Message="Network Interface /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Network/networkInterfaces/pkrniwgyajbups4 is used by existing resource /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Compute/virtualMachines/pkrvmwgyajbups4. In order to delete the network interface, it must be dissociated from the resource. To learn more, see aka.ms/deletenic." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkrvnwgyajbups4
==> azure-arm.my-example: Error: network.VirtualNetworksClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="InUseSubnetCannotBeDeleted" Message="Subnet pkrsnwgyajbups4 is in use by /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Network/networkInterfaces/pkrniwgyajbups4/ipConfigurations/ipconfig and cannot be deleted. In order to delete the subnet, delete all the resources within the subnet. See aka.ms/deletesubnet." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/publicIPAddresses : 'pkripwgyajbups4'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/networkInterfaces : 'pkrniwgyajbups4'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvnwgyajbups4'
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkripwgyajbups4
==> azure-arm.my-example: Error: network.PublicIPAddressesClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="PublicIPAddressCannotBeDeleted" Message="Public IP address /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Network/publicIPAddresses/pkripwgyajbups4 can not be deleted since it is still allocated to resource /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Network/networkInterfaces/pkrniwgyajbups4/ipConfigurations/ipconfig. In order to delete the public IP, disassociate/detach the Public IP address from the resource.  To learn how to do this, see aka.ms/deletepublicip." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkrvnwgyajbups4
==> azure-arm.my-example: Error: network.VirtualNetworksClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="InUseSubnetCannotBeDeleted" Message="Subnet pkrsnwgyajbups4 is in use by /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Network/networkInterfaces/pkrniwgyajbups4/ipConfigurations/ipconfig and cannot be deleted. In order to delete the subnet, delete all the resources within the subnet. See aka.ms/deletesubnet." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/publicIPAddresses : 'pkripwgyajbups4'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvnwgyajbups4'
==> azure-arm.my-example:  Deleting -> Microsoft.Compute/disks : '/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-wgyajbups4/providers/Microsoft.Compute/disks/pkroswgyajbups4'
==> azure-arm.my-example: Removing the created Deployment object: 'pkrdpwgyajbups4'
==> azure-arm.my-example:
==> azure-arm.my-example: Cleanup requested, deleting resource group ...
==> azure-arm.my-example: Resource group has been deleted.
Build 'azure-arm.my-example' finished after 6 minutes 34 seconds.

==> Wait completed after 6 minutes 34 seconds

==> Builds finished. The artifacts of successful builds are:
--> azure-arm.my-example: Azure.ResourceManagement.VMImage:

OSType: Linux
ManagedImageResourceGroupName: packerlinux02
ManagedImageName: myPackerImage
ManagedImageId: /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Compute/images/myPackerImage
ManagedImageLocation: East US

And we can see the full list of items in the RG in the Azure portal:

/content/images/2021/09/packer-build2-02.png

And if we wish to use VHD, we can simply uncomment the code and do it again:

# VHD style
resource_group_name = "${var.myrg}"
storage_account = "${var.mysa}"
capture_container_name = "images"
capture_name_prefix = "packer"

# Managed Image style
# managed_image_resource_group_name = "${var.myrg}"
# managed_image_name = "myPackerImage"

Rerunning will create the VHD:

$ packer build -var "myrg=`terraform output -raw packer_rg_name`" -var "mysa=`terraform output -raw packer_sa_name`" -var "client_secret=$SP_PASS" -var "client_id=$SP_ID" -var "tenant_id=$MYTENANT" -var "subscription_id=$MYSUB" .
azure-arm.my-example: output will be in this color.

==> azure-arm.my-example: Running builder ...
==> azure-arm.my-example: Getting tokens using client secret
==> azure-arm.my-example: Getting tokens using client secret
    azure-arm.my-example: Creating Azure Resource Manager (ARM) client ...
==> azure-arm.my-example: Warning: You are using Azure Packer Builder to create VHDs which is being deprecated, consider using Managed Images. Learn more https://www.packer.io/docs/builders/azure/arm#azure-arm-builder-specific-options
==> azure-arm.my-example: WARNING: Zone resiliency may not be supported in East US, checkout the docs at https://docs.microsoft.com/en-us/azure/availability-zones/
==> azure-arm.my-example: Creating resource group ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> Location          : 'East US'
==> azure-arm.my-example:  -> Tags              :
==> azure-arm.my-example:  ->> dept : engineering
==> azure-arm.my-example: Validating deployment template ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> DeploymentName    : 'pkrdpgbwsl6tmzf'
==> azure-arm.my-example: Deploying deployment template ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> DeploymentName    : 'pkrdpgbwsl6tmzf'
==> azure-arm.my-example:
==> azure-arm.my-example: Getting the VM's IP address ...
==> azure-arm.my-example:  -> ResourceGroupName   : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> PublicIPAddressName : 'pkripgbwsl6tmzf'
==> azure-arm.my-example:  -> NicName             : 'pkrnigbwsl6tmzf'
==> azure-arm.my-example:  -> Network Connection  : 'PublicEndpoint'
==> azure-arm.my-example:  -> IP Address          : '40.117.252.141'
==> azure-arm.my-example: Waiting for SSH to become available...
==> azure-arm.my-example: Connected to SSH!
==> azure-arm.my-example: Provisioning with shell script: ./setup-azcli.sh
    azure-arm.my-example: Hit:1 http://azure.archive.ubuntu.com/ubuntu bionic InRelease
    azure-arm.my-example: Get:2 http://azure.archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
    azure-arm.my-example: Get:3 http://azure.archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
    azure-arm.my-example: Get:4 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
    azure-arm.my-example: Get:5 http://azure.archive.ubuntu.com/ubuntu bionic/universe amd64 Packages [8570 kB]
    azure-arm.my-example: Get:6 http://azure.archive.ubuntu.com/ubuntu bionic/universe Translation-en [4941 kB]
    azure-arm.my-example: Get:7 http://azure.archive.ubuntu.com/ubuntu bionic/multiverse amd64 Packages [151 kB]
    azure-arm.my-example: Get:8 http://azure.archive.ubuntu.com/ubuntu bionic/multiverse Translation-en [108 kB]
    azure-arm.my-example: Get:9 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2192 kB]
    azure-arm.my-example: Get:10 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main Translation-en [430 kB]
    azure-arm.my-example: Get:11 http://azure.archive.ubuntu.com/ubuntu bionic-updates/restricted amd64 Packages [443 kB]
    azure-arm.my-example: Get:12 http://azure.archive.ubuntu.com/ubuntu bionic-updates/restricted Translation-en [59.9 kB]
    azure-arm.my-example: Get:13 http://azure.archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [1748 kB]
    azure-arm.my-example: Get:14 http://azure.archive.ubuntu.com/ubuntu bionic-updates/universe Translation-en [375 kB]
    azure-arm.my-example: Get:15 http://azure.archive.ubuntu.com/ubuntu bionic-updates/multiverse amd64 Packages [27.3 kB]
    azure-arm.my-example: Get:16 http://azure.archive.ubuntu.com/ubuntu bionic-updates/multiverse Translation-en [6808 B]
    azure-arm.my-example: Get:17 http://azure.archive.ubuntu.com/ubuntu bionic-backports/main amd64 Packages [10.0 kB]
    azure-arm.my-example: Get:18 http://azure.archive.ubuntu.com/ubuntu bionic-backports/main Translation-en [4764 B]
    azure-arm.my-example: Get:19 http://azure.archive.ubuntu.com/ubuntu bionic-backports/universe amd64 Packages [10.3 kB]
    azure-arm.my-example: Get:20 http://azure.archive.ubuntu.com/ubuntu bionic-backports/universe Translation-en [4588 B]
    azure-arm.my-example: Get:21 http://security.ubuntu.com/ubuntu bionic-security/main amd64 Packages [1846 kB]
    azure-arm.my-example: Get:22 http://security.ubuntu.com/ubuntu bionic-security/main Translation-en [338 kB]
    azure-arm.my-example: Get:23 http://security.ubuntu.com/ubuntu bionic-security/restricted amd64 Packages [419 kB]
    azure-arm.my-example: Get:24 http://security.ubuntu.com/ubuntu bionic-security/restricted Translation-en [56.1 kB]
    azure-arm.my-example: Get:25 http://security.ubuntu.com/ubuntu bionic-security/universe amd64 Packages [1137 kB]
    azure-arm.my-example: Get:26 http://security.ubuntu.com/ubuntu bionic-security/universe Translation-en [259 kB]
    azure-arm.my-example: Get:27 http://security.ubuntu.com/ubuntu bionic-security/multiverse amd64 Packages [20.9 kB]
    azure-arm.my-example: Get:28 http://security.ubuntu.com/ubuntu bionic-security/multiverse Translation-en [4732 B]
    azure-arm.my-example: Fetched 23.4 MB in 5s (4935 kB/s)
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Building dependency tree...
    azure-arm.my-example: Reading state information...
    azure-arm.my-example: lsb-release is already the newest version (9.20170808ubuntu1).
    azure-arm.my-example: lsb-release set to manually installed.
    azure-arm.my-example: ca-certificates is already the newest version (20210119~18.04.1).
    azure-arm.my-example: ca-certificates set to manually installed.
    azure-arm.my-example: gnupg is already the newest version (2.2.4-1ubuntu1.4).
    azure-arm.my-example: gnupg set to manually installed.
    azure-arm.my-example: The following package was automatically installed and is no longer required:
    azure-arm.my-example:   linux-headers-4.15.0-151
    azure-arm.my-example: Use 'sudo apt autoremove' to remove it.
    azure-arm.my-example: The following additional packages will be installed:
    azure-arm.my-example:   libcurl4
    azure-arm.my-example: The following NEW packages will be installed:
    azure-arm.my-example:   apt-transport-https
    azure-arm.my-example: The following packages will be upgraded:
    azure-arm.my-example:   curl libcurl4
    azure-arm.my-example: 2 upgraded, 1 newly installed, 0 to remove and 28 not upgraded.
    azure-arm.my-example: Need to get 382 kB of archives.
    azure-arm.my-example: After this operation, 154 kB of additional disk space will be used.
    azure-arm.my-example: Get:1 http://azure.archive.ubuntu.com/ubuntu bionic-updates/universe amd64 apt-transport-https all 1.6.14 [4348 B]
    azure-arm.my-example: Get:2 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main amd64 curl amd64 7.58.0-2ubuntu3.14 [159 kB]
    azure-arm.my-example: Get:3 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main amd64 libcurl4 amd64 7.58.0-2ubuntu3.14 [219 kB]
    azure-arm.my-example: Fetched 382 kB in 0s (22.4 MB/s)
    azure-arm.my-example: Selecting previously unselected package apt-transport-https.
    azure-arm.my-example: (Reading database ... 76951 files and directories currently installed.)
    azure-arm.my-example: Preparing to unpack .../apt-transport-https_1.6.14_all.deb ...
    azure-arm.my-example: Unpacking apt-transport-https (1.6.14) ...
    azure-arm.my-example: Preparing to unpack .../curl_7.58.0-2ubuntu3.14_amd64.deb ...
    azure-arm.my-example: Unpacking curl (7.58.0-2ubuntu3.14) over (7.58.0-2ubuntu3.13) ...
    azure-arm.my-example: Preparing to unpack .../libcurl4_7.58.0-2ubuntu3.14_amd64.deb ...
    azure-arm.my-example: Unpacking libcurl4:amd64 (7.58.0-2ubuntu3.14) over (7.58.0-2ubuntu3.13) ...
    azure-arm.my-example: Setting up apt-transport-https (1.6.14) ...
    azure-arm.my-example: Setting up libcurl4:amd64 (7.58.0-2ubuntu3.14) ...
    azure-arm.my-example: Setting up curl (7.58.0-2ubuntu3.14) ...
    azure-arm.my-example: Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
    azure-arm.my-example: Processing triggers for libc-bin (2.27-3ubuntu1.4) ...
==> azure-arm.my-example: gpg: WARNING: unsafe ownership on homedir '/home/packer/.gnupg'
    azure-arm.my-example: deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ bionic main
    azure-arm.my-example: Hit:1 http://azure.archive.ubuntu.com/ubuntu bionic InRelease
    azure-arm.my-example: Hit:2 http://azure.archive.ubuntu.com/ubuntu bionic-updates InRelease
    azure-arm.my-example: Hit:3 http://azure.archive.ubuntu.com/ubuntu bionic-backports InRelease
    azure-arm.my-example: Hit:4 http://security.ubuntu.com/ubuntu bionic-security InRelease
    azure-arm.my-example: Get:5 https://packages.microsoft.com/repos/azure-cli bionic InRelease [3965 B]
    azure-arm.my-example: Get:6 https://packages.microsoft.com/repos/azure-cli bionic/main amd64 Packages [15.0 kB]
    azure-arm.my-example: Fetched 19.0 kB in 1s (35.6 kB/s)
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Reading package lists...
    azure-arm.my-example: Building dependency tree...
    azure-arm.my-example: Reading state information...
    azure-arm.my-example: The following package was automatically installed and is no longer required:
    azure-arm.my-example:   linux-headers-4.15.0-151
    azure-arm.my-example: Use 'sudo apt autoremove' to remove it.
    azure-arm.my-example: The following NEW packages will be installed:
    azure-arm.my-example:   azure-cli
    azure-arm.my-example: 0 upgraded, 1 newly installed, 0 to remove and 28 not upgraded.
    azure-arm.my-example: Need to get 63.1 MB of archives.
    azure-arm.my-example: After this operation, 952 MB of additional disk space will be used.
    azure-arm.my-example: Get:1 https://packages.microsoft.com/repos/azure-cli bionic/main amd64 azure-cli all 2.27.2-1~bionic [63.1 MB]
    azure-arm.my-example: Fetched 63.1 MB in 1s (49.6 MB/s)
    azure-arm.my-example: Selecting previously unselected package azure-cli.
    azure-arm.my-example: (Reading database ... 76955 files and directories currently installed.)
    azure-arm.my-example: Preparing to unpack .../azure-cli_2.27.2-1~bionic_all.deb ...
    azure-arm.my-example: Unpacking azure-cli (2.27.2-1~bionic) ...
    azure-arm.my-example: Setting up azure-cli (2.27.2-1~bionic) ...
==> azure-arm.my-example: Querying the machine's properties ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmgbwsl6tmzf'
==> azure-arm.my-example:  -> OS Disk           : 'https://idjpackersa02.blob.core.windows.net/images/pkrosgbwsl6tmzf.vhd'
==> azure-arm.my-example: Querying the machine's additional disks properties ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmgbwsl6tmzf'
==> azure-arm.my-example: Powering off machine ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmgbwsl6tmzf'
==> azure-arm.my-example: Capturing image ...
==> azure-arm.my-example:  -> Compute ResourceGroupName : 'pkr-Resource-Group-gbwsl6tmzf'
==> azure-arm.my-example:  -> Compute Name              : 'pkrvmgbwsl6tmzf'
==> azure-arm.my-example:  -> Compute Location          : 'East US'
==> azure-arm.my-example:
==> azure-arm.my-example: Deleting individual resources ...
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Compute/virtualMachines : 'pkrvmgbwsl6tmzf'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/networkInterfaces : 'pkrnigbwsl6tmzf'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/virtualNetworks : 'pkrvngbwsl6tmzf'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/publicIPAddresses : 'pkripgbwsl6tmzf'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/publicIPAddresses : 'pkripgbwsl6tmzf'
==> azure-arm.my-example: Waiting for deletion of all resources...
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/networkInterfaces : 'pkrnigbwsl6tmzf'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvngbwsl6tmzf'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Compute/virtualMachines : 'pkrvmgbwsl6tmzf'
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkripgbwsl6tmzf
==> azure-arm.my-example: Error: network.PublicIPAddressesClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="PublicIPAddressCannotBeDeleted" Message="Public IP address /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-gbwsl6tmzf/providers/Microsoft.Network/publicIPAddresses/pkripgbwsl6tmzf can not be deleted since it is still allocated to resource /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-gbwsl6tmzf/providers/Microsoft.Network/networkInterfaces/pkrnigbwsl6tmzf/ipConfigurations/ipconfig. In order to delete the public IP, disassociate/detach the Public IP address from the resource.  To learn how to do this, see aka.ms/deletepublicip." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkrvngbwsl6tmzf
==> azure-arm.my-example: Error: network.VirtualNetworksClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="InUseSubnetCannotBeDeleted" Message="Subnet pkrsngbwsl6tmzf is in use by /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-gbwsl6tmzf/providers/Microsoft.Network/networkInterfaces/pkrnigbwsl6tmzf/ipConfigurations/ipconfig and cannot be deleted. In order to delete the subnet, delete all the resources within the subnet. See aka.ms/deletesubnet." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/publicIPAddresses : 'pkripgbwsl6tmzf'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvngbwsl6tmzf'
==> azure-arm.my-example:  Deleting -> image : 'https://idjpackersa02.blob.core.windows.net/images/pkrosgbwsl6tmzf.vhd'
==> azure-arm.my-example: Removing the created Deployment object: 'pkrdpgbwsl6tmzf'
==> azure-arm.my-example:
==> azure-arm.my-example: Cleanup requested, deleting resource group ...
==> azure-arm.my-example: Resource group has been deleted.
Build 'azure-arm.my-example' finished after 5 minutes 31 seconds.

==> Wait completed after 5 minutes 31 seconds

==> Builds finished. The artifacts of successful builds are:
--> azure-arm.my-example: Azure.ResourceManagement.VMImage:

OSType: Linux
StorageAccountLocation: eastus
OSDiskUri: https://idjpackersa02.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-osDisk.cde0f801-7da2-4d17-9e3e-751dbb74fef3.vhd
OSDiskUriReadOnlySas: https://idjpackersa02.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-osDisk.cde0f801-7da2-4d17-9e3e-751dbb74fef3.vhd?se=2021-10-06T22%3A40%3A40Z&sig=piKA77zP3STxZavNN1%2FhNU5jspYjVgrK9S7nbxvnjCw%3D&sp=r&sr=b&sv=2018-03-28
TemplateUri: https://idjpackersa02.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-vmTemplate.cde0f801-7da2-4d17-9e3e-751dbb74fef3.json
TemplateUriReadOnlySas: https://idjpackersa02.blob.core.windows.net/system/Microsoft.Compute/Images/images/packer-vmTemplate.cde0f801-7da2-4d17-9e3e-751dbb74fef3.json?se=2021-10-06T22%3A40%3A40Z&sig=5MBHgRQdPJDofdJOtQN0T94pDQk4a9lnA8b9%2BrHoes4%3D&sp=r&sr=b&sv=2018-03-28

And we can see that in the portal:

/content/images/2021/09/packer-build2-03.png

Using a VHD locally

In order to use this VHD locally, I’ll need to download it. Since I don’t have the bandwidth to pull 30Gb (and with the egregious data caps on home internet, I wouldn’t do it anyways), I’ll want to compress it first.

To do this, we can use the same image we just made to create a host.

$ az vm create -g packerlinux02 --image myPackerImage --name myLinuxDemoMI2 --admin-username azureuser --generate-ssh-keys

The problem is that this host will have a 30Gb disk which is the same size as the file we are attempting to compress. We’ll need to add more storage to make it usable.

To address this shortcoming, after creating the vm with the az vm create command, I went to the portal and added a 60Gb data disk

/content/images/2021/09/packer-build2-04.png

Once created, I SSH’ed into the Azure VM to mount the disk

$ azureuser@23.96.114.116

azureuser@myLinuxDemoMI2:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.7G     0  1.7G   0% /dev
tmpfs           344M  676K  343M   1% /run
/dev/sdc1        29G  2.6G   27G   9% /
tmpfs           1.7G     0  1.7G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           1.7G     0  1.7G   0% /sys/fs/cgroup
/dev/sdc15      105M  6.6M   98M   7% /boot/efi
/dev/sda1       6.9G   32M  6.5G   1% /mnt
tmpfs           344M     0  344M   0% /run/user/1001
azureuser@myLinuxDemoMI2:~$ lsblk -o NAME,HCTL,SIZE,MOUNTPOINT | grep -i "sd"
sda     1:0:1:0       7G
└─sda1                7G /mnt
sdb     3:0:0:0      60G
sdc     0:0:0:0      30G
├─sdc1             29.9G /
├─sdc14               4M
└─sdc15             106M /boot/efi
azureuser@myLinuxDemoMI2:~$ sudo parted /dev/sdb --script mklabel gpt mkpart xfspart xfs 0% 100%
azureuser@myLinuxDemoMI2:~$ sudo mkfs.xfs /dev/sdb1
meta-data=/dev/sdb1              isize=512    agcount=4, agsize=3932032 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=0, rmapbt=0, reflink=0
data     =                       bsize=4096   blocks=15728128, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=7679, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
azureuser@myLinuxDemoMI2:~$ sudo partprobe /dev/sdb1
azureuser@myLinuxDemoMI2:~$ sudo mkdir /datadrive
azureuser@myLinuxDemoMI2:~$ sudo mount /dev/sdb1 /datadrive
azureuser@myLinuxDemoMI2:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.7G     0  1.7G   0% /dev
tmpfs           344M  676K  343M   1% /run
/dev/sdc1        29G  2.6G   27G   9% /
tmpfs           1.7G     0  1.7G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           1.7G     0  1.7G   0% /sys/fs/cgroup
/dev/sdc15      105M  6.6M   98M   7% /boot/efi
/dev/sda1       6.9G   32M  6.5G   1% /mnt
tmpfs           344M     0  344M   0% /run/user/1001
/dev/sdb1        60G   94M   60G   1% /datadrive

Once mounted as “/datadrive”, I was able to use the Azure CLI to download the existing VHD to the mount:

$ az login
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code RJLNE9U47 to authenticate.
The following tenants don't contain accessible subscriptions. Use 'az login --allow-no-subscriptions' to have tenant level access.
2f5b31ae-cc9f-445d-bec6-fe0546b2a741 'mytestdomain'
5b42c447-cf12-4b56-8de9-fc7688e36ec6 'IDJCompleteNonsense'
92a2e5a9-a8ab-4d8c-91eb-8af9712c16d5 'Princess King'
[
  {
...

Even though auth-mode should have worked, it didn’t. So I then used the account key

azureuser@myLinuxDemoMI2:/datadrive$ az storage blob download --container-name system --file my.vhd --name Microsoft.Compute/Images/images/packer-osDisk.cde0f801-7da2-4d17-9e3e-751dbb74fef3.vhd --account-name idjpackersa02 --account-key bm90IHJlYWxseSBhIHN0b3JhZ2Uga2V5LCB5YSBrbm93Cg==
Alive[                                                                ]  1.3281%

This took a while, but it did eventually finish

$ az storage blob download --container-name system --file my.vhd --name Microsoft.Compute/Images/images/packer-osDisk.cde0f801-7da2-4d17-9e3e-751dbb74fef3.vhd --account-name idjpackersa02 --account-key bm90IHJlYWxseSBhIHN0b3JhZ2Uga2V5LCB5YSBrbm93Cg==
Finished[#############################################################]  100.0000%
{
  "content": null,
  "deleted": false,
  "metadata": {
    "MicrosoftAzureCompute_CapturedVMKey": "/Subscriptions/944c019d-3e46-422b-b63a-86513f147562/ResourceGroups/PKR-RESOURCE-GROUP-GBWSL6TMZF/VMs/PKRVMGBWSL6TMZF",
    "MicrosoftAzureCompute_ImageType": "OSDisk",
    "MicrosoftAzureCompute_OSState": "Generalized",
    "MicrosoftAzureCompute_OSType": "Linux"
  },
  "name": "Microsoft.Compute/Images/images/packer-osDisk.cde0f801-7da2-4d17-9e3e-751dbb74fef3.vhd",
  "properties": {
    "appendBlobCommittedBlockCount": null,
    "blobTier": null,
    "blobTierChangeTime": null,
    "blobTierInferred": false,
    "blobType": "PageBlob",
    "contentLength": 32213303808,
    "contentMd5": null,
    "contentRange": "bytes None-None/32213303808",
    "contentSettings": {
      "cacheControl": null,
      "contentDisposition": null,
      "contentEncoding": null,
      "contentLanguage": null,
      "contentType": "application/octet-stream"
    },
    "copy": {
      "completionTime": "2021-09-06T22:39:55+00:00",
      "id": "4971b7b6-ce16-4f94-b9d5-d2fa1c852c58",
      "progress": "32213303808/32213303808",
      "source": "https://idjpackersa02.blob.core.windows.net/images/pkrosgbwsl6tmzf.vhd?sv=2018-03-28&sr=b&st=2021-09-06T22%3a24%3a55Z&se=2021-09-06T23%3a39%3a55Z&sp=rw",
      "status": "success",
      "statusDescription": null
    },
    "creationTime": "2021-09-06T22:39:55+00:00",
    "deletedTime": null,
    "etag": "\"0x8D971873FB7D002\"",
    "lastModified": "2021-09-06T22:39:55+00:00",
    "lease": {
      "duration": null,
      "state": "available",
      "status": "unlocked"
    },
    "pageBlobSequenceNumber": 1,
    "remainingRetentionDays": null,
    "serverEncrypted": true
  },
  "snapshot": null
}

Again, we had to expand the disk because the base image is 30gb, the same size as the VHD.

We need, of course, enough space to download the image AND then compress it.

azureuser@myLinuxDemoMI2:/datadrive$ tar -czvf my.vhd.tgz ./my.vhd
./my.vhd

note: this step may appear hung. For me this took about 10m with no output.

When done, we can see it was created:

$ ls -ltrah
total 31G
drwxr-xr-x 24 root      root      4.0K Sep  6 23:30 ..
-rw-rw-r--  1 azureuser azureuser    0 Sep  6 23:32 asdf
-rw-rw-r--  1 azureuser azureuser  31G Sep  6 23:43 my.vhd
drwxrwxrwx  2 root      root        50 Sep  6 23:44 .
-rw-rw-r--  1 azureuser azureuser 697M Sep  6 23:53 my.vhd.tgz

That is a pretty significant space savings; 31Gb to just under 700Mb.

We can upload with a similar command to what we used to download:

$ az storage blob upload --container-name system --file my.vhd.tgz --name Microsoft.Compute/Images/images/pac
ker-osDisk.cde0f801-7da2-4d17-9e3e-751dbb74fef3.vhd.tgz --account-name idjpackersa02 --account-key bm90IHJlYWxseSBhIHN0b3JhZ2Uga2V5LCB5YSBrbm93Cg==
Finished[#############################################################]  100.0000%
{
  "etag": "\"0x8D97191EF1D7956\"",
  "lastModified": "2021-09-06T23:56:24+00:00"
}

Now i can bring this file down locally.

I first tried just downloading it from the browser:

/content/images/2021/09/packer-build2-05.png

However, it timed out, so i decided to fallback to just downloading with the Azure CLI.

Here I’m using a laptop with enough disk and Hyper-V manager already installed. I should point out, WSL uses a virtual drive, so if you want to avoid filling that up (when we expand), change dir over to /mnt/c.

I followed the same steps as above to download, only this time using the name “Microsoft.Compute/Images/images/pac ker-osDisk.cde0f801-7da2-4d17-9e3e-751dbb74fef3.vhd.tgz” and file “my.vhd.tgz”.

Once downloaded, i just used tar -xzvf my.vhd.tgz

builder@DESKTOP-72D2D9T:/mnt/c/Users/isaac/Downloads$ ls -ltrah | grep my.vhd
-rwxrwxrwx 1 builder builder  31G Sep  6 18:43 my.vhd
-rwxrwxrwx 1 builder builder 697M Sep  6 19:34 my.vhd.tgz

Creating a VM with Hyper-V

Choose Quick Create and Local Installation Source.

/content/images/2021/09/packer-build2-09.png

Then you can pick your downloaded and expanded VHD

/content/images/2021/09/packer-build2-06.png

When completed, you can connect to launch the console.

/content/images/2021/09/packer-build2-07.png

And if we had a valid user (something we should correct later), we could login. However, this shows it was downloaded locally and is running:

/content/images/2021/09/packer-build2-08.png

Cleanup

Do not forget to remove any VMs made in this excercise. They can cost some money over time.

Checking for running instances:

$ az vm list -g packerlinux02 -o table
Name            ResourceGroup    Location    Zones
--------------  ---------------  ----------  -------
myLinuxDemoMI2  packerlinux02    eastus

Then delete

$ az vm delete -g packerlinux02 -n myLinuxDemoMI2
Are you sure you want to perform this operation? (y/n): y
 - Running ..

Using as VMSS pools

We can create a VMSS pool from this image to be used by Azure DevOps (or other uses) with the CLI quite easily.

The key note is to set the ‘instance-count’ to 0 right off.

$ az vmss create -n MyLinuxVMSS -g packerlinux02 --image myPackerImage --instance-count 0 -l "East US" --admin-username azureuser --generate-ssh-keys
{
  "vmss": {
    "doNotRunExtensionsOnOverprovisionedVMs": false,
    "overprovision": true,
    "provisioningState": "Succeeded",
    "singlePlacementGroup": true,
    "uniqueId": "0b679acb-6fc3-4be1-a5c9-183561d1b978",
    "upgradePolicy": {
      "mode": "Manual",
      "rollingUpgradePolicy": {
        "maxBatchInstancePercent": 20,
        "maxUnhealthyInstancePercent": 20,
        "maxUnhealthyUpgradedInstancePercent": 20,
        "pauseTimeBetweenBatches": "PT0S"
      }
    },
    "virtualMachineProfile": {
      "networkProfile": {
        "networkInterfaceConfigurations": [
          {
            "name": "mylin162fNic",
            "properties": {
              "dnsSettings": {
                "dnsServers": []
              },
              "enableAcceleratedNetworking": false,
              "enableIPForwarding": false,
              "ipConfigurations": [
                {
                  "name": "mylin162fIPConfig",
                  "properties": {
                    "loadBalancerBackendAddressPools": [
                      {
                        "id": "/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Network/loadBalancers/MyLinuxVMSSLB/backendAddressPools/MyLinuxVMSSLBBEPool",
                        "resourceGroup": "packerlinux02"
                      }
                    ],
                    "loadBalancerInboundNatPools": [
                      {
                        "id": "/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Network/loadBalancers/MyLinuxVMSSLB/inboundNatPools/MyLinuxVMSSLBNatPool",
                        "resourceGroup": "packerlinux02"
                      }
                    ],
                    "privateIPAddressVersion": "IPv4",
                    "subnet": {
                      "id": "/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Network/virtualNetworks/myLinuxDemoMI2VNET/subnets/myLinuxDemoMI2Subnet",
                      "resourceGroup": "packerlinux02"
                    }
                  }
                }
              ],
              "primary": true
            }
          }
        ]
      },
      "osProfile": {
        "adminUsername": "azureuser",
        "allowExtensionOperations": true,
        "computerNamePrefix": "mylin162f",
        "linuxConfiguration": {
          "disablePasswordAuthentication": true,
          "provisionVMAgent": true,
          "ssh": {
            "publicKeys": [
              {
                "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCztCsq2pg/AFf8t6d6LobwssgaXLVNnzn4G0e7M13J9t2o41deZjLQaRTLYyqGhmwp114GpJnac08F4Ln87CbIu2jbQCC2y89bE4k2a9226VJDasdfQ3f8gDvO4iFKNla2s8E1gpYv6VxN7e7OX+FJmJ4dY2ydPxQ6RoxOLxWx6IDk9ysDK8MoSIUoD9nvD/PqlWBZLXBqqasdfasdfsadfasdfsadfL4lQHjK2NwqN8AK6pC1ywItDc1fUpJZEEPOJQLShI+dqqqjUptwJUPq87h",
                "path": "/home/azureuser/.ssh/authorized_keys"
              }
            ]
          }
        },
        "requireGuestProvisionSignal": true,
        "secrets": []
      },
      "storageProfile": {
        "imageReference": {
          "id": "/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Compute/images/myPackerImage",
          "resourceGroup": "packerlinux02"
        },
        "osDisk": {
          "caching": "ReadWrite",
          "createOption": "FromImage",
          "diskSizeGB": 30,
          "managedDisk": {
            "storageAccountType": "Standard_LRS"
          },
          "osType": "Linux"
        }
      }
    }
  }
}

You may need to grant your Azure DevOps Subscription Service Principal access to the VMSS in order to use it. I did that and it also took a good 10+ minutes for the listing to show in Azure DevOps portal

/content/images/2021/09/packer-build2-10.png

Adding Agent Pool in AzDO

Once it is ready, we can select it in the Agent Pool VMSS create window:

/content/images/2021/09/packer-build2-11.png

And again, make sure to set the standby to 0 unless you want to pay for a running instance

/content/images/2021/09/packer-build2-12.png

You can change some of the settings - like how many on standby or delay before deleting them (this is useful if you use a very large class and you want it torn down immediately after use)

/content/images/2021/09/packer-build2-13.png

To do a quick test, I’ll create a quick classic (graphical) build job and specify the pool. Here I do not care about the git repo, I’m just trying to test the pool

/content/images/2021/09/packer-build2-14.png

We can use a quick bit of bash to test. I’m interested in if the ‘packer’ user shows up in the password hash and if the azure CLI is installed

# Write your commands here
whoami
less /etc/passwd | grep packer
az version

/content/images/2021/09/packer-build2-15.png

be aware the first time it is run, it will take some time as there is no VM as of yet

/content/images/2021/09/packer-build2-16.png

and our test result shows it is indeed the packer based VM

/content/images/2021/09/packer-build2-17.png

We left the default 30m idle, so we should be able to see the instance still listed in the VMSS agent pool listing

/content/images/2021/09/packer-build2-18.png

which corresponds to the instance we see in the Azure Portal under Instances for the VMSS

/content/images/2021/09/packer-build2-19.png

Since we set the timeout to 30m, we see that it was scaled back in after 30 minutes had passed:

/content/images/2021/09/packer-build2-20.png

Basing an image on an image

What if we wanted to take a base image and expand upon it? This is also pretty easy to do in Packer.

We have two choices for referencing non-marketplace images. The first is using an Image URL:

image_url (string) - URL to a custom VHD to use for your base image. If this value is set, image_publisher, image_offer, image_sku, or image_version should not be set.

The other is using a custom managed image name:

custom_managed_image_name (string) - Name of a custom managed image to use for your base image. If this value is set, do not set image_publisher, image_offer, image_sku, or image_version. If this value is set, the option custom_managed_image_resource_group_name must also be set. See documentation to learn more about managed images.

We could do either, but for this example, let’s expand on the Managed Image we’ve been using.

We will comment out the marketplace image settings, change the base to “packer2” and refer to our existing managed image name.

We will also do something different this time. Let’s install azcopy.

$ cat setup-azcopy.sh
#!/bin/bash

export DEBIAN_FRONTEND=noninteractive

# Note: Assumes all is being run with root or via sudo

# pre-requisites for cli
apt-get update
apt-get -y install wget

# download azcopy
wget https://aka.ms/downloadazcopy-v10-linux

# expand
umask 0002
tar -xf downloadazcopy-v10-linux

# remove any existing
rm -f /usr/bin/azcopy || true

# move into place
cp ./azcopy_linux_amd64_*/azcopy /usr/bin/
chmod 755 /usr/bin/azcopy

Here is the updated build pkr.hcl file

source "azure-arm" "my-example" {
  client_id = "${var.client_id}"
  client_secret = "${var.client_secret}"


  tenant_id= "${var.tenant_id}"
  subscription_id = "${var.subscription_id}"

  # VHD style
  resource_group_name = "${var.myrg}"
  storage_account = "${var.mysa}"
  capture_container_name = "images"
  capture_name_prefix = "packer2"

  # Managed Image style
  # managed_image_resource_group_name = "${var.myrg}"
  # managed_image_name = "myPackerImage"

  os_type = "Linux"

  # Market Place images
  # image_publisher = "Canonical"
  # image_offer = "UbuntuServer"
  # image_sku = "18.04-LTS"

  custom_managed_image_name = "myPackerImage"

  location = "East US"
  vm_size = "Standard_DS2_v2"

  azure_tags = {
    dept = "engineering"
  }
}

build {
  sources = ["sources.azure-arm.my-example"]

  provisioner "shell" {

    execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo {{ .Path }}"
    script          = "./setup-azcopy.sh"
  }
}

I’ll need to capture the RG and SA from before. Since I’m doing this in a new directory, I’ll set some env vars first, then cd to my new packer dir

builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo02$ export TFSA=`terraform output -raw packer_sa_name`
builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo02$ export TFRG=`terraform output -raw packer_rg_name`
builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo02$ cd ../demo03
builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo03$ packer build -var "myrg=$TFRG" -var "mysa=$TFSA" -var "client_secret=$SP_PASS" -var "client_id=$SP_ID" -var "tenant_id=$MYTENANT" -var "subscription_id=$MYSUB" .

The errors show i missed a few fields:

$ packer build -var "myrg=$TFRG" -var "mysa=$TFSA" -var "client_secret=$SP_PASS" -var "client_id=$SP_ID" -var "tenant_id=$MYTENANT" -var "subscription_id=$MYSUB" .
Error: 3 error(s) occurred:

* A custom_managed_image_resource_group_name must be specified
* A managed_image_resource_group_name must be specified
* A managed_image_name must be specified

  on ubuntu-test.pkr.hcl line 2:
  (source code not available)



==> Wait completed after 4 microseconds

==> Builds finished but no artifacts were created.

It would appear making a VHD based image on a ManagedImage isn’t supported. Let’s change to a managed on a managed and try again:


source "azure-arm" "my-example" {
  client_id = "${var.client_id}"
  client_secret = "${var.client_secret}"
  

  tenant_id= "${var.tenant_id}"
  subscription_id = "${var.subscription_id}"

  # VHD style
  # resource_group_name = "${var.myrg}"
  # storage_account = "${var.mysa}"
  # capture_container_name = "images"
  # capture_name_prefix = "packer2"

  # Managed Image style
  managed_image_resource_group_name = "${var.myrg}"
  managed_image_name = "myPackerImage2"

  os_type = "Linux"

  # Market Place images
  # image_publisher = "Canonical"
  # image_offer = "UbuntuServer"
  # image_sku = "18.04-LTS"

  custom_managed_image_resource_group_name = "${var.myrg}"
  custom_managed_image_name = "myPackerImage"

  location = "East US"
  vm_size = "Standard_DS2_v2"

  azure_tags = {
    dept = "engineering"
  }
}

build {
  sources = ["sources.azure-arm.my-example"]
  
  provisioner "shell" {
    
    execute_command = "chmod +x {{ .Path }}; {{ .Vars }} sudo {{ .Path }}"
    script          = "./setup-azcopy.sh"
  }
}

and building created a new image:

$ packer build -var "myrg=$TFRG" -var "mysa=$TFSA" -var "client_secret=$SP_PASS" -var "client_id=$SP_ID" -var "tenant_id=$MYTENANT" -var "subscription_id=$MYSUB" .
azure-arm.my-example: output will be in this color.

==> azure-arm.my-example: Running builder ...
==> azure-arm.my-example: Getting tokens using client secret
==> azure-arm.my-example: Getting tokens using client secret
    azure-arm.my-example: Creating Azure Resource Manager (ARM) client ...
==> azure-arm.my-example: WARNING: Zone resiliency may not be supported in East US, checkout the docs at https://docs.microsoft.com/en-us/azure/availability-zones/
==> azure-arm.my-example: Creating resource group ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> Location          : 'East US'
==> azure-arm.my-example:  -> Tags              :
==> azure-arm.my-example:  ->> dept : engineering
==> azure-arm.my-example: Validating deployment template ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> DeploymentName    : 'pkrdpz6h1s3pp3w'
==> azure-arm.my-example: Deploying deployment template ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> DeploymentName    : 'pkrdpz6h1s3pp3w'
==> azure-arm.my-example:
==> azure-arm.my-example: Getting the VM's IP address ...
==> azure-arm.my-example:  -> ResourceGroupName   : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> PublicIPAddressName : 'pkripz6h1s3pp3w'
==> azure-arm.my-example:  -> NicName             : 'pkrniz6h1s3pp3w'
==> azure-arm.my-example:  -> Network Connection  : 'PublicEndpoint'
==> azure-arm.my-example:  -> IP Address          : '52.168.93.7'
==> azure-arm.my-example: Waiting for SSH to become available...
==> azure-arm.my-example: Connected to SSH!
==> azure-arm.my-example: Provisioning with shell script: ./setup-azcopy.sh
    azure-arm.my-example: Hit:1 http://azure.archive.ubuntu.com/ubuntu bionic InRelease
    azure-arm.my-example: Get:2 http://azure.archive.ubuntu.com/ubuntu bionic-updates InRelease [88.7 kB]
    azure-arm.my-example: Get:3 http://azure.archive.ubuntu.com/ubuntu bionic-backports InRelease [74.6 kB]
    azure-arm.my-example: Get:4 http://security.ubuntu.com/ubuntu bionic-security InRelease [88.7 kB]
    azure-arm.my-example: Get:5 https://packages.microsoft.com/repos/azure-cli bionic InRelease [3964 B]
    azure-arm.my-example: Get:6 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main amd64 Packages [2192 kB]
    azure-arm.my-example: Get:7 http://azure.archive.ubuntu.com/ubuntu bionic-updates/main Translation-en [430 kB]
    azure-arm.my-example: Get:8 http://azure.archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages [1747 kB]
    azure-arm.my-example: Get:9 https://packages.microsoft.com/repos/azure-cli bionic/main amd64 Packages [15.1 kB]
    azure-arm.my-example: Fetched 4640 kB in 1s (3728 kB/s)
    azure-arm.my-example: Reading package lists...
==> azure-arm.my-example: E: Could not get lock /var/lib/dpkg/lock-frontend - open (11: Resource temporarily unavailable)
==> azure-arm.my-example: E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
==> azure-arm.my-example: --2021-09-07 12:43:24--  https://aka.ms/downloadazcopy-v10-linux
==> azure-arm.my-example: Resolving aka.ms (aka.ms)... 104.67.209.176
==> azure-arm.my-example: Connecting to aka.ms (aka.ms)|104.67.209.176|:443... connected.
==> azure-arm.my-example: HTTP request sent, awaiting response... 301 Moved Permanently
==> azure-arm.my-example: Location: https://azcopyvnext.azureedge.net/release20210901/azcopy_linux_amd64_10.12.1.tar.gz [following]
==> azure-arm.my-example: --2021-09-07 12:43:24--  https://azcopyvnext.azureedge.net/release20210901/azcopy_linux_amd64_10.12.1.tar.gz
==> azure-arm.my-example: Resolving azcopyvnext.azureedge.net (azcopyvnext.azureedge.net)... 104.97.85.132, 104.97.85.146, 2600:1408:5400:1b::173e:e695, ...
==> azure-arm.my-example: Connecting to azcopyvnext.azureedge.net (azcopyvnext.azureedge.net)|104.97.85.132|:443... connected.
==> azure-arm.my-example: HTTP request sent, awaiting response... 200 OK
==> azure-arm.my-example: Length: 11851766 (11M) [application/gzip]
==> azure-arm.my-example: Saving to: ‘downloadazcopy-v10-linux’
==> azure-arm.my-example:
==> azure-arm.my-example:      0K .......... .......... .......... .......... ..........  0% 40.5M 0s
==> azure-arm.my-example:     50K .......... .......... .......... .......... ..........  0% 34.4M 0s
==> azure-arm.my-example:    100K .......... .......... .......... .......... ..........  1% 25.2M 0s
==> azure-arm.my-example:    150K .......... .......... .......... .......... ..........  1% 46.9M 0s
==> azure-arm.my-example:    200K .......... .......... .......... .......... ..........  2% 40.2M 0s
==> azure-arm.my-example:    250K .......... .......... .......... .......... ..........  2% 51.4M 0s
==> azure-arm.my-example:    300K .......... .......... .......... .......... ..........  3% 37.4M 0s
==> azure-arm.my-example:    350K .......... .......... .......... .......... ..........  3% 51.2M 0s
==> azure-arm.my-example:    400K .......... .......... .......... .......... ..........  3%  266M 0s
==> azure-arm.my-example:    450K .......... .......... .......... .......... ..........  4%  290M 0s
==> azure-arm.my-example:    500K .......... .......... .......... .......... ..........  4%  258M 0s
==> azure-arm.my-example:    550K .......... .......... .......... .......... ..........  5%  177M 0s
==> azure-arm.my-example:    600K .......... .......... .......... .......... ..........  5%  275M 0s
==> azure-arm.my-example:    650K .......... .......... .......... .......... ..........  6%  257M 0s
==> azure-arm.my-example:    700K .......... .......... .......... .......... ..........  6%  168M 0s
==> azure-arm.my-example:    750K .......... .......... .......... .......... ..........  6%  304M 0s
==> azure-arm.my-example:    800K .......... .......... .......... .......... ..........  7%  245M 0s
==> azure-arm.my-example:    850K .......... .......... .......... .......... ..........  7%  104M 0s
==> azure-arm.my-example:    900K .......... .......... .......... .......... ..........  8% 40.1M 0s
==> azure-arm.my-example:    950K .......... .......... .......... .......... ..........  8% 46.1M 0s
==> azure-arm.my-example:   1000K .......... .......... .......... .......... ..........  9% 37.9M 0s
==> azure-arm.my-example:   1050K .......... .......... .......... .......... ..........  9% 46.4M 0s
==> azure-arm.my-example:   1100K .......... .......... .......... .......... ..........  9% 50.5M 0s
==> azure-arm.my-example:   1150K .......... .......... .......... .......... .......... 10%  131M 0s
==> azure-arm.my-example:   1200K .......... .......... .......... .......... .......... 10%  273M 0s
==> azure-arm.my-example:   1250K .......... .......... .......... .......... .......... 11%  127M 0s
==> azure-arm.my-example:   1300K .......... .......... .......... .......... .......... 11%  329M 0s
==> azure-arm.my-example:   1350K .......... .......... .......... .......... .......... 12%  173M 0s
==> azure-arm.my-example:   1400K .......... .......... .......... .......... .......... 12%  156M 0s
==> azure-arm.my-example:   1450K .......... .......... .......... .......... .......... 12%  259M 0s
==> azure-arm.my-example:   1500K .......... .......... .......... .......... .......... 13%  289M 0s
==> azure-arm.my-example:   1550K .......... .......... .......... .......... .......... 13% 47.4M 0s
==> azure-arm.my-example:   1600K .......... .......... .......... .......... .......... 14% 58.0M 0s
==> azure-arm.my-example:   1650K .......... .......... .......... .......... .......... 14% 50.8M 0s
==> azure-arm.my-example:   1700K .......... .......... .......... .......... .......... 15% 52.2M 0s
==> azure-arm.my-example:   1750K .......... .......... .......... .......... .......... 15% 50.2M 0s
==> azure-arm.my-example:   1800K .......... .......... .......... .......... .......... 15% 73.3M 0s
==> azure-arm.my-example:   1850K .......... .......... .......... .......... .......... 16% 53.5M 0s
==> azure-arm.my-example:   1900K .......... .......... .......... .......... .......... 16% 51.5M 0s
==> azure-arm.my-example:   1950K .......... .......... .......... .......... .......... 17% 46.0M 0s
==> azure-arm.my-example:   2000K .......... .......... .......... .......... .......... 17% 85.1M 0s
==> azure-arm.my-example:   2050K .......... .......... .......... .......... .......... 18%  249M 0s
==> azure-arm.my-example:   2100K .......... .......... .......... .......... .......... 18%  198M 0s
==> azure-arm.my-example:   2150K .......... .......... .......... .......... .......... 19%  266M 0s
==> azure-arm.my-example:   2200K .......... .......... .......... .......... .......... 19%  151M 0s
==> azure-arm.my-example:   2250K .......... .......... .......... .......... .......... 19%  291M 0s
==> azure-arm.my-example:   2300K .......... .......... .......... .......... .......... 20%  177M 0s
==> azure-arm.my-example:   2350K .......... .......... .......... .......... .......... 20%  305M 0s
==> azure-arm.my-example:   2400K .......... .......... .......... .......... .......... 21%  197M 0s
==> azure-arm.my-example:   2450K .......... .......... .......... .......... .......... 21%  197M 0s
==> azure-arm.my-example:   2500K .......... .......... .......... .......... .......... 22%  269M 0s
==> azure-arm.my-example:   2550K .......... .......... .......... .......... .......... 22%  292M 0s
==> azure-arm.my-example:   2600K .......... .......... .......... .......... .......... 22%  187M 0s
==> azure-arm.my-example:   2650K .......... .......... .......... .......... .......... 23%  274M 0s
==> azure-arm.my-example:   2700K .......... .......... .......... .......... .......... 23%  270M 0s
==> azure-arm.my-example:   2750K .......... .......... .......... .......... .......... 24%  170M 0s
==> azure-arm.my-example:   2800K .......... .......... .......... .......... .......... 24%  243M 0s
==> azure-arm.my-example:   2850K .......... .......... .......... .......... .......... 25%  308M 0s
==> azure-arm.my-example:   2900K .......... .......... .......... .......... .......... 25%  175M 0s
==> azure-arm.my-example:   2950K .......... .......... .......... .......... .......... 25%  294M 0s
==> azure-arm.my-example:   3000K .......... .......... .......... .......... .......... 26%  276M 0s
==> azure-arm.my-example:   3050K .......... .......... .......... .......... .......... 26%  297M 0s
==> azure-arm.my-example:   3100K .......... .......... .......... .......... .......... 27%  182M 0s
==> azure-arm.my-example:   3150K .......... .......... .......... .......... .......... 27%  203M 0s
==> azure-arm.my-example:   3200K .......... .......... .......... .......... .......... 28%  271M 0s
==> azure-arm.my-example:   3250K .......... .......... .......... .......... .......... 28%  221M 0s
==> azure-arm.my-example:   3300K .......... .......... .......... .......... .......... 28%  292M 0s
==> azure-arm.my-example:   3350K .......... .......... .......... .......... .......... 29%  192M 0s
==> azure-arm.my-example:   3400K .......... .......... .......... .......... .......... 29%  253M 0s
==> azure-arm.my-example:   3450K .......... .......... .......... .......... .......... 30%  291M 0s
==> azure-arm.my-example:   3500K .......... .......... .......... .......... .......... 30%  199M 0s
==> azure-arm.my-example:   3550K .......... .......... .......... .......... .......... 31%  198M 0s
==> azure-arm.my-example:   3600K .......... .......... .......... .......... .......... 31%  279M 0s
==> azure-arm.my-example:   3650K .......... .......... .......... .......... .......... 31%  279M 0s
==> azure-arm.my-example:   3700K .......... .......... .......... .......... .......... 32%  166M 0s
==> azure-arm.my-example:   3750K .......... .......... .......... .......... .......... 32% 46.6M 0s
==> azure-arm.my-example:   3800K .......... .......... .......... .......... .......... 33% 56.1M 0s
==> azure-arm.my-example:   3850K .......... .......... .......... .......... .......... 33% 53.8M 0s
==> azure-arm.my-example:   3900K .......... .......... .......... .......... .......... 34% 65.1M 0s
==> azure-arm.my-example:   3950K .......... .......... .......... .......... .......... 34% 32.4M 0s
==> azure-arm.my-example:   4000K .......... .......... .......... .......... .......... 34% 56.9M 0s
==> azure-arm.my-example:   4050K .......... .......... .......... .......... .......... 35% 57.7M 0s
==> azure-arm.my-example:   4100K .......... .......... .......... .......... .......... 35% 64.0M 0s
==> azure-arm.my-example:   4150K .......... .......... .......... .......... .......... 36% 62.5M 0s
==> azure-arm.my-example:   4200K .......... .......... .......... .......... .......... 36% 71.0M 0s
==> azure-arm.my-example:   4250K .......... .......... .......... .......... .......... 37% 57.5M 0s
==> azure-arm.my-example:   4300K .......... .......... .......... .......... .......... 37% 63.6M 0s
==> azure-arm.my-example:   4350K .......... .......... .......... .......... .......... 38% 61.9M 0s
==> azure-arm.my-example:   4400K .......... .......... .......... .......... .......... 38% 54.2M 0s
==> azure-arm.my-example:   4450K .......... .......... .......... .......... .......... 38% 60.8M 0s
==> azure-arm.my-example:   4500K .......... .......... .......... .......... .......... 39% 61.0M 0s
==> azure-arm.my-example:   4550K .......... .......... .......... .......... .......... 39% 63.4M 0s
==> azure-arm.my-example:   4600K .......... .......... .......... .......... .......... 40% 68.2M 0s
==> azure-arm.my-example:   4650K .......... .......... .......... .......... .......... 40% 62.3M 0s
==> azure-arm.my-example:   4700K .......... .......... .......... .......... .......... 41% 64.6M 0s
==> azure-arm.my-example:   4750K .......... .......... .......... .......... .......... 41%  268M 0s
==> azure-arm.my-example:   4800K .......... .......... .......... .......... .......... 41%  245M 0s
==> azure-arm.my-example:   4850K .......... .......... .......... .......... .......... 42%  243M 0s
==> azure-arm.my-example:   4900K .......... .......... .......... .......... .......... 42%  241M 0s
==> azure-arm.my-example:   4950K .......... .......... .......... .......... .......... 43%  307M 0s
==> azure-arm.my-example:   5000K .......... .......... .......... .......... .......... 43%  246M 0s
==> azure-arm.my-example:   5050K .......... .......... .......... .......... .......... 44%  276M 0s
==> azure-arm.my-example:   5100K .......... .......... .......... .......... .......... 44%  245M 0s
==> azure-arm.my-example:   5150K .......... .......... .......... .......... .......... 44%  198M 0s
==> azure-arm.my-example:   5200K .......... .......... .......... .......... .......... 45%  220M 0s
==> azure-arm.my-example:   5250K .......... .......... .......... .......... .......... 45%  286M 0s
==> azure-arm.my-example:   5300K .......... .......... .......... .......... .......... 46%  271M 0s
==> azure-arm.my-example:   5350K .......... .......... .......... .......... .......... 46%  181M 0s
==> azure-arm.my-example:   5400K .......... .......... .......... .......... .......... 47%  261M 0s
==> azure-arm.my-example:   5450K .......... .......... .......... .......... .......... 47%  221M 0s
==> azure-arm.my-example:   5500K .......... .......... .......... .......... .......... 47%  251M 0s
==> azure-arm.my-example:   5550K .......... .......... .......... .......... .......... 48%  287M 0s
==> azure-arm.my-example:   5600K .......... .......... .......... .......... .......... 48%  243M 0s
==> azure-arm.my-example:   5650K .......... .......... .......... .......... .......... 49%  289M 0s
==> azure-arm.my-example:   5700K .......... .......... .......... .......... .......... 49%  119M 0s
==> azure-arm.my-example:   5750K .......... .......... .......... .......... .......... 50%  244M 0s
==> azure-arm.my-example:   5800K .......... .......... .......... .......... .......... 50%  288M 0s
==> azure-arm.my-example:   5850K .......... .......... .......... .......... .......... 50%  133M 0s
==> azure-arm.my-example:   5900K .......... .......... .......... .......... .......... 51%  269M 0s
==> azure-arm.my-example:   5950K .......... .......... .......... .......... .......... 51%  246M 0s
==> azure-arm.my-example:   6000K .......... .......... .......... .......... .......... 52%  312M 0s
==> azure-arm.my-example:   6050K .......... .......... .......... .......... .......... 52%  135M 0s
==> azure-arm.my-example:   6100K .......... .......... .......... .......... .......... 53%  209M 0s
==> azure-arm.my-example:   6150K .......... .......... .......... .......... .......... 53%  205M 0s
==> azure-arm.my-example:   6200K .......... .......... .......... .......... .......... 54%  268M 0s
==> azure-arm.my-example:   6250K .......... .......... .......... .......... .......... 54%  203M 0s
==> azure-arm.my-example:   6300K .......... .......... .......... .......... .......... 54%  146M 0s
==> azure-arm.my-example:   6350K .......... .......... .......... .......... .......... 55% 52.4M 0s
==> azure-arm.my-example:   6400K .......... .......... .......... .......... .......... 55% 50.5M 0s
==> azure-arm.my-example:   6450K .......... .......... .......... .......... .......... 56% 59.1M 0s
==> azure-arm.my-example:   6500K .......... .......... .......... .......... .......... 56% 61.3M 0s
==> azure-arm.my-example:   6550K .......... .......... .......... .......... .......... 57% 55.3M 0s
==> azure-arm.my-example:   6600K .......... .......... .......... .......... .......... 57% 64.7M 0s
==> azure-arm.my-example:   6650K .......... .......... .......... .......... .......... 57% 60.4M 0s
==> azure-arm.my-example:   6700K .......... .......... .......... .......... .......... 58% 70.1M 0s
==> azure-arm.my-example:   6750K .......... .......... .......... .......... .......... 58% 63.8M 0s
==> azure-arm.my-example:   6800K .......... .......... .......... .......... .......... 59% 64.9M 0s
==> azure-arm.my-example:   6850K .......... .......... .......... .......... .......... 59% 64.2M 0s
==> azure-arm.my-example:   6900K .......... .......... .......... .......... .......... 60% 58.4M 0s
==> azure-arm.my-example:   6950K .......... .......... .......... .......... .......... 60% 57.2M 0s
==> azure-arm.my-example:   7000K .......... .......... .......... .......... .......... 60% 55.3M 0s
==> azure-arm.my-example:   7050K .......... .......... .......... .......... .......... 61% 73.7M 0s
==> azure-arm.my-example:   7100K .......... .......... .......... .......... .......... 61% 60.9M 0s
==> azure-arm.my-example:   7150K .......... .......... .......... .......... .......... 62% 65.7M 0s
==> azure-arm.my-example:   7200K .......... .......... .......... .......... .......... 62% 59.7M 0s
==> azure-arm.my-example:   7250K .......... .......... .......... .......... .......... 63% 51.0M 0s
==> azure-arm.my-example:   7300K .......... .......... .......... .......... .......... 63% 53.8M 0s
==> azure-arm.my-example:   7350K .......... .......... .......... .......... .......... 63% 84.7M 0s
==> azure-arm.my-example:   7400K .......... .......... .......... .......... .......... 64%  268M 0s
==> azure-arm.my-example:   7450K .......... .......... .......... .......... .......... 64%  252M 0s
==> azure-arm.my-example:   7500K .......... .......... .......... .......... .......... 65%  247M 0s
==> azure-arm.my-example:   7550K .......... .......... .......... .......... .......... 65%  266M 0s
==> azure-arm.my-example:   7600K .......... .......... .......... .......... .......... 66%  247M 0s
==> azure-arm.my-example:   7650K .......... .......... .......... .......... .......... 66%  289M 0s
==> azure-arm.my-example:   7700K .......... .......... .......... .......... .......... 66%  258M 0s
==> azure-arm.my-example:   7750K .......... .......... .......... .......... .......... 67%  266M 0s
==> azure-arm.my-example:   7800K .......... .......... .......... .......... .......... 67%  290M 0s
==> azure-arm.my-example:   7850K .......... .......... .......... .......... .......... 68%  259M 0s
==> azure-arm.my-example:   7900K .......... .......... .......... .......... .......... 68%  276M 0s
==> azure-arm.my-example:   7950K .......... .......... .......... .......... .......... 69%  244M 0s
==> azure-arm.my-example:   8000K .......... .......... .......... .......... .......... 69%  286M 0s
==> azure-arm.my-example:   8050K .......... .......... .......... .......... .......... 69%  231M 0s
==> azure-arm.my-example:   8100K .......... .......... .......... .......... .......... 70%  325M 0s
==> azure-arm.my-example:   8150K .......... .......... .......... .......... .......... 70%  236M 0s
==> azure-arm.my-example:   8200K .......... .......... .......... .......... .......... 71%  297M 0s
==> azure-arm.my-example:   8250K .......... .......... .......... .......... .......... 71%  126M 0s
==> azure-arm.my-example:   8300K .......... .......... .......... .......... .......... 72%  251M 0s
==> azure-arm.my-example:   8350K .......... .......... .......... .......... .......... 72%  253M 0s
==> azure-arm.my-example:   8400K .......... .......... .......... .......... .......... 73%  288M 0s
==> azure-arm.my-example:   8450K .......... .......... .......... .......... .......... 73%  268M 0s
==> azure-arm.my-example:   8500K .......... .......... .......... .......... .......... 73%  260M 0s
==> azure-arm.my-example:   8550K .......... .......... .......... .......... .......... 74%  245M 0s
==> azure-arm.my-example:   8600K .......... .......... .......... .......... .......... 74%  270M 0s
==> azure-arm.my-example:   8650K .......... .......... .......... .......... .......... 75%  245M 0s
==> azure-arm.my-example:   8700K .......... .......... .......... .......... .......... 75%  284M 0s
==> azure-arm.my-example:   8750K .......... .......... .......... .......... .......... 76%  254M 0s
==> azure-arm.my-example:   8800K .......... .......... .......... .......... .......... 76%  274M 0s
==> azure-arm.my-example:   8850K .......... .......... .......... .......... .......... 76%  288M 0s
==> azure-arm.my-example:   8900K .......... .......... .......... .......... .......... 77%  257M 0s
==> azure-arm.my-example:   8950K .......... .......... .......... .......... .......... 77%  279M 0s
==> azure-arm.my-example:   9000K .......... .......... .......... .......... .......... 78%  244M 0s
==> azure-arm.my-example:   9050K .......... .......... .......... .......... .......... 78%  287M 0s
==> azure-arm.my-example:   9100K .......... .......... .......... .......... .......... 79%  241M 0s
==> azure-arm.my-example:   9150K .......... .......... .......... .......... .......... 79%  301M 0s
==> azure-arm.my-example:   9200K .......... .......... .......... .......... .......... 79% 56.9M 0s
==> azure-arm.my-example:   9250K .......... .......... .......... .......... .......... 80% 57.9M 0s
==> azure-arm.my-example:   9300K .......... .......... .......... .......... .......... 80% 52.0M 0s
==> azure-arm.my-example:   9350K .......... .......... .......... .......... .......... 81% 57.0M 0s
==> azure-arm.my-example:   9400K .......... .......... .......... .......... .......... 81% 49.8M 0s
==> azure-arm.my-example:   9450K .......... .......... .......... .......... .......... 82% 55.3M 0s
==> azure-arm.my-example:   9500K .......... .......... .......... .......... .......... 82% 52.7M 0s
==> azure-arm.my-example:   9550K .......... .......... .......... .......... .......... 82% 43.3M 0s
==> azure-arm.my-example:   9600K .......... .......... .......... .......... .......... 83% 37.8M 0s
==> azure-arm.my-example:   9650K .......... .......... .......... .......... .......... 83% 49.9M 0s
==> azure-arm.my-example:   9700K .......... .......... .......... .......... .......... 84% 89.9M 0s
==> azure-arm.my-example:   9750K .......... .......... .......... .......... .......... 84%  286M 0s
==> azure-arm.my-example:   9800K .......... .......... .......... .......... .......... 85%  168M 0s
==> azure-arm.my-example:   9850K .......... .......... .......... .......... .......... 85%  271M 0s
==> azure-arm.my-example:   9900K .......... .......... .......... .......... .......... 85%  296M 0s
==> azure-arm.my-example:   9950K .......... .......... .......... .......... .......... 86%  256M 0s
==> azure-arm.my-example:  10000K .......... .......... .......... .......... .......... 86%  274M 0s
==> azure-arm.my-example:  10050K .......... .......... .......... .......... .......... 87%  248M 0s
==> azure-arm.my-example:  10100K .......... .......... .......... .......... .......... 87%  280M 0s
==> azure-arm.my-example:  10150K .......... .......... .......... .......... .......... 88%  237M 0s
==> azure-arm.my-example:  10200K .......... .......... .......... .......... .......... 88%  241M 0s
==> azure-arm.my-example:  10250K .......... .......... .......... .......... .......... 88%  288M 0s
==> azure-arm.my-example:  10300K .......... .......... .......... .......... .......... 89%  278M 0s
==> azure-arm.my-example:  10350K .......... .......... .......... .......... .......... 89%  246M 0s
==> azure-arm.my-example:  10400K .......... .......... .......... .......... .......... 90%  288M 0s
==> azure-arm.my-example:  10450K .......... .......... .......... .......... .......... 90%  274M 0s
==> azure-arm.my-example:  10500K .......... .......... .......... .......... .......... 91%  310M 0s
==> azure-arm.my-example:  10550K .......... .......... .......... .......... .......... 91%  262M 0s
==> azure-arm.my-example:  10600K .......... .......... .......... .......... .......... 92%  312M 0s
==> azure-arm.my-example:  10650K .......... .......... .......... .......... .......... 92%  269M 0s
==> azure-arm.my-example:  10700K .......... .......... .......... .......... .......... 92%  292M 0s
==> azure-arm.my-example:  10750K .......... .......... .......... .......... .......... 93%  247M 0s
==> azure-arm.my-example:  10800K .......... .......... .......... .......... .......... 93%  290M 0s
==> azure-arm.my-example:  10850K .......... .......... .......... .......... .......... 94%  255M 0s
==> azure-arm.my-example:  10900K .......... .......... .......... .......... .......... 94%  273M 0s
==> azure-arm.my-example:  10950K .......... .......... .......... .......... .......... 95%  291M 0s
==> azure-arm.my-example:  11000K .......... .......... .......... .......... .......... 95%  255M 0s
==> azure-arm.my-example:  11050K .......... .......... .......... .......... .......... 95%  275M 0s
==> azure-arm.my-example:  11100K .......... .......... .......... .......... .......... 96%  248M 0s
==> azure-arm.my-example:  11150K .......... .......... .......... .......... .......... 96%  283M 0s
==> azure-arm.my-example:  11200K .......... .......... .......... .......... .......... 97%  214M 0s
==> azure-arm.my-example:  11250K .......... .......... .......... .......... .......... 97%  251M 0s
==> azure-arm.my-example:  11300K .......... .......... .......... .......... .......... 98% 83.7M 0s
==> azure-arm.my-example:  11350K .......... .......... .......... .......... .......... 98% 57.0M 0s
==> azure-arm.my-example:  11400K .......... .......... .......... .......... .......... 98% 65.9M 0s
==> azure-arm.my-example:  11450K .......... .......... .......... .......... .......... 99% 69.5M 0s
==> azure-arm.my-example:  11500K .......... .......... .......... .......... .......... 99% 64.9M 0s
==> azure-arm.my-example:  11550K .......... .......... ...                             100% 64.7M=0.1s
==> azure-arm.my-example:
==> azure-arm.my-example: 2021-09-07 12:43:24 (109 MB/s) - ‘downloadazcopy-v10-linux’ saved [11851766/11851766]
==> azure-arm.my-example:
==> azure-arm.my-example: Querying the machine's properties ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmz6h1s3pp3w'
==> azure-arm.my-example:  -> Managed OS Disk   : '/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Compute/disks/pkrosz6h1s3pp3w'
==> azure-arm.my-example: Querying the machine's additional disks properties ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmz6h1s3pp3w'
==> azure-arm.my-example: Powering off machine ...
==> azure-arm.my-example:  -> ResourceGroupName : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> ComputeName       : 'pkrvmz6h1s3pp3w'
==> azure-arm.my-example: Capturing image ...
==> azure-arm.my-example:  -> Compute ResourceGroupName : 'pkr-Resource-Group-z6h1s3pp3w'
==> azure-arm.my-example:  -> Compute Name              : 'pkrvmz6h1s3pp3w'
==> azure-arm.my-example:  -> Compute Location          : 'East US'
==> azure-arm.my-example:  -> Image ResourceGroupName   : 'packerlinux02'
==> azure-arm.my-example:  -> Image Name                : 'myPackerImage2'
==> azure-arm.my-example:  -> Image Location            : 'East US'
==> azure-arm.my-example:
==> azure-arm.my-example: Deleting individual resources ...
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Compute/virtualMachines : 'pkrvmz6h1s3pp3w'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/networkInterfaces : 'pkrniz6h1s3pp3w'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/publicIPAddresses : 'pkripz6h1s3pp3w'
==> azure-arm.my-example: Adding to deletion queue -> Microsoft.Network/virtualNetworks : 'pkrvnz6h1s3pp3w'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Compute/virtualMachines : 'pkrvmz6h1s3pp3w'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/networkInterfaces : 'pkrniz6h1s3pp3w'
==> azure-arm.my-example: Waiting for deletion of all resources...
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/publicIPAddresses : 'pkripz6h1s3pp3w'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvnz6h1s3pp3w'
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkrvnz6h1s3pp3w
==> azure-arm.my-example: Error: network.VirtualNetworksClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="InUseSubnetCannotBeDeleted" Message="Subnet pkrsnz6h1s3pp3w is in use by /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Network/networkInterfaces/pkrniz6h1s3pp3w/ipConfigurations/ipconfig and cannot be deleted. In order to delete the subnet, delete all the resources within the subnet. See aka.ms/deletesubnet." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkrniz6h1s3pp3w
==> azure-arm.my-example: Error: network.InterfacesClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="NicInUse" Message="Network Interface /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Network/networkInterfaces/pkrniz6h1s3pp3w is used by existing resource /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Compute/virtualMachines/pkrvmz6h1s3pp3w. In order to delete the network interface, it must be dissociated from the resource. To learn more, see aka.ms/deletenic." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkripz6h1s3pp3w
==> azure-arm.my-example: Error: network.PublicIPAddressesClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="PublicIPAddressCannotBeDeleted" Message="Public IP address /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Network/publicIPAddresses/pkripz6h1s3pp3w can not be deleted since it is still allocated to resource /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Network/networkInterfaces/pkrniz6h1s3pp3w/ipConfigurations/ipconfig. In order to delete the public IP, disassociate/detach the Public IP address from the resource.  To learn how to do this, see aka.ms/deletepublicip." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvnz6h1s3pp3w'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/networkInterfaces : 'pkrniz6h1s3pp3w'
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/publicIPAddresses : 'pkripz6h1s3pp3w'
==> azure-arm.my-example: Error deleting resource. Will retry.
==> azure-arm.my-example: Name: pkrvnz6h1s3pp3w
==> azure-arm.my-example: Error: network.VirtualNetworksClient#Delete: Failure sending request: StatusCode=0 -- Original Error: Code="InUseSubnetCannotBeDeleted" Message="Subnet pkrsnz6h1s3pp3w is in use by /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Network/networkInterfaces/pkrniz6h1s3pp3w/ipConfigurations/ipconfig and cannot be deleted. In order to delete the subnet, delete all the resources within the subnet. See aka.ms/deletesubnet." Details=[]
==> azure-arm.my-example:
==> azure-arm.my-example: Attempting deletion -> Microsoft.Network/virtualNetworks : 'pkrvnz6h1s3pp3w'
==> azure-arm.my-example:  Deleting -> Microsoft.Compute/disks : '/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/pkr-Resource-Group-z6h1s3pp3w/providers/Microsoft.Compute/disks/pkrosz6h1s3pp3w'
==> azure-arm.my-example: Removing the created Deployment object: 'pkrdpz6h1s3pp3w'
==> azure-arm.my-example:
==> azure-arm.my-example: Cleanup requested, deleting resource group ...
==> azure-arm.my-example: Resource group has been deleted.
Build 'azure-arm.my-example' finished after 4 minutes 50 seconds.

==> Wait completed after 4 minutes 50 seconds

==> Builds finished. The artifacts of successful builds are:
--> azure-arm.my-example: Azure.ResourceManagement.VMImage:

OSType: Linux
ManagedImageResourceGroupName: packerlinux02
ManagedImageName: myPackerImage2
ManagedImageId: /subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Compute/images/myPackerImage2
ManagedImageLocation: East US

and we can check it out by using az vm create on the new image and logging in to verify azcopy exists

builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo03$ az vm create -g packerlinux02 --image myPackerImage2 --name myLinuxDemoMI3 --admin-username azureuser --generate-ssh-keys
It is recommended to use parameter "--public-ip-sku Standard" to create new VM with Standard public IP. Please note that the default public IP used for VM creation will be changed from Basic to Standard in the future.
{
  "fqdns": "",
  "id": "/subscriptions/944c019d-3e46-422b-b63a-86513f147562/resourceGroups/packerlinux02/providers/Microsoft.Compute/virtualMachines/myLinuxDemoMI3",
  "location": "eastus",
  "macAddress": "00-0D-3A-8A-AD-96",
  "powerState": "VM running",
  "privateIpAddress": "10.0.0.5",
  "publicIpAddress": "13.68.171.10",
  "resourceGroup": "packerlinux02",
  "zones": ""
}
builder@DESKTOP-QADGF36:~/Workspaces/packerDemo/demo03$ ssh azureuser@13.68.171.10
The authenticity of host '13.68.171.10 (13.68.171.10)' can't be established.
ECDSA key fingerprint is SHA256:0hoqtKsCzXrjVVvmK59oJeZr6WlVc9UG/yyfSXREAeQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '13.68.171.10' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-1055-azure x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue Sep  7 15:18:24 UTC 2021

  System load:  0.08              Processes:           108
  Usage of /:   8.9% of 28.90GB   Users logged in:     0
  Memory usage: 5%                IP address for eth0: 10.0.0.5
  Swap usage:   0%

 * Super-optimized for small spaces - read how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

   https://ubuntu.com/blog/microk8s-memory-optimisation

39 updates can be applied immediately.
35 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable

New release '20.04.3 LTS' available.
Run 'do-release-upgrade' to upgrade to it.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

azureuser@myLinuxDemoMI3:~$ which azcopy
/usr/bin/azcopy

Cleanup

And always make sure to remove instances when done testing to minimize costs.

$ az vm delete -g packerlinux02 -n myLinuxDemoMI3
Are you sure you want to perform this operation? (y/n): y

Summary

We expanded on our first post about packer by moving from creating infrastructure with the Azure CLI and Portal to using Terraform. We then created both Managed Images and VHD images in Azure and showed how to chain one packer built image to another (building on top of a prior image).

This is actually a very common pattern. Often organizations have a “Blessed” or “Security Approved” image that has the hardening IT SecOps requires. By chaining off this image, it is relatively easy to build a catalogue of packer based images that apply the additional layers of tooling. These images can then be consumed by the developers in your organization inside their deployment tooling/configurations.

Lastly, we covered using an Azure VM to compress the large VHD image to a tgz and transfer it to a desktop (an older Surface Book laptop, actually) then launch it with Hyper-V in Windows 10 Pro.

The patterns we showed will scale to other clouds as well.

packer terraform azure azdo hashi

Have something to add? Feedback? Try our new forums

Isaac Johnson

Isaac Johnson

Cloud Solutions Architect

Isaac is a CSA and DevOps engineer who focuses on cloud migrations and devops processes. He also is a dad to three wonderful daughters (hence the references to Princess King sprinkled throughout the blog).

Theme built by C.S. Rhymes