Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Terraform's file provisioner to copy from my local machine onto a VM?

I'm new to Terraform and have so far managed to get a basic VM (plus Resource Manager trimmings) up and running on Azure. The next task I have in mind is to have Terraform copy a file from my local machine into the newly created instance. Ideally I'm after a solution where the file will be copied each time the apply command is run.

I feel like I'm pretty close but so far I just get endless "Still creating..." statements once I apply (the file is 0kb so after a couple of mins it feels safe to give up).

So far, this is what I've got (based on this code): https://stackoverflow.com/a/37866044/4941009

Network

resource "azurerm_public_ip" "pub-ip" {
    name = "PublicIp"
    location = "${var.location}"
    resource_group_name = "${azurerm_resource_group.rg.name}"
    public_ip_address_allocation = "Dynamic"
    domain_name_label = "${var.hostname}"
}

VM

resource "azurerm_virtual_machine" "vm" {
  name                  = "${var.hostname}"
  location              = "${var.location}"
  resource_group_name   = "${azurerm_resource_group.rg.name}"
  vm_size               = "${var.vm_size}"
  network_interface_ids = ["${azurerm_network_interface.nic.id}"]

  storage_image_reference {
    publisher = "${var.image_publisher}"
    offer     = "${var.image_offer}"
    sku       = "${var.image_sku}"
    version   = "${var.image_version}"
  }

  storage_os_disk {
    name          = "${var.hostname}osdisk1"
    vhd_uri       = "${azurerm_storage_account.stor.primary_blob_endpoint}${azurerm_storage_container.cont.name}/${var.hostname}osdisk.vhd"
    os_type       = "${var.os_type}"
    caching       = "ReadWrite"
    create_option = "FromImage"
  }

  os_profile {
    computer_name  = "${var.hostname}"
    admin_username = "${var.admin_username}"
    admin_password = "${var.admin_password}"
  }

  os_profile_windows_config {
    provision_vm_agent = true
  }

  boot_diagnostics {
    enabled     = true
    storage_uri = "${azurerm_storage_account.stor.primary_blob_endpoint}"
  }

  tags {
      environment = "${var.environment}"
  }
}

File Provisioner

resource "null_resource" "copy-test-file" {

  connection {
    type     = "ssh"
    host     = "${azurerm_virtual_machine.vm.ip_address}"
    user     = "${var.admin_username}"
    password = "${var.admin_password}"
  }

  provisioner "file" {
    source      = "test.txt"
    destination = "/tmp/test.txt"
  }

}

As an aside, if I pass incorrect login details to the provisioner (ie rerun this after the VM has already been created and supply a different password to the provisioner) the behaviour is the same. Can anyone suggest where I'm going wrong?

like image 557
EmmaO91 Avatar asked Feb 01 '18 16:02

EmmaO91


People also ask

What Provisioner can you use to that invokes a command on the machine that runs Terraform CLI?

»local-exec Provisioner. The local-exec provisioner invokes a local executable after a resource is created. This invokes a process on the machine running Terraform, not on the resource.

What is remote Provisioner?

The remote-exec provisioner invokes a script on a remote resource after it is created. This can be used to run a configuration management tool, bootstrap into a cluster, etc. To invoke a local process, see the local-exec provisioner instead.

What is provider and Provisioner in Terraform?

Provider development teams often prioritize features based on interest, so opening an issue is a way to record your interest in the feature. Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction.


2 Answers

I eventually got this working. Honestly, I kind of forgot about this question so I can't remember what my exact issue was, the example below though seems to work on my instance:

resource "null_resource" remoteExecProvisionerWFolder {

  provisioner "file" {
    source      = "test.txt"
    destination = "/tmp/test.txt"
  }

  connection {
    host     = "${azurerm_virtual_machine.vm.ip_address}"
    type     = "ssh"
    user     = "${var.admin_username}"
    password = "${var.admin_password}"
    agent    = "false"
  }
}

So it looks like the only difference here is the addition of agent = "false". This would make some sense as there's only one SSH authentication agent for windows and it's probable I hadn't explicitly specified to use that agent before. However it could well be that I ultimately changed something elsewhere in the configuration. Sorry future people for not being much help on this one.

like image 119
EmmaO91 Avatar answered Oct 13 '22 09:10

EmmaO91


FYI, windows instances you can connect via type winrm

resource "null_resource" "provision_web" {

  connection {
    host     = "${azurerm_virtual_machine.vm.ip_address}"
    type     = "winrm"
    user     = "alex"
    password = "alexiscool1!"
  }

  provisioner "file" {
    source      = "path/to/folder"
    destination = "C:/path/to/destination"
  }

}
like image 28
Alex Bevan Avatar answered Oct 13 '22 08:10

Alex Bevan