Просмотр исходного кода

hostinfo: add hostinfo package, move stuff out of controlclient

And make it cheaper, so other parts of the code can check the
environment.

Signed-off-by: Brad Fitzpatrick <[email protected]>
Brad Fitzpatrick 4 лет назад
Родитель
Сommit
03311bb0d6
3 измененных файлов с 123 добавлено и 71 удалено
  1. 2 1
      cmd/tailscaled/depaware.txt
  2. 4 70
      control/controlclient/hostinfo_linux.go
  3. 117 0
      hostinfo/hostinfo.go

+ 2 - 1
cmd/tailscaled/depaware.txt

@@ -25,7 +25,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
    W 💣 github.com/tailscale/certstore                               from tailscale.com/control/controlclient
         github.com/tcnksm/go-httpstat                                from tailscale.com/net/netcheck
      💣 go4.org/intern                                               from inet.af/netaddr
-     💣 go4.org/mem                                                  from tailscale.com/control/controlclient+
+     💣 go4.org/mem                                                  from tailscale.com/derp+
         go4.org/unsafe/assume-no-moving-gc                           from go4.org/intern
      💣 golang.zx2c4.com/wireguard/conn                              from golang.zx2c4.com/wireguard/device+
    W 💣 golang.zx2c4.com/wireguard/conn/winrio                       from golang.zx2c4.com/wireguard/conn
@@ -81,6 +81,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         tailscale.com/derp/derpmap                                   from tailscale.com/cmd/tailscaled+
         tailscale.com/disco                                          from tailscale.com/derp+
         tailscale.com/health                                         from tailscale.com/control/controlclient+
+   L    tailscale.com/hostinfo                                       from tailscale.com/control/controlclient
         tailscale.com/internal/deephash                              from tailscale.com/ipn/ipnlocal+
         tailscale.com/ipn                                            from tailscale.com/ipn/ipnserver+
         tailscale.com/ipn/ipnlocal                                   from tailscale.com/ipn/ipnserver+

+ 4 - 70
control/controlclient/hostinfo_linux.go

@@ -9,13 +9,11 @@ package controlclient
 import (
 	"bytes"
 	"fmt"
-	"io"
 	"io/ioutil"
-	"os"
 	"strings"
 	"syscall"
 
-	"go4.org/mem"
+	"tailscale.com/hostinfo"
 	"tailscale.com/util/lineread"
 	"tailscale.com/version/distro"
 )
@@ -56,20 +54,11 @@ func osVersionLinux() string {
 		}
 		attrBuf.WriteByte(byte(b))
 	}
