Esempio n. 1
0
// MapIP2Container maps IP nodes produced from MapContainer2IP back to
// container nodes.  If there is more than one container with a given
// IP, it is dropped.
func MapIP2Container(n report.Node, _ report.Networks) report.Nodes {
	// If an IP is shared between multiple containers, we can't
	// reliably attribute an connection based on its IP
	if count, _ := n.Counters.Lookup(IP); count > 1 {
		return report.Nodes{}
	}

	// Propagate the internet pseudo node
	if strings.HasSuffix(n.ID, TheInternetID) {
		return report.Nodes{n.ID: n}
	}

	// If this node is not a container, exclude it.
	// This excludes all the nodes we've dragged in from endpoint
	// that we failed to join to a container.
	containerID, ok := n.Latest.Lookup(docker.ContainerID)
	if !ok {
		return report.Nodes{}
	}

	id := report.MakeContainerNodeID(containerID)
	return report.Nodes{
		id: NewDerivedNode(id, n).
			WithTopology(report.Container),
	}
}
Esempio n. 2
0
// 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}
}
Esempio n. 3
0
func TestContainerHostnameFilterRenderer(t *testing.T) {
	// add a system container into the topology and ensure
	// it is filtered out correctly.
	input := fixture.Report.Copy()

	clientContainer2ID := "f6g7h8i9j1"
	clientContainer2NodeID := report.MakeContainerNodeID(clientContainer2ID)
	input.Container.AddNode(report.MakeNodeWith(clientContainer2NodeID, map[string]string{
		docker.LabelPrefix + "works.weave.role": "system",
		docker.ContainerHostname:                fixture.ClientContainerHostname,
		report.HostNodeID:                       fixture.ClientHostNodeID,
	}).
		WithParents(report.EmptySets.
			Add("host", report.MakeStringSet(fixture.ClientHostNodeID)),
		).WithTopology(report.Container))

	have := Prune(render.ContainerHostnameRenderer.Render(input, render.FilterApplication))
	want := Prune(expected.RenderedContainerHostnames)
	// Test works by virtue of the RenderedContainerHostname only having a container
	// counter == 1

	if !reflect.DeepEqual(want, have) {
		t.Error(test.Diff(want, have))
	}
}
Esempio n. 4
0
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, false, "")
		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: %s", tc, test.Diff(want, result))
			}
		}
	})
}
Esempio n. 5
0
func TestControls(t *testing.T) {
	mdc := newMockClient()
	setupStubs(mdc, func() {
		registry, _ := docker.NewRegistry(10*time.Second, nil, false, "")
		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)
			}
		}
	})
}
Esempio n. 6
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
}
Esempio n. 7
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
}
Esempio n. 8
0
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(report.MakeNodeWith(pid1NodeID, map[string]string{process.PID: "2"}))
	input.Process.AddNode(report.MakeNodeWith(pid2NodeID, 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)
		}
	}
}
Esempio n. 9
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
		}

		topology.AddNode(report.MakeNodeWith(nodeID, 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()))),
		))

	}
}
Esempio n. 10
0
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
}
Esempio n. 11
0
func (r *registry) updateContainerState(containerID string, intendedState *string) {
	r.Lock()
	defer r.Unlock()

	dockerContainer, err := r.client.InspectContainer(containerID)
	if err != nil {
		// Don't spam the logs if the container was short lived
		if _, ok := err.(*docker_client.NoSuchContainer); !ok {
			log.Errorf("Error processing event for container %s: %v", containerID, err)
			return
		}

		// Container doesn't exist anymore, so lets stop and remove it
		c, ok := r.containers.Get(containerID)
		if !ok {
			return
		}
		container := c.(Container)

		r.containers.Delete(containerID)
		delete(r.containersByPID, container.PID())
		if r.collectStats {
			container.StopGatheringStats()
		}

		if intendedState != nil {
			node := report.MakeNodeWith(report.MakeContainerNodeID(containerID), map[string]string{
				ContainerID:    containerID,
				ContainerState: *intendedState,
			})
			// Trigger anyone watching for updates
			for _, f := range r.watchers {
				f(node)
			}
		}
		return
	}

	// Container exists, ensure we have it
	o, ok := r.containers.Get(containerID)
	var c Container
	if !ok {
		c = NewContainerStub(dockerContainer, r.hostID)
		r.containers.Insert(containerID, c)
	} else {
		c = o.(Container)
		// potentially remove existing pid mapping.
		delete(r.containersByPID, c.PID())
		c.UpdateState(dockerContainer)
	}

	// Update PID index
	if c.PID() > 1 {
		r.containersByPID[c.PID()] = c
	}

	// Trigger anyone watching for updates
	if err != nil {
		node := c.GetNode()
		for _, f := range r.watchers {
			f(node)
		}
	}

	// And finally, ensure we gather stats for it
	if r.collectStats {
		if dockerContainer.State.Running {
			if err := c.StartGatheringStats(); err != nil {
				log.Errorf("Error gather stats for container: %s", containerID)
				return
			}
		} else {
			c.StopGatheringStats()
		}
	}
}
Esempio n. 12
0
	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"
	ClientContainerName   = "client"
	ServerContainerID     = "5e4d3c2b1a"
	ServerContainerName   = "task-name-5-server-aceb93e2f2b797caba01"
	ClientContainerNodeID = report.MakeContainerNodeID(ClientContainerID)
	ServerContainerNodeID = report.MakeContainerNodeID(ServerContainerID)

	ClientContainerHostname = ClientContainerName + ".hostname.com"
	ServerContainerHostname = ServerContainerName + ".hostname.com"

	ClientContainerImageID     = "imageid123"
	ServerContainerImageID     = "imageid456"
	ClientContainerImageNodeID = report.MakeContainerImageNodeID(ClientContainerImageID)
	ServerContainerImageNodeID = report.MakeContainerImageNodeID(ServerContainerImageID)
	ClientContainerImageName   = "image/client"
	ServerContainerImageName   = "image/server"

	KubernetesNamespace = "ping"
	ClientPodID         = "ping/pong-a"
	ServerPodID         = "ping/pong-b"
