Browse Source

hostinfo: fix earlier git fail, add files lost in move

This was meant to be part of 47045265b9b340418fbfe08e50297dc875e54ce9
which instead deleted them :(

Updates tailscale/corp#1959
Brad Fitzpatrick 4 years ago
parent
commit
3ac731dda1
3 changed files with 161 additions and 0 deletions
  1. 93 0
      hostinfo/hostinfo_linux.go
  2. 29 0
      hostinfo/hostinfo_test.go
  3. 39 0
      hostinfo/hostinfo_windows.go

+ 93 - 0
hostinfo/hostinfo_linux.go

@@ -0,0 +1,93 @@
+// 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.
+
+//go:build linux && !android
+// +build linux,!android
+
+package hostinfo
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"strings"
+	"syscall"
+
+	"tailscale.com/util/lineread"
+	"tailscale.com/version/distro"
+)
+
+func init() {
+	osVersion = osVersionLinux
+}
+
+func osVersionLinux() string {
+	dist := distro.Get()
+	propFile := "/etc/os-release"
+	switch dist {
+	case distro.Synology:
+		propFile = "/etc.defaults/VERSION"
+	case distro.OpenWrt:
+		propFile = "/etc/openwrt_release"
+	}
+
+	m := map[string]string{}
+	lineread.File(propFile, func(line []byte) error {
+		eq := bytes.IndexByte(line, '=')
+		if eq == -1 {
+			return nil
+		}
+		k, v := string(line[:eq]), strings.Trim(string(line[eq+1:]), `"'`)
+		m[k] = v
+		return nil
+	})
+
+	var un syscall.Utsname
+	syscall.Uname(&un)
+
+	var attrBuf strings.Builder
+	attrBuf.WriteString("; kernel=")
+	for _, b := range un.Release {
+		if b == 0 {
+			break
+		}
+		attrBuf.WriteByte(byte(b))
+	}
+	if inContainer() {
+		attrBuf.WriteString("; container")
+	}
+	if env := GetEnvType(); env != "" {
+		fmt.Fprintf(&attrBuf, "; env=%s", env)
+	}
+	attr := attrBuf.String()
+
+	id := m["ID"]
+
+	switch id {
+	case "debian":
+		slurp, _ := ioutil.ReadFile("/etc/debian_version")
+		return fmt.Sprintf("Debian %s (%s)%s", bytes.TrimSpace(slurp), m["VERSION_CODENAME"], attr)
+	case "ubuntu":
+		return fmt.Sprintf("Ubuntu %s%s", m["VERSION"], attr)
+	case "", "centos": // CentOS 6 has no /etc/os-release, so its id is ""
+		if cr, _ := ioutil.ReadFile("/etc/centos-release"); len(cr) > 0 { // "CentOS release 6.10 (Final)
+			return fmt.Sprintf("%s%s", bytes.TrimSpace(cr), attr)
+		}
+		fallthrough
+	case "fedora", "rhel", "alpine", "nixos":
+		// Their PRETTY_NAME is fine as-is for all versions I tested.
+		fallthrough
+	default:
+		if v := m["PRETTY_NAME"]; v != "" {
+			return fmt.Sprintf("%s%s", v, attr)
+		}
+	}
+	switch dist {
+	case distro.Synology:
+		return fmt.Sprintf("Synology %s%s", m["productversion"], attr)
+	case distro.OpenWrt:
+		return fmt.Sprintf("OpenWrt %s%s", m["DISTRIB_RELEASE"], attr)
+	}
+	return fmt.Sprintf("Other%s", attr)
+}

+ 29 - 0
hostinfo/hostinfo_test.go

@@ -0,0 +1,29 @@
+// 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
+
+import (
+	"encoding/json"
+	"testing"
+)
+
+func TestNew(t *testing.T) {
+	hi := New()
+	if hi == nil {
+		t.Fatal("no Hostinfo")
+	}
+	j, err := json.MarshalIndent(hi, "  ", "")
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Logf("Got: %s", j)
+}
+
+func TestOSVersion(t *testing.T) {
+	if osVersion == nil {
+		t.Skip("not available for OS")
+	}
+	t.Logf("Got: %#q", osVersion())
+}

+ 39 - 0
hostinfo/hostinfo_windows.go

@@ -0,0 +1,39 @@
+// 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
+
+import (
+	"os/exec"
+	"strings"
+	"sync/atomic"
+	"syscall"
+)
+
+func init() {
+	osVersion = osVersionWindows
+}
+
+var winVerCache atomic.Value // of string
+
+func osVersionWindows() string {
+	if s, ok := winVerCache.Load().(string); ok {
+		return s
+	}
+	cmd := exec.Command("cmd", "/c", "ver")
+	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
+	out, _ := cmd.Output() // "\nMicrosoft Windows [Version 10.0.19041.388]\n\n"
+	s := strings.TrimSpace(string(out))
+	s = strings.TrimPrefix(s, "Microsoft Windows [")
+	s = strings.TrimSuffix(s, "]")
+
+	// "Version 10.x.y.z", with "Version" localized. Keep only stuff after the space.
+	if sp := strings.Index(s, " "); sp != -1 {
+		s = s[sp+1:]
+	}
+	if s != "" {
+		winVerCache.Store(s)
+	}
+	return s // "10.0.19041.388", ideally
+}