func InstanceTags() ([]string, error) {
	var s []string
	j, err := 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
}
InstanceTags returns the list of user-defined instance tags,
assigned when initially creating a GCE instance.
package metadata  
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"
	"google.golang.org/cloud/internal"
)
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 metaClient = &http.Client{
	Transport: &internal.Transport{
		Base: &http.Transport{
			Dial: (&net.Dialer{
				Timeout:   750 * time.Millisecond,
				KeepAlive: 30 * time.Second,
			}).Dial,
			ResponseHeaderTimeout: 750 * time.Millisecond,
		},
	},
}
type NotDefinedError string
func (suffix NotDefinedError) Error() string {
	return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
}
func Get(suffix string) (string, error) {
	val, _, err := getETag(suffix)
	return val, err
}
func getETag(suffix string) (value, etag string, err error) {
	host := os.Getenv("GCE_METADATA_HOST")
	if host == "" {
		host = "169.254.169.254"
	}
	url := "http://" + host + "/computeMetadata/v1/" + suffix
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Metadata-Flavor", "Google")
	res, err := metaClient.Do(req)
	if err != nil {
		return "", "", err
	}
	defer res.Body.Close()
	if res.StatusCode == http.StatusNotFound {
		return "", "", NotDefinedError(suffix)
	}
	if res.StatusCode != 200 {
		return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
	}
	all, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", "", err
	}
	return string(all), res.Header.Get("Etag"), nil
}
func getTrimmed(suffix string) (s string, err error) {
	s, err = Get(suffix)
	s = strings.TrimSpace(s)
	return
}
func (c *cachedValue) get() (v string, err error) {
	defer c.mu.Unlock()
	c.mu.Lock()
	if c.v != "" {
		return c.v, nil
	}
	if c.trim {
		v, err = getTrimmed(c.k)
	} else {
		v, err = Get(c.k)
	}
	if err == nil {
		c.v = v
	}
	return
}
var onGCE struct {
	sync.Mutex
	set bool
	v   bool
}
func OnGCE() bool {
	defer onGCE.Unlock()
	onGCE.Lock()
	if onGCE.set {
		return onGCE.v
	}
	onGCE.set = true
	res, err := metaClient.Get("http://metadata.google.internal")
	if err != nil {
		return false
	}
	onGCE.v = res.Header.Get("Metadata-Flavor") == "Google"
	return onGCE.v
}
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
	const failedSubscribeSleep = time.Second * 5
	val, lastETag, err := getETag(suffix)
	if err != nil {
		return err
	}
	if err := fn(val, true); err != nil {
		return err
	}
	ok := true
	suffix += "?wait_for_change=true&last_etag="
	for {
		val, etag, err := getETag(suffix + url.QueryEscape(lastETag))
		if err != nil {
			if _, deleted := err.(NotDefinedError); !deleted {
				time.Sleep(failedSubscribeSleep)
				continue  
			}
			ok = false
		}
		lastETag = etag
		if err := fn(val, ok); err != nil || !ok {
			return err
		}
	}
}
func ProjectID() (string, error) { return projID.get() }
func NumericProjectID() (string, error) { return projNum.get() }
func InternalIP() (string, error) {
	return getTrimmed("instance/network-interfaces/0/ip")
}
func ExternalIP() (string, error) {
	return getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
}
func Hostname() (string, error) {
	return getTrimmed("instance/hostname")
}