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"
}