hostinfo: move packageType out to platform-specific files

Change-Id: I3236b3d4e2376dd7e2482c2562817b1b6f44872e
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2022-02-22 10:01:36 -08:00 committed by Brad Fitzpatrick
parent c7a8f0992d
commit 4fee321004
4 changed files with 86 additions and 53 deletions

View File

@ -10,7 +10,6 @@ import (
"bufio" "bufio"
"io" "io"
"os" "os"
"path/filepath"
"runtime" "runtime"
"strings" "strings"
"sync/atomic" "sync/atomic"
@ -32,13 +31,17 @@ func New() *tailcfg.Hostinfo {
Hostname: hostname, Hostname: hostname,
OS: version.OS(), OS: version.OS(),
OSVersion: GetOSVersion(), OSVersion: GetOSVersion(),
Package: packageType(), Package: packageTypeCached(),
GoArch: runtime.GOARCH, GoArch: runtime.GOARCH,
DeviceModel: deviceModel(), DeviceModel: deviceModel(),
} }
} }
var osVersion func() string // non-nil on some platforms // non-nil on some platforms
var (
osVersion func() string
packageType func() string
)
// GetOSVersion returns the OSVersion of current host if available. // GetOSVersion returns the OSVersion of current host if available.
func GetOSVersion() string { func GetOSVersion() string {
@ -51,60 +54,18 @@ func GetOSVersion() string {
return "" return ""
} }
func packageType() (ret string) { func packageTypeCached() string {
if v, _ := packagingType.Load().(string); v != "" { if v, _ := packagingType.Load().(string); v != "" {
return v return v
} }
switch runtime.GOOS { if packageType == nil {
case "windows": return ""
defer func() {
if ret != "" {
packagingType.Store(ret)
}
}()
if _, err := os.Stat(`C:\ProgramData\chocolatey\lib\tailscale`); err == nil {
return "choco"
}
exe, err := os.Executable()
if err != nil {
return ""
}
dir := filepath.Dir(exe)
if !strings.Contains(dir, "Program Files") {
// Atypical. Not worth trying to detect. Likely open
// source tailscaled or a developer running by hand.
return ""
}
nsisUninstaller := filepath.Join(dir, "Uninstall-Tailscale.exe")
_, err = os.Stat(nsisUninstaller)
if err == nil {
return "nsis"
}
if os.IsNotExist(err) {
_, cliErr := os.Stat(filepath.Join(dir, "tailscale.exe"))
_, daemonErr := os.Stat(filepath.Join(dir, "tailscaled.exe"))
if cliErr == nil && daemonErr == nil {
// Almost certainly MSI.
// We have tailscaled.exe and tailscale.exe
// next to each other in Program Files, but no
// uninstaller.
// TODO(bradfitz,dblohm7): tighter heuristic?
return "msi"
}
}
case "darwin":
// Using tailscaled or IPNExtension?
exe, _ := os.Executable()
return filepath.Base(exe)
case "linux":
// Report whether this is in a snap.
// See https://snapcraft.io/docs/environment-variables
// We just look at two somewhat arbitrarily.
if os.Getenv("SNAP_NAME") != "" && os.Getenv("SNAP") != "" {
return "snap"
}
} }
return "" v := packageType()
if v != "" {
SetPackage(v)
}
return v
} }
// EnvType represents a known environment type. // EnvType represents a known environment type.

View File

@ -0,0 +1,23 @@
// Copyright (c) 2022 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.
//go:build darwin
// +build darwin
package hostinfo
import (
"os"
"path/filepath"
)
func init() {
packageType = packageTypeDarwin
}
func packageTypeDarwin() string {
// Using tailscaled or IPNExtension?
exe, _ := os.Executable()
return filepath.Base(exe)
}

View File

@ -21,6 +21,7 @@ import (
func init() { func init() {
osVersion = osVersionLinux osVersion = osVersionLinux
packageType = packageTypeLinux
if v := linuxDeviceModel(); v != "" { if v := linuxDeviceModel(); v != "" {
SetDeviceModel(v) SetDeviceModel(v)
@ -115,3 +116,13 @@ func osVersionLinux() string {
} }
return fmt.Sprintf("Other%s", attr) return fmt.Sprintf("Other%s", attr)
} }
func packageTypeLinux() string {
// Report whether this is in a snap.
// See https://snapcraft.io/docs/environment-variables
// We just look at two somewhat arbitrarily.
if os.Getenv("SNAP_NAME") != "" && os.Getenv("SNAP") != "" {
return "snap"
}
return ""
}

View File

@ -6,6 +6,9 @@ package hostinfo
import ( import (
"fmt" "fmt"
"os"
"path/filepath"
"strings"
"sync/atomic" "sync/atomic"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@ -14,6 +17,7 @@ import (
func init() { func init() {
osVersion = osVersionWindows osVersion = osVersionWindows
packageType = packageTypeWindows
} }
var winVerCache atomic.Value // of string var winVerCache atomic.Value // of string
@ -56,3 +60,37 @@ func getUBR() (uint32, error) {
return uint32(val), nil return uint32(val), nil
} }
func packageTypeWindows() string {
if _, err := os.Stat(`C:\ProgramData\chocolatey\lib\tailscale`); err == nil {
return "choco"
}
exe, err := os.Executable()
if err != nil {
return ""
}
dir := filepath.Dir(exe)
if !strings.Contains(dir, "Program Files") {
// Atypical. Not worth trying to detect. Likely open
// source tailscaled or a developer running by hand.
return ""
}
nsisUninstaller := filepath.Join(dir, "Uninstall-Tailscale.exe")
_, err = os.Stat(nsisUninstaller)
if err == nil {
return "nsis"
}
if os.IsNotExist(err) {
_, cliErr := os.Stat(filepath.Join(dir, "tailscale.exe"))
_, daemonErr := os.Stat(filepath.Join(dir, "tailscaled.exe"))
if cliErr == nil && daemonErr == nil {
// Almost certainly MSI.
// We have tailscaled.exe and tailscale.exe
// next to each other in Program Files, but no
// uninstaller.
// TODO(bradfitz,dblohm7): tighter heuristic?
return "msi"
}
}
return ""
}