Ozan Temel
Ozan Temel

Reputation: 65

How to list running instances on Google Cloud Platform with Go

I'm trying to learn Go by managing Google Cloud Platform. I didn't understand how to use related functions about Compute. The goal is listing instances with some go code.

This is https://godoc.org/google.golang.org/api/compute/v1#InstancesService.List the related function.

func (r *InstancesService) List(project string, zone string) *InstancesListCall

There are two structs, InstancesService and InstancesListCall

As far as i understand i should define these structs but it's not clear the things should be defined in the structs. I've searched for examples but many of them using rest calls instead of golang api. Have any idea how to list instances with go?

Upvotes: 0

Views: 4385

Answers (3)

Bora Özkan
Bora Özkan

Reputation: 83

You can also use AggregatedList and cloud cred in golang and can retrieve all instance information

package main

import (
"context"
"flag"
"fmt"
"log"
"github.com/binxio/gcloudconfig"
"golang.org/x/oauth2/google"
"google.golang.org/api/compute/v1"
"google.golang.org/api/option"
)

func main() {
//gcp session
var credentials *google.Credentials

name := flag.String("configuration", "", "`kunets` of the configuration to use")
project := flag.String("project", "", "`kunets` of the project to query")
flag.Parse()

credentials, _ = gcloudconfig.GetCredentials(*name)

if project == nil || *project == "" {
    project = &credentials.ProjectID
}

if *project == "" {
    log.Printf("%v", credentials)
    log.Fatal("no -project specified")
}

computeService, err := compute.NewService(context.Background(), option.WithCredentials(credentials))
if err != nil {
    log.Fatal(err)
}

token := ""

var list *compute.InstanceAggregatedList
if list, err = computeService.Instances.AggregatedList(*project).PageToken(token).Do(); err != nil {
    log.Fatal(err)
}

for _, instances := range list.Items {
    for _, instance := range instances.Instances {

        EXTERNAL_IP := instance.NetworkInterfaces[0].AccessConfigs[0].NatIP
        fmt.Printf("%s \n", EXTERNAL_IP)
        INTERNAL_IP := instance.NetworkInterfaces[0].NetworkIP
        fmt.Printf("%s \n", INTERNAL_IP)
        fmt.Printf("%s \n", instance.Name)

    }
  }
}

Upvotes: 0

Ari
Ari

Reputation: 6189

You can also use Aggregated List which will search every zone for you. This saves you having to do nested loops or figuring out what the zones are.

https://pkg.go.dev/cloud.google.com/go/compute/apiv1#InstancesClient.AggregatedList

The below assumes you have logged into gcloud and set your ADC.

$ gcloud init
$ gcloud auth application-default login

Using a service account key is also possible but not demonstrated below.

package main

import (
    "context"
    "fmt"
    "log"

    compute "cloud.google.com/go/compute/apiv1"
    "google.golang.org/api/iterator"
    protobuf "google.golang.org/genproto/googleapis/cloud/compute/v1"
)

func main() {

    ctx := context.Background()

    c, err := compute.NewInstancesRESTClient(ctx)
    if err != nil {
        log.Fatalln(err)
    }
    defer c.Close()

    project := "my-project"

    req := &protobuf.AggregatedListInstancesRequest{
        Project: project,
    }

    it := c.client.AggregatedList(ctx, req)

    for {
        resp, err := it.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            log.Fatalln(err)
        }
        fmt.Println(resp)
    }

}

Upvotes: 1

grenade
grenade

Reputation: 32169

i had to write something like this today and googling for examples turned up surprisingly little. i've written up what i learned below, however, i'm quite new to golang so maybe smarter people can suggest improvements.

my work in progress is at: https://github.com/grenade/rubberneck


if you want to run your go program from a development pc that is not on the google compute platform:

  • set up the gcloud cli to run on your pc (instructions: https://cloud.google.com/sdk/gcloud)
  • create a service account for your go application to run under (instructions: https://cloud.google.com/docs/authentication/production#creating_a_service_account)
  • grant permissions to the service account (use the same instructions link above)
  • create a local key file containing your new service account credentials (use the same instructions link above)
  • set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your local key file
  • write your go application. something like this:
package main

import (

  "golang.org/x/net/context"
  "google.golang.org/api/compute/v1"
  "golang.org/x/oauth2/google"

  "fmt"
  "strings"
)

func main() {
  projects := [...]string{
    "my-project-one",
    "my-project-two",
  }
  filters := [...]string{
    "status = RUNNING",
    "name != my-uninteresting-instance-one",
    "name != my-uninteresting-instance-two",
  }

  ctx := context.Background()
  client, err := google.DefaultClient(ctx,compute.ComputeScope)
  if err != nil {
    fmt.Println(err)
  }
  computeService, err := compute.New(client)
  for _, project := range projects {
    zoneListCall := computeService.Zones.List(project)
    zoneList, err := zoneListCall.Do()
    if err != nil {
      fmt.Println("Error", err)
    } else {
      for _, zone := range zoneList.Items {
        instanceListCall := computeService.Instances.List(project, zone.Name)
        instanceListCall.Filter(strings.Join(filters[:], " "))
        instanceList, err := instanceListCall.Do()
        if err != nil {
          fmt.Println("Error", err)
        } else {
          for _, instance := range instanceList.Items {
            if workerType, isWorker := instance.Labels["worker-type"]; isWorker {
              m := strings.Split(instance.MachineType, "/")
              fmt.Printf("cloud: gcp, zone: %v, name: %v, instance id: %v, machine type: %v, worker type: %v, launch time: %v\n",
                zone.Name,
                instance.Name,
                instance.Id,
                m[len(m)-1],
                workerType,
                instance.CreationTimestamp)
            }
          }
        }
      }
    }
  }
}

Upvotes: 4

Related Questions