Scaling on GCP
Resize a Google Compute Engine managed instance group with a small Oban.Pro.Cloud module
built on Req. The project, zone, and group are resolved in init/1, and scale/2 posts the
desired size to the resize endpoint.
def deps do
[
{:req, "~> 0.5"}
]
endThe Module
The Oban.Pro.Cloud.init/1 callback reads the API key from the system environment and leaves the
project, zone, and instance group manager to pass through as options. The Oban.Pro.Cloud.scale/2
callback posts the desired size and returns {:ok, conf} so the scaler can track the response.
defmodule MyApp.GCP do
@behaviour Oban.Pro.Cloud
@impl Oban.Pro.Cloud
def init(opts) do
opts
|> Keyword.put_new(:api_key, System.fetch_env!("GCP_API_KEY"))
|> Map.new()
end
@impl Oban.Pro.Cloud
def scale(desired, conf) do
url =
"https://compute.googleapis.com/compute/v1/projects/#{conf.project_id}/zones/" <>
"#{conf.zone}/instanceGroupManagers/#{conf.instance_group_manager}/resize"
case Req.post(url, params: [size: desired, key: conf.api_key]) do
{:ok, %{status: status}} when status in 200..299 -> {:ok, conf}
{:ok, response} -> {:error, response}
{:error, reason} -> {:error, reason}
end
end
endAn API key keeps the example short, but it only works where Compute Engine accepts one. For
service-account auth, swap the key param for an OAuth token in an authorization header and mint
it however your app already talks to Google.
Using It
Point a scaler at the module and pass the group it should resize:
cloud = {MyApp.GCP, project_id: "my-project", zone: "us-east1-b", instance_group_manager: "workers"}
{DynamicScaler, scalers: [range: 1..5, cloud: cloud]}