Beispiel #1
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
}
Beispiel #2
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)
		}
	}
}
Beispiel #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
		}

		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()))),
		))

	}
}
Beispiel #4
0
// MapContainer2ContainerImage maps container Nodes to container
// image Nodes.
//
// If this function is given a node without a docker_image_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 MapContainer2ContainerImage(n report.Node, _ report.Networks) report.Nodes {
	// Propagate all pseudo nodes
	if n.Topology == Pseudo {
		return report.Nodes{n.ID: n}
	}

	// Otherwise, if some some reason the container doesn't have a image_id
	// (maybe slightly out of sync reports), just drop it
	imageID, timestamp, ok := n.Latest.LookupEntry(docker.ImageID)
	if !ok {
		return report.Nodes{}
	}

	// Add container id key to the counters, which will later be counted to produce the minor label
	id := report.MakeContainerImageNodeID(imageID)
	result := NewDerivedNode(id, n).WithTopology(report.ContainerImage)
	result.Latest = result.Latest.Set(docker.ImageID, timestamp, imageID)
	result.Counters = result.Counters.Add(n.Topology, 1)
	return report.Nodes{id: result}
}
Beispiel #5
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
		}
		output := c.Copy()
		output = propagateLatest(docker.ImageName, image, output)
		output = propagateLatest(docker.ImageLabelPrefix+"works.weave.role", image, output)
		outputs[id] = output
	}
	return outputs
}
Beispiel #6
0
func (r *Reporter) containerImageTopology() report.Topology {
	result := report.MakeTopology().
		WithMetadataTemplates(ContainerImageMetadataTemplates).
		WithTableTemplates(ContainerImageTableTemplates)

	r.registry.WalkImages(func(image *docker_client.APIImages) {
		imageID := trimImageID(image.ID)
		nodeID := report.MakeContainerImageNodeID(imageID)
		node := report.MakeNodeWith(nodeID, map[string]string{
			ImageID: imageID,
		})
		node = node.AddTable(ImageLabelPrefix, image.Labels)

		if len(image.RepoTags) > 0 {
			node = node.WithLatests(map[string]string{ImageName: image.RepoTags[0]})
		}

		result.AddNode(node)
	})

	return result
}
Beispiel #7
0
func TestContainer(t *testing.T) {
	log.SetOutput(ioutil.Discard)

	oldDialStub, oldNewClientConnStub := docker.DialStub, docker.NewClientConnStub
	defer func() { docker.DialStub, docker.NewClientConnStub = oldDialStub, oldNewClientConnStub }()

	docker.DialStub = func(network, address string) (net.Conn, error) {
		return nil, nil
	}

	reader, writer := io.Pipe()
	connection := &mockConnection{reader}

	docker.NewClientConnStub = func(c net.Conn, r *bufio.Reader) docker.ClientConn {
		return connection
	}

	now := time.Unix(12345, 67890).UTC()
	mtime.NowForce(now)
	defer mtime.NowReset()

	const hostID = "scope"
	c := docker.NewContainer(container1, hostID)
	err := c.StartGatheringStats()
	if err != nil {
		t.Errorf("%v", err)
	}
	defer c.StopGatheringStats()

	// Send some stats to the docker container
	stats := &client.Stats{}
	stats.Read = now
	stats.MemoryStats.Usage = 12345
	stats.MemoryStats.Limit = 45678
	encoder := codec.NewEncoder(writer, &codec.JsonHandle{})
	if err = encoder.Encode(&stats); err != nil {
		t.Error(err)
	}

	// Now see if we go them
	{
		uptime := (now.Sub(startTime) / time.Second) * time.Second
		want := report.MakeNodeWith("ping;<container>", map[string]string{
			"docker_container_command":     " ",
			"docker_container_created":     "01 Jan 01 00:00 UTC",
			"docker_container_id":          "ping",
			"docker_container_name":        "pong",
			"docker_image_id":              "baz",
			"docker_label_foo1":            "bar1",
			"docker_label_foo2":            "bar2",
			"docker_container_state":       "running",
			"docker_container_state_human": "Up 6 years",
			"docker_container_uptime":      uptime.String(),
		}).
			WithControls(
				docker.RestartContainer, docker.StopContainer, docker.PauseContainer,
				docker.AttachContainer, docker.ExecContainer,
			).WithMetrics(report.Metrics{
			"docker_cpu_total_usage": report.MakeMetric(),
			"docker_memory_usage":    report.MakeMetric().Add(now, 12345).WithMax(45678),
		}).WithParents(report.EmptySets.
			Add(report.ContainerImage, report.MakeStringSet(report.MakeContainerImageNodeID("baz"))),
		)

		test.Poll(t, 100*time.Millisecond, want, func() interface{} {
			node := c.GetNode()
			node.Latest.ForEach(func(k, v string) {
				if v == "0" || v == "" {
					node.Latest = node.Latest.Delete(k)
				}
			})
			return node
		})
	}

	{
		want := report.EmptySets.
			Add("docker_container_ports", report.MakeStringSet("1.2.3.4:80->80/tcp", "81/tcp")).
			Add("docker_container_ips", report.MakeStringSet("1.2.3.4")).
			Add("docker_container_ips_with_scopes", report.MakeStringSet(";1.2.3.4"))

		test.Poll(t, 100*time.Millisecond, want, func() interface{} {
			return c.NetworkInfo([]net.IP{})
		})
	}

	if c.Image() != "baz" {
		t.Errorf("%s != baz", c.Image())
	}
	if c.PID() != 2 {
		t.Errorf("%d != 2", c.PID())
	}
	node := c.GetNode().WithSets(c.NetworkInfo([]net.IP{}))
	if have := docker.ExtractContainerIPs(node); !reflect.DeepEqual(have, []string{"1.2.3.4"}) {
		t.Errorf("%v != %v", have, []string{"1.2.3.4"})
	}
}
Beispiel #8
0
	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"
	ClientPodUID        = "5d4c3b2a1"
	ServerPodUID        = "i9h8g7f6e"
	ClientPodNodeID     = report.MakePodNodeID(ClientPodUID)
	ServerPodNodeID     = report.MakePodNodeID(ServerPodUID)
	ServiceName         = "pongservice"
	ServiceID           = "ping/pongservice"
	ServiceUID          = "service1234"
	ServiceNodeID       = report.MakeServiceNodeID(ServiceUID)
Beispiel #9
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")
		}
	}
}