func (c *Client) Scopes(serviceAccount string) ([]string, error) {
	if serviceAccount == "" {
		serviceAccount = "default"
	}
	return c.lines("instance/service-accounts/" + serviceAccount + "/scopes")
}
Scopes returns the service account scopes for the given account.
The account may be empty or the string "default" to use the instance's
main account.
package metadata  
import (
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"runtime"
	"strings"
	"sync"
	"time"
)
const (
	metadataIP = "169.254.169.254"
	metadataHostEnv = "GCE_METADATA_HOST"
	userAgent = "gcloud-golang/0.1"
)
type cachedValue struct {
	k    string
	trim bool
	mu   sync.Mutex
	v    string
}
var (
	projID  = &cachedValue{k: "project/project-id", trim: true}
	projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
	instID  = &cachedValue{k: "instance/id", trim: true}
)
var defaultClient = &Client{hc: &http.Client{
	Transport: &http.Transport{
		Dial: (&net.Dialer{
			Timeout:   2 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
	},
}}
type NotDefinedError string
func (suffix NotDefinedError) Error() string {
	return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
}
func (c *cachedValue) get(cl *Client) (v string, err error) {
	defer c.mu.Unlock()
	c.mu.Lock()
	if c.v != "" {
		return c.v, nil
	}
	if c.trim {
		v, err = cl.getTrimmed(c.k)
	} else {
		v, err = cl.Get(c.k)
	}
	if err == nil {
		c.v = v
	}
	return
}
var (
	onGCEOnce sync.Once
	onGCE     bool
)
func OnGCE() bool {
	onGCEOnce.Do(initOnGCE)
	return onGCE
}
func initOnGCE() {
	onGCE = testOnGCE()
}
func testOnGCE() bool {
	if os.Getenv(metadataHostEnv) != "" {
		return true
	}
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	resc := make(chan bool, 2)
	go func() {
		req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
		req.Header.Set("User-Agent", userAgent)
		res, err := defaultClient.hc.Do(req.WithContext(ctx))
		if err != nil {
			resc <- false
			return
		}
		defer res.Body.Close()
		resc <- res.Header.Get("Metadata-Flavor") == "Google"
	}()
	go func() {
		addrs, err := net.DefaultResolver.LookupHost(ctx, "metadata.google.internal")
		if err != nil || len(addrs) == 0 {
			resc <- false
			return
		}
		resc <- strsContains(addrs, metadataIP)
	}()
	tryHarder := systemInfoSuggestsGCE()
	if tryHarder {
		res := <-resc
		if res {
			return true
		}
		timer := time.NewTimer(5 * time.Second)
		defer timer.Stop()
		select {
		case res = <-resc:
			return res
		case <-timer.C:
			return false
		}
	}
	return <-resc
}
func systemInfoSuggestsGCE() bool {
	if runtime.GOOS != "linux" {
		return false
	}
	slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
	name := strings.TrimSpace(string(slurp))
	return name == "Google" || name == "Google Compute Engine"
}
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
	return defaultClient.Subscribe(suffix, fn)
}
func Get(suffix string) (string, error) { return defaultClient.Get(suffix) }
func ProjectID() (string, error) { return defaultClient.ProjectID() }
func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() }
func InternalIP() (string, error) { return defaultClient.InternalIP() }
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
func Email(serviceAccount string) (string, error) { return defaultClient.Email(serviceAccount) }
func Hostname() (string, error) { return defaultClient.Hostname() }
func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() }
func InstanceID() (string, error) { return defaultClient.InstanceID() }
func InstanceName() (string, error) { return defaultClient.InstanceName() }
func Zone() (string, error) { return defaultClient.Zone() }
func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() }
func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() }
func InstanceAttributeValue(attr string) (string, error) {
	return defaultClient.InstanceAttributeValue(attr)
}
func ProjectAttributeValue(attr string) (string, error) {
	return defaultClient.ProjectAttributeValue(attr)
}
func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) }
func strsContains(ss []string, s string) bool {
	for _, v := range ss {
		if v == s {
			return true
		}
	}
	return false
}
type Client struct {
	hc *http.Client
}
func NewClient(c *http.Client) *Client {
	if c == nil {
		return defaultClient
	}
	return &Client{hc: c}
}
func (c *Client) getETag(suffix string) (value, etag string, err error) {
	host := os.Getenv(metadataHostEnv)
	if host == "" {
		host = metadataIP
	}
	suffix = strings.TrimLeft(suffix, "/")
	u := "http://" + host + "/computeMetadata/v1/" + suffix
	req, err := http.NewRequest("GET", u, nil)
	if err != nil {
		return "", "", err
	}
	req.Header.Set("Metadata-Flavor", "Google")
	req.Header.Set("User-Agent", userAgent)
	res, err := c.hc.Do(req)
	if err != nil {
		return "", "", err
	}
	defer res.Body.Close()
	if res.StatusCode == http.StatusNotFound {
		return "", "", NotDefinedError(suffix)
	}
	all, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", "", err
	}
	if res.StatusCode != 200 {
		return "", "", &Error{Code: res.StatusCode, Message: string(all)}
	}
	return string(all), res.Header.Get("Etag"), nil
}
func (c *Client) Get(suffix string) (string, error) {
	val, _, err := c.getETag(suffix)
	return val, err
}
func (c *Client) getTrimmed(suffix string) (s string, err error) {
	s, err = c.Get(suffix)
	s = strings.TrimSpace(s)
	return
}
func (c *Client) lines(suffix string) ([]string, error) {
	j, err := c.Get(suffix)
	if err != nil {
		return nil, err
	}
	s := strings.Split(strings.TrimSpace(j), "\n")
	for i := range s {
		s[i] = strings.TrimSpace(s[i])
	}
	return s, nil
}
func (c *Client) ProjectID() (string, error) { return projID.get(c) }
func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) }
func (c *Client) InstanceID() (string, error) { return instID.get(c) }
func (c *Client) InternalIP() (string, error) {
	return c.getTrimmed("instance/network-interfaces/0/ip")
}
func (c *Client) Email(serviceAccount string) (string, error) {
	if serviceAccount == "" {
		serviceAccount = "default"
	}
	return c.getTrimmed("instance/service-accounts/" + serviceAccount + "/email")
}
func (c *Client) ExternalIP() (string, error) {
	return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
}
func (c *Client) Hostname() (string, error) {
	return c.getTrimmed("instance/hostname")
}
func (c *Client) InstanceTags() ([]string, error) {
	var s []string
	j, err := c.Get("instance/tags")
	if err != nil {
		return nil, err
	}
	if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
		return nil, err
	}
	return s, nil
}
func (c *Client) InstanceName() (string, error) {
	return c.getTrimmed("instance/name")
}
func (c *Client) Zone() (string, error) {
	zone, err := c.getTrimmed("instance/zone")
	if err != nil {
		return "", err
	}
	return zone[strings.LastIndex(zone, "/")+1:], nil
}
func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") }
func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") }
func (c *Client) InstanceAttributeValue(attr string) (string, error) {
	return c.Get("instance/attributes/" + attr)
}
func (c *Client) ProjectAttributeValue(attr string) (string, error) {
	return c.Get("project/attributes/" + attr)
}