HostMetadata becomes Host Topology

- All HostMetadata information becomes NodeMetadata
- Significant change to mechanics, but same net effect
- LocalNets becomes "local_networks", space-separated list of CIDRs
- Load becomes simple single string
- Use MakeHostNodeID for indexing into Host topology
- (That changes the app /origin/{id} handler; will be removed later)
This commit is contained in:
Peter Bourgon
2015-06-09 15:38:08 +02:00
parent 1e0b83eb6d
commit d438261742
20 changed files with 180 additions and 365 deletions

View File

@@ -66,7 +66,7 @@ func handleNode(rep Reporter, t topologyView, w http.ResponseWriter, r *http.Req
http.NotFound(w, r)
return
}
originHostFunc := func(id string) (OriginHost, bool) { return getOriginHost(rpt.HostMetadatas, id) }
originHostFunc := func(id string) (OriginHost, bool) { return getOriginHost(rpt.Host, id) }
originNodeFunc := func(id string) (OriginNode, bool) { return getOriginNode(t.selector(rpt), id) }
respondWith(w, http.StatusOK, APINode{Node: makeDetailed(node, originHostFunc, originNodeFunc)})
}

View File

@@ -56,9 +56,8 @@ outer:
Numeric: false,
Rows: []report.Row{
{"Hostname", host.Hostname, ""},
{"Load", fmt.Sprintf("%.2f %.2f %.2f", host.LoadOne, host.LoadFive, host.LoadFifteen), ""},
{"Load", host.Load, ""},
{"OS", host.OS, ""},
//{"Addresses", strings.Join(host.Addresses, ", "), ""},
{"ID", id, ""},
},
})
@@ -75,12 +74,10 @@ outer:
func unknownOriginHost(id string) OriginHost {
return OriginHost{
Hostname: fmt.Sprintf("[%s]", id),
OS: "unknown",
Addresses: []string{},
LoadOne: 0.0,
LoadFive: 0.0,
LoadFifteen: 0.0,
Hostname: fmt.Sprintf("[%s]", id),
OS: "unknown",
Networks: []string{},
Load: "",
}
}

View File

