Merge pull request #28 from monnand/docker-alias

Displays docker container's name
This commit is contained in:
Victor Marmol 2014-06-12 17:38:38 -07:00
commit 7126b1408c
12 changed files with 86 additions and 66 deletions

View File

@ -32,7 +32,7 @@ type ListType int
type ContainerHandler interface {
GetSpec() (*info.ContainerSpec, error)
GetStats() (*info.ContainerStats, error)
ListContainers(listType ListType) ([]string, error)
ListContainers(listType ListType) ([]info.ContainerReference, error)
ListThreads(listType ListType) ([]int, error)
ListProcesses(listType ListType) ([]int, error)
StatsSummary() (*info.ContainerStatsPercentiles, error)

View File

@ -285,12 +285,12 @@ func (self *dockerContainerHandler) GetStats() (stats *info.ContainerStats, err
return
}
func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]string, error) {
func (self *dockerContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
if self.isDockerContainer() {
return nil, nil
}
if self.isRootContainer() && listType == container.LIST_SELF {
return []string{"/docker"}, nil
return []info.ContainerReference{info.ContainerReference{Name: "/docker"}}, nil
}
opt := docker.ListContainersOptions{
All: true,
@ -299,16 +299,21 @@ func (self *dockerContainerHandler) ListContainers(listType container.ListType)
if err != nil {
return nil, err
}
ret := make([]string, 0, len(containers)+1)
ret := make([]info.ContainerReference, 0, len(containers)+1)
for _, c := range containers {
if !strings.HasPrefix(c.Status, "Up ") {
continue
}
path := fmt.Sprintf("/docker/%v", c.ID)
ret = append(ret, path)
aliases := c.Names
ref := info.ContainerReference{
Name: path,
Aliases: aliases,
}
ret = append(ret, ref)
}
if self.isRootContainer() {
ret = append(ret, "/docker")
ret = append(ret, info.ContainerReference{Name: "/docker"})
}
return ret, nil
}

View File

@ -34,7 +34,7 @@ func (self *containerListFilter) GetStats() (*info.ContainerStats, error) {
return self.handler.GetStats()
}
func (self *containerListFilter) ListContainers(listType ListType) ([]string, error) {
func (self *containerListFilter) ListContainers(listType ListType) ([]info.ContainerReference, error) {
containers, err := self.handler.ListContainers(listType)
if err != nil {
return nil, err
@ -42,9 +42,9 @@ func (self *containerListFilter) ListContainers(listType ListType) ([]string, er
if len(containers) == 0 {
return nil, nil
}
ret := make([]string, 0, len(containers))
ret := make([]info.ContainerReference, 0, len(containers))
for _, c := range containers {
if self.filter(c) {
if self.filter(c.Name) {
ret = append(ret, c)
}
}

View File

@ -37,9 +37,9 @@ func (self *mockContainerHandler) GetStats() (*info.ContainerStats, error) {
return args.Get(0).(*info.ContainerStats), args.Error(1)
}
func (self *mockContainerHandler) ListContainers(listType ListType) ([]string, error) {
func (self *mockContainerHandler) ListContainers(listType ListType) ([]info.ContainerReference, error) {
args := self.Called(listType)
return args.Get(0).([]string), args.Error(1)
return args.Get(0).([]info.ContainerReference), args.Error(1)
}
func (self *mockContainerHandler) ListThreads(listType ListType) ([]int, error) {
@ -55,10 +55,10 @@ func (self *mockContainerHandler) ListProcesses(listType ListType) ([]int, error
func TestWhiteListContainerFilter(t *testing.T) {
mockc := &mockContainerHandler{}
mockc.On("ListContainers", LIST_RECURSIVE).Return(
[]string{
"/docker/ee0103",
"/container/created/by/lmctfy",
"/user/something",
[]info.ContainerReference{
info.ContainerReference{Name: "/docker/ee0103"},
info.ContainerReference{Name: "/container/created/by/lmctfy"},
info.ContainerReference{Name: "/user/something"},
},
nil,
)
@ -76,7 +76,7 @@ func TestWhiteListContainerFilter(t *testing.T) {
for _, c := range containers {
legal := false
for _, prefix := range filterPaths {
if strings.HasPrefix(c, prefix) {
if strings.HasPrefix(c.Name, prefix) {
legal = true
}
}
@ -90,10 +90,10 @@ func TestWhiteListContainerFilter(t *testing.T) {
func TestBlackListContainerFilter(t *testing.T) {
mockc := &mockContainerHandler{}
mockc.On("ListContainers", LIST_RECURSIVE).Return(
[]string{
"/docker/ee0103",
"/container/created/by/lmctfy",
"/user/something",
[]info.ContainerReference{
info.ContainerReference{Name: "/docker/ee0103"},
info.ContainerReference{Name: "/container/created/by/lmctfy"},
info.ContainerReference{Name: "/user/something"},
},
nil,
)
@ -111,7 +111,7 @@ func TestBlackListContainerFilter(t *testing.T) {
for _, c := range containers {
legal := true
for _, prefix := range filterPaths {
if strings.HasPrefix(c, prefix) {
if strings.HasPrefix(c.Name, prefix) {
legal = false
}
}

View File

@ -157,7 +157,7 @@ func (c *lmctfyContainerHandler) GetStats() (*info.ContainerStats, error) {
}
// Gets all subcontainers.
func (c *lmctfyContainerHandler) ListContainers(listType container.ListType) ([]string, error) {
func (c *lmctfyContainerHandler) ListContainers(listType container.ListType) ([]info.ContainerReference, error) {
// Prepare the arguments.
args := []string{"list", "containers", "-v"}
if listType == container.LIST_RECURSIVE {
@ -174,13 +174,14 @@ func (c *lmctfyContainerHandler) ListContainers(listType container.ListType) ([]
// Parse lines as container names.
if len(data) == 0 {
return []string{}, nil
return nil, nil
}
names := strings.Split(string(data), "\n")
containerNames := make([]string, 0, len(names))
containerNames := make([]info.ContainerReference, 0, len(names))
for _, name := range names {
if len(name) != 0 {
containerNames = append(containerNames, name)
ref := info.ContainerReference{Name: name}
containerNames = append(containerNames, ref)
}
}
return containerNames, nil

View File

@ -94,7 +94,7 @@ func (self *percentilesContainerHandlerWrapper) GetStats() (*info.ContainerStats
return stats, nil
}
func (self *percentilesContainerHandlerWrapper) ListContainers(listType ListType) ([]string, error) {
func (self *percentilesContainerHandlerWrapper) ListContainers(listType ListType) ([]info.ContainerReference, error) {
return self.handler.ListContainers(listType)
}

View File

@ -29,7 +29,7 @@ type mockContainer struct {
func (self *mockContainer) GetSpec() (*info.ContainerSpec, error) {
return nil, nil
}
func (self *mockContainer) ListContainers(listType ListType) ([]string, error) {
func (self *mockContainer) ListContainers(listType ListType) ([]info.ContainerReference, error) {
return nil, nil
}

View File

@ -49,12 +49,19 @@ type ContainerSpec struct {
Memory *MemorySpec `json:"memory,omitempty"`
}
type ContainerInfo struct {
// Container reference contains enough information to uniquely identify a container
type ContainerReference struct {
// The absolute name of the container.
Name string `json:"name"`
Aliases []string `json:"aliases,omitempty"`
}
type ContainerInfo struct {
ContainerReference
// The direct subcontainers of the current container.
Subcontainers []string `json:"subcontainers,omitempty"`
Subcontainers []ContainerReference `json:"subcontainers,omitempty"`
// The isolation used in the container.
Spec *ContainerSpec `json:"spec,omitempty"`

View File

@ -30,7 +30,9 @@ func TestStatsStartTime(t *testing.T) {
stats = append(stats, s)
}
cinfo := &ContainerInfo{
Name: "/some/container",
ContainerReference: ContainerReference{
Name: "/some/container",
},
Stats: stats,
}
ref := ct.Add(time.Duration(N-1) * time.Second)
@ -52,7 +54,9 @@ func TestStatsEndTime(t *testing.T) {
stats = append(stats, s)
}
cinfo := &ContainerInfo{
Name: "/some/container",
ContainerReference: ContainerReference{
Name: "/some/container",
},
Stats: stats,
}
ref := ct

View File

@ -35,11 +35,11 @@ type containerStat struct {
Data *info.ContainerStats
}
type containerInfo struct {
Name string
Subcontainers []string
Spec *info.ContainerSpec
Stats *list.List
StatsSummary *info.ContainerStatsPercentiles
info.ContainerReference
Subcontainers []info.ContainerReference
Spec *info.ContainerSpec
Stats *list.List
StatsSummary *info.ContainerStatsPercentiles
}
type containerData struct {

View File

@ -111,7 +111,9 @@ func (m *manager) GetContainerInfo(containerName string) (*info.ContainerInfo, e
// Make a copy of the info for the user.
ret := &info.ContainerInfo{
Name: cinfo.Name,
ContainerReference: info.ContainerReference{
Name: cinfo.Name,
},
Subcontainers: cinfo.Subcontainers,
Spec: cinfo.Spec,
StatsSummary: cinfo.StatsSummary,
@ -180,10 +182,8 @@ func (m *manager) destroyContainer(containerName string) error {
return nil
}
type empty struct{}
// Detect all containers that have been added or deleted.
func (m *manager) getContainersDiff() (added []string, removed []string, err error) {
func (m *manager) getContainersDiff() (added []info.ContainerReference, removed []info.ContainerReference, err error) {
// TODO(vmarmol): We probably don't need to lock around / since it will always be there.
m.containersLock.RLock()
defer m.containersLock.RUnlock()
@ -197,24 +197,24 @@ func (m *manager) getContainersDiff() (added []string, removed []string, err err
if err != nil {
return nil, nil, err
}
allContainers = append(allContainers, "/")
allContainers = append(allContainers, info.ContainerReference{Name: "/"})
// Determine which were added and which were removed.
allContainersSet := make(map[string]*empty)
for name, _ := range m.containers {
allContainersSet[name] = &empty{}
allContainersSet := make(map[string]*containerData)
for name, d := range m.containers {
allContainersSet[name] = d
}
for _, name := range allContainers {
delete(allContainersSet, name)
_, ok := m.containers[name]
for _, c := range allContainers {
delete(allContainersSet, c.Name)
_, ok := m.containers[c.Name]
if !ok {
added = append(added, name)
added = append(added, c)
}
}
// Removed ones are no longer in the container listing.
for name, _ := range allContainersSet {
removed = append(removed, name)
for _, d := range allContainersSet {
removed = append(removed, d.info.ContainerReference)
}
return
@ -228,18 +228,18 @@ func (m *manager) detectContainers() error {
}
// Add the new containers.
for _, name := range added {
_, err = m.createContainer(name)
for _, container := range added {
_, err = m.createContainer(container.Name)
if err != nil {
return fmt.Errorf("Failed to create existing container: %s: %s", name, err)
return fmt.Errorf("Failed to create existing container: %s: %s", container.Name, err)
}
}
// Remove the old containers.
for _, name := range removed {
err = m.destroyContainer(name)
for _, container := range removed {
err = m.destroyContainer(container.Name)
if err != nil {
return fmt.Errorf("Failed to destroy existing container: %s: %s", name, err)
return fmt.Errorf("Failed to destroy existing container: %s: %s", container.Name, err)
}
}

View File

@ -50,8 +50,8 @@ var pageTemplate *template.Template
type pageData struct {
ContainerName string
ParentContainers []string
Subcontainers []string
ParentContainers []info.ContainerReference
Subcontainers []info.ContainerReference
Spec *info.ContainerSpec
Stats []*info.ContainerStats
MachineInfo *info.MachineInfo
@ -69,14 +69,17 @@ func init() {
}
// TODO(vmarmol): Escape this correctly.
func containerLink(containerName string, basenameOnly bool, cssClasses string) interface{} {
func containerLink(container info.ContainerReference, basenameOnly bool, cssClasses string) interface{} {
var displayName string
if basenameOnly {
displayName = path.Base(string(containerName))
containerName := container.Name
if len(container.Aliases) > 0 {
displayName = container.Aliases[0]
} else if basenameOnly {
displayName = path.Base(string(container.Name))
} else {
displayName = string(containerName)
displayName = string(container.Name)
}
if containerName == "root" {
if container.Name == "root" {
containerName = "/"
}
return template.HTML(fmt.Sprintf("<a class=\"%s\" href=\"%s%s\">%s</a>", cssClasses, ContainersPage[:len(ContainersPage)-1], containerName, displayName))
@ -167,15 +170,15 @@ func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL)
}
// Make a list of the parent containers and their links
var parentContainers []string
parentContainers = append(parentContainers, string("root"))
var parentContainers []info.ContainerReference
parentContainers = append(parentContainers, info.ContainerReference{Name: "root"})
parentName := ""
for _, part := range strings.Split(string(cont.Name), "/") {
if part == "" {
continue
}
parentName += "/" + part
parentContainers = append(parentContainers, string(parentName))
parentContainers = append(parentContainers, info.ContainerReference{Name: parentName})
}
data := &pageData{