GcpCompute.Instance.spec/1 turns a friendly keyword list into the (verbose)
Compute instances.insert JSON body, with cheap Spot VM defaults. You pass
that keyword list straight to GcpCompute.Instances.insert/3 /
insert_and_wait/3, which build and validate it for you.
Options
| Option | Default | Notes |
|---|---|---|
:name | — (required) | Instance name (RFC1035). |
:zone | the config's :zone | Injected automatically; override per call. |
:machine_type | "e2-micro" | Short name, or a full zones/.../machineTypes/... URL. |
:source_image | projects/debian-cloud/global/images/family/debian-12 | Boot disk image. |
:disk_size_gb | 10 | Boot disk size. |
:spot | true | true → SPOT, no auto-restart, DELETE on termination. |
:max_run_duration | nil | Seconds. Hard server-side TTL (scheduling.maxRunDuration). |
:external_ip | true | Attach an ephemeral external IP (ONE_TO_ONE_NAT). |
:startup_script | nil | Shell script injected as startup-script metadata. |
:metadata | %{} | Extra metadata key/values. |
:labels | %{} | Resource labels (great for ownership/cost attribution). |
:tags | [] | Network tags (firewall targeting). |
:network | "global/networks/default" | Network URL. |
:subnetwork | nil | Subnetwork URL. |
:service_account | nil | Service-account email to attach. |
:scopes | ["https://www.googleapis.com/auth/cloud-platform"] | Scopes for the service account. |
A cheap, self-deleting Spot VM (the default)
GcpCompute.insert_instance_and_wait(config,
name: "worker-1",
machine_type: "e2-micro",
max_run_duration: 3600
)produces scheduling equivalent to:
{
"provisioningModel": "SPOT",
"automaticRestart": false,
"instanceTerminationAction": "DELETE",
"maxRunDuration": { "seconds": 3600 }
}A standard, internal-only VM
GcpCompute.insert_instance(config,
name: "db-1",
machine_type: "n2-standard-4",
spot: false,
external_ip: false,
disk_size_gb: 100
)Injecting tooling via startup script
startup = """
#!/bin/bash
apt-get update && apt-get install -y docker.io
docker run -d --restart=always ghcr.io/me/scenario:latest
"""
GcpCompute.insert_instance(config,
name: "scenario-1",
machine_type: "e2-standard-2",
startup_script: startup,
labels: %{"scenario" => "web-101"},
tags: ["scenario"]
)Attaching a service account
GcpCompute.insert_instance(config,
name: "uploader-1",
machine_type: "e2-small",
service_account: "uploader@my-project.iam.gserviceaccount.com",
scopes: ["https://www.googleapis.com/auth/devstorage.read_write"]
)Building the body separately
spec/1 returns the body so you can inspect or tweak it:
{:ok, body} = GcpCompute.Instance.spec(name: "w", zone: "us-central1-a", machine_type: "e2-micro")Escape hatch: a raw body
Need a field spec/1 doesn't model (GPUs, multiple disks, confidential compute)?
Pass a raw Compute API body map straight to insert/3 — it's used verbatim:
GcpCompute.Instances.insert(config, %{
"name" => "gpu-1",
"machineType" => "zones/us-central1-a/machineTypes/a2-highgpu-1g",
"guestAccelerators" => [%{"acceleratorType" => "...", "acceleratorCount" => 1}],
"disks" => [%{"boot" => true, "initializeParams" => %{"sourceImage" => "..."}}],
"networkInterfaces" => [%{"network" => "global/networks/default"}]
})