diff --git a/probe/docker/container.go b/probe/docker/container.go index 700f408a5..42bee395d 100644 --- a/probe/docker/container.go +++ b/probe/docker/container.go @@ -216,6 +216,7 @@ func (c *container) GetNodeMetadata() report.NodeMetadata { ContainerIPs: strings.Join(append(c.container.NetworkSettings.SecondaryIPAddresses, c.container.NetworkSettings.IPAddress), " "), }) + AddLabels(result, c.container.Config.Labels) if c.latestStats == nil { return result diff --git a/probe/docker/labels.go b/probe/docker/labels.go new file mode 100644 index 000000000..2cc6a8dd4 --- /dev/null +++ b/probe/docker/labels.go @@ -0,0 +1,31 @@ +package docker + +import ( + "strings" + + "github.com/weaveworks/scope/report" +) + +// LabelPrefix is the key prefix used for Docker labels in NodeMetadata (e.g. a +// Docker label "labelKey"="labelValue" will get encoded as +// "docker_label_labelKey"="dockerValue" in the metadata) +const LabelPrefix = "docker_label_" + +// AddLabels appends Docker labels to the NodeMetadata from a topology. +func AddLabels(nmd report.NodeMetadata, labels map[string]string) { + for key, value := range labels { + nmd.Metadata[LabelPrefix+key] = value + } +} + +// ExtractLabels returns the list of Docker labels given a NodeMetadata from a topology. +func ExtractLabels(nmd report.NodeMetadata) map[string]string { + result := map[string]string{} + for key, value := range nmd.Metadata { + if strings.HasPrefix(key, LabelPrefix) { + label := key[len(LabelPrefix):] + result[label] = value + } + } + return result +} diff --git a/probe/docker/labels_test.go b/probe/docker/labels_test.go new file mode 100644 index 000000000..45c295e0d --- /dev/null +++ b/probe/docker/labels_test.go @@ -0,0 +1,25 @@ +package docker_test + +import ( + "reflect" + "testing" + + "github.com/weaveworks/scope/probe/docker" + "github.com/weaveworks/scope/report" + "github.com/weaveworks/scope/test" +) + +func TestLabels(t *testing.T) { + want := map[string]string{ + "foo1": "bar1", + "foo2": "bar2", + } + nmd := report.MakeNodeMetadata() + + docker.AddLabels(nmd, want) + have := docker.ExtractLabels(nmd) + + if !reflect.DeepEqual(want, have) { + t.Error(test.Diff(want, have)) + } +} diff --git a/probe/docker/registry_test.go b/probe/docker/registry_test.go index 8ff812b9f..16de8e9f0 100644 --- a/probe/docker/registry_test.go +++ b/probe/docker/registry_test.go @@ -106,12 +106,24 @@ var ( NetworkSettings: &client.NetworkSettings{ IPAddress: "1.2.3.4", }, + Config: &client.Config{ + Labels: map[string]string{ + "foo1": "bar1", + "foo2": "bar2", + }, + }, } container2 = &client.Container{ ID: "wiff", Name: "waff", Image: "baz", State: client.State{Pid: 1, Running: true}, + Config: &client.Config{ + Labels: map[string]string{ + "foo1": "bar1", + "foo2": "bar2", + }, + }, } apiContainer1 = client.APIContainers{ID: "ping"} apiImage1 = client.APIImages{ID: "baz", RepoTags: []string{"bang", "not-chosen"}} diff --git a/probe/docker/reporter.go b/probe/docker/reporter.go index 587fcff28..5f499557f 100644 --- a/probe/docker/reporter.go +++ b/probe/docker/reporter.go @@ -52,6 +52,7 @@ func (r *Reporter) containerImageTopology() report.Topology { nmd := report.MakeNodeMetadataWith(map[string]string{ ImageID: image.ID, }) + AddLabels(nmd, image.Labels) if len(image.RepoTags) > 0 { nmd.Metadata[ImageName] = image.RepoTags[0] diff --git a/render/detailed_node.go b/render/detailed_node.go index 263411b0e..c5fd927b9 100644 --- a/render/detailed_node.go +++ b/render/detailed_node.go @@ -312,6 +312,7 @@ func containerOriginTable(nmd report.NodeMetadata, addHostTag bool) (Table, bool for _, ip := range docker.ExtractContainerIPs(nmd) { rows = append(rows, Row{Key: "IP Address", ValueMajor: ip, ValueMinor: ""}) } + rows = append(rows, getDockerLabelRows(nmd)...) if val, ok := nmd.Metadata[docker.MemoryUsage]; ok { memory, err := strconv.ParseFloat(val, 64) @@ -349,6 +350,7 @@ func containerImageOriginTable(nmd report.NodeMetadata) (Table, bool) { rows = append(rows, Row{Key: tuple.human, ValueMajor: val, ValueMinor: ""}) } } + rows = append(rows, getDockerLabelRows(nmd)...) title := "Container Image" var ( nameFound bool @@ -365,6 +367,21 @@ func containerImageOriginTable(nmd report.NodeMetadata) (Table, bool) { }, len(rows) > 0 || nameFound } +func getDockerLabelRows(nmd report.NodeMetadata) []Row { + rows := []Row{} + // Add labels in alphabetical order + labels := docker.ExtractLabels(nmd) + labelKeys := make([]string, 0, len(labels)) + for k := range labels { + labelKeys = append(labelKeys, k) + } + sort.Strings(labelKeys) + for _, labelKey := range labelKeys { + rows = append(rows, Row{Key: fmt.Sprintf("Label %q", labelKey), ValueMajor: labels[labelKey]}) + } + return rows +} + func hostOriginTable(nmd report.NodeMetadata) (Table, bool) { rows := []Row{} for _, tuple := range []struct{ key, human string }{ diff --git a/render/detailed_node_test.go b/render/detailed_node_test.go index af34a06b7..f47c54064 100644 --- a/render/detailed_node_test.go +++ b/render/detailed_node_test.go @@ -58,6 +58,8 @@ func TestOriginTable(t *testing.T) { {"Host", test.ServerHostID, "", false}, {"ID", test.ServerContainerID, "", false}, {"Image ID", test.ServerContainerImageID, "", false}, + {`Label "foo1"`, `bar1`, "", false}, + {`Label "foo2"`, `bar2`, "", false}, }, }, } { @@ -146,6 +148,8 @@ func TestMakeDetailedContainerNode(t *testing.T) { Rows: []render.Row{ {"ID", test.ServerContainerID, "", false}, {"Image ID", test.ServerContainerImageID, "", false}, + {`Label "foo1"`, `bar1`, "", false}, + {`Label "foo2"`, `bar2`, "", false}, }, }, { diff --git a/test/report_fixture.go b/test/report_fixture.go index b84314239..cb9ac84a4 100644 --- a/test/report_fixture.go +++ b/test/report_fixture.go @@ -174,10 +174,12 @@ var ( report.HostNodeID: ClientHostNodeID, }), ServerContainerNodeID: report.MakeNodeMetadataWith(map[string]string{ - docker.ContainerID: ServerContainerID, - docker.ContainerName: "server", - docker.ImageID: ServerContainerImageID, - report.HostNodeID: ServerHostNodeID, + docker.ContainerID: ServerContainerID, + docker.ContainerName: "server", + docker.ImageID: ServerContainerImageID, + report.HostNodeID: ServerHostNodeID, + docker.LabelPrefix + "foo1": "bar1", + docker.LabelPrefix + "foo2": "bar2", }), }, }, @@ -189,9 +191,11 @@ var ( report.HostNodeID: ClientHostNodeID, }), ServerContainerImageNodeID: report.MakeNodeMetadataWith(map[string]string{ - docker.ImageID: ServerContainerImageID, - docker.ImageName: ServerContainerImageName, - report.HostNodeID: ServerHostNodeID, + docker.ImageID: ServerContainerImageID, + docker.ImageName: ServerContainerImageName, + report.HostNodeID: ServerHostNodeID, + docker.LabelPrefix + "foo1": "bar1", + docker.LabelPrefix + "foo2": "bar2", }), }, },