Doing the same with the Ubuntu cloud OVA's and I've found a little bit of a workaround on this. It's not ideal, as it involves a reboot, meaning you need a local-exec
provisioner to detect when the instance is actually finished, but it works.
Say you have two yaml files that you're using for userdata - the first that you're passing with vApp Properties named vapp-userdata.yaml
and then the second you're passing for the VMware datasource named guest-userdata.yaml
Something like this in Terraform
vapp {
properties = {
user-data = base64encode(data.template_file.vapp_userdata[count.index].rendered)
}
}
extra_config = {
"guestinfo.metadata" = base64encode(data.template_file.guest-metadata[count.index].rendered)
"guestinfo.metadata.encoding" = "base64"
"guestinfo.userdata" = base64encode(data.template_file.userdata.rendered)
"guestinfo.userdata.encoding" = "base64"
}
In your vapp-userdata.yaml
have a write_file
action that overwrites the current datasource definitions and removes OVF
as you've already reached that point.
write_files:
- path: /etc/cloud/cloud.cfg.d/90_dpkg.cfg
owner: root:root
permissions: "0644"
content: |
datasource_list: [ VMware, None ]
Then at the bottom finish with a reboot
power_state:
timeout: 600
mode: reboot
When the VM reboots after that last command, it will read in the VMware
datasource as defined in the new cloud-init config and will process your guest-userdata.yaml
and metadata.yaml
if you've defined that too.
As for detecting when it's finished, I'm still trying to figure out the best way of doing that. The easy way is you start nc -l 12345
at the end of guest-userdata.yaml
and have a local provisioner that proceeds when it can connect to tcp/12345
, but that leaves you with a netcat listener open on tcp/12345
which is less than ideal.
If you find a better way, reply :)
Edit
There's absolutely going to be a better way of doing this, but...
At the bottom of guest-userdata.yaml
runcmd:
- mkdir -p /mnt/sharedfolder
- sysctl -w vm.overcommit_memory=1
- sysctl -w kernel.panic=10
- sysctl -w kernel.panic_on_oops=1
- curl https://releases.rancher.com/install-docker/${docker_version}.sh | sh
- usermod -aG docker ubuntu
- nc -l 1234 & ncpid=$! #start nc and get PID
- sleep 20
- kill $ncpid #kill PID once Terraform has had time to connect
Then as a provisioner at the end of your .tf
file
provisioner "local-exec" {
# Wait for cloud-init userdata cmds
# Netcat: z (scan port only), w1 (wait 1 second)
command = "count=0; until $(nc -zw1 ${self.default_ip_address} 1234); do sleep 1; count=`expr $count + 1`; done"
}