@@ -115,19 +115,21 @@ func (s StaticReport) Report() report.Report {
},
},
HostMetadatas: report.HostMetadatas{
"hostA": report.HostMetadata{
Hostname: "node-a.local",
LocalNets: []*net.IPNet{localNet},
OS: "Linux",
LoadOne: 3.1415,
LoadFive: 2.7182,
LoadFifteen: 1.6180,
},
"hostB": report.HostMetadata{
Hostname: "node-b.local",
LocalNets: []*net.IPNet{localNet},
OS: "Linux",
Host: report.Topology{
Adjacency: report.Adjacency{},
EdgeMetadatas: report.EdgeMetadatas{},
NodeMetadatas: report.NodeMetadatas{
report.MakeHostNodeID("hostA"): report.NodeMetadata{
"host_name": "node-a.local",
"os": "Linux",
"local_networks": localNet.String(),
"load": "3.14 2.71 1.61",
},
report.MakeHostNodeID("hostB"): report.NodeMetadata{
"host_name": "node-b.local",
"os": "Linux",
"local_networks": localNet.String(),
},
},
},
}

View File

@@ -2,6 +2,7 @@ package main
import (
"net/http"
"strings"
"github.com/gorilla/mux"
@@ -12,32 +13,23 @@ import (
// some data in the system. The struct is returned by the /api/origin/{id}
// handler.
type OriginHost struct {
Hostname string `json:"hostname"`
OS string `json:"os"`
Addresses []string `json:"addresses"`
LoadOne float64 `json:"load_one"`
LoadFive float64 `json:"load_five"`
LoadFifteen float64 `json:"load_fifteen"`
Hostname string `json:"hostname"`
OS string `json:"os"`
Networks []string `json:"networks"`
Load string `json:"load"`
}
func getOriginHost(mds report.HostMetadatas, nodeID string) (OriginHost, bool) {
host, ok := mds[nodeID]
func getOriginHost(t report.Topology, nodeID string) (OriginHost, bool) {
host, ok := t.NodeMetadatas[nodeID]
if !ok {
return OriginHost{}, false
}
var addrs []string
for _, l := range host.LocalNets {
addrs = append(addrs, l.String())
}
return OriginHost{
Hostname: host.Hostname,
OS: host.OS,
Addresses: addrs,
LoadOne: host.LoadOne,
LoadFive: host.LoadFive,
LoadFifteen: host.LoadFifteen,
Hostname: host["host_name"],
OS: host["os"],
Networks: strings.Split(host["local_networks"], " "),
Load: host["load"],
}, true
}
@@ -48,7 +40,7 @@ func makeOriginHostHandler(rep Reporter) http.HandlerFunc {
vars = mux.Vars(r)
nodeID = vars["id"]
)
origin, ok := getOriginHost(rep.Report().HostMetadatas, nodeID)
origin, ok := getOriginHost(rep.Report().Host, nodeID)
if !ok {
http.NotFound(w, r)
return

View File

@@ -15,7 +15,7 @@ func TestAPIOriginHost(t *testing.T) {
{
// Origin
body := getRawJSON(t, ts, "/api/origin/host/hostA")
body := getRawJSON(t, ts, "/api/origin/host/hostA;<host>") // TODO MakeHostNodeID
var o OriginHost
if err := json.Unmarshal(body, &o); err != nil {
t.Fatalf("JSON parse error: %s", err)
@@ -23,13 +23,7 @@ func TestAPIOriginHost(t *testing.T) {
if want, have := "Linux", o.OS; want != have {
t.Errorf("Origin error. Want %v, have %v", want, have)
}
if want, have := 3.1415, o.LoadOne; want != have {
t.Errorf("Origin error. Want %v, have %v", want, have)
}
if want, have := 2.7182, o.LoadFive; want != have {
t.Errorf("Origin error. Want %v, have %v", want, have)
}
if want, have := 1.6180, o.LoadFifteen; want != have {
if want, have := "3.14 2.71 1.61", o.Load; want != have {
t.Errorf("Origin error. Want %v, have %v", want, have)
}
}

View File

@@ -71,17 +71,19 @@ func checkRequest(t *testing.T, ts *httptest.Server, method, path string, body [
func getRawJSON(t *testing.T, ts *httptest.Server, path string) []byte {
res, body := checkGet(t, ts, path)
_, file, line, _ := runtime.Caller(1)
file = filepath.Base(file)
if res.StatusCode != 200 {
t.Fatalf("Expected status %d, got %d. Path: %s", 200, res.StatusCode, path)
t.Fatalf("%s:%d: Expected status %d, got %d. Path: %s", file, line, 200, res.StatusCode, path)
}
foundCtype := res.Header.Get("content-type")
if foundCtype != "application/json" {
t.Errorf("Wrong Content-type for JSON: %s", foundCtype)
t.Errorf("%s:%d: Wrong Content-type for JSON: %s", file, line, foundCtype)
}
if len(body) == 0 {
t.Errorf("No response body")
t.Errorf("%s:%d: No response body", file, line)
}
// fmt.Printf("Body: %s", body)

View File

@@ -127,7 +127,7 @@ func discover(c collector, p publisher, fixed []string) {
var (
now = time.Now()
localNets = r.LocalNets()
localNets = r.LocalNetworks()
)
for _, adjacent := range r.Address.Adjacency {

View File

@@ -112,11 +112,11 @@ func DemoReport(nodeCount int) report.Report {
r.Address.Adjacency[nodeDstAddressID] = r.Address.Adjacency[nodeDstAddressID].Add(srcAddressID)
// Host data
r.HostMetadatas["hostX"] = report.HostMetadata{
Timestamp: time.Now().UTC(),
Hostname: "host-x",
LocalNets: []*net.IPNet{localNet},
OS: "linux",
r.Host.NodeMetadatas["hostX"] = report.NodeMetadata{
"ts": time.Now().UTC().Format(time.RFC3339Nano),
"host_name": "host-x",
"local_networks": localNet.String(),
"os": "linux",
}
}

View File

@@ -112,11 +112,11 @@ func DemoReport(nodeCount int) report.Report {
r.Address.Adjacency[nodeDstAddressID] = r.Address.Adjacency[nodeDstAddressID].Add(srcAddressID)
// Host data
r.HostMetadatas["hostX"] = report.HostMetadata{
Timestamp: time.Now().UTC(),
Hostname: "host-x",
LocalNets: []*net.IPNet{localNet},
OS: "linux",
r.Host.NodeMetadatas["hostX"] = report.NodeMetadata{
"ts": time.Now().UTC().Format(time.RFC3339Nano),
"host_name": "host-x",
"local_networks": localNet.String(),
"os": "linux",
}
}

View File

@@ -9,6 +9,7 @@ import (
"os/signal"
"runtime"
"strconv"
"strings"
"syscall"
"time"
@@ -79,8 +80,8 @@ func main() {
defer close(quit)
go func() {
var (
hostname = hostname()
nodeID = hostname // TODO: we should sanitize the hostname
hostName = hostname()
hostID = hostName // TODO: we should sanitize the hostname
pubTick = time.Tick(*publishInterval)
spyTick = time.Tick(*spyInterval)
r = report.MakeReport()
@@ -90,12 +91,12 @@ func main() {
select {
case <-pubTick:
publishTicks.WithLabelValues().Add(1)
r.HostMetadatas[nodeID] = hostMetadata(hostname)
r.Host = hostTopology(hostID, hostName)
publisher.Publish(r)
r = report.MakeReport()
case <-spyTick:
r.Merge(spy(hostname, hostname, *spyProcs))
r.Merge(spy(hostID, hostName, *spyProcs))
r = tag.Apply(r, taggers)
// log.Printf("merged report:\n%#v\n", r)
@@ -108,34 +109,31 @@ func main() {
log.Printf("%s", <-interrupt())
}
// hostTopology produces a host topology for this host. No need to do this
// more than once per published report.
func hostTopology(hostID, hostName string) report.Topology {
var localCIDRs []string
if localNets, err := net.InterfaceAddrs(); err == nil {
// Not all networks are IP networks.
for _, localNet := range localNets {
if ipNet, ok := localNet.(*net.IPNet); ok {
localCIDRs = append(localCIDRs, ipNet.String())
}
}
}
t := report.NewTopology()
t.NodeMetadatas[report.MakeHostNodeID(hostID)] = report.NodeMetadata{
"ts": time.Now().UTC().Format(time.RFC3339Nano),
"host_name": hostName,
"local_networks": strings.Join(localCIDRs, " "),
"os": runtime.GOOS,
"load": getLoad(),
}
return t
}
func interrupt() chan os.Signal {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
return c
}
// hostMetadata produces an instantaneous HostMetadata for this host. No need
// to do this more than once per published report.
func hostMetadata(hostname string) report.HostMetadata {
loadOne, loadFive, loadFifteen := getLoads()
host := report.HostMetadata{
Timestamp: time.Now().UTC(),
Hostname: hostname,
OS: runtime.GOOS,
LoadOne: loadOne,
LoadFive: loadFive,
LoadFifteen: loadFifteen,
}
if localNets, err := net.InterfaceAddrs(); err == nil {
// Not all networks are IP networks.
for _, localNet := range localNets {
if net, ok := localNet.(*net.IPNet); ok {
host.LocalNets = append(host.LocalNets, net)
}
}
}
return host
}

View File

@@ -1,33 +1,21 @@
package main
import (
"fmt"
"os/exec"
"strconv"
"strings"
"regexp"
)
func getLoads() (float64, float64, float64) {
var loadRe = regexp.MustCompile(`load average\: ([0-9\.]+), ([0-9\.]+), ([0-9\.]+)`)
func getLoad() string {
out, err := exec.Command("w").CombinedOutput()
if err != nil {
return -1, -1, -1
return "unknown"
}
noCommas := strings.NewReplacer(",", "")
firstLine := strings.Split(string(out), "\n")[0]
toks := strings.Fields(firstLine)
if len(toks) < 5 {
return -1, -1, -1
matches := loadRe.FindAllStringSubmatch(string(out), -1)
if matches == nil || len(matches) < 1 || len(matches[0]) < 4 {
return "unknown"
}
one, err := strconv.ParseFloat(noCommas.Replace(toks[len(toks)-3]), 64)
if err != nil {
return -1, -1, -1
}
five, err := strconv.ParseFloat(noCommas.Replace(toks[len(toks)-2]), 64)
if err != nil {
return -1, -1, -1
}
fifteen, err := strconv.ParseFloat(noCommas.Replace(toks[len(toks)-1]), 64)
if err != nil {
return -1, -1, -1
}
return one, five, fifteen
return fmt.Sprintf("%s %s %s", matches[0][1], matches[0][2], matches[0][3])
}

View File

@@ -1,31 +1,32 @@
package main
import (
"fmt"
"io/ioutil"
"strconv"
"strings"
)
func getLoads() (float64, float64, float64) {
func getLoad() string {
buf, err := ioutil.ReadFile("/proc/loadavg")
if err != nil {
return -1, -1, -1
return "unknown"
}
toks := strings.Fields(string(buf))
if len(toks) < 3 {
return -1, -1, -1
return "unknown"
}
one, err := strconv.ParseFloat(toks[0], 64)
if err != nil {
return -1, -1, -1
return "unknown"
}
five, err := strconv.ParseFloat(toks[1], 64)
if err != nil {
return -1, -1, -1
return "unknown"
}
fifteen, err := strconv.ParseFloat(toks[2], 64)
if err != nil {
return -1, -1, -1
return "unknown"
}
return one, five, fifteen
return fmt.Sprintf("%.2f %.2f %.2f", one, five, fifteen)
}

21
report/diff_test.go Normal file
View File

@@ -0,0 +1,21 @@
package report_test
import (
"github.com/davecgh/go-spew/spew"
"github.com/pmezard/go-difflib/difflib"
)
func init() {
spew.Config.SortKeys = true // :\
}
func diff(want, have interface{}) string {
text, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
A: difflib.SplitLines(spew.Sdump(want)),
B: difflib.SplitLines(spew.Sdump(have)),
FromFile: "want",
ToFile: "have",
Context: 5,
})
return "\n" + text
}

View File

@@ -8,7 +8,7 @@ package report
func (r *Report) Merge(other Report) {
r.Endpoint.Merge(other.Endpoint)
r.Address.Merge(other.Address)
r.HostMetadatas.Merge(other.HostMetadatas)
r.Host.Merge(other.Host)
}
// Merge merges another Topology into the receiver.
@@ -45,20 +45,6 @@ func (e *EdgeMetadatas) Merge(other EdgeMetadatas) {
}
}
// Merge merges another HostMetadata into the receiver.
// It'll takes the lastest version if there are conflicts.
func (e *HostMetadatas) Merge(other HostMetadatas) {
for hostID, meta := range other {
if existing, ok := (*e)[hostID]; ok {
// Conflict. Take the newest.
if existing.Timestamp.After(meta.Timestamp) {
continue
}
}
(*e)[hostID] = meta
}
}
// Merge merges another EdgeMetadata into the receiver. The two edge metadatas
// should represent the same edge on different times.
func (m *EdgeMetadata) Merge(other EdgeMetadata) {

View File

@@ -3,7 +3,6 @@ package report
import (
"reflect"
"testing"
"time"
)
func TestMergeAdjacency(t *testing.T) {
@@ -215,107 +214,6 @@ func TestMergeEdgeMetadatas(t *testing.T) {
}
}
func TestMergeHostMetadatas(t *testing.T) {
now := time.Now()
for name, c := range map[string]struct {
a, b, want HostMetadatas
}{
"Empty a": {
a: HostMetadatas{},
b: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux",
},
},
want: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux",
},
},
},
"Empty b": {
a: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux",
},
},
b: HostMetadatas{},
want: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux",
},
},
},
"Host merge": {
a: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux",
},
},
b: HostMetadatas{
"hostB": HostMetadata{
Timestamp: now,
Hostname: "host-b",
OS: "freedos",
},
},
want: HostMetadatas{
"hostB": HostMetadata{
Timestamp: now,
Hostname: "host-b",
OS: "freedos",
},
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux",
},
},
},
"Host conflict": {
a: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux1",
},
},
b: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now.Add(-10 * time.Second),
Hostname: "host-a",
OS: "linux0",
},
},
want: HostMetadatas{
"hostA": HostMetadata{
Timestamp: now,
Hostname: "host-a",
OS: "linux1",
},
},
},
} {
have := c.a
have.Merge(c.b)
if !reflect.DeepEqual(c.want, have) {
t.Errorf("%s: want\n\t%#v, have\n\t%#v", name, c.want, have)
}
}
}
func TestMergeNodeMetadatas(t *testing.T) {
for name, c := range map[string]struct {
a, b, want NodeMetadatas

View File

@@ -1,9 +1,8 @@
package report
import (
"encoding/json"
"net"
"time"
"strings"
)
// Report is the core data type. It's produced by probes, and consumed and
@@ -20,20 +19,10 @@ type Report struct {
// endpoints (e.g. ICMP). Edges are present.
Address Topology
HostMetadatas
}
// HostMetadatas contains metadata about the host(s) represented in the Report.
type HostMetadatas map[string]HostMetadata
// HostMetadata describes metadata that probes can collect about the host that
// they run on. It has a timestamp when the measurement was made.
type HostMetadata struct {
Timestamp time.Time
Hostname string
LocalNets []*net.IPNet
OS string
LoadOne, LoadFive, LoadFifteen float64
// Host nodes are physical hosts that run probes. Metadata includes things
// like operating system, load, etc. The information is scraped by the
// probes with each published report. Edges are not present.
Host Topology
}
// RenderableNode is the data type that's yielded to the JavaScript layer as
@@ -79,9 +68,9 @@ type Row struct {
// MakeReport makes a clean report, ready to Merge() other reports into.
func MakeReport() Report {
return Report{
Endpoint: NewTopology(),
Address: NewTopology(),
HostMetadatas: map[string]HostMetadata{},
Endpoint: NewTopology(),
Address: NewTopology(),
Host: NewTopology(),
}
}
@@ -89,59 +78,38 @@ func MakeReport() Report {
// LocalNets of the hosts in HostMetadata to determine which addresses are
// local.
func (r Report) SquashRemote() Report {
localNets := r.HostMetadatas.LocalNets()
localNetworks := r.LocalNetworks()
return Report{
Endpoint: Squash(r.Endpoint, EndpointIDAddresser, localNets),
Address: Squash(r.Address, AddressIDAddresser, localNets),
HostMetadatas: r.HostMetadatas,
Endpoint: Squash(r.Endpoint, EndpointIDAddresser, localNetworks),
Address: Squash(r.Address, AddressIDAddresser, localNetworks),
Host: Squash(r.Host, PanicIDAddresser, localNetworks),
}
}
// LocalNets gives the union of all local network IPNets for all hosts
// represented in the HostMetadatas.
func (m HostMetadatas) LocalNets() []*net.IPNet {
var nets []*net.IPNet
for _, node := range m {
OUTER:
for _, local := range node.LocalNets {
for _, existing := range nets {
if existing == local {
continue OUTER
// LocalNetworks returns a superset of the networks (think: CIDRs) that are
// "local" from the perspective of each host represented in the report. It's
// used to determine which nodes in the report are "remote", i.e. outside of
// our infrastructure.
func (r Report) LocalNetworks() []*net.IPNet {
var ipNets []*net.IPNet
for _, md := range r.Host.NodeMetadatas {
val, ok := md["local_networks"]
if !ok {
continue
}
outer:
for _, s := range strings.Fields(val) {
_, ipNet, err := net.ParseCIDR(s)
if err != nil {
continue
}
for _, existing := range ipNets {
if ipNet.String() == existing.String() {
continue outer
}
}
nets = append(nets, local)
ipNets = append(ipNets, ipNet)
}
}
return nets
}
// UnmarshalJSON is a custom JSON deserializer for HostMetadata to deal with
// the Localnets.
func (m *HostMetadata) UnmarshalJSON(data []byte) error {
type netmask struct {
IP net.IP
Mask []byte
}
tmpHMD := struct {
Timestamp time.Time
Hostname string
LocalNets []*netmask
OS string
LoadOne, LoadFive, LoadFifteen float64
}{}
err := json.Unmarshal(data, &tmpHMD)
if err != nil {
return err
}
m.Timestamp = tmpHMD.Timestamp
m.Hostname = tmpHMD.Hostname
m.OS = tmpHMD.OS
m.LoadOne = tmpHMD.LoadOne
m.LoadFive = tmpHMD.LoadFive
m.LoadFifteen = tmpHMD.LoadFifteen
for _, ln := range tmpHMD.LocalNets {
m.LocalNets = append(m.LocalNets, &net.IPNet{IP: ln.IP, Mask: ln.Mask})
}
return nil
return ipNets
}

View File

@@ -1,37 +1 @@
package report
import (
"encoding/json"
"fmt"
"net"
"testing"
"time"
)
func TestHostJSON(t *testing.T) {
_, localNet, _ := net.ParseCIDR("192.168.1.2/16")
host := HostMetadata{
Timestamp: time.Now(),
Hostname: "euclid",
LocalNets: []*net.IPNet{localNet},
OS: "linux",
}
e, err := json.Marshal(host)
if err != nil {
t.Fatalf("Marshal error: %v", err)
}
var hostAgain HostMetadata
err = json.Unmarshal(e, &hostAgain)
if err != nil {
t.Fatalf("Unarshal error: %v", err)
}
// need to compare pointers. No fun.
want := fmt.Sprintf("%+v", host)
got := fmt.Sprintf("%+v", hostAgain)
if want != got {
t.Errorf("Host not the same. Want \n%+v, got \n%+v", want, got)
}
}

View File

@@ -112,21 +112,25 @@ func reportToSquash() Report {
},
},
HostMetadatas: HostMetadatas{
"hostA": HostMetadata{
Hostname: "node-a.local",
OS: "Linux",
LocalNets: []*net.IPNet{netdot1},
},
"hostB": HostMetadata{
Hostname: "node-b.local",
OS: "Linux",
LocalNets: []*net.IPNet{netdot1},
},
"hostZ": HostMetadata{
Hostname: "node-z.local",
OS: "Linux",
LocalNets: []*net.IPNet{netdot2},
Host: Topology{
Adjacency: Adjacency{},
EdgeMetadatas: EdgeMetadatas{},
NodeMetadatas: NodeMetadatas{
MakeHostNodeID("hostA"): NodeMetadata{
"host_name": "node-a.local",
"os": "Linux",
"local_networks": netdot1.String(),
},
MakeHostNodeID("hostB"): NodeMetadata{
"host_name": "node-b.local",
"os": "Linux",
"local_networks": netdot1.String(),
},
MakeHostNodeID("hostZ"): NodeMetadata{
"host_name": "node-z.local",
"os": "Linux",
"local_networks": netdot2.String(),
},
},
},
}
@@ -166,7 +170,7 @@ func TestSquashTopology(t *testing.T) {
NodeMetadatas: reportToSquash().Endpoint.NodeMetadatas,
}
have := Squash(reportToSquash().Endpoint, EndpointIDAddresser, reportToSquash().HostMetadatas.LocalNets())
have := Squash(reportToSquash().Endpoint, EndpointIDAddresser, reportToSquash().LocalNetworks())
if !reflect.DeepEqual(want, have) {
t.Errorf("want\n\t%#v, have\n\t%#v", want, have)
}
@@ -246,11 +250,11 @@ func TestSquashReport(t *testing.T) {
},
},
},
HostMetadatas: reportToSquash().HostMetadatas,
Host: reportToSquash().Host,
}
have := reportToSquash().SquashRemote()
if !reflect.DeepEqual(want, have) {
t.Errorf("want\n\t%#v, have\n\t%#v", want, have)
t.Error(diff(want, have))
}
}

View File

@@ -406,5 +406,5 @@ func diff(want, have interface{}) string {
ToFile: "have",
Context: 3,
})
return text
return "\n" + text
}

View File

@@ -39,12 +39,12 @@ func TestMerge(t *testing.T) {
{
r := report.MakeReport()
r.HostMetadatas["p1"] = report.HostMetadata{Hostname: "test1"}
r.Host.NodeMetadatas["p1"] = report.NodeMetadata{"host_name": "test1"}
p1.Publish(r)
}
{
r := report.MakeReport()
r.HostMetadatas["p2"] = report.HostMetadata{Hostname: "test2"}
r.Host.NodeMetadatas["p2"] = report.NodeMetadata{"host_name": "test2"}
p2.Publish(r)
}
@@ -52,10 +52,10 @@ func TestMerge(t *testing.T) {
go func() {
defer close(success)
for r := range c.Reports() {
if r.HostMetadatas["p1"].Hostname != "test1" {
if r.Host.NodeMetadatas["p1"]["host_name"] != "test1" {
continue
}
if r.HostMetadatas["p2"].Hostname != "test2" {
if r.Host.NodeMetadatas["p2"]["host_name"] != "test2" {
continue
}
return