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
|
// 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.
|
// 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)
|
||||||
if err != nil || !ctnr.State.Running {
|
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) {
|
func parseDockerVersion(full_version_string string) ([]int, error) {
|
||||||
|
@ -22,11 +22,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ContainerHandlerFactory interface {
|
type ContainerHandlerFactory interface {
|
||||||
// Create a new ContainerHandler using this factory. CanHandle() must have returned true.
|
// Create a new ContainerHandler using this factory. CanHandleAndAccept() must have returned true.
|
||||||
NewContainerHandler(name string) (ContainerHandler, error)
|
NewContainerHandler(name string) (c ContainerHandler, err error)
|
||||||
|
|
||||||
// Returns whether this factory can handle the specified container.
|
// Returns whether this factory can handle and accept the specified container.
|
||||||
CanHandle(name string) (bool, error)
|
CanHandleAndAccept(name string) (handle bool, accept bool, err error)
|
||||||
|
|
||||||
// Name of the factory.
|
// Name of the factory.
|
||||||
String() string
|
String() string
|
||||||
@ -57,25 +57,30 @@ func HasFactories() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new ContainerHandler for the specified container.
|
// Create a new ContainerHandler for the specified container.
|
||||||
func NewContainerHandler(name string) (ContainerHandler, error) {
|
func NewContainerHandler(name string) (ContainerHandler, bool, error) {
|
||||||
factoriesLock.RLock()
|
factoriesLock.RLock()
|
||||||
defer factoriesLock.RUnlock()
|
defer factoriesLock.RUnlock()
|
||||||
|
|
||||||
// Create the ContainerHandler with the first factory that supports it.
|
// Create the ContainerHandler with the first factory that supports it.
|
||||||
for _, factory := range factories {
|
for _, factory := range factories {
|
||||||
canHandle, err := factory.CanHandle(name)
|
canHandle, canAccept, err := factory.CanHandleAndAccept(name)
|
||||||
if err != nil {
|
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 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)
|
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 {
|
} else {
|
||||||
glog.V(4).Infof("Factory %q was unable to handle container %q", factory, name)
|
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.
|
// Clear the known factories.
|
||||||
|
@ -24,14 +24,15 @@ type mockContainerHandlerFactory struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
Name string
|
Name string
|
||||||
CanHandleValue bool
|
CanHandleValue bool
|
||||||
|
CanAcceptValue bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *mockContainerHandlerFactory) String() string {
|
func (self *mockContainerHandlerFactory) String() string {
|
||||||
return self.Name
|
return self.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *mockContainerHandlerFactory) CanHandle(name string) (bool, error) {
|
func (self *mockContainerHandlerFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||||
return self.CanHandleValue, nil
|
return self.CanHandleValue, self.CanAcceptValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *mockContainerHandlerFactory) NewContainerHandler(name string) (ContainerHandler, error) {
|
func (self *mockContainerHandlerFactory) NewContainerHandler(name string) (ContainerHandler, error) {
|
||||||
@ -50,6 +51,7 @@ func TestNewContainerHandler_FirstMatches(t *testing.T) {
|
|||||||
allwaysYes := &mockContainerHandlerFactory{
|
allwaysYes := &mockContainerHandlerFactory{
|
||||||
Name: "yes",
|
Name: "yes",
|
||||||
CanHandleValue: true,
|
CanHandleValue: true,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysYes)
|
RegisterContainerHandlerFactory(allwaysYes)
|
||||||
|
|
||||||
@ -60,7 +62,7 @@ func TestNewContainerHandler_FirstMatches(t *testing.T) {
|
|||||||
}
|
}
|
||||||
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
||||||
|
|
||||||
cont, err := NewContainerHandler(testContainerName)
|
cont, _, err := NewContainerHandler(testContainerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -76,11 +78,13 @@ func TestNewContainerHandler_SecondMatches(t *testing.T) {
|
|||||||
allwaysNo := &mockContainerHandlerFactory{
|
allwaysNo := &mockContainerHandlerFactory{
|
||||||
Name: "no",
|
Name: "no",
|
||||||
CanHandleValue: false,
|
CanHandleValue: false,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysNo)
|
RegisterContainerHandlerFactory(allwaysNo)
|
||||||
allwaysYes := &mockContainerHandlerFactory{
|
allwaysYes := &mockContainerHandlerFactory{
|
||||||
Name: "yes",
|
Name: "yes",
|
||||||
CanHandleValue: true,
|
CanHandleValue: true,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysYes)
|
RegisterContainerHandlerFactory(allwaysYes)
|
||||||
|
|
||||||
@ -91,7 +95,7 @@ func TestNewContainerHandler_SecondMatches(t *testing.T) {
|
|||||||
}
|
}
|
||||||
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
||||||
|
|
||||||
cont, err := NewContainerHandler(testContainerName)
|
cont, _, err := NewContainerHandler(testContainerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -107,16 +111,44 @@ func TestNewContainerHandler_NoneMatch(t *testing.T) {
|
|||||||
allwaysNo1 := &mockContainerHandlerFactory{
|
allwaysNo1 := &mockContainerHandlerFactory{
|
||||||
Name: "no",
|
Name: "no",
|
||||||
CanHandleValue: false,
|
CanHandleValue: false,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysNo1)
|
RegisterContainerHandlerFactory(allwaysNo1)
|
||||||
allwaysNo2 := &mockContainerHandlerFactory{
|
allwaysNo2 := &mockContainerHandlerFactory{
|
||||||
Name: "no",
|
Name: "no",
|
||||||
CanHandleValue: false,
|
CanHandleValue: false,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysNo2)
|
RegisterContainerHandlerFactory(allwaysNo2)
|
||||||
|
|
||||||
_, err := NewContainerHandler(testContainerName)
|
_, _, err := NewContainerHandler(testContainerName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected NewContainerHandler to fail")
|
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
|
package raw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
@ -24,6 +25,8 @@ import (
|
|||||||
info "github.com/google/cadvisor/info/v1"
|
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 {
|
type rawFactory struct {
|
||||||
// Factory for machine information.
|
// Factory for machine information.
|
||||||
machineInfoFactory info.MachineInfoFactory
|
machineInfoFactory info.MachineInfoFactory
|
||||||
@ -43,9 +46,10 @@ func (self *rawFactory) NewContainerHandler(name string) (container.ContainerHan
|
|||||||
return newRawContainerHandler(name, self.cgroupSubsystems, self.machineInfoFactory, self.fsInfo)
|
return newRawContainerHandler(name, self.cgroupSubsystems, self.machineInfoFactory, self.fsInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The raw factory can handle any container.
|
// The raw factory can handle any container. If --docker_only is set to false, non-docker containers are ignored.
|
||||||
func (self *rawFactory) CanHandle(name string) (bool, error) {
|
func (self *rawFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||||
return true, nil
|
accept := name == "/" || !*dockerOnly
|
||||||
|
return true, accept, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo) error {
|
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.
|
// Get info for all requested containers based on the request options.
|
||||||
GetRequestedContainersInfo(containerName string, options v2.RequestOptions) (map[string]*info.ContainerInfo, error)
|
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.
|
// Get information about the machine.
|
||||||
GetMachineInfo() (*info.MachineInfo, error)
|
GetMachineInfo() (*info.MachineInfo, error)
|
||||||
|
|
||||||
@ -619,12 +622,32 @@ func (m *manager) GetVersionInfo() (*info.VersionInfo, error) {
|
|||||||
return &m.versionInfo, nil
|
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.
|
// Create a container.
|
||||||
func (m *manager) createContainer(containerName string) error {
|
func (m *manager) createContainer(containerName string) error {
|
||||||
handler, err := container.NewContainerHandler(containerName)
|
handler, accept, err := container.NewContainerHandler(containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if !accept {
|
||||||
|
// ignoring this container.
|
||||||
|
glog.V(4).Infof("ignoring container %q", containerName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
logUsage := *logCadvisorUsage && containerName == m.cadvisorContainer
|
logUsage := *logCadvisorUsage && containerName == m.cadvisorContainer
|
||||||
cont, err := newContainerData(containerName, m.memoryStorage, handler, m.loadReader, logUsage)
|
cont, err := newContainerData(containerName, m.memoryStorage, handler, m.loadReader, logUsage)
|
||||||
if err != nil {
|
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)
|
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 {
|
func (c *ManagerMock) WatchForEvents(queryuest *events.Request, passedChannel chan *info.Event) error {
|
||||||
args := c.Called(queryuest, passedChannel)
|
args := c.Called(queryuest, passedChannel)
|
||||||
return args.Error(0)
|
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.
|
// Build the links for the subcontainers.
|
||||||
subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
|
subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
|
||||||
for _, sub := range cont.Subcontainers {
|
for _, sub := range cont.Subcontainers {
|
||||||
|
if !m.Exists(sub.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
subcontainerLinks = append(subcontainerLinks, link{
|
subcontainerLinks = append(subcontainerLinks, link{
|
||||||
Text: getContainerDisplayName(sub),
|
Text: getContainerDisplayName(sub),
|
||||||
Link: path.Join(ContainersPage, sub.Name),
|
Link: path.Join(ContainersPage, sub.Name),
|
||||||
|
Loading…
Reference in New Issue
Block a user