-	if inContainer() {
+	if hostinfo.InContainer() {
 		attrBuf.WriteString("; container")
 	}
-	if inKnative() {
-		attrBuf.WriteString("; env=kn")
-	}
-	if inAWSLambda() {
-		attrBuf.WriteString("; env=lm")
-	}
-	if inHerokuDyno() {
-		attrBuf.WriteString("; env=hr")
-	}
-	if inAzureAppService() {
-		attrBuf.WriteString("; env=az")
+	if env := hostinfo.GetEnvType(); env != "" {
+		fmt.Fprintf(&attrBuf, "; env=%s", env)
 	}
 	attr := attrBuf.String()
 
@@ -102,58 +91,3 @@ func osVersionLinux() string {
 	}
 	return fmt.Sprintf("Other%s", attr)
 }
-
-func inContainer() (ret bool) {
-	lineread.File("/proc/1/cgroup", func(line []byte) error {
-		if mem.Contains(mem.B(line), mem.S("/docker/")) ||
-			mem.Contains(mem.B(line), mem.S("/lxc/")) {
-			ret = true
-			return io.EOF // arbitrary non-nil error to stop loop
-		}
-		return nil
-	})
-	lineread.File("/proc/mounts", func(line []byte) error {
-		if mem.Contains(mem.B(line), mem.S("fuse.lxcfs")) {
-			ret = true
-			return io.EOF
-		}
-		return nil
-	})
-	return
-}
-
-func inKnative() bool {
-	// https://cloud.google.com/run/docs/reference/container-contract#env-vars
-	if os.Getenv("K_REVISION") != "" && os.Getenv("K_CONFIGURATION") != "" &&
-		os.Getenv("K_SERVICE") != "" && os.Getenv("PORT") != "" {
-		return true
-	}
-	return false
-}
-
-func inAWSLambda() bool {
-	// https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
-	if os.Getenv("AWS_LAMBDA_FUNCTION_NAME") != "" &&
-		os.Getenv("AWS_LAMBDA_FUNCTION_VERSION") != "" &&
-		os.Getenv("AWS_LAMBDA_INITIALIZATION_TYPE") != "" &&
-		os.Getenv("AWS_LAMBDA_RUNTIME_API") != "" {
-		return true
-	}
-	return false
-}
-
-func inHerokuDyno() bool {
-	// https://devcenter.heroku.com/articles/dynos#local-environment-variables
-	if os.Getenv("PORT") != "" && os.Getenv("DYNO") != "" {
-		return true
-	}
-	return false
-}
-
-func inAzureAppService() bool {
-	if os.Getenv("APPSVC_RUN_ZIP") != "" && os.Getenv("WEBSITE_STACK") != "" &&
-		os.Getenv("WEBSITE_AUTH_AUTO_AAD") != "" {
-		return true
-	}
-	return false
-}

+ 117 - 0
hostinfo/hostinfo.go

@@ -0,0 +1,117 @@
+// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package hostinfo answers questions about the host environment that Tailscale is
+// running on.
+//
+// TODO(bradfitz): move more of control/controlclient/hostinfo_* into this package.
+package hostinfo
+
+import (
+	"io"
+	"os"
+	"runtime"
+	"sync/atomic"
+
+	"go4.org/mem"
+	"tailscale.com/util/lineread"
+)
+
+// EnvType represents a known environment type.
+// The empty string, the default, means unknown.
+type EnvType string
+
+const (
+	KNative         = EnvType("kn")
+	AWSLambda       = EnvType("lm")
+	Heroku          = EnvType("hr")
+	AzureAppService = EnvType("az")
+)
+
+var envType atomic.Value // of EnvType
+
+func GetEnvType() EnvType {
+	if e, ok := envType.Load().(EnvType); ok {
+		return e
+	}
+	e := getEnvType()
+	envType.Store(e)
+	return e
+}
+
+func getEnvType() EnvType {
+	if inKnative() {
+		return KNative
+	}
+	if inAWSLambda() {
+		return AWSLambda
+	}
+	if inHerokuDyno() {
+		return Heroku
+	}
+	if inAzureAppService() {
+		return AzureAppService
+	}
+	return ""
+}
+
+// InContainer reports whether we're running in a container.
+func InContainer() bool {
+	if runtime.GOOS != "linux" {
+		return false
+	}
+	var ret bool
+	lineread.File("/proc/1/cgroup", func(line []byte) error {
+		if mem.Contains(mem.B(line), mem.S("/docker/")) ||
+			mem.Contains(mem.B(line), mem.S("/lxc/")) {
+			ret = true
+			return io.EOF // arbitrary non-nil error to stop loop
+		}
+		return nil
+	})
+	lineread.File("/proc/mounts", func(line []byte) error {
+		if mem.Contains(mem.B(line), mem.S("fuse.lxcfs")) {
+			ret = true
+			return io.EOF
+		}
+		return nil
+	})
+	return ret
+}
+
+func inKnative() bool {
+	// https://cloud.google.com/run/docs/reference/container-contract#env-vars
+	if os.Getenv("K_REVISION") != "" && os.Getenv("K_CONFIGURATION") != "" &&
+		os.Getenv("K_SERVICE") != "" && os.Getenv("PORT") != "" {
+		return true
+	}
+	return false
+}
+
+func inAWSLambda() bool {
+	// https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
+	if os.Getenv("AWS_LAMBDA_FUNCTION_NAME") != "" &&
+		os.Getenv("AWS_LAMBDA_FUNCTION_VERSION") != "" &&
+		os.Getenv("AWS_LAMBDA_INITIALIZATION_TYPE") != "" &&
+		os.Getenv("AWS_LAMBDA_RUNTIME_API") != "" {
+		return true
+	}
+	return false
+}
+
+func inHerokuDyno() bool {
+	// https://devcenter.heroku.com/articles/dynos#local-environment-variables
+	if os.Getenv("PORT") != "" && os.Getenv("DYNO") != "" {
+		return true
+	}
+	return false
+}
+
+func inAzureAppService() bool {
+	if os.Getenv("APPSVC_RUN_ZIP") != "" && os.Getenv("WEBSITE_STACK") != "" &&
+		os.Getenv("WEBSITE_AUTH_AUTO_AAD") != "" {
+		return true
+	}
+	return false
+}