14

I'm using azurerm_virtual_machine_extension to bootstrap some virtual machines in azure.

All examples i've found show using something similar to:

settings = <<SETTINGS
    {   
    "fileUris": [ "https://my.bootstrapscript.com/script.sh}" ],
    "commandToExecute": "bash script.sh"
    }
SETTINGS

While this works, my issue is i'm having to publicly host script for use with fileUris. Is there an option within settings that will allow me to send local file contents from my terraform folder?

Something like:

settings = <<SETTINGS
    {   
    "file": [ ${file("./script.txt")} ],
    "commandToExecute": "bash script.sh"
    }
SETTINGS

Thanks.

4c74356b41
  • 69,186
  • 6
  • 100
  • 141
Mark Pendlebury
  • 173
  • 1
  • 1
  • 7

1 Answers1

33

Yes We Can!

Introduction

In protected_settings, use "script".

Scripts

terraform script

provider "azurerm" {
}

resource "azurerm_virtual_machine_extension" "vmext" {
    resource_group_name     = "${var.resource_group_name}"
    location                = "${var.location}"
    name                    = "${var.hostname}-vmext"

    virtual_machine_name = "${var.hostname}"
    publisher            = "Microsoft.Azure.Extensions"
    type                 = "CustomScript"
    type_handler_version = "2.0"

    protected_settings = <<PROT
    {
        "script": "${base64encode(file(var.scfile))}"
    }
    PROT
}

variables

variable resource_group_name {
    type = string
    default = "ORA"
}

variable location {
    type = string
    default = "eastus"
}

variable hostname {
    type = string
    default = "ora"
}

variable scfile{
    type = string
    default = "yum.bash"
}

bash script

#!/bin/bash

mkdir -p ~/download
cd ~/download
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -ivh epel-release-latest-7.noarch.rpm
yum -y install cowsay
cowsay ExaGridDba

Output

apply

[terraform@terra stackoverflow]$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azurerm_virtual_machine_extension.vmex0 will be created
  + resource "azurerm_virtual_machine_extension" "vmex0" {
      + id                   = (known after apply)
      + location             = "eastus"
      + name                 = "ora-vmext"
      + protected_settings   = (sensitive value)
      + publisher            = "Microsoft.Azure.Extensions"
      + resource_group_name  = "ORA"
      + tags                 = (known after apply)
      + type                 = "CustomScript"
      + type_handler_version = "2.0"
      + virtual_machine_name = "ora"
    }

Plan: 1 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_virtual_machine_extension.vmex0: Creating...
azurerm_virtual_machine_extension.vmex0: Still creating... [10s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [20s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [30s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [40s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [50s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [1m0s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [1m10s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [1m20s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [1m30s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [1m40s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [1m50s elapsed]
azurerm_virtual_machine_extension.vmex0: Still creating... [2m0s elapsed]
azurerm_virtual_machine_extension.vmex0: Creation complete after 2m1s [id=/subscriptions/7fe8a9c3-0812-42e2-9733-3f567308a0d0/resourceGroups/ORA/providers/Microsoft.Compute/virtualMachines/ora/extensions/ora-vmext]

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

stdout on the target

[root@ora ~]# cat /var/lib/waagent/custom-script/download/0/stdout
Preparing...                          ########################################
Updating / installing...
epel-release-7-12                     ########################################
Loaded plugins: langpacks, ulninfo
Resolving Dependencies
--> Running transaction check
---> Package cowsay.noarch 0:3.04-4.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package          Arch             Version                 Repository      Size
================================================================================
Installing:
 cowsay           noarch           3.04-4.el7              epel            42 k

Transaction Summary
================================================================================
Install  1 Package

Total download size: 42 k
Installed size: 77 k
Downloading packages:
Public key for cowsay-3.04-4.el7.noarch.rpm is not installed
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : cowsay-3.04-4.el7.noarch                                     1/1
  Verifying  : cowsay-3.04-4.el7.noarch                                     1/1

Installed:
  cowsay.noarch 0:3.04-4.el7

Complete!

< ExaGridDba >
 ------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Remarks

  1. The script size limit is 262144 bytes base64 encoded, or 196608 bytes.
  2. "#!" determines the interpreter. "#!/bin/python" would start a python script.
  3. These azurerm_virtual_machine_extension parameters are not required:
    • settings
    • fileUris
    • commandToExecute
    • storageAccountName
    • storageAccountKey
  4. protected_settings parameter "script" might not be mentioned in the Terraform documentation. Please refer to Use the Azure Custom Script Extension Version 2 with Linux virtual machines
  5. azurerm_virtual_machine_extension may be used during VM creation, or as a standalone administrative tool.

Conclusion

In Azure VM, it is possible to run a script without referring to a blob storage account.

Brian Fitzgerald
  • 634
  • 7
  • 14
  • Exactly what I need! Thanks – Mark Pendlebury Nov 11 '19 at 08:55
  • 3
    How do you pass arguments to the shell script? I am in the same situation, but my bash script has some arguments to pass. – zeroweb Feb 28 '20 at 03:21
  • 3
    @getvivekv, settings = < – Antony Makaruk Jun 25 '20 at 04:57
  • This doesn't work anymore, as commandToExecute made required – Pavel Pikat Jul 23 '20 at 21:16
  • 3
    @PavelPikat incorrect. commandToExecute is Microsoft.Compute (Windows VMs) whereas Microsoft.Azure.Extensions is Ubuntu/Linux/OtherAzureOS – Lucero79 Sep 16 '20 at 11:56
  • @Lucero79 I think you are mixing many things. Microsoft.Compute is a resource/namespace for VMs (correct), but there's no separation between Windows compute or Linux compute - VMs are generic and can run different images (Windows or Linux), where as extensions exists for both Linux and Window, but there are no specific OS for Azure – Pavel Pikat Oct 09 '20 at 10:11
  • @PavelPikat, sorry, I think it is you who is mistaken, and this is why reading documentation is so important. There is azurerm_virtual_machine which can be any OS, as you say, however, the commandToExecute is native to the Microsoft.Compute namespace extension which ONLY works with Windows OS VMs. There is now a provider differentiation for azurerm_windows_virtual_machine too, to assist in avoiding this confusion moving forward. – Lucero79 Oct 10 '20 at 18:32
  • @Lucero79 any supporting argument available for windows(Microsoft.Compute) same as `script`, I have to execute the PS script without external file access. – user881703 Sep 13 '21 at 05:53