Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix host on darwin #289

Merged
merged 1 commit into from
Jun 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ test:
- cd $SRCDIR; ./bin/lint .
- cd $SRCDIR; make client-test
- cd $SRCDIR; make static
- cd $SRCDIR; make
- cd $SRCDIR; rm -f app/app probe/probe; GOOS=darwin make

This comment was marked as abuse.

This comment was marked as abuse.

- cd $SRCDIR; rm -f app/app probe/probe; GOOS=linux make
- cd $SRCDIR; ./bin/test -slow
- cd $SRCDIR/experimental; make
post:
Expand Down
31 changes: 3 additions & 28 deletions probe/host/reporter.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package host

import (
"fmt"
"io/ioutil"
"net"
"runtime"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -34,7 +31,6 @@ const (
var (
InterfaceAddrs = net.InterfaceAddrs
Now = func() string { return time.Now().UTC().Format(time.RFC3339Nano) }
ReadFile = ioutil.ReadFile
)

type reporter struct {
Expand All @@ -51,27 +47,6 @@ func NewReporter(hostID, hostName string) tag.Reporter {
}
}

func getUptime() (time.Duration, error) {
var result time.Duration

buf, err := ReadFile(ProcUptime)
if err != nil {
return result, err
}

fields := strings.Fields(string(buf))
if len(fields) != 2 {
return result, fmt.Errorf("invalid format: %s", string(buf))
}

uptime, err := strconv.ParseFloat(fields[0], 64)
if err != nil {
return result, err
}

return time.Duration(uptime) * time.Second, nil
}

func (r *reporter) Report() (report.Report, error) {
var (
rep = report.MakeReport()
Expand All @@ -89,12 +64,12 @@ func (r *reporter) Report() (report.Report, error) {
}
}

uptime, err := getUptime()
uptime, err := GetUptime()
if err != nil {
return rep, err
}

kernel, err := getKernelVersion()
kernel, err := GetKernelVersion()
if err != nil {
return rep, err
}
Expand All @@ -104,7 +79,7 @@ func (r *reporter) Report() (report.Report, error) {
HostName: r.hostName,
LocalNetworks: strings.Join(localCIDRs, " "),
OS: runtime.GOOS,
Load: getLoad(),
Load: GetLoad(),
KernelVersion: kernel,
Uptime: uptime.String(),
}
Expand Down
67 changes: 23 additions & 44 deletions probe/host/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,71 +4,49 @@ import (
"net"
"reflect"
"runtime"
"syscall"
"testing"
"time"

"github.com/weaveworks/scope/probe/host"
"github.com/weaveworks/scope/report"
"github.com/weaveworks/scope/test"
)

const (
procLoad = "0.59 0.36 0.29 1/200 12187"
procUptime = "1004143.23 1263220.30"
release = "release"
version = "version"

release = "release"
version = "version"
network = "192.168.0.0/16"
hostid = "hostid"
hostID = "hostid"
now = "now"
hostname = "hostname"
load = "0.59 0.36 0.29"
uptime = "278h55m43s"
kernel = "release version"
)

func string2c(s string) [65]int8 {
var result [65]int8
for i, c := range s {
result[i] = int8(c)
}
return result
}

func TestReporter(t *testing.T) {
oldInterfaceAddrs, oldNow, oldReadFile, oldUname := host.InterfaceAddrs, host.Now, host.ReadFile, host.Uname
var (
oldGetKernelVersion = host.GetKernelVersion
oldGetLoad = host.GetLoad
oldGetUptime = host.GetUptime
oldInterfaceAddrs = host.InterfaceAddrs
oldNow = host.Now
)
defer func() {
host.InterfaceAddrs, host.Now, host.ReadFile, host.Uname = oldInterfaceAddrs, oldNow, oldReadFile, oldUname
host.GetKernelVersion = oldGetKernelVersion
host.GetLoad = oldGetLoad
host.GetUptime = oldGetUptime
host.InterfaceAddrs = oldInterfaceAddrs
host.Now = oldNow
}()

host.InterfaceAddrs = func() ([]net.Addr, error) {
_, ipnet, _ := net.ParseCIDR(network)
return []net.Addr{ipnet}, nil
}

host.GetKernelVersion = func() (string, error) { return release + " " + version, nil }
host.GetLoad = func() string { return load }
host.GetUptime = func() (time.Duration, error) { return time.ParseDuration(uptime) }
host.Now = func() string { return now }
host.InterfaceAddrs = func() ([]net.Addr, error) { _, ipnet, _ := net.ParseCIDR(network); return []net.Addr{ipnet}, nil }

host.ReadFile = func(filename string) ([]byte, error) {
switch filename {
case host.ProcUptime:
return []byte(procUptime), nil
case host.ProcLoad:
return []byte(procLoad), nil
default:
panic(filename)
}
}

host.Uname = func(uts *syscall.Utsname) error {
uts.Release = string2c(release)
uts.Version = string2c(version)
return nil
}

r := host.NewReporter(hostid, hostname)
have, _ := r.Report()
want := report.MakeReport()
want.Host.NodeMetadatas[report.MakeHostNodeID(hostid)] = report.NodeMetadata{
want.Host.NodeMetadatas[report.MakeHostNodeID(hostID)] = report.NodeMetadata{
host.Timestamp: now,
host.HostName: hostname,
host.LocalNetworks: network,
Expand All @@ -77,7 +55,8 @@ func TestReporter(t *testing.T) {
host.Uptime: uptime,
host.KernelVersion: kernel,
}

r := host.NewReporter(hostID, hostname)
have, _ := r.Report()
if !reflect.DeepEqual(want, have) {
t.Errorf("%s", test.Diff(want, have))
}
Expand Down
49 changes: 45 additions & 4 deletions probe/host/system_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,31 @@ import (
"fmt"
"os/exec"
"regexp"
"strconv"
"time"
)

var loadRe = regexp.MustCompile(`load average\: ([0-9\.]+), ([0-9\.]+), ([0-9\.]+)`)
var (
unameRe = regexp.MustCompile(`Darwin Kernel Version ([0-9\.]+)\:`)
loadRe = regexp.MustCompile(`load averages: ([0-9\.]+) ([0-9\.]+) ([0-9\.]+)`)
uptimeRe = regexp.MustCompile(`up ([0-9]+) day[s]*,[ ]+([0-9]+)\:([0-9][0-9])`)
)

func getKernelVersion() (string, error) {
return "", nil
// GetKernelVersion returns the kernel version as reported by uname.
var GetKernelVersion = func() (string, error) {
out, err := exec.Command("uname", "-v").CombinedOutput()
if err != nil {
return "Darwin unknown", err
}
matches := unameRe.FindAllStringSubmatch(string(out), -1)
if matches == nil || len(matches) < 1 || len(matches[0]) < 1 {
return "Darwin unknown", nil
}
return fmt.Sprintf("Darwin %s", matches[0][1]), nil
}

func getLoad() string {
// GetLoad returns the current load averages in standard form.
var GetLoad = func() string {
out, err := exec.Command("w").CombinedOutput()
if err != nil {
return "unknown"
Expand All @@ -23,3 +39,28 @@ func getLoad() string {
}
return fmt.Sprintf("%s %s %s", matches[0][1], matches[0][2], matches[0][3])
}

// GetUptime returns the uptime of the host.
var GetUptime = func() (time.Duration, error) {
out, err := exec.Command("w").CombinedOutput()
if err != nil {
return 0, err
}
matches := uptimeRe.FindAllStringSubmatch(string(out), -1)
if matches == nil || len(matches) < 1 || len(matches[0]) < 4 {
return 0, err
}
d, err := strconv.Atoi(matches[0][1])
if err != nil {
return 0, err
}
h, err := strconv.Atoi(matches[0][2])
if err != nil {
return 0, err
}
m, err := strconv.Atoi(matches[0][3])
if err != nil {
return 0, err
}
return (time.Duration(d) * 24 * time.Hour) + (time.Duration(h) * time.Hour) + (time.Duration(m) * time.Minute), nil
}
34 changes: 29 additions & 5 deletions probe/host/system_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package host

import (
"fmt"
"io/ioutil"
"strconv"
"strings"
"syscall"
"time"
)

// Uname exported for testing
// Uname is swappable for mocking in tests.
var Uname = syscall.Uname

func charsToString(ca [65]int8) string {
Expand All @@ -22,16 +24,18 @@ func charsToString(ca [65]int8) string {
return string(s[0:lens])
}

func getKernelVersion() (string, error) {
// GetKernelVersion returns the kernel version as reported by uname.
var GetKernelVersion = func() (string, error) {
var utsname syscall.Utsname
if err := Uname(&utsname); err != nil {
return "", err
return "unknown", err
}
return fmt.Sprintf("%s %s", charsToString(utsname.Release), charsToString(utsname.Version)), nil
}

func getLoad() string {
buf, err := ReadFile(ProcLoad)
// GetLoad returns the current load averages in standard form.
var GetLoad = func() string {
buf, err := ioutil.ReadFile("/proc/loadavg")
if err != nil {
return "unknown"
}
Expand All @@ -53,3 +57,23 @@ func getLoad() string {
}
return fmt.Sprintf("%.2f %.2f %.2f", one, five, fifteen)
}

// GetUptime returns the uptime of the host.
var GetUptime = func() (time.Duration, error) {
buf, err := ioutil.ReadFile("/proc/uptime")
if err != nil {
return 0, err
}

fields := strings.Fields(string(buf))
if len(fields) != 2 {
return 0, fmt.Errorf("invalid format: %s", string(buf))
}

uptime, err := strconv.ParseFloat(fields[0], 64)
if err != nil {
return 0, err
}

return time.Duration(uptime) * time.Second, nil
}
40 changes: 40 additions & 0 deletions probe/host/system_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package host_test

import (
"fmt"
"syscall"
"testing"

"github.com/weaveworks/scope/probe/host"
)

func TestUname(t *testing.T) {
oldUname := host.Uname
defer func() { host.Uname = oldUname }()

const (
release = "rls"
version = "ver"
)
host.Uname = func(uts *syscall.Utsname) error {
uts.Release = string2c(release)
uts.Version = string2c(version)
return nil
}

have, err := host.GetKernelVersion()
if err != nil {
t.Fatal(err)
}
if want := fmt.Sprintf("%s %s", release, version); want != have {
t.Errorf("want %q, have %q", want, have)
}
}

func string2c(s string) [65]int8 {
var result [65]int8
for i, c := range s {
result[i] = int8(c)
}
return result
}
38 changes: 38 additions & 0 deletions probe/host/system_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package host_test

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.

This comment was marked as abuse.


import (
"strings"
"testing"

"github.com/weaveworks/scope/probe/host"
)

func TestGetKernelVersion(t *testing.T) {
have, err := host.GetKernelVersion()
if err != nil {
t.Fatal(err)
}
if strings.Contains(have, "unknown") {
t.Fatal(have)
}
t.Log(have)
}

func TestGetLoad(t *testing.T) {
have := host.GetLoad()
if strings.Contains(have, "unknown") {
t.Fatal(have)
}
t.Log(have)
}

func TestGetUptime(t *testing.T) {
have, err := host.GetUptime()
if err != nil {
t.Fatal(err)
}
if have == 0 {
t.Fatal(have)
}
t.Log(have.String())
}