azurepowershellterraformazure-virtual-machine

Terraform - Azure - azurerm_virtual_machine_extension - inline Powershell script


I am preparing VM deployment, and on VMs, I need to run some Powershell command lets. I need to change the Postgresql property. I am working on Azure cloud, Terraform deployment has been tested, and works as expected, VM is deployed with all required configurations, but facing some problems with PowerShell commands. I use terraform resource azurerm_virtual_machine_extension, it works when I am trying to install/use one block of code, for example

resource "azurerm_virtual_machine_extension" "start_postgres_service" {
  name                 = "start_postgresql"
  virtual_machine_id   = azurerm_windows_virtual_machine.virtual_machine.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.9"

  settings = <<SETTINGS
 {
  "commandToExecute": "powershell -ExecutionPolicy Unrestricted Start-Service -Name postgresql-x64-16"
 }
SETTINGS
}

I don't want to use storage account and container and .ps1 script file uploaded to storage container, I need to use inline powershell code. My powershell file and terraform clode below.

param (
    [string]$VMUser,
    [string]$VMPassword,
    [string]$VMName
)

$account=".\$VMUser"
$password= "$VMPassword"
$service="name='postgresql-x64-16'"

$svc=Get-WmiObject win32_service -ComputerName "$VMName" -filter $service
$svc.StopService()
$svc.change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
$svc.StartService()
resource "azurerm_virtual_machine_extension" "start_postgres_service" {
  name                 = "start_and_change_postgresql"
  virtual_machine_id   = azurerm_windows_virtual_machine.virtual_machine.id
  publisher            = "Microsoft.Compute"
  type                 = "CustomScriptExtension"
  type_handler_version = "1.9"

  settings = <<SETTINGS
    {
      "commandToExecute": "powershell -Command \\"param([string]`\\$VMUser, [string]`\\$VMPassword, [string]`\\$VMName); `\\$account = '.\\\\' + `\\$VMUser; `\\$password = `\\$VMPassword; `\\$service = 'name=\\\\'postgresql-x64-16\\\\''; `\\$svc = Get-WmiObject win32_service -ComputerName `\\$VMName -filter `\\$service; `\\$svc.StopService(); `\\$svc.change($null,$null,$null,$null,$null,$null,`\\$account,`\\$password,$null,$null,$null); `\\$svc.StartService();\\" -VMUser '${var.vm_user}' -VMPassword '${var.vm_password}' -VMName '${azurerm_windows_virtual_machine.virtual_machine.computer_name}'"
    }
  SETTINGS
}

Appreciated for for all your assistance.


Solution

  • To execute multiple commands without storing the script in a storage account, you can use the inline method, but the best way is to store the script in a storage account or a public repository to run multiple scripts without any conflicts.

    Alternate way you can also use Invoke-AzVMRunCommand in null resource block.

    provider "azurerm" {
      features {}
    }
    
    data "azurerm_virtual_machine" "example" {
      name                = "VenkatVM"
      resource_group_name = "APIM"
    }
    
    resource "azurerm_virtual_machine_extension" "manage_services" {
      name                 = "Extensions"
      virtual_machine_id   = data.azurerm_virtual_machine.example.id
      publisher            = "Microsoft.Compute"
      type                 = "CustomScriptExtension"
      type_handler_version = "1.8"
    
      settings = <<SETTINGS
        {
          "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \\\"Start-Service -Name 'postgresql-x64-16'; Start-Service -Name 'PhoneSvc'; Stop-Service -Name 'Spooler'\\\""
        }
      SETTINGS
    }
    
    

    Terraform apply:

    enter image description here

    Extension has been installed successfully.

    enter image description here

    Service started successfully.

    enter image description here

    To change the PostgreSQL account, you need to connect with psql and then connect to the database. So, it’s not possible directly from PowerShell commands. Refer to the link to switch users in PostgreSQL.