Пример #1
0
func (c *container) ports(localAddrs []net.IP) report.StringSet {
	if c.container.NetworkSettings == nil {
		return report.MakeStringSet()
	}

	ports := []string{}
	for port, bindings := range c.container.NetworkSettings.Ports {
		if len(bindings) == 0 {
			ports = append(ports, fmt.Sprintf("%s", port))
			continue
		}
		for _, b := range bindings {
			if b.HostIP != "0.0.0.0" {
				ports = append(ports, fmt.Sprintf("%s:%s->%s", b.HostIP, b.HostPort, port))
				continue
			}

			for _, ip := range localAddrs {
				if ip.To4() != nil {
					ports = append(ports, fmt.Sprintf("%s:%s->%s", ip, b.HostPort, port))
				}
			}
		}
	}

	return report.MakeStringSet(ports...)
}
Пример #2
0
func TestWeaveTaggerOverlayTopology(t *testing.T) {
	oldExecCmd := exec.Command
	defer func() { exec.Command = oldExecCmd }()
	exec.Command = func(name string, args ...string) exec.Cmd {
		return testExec.NewMockCmdString(fmt.Sprintf("%s %s %s/24\n", mockContainerID, mockContainerMAC, mockContainerIP))
	}

	s := httptest.NewServer(http.HandlerFunc(mockWeaveRouter))
	defer s.Close()

	w := overlay.NewWeave(mockHostID, s.URL)
	defer w.Stop()
	w.Tick()

	{
		have, err := w.Report()
		if err != nil {
			t.Fatal(err)
		}
		if want, have := report.MakeTopology().AddNode(
			report.MakeOverlayNodeID(mockWeavePeerName),
			report.MakeNodeWith(map[string]string{
				overlay.WeavePeerName:     mockWeavePeerName,
				overlay.WeavePeerNickName: mockWeavePeerNickName,
			}),
		), have.Overlay; !reflect.DeepEqual(want, have) {
			t.Error(test.Diff(want, have))
		}
	}

	{
		nodeID := report.MakeContainerNodeID(mockHostID, mockContainerID)
		want := report.Report{
			Container: report.MakeTopology().AddNode(nodeID, report.MakeNodeWith(map[string]string{
				docker.ContainerID:       mockContainerID,
				overlay.WeaveDNSHostname: mockHostname,
				overlay.WeaveMACAddress:  mockContainerMAC,
			}).WithSets(report.Sets{
				docker.ContainerIPs:           report.MakeStringSet(mockContainerIP),
				docker.ContainerIPsWithScopes: report.MakeStringSet(mockContainerIPWithScope),
			})),
		}
		have, err := w.Tag(report.Report{
			Container: report.MakeTopology().AddNode(nodeID, report.MakeNodeWith(map[string]string{
				docker.ContainerID: mockContainerID,
			})),
		})
		if err != nil {
			t.Fatal(err)
		}
		if !reflect.DeepEqual(want, have) {
			t.Error(test.Diff(want, have))
		}
	}
}
Пример #3
0
func (t *Tagger) tag(tree process.Tree, topology *report.Topology) {
	for nodeID, node := range topology.Nodes {
		pidStr, ok := node.Latest.Lookup(process.PID)
		if !ok {
			continue
		}

		pid, err := strconv.ParseUint(pidStr, 10, 64)
		if err != nil {
			continue
		}

		var (
			c         Container
			candidate = int(pid)
		)

		t.registry.LockedPIDLookup(func(lookup func(int) Container) {
			for {
				c = lookup(candidate)
				if c != nil {
					break
				}

				candidate, err = tree.GetParent(candidate)
				if err != nil {
					break
				}
			}
		})

		if c == nil || ContainerIsStopped(c) || c.PID() == 1 {
			continue
		}

		node := report.MakeNodeWith(nodeID, map[string]string{
			ContainerID: c.ID(),
		}).WithParents(report.EmptySets.
			Add(report.Container, report.MakeStringSet(report.MakeContainerNodeID(c.ID()))),
		)

		// If we can work out the image name, add a parent tag for it
		image, ok := t.registry.GetContainerImage(c.Image())
		if ok && len(image.RepoTags) > 0 {
			imageName := ImageNameWithoutVersion(image.RepoTags[0])
			node = node.WithParents(report.EmptySets.
				Add(report.ContainerImage, report.MakeStringSet(report.MakeContainerImageNodeID(imageName))),
			)
		}

		topology.AddNode(node)
	}
}
Пример #4
0
func (c *container) GetNode(hostID string, localAddrs []net.IP) report.Node {
	c.RLock()
	defer c.RUnlock()

	ips := append(c.container.NetworkSettings.SecondaryIPAddresses, c.container.NetworkSettings.IPAddress)
	// Treat all Docker IPs as local scoped.
	ipsWithScopes := []string{}
	for _, ip := range ips {
		ipsWithScopes = append(ipsWithScopes, report.MakeScopedAddressNodeID(hostID, ip))
	}

	state := c.State()

	result := report.MakeNodeWith(map[string]string{
		ContainerID:       c.ID(),
		ContainerName:     strings.TrimPrefix(c.container.Name, "/"),
		ContainerCreated:  c.container.Created.Format(time.RFC822),
		ContainerCommand:  c.container.Path + " " + strings.Join(c.container.Args, " "),
		ImageID:           c.container.Image,
		ContainerHostname: c.Hostname(),
		ContainerState:    state,
	}).WithSets(report.EmptySets.
		Add(ContainerPorts, c.ports(localAddrs)).
		Add(ContainerIPs, report.MakeStringSet(ips...)).
		Add(ContainerIPsWithScopes, report.MakeStringSet(ipsWithScopes...)),
	).WithMetrics(
		c.metrics(),
	).WithParents(report.EmptySets.
		Add(report.ContainerImage, report.MakeStringSet(report.MakeContainerImageNodeID(c.container.Image))),
	)

	if c.container.State.Paused {
		result = result.WithControls(UnpauseContainer)
	} else if c.container.State.Running {
		uptime := (mtime.Now().Sub(c.container.State.StartedAt) / time.Second) * time.Second
		result = result.WithLatests(map[string]string{
			ContainerUptime:       uptime.String(),
			ContainerRestartCount: strconv.Itoa(c.container.RestartCount),
		})
		result = result.WithControls(
			RestartContainer, StopContainer, PauseContainer, AttachContainer, ExecContainer,
		)
	} else {
		result = result.WithControls(StartContainer)
	}

	result = AddLabels(result, c.container.Config.Labels)
	result = result.WithMetrics(c.metrics())
	return result
}
Пример #5
0
func TestMakeStringSet(t *testing.T) {
	for _, testcase := range []struct {
		input []string
		want  report.StringSet
	}{
		{input: []string{}, want: report.MakeStringSet()},
		{input: []string{"a"}, want: report.MakeStringSet("a")},
		{input: []string{"a", "a"}, want: report.MakeStringSet("a")},
		{input: []string{"b", "c", "a"}, want: report.MakeStringSet("a", "b", "c")},
	} {
		if want, have := testcase.want, report.MakeStringSet(testcase.input...); !reflect.DeepEqual(want, have) {
			t.Errorf("%v: want %v, have %v", testcase.input, want, have)
		}
	}
}
Пример #6
0
// Tag implements Tagger.
func (w *Weave) Tag(r report.Report) (report.Report, error) {
	w.mtx.RLock()
	defer w.mtx.RUnlock()

	// Put information from weaveDNS on the container nodes
	for _, entry := range w.statusCache.DNS.Entries {
		if entry.Tombstone > 0 {
			continue
		}
		nodeID := report.MakeContainerNodeID(entry.ContainerID)
		node, ok := r.Container.Nodes[nodeID]
		if !ok {
			continue
		}
		w, _ := node.Latest.Lookup(WeaveDNSHostname)
		hostnames := report.IDList(strings.Fields(w))
		hostnames = hostnames.Add(strings.TrimSuffix(entry.Hostname, "."))
		r.Container.Nodes[nodeID] = node.WithLatests(map[string]string{WeaveDNSHostname: strings.Join(hostnames, " ")})
	}

	// Put information from weave ps on the container nodes
	const maxPrefixSize = 12
	for id, node := range r.Container.Nodes {
		prefix, ok := node.Latest.Lookup(docker.ContainerID)
		if !ok {
			continue
		}
		if len(prefix) > maxPrefixSize {
			prefix = prefix[:maxPrefixSize]
		}
		entry, ok := w.psCache[prefix]
		if !ok {
			continue
		}

		ipsWithScope := report.MakeStringSet()
		for _, ip := range entry.IPs {
			ipsWithScope = ipsWithScope.Add(report.MakeAddressNodeID("", ip))
		}
		node = node.WithSet(docker.ContainerIPs, report.MakeStringSet(entry.IPs...))
		node = node.WithSet(docker.ContainerIPsWithScopes, ipsWithScope)
		node = node.WithLatests(map[string]string{
			WeaveMACAddress: entry.MACAddress,
		})
		r.Container.Nodes[id] = node
	}
	return r, nil
}
Пример #7
0
// Render produces a container graph where the the latest metadata contains the
// container image name, if found.
func (r containerWithImageNameRenderer) Render(rpt report.Report, dct Decorator) report.Nodes {
	containers := r.Renderer.Render(rpt, dct)
	images := SelectContainerImage.Render(rpt, dct)

	outputs := report.Nodes{}
	for id, c := range containers {
		outputs[id] = c
		imageID, ok := c.Latest.Lookup(docker.ImageID)
		if !ok {
			continue
		}
		image, ok := images[report.MakeContainerImageNodeID(imageID)]
		if !ok {
			continue
		}
		imageName, ok := image.Latest.Lookup(docker.ImageName)
		if !ok {
			continue
		}
		imageNameWithoutVersion := docker.ImageNameWithoutVersion(imageName)
		imageNodeID := report.MakeContainerImageNodeID(imageNameWithoutVersion)

		output := c.Copy()
		output = propagateLatest(docker.ImageName, image, output)
		output = propagateLatest(docker.ImageLabelPrefix+"works.weave.role", image, output)
		output.Parents = output.Parents.
			Delete(report.ContainerImage).
			Add(report.ContainerImage, report.MakeStringSet(imageNodeID))
		outputs[id] = output
	}
	return outputs
}
Пример #8
0
func (r *Reporter) podTopology(services []Service) (report.Topology, report.Topology, error) {
	pods, containers := report.MakeTopology(), report.MakeTopology()
	selectors := map[string]labels.Selector{}
	for _, service := range services {
		selectors[service.ID()] = service.Selector()
	}
	err := r.client.WalkPods(func(p Pod) error {
		for serviceID, selector := range selectors {
			if selector.Matches(p.Labels()) {
				p.AddServiceID(serviceID)
			}
		}
		nodeID := report.MakePodNodeID(p.Namespace(), p.Name())
		pods = pods.AddNode(nodeID, p.GetNode())

		container := report.MakeNodeWith(map[string]string{
			PodID:     p.ID(),
			Namespace: p.Namespace(),
		}).WithParents(report.EmptySets.Add(report.Pod, report.MakeStringSet(nodeID)))
		for _, containerID := range p.ContainerIDs() {
			containers.AddNode(report.MakeContainerNodeID(containerID), container)
		}
		return nil
	})
	return pods, containers, err
}
Пример #9
0
// Report implements Reporter.
func (w *Weave) Report() (report.Report, error) {
	w.mtx.RLock()
	defer w.mtx.RUnlock()

	r := report.MakeReport()
	r.Container = r.Container.WithMetadataTemplates(report.MetadataTemplates{
		WeaveMACAddress:  {ID: WeaveMACAddress, Label: "Weave MAC", From: report.FromLatest, Priority: 17},
		WeaveDNSHostname: {ID: WeaveDNSHostname, Label: "Weave DNS Name", From: report.FromLatest, Priority: 18},
	})
	for _, peer := range w.statusCache.Router.Peers {
		r.Overlay.AddNode(report.MakeNodeWith(report.MakeOverlayNodeID(peer.Name), map[string]string{
			WeavePeerName:     peer.Name,
			WeavePeerNickName: peer.NickName,
		}))

	}
	if w.statusCache.IPAM.DefaultSubnet != "" {
		r.Overlay.AddNode(
			report.MakeNode(report.MakeOverlayNodeID(w.statusCache.Router.Name)).WithSets(
				report.MakeSets().Add(host.LocalNetworks, report.MakeStringSet(w.statusCache.IPAM.DefaultSubnet)),
			),
		)
	}
	return r, nil
}
Пример #10
0
// Report implements Reporter.
func (r *Reporter) Report() (report.Report, error) {
	var (
		rep        = report.MakeReport()
		localCIDRs []string
	)

	for _, localNet := range r.localNets {
		localCIDRs = append(localCIDRs, localNet.String())
	}

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

	kernel, err := GetKernelVersion()
	if err != nil {
		return rep, err
	}

	rep.Host.AddNode(report.MakeHostNodeID(r.hostID), report.MakeNodeWith(map[string]string{
		Timestamp:     Now(),
		HostName:      r.hostName,
		OS:            runtime.GOOS,
		Load:          GetLoad(),
		KernelVersion: kernel,
		Uptime:        uptime.String(),
	}).WithSets(report.Sets{
		LocalNetworks: report.MakeStringSet(localCIDRs...),
	}))

	return rep, nil
}
Пример #11
0
func (r *Reporter) addConnection(rpt *report.Report, t fourTuple, extraFromNode, extraToNode map[string]string) {
	var (
		fromEndpointNodeID = report.MakeEndpointNodeID(r.hostID, t.fromAddr, strconv.Itoa(int(t.fromPort)))
		toEndpointNodeID   = report.MakeEndpointNodeID(r.hostID, t.toAddr, strconv.Itoa(int(t.toPort)))

		fromNode = report.MakeNodeWith(fromEndpointNodeID, map[string]string{
			Addr: t.fromAddr,
			Port: strconv.Itoa(int(t.fromPort)),
		}).WithEdge(toEndpointNodeID, report.EdgeMetadata{})
		toNode = report.MakeNodeWith(toEndpointNodeID, map[string]string{
			Addr: t.toAddr,
			Port: strconv.Itoa(int(t.toPort)),
		})
	)

	// In case we have a reverse resolution for the IP, we can use it for
	// the name...
	if toNames, err := r.reverseResolver.get(t.toAddr); err == nil {
		toNode = toNode.WithSet(ReverseDNSNames, report.MakeStringSet(toNames...))
	}

	if extraFromNode != nil {
		fromNode = fromNode.WithLatests(extraFromNode)
	}
	if extraToNode != nil {
		toNode = toNode.WithLatests(extraToNode)
	}
	rpt.Endpoint = rpt.Endpoint.AddNode(fromNode)
	rpt.Endpoint = rpt.Endpoint.AddNode(toNode)
}
Пример #12
0
func TestReporter(t *testing.T) {
	var (
		release   = "release"
		version   = "version"
		network   = "192.168.0.0/16"
		hostID    = "hostid"
		hostname  = "hostname"
		timestamp = time.Now()
		load      = report.Metrics{
			host.Load1:    report.MakeMetric().Add(timestamp, 1.0),
			host.Load5:    report.MakeMetric().Add(timestamp, 5.0),
			host.Load15:   report.MakeMetric().Add(timestamp, 15.0),
			host.CPUUsage: report.MakeMetric().Add(timestamp, 30.0).WithMax(100.0),
			host.MemUsage: report.MakeMetric().Add(timestamp, 60.0).WithMax(100.0),
		}
		uptime      = "278h55m43s"
		kernel      = "release version"
		_, ipnet, _ = net.ParseCIDR(network)
		localNets   = report.Networks([]*net.IPNet{ipnet})
	)

	mtime.NowForce(timestamp)
	defer mtime.NowReset()

	var (
		oldGetKernelVersion    = host.GetKernelVersion
		oldGetLoad             = host.GetLoad
		oldGetUptime           = host.GetUptime
		oldGetCPUUsagePercent  = host.GetCPUUsagePercent
		oldGetMemoryUsageBytes = host.GetMemoryUsageBytes
	)
	defer func() {
		host.GetKernelVersion = oldGetKernelVersion
		host.GetLoad = oldGetLoad
		host.GetUptime = oldGetUptime
		host.GetCPUUsagePercent = oldGetCPUUsagePercent
		host.GetMemoryUsageBytes = oldGetMemoryUsageBytes
	}()
	host.GetKernelVersion = func() (string, error) { return release + " " + version, nil }
	host.GetLoad = func(time.Time) report.Metrics { return load }
	host.GetUptime = func() (time.Duration, error) { return time.ParseDuration(uptime) }
	host.GetCPUUsagePercent = func() (float64, float64) { return 30.0, 100.0 }
	host.GetMemoryUsageBytes = func() (float64, float64) { return 60.0, 100.0 }

	want := report.MakeReport()
	want.Host.AddNode(report.MakeHostNodeID(hostID), report.MakeNodeWith(map[string]string{
		host.Timestamp:     timestamp.UTC().Format(time.RFC3339Nano),
		host.HostName:      hostname,
		host.OS:            runtime.GOOS,
		host.Uptime:        uptime,
		host.KernelVersion: kernel,
	}).WithSets(report.Sets{
		host.LocalNetworks: report.MakeStringSet(network),
	}).WithMetrics(load))
	have, _ := host.NewReporter(hostID, hostname, localNets).Report()
	if !reflect.DeepEqual(want, have) {
		t.Errorf("%s", test.Diff(want, have))
	}
}
Пример #13
0
// Tag implements Tagger.
func (w *Weave) Tag(r report.Report) (report.Report, error) {
	w.mtx.RLock()
	defer w.mtx.RUnlock()

	// Put information from weaveDNS on the container nodes
	for _, entry := range w.status.DNS.Entries {
		if entry.Tombstone > 0 {
			continue
		}
		nodeID := report.MakeContainerNodeID(w.hostID, entry.ContainerID)
		node, ok := r.Container.Nodes[nodeID]
		if !ok {
			continue
		}
		hostnames := report.IDList(strings.Fields(node.Metadata[WeaveDNSHostname]))
		hostnames = hostnames.Add(strings.TrimSuffix(entry.Hostname, "."))
		node.Metadata[WeaveDNSHostname] = strings.Join(hostnames, " ")
	}

	// Put information from weave ps on the container nodes
	psEntries, err := w.ps()
	if err != nil {
		return r, nil
	}
	psEntriesByPrefix := map[string]psEntry{}
	for _, entry := range psEntries {
		psEntriesByPrefix[entry.containerIDPrefix] = entry
	}
	for id, node := range r.Container.Nodes {
		prefix := node.Metadata[docker.ContainerID][:12]
		entry, ok := psEntriesByPrefix[prefix]
		if !ok {
			continue
		}

		ipsWithScope := report.MakeStringSet()
		for _, ip := range entry.ips {
			ipsWithScope = ipsWithScope.Add(report.MakeAddressNodeID("", ip))
		}
		node = node.WithSet(docker.ContainerIPs, report.MakeStringSet(entry.ips...))
		node = node.WithSet(docker.ContainerIPsWithScopes, ipsWithScope)
		node.Metadata[WeaveMACAddress] = entry.macAddress
		r.Container.Nodes[id] = node
	}
	return r, nil
}
Пример #14
0
func (t *Tagger) tag(tree process.Tree, topology *report.Topology) {
	for nodeID, node := range topology.Nodes {
		pidStr, ok := node.Latest.Lookup(process.PID)
		if !ok {
			continue
		}

		pid, err := strconv.ParseUint(pidStr, 10, 64)
		if err != nil {
			continue
		}

		var (
			c         Container
			candidate = int(pid)
		)

		t.registry.LockedPIDLookup(func(lookup func(int) Container) {
			for {
				c = lookup(candidate)
				if c != nil {
					break
				}

				candidate, err = tree.GetParent(candidate)
				if err != nil {
					break
				}
			}
		})

		if c == nil || c.State() == StateStopped || c.PID() == 1 {
			continue
		}

		topology.AddNode(nodeID, report.MakeNodeWith(map[string]string{
			ContainerID: c.ID(),
		}).WithParents(report.EmptySets.
			Add(report.Container, report.MakeStringSet(report.MakeContainerNodeID(c.ID()))).
			Add(report.ContainerImage, report.MakeStringSet(report.MakeContainerImageNodeID(c.Image()))),
		))
	}
}
Пример #15
0
func TestSetsMerge(t *testing.T) {
	for _, testcase := range []struct {
		a, b report.Sets
		want map[string][]string
	}{
		{report.EmptySets, report.EmptySets, map[string][]string{}},
		{
			report.EmptySets,
			report.EmptySets.Add("a", report.MakeStringSet("b")),
			map[string][]string{"a": {"b"}},
		},
		{
			report.EmptySets,
			report.EmptySets.Add("a", report.MakeStringSet("b", "c")),
			map[string][]string{"a": {"b", "c"}},
		},
		{
			report.EmptySets.Add("a", report.MakeStringSet("1")).Add("b", report.MakeStringSet("2")),
			report.EmptySets.Add("c", report.MakeStringSet("3")).Add("b", report.MakeStringSet("3")),
			map[string][]string{"a": {"1"}, "b": {"2", "3"}, "c": {"3"}},
		},
	} {
		haveSets := testcase.a.Merge(testcase.b)
		have := map[string][]string{}
		keys := haveSets.Keys()
		for _, k := range keys {
			have[k], _ = haveSets.Lookup(k)
		}

		if !reflect.DeepEqual(testcase.want, have) {
			t.Errorf("%+v.Merge(%+v): want %+v, have %+v", testcase.a, testcase.b, testcase.want, have)
		}
	}
}
Пример #16
0
func TestReporter(t *testing.T) {
	var (
		release   = "release"
		version   = "version"
		network   = "192.168.0.0/16"
		hostID    = "hostid"
		now       = "now"
		hostname  = "hostname"
		timestamp = time.Now()
		load      = report.Metrics{
			host.Load1:  report.MakeMetric().Add(timestamp, 1.0),
			host.Load5:  report.MakeMetric().Add(timestamp, 5.0),
			host.Load15: report.MakeMetric().Add(timestamp, 15.0),
		}
		uptime      = "278h55m43s"
		kernel      = "release version"
		_, ipnet, _ = net.ParseCIDR(network)
		localNets   = report.Networks([]*net.IPNet{ipnet})
	)

	var (
		oldGetKernelVersion = host.GetKernelVersion
		oldGetLoad          = host.GetLoad
		oldGetUptime        = host.GetUptime
		oldNow              = host.Now
	)
	defer func() {
		host.GetKernelVersion = oldGetKernelVersion
		host.GetLoad = oldGetLoad
		host.GetUptime = oldGetUptime
		host.Now = oldNow
	}()
	host.GetKernelVersion = func() (string, error) { return release + " " + version, nil }
	host.GetLoad = func() report.Metrics { return load }
	host.GetUptime = func() (time.Duration, error) { return time.ParseDuration(uptime) }
	host.Now = func() string { return now }

	want := report.MakeReport()
	want.Host.AddNode(report.MakeHostNodeID(hostID), report.MakeNodeWith(map[string]string{
		host.Timestamp:     now,
		host.HostName:      hostname,
		host.OS:            runtime.GOOS,
		host.Uptime:        uptime,
		host.KernelVersion: kernel,
	}).WithSets(report.Sets{
		host.LocalNetworks: report.MakeStringSet(network),
	}).WithMetrics(load))
	have, _ := host.NewReporter(hostID, hostname, localNets).Report()
	if !reflect.DeepEqual(want, have) {
		t.Errorf("%s", test.Diff(want, have))
	}
}
Пример #17
0
func TestReporter(t *testing.T) {
	want := report.MakeReport()
	pod1ID := report.MakePodNodeID("ping", "pong-a")
	pod2ID := report.MakePodNodeID("ping", "pong-b")
	serviceID := report.MakeServiceNodeID("ping", "pongservice")
	want.Pod = report.MakeTopology().AddNode(pod1ID, report.MakeNodeWith(map[string]string{
		kubernetes.PodID:           "ping/pong-a",
		kubernetes.PodName:         "pong-a",
		kubernetes.Namespace:       "ping",
		kubernetes.PodCreated:      pod1.Created(),
		kubernetes.PodContainerIDs: "container1 container2",
		kubernetes.ServiceIDs:      "ping/pongservice",
	}).WithParents(report.Sets{
		report.Service: report.MakeStringSet(serviceID),
	})).AddNode(pod2ID, report.MakeNodeWith(map[string]string{
		kubernetes.PodID:           "ping/pong-b",
		kubernetes.PodName:         "pong-b",
		kubernetes.Namespace:       "ping",
		kubernetes.PodCreated:      pod1.Created(),
		kubernetes.PodContainerIDs: "container3 container4",
		kubernetes.ServiceIDs:      "ping/pongservice",
	}).WithParents(report.Sets{
		report.Service: report.MakeStringSet(serviceID),
	}))
	want.Service = report.MakeTopology().AddNode(serviceID, report.MakeNodeWith(map[string]string{
		kubernetes.ServiceID:      "ping/pongservice",
		kubernetes.ServiceName:    "pongservice",
		kubernetes.Namespace:      "ping",
		kubernetes.ServiceCreated: pod1.Created(),
	}))
	want.Container = report.MakeTopology().AddNode(report.MakeContainerNodeID("container1"), report.MakeNodeWith(map[string]string{
		kubernetes.PodID:     "ping/pong-a",
		kubernetes.Namespace: "ping",
	}).WithParents(report.Sets{
		report.Pod: report.MakeStringSet(pod1ID),
	})).AddNode(report.MakeContainerNodeID("container2"), report.MakeNodeWith(map[string]string{
		kubernetes.PodID:     "ping/pong-a",
		kubernetes.Namespace: "ping",
	}).WithParents(report.Sets{
		report.Pod: report.MakeStringSet(pod1ID),
	})).AddNode(report.MakeContainerNodeID("container3"), report.MakeNodeWith(map[string]string{
		kubernetes.PodID:     "ping/pong-b",
		kubernetes.Namespace: "ping",
	}).WithParents(report.Sets{
		report.Pod: report.MakeStringSet(pod2ID),
	})).AddNode(report.MakeContainerNodeID("container4"), report.MakeNodeWith(map[string]string{
		kubernetes.PodID:     "ping/pong-b",
		kubernetes.Namespace: "ping",
	}).WithParents(report.Sets{
		report.Pod: report.MakeStringSet(pod2ID),
	}))

	reporter := kubernetes.NewReporter(mockClientInstance)
	have, _ := reporter.Report()
	if !reflect.DeepEqual(want, have) {
		t.Errorf("%s", test.Diff(want, have))
	}
}
Пример #18
0
func (c *container) getBaseNode() report.Node {
	result := report.MakeNodeWith(report.MakeContainerNodeID(c.ID()), map[string]string{
		ContainerID:       c.ID(),
		ContainerCreated:  c.container.Created.Format(time.RFC822),
		ContainerCommand:  c.container.Path + " " + strings.Join(c.container.Args, " "),
		ImageID:           c.Image(),
		ContainerHostname: c.Hostname(),
	}).WithParents(report.EmptySets.
		Add(report.ContainerImage, report.MakeStringSet(report.MakeContainerImageNodeID(c.Image()))),
	)
	result = result.AddTable(LabelPrefix, c.container.Config.Labels)
	result = result.AddTable(EnvPrefix, c.env())
	return result
}
Пример #19
0
func (c *container) NetworkInfo(localAddrs []net.IP) report.Sets {
	c.RLock()
	defer c.RUnlock()

	ips := c.container.NetworkSettings.SecondaryIPAddresses
	if c.container.NetworkSettings.IPAddress != "" {
		ips = append(ips, c.container.NetworkSettings.IPAddress)
	}

	// For now, for the proof-of-concept, we just add networks as a set of
	// names. For the next iteration, we will probably want to create a new
	// Network topology, populate the network nodes with all of the details
	// here, and provide foreign key links from nodes to networks.
	networks := make([]string, 0, len(c.container.NetworkSettings.Networks))
	for name, settings := range c.container.NetworkSettings.Networks {
		networks = append(networks, name)
		if settings.IPAddress != "" {
			ips = append(ips, settings.IPAddress)
		}
	}

	// Filter out IPv6 addresses; nothing works with IPv6 yet
	ipv4s := []string{}
	for _, ip := range ips {
		if isIPv4(ip) {
			ipv4s = append(ipv4s, ip)
		}
	}
	// Treat all Docker IPs as local scoped.
	ipsWithScopes := addScopeToIPs(c.hostID, ipv4s)

	return report.EmptySets.
		Add(ContainerNetworks, report.MakeStringSet(networks...)).
		Add(ContainerPorts, c.ports(localAddrs)).
		Add(ContainerIPs, report.MakeStringSet(ipv4s...)).
		Add(ContainerIPsWithScopes, report.MakeStringSet(ipsWithScopes...))
}
Пример #20
0
func TestTagger(t *testing.T) {
	oldProcessTree := docker.NewProcessTreeStub
	defer func() { docker.NewProcessTreeStub = oldProcessTree }()

	docker.NewProcessTreeStub = func(_ process.Walker) (process.Tree, error) {
		return &mockProcessTree{map[int]int{3: 2}}, nil
	}

	var (
		pid1NodeID = report.MakeProcessNodeID("somehost.com", "2")
		pid2NodeID = report.MakeProcessNodeID("somehost.com", "3")
		wantNode   = report.MakeNodeWith(map[string]string{
			docker.ContainerID: "ping",
		}).WithParents(report.Sets{
			report.Container:      report.MakeStringSet(report.MakeContainerNodeID("ping")),
			report.ContainerImage: report.MakeStringSet(report.MakeContainerImageNodeID("baz")),
		})
	)

	input := report.MakeReport()
	input.Process.AddNode(pid1NodeID, report.MakeNodeWith(map[string]string{process.PID: "2"}))
	input.Process.AddNode(pid2NodeID, report.MakeNodeWith(map[string]string{process.PID: "3"}))

	want := report.MakeReport()
	want.Process.AddNode(pid1NodeID, report.MakeNodeWith(map[string]string{process.PID: "2"}).Merge(wantNode))
	want.Process.AddNode(pid2NodeID, report.MakeNodeWith(map[string]string{process.PID: "3"}).Merge(wantNode))

	tagger := docker.NewTagger(mockRegistryInstance, nil)
	have, err := tagger.Tag(input)
	if err != nil {
		t.Errorf("%v", err)
	}
	if !reflect.DeepEqual(want, have) {
		t.Errorf("%s", test.Diff(want, have))
	}
}
Пример #21
0
// Tag implements Tagger.
func (t Tagger) Tag(r report.Report) (report.Report, error) {
	var (
		metadata = map[string]string{report.HostNodeID: t.hostNodeID}
		parents  = report.EmptySets.Add(report.Host, report.MakeStringSet(t.hostNodeID))
	)

	// Explicitly don't tag Endpoints and Addresses - These topologies include pseudo nodes,
	// and as such do their own host tagging
	for _, topology := range []report.Topology{r.Process, r.Container, r.ContainerImage, r.Host, r.Overlay, r.Pod} {
		for _, node := range topology.Nodes {
			topology.AddNode(node.WithLatests(metadata).WithParents(parents))
		}
	}
	return r, nil
}
Пример #22
0
func TestStringSetContains(t *testing.T) {
	for _, testcase := range []struct {
		contents []string
		target   string
		want     bool
	}{
		{nil, "foo", false},
		{[]string{}, "foo", false},
		{[]string{"a"}, "foo", false},
		{[]string{"a", "foo"}, "foo", true},
		{[]string{"foo", "b"}, "foo", true},
	} {
		have := report.MakeStringSet(testcase.contents...).Contains(testcase.target)
		if testcase.want != have {
			t.Errorf("%+v.Contains(%q): want %v, have %v", testcase.contents, testcase.target, testcase.want, have)
		}
	}
}
Пример #23
0
// Report implements Reporter.
func (r *Reporter) Report() (report.Report, error) {
	var (
		rep        = report.MakeReport()
		localCIDRs []string
	)

	localNets, err := GetLocalNetworks()
	if err != nil {
		return rep, nil
	}
	for _, localNet := range localNets {
		localCIDRs = append(localCIDRs, localNet.String())
	}

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

	kernel, err := GetKernelVersion()
	if err != nil {
		return rep, err
	}

	now := mtime.Now()
	metrics := GetLoad(now)
	cpuUsage, max := GetCPUUsagePercent()
	metrics[CPUUsage] = report.MakeMetric().Add(now, cpuUsage).WithMax(max)
	memoryUsage, max := GetMemoryUsageBytes()
	metrics[MemoryUsage] = report.MakeMetric().Add(now, memoryUsage).WithMax(max)

	rep.Host.AddNode(report.MakeHostNodeID(r.hostID), report.MakeNodeWith(map[string]string{
		Timestamp:     mtime.Now().UTC().Format(time.RFC3339Nano),
		HostName:      r.hostName,
		OS:            runtime.GOOS,
		KernelVersion: kernel,
		Uptime:        uptime.String(),
	}).WithSets(report.EmptySets.
		Add(LocalNetworks, report.MakeStringSet(localCIDRs...)),
	).WithMetrics(metrics))

	return rep, nil
}
Пример #24
0
func TestReportLocalNetworks(t *testing.T) {
	r := report.MakeReport().Merge(report.Report{
		Host: report.Topology{
			Nodes: report.Nodes{
				"nonets": report.MakeNode(),
				"foo": report.MakeNode().WithSets(report.Sets{
					host.LocalNetworks: report.MakeStringSet(
						"10.0.0.1/8", "192.168.1.1/24", "10.0.0.1/8", "badnet/33"),
				}),
			},
		},
	})
	want := report.Networks([]*net.IPNet{
		mustParseCIDR("10.0.0.1/8"),
		mustParseCIDR("192.168.1.1/24"),
	})
	have := render.LocalNetworks(r)
	if !reflect.DeepEqual(want, have) {
		t.Errorf("%s", test.Diff(want, have))
	}
}
Пример #25
0
func TestNodeMetadata(t *testing.T) {
	inputs := []struct {
		name string
		node report.Node
		want []detailed.MetadataRow
	}{
		{
			name: "container",
			node: report.MakeNodeWith(map[string]string{
				docker.ContainerID:            fixture.ClientContainerID,
				docker.LabelPrefix + "label1": "label1value",
			}).WithTopology(report.Container).WithSets(report.Sets{
				docker.ContainerIPs: report.MakeStringSet("10.10.10.0/24", "10.10.10.1/24"),
			}).WithLatest(docker.ContainerState, fixture.Now, docker.StateRunning),
			want: []detailed.MetadataRow{
				{ID: docker.ContainerID, Label: "ID", Value: fixture.ClientContainerID},
				{ID: docker.ContainerState, Label: "State", Value: "running"},
				{ID: docker.ContainerIPs, Label: "IPs", Value: "10.10.10.0/24, 10.10.10.1/24"},
				{
					ID:    "label_label1",
					Label: "Label \"label1\"",
					Value: "label1value",
				},
			},
		},
		{
			name: "unknown topology",
			node: report.MakeNodeWith(map[string]string{
				docker.ContainerID: fixture.ClientContainerID,
			}).WithTopology("foobar").WithID(fixture.ClientContainerNodeID),
			want: nil,
		},
	}
	for _, input := range inputs {
		have := detailed.NodeMetadata(input.node)
		if !reflect.DeepEqual(input.want, have) {
			t.Errorf("%s: %s", input.name, test.Diff(input.want, have))
		}
	}
}
Пример #26
0
func (p *pod) GetNode() report.Node {
	n := report.MakeNodeWith(map[string]string{
		PodID:           p.ID(),
		PodName:         p.Name(),
		Namespace:       p.Namespace(),
		PodCreated:      p.Created(),
		PodContainerIDs: strings.Join(p.ContainerIDs(), " "),
	})
	if len(p.serviceIDs) > 0 {
		n.Metadata[ServiceIDs] = strings.Join(p.serviceIDs, " ")
	}
	for _, serviceID := range p.serviceIDs {
		segments := strings.SplitN(serviceID, "/", 2)
		if len(segments) != 2 {
			continue
		}
		n = n.WithParents(report.Sets{
			report.Service: report.MakeStringSet(report.MakeServiceNodeID(p.Namespace(), segments[1])),
		})
	}
	return n
}
Пример #27
0
func TestTagger(t *testing.T) {
	var (
		hostID         = "foo"
		probeID        = "a1b2c3d4"
		endpointNodeID = report.MakeEndpointNodeID(hostID, "1.2.3.4", "56789") // hostID ignored
		nodeMetadata   = report.MakeNodeWith(map[string]string{"foo": "bar"})
	)

	r := report.MakeReport()
	r.Process.AddNode(endpointNodeID, nodeMetadata)
	want := nodeMetadata.Merge(report.MakeNodeWith(map[string]string{
		report.HostNodeID: report.MakeHostNodeID(hostID),
		report.ProbeID:    probeID,
	}).WithParents(report.Sets{
		report.Host: report.MakeStringSet(report.MakeHostNodeID(hostID)),
	}))
	rpt, _ := host.NewTagger(hostID, probeID).Tag(r)
	have := rpt.Process.Nodes[endpointNodeID].Copy()
	if !reflect.DeepEqual(want, have) {
		t.Error(test.Diff(want, have))
	}
}
Пример #28
0
func TestTagger(t *testing.T) {
	var (
		hostID         = "foo"
		probeID        = "a1b2c3d4"
		endpointNodeID = report.MakeEndpointNodeID(hostID, "1.2.3.4", "56789") // hostID ignored
		node           = report.MakeNodeWith(map[string]string{"foo": "bar"})
	)

	r := report.MakeReport()
	r.Process.AddNode(endpointNodeID, node)
	rpt, _ := host.NewTagger(hostID, probeID).Tag(r)
	have := rpt.Process.Nodes[endpointNodeID].Copy()

	// It should now have the host ID
	wantHostID := report.MakeHostNodeID(hostID)
	if hostID, ok := have.Latest.Lookup(report.HostNodeID); !ok || hostID != wantHostID {
		t.Errorf("Expected %q got %q", wantHostID, report.MakeHostNodeID(hostID))
	}

	// It should now have the probe ID
	if haveProbeID, ok := have.Latest.Lookup(report.ProbeID); !ok || haveProbeID != probeID {
		t.Errorf("Expected %q got %q", probeID, haveProbeID)
	}

	// It should still have the other keys
	want := "bar"
	if have, ok := have.Latest.Lookup("foo"); !ok || have != want {
		t.Errorf("Expected %q got %q", want, have)
	}

	// It should have the host as a parent
	wantParent := report.MakeHostNodeID(hostID)
	if have, ok := have.Parents.Lookup(report.Host); !ok || len(have) != 1 || have[0] != wantParent {
		t.Errorf("Expected %q got %q", report.MakeStringSet(wantParent), have)
	}
}
Пример #29
0
func TestNodeMetadata(t *testing.T) {
	inputs := []struct {
		name string
		node report.Node
		want []report.MetadataRow
	}{
		{
			name: "container",
			node: report.MakeNodeWith(fixture.ClientContainerNodeID, map[string]string{
				docker.ContainerID:            fixture.ClientContainerID,
				docker.LabelPrefix + "label1": "label1value",
				docker.ContainerStateHuman:    docker.StateRunning,
			}).WithTopology(report.Container).WithSets(report.EmptySets.
				Add(docker.ContainerIPs, report.MakeStringSet("10.10.10.0/24", "10.10.10.1/24")),
			),
			want: []report.MetadataRow{
				{ID: docker.ContainerID, Label: "ID", Value: fixture.ClientContainerID, Priority: 1},
				{ID: docker.ContainerStateHuman, Label: "State", Value: "running", Priority: 2},
				{ID: docker.ContainerIPs, Label: "IPs", Value: "10.10.10.0/24, 10.10.10.1/24", Priority: 15},
			},
		},
		{
			name: "unknown topology",
			node: report.MakeNodeWith(fixture.ClientContainerNodeID, map[string]string{
				docker.ContainerID: fixture.ClientContainerID,
			}).WithTopology("foobar"),
			want: nil,
		},
	}
	for _, input := range inputs {
		have := detailed.NodeMetadata(fixture.Report, input.node)
		if !reflect.DeepEqual(input.want, have) {
			t.Errorf("%s: %s", input.name, test.Diff(input.want, have))
		}
	}
}
				serverEndpointNodeID: report.MakeNode().WithLatests(map[string]string{
					endpoint.Addr:        serverIP,
					endpoint.Port:        serverPort,
					endpoint.Conntracked: "true",
				}).WithID(serverEndpointNodeID).WithTopology(report.Endpoint),
			},
		},
		Container: report.Topology{
			Nodes: report.Nodes{
				containerNodeID: report.MakeNode().WithLatests(map[string]string{
					docker.ContainerID:   containerID,
					docker.ContainerName: containerName,
					report.HostNodeID:    serverHostNodeID,
				}).WithSets(report.EmptySets.
					Add(docker.ContainerIPs, report.MakeStringSet(containerIP)).
					Add(docker.ContainerPorts, report.MakeStringSet(fmt.Sprintf("%s:%s->%s/tcp", serverIP, serverPort, serverPort))),
				).WithID(containerNodeID).WithTopology(report.Container),
			},
		},
		Host: report.Topology{
			Nodes: report.Nodes{
				serverHostNodeID: report.MakeNodeWith(map[string]string{
					report.HostNodeID: serverHostNodeID,
				}).WithSets(report.EmptySets.
					Add(host.LocalNetworks, report.MakeStringSet("192.168.0.0/16")),
				).WithID(serverHostNodeID).WithTopology(report.Host),
			},
		},
	}