# `GcpCompute.Instance`
[🔗](https://github.com/nyo16/gcp_compute/blob/v0.3.0/lib/gcp_compute/instance.ex#L1)

A Compute Engine instance — both the parsed result of a `get`/`list`, and a
builder (`spec/1`) for the JSON body that `insert` expects.

## Building an insert body

`spec/1` turns friendly options into the verbose Compute JSON, with sane
defaults for a cheap, self-deleting Spot VM:

    {:ok, body} =
      GcpCompute.Instance.spec(
        name: "worker-1",
        zone: "us-central1-a",
        machine_type: "e2-micro",
        spot: true,
        max_run_duration: 3600,
        startup_script: "#!/bin/bash\necho hi > /tmp/ready",
        labels: %{"team" => "platform"}
      )

You can always pass a raw map to `GcpCompute.Instances.insert/3` instead if you
need a field `spec/1` doesn't cover.

# `t`

```elixir
@type t() :: %GcpCompute.Instance{
  created_at: DateTime.t() | nil,
  disks: [GcpCompute.Disk.t()],
  id: String.t() | nil,
  labels: map() | nil,
  machine_type: String.t() | nil,
  name: String.t() | nil,
  network_interfaces: [GcpCompute.NetworkInterface.t()],
  raw: map(),
  scheduling: GcpCompute.Scheduling.t() | nil,
  self_link: String.t() | nil,
  status: String.t() | nil,
  tags: [String.t()],
  zone: String.t() | nil
}
```

# `external_ip`

```elixir
@spec external_ip(t()) :: String.t() | nil
```

The instance's first external (NAT) IP address, if any.

# `from_json`

```elixir
@spec from_json(map()) :: t()
```

Parse a decoded JSON instance map into nested structs (short names, IPs, DateTimes).

# `internal_ip`

```elixir
@spec internal_ip(t()) :: String.t() | nil
```

The instance's first internal IP address, if any.

# `spec`

```elixir
@spec spec(keyword()) :: {:ok, map()} | {:error, GcpCompute.Error.t()}
```

Build (and validate) the JSON body for `instances.insert`.

See the module doc for the full option list. Returns `{:ok, body}` or
`{:error, %GcpCompute.Error{reason: :invalid_spec}}`.

# `spec!`

```elixir
@spec spec!(keyword()) :: map()
```

Same as `spec/1` but raises on invalid options.

# `spot?`

```elixir
@spec spot?(t()) :: boolean()
```

Whether this instance is a Spot VM — i.e. preemptible, and cheap because of it.

Reads `scheduling.provisioningModel`, so it reflects what GCP actually
provisioned rather than what was asked for.

    {:ok, vm} = GcpCompute.get_instance(config, "worker-1")
    GcpCompute.Instance.spot?(vm)
    #=> true

A Spot VM can be preempted at any time; with this library's default
`instanceTerminationAction: "DELETE"` it is then deleted, and
`GcpCompute.Instances.preemption/3` is what tells you afterwards.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
