0

below code creates 3 linux ubuntu azure vm's .At the same time i want to execute shell script in these 3 vm's .For this am using the below code but am getting the following error basically am using filebase64 to execute the code but its not working.Could anyone please check it and let me know the issue

            # Resource-1: Azure Resource Group
            resource "azurerm_resource_group" "myrg" {
              name = "${var.resource_group}"
              location = "${var.location}"
            }
            
            # Create Virtual Network
            resource "azurerm_virtual_network" "myvnet" {
              name                = "myvnet-1"
              address_space       = ["10.0.0.0/16"]
              location            = azurerm_resource_group.myrg.location
              resource_group_name = azurerm_resource_group.myrg.name
            }
            
            # Create Subnet
            resource "azurerm_subnet" "mysubnet" {
              
              name                 = "mysubnet-1"
              resource_group_name  = azurerm_resource_group.myrg.name
              virtual_network_name = azurerm_virtual_network.myvnet.name
              address_prefixes     = ["10.0.2.0/24"]
            }
            
            
            #Create Bastion host
            resource "azurerm_subnet" "Azure_Bastion_Subnet" {
              name                 = "AzureBastionSubnet"
              resource_group_name  = azurerm_resource_group.myrg.name
              virtual_network_name = azurerm_virtual_network.myvnet.name
              address_prefixes     = ["10.0.3.0/24"]
            }
            
            #Create Azure Public IP Address
            resource "azurerm_public_ip" "mypublicip" {
             
              count               =  "${var.instance_count}"
              name                = "mypublicip-${count.index}"
              resource_group_name = azurerm_resource_group.myrg.name
              location            = azurerm_resource_group.myrg.location
              allocation_method   = "Static"
              sku                 = "Standard"
              domain_name_label = "app1-vm-${count.index}-${random_string.myrandom.id}"  
            }
            
            
            resource "azurerm_network_interface" "myvmnic" {
              count =  "${var.instance_count}"
              name = "vmnic-${count.index}"
              location = azurerm_resource_group.myrg.location
              resource_group_name = azurerm_resource_group.myrg.name
            
            ip_configuration {
              name = "internal"
              subnet_id = azurerm_subnet.mysubnet.id
              private_ip_address_allocation = "Dynamic"
              public_ip_address_id = element(azurerm_public_ip.mypublicip[*].id, count.index)
              
            }
            }
            
            resource "azurerm_network_security_group" "linux-nsg"{
              name                = "acceptanceTestSecurityGroup1"
              location            = azurerm_resource_group.myrg.location
              resource_group_name = azurerm_resource_group.myrg.name
            
              security_rule {
                name                       = "Allowssh"
                priority                   = 150
                direction                  = "Inbound"
                access                     = "Allow"
                protocol                   = "*"
                source_port_range          = "*"
                destination_port_range     = "*"
                source_address_prefix      = "*"
                destination_address_prefix = "*"
              }
            
              security_rule {
                name                       = "Allow"
                priority                   = 100
                direction                  = "Outbound"
                access                     = "Allow"
                protocol                   = "*"
                source_port_range          = "*"
                destination_port_range     = "*"
                source_address_prefix      = "*"
                destination_address_prefix = "*"
              }
            }
              
            resource "azurerm_subnet_network_security_group_association" "example" {
              subnet_id                 = azurerm_subnet.mysubnet.id
              network_security_group_id = azurerm_network_security_group.linux-nsg.id
            }
            
            data "template_file" "config"{
                template = file("${path.module}/script.sh")
               }
            
            # Resource: Azure Linux Virtual Machine
            resource "azurerm_linux_virtual_machine" "mylinuxvm" {
              count               =  "${var.instance_count}"
              name                = "mylinuxvm-${count.index}"
              computer_name       = "zookeeper-${count.index}" # Hostname of the VM
              resource_group_name = azurerm_resource_group.myrg.name
              location            = azurerm_resource_group.myrg.location
              size                = "Standard_DS1_v2"
              admin_username      = "useradmin"
              #admin_password      = "Solr@12345"
              network_interface_ids = [ element(azurerm_network_interface.myvmnic[*].id, count.index)]
              custom_data  = filebase64(data.template_file.config.rendered)
              disable_password_authentication = true
              admin_ssh_key {
                username   = "useradmin"
                public_key = file("${path.module}/ssh-keys/terraform-azure.pub")
              }
              
               os_disk {
                name = "osdisk${count.index}"
                caching              = "ReadWrite"
                storage_account_type = "Standard_LRS"
              }
            
              source_image_reference {
                publisher = "Canonical"
                offer     = "UbuntuServer"
                sku       = "16.04-LTS"
                version   = "latest"
              }
              connection {
                type = "ssh"
                host = self.public_ip_address
                user = self.admin_username
                private_key = file("${path.module}/ssh-keys/terraform-azure.pem")
               }
            
             } 
            resource "azurerm_public_ip" "bastion_ip" {
              name                = "bastion_ip"
              location            = azurerm_resource_group.myrg.location
              resource_group_name = azurerm_resource_group.myrg.name
              allocation_method   = "Static"
              sku                 = "Standard"
            }
            
            
            resource "azurerm_bastion_host" "bastion_test" {
              name                = "bastion-test"
              location            = azurerm_resource_group.myrg.location
              resource_group_name = azurerm_resource_group.myrg.name
              
            
              ip_configuration {
                name                 = "bastion-configuration"
                subnet_id            = azurerm_subnet.Azure_Bastion_Subnet.id
                public_ip_address_id = azurerm_public_ip.bastion_ip.id
              }
            }
            
       
            
            Error: Invalid function argument
              on main.tf line 125, in resource "azurerm_linux_virtual_machine" "mylinuxvm":
             125:   custom_data  = filebase64(data.template_file.config.rendered)
                ├────────────────
                │ while calling filebase64(path)
                │ data.template_file.config.rendered is "#!/bin/sh\nhost=$(hostname)\nif [ \"$host\" = \"zookeeper-0\" ]\nthen\nmkdir -p 
            ~/zookeeper/zk-server-1\nmkdir -p ~/zookeeper/data/zk1\nmkdir -p ~/zookeeper/log/zk1\n\nelif [ \"$host\" = \"zookeeper-1\" 
            ]\nthen\nmkdir -p ~/zookeeper/zk-server-2\nmkdir -p ~/zookeeper/data/zk2\nmkdir -p ~/zookeeper/log/zk2\necho \"2\" > 
            ~/zookeeper/data/zk2/myid\n\nelif [ \"$host\" = \"zookeeper-2\" ]\nthen\nmkdir -p ~/zookeeper/zk-server-3\nmkdir -p 
            ~/zookeeper/data/zk3\nmkdir -p ~/zookeeper/log/zk3\necho \"3\" > ~/zookeeper/data/zk3/myid\nfi\n\n"
            Invalid value for "path" parameter: no file exists at
            "#!/bin/sh\nhost=$(hostname)\nif [ \"$host\" = \"zookeeper-0\" ]\nthen\nmkdir
            -p ~/zookeeper/zk-server-1\nmkdir -p ~/zookeeper/data/zk1\nmkdir -p
            ~/zookeeper/log/zk1\n\nelif [ \"$host\" = \"zookeeper-1\" ]\nthen\nmkdir -p
            ~/zookeeper/zk-server-2\nmkdir -p ~/zookeeper/data/zk2\nmkdir -p
            ~/zookeeper/log/zk2\necho \"2\" > ~/zookeeper/data/zk2/myid\n\nelif [
            \"$host\" = \"zookeeper-2\" ]\nthen\nmkdir -p ~/zookeeper/zk-server-3\nmkdir
            -p ~/zookeeper/data/zk3\nmkdir -p ~/zookeeper/log/zk3\necho \"3\" >
            ~/zookeeper/data/zk3/myid\nfi\n\n"; this function works only with files that
            are distributed as part of the configuration source code, so if this file
            will be created by a resource in this configuration you must instead obtain
            this result from an attribute of that resource.
            Error: Invalid function argument
              on main.tf line 125, in resource "azurerm_linux_virtual_machine" "mylinuxvm":
             125:   custom_data  = filebase64(data.template_file.config.rendered)
                ├────────────────
                │ while calling filebase64(path)
                │ data.template_file.config.rendered is "#!/bin/sh\nhost=$(hostname)\nif [ \"$host\" = \"zookeeper-0\" ]\nthen\nmkdir -p 
            ~/zookeeper/zk-server-1\nmkdir -p ~/zookeeper/data/zk1\nmkdir -p ~/zookeeper/log/zk1\n\nelif [ \"$host\" = \"zookeeper-1\" 
            ]\nthen\nmkdir -p ~/zookeeper/zk-server-2\nmkdir -p ~/zookeeper/data/zk2\nmkdir -p ~/zookeeper/log/zk2\necho \"2\" > 
            ~/zookeeper/data/zk2/myid\n\nelif [ \"$host\" = \"zookeeper-2\" ]\nthen\nmkdir -p ~/zookeeper/zk-server-3\nmkdir -p 
            ~/zookeeper/data/zk3\nmkdir -p ~/zookeeper/log/zk3\necho \"3\" > ~/zookeeper/data/zk3/myid\nfi\n\n"
            Invalid value for "path" parameter: no file exists at
            "#!/bin/sh\nhost=$(hostname)\nif [ \"$host\" = \"zookeeper-0\" ]\nthen\nmkdir
            -p ~/zookeeper/zk-server-1\nmkdir -p ~/zookeeper/data/zk1\nmkdir -p
            ~/zookeeper/log/zk1\n\nelif [ \"$host\" = \"zookeeper-1\" ]\nthen\nmkdir -p
            ~/zookeeper/zk-server-2\nmkdir -p ~/zookeeper/data/zk2\nmkdir -p
            ~/zookeeper/log/zk2\necho \"2\" > ~/zookeeper/data/zk2/myid\n\nelif [
            \"$host\" = \"zookeeper-2\" ]\nthen\nmkdir -p ~/zookeeper/zk-server-3\nmkdir
            -p ~/zookeeper/data/zk3\nmkdir -p ~/zookeeper/log/zk3\necho \"3\" >
            ~/zookeeper/data/zk3/myid\nfi\n\n"; this function works only with files that
            are distributed as part of the configuration source code, so if this file
            will be created by a resource in this configuration you must instead obtain
            this result from an attribute of that resource.
            Error: Invalid function argument
              on main.tf line 125, in resource "azurerm_linux_virtual_machine" "mylinuxvm":
             125:   custom_data  = filebase64(data.template_file.config.rendered)
                ├────────────────
                │ while calling filebase64(path)
                │ data.template_file.config.rendered is "#!/bin/sh\nhost=$(hostname)\nif [ \"$host\" = \"zookeeper-0\" ]\nthen\nmkdir -p 
            ~/zookeeper/zk-server-1\nmkdir -p ~/zookeeper/data/zk1\nmkdir -p ~/zookeeper/log/zk1\n\nelif [ \"$host\" = \"zookeeper-1\" 
            ]\nthen\nmkdir -p ~/zookeeper/zk-server-2\nmkdir -p ~/zookeeper/data/zk2\nmkdir -p ~/zookeeper/log/zk2\necho \"2\" > 
            ~/zookeeper/data/zk2/myid\n\nelif [ \"$host\" = \"zookeeper-2\" ]\nthen\nmkdir -p ~/zookeeper/zk-server-3\nmkdir -p 
            ~/zookeeper/data/zk3\nmkdir -p ~/zookeeper/log/zk3\necho \"3\" > ~/zookeeper/data/zk3/myid\nfi\n\n"
            Invalid value for "path" parameter: no file exists at
            "#!/bin/sh\nhost=$(hostname)\nif [ \"$host\" = \"zookeeper-0\" ]\nthen\nmkdir
            -p ~/zookeeper/zk-server-1\nmkdir -p ~/zookeeper/data/zk1\nmkdir -p
            ~/zookeeper/log/zk1\n\nelif [ \"$host\" = \"zookeeper-1\" ]\nthen\nmkdir -p
            ~/zookeeper/zk-server-2\nmkdir -p ~/zookeeper/data/zk2\nmkdir -p
            ~/zookeeper/log/zk2\necho \"2\" > ~/zookeeper/data/zk2/myid\n\nelif [
            \"$host\" = \"zookeeper-2\" ]\nthen\nmkdir -p ~/zookeeper/zk-server-3\nmkdir
            -p ~/zookeeper/data/zk3\nmkdir -p ~/zookeeper/log/zk3\necho \"3\" >
            ~/zookeeper/data/zk3/myid\nfi\n\n"; this function works only with files that
            are distributed as part of the configuration source code, so if this file
            will be created by a resource in this configuration you must instead obtain
            this result from an attribute of that resource.
2
  • There is no script at the location you are pointing the data source to. Commented Jan 9, 2023 at 19:45
  • script is there in the same location Commented Jan 9, 2023 at 20:00

1 Answer 1

1

Delete this block

data "template_file" "config" {
  template = file("${path.module}/script.sh")
}

and Replace below code

# Resource: Azure Linux Virtual Machine
resource "azurerm_linux_virtual_machine" "mylinuxvm" {
[...
custom_data  = filebase64(data.template_file.config.rendered)
...]
}

with

# Resource: Azure Linux Virtual Machine
resource "azurerm_linux_virtual_machine" "mylinuxvm" {
[...
custom_data  = filebase64("${path.module}/script.sh")
...]
}

As an reference your result would be

  # azurerm_linux_virtual_machine.mylinuxvm[0] will be created
  + resource "azurerm_linux_virtual_machine" "mylinuxvm" {
      + admin_username                  = "useradmin"
      + allow_extension_operations      = true
      + computer_name                   = "zookeeper-0"
      + custom_data                     = (sensitive value)
      + disable_password_authentication = true
      + extensions_time_budget          = "PT1H30M"
      + id                              = (known after apply)
      + location                        = "westeurope"
      + max_bid_price                   = -1
      + name                            = "mylinuxvm-0"
      + network_interface_ids           = (known after apply)
      + patch_assessment_mode           = "ImageDefault"
      + patch_mode                      = "ImageDefault"
      + platform_fault_domain           = -1
      + priority                        = "Regular"
      + private_ip_address              = (known after apply)
      + private_ip_addresses            = (known after apply)
      + provision_vm_agent              = true
      + public_ip_address               = (known after apply)
      + public_ip_addresses             = (known after apply)
      + resource_group_name             = "rg-kv-stackoverflow"
      + size                            = "Standard_DS1_v2"
      + virtual_machine_id              = (known after apply)
[...]

Edited

script I have used to validate

Please check your script also if it works properly. You could verify this by checking the /var/log/cloud-init-output.log file

#!/bin/bash

printf "Hello World"
mkdir -p /tmp/user-data

Logs from cloud-init-output.log

Cloud-init v. 21.1-19-gbad84ad4-0ubuntu1~16.04.2 running 'modules:config' at Tue, 10 Jan 2023 10:59:16 +0000. Up 40.04 seconds.
Hello WorldCloud-init v. 21.1-19-gbad84ad4-0ubuntu1~16.04.2 running 'modules:final' at Tue, 10 Jan 2023 10:59:32 +0000. Up 56.18 seconds.

Execution of script

  • user-data directory is created.
azureadmin@zookeeper-0:~$ ls -l /tmp
total 8
drwx------ 3 root root 4096 Jan 10 10:58 systemd-private-1ff50958c212495f8f02a9d123bf4cac-systemd-timesyncd.service-Wcs89v
drwxr-xr-x 2 root root 4096 Jan 10 10:59 user-data

Additional background

Custom data is made available to the VM during first startup or setup, which is called provisioning. If your machine was already created and then you are using custom data in that case you have to do additional steps. Refer to https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data

Sign up to request clarification or add additional context in comments.

2 Comments

i have tried this method also but the code is just creating vm's it is not executing the shell script urceGroups/myrg/providers/Microsoft.Compute/virtualMachines/mylinuxvm-0] azurerm_linux_virtual_machine.mylinuxvm[2]: Creation complete after 57s [id=/subscriptions/72fe83f9-13d1-423d-84c7-0a2b3996813d/reso urceGroups/myrg/providers/Microsoft.Compute/virtualMachines/mylinuxvm-2] azurerm_linux_virtual_machine.mylinuxvm[1]: Creation complete after 59s [ Apply complete! Resources: 3 added, 0 changed, 3 destroyed.
updated my answer , kindly check your script and cloud-init-output.log file for details

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.