func TestReporter(t *testing.T) { want := report.MakeReport() want.Container = report.Topology{ Adjacency: report.Adjacency{}, EdgeMetadatas: report.EdgeMetadatas{}, NodeMetadatas: report.NodeMetadatas{ report.MakeContainerNodeID("", "ping"): report.NewNodeMetadata(map[string]string{ docker.ContainerID: "ping", docker.ContainerName: "pong", docker.ImageID: "baz", }), }, } want.ContainerImage = report.Topology{ Adjacency: report.Adjacency{}, EdgeMetadatas: report.EdgeMetadatas{}, NodeMetadatas: report.NodeMetadatas{ report.MakeContainerNodeID("", "baz"): report.NewNodeMetadata(map[string]string{ docker.ImageID: "baz", docker.ImageName: "bang", }), }, } reporter := docker.NewReporter(mockRegistryInstance, "") have, _ := reporter.Report() if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
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)) } }
func TestReporter(t *testing.T) { want := report.MakeReport() want.Container = report.Topology{ Nodes: report.Nodes{ report.MakeContainerNodeID("", "ping"): report.MakeNodeWith(map[string]string{ docker.ContainerID: "ping", docker.ContainerName: "pong", docker.ImageID: "baz", }), }, Controls: report.Controls{ docker.RestartContainer: report.Control{ ID: docker.RestartContainer, Human: "Restart", Icon: "fa-repeat", }, docker.StartContainer: report.Control{ ID: docker.StartContainer, Human: "Start", Icon: "fa-play", }, docker.StopContainer: report.Control{ ID: docker.StopContainer, Human: "Stop", Icon: "fa-stop", }, docker.PauseContainer: report.Control{ ID: docker.PauseContainer, Human: "Pause", Icon: "fa-pause", }, docker.UnpauseContainer: report.Control{ ID: docker.UnpauseContainer, Human: "Unpause", Icon: "fa-play", }, }, } want.ContainerImage = report.Topology{ Nodes: report.Nodes{ report.MakeContainerNodeID("", "baz"): report.MakeNodeWith(map[string]string{ docker.ImageID: "baz", docker.ImageName: "bang", }), }, Controls: report.Controls{}, } reporter := docker.NewReporter(mockRegistryInstance, "") have, _ := reporter.Report() if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestControls(t *testing.T) { mdc := newMockClient() setupStubs(mdc, func() { registry, _ := docker.NewRegistry(10*time.Second, nil) defer registry.Stop() for _, tc := range []struct{ command, result string }{ {docker.StopContainer, "stopped"}, {docker.StartContainer, "started"}, {docker.RestartContainer, "restarted"}, {docker.PauseContainer, "paused"}, {docker.UnpauseContainer, "unpaused"}, } { result := controls.HandleControlRequest(xfer.Request{ Control: tc.command, NodeID: report.MakeContainerNodeID("a1b2c3d4e5"), }) if !reflect.DeepEqual(result, xfer.Response{ Error: tc.result, }) { t.Error(result) } } }) }
// Tag implements Tagger. func (w Weave) Tag(r report.Report) (report.Report, error) { status, err := w.update() if err != nil { return r, nil } for _, entry := range status.DNS.Entries { if entry.Tombstone > 0 { continue } nodeID := report.MakeContainerNodeID(w.hostID, entry.ContainerID) node, ok := r.Container.NodeMetadatas[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, " ") r.Container.NodeMetadatas[nodeID] = node } psEntries, err := w.ps() if err != nil { return r, nil } for _, e := range psEntries { w.tagContainer(r, e.containerIDPrefix, e.macAddress, e.ips) } return r, nil }
func TestPipes(t *testing.T) { oldNewPipe := controls.NewPipe defer func() { controls.NewPipe = oldNewPipe }() controls.NewPipe = func(_ controls.PipeClient, _ string) (string, xfer.Pipe, error) { return "pipeid", mockPipe{}, nil } mdc := newMockClient() setupStubs(mdc, func() { registry, _ := docker.NewRegistry(10*time.Second, nil) defer registry.Stop() test.Poll(t, 100*time.Millisecond, true, func() interface{} { _, ok := registry.GetContainer("ping") return ok }) for _, tc := range []string{ docker.AttachContainer, docker.ExecContainer, } { result := controls.HandleControlRequest(xfer.Request{ Control: tc, NodeID: report.MakeContainerNodeID("ping"), }) want := xfer.Response{ Pipe: "pipeid", RawTTY: true, } if !reflect.DeepEqual(result, want) { t.Errorf("diff: %s", test.Diff(want, result)) } } }) }
func (r *Reporter) containerTopology(localAddrs []net.IP) report.Topology { result := report.MakeTopology() result.Controls.AddControl(report.Control{ ID: StopContainer, Human: "Stop", Icon: "fa-stop", }) result.Controls.AddControl(report.Control{ ID: StartContainer, Human: "Start", Icon: "fa-play", }) result.Controls.AddControl(report.Control{ ID: RestartContainer, Human: "Restart", Icon: "fa-repeat", }) result.Controls.AddControl(report.Control{ ID: PauseContainer, Human: "Pause", Icon: "fa-pause", }) result.Controls.AddControl(report.Control{ ID: UnpauseContainer, Human: "Unpause", Icon: "fa-play", }) r.registry.WalkContainers(func(c Container) { nodeID := report.MakeContainerNodeID(r.hostID, c.ID()) result.AddNode(nodeID, c.GetNode(r.hostID, localAddrs)) }) return result }
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 }
// MapProcess2Container maps process Nodes to container // Nodes. // // If this function is given a node without a docker_container_id // (including other pseudo nodes), it will produce an "Uncontained" // pseudo node. // // Otherwise, this function will produce a node with the correct ID // format for a container, but without any Major or Minor labels. // It does not have enough info to do that, and the resulting graph // must be merged with a container graph to get that info. func MapProcess2Container(n report.Node, _ report.Networks) report.Nodes { // Propagate pseudo nodes if n.Topology == Pseudo { return report.Nodes{n.ID: n} } // Otherwise, if the process is not in a container, group it // into an per-host "Uncontained" node. If for whatever reason // this node doesn't have a host id in their nodemetadata, it'll // all get grouped into a single uncontained node. var ( id string node report.Node ) if containerID, ok := n.Latest.Lookup(docker.ContainerID); ok { id = report.MakeContainerNodeID(containerID) node = NewDerivedNode(id, n).WithTopology(report.Container) } else { id = MakePseudoNodeID(UncontainedID, report.ExtractHostID(n)) node = NewDerivedPseudoNode(id, n) node = propagateLatest(report.HostNodeID, n, node) node = propagateLatest(IsConnected, n, node) } return report.Nodes{id: node} }
func TestReporter(t *testing.T) { containerImageNodeID := report.MakeContainerImageNodeID("baz") rpt, err := docker.NewReporter(mockRegistryInstance, "host1", nil).Report() if err != nil { t.Fatal(err) } // Reporter should add a container { containerNodeID := report.MakeContainerNodeID("ping") node, ok := rpt.Container.Nodes[containerNodeID] if !ok { t.Fatalf("Expected report to have container image %q, but not found", containerNodeID) } for k, want := range map[string]string{ docker.ContainerID: "ping", docker.ContainerName: "pong", docker.ImageID: "baz", } { if have, ok := node.Latest.Lookup(k); !ok || have != want { t.Errorf("Expected container %s latest %q: %q, got %q", containerNodeID, k, want, have) } } // container should have controls if len(rpt.Container.Controls) == 0 { t.Errorf("Container should have some controls") } // container should have the image as a parent if parents, ok := node.Parents.Lookup(report.ContainerImage); !ok || !parents.Contains(containerImageNodeID) { t.Errorf("Expected container %s to have parent container image %q, got %q", containerNodeID, containerImageNodeID, parents) } } // Reporter should add a container image { node, ok := rpt.ContainerImage.Nodes[containerImageNodeID] if !ok { t.Fatalf("Expected report to have container image %q, but not found", containerImageNodeID) } for k, want := range map[string]string{ docker.ImageID: "baz", docker.ImageName: "bang", } { if have, ok := node.Latest.Lookup(k); !ok || have != want { t.Errorf("Expected container image %s latest %q: %q, got %q", containerImageNodeID, k, want, have) } } // container image should have no controls if len(rpt.ContainerImage.Controls) != 0 { t.Errorf("Container images should not have any controls") } } }
func (r *Reporter) containerTopology() report.Topology { result := report.NewTopology() r.registry.WalkContainers(func(c Container) { nodeID := report.MakeContainerNodeID(r.scope, c.ID()) result.NodeMetadatas[nodeID] = c.GetNodeMetadata() }) return result }
func (r *Reporter) containerTopology() report.Topology { result := report.MakeTopology() r.registry.WalkContainers(func(c Container) { nodeID := report.MakeContainerNodeID(r.hostID, c.ID()) result.AddNode(nodeID, c.GetNode()) }) return result }
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)) } } }
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) } }
// ContainerUpdated should be called whenever a container is updated. func (r *Reporter) ContainerUpdated(c Container) { localAddrs, err := report.LocalAddresses() if err != nil { log.Errorf("Error getting local address: %v", err) return } // Publish a 'short cut' report container just this container rpt := report.MakeReport() rpt.Shortcut = true rpt.Container.AddNode(report.MakeContainerNodeID(c.ID()), c.GetNode(r.hostID, localAddrs)) r.probe.Publish(rpt) }
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 }
func TestTagger(t *testing.T) { mtime.NowForce(time.Now()) defer mtime.NowReset() 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") ) 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"})) have, err := docker.NewTagger(mockRegistryInstance, nil).Tag(input) if err != nil { t.Errorf("%v", err) } // Processes should be tagged with their container ID, and parents for _, nodeID := range []string{pid1NodeID, pid2NodeID} { node, ok := have.Process.Nodes[nodeID] if !ok { t.Errorf("Expected process node %s, but not found", nodeID) } // node should have the container id added if have, ok := node.Latest.Lookup(docker.ContainerID); !ok || have != "ping" { t.Errorf("Expected process node %s to have container id %q, got %q", nodeID, "ping", have) } // node should have the container as a parent if have, ok := node.Parents.Lookup(report.Container); !ok || !have.Contains(report.MakeContainerNodeID("ping")) { t.Errorf("Expected process node %s to have container %q as a parent, got %q", nodeID, "ping", have) } // node should have the container image as a parent if have, ok := node.Parents.Lookup(report.ContainerImage); !ok || !have.Contains(report.MakeContainerImageNodeID("baz")) { t.Errorf("Expected process node %s to have container image %q as a parent, got %q", nodeID, "baz", have) } } }
// 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 }
// 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 }
func (r *Reporter) containerImageTopology() report.Topology { result := report.NewTopology() r.registry.WalkImages(func(image *docker_client.APIImages) { nmd := report.NodeMetadata{ ImageID: image.ID, } if len(image.RepoTags) > 0 { nmd[ImageName] = image.RepoTags[0] } nodeID := report.MakeContainerNodeID(r.scope, image.ID) result.NodeMetadatas[nodeID] = nmd }) return result }
// MapContainerIdentity maps a container topology node to a container // renderable node. As it is only ever run on container topology nodes, we // expect that certain keys are present. func MapContainerIdentity(m RenderableNode, _ report.Networks) RenderableNodes { id, ok := m.Metadata[docker.ContainerID] if !ok { return RenderableNodes{} } var ( major, _ = GetRenderableContainerName(m.Node) minor = report.ExtractHostID(m.Node) rank = m.Metadata[docker.ImageID] ) node := NewRenderableNodeWith(id, major, minor, rank, m) if imageID, ok := m.Metadata[docker.ImageID]; ok { hostID, _, _ := report.ParseContainerNodeID(m.ID) node.Origins = node.Origins.Add(report.MakeContainerNodeID(hostID, imageID)) } return RenderableNodes{id: node} }
func (r *Reporter) containerImageTopology() report.Topology { result := report.MakeTopology() r.registry.WalkImages(func(image *docker_client.APIImages) { nmd := report.MakeNodeWith(map[string]string{ ImageID: image.ID, }) AddLabels(nmd, image.Labels) if len(image.RepoTags) > 0 { nmd.Metadata[ImageName] = image.RepoTags[0] } nodeID := report.MakeContainerNodeID(r.hostID, image.ID) result.AddNode(nodeID, nmd) }) return result }
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()))), )) } }
// 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 } containersByPrefix := map[string]report.Node{} for _, node := range r.Container.Nodes { prefix := node.Metadata[docker.ContainerID][:12] containersByPrefix[prefix] = node } for _, e := range psEntries { node, ok := containersByPrefix[e.containerIDPrefix] if !ok { continue } existingIPs := report.MakeIDList(docker.ExtractContainerIPs(node)...) existingIPs = existingIPs.Add(e.ips...) node.Metadata[docker.ContainerIPs] = strings.Join(existingIPs, " ") node.Metadata[WeaveMACAddress] = e.macAddress } return r, nil }
func (r processWithContainerNameRenderer) Render(rpt report.Report, dct Decorator) report.Nodes { processes := r.Renderer.Render(rpt, dct) containers := SelectContainer.Render(rpt, dct) outputs := report.Nodes{} for id, p := range processes { outputs[id] = p containerID, timestamp, ok := p.Latest.LookupEntry(docker.ContainerID) if !ok { continue } container, ok := containers[report.MakeContainerNodeID(containerID)] if !ok { continue } output := p.Copy() output.Latest = output.Latest.Set(docker.ContainerID, timestamp, containerID) if containerName, timestamp, ok := container.Latest.LookupEntry(docker.ContainerName); ok { output.Latest = output.Latest.Set(docker.ContainerName, timestamp, containerName) } outputs[id] = output } return outputs }
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)) } }
Server80NodeID = report.MakeEndpointNodeID(ServerHostID, ServerIP, ServerPort) // apache UnknownClient1NodeID = report.MakeEndpointNodeID(ServerHostID, UnknownClient1IP, UnknownClient1Port) // we want to ensure two unknown clients, connnected UnknownClient2NodeID = report.MakeEndpointNodeID(ServerHostID, UnknownClient2IP, UnknownClient2Port) // to the same server, are deduped. UnknownClient3NodeID = report.MakeEndpointNodeID(ServerHostID, UnknownClient3IP, UnknownClient3Port) // Check this one isn't deduped RandomClientNodeID = report.MakeEndpointNodeID(ServerHostID, RandomClientIP, RandomClientPort) // this should become an internet node NonContainerNodeID = report.MakeEndpointNodeID(ServerHostID, ServerIP, NonContainerClientPort) GoogleEndpointNodeID = report.MakeEndpointNodeID(ServerHostID, GoogleIP, GooglePort) ClientProcess1NodeID = report.MakeProcessNodeID(ClientHostID, Client1PID) ClientProcess2NodeID = report.MakeProcessNodeID(ClientHostID, Client2PID) ServerProcessNodeID = report.MakeProcessNodeID(ServerHostID, ServerPID) NonContainerProcessNodeID = report.MakeProcessNodeID(ServerHostID, NonContainerPID) ClientContainerID = "a1b2c3d4e5" ServerContainerID = "5e4d3c2b1a" ClientContainerNodeID = report.MakeContainerNodeID(ClientHostID, ClientContainerID) ServerContainerNodeID = report.MakeContainerNodeID(ServerHostID, ServerContainerID) ClientContainerImageID = "imageid123" ServerContainerImageID = "imageid456" ClientContainerImageNodeID = report.MakeContainerNodeID(ClientHostID, ClientContainerImageID) ServerContainerImageNodeID = report.MakeContainerNodeID(ServerHostID, ServerContainerImageID) ClientContainerImageName = "image/client" ServerContainerImageName = "image/server" ClientAddressNodeID = report.MakeAddressNodeID(ClientHostID, ClientIP) ServerAddressNodeID = report.MakeAddressNodeID(ServerHostID, ServerIP) UnknownAddress1NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient1IP) UnknownAddress2NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient2IP) UnknownAddress3NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient3IP) RandomAddressNodeID = report.MakeAddressNodeID(ServerHostID, RandomClientIP) // this should become an internet node
func TestReporter(t *testing.T) { pod1ID := report.MakePodNodeID("ping", "pong-a") pod2ID := report.MakePodNodeID("ping", "pong-b") serviceID := report.MakeServiceNodeID("ping", "pongservice") rpt, _ := kubernetes.NewReporter(mockClientInstance).Report() // Reporter should have added the following pods for _, pod := range []struct { id string parentService string latest map[string]string }{ {pod1ID, serviceID, 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", }}, {pod2ID, serviceID, 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", }}, } { node, ok := rpt.Pod.Nodes[pod.id] if !ok { t.Errorf("Expected report to have pod %q, but not found", pod.id) } if parents, ok := node.Parents.Lookup(report.Service); !ok || !parents.Contains(pod.parentService) { t.Errorf("Expected pod %s to have parent service %q, got %q", pod.id, pod.parentService, parents) } for k, want := range pod.latest { if have, ok := node.Latest.Lookup(k); !ok || have != want { t.Errorf("Expected pod %s latest %q: %q, got %q", pod.id, k, want, have) } } } // Reporter should have added a service { node, ok := rpt.Service.Nodes[serviceID] if !ok { t.Errorf("Expected report to have service %q, but not found", serviceID) } for k, want := range map[string]string{ kubernetes.ServiceID: "ping/pongservice", kubernetes.ServiceName: "pongservice", kubernetes.Namespace: "ping", kubernetes.ServiceCreated: pod1.Created(), } { if have, ok := node.Latest.Lookup(k); !ok || have != want { t.Errorf("Expected service %s latest %q: %q, got %q", serviceID, k, want, have) } } } // Reporter should have tagged the containers for _, pod := range []struct { id, nodeID string containers []string }{ {"ping/pong-a", pod1ID, []string{"container1", "container2"}}, {"ping/pong-b", pod2ID, []string{"container3", "container4"}}, } { for _, containerID := range pod.containers { node, ok := rpt.Container.Nodes[report.MakeContainerNodeID(containerID)] if !ok { t.Errorf("Expected report to have container %q, but not found", containerID) } // container should have pod id if have, ok := node.Latest.Lookup(kubernetes.PodID); !ok || have != pod.id { t.Errorf("Expected container %s latest %q: %q, got %q", containerID, kubernetes.PodID, pod.id, have) } // container should have namespace if have, ok := node.Latest.Lookup(kubernetes.Namespace); !ok || have != "ping" { t.Errorf("Expected container %s latest %q: %q, got %q", containerID, kubernetes.Namespace, "ping", have) } // container should have pod parent if parents, ok := node.Parents.Lookup(report.Pod); !ok || !parents.Contains(pod.nodeID) { t.Errorf("Expected container %s to have parent service %q, got %q", containerID, pod.nodeID, parents) } } } }
var ( serverHostID = "host1" serverHostNodeID = report.MakeHostNodeID(serverHostID) randomIP = "3.4.5.6" randomPort = "56789" randomEndpointNodeID = report.MakeEndpointNodeID(serverHostID, randomIP, randomPort) serverIP = "192.168.1.1" serverPort = "80" serverEndpointNodeID = report.MakeEndpointNodeID(serverHostID, serverIP, serverPort) containerID = "a1b2c3d4e5" containerIP = "192.168.0.1" containerName = "foo" containerNodeID = report.MakeContainerNodeID(containerID) rpt = report.Report{ Endpoint: report.Topology{ Nodes: report.Nodes{ randomEndpointNodeID: report.MakeNode().WithLatests(map[string]string{ endpoint.Addr: randomIP, endpoint.Port: randomPort, endpoint.Conntracked: "true", }).WithAdjacent(serverEndpointNodeID).WithID(randomEndpointNodeID).WithTopology(report.Endpoint), serverEndpointNodeID: report.MakeNode().WithLatests(map[string]string{ endpoint.Addr: serverIP, endpoint.Port: serverPort, endpoint.Conntracked: "true", }).WithID(serverEndpointNodeID).WithTopology(report.Endpoint),
Server80NodeID = report.MakeEndpointNodeID(ServerHostID, ServerIP, ServerPort) // apache UnknownClient1NodeID = report.MakeEndpointNodeID(ServerHostID, UnknownClient1IP, UnknownClient1Port) // we want to ensure two unknown clients, connnected UnknownClient2NodeID = report.MakeEndpointNodeID(ServerHostID, UnknownClient2IP, UnknownClient2Port) // to the same server, are deduped. UnknownClient3NodeID = report.MakeEndpointNodeID(ServerHostID, UnknownClient3IP, UnknownClient3Port) // Check this one isn't deduped RandomClientNodeID = report.MakeEndpointNodeID(ServerHostID, RandomClientIP, RandomClientPort) // this should become an internet node NonContainerNodeID = report.MakeEndpointNodeID(ServerHostID, ServerIP, NonContainerClientPort) GoogleEndpointNodeID = report.MakeEndpointNodeID(ServerHostID, GoogleIP, GooglePort) ClientProcess1NodeID = report.MakeProcessNodeID(ClientHostID, Client1PID) ClientProcess2NodeID = report.MakeProcessNodeID(ClientHostID, Client2PID) ServerProcessNodeID = report.MakeProcessNodeID(ServerHostID, ServerPID) NonContainerProcessNodeID = report.MakeProcessNodeID(ServerHostID, NonContainerPID) ClientContainerID = "a1b2c3d4e5" ServerContainerID = "5e4d3c2b1a" ClientContainerNodeID = report.MakeContainerNodeID(ClientContainerID) ServerContainerNodeID = report.MakeContainerNodeID(ServerContainerID) ClientContainerImageID = "imageid123" ServerContainerImageID = "imageid456" ClientContainerImageNodeID = report.MakeContainerImageNodeID(ClientContainerImageID) ServerContainerImageNodeID = report.MakeContainerImageNodeID(ServerContainerImageID) ClientContainerImageName = "image/client" ServerContainerImageName = "image/server" ClientAddressNodeID = report.MakeAddressNodeID(ClientHostID, ClientIP) ServerAddressNodeID = report.MakeAddressNodeID(ServerHostID, ServerIP) UnknownAddress1NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient1IP) UnknownAddress2NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient2IP) UnknownAddress3NodeID = report.MakeAddressNodeID(ServerHostID, UnknownClient3IP) RandomAddressNodeID = report.MakeAddressNodeID(ServerHostID, RandomClientIP) // this should become an internet node