Merge pull request #670 from rjnagal/docker
Add --docker_only flag to enable tracking for only docker containers & root.
This commit is contained in:
commit
95f1ee9c40
@ -134,17 +134,19 @@ func FullContainerName(dockerId string) string {
|
||||
}
|
||||
|
||||
// Docker handles all containers under /docker
|
||||
func (self *dockerFactory) CanHandle(name string) (bool, error) {
|
||||
func (self *dockerFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||
// docker factory accepts all containers it can handle.
|
||||
canAccept := true
|
||||
// Check if the container is known to docker and it is active.
|
||||
id := ContainerNameToDockerId(name)
|
||||
|
||||
// We assume that if Inspect fails then the container is not known to docker.
|
||||
ctnr, err := self.client.InspectContainer(id)
|
||||
if err != nil || !ctnr.State.Running {
|
||||
return false, fmt.Errorf("error inspecting container: %v", err)
|
||||
return false, canAccept, fmt.Errorf("error inspecting container: %v", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return true, canAccept, nil
|
||||
}
|
||||
|
||||
func parseDockerVersion(full_version_string string) ([]int, error) {
|
||||
|
@ -22,11 +22,11 @@ import (
|
||||
)
|
||||
|
||||
type ContainerHandlerFactory interface {
|
||||
// Create a new ContainerHandler using this factory. CanHandle() must have returned true.
|
||||
NewContainerHandler(name string) (ContainerHandler, error)
|
||||
// Create a new ContainerHandler using this factory. CanHandleAndAccept() must have returned true.
|
||||
NewContainerHandler(name string) (c ContainerHandler, err error)
|
||||
|
||||
// Returns whether this factory can handle the specified container.
|
||||
CanHandle(name string) (bool, error)
|
||||
// Returns whether this factory can handle and accept the specified container.
|
||||
CanHandleAndAccept(name string) (handle bool, accept bool, err error)
|
||||
|
||||
// Name of the factory.
|
||||
String() string
|
||||
@ -57,25 +57,30 @@ func HasFactories() bool {
|
||||
}
|
||||
|
||||
// Create a new ContainerHandler for the specified container.
|
||||
func NewContainerHandler(name string) (ContainerHandler, error) {
|
||||
func NewContainerHandler(name string) (ContainerHandler, bool, error) {
|
||||
factoriesLock.RLock()
|
||||
defer factoriesLock.RUnlock()
|
||||
|
||||
// Create the ContainerHandler with the first factory that supports it.
|
||||
for _, factory := range factories {
|
||||
canHandle, err := factory.CanHandle(name)
|
||||
canHandle, canAccept, err := factory.CanHandleAndAccept(name)
|
||||
if err != nil {
|
||||
glog.V(4).Infof("Error trying to work out if we can hande %s: %v", name, err)
|
||||
glog.V(4).Infof("Error trying to work out if we can handle %s: %v", name, err)
|
||||
}
|
||||
if canHandle {
|
||||
if !canAccept {
|
||||
glog.V(3).Infof("Factory %q can handle container %q, but ignoring.", factory, name)
|
||||
return nil, false, nil
|
||||
}
|
||||
glog.V(3).Infof("Using factory %q for container %q", factory, name)
|
||||
return factory.NewContainerHandler(name)
|
||||
handle, err := factory.NewContainerHandler(name)
|
||||
return handle, canAccept, err
|
||||
} else {
|
||||
glog.V(4).Infof("Factory %q was unable to handle container %q", factory, name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no known factory can handle creation of container")
|
||||
return nil, false, fmt.Errorf("no known factory can handle creation of container")
|
||||
}
|
||||
|
||||
// Clear the known factories.
|
||||
|
@ -24,14 +24,15 @@ type mockContainerHandlerFactory struct {
|
||||
mock.Mock
|
||||
Name string
|
||||
CanHandleValue bool
|
||||
CanAcceptValue bool
|
||||
}
|
||||
|
||||
func (self *mockContainerHandlerFactory) String() string {
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *mockContainerHandlerFactory) CanHandle(name string) (bool, error) {
|
||||
return self.CanHandleValue, nil
|
||||
func (self *mockContainerHandlerFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||
return self.CanHandleValue, self.CanAcceptValue, nil
|
||||
}
|
||||
|
||||
func (self *mockContainerHandlerFactory) NewContainerHandler(name string) (ContainerHandler, error) {
|
||||
@ -50,6 +51,7 @@ func TestNewContainerHandler_FirstMatches(t *testing.T) {
|
||||
allwaysYes := &mockContainerHandlerFactory{
|
||||
Name: "yes",
|
||||
CanHandleValue: true,
|
||||
CanAcceptValue: true,
|
||||
}
|
||||
RegisterContainerHandlerFactory(allwaysYes)
|
||||
|
||||
@ -60,7 +62,7 @@ func TestNewContainerHandler_FirstMatches(t *testing.T) {
|
||||
}
|
||||
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
||||
|
||||
cont, err := NewContainerHandler(testContainerName)
|
||||
cont, _, err := NewContainerHandler(testContainerName)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -76,11 +78,13 @@ func TestNewContainerHandler_SecondMatches(t *testing.T) {
|
||||
allwaysNo := &mockContainerHandlerFactory{
|
||||
Name: "no",
|
||||
CanHandleValue: false,
|
||||
CanAcceptValue: true,
|
||||
}
|
||||
RegisterContainerHandlerFactory(allwaysNo)
|
||||
allwaysYes := &mockContainerHandlerFactory{
|
||||
Name: "yes",
|
||||
CanHandleValue: true,
|
||||
CanAcceptValue: true,
|
||||
}
|
||||
RegisterContainerHandlerFactory(allwaysYes)
|
||||
|
||||
@ -91,7 +95,7 @@ func TestNewContainerHandler_SecondMatches(t *testing.T) {
|
||||
}
|
||||
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
||||
|
||||
cont, err := NewContainerHandler(testContainerName)
|
||||
cont, _, err := NewContainerHandler(testContainerName)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -107,16 +111,44 @@ func TestNewContainerHandler_NoneMatch(t *testing.T) {
|
||||
allwaysNo1 := &mockContainerHandlerFactory{
|
||||
Name: "no",
|
||||
CanHandleValue: false,
|
||||
CanAcceptValue: true,
|
||||
}
|
||||
RegisterContainerHandlerFactory(allwaysNo1)
|
||||
allwaysNo2 := &mockContainerHandlerFactory{
|
||||
Name: "no",
|
||||
CanHandleValue: false,
|
||||
CanAcceptValue: true,
|
||||
}
|
||||
RegisterContainerHandlerFactory(allwaysNo2)
|
||||
|
||||
_, err := NewContainerHandler(testContainerName)
|
||||
_, _, err := NewContainerHandler(testContainerName)
|
||||
if err == nil {
|
||||
t.Error("Expected NewContainerHandler to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewContainerHandler_Accept(t *testing.T) {
|
||||
ClearContainerHandlerFactories()
|
||||
|
||||
// Register handler that can handle the container, but can't accept it.
|
||||
cannotHandle := &mockContainerHandlerFactory{
|
||||
Name: "no",
|
||||
CanHandleValue: false,
|
||||
CanAcceptValue: true,
|
||||
}
|
||||
RegisterContainerHandlerFactory(cannotHandle)
|
||||
cannotAccept := &mockContainerHandlerFactory{
|
||||
Name: "no",
|
||||
CanHandleValue: true,
|
||||
CanAcceptValue: false,
|
||||
}
|
||||
RegisterContainerHandlerFactory(cannotAccept)
|
||||
|
||||
_, accept, err := NewContainerHandler(testContainerName)
|
||||
if err != nil {
|
||||
t.Error("Expected NewContainerHandler to succeed")
|
||||
}
|
||||
if accept == true {
|
||||
t.Error("Expected NewContainerHandler to ignore the container.")
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
package raw
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
@ -24,6 +25,8 @@ import (
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
)
|
||||
|
||||
var dockerOnly = flag.Bool("docker_only", false, "Only report docker containers in addition to root stats")
|
||||
|
||||
type rawFactory struct {
|
||||
// Factory for machine information.
|
||||
machineInfoFactory info.MachineInfoFactory
|
||||
@ -43,9 +46,10 @@ func (self *rawFactory) NewContainerHandler(name string) (container.ContainerHan
|
||||
return newRawContainerHandler(name, self.cgroupSubsystems, self.machineInfoFactory, self.fsInfo)
|
||||
}
|
||||
|
||||
// The raw factory can handle any container.
|
||||
func (self *rawFactory) CanHandle(name string) (bool, error) {
|
||||
return true, nil
|
||||
// The raw factory can handle any container. If --docker_only is set to false, non-docker containers are ignored.
|
||||
func (self *rawFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||
accept := name == "/" || !*dockerOnly
|
||||
return true, accept, nil
|
||||
}
|
||||
|
||||
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo) error {
|
||||
|
@ -73,6 +73,9 @@ type Manager interface {
|
||||
// Get info for all requested containers based on the request options.
|
||||
GetRequestedContainersInfo(containerName string, options v2.RequestOptions) (map[string]*info.ContainerInfo, error)
|
||||
|
||||
// Returns true if the named container exists.
|
||||
Exists(containerName string) bool
|
||||
|
||||
// Get information about the machine.
|
||||
GetMachineInfo() (*info.MachineInfo, error)
|
||||
|
||||
@ -619,12 +622,32 @@ func (m *manager) GetVersionInfo() (*info.VersionInfo, error) {
|
||||
return &m.versionInfo, nil
|
||||
}
|
||||
|
||||
func (m *manager) Exists(containerName string) bool {
|
||||
m.containersLock.Lock()
|
||||
defer m.containersLock.Unlock()
|
||||
|
||||
namespacedName := namespacedContainerName{
|
||||
Name: containerName,
|
||||
}
|
||||
|
||||
_, ok := m.containers[namespacedName]
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Create a container.
|
||||
func (m *manager) createContainer(containerName string) error {
|
||||
handler, err := container.NewContainerHandler(containerName)
|
||||
handler, accept, err := container.NewContainerHandler(containerName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !accept {
|
||||
// ignoring this container.
|
||||
glog.V(4).Infof("ignoring container %q", containerName)
|
||||
return nil
|
||||
}
|
||||
logUsage := *logCadvisorUsage && containerName == m.cadvisorContainer
|
||||
cont, err := newContainerData(containerName, m.memoryStorage, handler, m.loadReader, logUsage)
|
||||
if err != nil {
|
||||
|
@ -70,6 +70,11 @@ func (c *ManagerMock) GetRequestedContainersInfo(containerName string, options v
|
||||
return args.Get(0).(map[string]*info.ContainerInfo), args.Error(1)
|
||||
}
|
||||
|
||||
func (c *ManagerMock) Exists(name string) bool {
|
||||
args := c.Called(name)
|
||||
return args.Get(0).(bool)
|
||||
}
|
||||
|
||||
func (c *ManagerMock) WatchForEvents(queryuest *events.Request, passedChannel chan *info.Event) error {
|
||||
args := c.Called(queryuest, passedChannel)
|
||||
return args.Error(0)
|
||||
|
@ -216,6 +216,9 @@ func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) e
|
||||
// Build the links for the subcontainers.
|
||||
subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
|
||||
for _, sub := range cont.Subcontainers {
|
||||
if !m.Exists(sub.Name) {
|
||||
continue
|
||||
}
|
||||
subcontainerLinks = append(subcontainerLinks, link{
|
||||
Text: getContainerDisplayName(sub),
|
||||
Link: path.Join(ContainersPage, sub.Name),
|
||||
|
Loading…
Reference in New Issue
Block a user