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 <bradfitz@tailscale.com>
pull/2164/head
Brad Fitzpatrick 3 years ago committed by Brad Fitzpatrick
parent 0022c3d2e2
commit 03311bb0d6

@ -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 W 💣 github.com/tailscale/certstore from tailscale.com/control/controlclient
github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck
💣 go4.org/intern from inet.af/netaddr 💣 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 go4.org/unsafe/assume-no-moving-gc from go4.org/intern
💣 golang.zx2c4.com/wireguard/conn from golang.zx2c4.com/wireguard/device+ 💣 golang.zx2c4.com/wireguard/conn from golang.zx2c4.com/wireguard/device+
W 💣 golang.zx2c4.com/wireguard/conn/winrio from golang.zx2c4.com/wireguard/conn 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/derp/derpmap from tailscale.com/cmd/tailscaled+
tailscale.com/disco from tailscale.com/derp+ tailscale.com/disco from tailscale.com/derp+
tailscale.com/health from tailscale.com/control/controlclient+ 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/internal/deephash from tailscale.com/ipn/ipnlocal+
tailscale.com/ipn from tailscale.com/ipn/ipnserver+ tailscale.com/ipn from tailscale.com/ipn/ipnserver+
tailscale.com/ipn/ipnlocal from tailscale.com/ipn/ipnserver+ tailscale.com/ipn/ipnlocal from tailscale.com/ipn/ipnserver+

@ -9,13 +9,11 @@ package controlclient
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"io/ioutil" "io/ioutil"
"os"
"strings" "strings"
"syscall" "syscall"
"go4.org/mem" "tailscale.com/hostinfo"
"tailscale.com/util/lineread" "tailscale.com/util/lineread"
"tailscale.com/version/distro" "tailscale.com/version/distro"
) )
@ -56,20 +54,11 @@ func osVersionLinux() string {
} }
attrBuf.WriteByte(byte(b)) attrBuf.WriteByte(byte(b))
} }
if inContainer() { if hostinfo.InContainer() {
attrBuf.WriteString("; container") attrBuf.WriteString("; container")
} }
if inKnative() { if env := hostinfo.GetEnvType(); env != "" {
attrBuf.WriteString("; env=kn") fmt.Fprintf(&attrBuf, "; env=%s", env)
}
if inAWSLambda() {
attrBuf.WriteString("; env=lm")
}
if inHerokuDyno() {
attrBuf.WriteString("; env=hr")
}
if inAzureAppService() {
attrBuf.WriteString("; env=az")
} }
attr := attrBuf.String() attr := attrBuf.String()
@ -102,58 +91,3 @@ func osVersionLinux() string {
} }
return fmt.Sprintf("Other%s", attr) 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
}

@ -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
}
Loading…
Cancel
Save