aboutsummaryrefslogtreecommitdiff
path: root/vendor/google.golang.org/cloud/compute/metadata/metadata.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/google.golang.org/cloud/compute/metadata/metadata.go')
-rw-r--r--vendor/google.golang.org/cloud/compute/metadata/metadata.go87
1 files changed, 71 insertions, 16 deletions
diff --git a/vendor/google.golang.org/cloud/compute/metadata/metadata.go b/vendor/google.golang.org/cloud/compute/metadata/metadata.go
index 13a1ed9..9821843 100644
--- a/vendor/google.golang.org/cloud/compute/metadata/metadata.go
+++ b/vendor/google.golang.org/cloud/compute/metadata/metadata.go
@@ -27,6 +27,7 @@ import (
"net/http"
"net/url"
"os"
+ "runtime"
"strings"
"sync"
"time"
@@ -37,8 +38,17 @@ import (
"google.golang.org/cloud/internal"
)
-// metadataIP is the documented metadata server IP address.
-const metadataIP = "169.254.169.254"
+const (
+ // metadataIP is the documented metadata server IP address.
+ metadataIP = "169.254.169.254"
+
+ // metadataHostEnv is the environment variable specifying the
+ // GCE metadata hostname. If empty, the default value of
+ // metadataIP ("169.254.169.254") is used instead.
+ // This is variable name is not defined by any spec, as far as
+ // I know; it was made up for the Go package.
+ metadataHostEnv = "GCE_METADATA_HOST"
+)
type cachedValue struct {
k string
@@ -110,7 +120,7 @@ func getETag(client *http.Client, suffix string) (value, etag string, err error)
// deployments. To enable spoofing of the metadata service, the environment
// variable GCE_METADATA_HOST is first inspected to decide where metadata
// requests shall go.
- host := os.Getenv("GCE_METADATA_HOST")
+ host := os.Getenv(metadataHostEnv)
if host == "" {
// Using 169.254.169.254 instead of "metadata" here because Go
// binaries built with the "netgo" tag and without cgo won't
@@ -163,25 +173,27 @@ func (c *cachedValue) get() (v string, err error) {
return
}
-var onGCE struct {
- sync.Mutex
- set bool
- v bool
-}
+var (
+ onGCEOnce sync.Once
+ onGCE bool
+)
// OnGCE reports whether this process is running on Google Compute Engine.
func OnGCE() bool {
- defer onGCE.Unlock()
- onGCE.Lock()
- if onGCE.set {
- return onGCE.v
- }
- onGCE.set = true
- onGCE.v = testOnGCE()
- return onGCE.v
+ onGCEOnce.Do(initOnGCE)
+ return onGCE
+}
+
+func initOnGCE() {
+ onGCE = testOnGCE()
}
func testOnGCE() bool {
+ // The user explicitly said they're on GCE, so trust them.
+ if os.Getenv(metadataHostEnv) != "" {
+ return true
+ }
+
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -208,9 +220,52 @@ func testOnGCE() bool {
resc <- strsContains(addrs, metadataIP)
}()
+ tryHarder := systemInfoSuggestsGCE()
+ if tryHarder {
+ res := <-resc
+ if res {
+ // The first strategy succeeded, so let's use it.
+ return true
+ }
+ // Wait for either the DNS or metadata server probe to
+ // contradict the other one and say we are running on
+ // GCE. Give it a lot of time to do so, since the system
+ // info already suggests we're running on a GCE BIOS.
+ timer := time.NewTimer(5 * time.Second)
+ defer timer.Stop()
+ select {
+ case res = <-resc:
+ return res
+ case <-timer.C:
+ // Too slow. Who knows what this system is.
+ return false
+ }
+ }
+
+ // There's no hint from the system info that we're running on
+ // GCE, so use the first probe's result as truth, whether it's
+ // true or false. The goal here is to optimize for speed for
+ // users who are NOT running on GCE. We can't assume that
+ // either a DNS lookup or an HTTP request to a blackholed IP
+ // address is fast. Worst case this should return when the
+ // metaClient's Transport.ResponseHeaderTimeout or
+ // Transport.Dial.Timeout fires (in two seconds).
return <-resc
}
+// systemInfoSuggestsGCE reports whether the local system (without
+// doing network requests) suggests that we're running on GCE. If this
+// returns true, testOnGCE tries a bit harder to reach its metadata
+// server.
+func systemInfoSuggestsGCE() bool {
+ if runtime.GOOS != "linux" {
+ // We don't have any non-Linux clues available, at least yet.
+ return false
+ }
+ slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
+ return strings.TrimSpace(string(slurp)) == "Google"
+}
+
// Subscribe subscribes to a value from the metadata service.
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
// The suffix may contain query parameters.