commit
4910466050
16
cadvisor.go
16
cadvisor.go
@ -63,12 +63,12 @@ func main() {
|
|||||||
|
|
||||||
// Register the raw driver.
|
// Register the raw driver.
|
||||||
if err := raw.Register(containerManager); err != nil {
|
if err := raw.Register(containerManager); err != nil {
|
||||||
glog.Fatalf("raw registration failed: %v.", err)
|
glog.Fatalf("Raw registration failed: %v.", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basic health handler.
|
// Basic health handler.
|
||||||
if err := healthz.RegisterHandler(); err != nil {
|
if err := healthz.RegisterHandler(); err != nil {
|
||||||
glog.Fatalf("failed to register healthz handler: %s", err)
|
glog.Fatalf("Failed to register healthz handler: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler for static content.
|
// Handler for static content.
|
||||||
@ -81,19 +81,15 @@ func main() {
|
|||||||
|
|
||||||
// Register API handler.
|
// Register API handler.
|
||||||
if err := api.RegisterHandlers(containerManager); err != nil {
|
if err := api.RegisterHandlers(containerManager); err != nil {
|
||||||
glog.Fatalf("failed to register API handlers: %s", err)
|
glog.Fatalf("Failed to register API handlers: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect / to containers page.
|
// Redirect / to containers page.
|
||||||
http.Handle("/", http.RedirectHandler(pages.ContainersPage, http.StatusTemporaryRedirect))
|
http.Handle("/", http.RedirectHandler(pages.ContainersPage, http.StatusTemporaryRedirect))
|
||||||
|
|
||||||
// Register the handler for the containers page.
|
if err := pages.RegisterHandlers(containerManager); err != nil {
|
||||||
http.HandleFunc(pages.ContainersPage, func(w http.ResponseWriter, r *http.Request) {
|
glog.Fatalf("Failed to register pages handlers: %s", err)
|
||||||
err := pages.ServerContainersPage(containerManager, w, r.URL)
|
}
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(w, "%s", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Start the manager.
|
// Start the manager.
|
||||||
if err := containerManager.Start(); err != nil {
|
if err := containerManager.Start(); err != nil {
|
||||||
|
@ -82,6 +82,26 @@ func IsDockerContainerName(name string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the Docker ID from the full container name.
|
||||||
|
func ContainerNameToDockerId(name string) string {
|
||||||
|
id := path.Base(name)
|
||||||
|
|
||||||
|
// Turn systemd cgroup name into Docker ID.
|
||||||
|
if useSystemd {
|
||||||
|
const systemdDockerPrefix = "docker-"
|
||||||
|
if strings.HasPrefix(id, systemdDockerPrefix) {
|
||||||
|
id = id[len(systemdDockerPrefix):]
|
||||||
|
}
|
||||||
|
|
||||||
|
const systemdScopeSuffix = ".scope"
|
||||||
|
if strings.HasSuffix(id, systemdScopeSuffix) {
|
||||||
|
id = id[:len(id)-len(systemdScopeSuffix)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a list of possible full container names for the specified Docker container name.
|
// Returns a list of possible full container names for the specified Docker container name.
|
||||||
func FullDockerContainerNames(dockerName string) []string {
|
func FullDockerContainerNames(dockerName string) []string {
|
||||||
names := make([]string, 0, 2)
|
names := make([]string, 0, 2)
|
||||||
@ -107,7 +127,7 @@ func (self *dockerFactory) CanHandle(name string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the container is known to docker and it is active.
|
// Check if the container is known to docker and it is active.
|
||||||
id := containerNameToDockerId(name)
|
id := ContainerNameToDockerId(name)
|
||||||
|
|
||||||
// We assume that if Inspect fails then the container is not known to docker.
|
// We assume that if Inspect fails then the container is not known to docker.
|
||||||
ctnr, err := self.client.InspectContainer(id)
|
ctnr, err := self.client.InspectContainer(id)
|
||||||
|
@ -85,7 +85,7 @@ func newDockerContainerHandler(
|
|||||||
if handler.isDockerRoot() {
|
if handler.isDockerRoot() {
|
||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
id := containerNameToDockerId(name)
|
id := ContainerNameToDockerId(name)
|
||||||
handler.id = id
|
handler.id = id
|
||||||
ctnr, err := client.InspectContainer(id)
|
ctnr, err := client.InspectContainer(id)
|
||||||
// We assume that if Inspect fails then the container is not known to docker.
|
// We assume that if Inspect fails then the container is not known to docker.
|
||||||
@ -96,25 +96,6 @@ func newDockerContainerHandler(
|
|||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func containerNameToDockerId(name string) string {
|
|
||||||
id := path.Base(name)
|
|
||||||
|
|
||||||
// Turn systemd cgroup name into Docker ID.
|
|
||||||
if useSystemd {
|
|
||||||
const systemdDockerPrefix = "docker-"
|
|
||||||
if strings.HasPrefix(id, systemdDockerPrefix) {
|
|
||||||
id = id[len(systemdDockerPrefix):]
|
|
||||||
}
|
|
||||||
|
|
||||||
const systemdScopeSuffix = ".scope"
|
|
||||||
if strings.HasSuffix(id, systemdScopeSuffix) {
|
|
||||||
id = id[:len(id)-len(systemdScopeSuffix)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
|
func (self *dockerContainerHandler) ContainerReference() (info.ContainerReference, error) {
|
||||||
return info.ContainerReference{
|
return info.ContainerReference{
|
||||||
Name: self.name,
|
Name: self.name,
|
||||||
|
@ -88,7 +88,6 @@ func (b ByteSize) Unit() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var funcMap = template.FuncMap{
|
var funcMap = template.FuncMap{
|
||||||
"containerLink": containerLink,
|
|
||||||
"printMask": printMask,
|
"printMask": printMask,
|
||||||
"printCores": printCores,
|
"printCores": printCores,
|
||||||
"printShares": printShares,
|
"printShares": printShares,
|
||||||
@ -102,52 +101,6 @@ var funcMap = template.FuncMap{
|
|||||||
"getFsUsagePercent": getFsUsagePercent,
|
"getFsUsagePercent": getFsUsagePercent,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(vmarmol): Consider housekeeping Spec too so we can show changes through time. We probably don't need it ever second though.
|
|
||||||
|
|
||||||
var pageTemplate *template.Template
|
|
||||||
|
|
||||||
type pageData struct {
|
|
||||||
ContainerName string
|
|
||||||
ParentContainers []info.ContainerReference
|
|
||||||
Subcontainers []info.ContainerReference
|
|
||||||
Spec info.ContainerSpec
|
|
||||||
Stats []*info.ContainerStats
|
|
||||||
MachineInfo *info.MachineInfo
|
|
||||||
ResourcesAvailable bool
|
|
||||||
CpuAvailable bool
|
|
||||||
MemoryAvailable bool
|
|
||||||
NetworkAvailable bool
|
|
||||||
FsAvailable bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
pageTemplate = template.New("containersTemplate").Funcs(funcMap)
|
|
||||||
_, err := pageTemplate.Parse(containersHtmlTemplate)
|
|
||||||
if err != nil {
|
|
||||||
glog.Fatalf("Failed to parse template: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(vmarmol): Escape this correctly.
|
|
||||||
func containerLink(container info.ContainerReference, basenameOnly bool, cssClasses string) interface{} {
|
|
||||||
var displayName string
|
|
||||||
containerName := container.Name
|
|
||||||
if len(container.Aliases) > 0 {
|
|
||||||
displayName = container.Aliases[0]
|
|
||||||
} else if basenameOnly {
|
|
||||||
displayName = path.Base(string(container.Name))
|
|
||||||
} else {
|
|
||||||
displayName = string(container.Name)
|
|
||||||
}
|
|
||||||
if container.Name == "root" {
|
|
||||||
containerName = "/"
|
|
||||||
} else if strings.Contains(container.Name, " ") {
|
|
||||||
// If it has a space, it is an a.k.a, so keep the base-name
|
|
||||||
containerName = container.Name[:strings.Index(container.Name, " ")]
|
|
||||||
}
|
|
||||||
return template.HTML(fmt.Sprintf("<a class=\"%s\" href=\"%s%s\">%s</a>", cssClasses, ContainersPage[:len(ContainersPage)-1], containerName, displayName))
|
|
||||||
}
|
|
||||||
|
|
||||||
func printMask(mask string, numCores int) interface{} {
|
func printMask(mask string, numCores int) interface{} {
|
||||||
masks := make([]string, numCores)
|
masks := make([]string, numCores)
|
||||||
activeCores := getActiveCores(mask)
|
activeCores := getActiveCores(mask)
|
||||||
@ -266,7 +219,7 @@ func getFsUsagePercent(limit, used uint64) uint64 {
|
|||||||
return uint64((float64(used) / float64(limit)) * 100)
|
return uint64((float64(used) / float64(limit)) * 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
|
func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
// The container name is the path after the handler
|
// The container name is the path after the handler
|
||||||
@ -278,8 +231,9 @@ func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL)
|
|||||||
}
|
}
|
||||||
cont, err := m.GetContainerInfo(containerName, &reqParams)
|
cont, err := m.GetContainerInfo(containerName, &reqParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get container \"%s\" with error: %s", containerName, err)
|
return fmt.Errorf("Failed to get container %q with error: %v", containerName, err)
|
||||||
}
|
}
|
||||||
|
displayName := getContainerDisplayName(cont.ContainerReference)
|
||||||
|
|
||||||
// Get the MachineInfo
|
// Get the MachineInfo
|
||||||
machineInfo, err := m.GetMachineInfo()
|
machineInfo, err := m.GetMachineInfo()
|
||||||
@ -288,41 +242,41 @@ func ServerContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make a list of the parent containers and their links
|
// Make a list of the parent containers and their links
|
||||||
var parentContainers []info.ContainerReference
|
pathParts := strings.Split(string(cont.Name), "/")
|
||||||
parentContainers = append(parentContainers, info.ContainerReference{Name: "root"})
|
parentContainers := make([]link, 0, len(pathParts))
|
||||||
parentName := ""
|
parentContainers = append(parentContainers, link{
|
||||||
for _, part := range strings.Split(string(cont.Name), "/") {
|
Text: "root",
|
||||||
if part == "" {
|
Link: ContainersPage,
|
||||||
|
})
|
||||||
|
for i := 1; i < len(pathParts); i++ {
|
||||||
|
// Skip empty parts.
|
||||||
|
if pathParts[i] == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parentName += "/" + part
|
parentContainers = append(parentContainers, link{
|
||||||
parentContainers = append(parentContainers, info.ContainerReference{Name: parentName})
|
Text: pathParts[i],
|
||||||
|
Link: path.Join(ContainersPage, path.Join(pathParts[1:i+1]...)),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick the shortest name of the container as the display name.
|
// Build the links for the subcontainers.
|
||||||
displayName := cont.Name
|
subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
|
||||||
for _, alias := range cont.Aliases {
|
for _, sub := range cont.Subcontainers {
|
||||||
if len(displayName) >= len(alias) {
|
subcontainerLinks = append(subcontainerLinks, link{
|
||||||
displayName = alias
|
Text: getContainerDisplayName(sub),
|
||||||
}
|
Link: path.Join(ContainersPage, sub.Name),
|
||||||
}
|
})
|
||||||
|
|
||||||
// Replace the last part of the parent containers with the displayName.
|
|
||||||
if displayName != cont.Name {
|
|
||||||
parentContainers[len(parentContainers)-1] = info.ContainerReference{
|
|
||||||
Name: fmt.Sprintf("%s (%s)", displayName, path.Base(cont.Name)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data := &pageData{
|
data := &pageData{
|
||||||
ContainerName: displayName,
|
DisplayName: displayName,
|
||||||
// TODO(vmarmol): Only use strings for this.
|
ContainerName: cont.Name,
|
||||||
ParentContainers: parentContainers,
|
ParentContainers: parentContainers,
|
||||||
Subcontainers: cont.Subcontainers,
|
Subcontainers: subcontainerLinks,
|
||||||
Spec: cont.Spec,
|
Spec: cont.Spec,
|
||||||
Stats: cont.Stats,
|
Stats: cont.Stats,
|
||||||
MachineInfo: machineInfo,
|
MachineInfo: machineInfo,
|
||||||
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
|
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork || cont.Spec.HasFilesystem,
|
||||||
CpuAvailable: cont.Spec.HasCpu,
|
CpuAvailable: cont.Spec.HasCpu,
|
||||||
MemoryAvailable: cont.Spec.HasMemory,
|
MemoryAvailable: cont.Spec.HasMemory,
|
||||||
NetworkAvailable: cont.Spec.HasNetwork,
|
NetworkAvailable: cont.Spec.HasNetwork,
|
||||||
|
@ -17,7 +17,7 @@ package pages
|
|||||||
const containersHtmlTemplate = `
|
const containersHtmlTemplate = `
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>cAdvisor - Container {{.ContainerName}}</title>
|
<title>cAdvisor - {{.DisplayName}}</title>
|
||||||
<!-- Latest compiled and minified CSS -->
|
<!-- Latest compiled and minified CSS -->
|
||||||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
|
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
|
||||||
|
|
||||||
@ -39,11 +39,11 @@ const containersHtmlTemplate = `
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>{{.ContainerName}}</h1>
|
<h1>{{.DisplayName}}</h1>
|
||||||
</div>
|
</div>
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
{{range $parentContainer := .ParentContainers}}
|
{{range $parentContainer := .ParentContainers}}
|
||||||
<li>{{containerLink $parentContainer true ""}}</li>
|
<li><a href="{{$parentContainer.Link}}">{{$parentContainer.Text}}</a></li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
@ -54,7 +54,7 @@ const containersHtmlTemplate = `
|
|||||||
</div>
|
</div>
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
{{range $subcontainer := .Subcontainers}}
|
{{range $subcontainer := .Subcontainers}}
|
||||||
{{containerLink $subcontainer false "list-group-item"}}
|
<a href="{{$subcontainer.Link}}" class="list-group-item">{{$subcontainer.Text}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -165,7 +165,7 @@ const containersHtmlTemplate = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3">
|
<div class="col-sm-3">
|
||||||
{{printSize .Limit}} {{printUnit .Limit}} ({{getFsUsagePercent .Limit .Usage}}%)
|
{{printSize .Limit}} {{printUnit .Limit}} ({{getFsUsagePercent .Limit .Usage}}%)
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
106
pages/docker.go
Normal file
106
pages/docker.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package pages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/google/cadvisor/container/docker"
|
||||||
|
"github.com/google/cadvisor/info"
|
||||||
|
"github.com/google/cadvisor/manager"
|
||||||
|
)
|
||||||
|
|
||||||
|
const DockerPage = "/docker/"
|
||||||
|
|
||||||
|
func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
// The container name is the path after the handler
|
||||||
|
containerName := u.Path[len(DockerPage)-1:]
|
||||||
|
|
||||||
|
var data *pageData
|
||||||
|
if containerName == "/" {
|
||||||
|
// Get the containers.
|
||||||
|
reqParams := info.ContainerInfoRequest{
|
||||||
|
NumStats: 0,
|
||||||
|
}
|
||||||
|
conts, err := m.DockerContainersInfo("/", &reqParams)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to get container %q with error: %v", containerName, err)
|
||||||
|
}
|
||||||
|
subcontainers := make([]link, 0, len(conts))
|
||||||
|
for _, cont := range conts {
|
||||||
|
subcontainers = append(subcontainers, link{
|
||||||
|
Text: getContainerDisplayName(cont.ContainerReference),
|
||||||
|
Link: path.Join("/docker", docker.ContainerNameToDockerId(cont.ContainerReference.Name)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerContainersText := "Docker Containers"
|
||||||
|
data = &pageData{
|
||||||
|
DisplayName: dockerContainersText,
|
||||||
|
ParentContainers: []link{
|
||||||
|
link{
|
||||||
|
Text: dockerContainersText,
|
||||||
|
Link: DockerPage,
|
||||||
|
}},
|
||||||
|
Subcontainers: subcontainers,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Get the container.
|
||||||
|
reqParams := info.ContainerInfoRequest{
|
||||||
|
NumStats: 60,
|
||||||
|
}
|
||||||
|
conts, err := m.DockerContainersInfo(containerName, &reqParams)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get container %q with error: %v", containerName, err)
|
||||||
|
}
|
||||||
|
if len(conts) != 1 {
|
||||||
|
return fmt.Errorf("received unexpected container for %q: %v", conts)
|
||||||
|
}
|
||||||
|
cont := conts[0]
|
||||||
|
displayName := getContainerDisplayName(cont.ContainerReference)
|
||||||
|
|
||||||
|
// Make a list of the parent containers and their links
|
||||||
|
var parentContainers []link
|
||||||
|
parentContainers = append(parentContainers, link{
|
||||||
|
Text: "Docker containers",
|
||||||
|
Link: DockerPage,
|
||||||
|
})
|
||||||
|
parentContainers = append(parentContainers, link{
|
||||||
|
Text: displayName,
|
||||||
|
Link: path.Join(DockerPage, docker.ContainerNameToDockerId(cont.Name)),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Get the MachineInfo
|
||||||
|
machineInfo, err := m.GetMachineInfo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
data = &pageData{
|
||||||
|
DisplayName: displayName,
|
||||||
|
ContainerName: cont.Name,
|
||||||
|
ParentContainers: parentContainers,
|
||||||
|
Spec: cont.Spec,
|
||||||
|
Stats: cont.Stats,
|
||||||
|
MachineInfo: machineInfo,
|
||||||
|
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
|
||||||
|
CpuAvailable: cont.Spec.HasCpu,
|
||||||
|
MemoryAvailable: cont.Spec.HasMemory,
|
||||||
|
NetworkAvailable: cont.Spec.HasNetwork,
|
||||||
|
FsAvailable: cont.Spec.HasFilesystem,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := pageTemplate.Execute(w, data)
|
||||||
|
if err != nil {
|
||||||
|
glog.Errorf("Failed to apply template: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(1).Infof("Request took %s", time.Since(start))
|
||||||
|
return nil
|
||||||
|
}
|
82
pages/pages.go
Normal file
82
pages/pages.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package pages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/google/cadvisor/info"
|
||||||
|
"github.com/google/cadvisor/manager"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pageTemplate *template.Template
|
||||||
|
|
||||||
|
type link struct {
|
||||||
|
// Text to show in the link.
|
||||||
|
Text string
|
||||||
|
|
||||||
|
// Web address to link to.
|
||||||
|
Link string
|
||||||
|
}
|
||||||
|
|
||||||
|
type pageData struct {
|
||||||
|
DisplayName string
|
||||||
|
ContainerName string
|
||||||
|
ParentContainers []link
|
||||||
|
Subcontainers []link
|
||||||
|
Spec info.ContainerSpec
|
||||||
|
Stats []*info.ContainerStats
|
||||||
|
MachineInfo *info.MachineInfo
|
||||||
|
ResourcesAvailable bool
|
||||||
|
CpuAvailable bool
|
||||||
|
MemoryAvailable bool
|
||||||
|
NetworkAvailable bool
|
||||||
|
FsAvailable bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
pageTemplate = template.New("containersTemplate").Funcs(funcMap)
|
||||||
|
_, err := pageTemplate.Parse(containersHtmlTemplate)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatalf("Failed to parse template: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register http handlers for pages.
|
||||||
|
func RegisterHandlers(containerManager manager.Manager) error {
|
||||||
|
// Register the handler for the containers page.
|
||||||
|
http.HandleFunc(ContainersPage, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
err := serveContainersPage(containerManager, w, r.URL)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, "%s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Register the handler for the docker page.
|
||||||
|
http.HandleFunc(DockerPage, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
err := serveDockerPage(containerManager, w, r.URL)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, "%s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContainerDisplayName(cont info.ContainerReference) string {
|
||||||
|
// Pick the shortest name of the container as the display name.
|
||||||
|
displayName := cont.Name
|
||||||
|
for _, alias := range cont.Aliases {
|
||||||
|
if len(displayName) >= len(alias) {
|
||||||
|
displayName = alias
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the full container name to the display name.
|
||||||
|
if displayName != cont.Name {
|
||||||
|
displayName = fmt.Sprintf("%s (%s)", displayName, cont.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return displayName
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user