banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Cloud

banshee/cloud-collection/cloud/google/https/

compute-instances

The status of each Compute Engine instance of a Google Cloud project, every zone at once, by the Compute Engine API.

  • cloud
  • google
  • google-cloud
  • gcp
  • compute-engine
  • instances
  • https
  • api

by banshee0 installations1 version

v1Latest

Published on October 27, 2026. First version.

Keen 1.0.0 · 73 lines
// The Compute Engine instances of a Google Cloud project, every zone at once, by the Compute Engine API with a
// service account: the status of each instance.
// Reads POST https://oauth2.googleapis.com/token by google.token, then GET
// https://compute.googleapis.com/compute/v1/projects/<project>/aggregated/instances, page after page.
need('protocol:http');
need('protocol:google');
$project = variable('google:project', 'text', array(
    'label' => 'Project',
    'help'  => 'The ID of the Google Cloud project, as the console writes it under Project ID: my-project-123456.',
));

per('instance', 'Instances');
output('status', 'text', array('label' => 'Status', 'per' => 'instance'));

watch.expect('not-running', 'Instance not running', 'status', array('critical' => array('running'), 'for' => '2 runs'));
watch.missing('missing', 'Instance missing', 'status', array('enabled' => false));

// The access token of the service account for this scope, asked by google.token and kept in the cache,
// encrypted on the poller, fifty minutes, under the hour Google gives it.
function access_token($scope) {
    if (cache.has('token')) {
        return cache.get('token');
    }
    $token = google.token($scope);
    cache.set('token', $token, 3000);
    return $token;
}

// One GET on a Google Cloud API with the token kept in the cache; a token Google no longer takes answers 401,
// and a new one is asked for, once.
function google_get($url, $scope, $what) {
    $answer = http.get($url, headers=array('Authorization' => 'Bearer ' . access_token($scope)));
    if ($answer['status'] == 401) {
        cache.delete('token');
        $answer = http.get($url, headers=array('Authorization' => 'Bearer ' . access_token($scope)));
    }
    if ($answer['status'] == 403) {
        fail('misconfigured', 'The service account may not read ' . $what . ', code 403',
            'Check its role on the project, and that the API is enabled on the project.');
    }
    if ($answer['status'] == 400 || $answer['status'] == 404) {
        fail('misconfigured', 'Google Cloud refuses to read ' . $what . ', code ' . $answer['status'],
            'Check the project and the names set on the probe.');
    }
    if ($answer['status'] != 200) {
        fail('unreachable', 'Google Cloud answers the reading of ' . $what . ' with code ' . $answer['status']);
    }
    return json.read($answer['body']);
}

// {"items": {"zones/europe-west1-b": {"instances": [{"name": "web-1", "status": "RUNNING", "zone":
// "https://…/zones/europe-west1-b", …}]}, "zones/us-central1-a": {"warning": {"code": "NO_RESULTS_ON_PAGE", …}}},
// "nextPageToken": "…"}: a scope per zone, with its instances or a warning that it has none.
$base = 'https://compute.googleapis.com/compute/v1/projects/' . url.encode($project) . '/aggregated/instances';
$token = '';
while (true) {
    $url = $base;
    if ($token != '') {
        $url = $base . '?' . url.query(array('pageToken' => $token));
    }
    $page = google_get($url, 'https://www.googleapis.com/auth/compute.readonly', 'the Compute Engine instances');
    // An instance is named <zone>/<name>: a name is unique in its zone only.
    foreach (list.get($page, 'items', array()) as $scope => $scoped) {
        $zone = text.split($scope, '/');
        foreach (list.get($scoped, 'instances', array()) as $instance) {
            value('status', text.lower($instance['status']), $zone[list.count($zone) - 1] . '/' . $instance['name']);
        }
    }
    $token = list.get($page, 'nextPageToken', '');
    if ($token == '') {
        break;
    }
}