GcpCompute (GcpCompute v0.2.0)

Copy Markdown View Source

Spawn and manage Google Compute Engine instances over the REST API.

Why REST?

The Compute Engine API is REST/JSON only — it has no gRPC endpoint. This library talks to it with Req; there is no connection pool or supervised process to run. A GcpCompute.Config is the only handle you pass around.

Quickstart

# 1. Mint tokens with Goth (or any GcpCompute.TokenProvider)
children = [{Goth, name: MyApp.Goth}]

# 2. Build a config (do this once, reuse it)
{:ok, config} =
  GcpCompute.Config.production(
    project: "my-project",
    zone: "us-central1-a",
    goth: MyApp.Goth
  )

# 3. Spawn a cheap, self-deleting Spot VM and wait for it
{:ok, instance} =
  GcpCompute.insert_instance_and_wait(config,
    name: "worker-1",
    machine_type: "e2-micro",
    spot: true,
    max_run_duration: 3600,
    startup_script: "#!/bin/bash\necho ready > /tmp/ready"
  )

GcpCompute.Instance.external_ip(instance)
#=> "34.x.x.x"

# 4. Tear it down
{:ok, _op} = GcpCompute.delete_instance_and_wait(config, "worker-1")

The functions here are thin wrappers over GcpCompute.Instances and GcpCompute.Operations; reach for those modules directly for the full surface.

Summary

Functions

clear_config(otp_app, key \\ :gcp_compute)

Drop the cached config for {otp_app, key} so the next config/2 re-reads env.

Returns :ok whether or not an entry was cached. See config/2 for the caching caveat (:persistent_term writes trigger a global GC).

config(otp_app, key \\ :gcp_compute)

Load (and cache) a config from application env.

# config :my_app, :gcp_compute, project: "p", zone: "...", token_provider: {...}
{:ok, config} = GcpCompute.config(:my_app)

The result is memoized in :persistent_term on the first successful load and reused on every later call. Caching is first-write-wins with no invalidation: once cached, later changes to the application env are ignored. Only successful loads are cached — an invalid env returns its {:error, _} without caching, so it is re-read next call. To force a reload after reconfiguring at runtime, call clear_config/2 first. (:persistent_term writes trigger a global GC, so treat clearing as a rare operation, not a per-request one.)

delete_instance(config, name, opts \\ [])

See GcpCompute.Instances.delete/3.

delete_instance_and_wait(config, name, opts \\ [])

See GcpCompute.Instances.delete_and_wait/3.

from_env(app, key)

See GcpCompute.Config.from_env/2.

get_instance(config, name, opts \\ [])

See GcpCompute.Instances.get/3.

insert_instance(config, instance, opts \\ [])

See GcpCompute.Instances.insert/3.

insert_instance_and_wait(config, instance, opts \\ [])

See GcpCompute.Instances.insert_and_wait/3.

launch(config, name, opts \\ [])

Spawn an instance and wait until it's running.

Sugar over insert_instance_and_wait/3: the name is lifted out, and spec options (machine_type, spot, …) are auto-separated from call options (:zone, :request_id, :timeout).

{:ok, vm} = GcpCompute.launch(config, "worker-1", machine_type: "e2-micro", spot: true)

list_instances(config, opts \\ [])

See GcpCompute.Instances.list/2.

list_instances_page(config, opts \\ [])

See GcpCompute.Instances.list_page/2.

local(opts)

See GcpCompute.Config.local/1.

new(opts)

See GcpCompute.Config.new/1.

production(opts)

See GcpCompute.Config.production/1.

start_instance(config, name, opts \\ [])

See GcpCompute.Instances.start/3.

stop_instance(config, name, opts \\ [])

See GcpCompute.Instances.stop/3.

terminate(config, name, opts \\ [])

Delete an instance and wait for it to be gone. Returns :ok.

wait_for_operation(config, operation, opts \\ [])

See GcpCompute.Operations.poll_until_done/3.