Esempio n. 13
0
func TestReporter(t *testing.T) {
	var controlProbeID = "a1b2c3d4"

	containerImageNodeID := report.MakeContainerImageNodeID("baz")
	rpt, err := docker.NewReporter(mockRegistryInstance, "host1", controlProbeID, 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",
			report.ControlProbeID: controlProbeID,
		} {
			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",
			docker.ImageLabelPrefix + "imgfoo1": "bar1",
			docker.ImageLabelPrefix + "imgfoo2": "bar2",
		} {
			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")
		}
	}
}
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)

	container1ID     = "11b2c3d4e5"
	container1IP     = "192.168.0.1"
	container1Name   = "foo"
	container1NodeID = report.MakeContainerNodeID(container1ID)

	container1Port           = "16782"
	container1EndpointNodeID = report.MakeEndpointNodeID(serverHostID, container1IP, container1Port)

	duplicatedIP             = "192.168.0.2"
	duplicatedPort           = "80"
	duplicatedEndpointNodeID = report.MakeEndpointNodeID(serverHostID, duplicatedIP, duplicatedPort)

	container2ID     = "21b2c3d4e5"
	container2IP     = duplicatedIP
	container2Name   = "bar"
	container2NodeID = report.MakeContainerNodeID(container2ID)

	pauseContainerID     = "31b2c3d4e5"
	pauseContainerIP     = duplicatedIP
Esempio n. 15
0
func TestWeaveTaggerOverlayTopology(t *testing.T) {
	w := overlay.NewWeave(mockHostID, weave.MockClient{})
	defer w.Stop()

	// Wait until the reporter reports some nodes
	test.Poll(t, 300*time.Millisecond, 1, func() interface{} {
		have, _ := w.Report()
		return len(have.Overlay.Nodes)
	})

	{
		// Overlay node should include peer name and nickname
		have, err := w.Report()
		if err != nil {
			t.Fatal(err)
		}

		nodeID := report.MakeOverlayNodeID(weave.MockWeavePeerName)
		node, ok := have.Overlay.Nodes[nodeID]
		if !ok {
			t.Errorf("Expected overlay node %q, but not found", nodeID)
		}
		if peerName, ok := node.Latest.Lookup(overlay.WeavePeerName); !ok || peerName != weave.MockWeavePeerName {
			t.Errorf("Expected weave peer name %q, got %q", weave.MockWeavePeerName, peerName)
		}
		if peerNick, ok := node.Latest.Lookup(overlay.WeavePeerNickName); !ok || peerNick != weave.MockWeavePeerNickName {
			t.Errorf("Expected weave peer nickname %q, got %q", weave.MockWeavePeerNickName, peerNick)
		}
		if localNetworks, ok := node.Sets.Lookup(host.LocalNetworks); !ok || !reflect.DeepEqual(localNetworks, report.MakeStringSet(weave.MockWeaveDefaultSubnet)) {
			t.Errorf("Expected weave node local_networks %q, got %q", report.MakeStringSet(weave.MockWeaveDefaultSubnet), localNetworks)
		}
	}

	{
		// Container nodes should be tagged with their overlay info
		nodeID := report.MakeContainerNodeID(weave.MockContainerID)
		have, err := w.Tag(report.Report{
			Container: report.MakeTopology().AddNode(report.MakeNodeWith(nodeID, map[string]string{
				docker.ContainerID: weave.MockContainerID,
			})),
		})
		if err != nil {
			t.Fatal(err)
		}

		node, ok := have.Container.Nodes[nodeID]
		if !ok {
			t.Errorf("Expected container node %q, but not found", nodeID)
		}

		// Should have Weave DNS Hostname
		if have, ok := node.Latest.Lookup(overlay.WeaveDNSHostname); !ok || have != weave.MockHostname {
			t.Errorf("Expected weave dns hostname %q, got %q", weave.MockHostname, have)
		}
		// Should have Weave MAC Address
		if have, ok := node.Latest.Lookup(overlay.WeaveMACAddress); !ok || have != weave.MockContainerMAC {
			t.Errorf("Expected weave mac address %q, got %q", weave.MockContainerMAC, have)
		}
		// Should have Weave container ip
		if have, ok := node.Sets.Lookup(docker.ContainerIPs); !ok || !have.Contains(weave.MockContainerIP) {
			t.Errorf("Expected container ips to include the weave IP %q, got %q", weave.MockContainerIP, have)
		}
		// Should have Weave container ip (with scope)
		if have, ok := node.Sets.Lookup(docker.ContainerIPsWithScopes); !ok || !have.Contains(mockContainerIPWithScope) {
			t.Errorf("Expected container ips to include the weave IP (with scope) %q, got %q", mockContainerIPWithScope, have)
		}
	}
}