Skip to content

Commit

Permalink
Expose docker image id and name
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom Wilkie committed May 22, 2015
1 parent f11168c commit 44c64b9
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 21 deletions.
2 changes: 2 additions & 0 deletions app/origin_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ func originNodeForProcess(node report.NodeMetadata) OriginNode {
for _, tuple := range []struct{ key, human string }{
{"docker_id", "Container ID"},
{"docker_name", "Container name"},
{"docker_image_id", "Container image ID"},
{"docker_image_name", "Container image name"},
{"cgroup", "cgroup"},
} {
if val, ok := node[tuple.key]; ok {
Expand Down
62 changes: 47 additions & 15 deletions probe/docker_process_mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
type dockerMapper struct {
sync.RWMutex
d map[int]*docker.Container
images map[string]*docker.APIImages
procRoot string
}

Expand All @@ -35,6 +36,7 @@ func (m *dockerMapper) loop(d time.Duration) {
type dockerClient interface {
ListContainers(docker.ListContainersOptions) ([]docker.APIContainers, error)
InspectContainer(string) (*docker.Container, error)
ListImages(docker.ListImagesOptions) ([]docker.APIImages, error)
}

func newRealDockerClient(endpoint string) (dockerClient, error) {
Expand Down Expand Up @@ -88,17 +90,32 @@ func (m *dockerMapper) update() {
}
}

imageList, err := client.ListImages(docker.ListImagesOptions{})
if err != nil {
log.Printf("docker mapper: %s", err)
return
}

imageMap := map[string]*docker.APIImages{}
for i, _ := range imageList {
image := &imageList[i]
imageMap[image.ID] = image
}

m.Lock()
m.d = pmap
m.images = imageMap
m.Unlock()
}

type dockerIDMapper struct {
type dockerProcessMapper struct {
*dockerMapper
key string
f func(*docker.Container) string
}

func (m dockerIDMapper) Key() string { return "docker_id" }
func (m dockerIDMapper) Map(pid uint) (string, error) {
func (m *dockerProcessMapper) Key() string { return m.key }
func (m *dockerProcessMapper) Map(pid uint) (string, error) {
m.RLock()
container, ok := m.d[int(pid)]
m.RUnlock()
Expand All @@ -107,22 +124,37 @@ func (m dockerIDMapper) Map(pid uint) (string, error) {
return "", fmt.Errorf("no container found for PID %d", pid)
}

return container.ID, nil
return m.f(container), nil
}

type dockerNameMapper struct {
*dockerMapper
func (m *dockerMapper) idMapper() processMapper {
return &dockerProcessMapper{m, "docker_id", func(c *docker.Container) string {
return c.ID
}}
}

func (m dockerNameMapper) Key() string { return "docker_name" }
func (m dockerNameMapper) Map(pid uint) (string, error) {
m.RLock()
container, ok := m.d[int(pid)]
m.RUnlock()
func (m *dockerMapper) nameMapper() processMapper {
return &dockerProcessMapper{m, "docker_name", func(c *docker.Container) string {
return c.Name
}}
}

if !ok {
return "", fmt.Errorf("no container found for PID %d", pid)
}
func (m *dockerMapper) imageIDMapper() processMapper {
return &dockerProcessMapper{m, "docker_image_id", func(c *docker.Container) string {
return c.Image
}}
}

func (m *dockerMapper) imageNameMapper() processMapper {
return &dockerProcessMapper{m, "docker_image_name", func(c *docker.Container) string {
m.RLock()
image, ok := m.images[c.Image]
m.RUnlock()

if !ok || len(image.RepoTags) == 0 {
return ""
}

return container.Name, nil
return image.RepoTags[0]
}}
}
27 changes: 22 additions & 5 deletions probe/docker_process_mapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
type mockDockerClient struct {
containers []docker.APIContainers
containerInfo map[string]*docker.Container
images []docker.APIImages
}

func (m mockDockerClient) ListContainers(options docker.ListContainersOptions) ([]docker.APIContainers, error) {
Expand All @@ -20,6 +21,10 @@ func (m mockDockerClient) InspectContainer(id string) (*docker.Container, error)
return m.containerInfo[id], nil
}

func (m mockDockerClient) ListImages(options docker.ListImagesOptions) ([]docker.APIImages, error) {
return m.images, nil
}

func TestDockerProcessMapper(t *testing.T) {
oldPIDTreeStub, oldDockerClientStub := newPIDTreeStub, newDockerClient
defer func() {
Expand All @@ -46,19 +51,23 @@ func TestDockerProcessMapper(t *testing.T) {
"foo": {
ID: "foo",
Name: "bar",
Image: "baz",
State: docker.State{Pid: 1, Running: true},
},
},
images: []docker.APIImages{{ID: "baz", RepoTags: []string{"tag"}}},
}, nil
}

dockerMapper := newDockerMapper("/proc", 10*time.Second)
dockerIDMapper := dockerIDMapper{dockerMapper}
dockerNameMapper := dockerNameMapper{dockerMapper}
dockerIDMapper := dockerMapper.idMapper()
dockerNameMapper := dockerMapper.nameMapper()
dockerImageIDMapper := dockerMapper.imageIDMapper()
dockerImageNameMapper := dockerMapper.imageNameMapper()

for pid, want := range map[uint]struct{ id, name string }{
1: {"foo", "bar"},
2: {"foo", "bar"},
for pid, want := range map[uint]struct{ id, name, imageID, imageName string }{
1: {"foo", "bar", "baz", "tag"},
2: {"foo", "bar", "baz", "tag"},
} {
haveID, err := dockerIDMapper.Map(pid)
if err != nil || want.id != haveID {
Expand All @@ -68,5 +77,13 @@ func TestDockerProcessMapper(t *testing.T) {
if err != nil || want.name != haveName {
t.Errorf("%d: want %q, have %q (%v)", pid, want.name, haveName, err)
}
haveImageID, err := dockerImageIDMapper.Map(pid)
if err != nil || want.imageID != haveImageID {
t.Errorf("%d: want %q, have %q (%v)", pid, want.name, haveName, err)
}
haveImageName, err := dockerImageNameMapper.Map(pid)
if err != nil || want.imageName != haveImageName {
t.Errorf("%d: want %q, have %q (%v)", pid, want.name, haveName, err)
}
}
}
3 changes: 2 additions & 1 deletion probe/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ func main() {

if *dockerMapper {
docker := newDockerMapper(*procRoot, *dockerInterval)
pms = append(pms, &dockerIDMapper{docker}, &dockerNameMapper{docker})
pms = append(pms, docker.idMapper(), docker.nameMapper(),
docker.imageIDMapper(), docker.imageNameMapper())
}

log.Printf("listening on %s", *listen)
Expand Down

0 comments on commit 44c64b9

Please sign in to comment.