Source File
metadata.go
Belonging Package
cloud.google.com/go/compute/metadata
package metadata // import "cloud.google.com/go/compute/metadata"
import (
)
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 ( NotDefinedError) () string {
return fmt.Sprintf("metadata: GCE metadata %q not defined", string())
}
func ( *cachedValue) ( *Client) ( string, error) {
defer .mu.Unlock()
.mu.Lock()
if .v != "" {
return .v, nil
}
if .trim {
, = .getTrimmed(.k)
} else {
, = .Get(.k)
}
if == nil {
.v =
}
return
}
var (
onGCEOnce sync.Once
onGCE bool
)
if os.Getenv(metadataHostEnv) != "" {
return true
}
, := context.WithCancel(context.Background())
defer ()
:= make(chan bool, 2)
go func() {
, := http.NewRequest("GET", "http://"+metadataIP, nil)
.Header.Set("User-Agent", userAgent)
, := defaultClient.hc.Do(.WithContext())
if != nil {
<- false
return
}
defer .Body.Close()
<- .Header.Get("Metadata-Flavor") == "Google"
}()
go func() {
, := net.DefaultResolver.LookupHost(, "metadata.google.internal")
if != nil || len() == 0 {
<- false
return
}
<- strsContains(, metadataIP)
}()
:= systemInfoSuggestsGCE()
if {
:= <-
return true
return false
}
}
return <-
}
func () bool {
func ( string) (string, error) { return defaultClient.Get() }
func () (string, error) { return defaultClient.ProjectID() }
func () (string, error) { return defaultClient.NumericProjectID() }
func () (string, error) { return defaultClient.InternalIP() }
func () (string, error) { return defaultClient.ExternalIP() }
func ( string) (string, error) { return defaultClient.Email() }
func () (string, error) { return defaultClient.Hostname() }
func () ([]string, error) { return defaultClient.InstanceTags() }
func () (string, error) { return defaultClient.InstanceID() }
func () (string, error) { return defaultClient.InstanceName() }
func () (string, error) { return defaultClient.Zone() }
func () ([]string, error) { return defaultClient.InstanceAttributes() }
func () ([]string, error) { return defaultClient.ProjectAttributes() }
func ( string) (string, error) {
return defaultClient.InstanceAttributeValue()
}
func ( string) (string, error) {
return defaultClient.ProjectAttributeValue()
}
:= os.Getenv(metadataHostEnv)
= metadataIP
}
= strings.TrimLeft(, "/")
:= "http://" + + "/computeMetadata/v1/" +
, := http.NewRequest("GET", , nil)
if != nil {
return "", "",
}
.Header.Set("Metadata-Flavor", "Google")
.Header.Set("User-Agent", userAgent)
, := .hc.Do()
if != nil {
return "", "",
}
defer .Body.Close()
if .StatusCode == http.StatusNotFound {
return "", "", NotDefinedError()
}
, := ioutil.ReadAll(.Body)
if != nil {
return "", "",
}
if .StatusCode != 200 {
return "", "", &Error{Code: .StatusCode, Message: string()}
}
return string(), .Header.Get("Etag"), nil
}
func ( *Client) ( string) (string, error) {
, , := .getETag()
return ,
}
func ( *Client) ( string) ( string, error) {
, = .Get()
= strings.TrimSpace()
return
}
func ( *Client) ( string) ([]string, error) {
, := .Get()
if != nil {
return nil,
}
:= strings.Split(strings.TrimSpace(), "\n")
for := range {
[] = strings.TrimSpace([])
}
return , nil
}
func ( *Client) () (string, error) {
return .getTrimmed("instance/network-interfaces/0/ip")
}
func ( *Client) ( string) (string, error) {
if == "" {
= "default"
}
return .getTrimmed("instance/service-accounts/" + + "/email")
}
func ( *Client) () (string, error) {
return .getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
}
func ( *Client) () (string, error) {
return .getTrimmed("instance/hostname")
}
func ( *Client) () (string, error) {
return .getTrimmed("instance/name")
}
, , := .getETag()
if != nil {
return
}
if := (, true); != nil {
return
}
:= true
if strings.ContainsRune(, '?') {
+= "&wait_for_change=true&last_etag="
} else {
+= "?wait_for_change=true&last_etag="
}
for {
, , := .getETag( + url.QueryEscape())
if != nil {
if , := .(NotDefinedError); ! {
time.Sleep()
continue // Retry on other errors.
}
= false
}
=
if := (, ); != nil || ! {
return
}
}
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |