Option 1 - use the metadata_startup_script file attribute

Though simple, the downside of this technique is that the instance is deleted and recreated whenever the script is changed (as opposed to Option 2 below, where only the script is re-run).

resource "google_compute_instance" "default" {

  name         = "test-metadata"

  machine_type = "n1-standard-1"

  zone         = "us-west1-a"

  metadata_startup_script = "echo hi > ./test.txt"

  tags = ["foo", "bar"]

  boot_disk {

    initialize_params {

      image = "debian-cloud/debian-9"

    }
  }

  // Local SSD disk

  scratch_disk {
    interface = "SCSI"
  }

  network_interface {
    network = "default"
    access_config {
      // Ephemeral IP
    }
  }
}

Option 2 - Use a key value pair inside of the metadata code block (note the dash in startup-script as opposed to an underscore).

locals {
    instance1_bootstrap = templatefile("${path.module}/bootstrap.tpl")
}

resource "google_compute_instance_from_template" "f5-instance-1" {
metadata = {

              startup-script = "local.instance1_bootstrap "
             foo = "bar"
     }
}

One can also pass your startup script by placing it in a metadata key with the name "startup_script" so depending on how you pass it, you get a different behavior. If you pass it via a metadata key, any changes cause the script to be rerun.

Viewing the metadata values on a running Compute Instance

Read this post to view metadata values on a running compute instance

Quick Recap to View the Compute Instance metadata
user@myinstance:~$ curl http://metadata/computeMetadata/v1/instance/attributes/foo -H “Metadata-Flavor: Google”
bar

YAML based User Data

For Custom Appliances, look at their own Cloud Init module documentation. e.g. F5 Cloud Init (YAML configuration)

gcloud compute instances create example-instance --metadata-from-file startup-script=myuserdata.yaml

On Windows

You would have a slightly different syntax to pass in  a windows shell command.

 metadata = {
    windows-startup-script-cmd = "net user /add devuser Abc123123 & net localgroup administrators devuser /add"
  }

To load a startup script from a URL

resource "google_compute_instance_template" "demo" {
  name                    = "test"
  description             = "test"
  machine_type            = "n1-standard-2"

  metadata = {
    startup-script-url = "gs://mygcpbucket/bootstrap.sh"
  }

Summary

Just like AWS EC2 supports custom scripts (bash on linux) to be passed in via a user_data attribute, GCP offers a couple of ways to pass in something similar - using a startup_script passed in as metadata.

There are two variations of this  metadata - the startup-script can be an additional metadata attribute- or it can be a standalone parameter that takes in a file name (or a raw script), as  shown above.

  • The compute_instance metadata attribute causes existing instances to be updated in place when values change.
  •   In contrast, the use of the metadata_startup_script attribute causes Terraform to delete and re-create the instances.

Need Help?

Need help with your GCP efforts? Start the conversation today.