Skip to content
This repository has been archived by the owner on Jul 19, 2018. It is now read-only.

[FEAT] Add container filesystem size capability #39

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions capabilities/filesystem/filesystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package filesystem

import (
"context"
"fmt"

"github.com/puppetlabs/lumogon/capabilities/payloadfilter"
"github.com/puppetlabs/lumogon/capabilities/registry"
"github.com/puppetlabs/lumogon/dockeradapter"
"github.com/puppetlabs/lumogon/logging"
"github.com/puppetlabs/lumogon/types"
)

var filesystemDescription = `The filesystem capability returns sizes of filesystem in a container as a map["layer"]"size"`

// The filesystemCapability capability output from the container runtime inspect
var filesystemCapability = dockeradapter.DockerAPICapability{
Capability: types.Capability{
Schema: "http://puppet.com/lumogon/capability/diff/draft-01/schema#1",
Title: "Filesystem",
Name: "filesystem",
Description: filesystemDescription,
Type: "dockerapi",
Payload: nil,
SupportedOS: map[string]int{"all": 1},
},
Harvest: func(capability *dockeradapter.DockerAPICapability, client dockeradapter.Harvester, id string, target types.TargetContainer) {
logging.Stderr("[Filesystem] Harvesting filesystem sizes from %s [%s]", target.Name, target.ID)
capability.HarvestID = id
logging.Stderr("[Filesystem] Harvesting filesystem capability, harvestid: %s", capability.HarvestID)

ctx := context.Background()
output := make(map[string]interface{})

containerData, err := client.ContainerFilesystem(ctx, target.ID)
if err != nil {
errorMsg := fmt.Sprintf("[Filesystem] Error getting filesystem data from targetContainer: %s, error: %s", target.Name, err)
logging.Stderr(errorMsg)
capability.PayloadError(errorMsg)
return
}

output["sizerw"] = containerData.SizeRw
output["sizerootfs"] = containerData.SizeRootFs
filtered, _ := payloadfilter.Filter(output)
logging.Stderr("[Filesystem] Output: %v", output)
logging.Stderr("[Filesystem] Filtered: %v", filtered)
capability.Payload = filtered
},
}

func init() {
logging.Stderr("[Filesystem] Initialising capability: %s", filesystemCapability.Title)
registry.Registry.Add(filesystemCapability)
}
7 changes: 7 additions & 0 deletions capabilities/filesystem/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package filesystem

// Init exists to allow host init() functions to run when
// invoked from the capabilities Init function, which is
// itself invoked by the Lumogon command handler.
func Init() {
}
3 changes: 3 additions & 0 deletions capabilities/init.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package capabilities

import (
"github.com/puppetlabs/lumogon/capabilities/filesystem"
"github.com/puppetlabs/lumogon/capabilities/host"
"github.com/puppetlabs/lumogon/capabilities/label"
"github.com/puppetlabs/lumogon/capabilities/ospackages"
Expand All @@ -9,7 +10,9 @@ import (
// Init exists to allow capabilities init() functions to run when
// invoked from the Lumogon command handler.
func Init() {

host.Init()
label.Init()
ospackages.Init()
filesystem.Init()
}
40 changes: 40 additions & 0 deletions dockeradapter/dockeradapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import (
"fmt"
"io"

"github.com/davecgh/go-spew/spew"
dockertypes "github.com/docker/docker/api/types"
dockercontainer "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client"
"github.com/puppetlabs/lumogon/logging"
"github.com/puppetlabs/lumogon/types"
"github.com/puppetlabs/lumogon/utils"
)

Expand All @@ -25,12 +28,14 @@ type Client interface {
Lister
HostInspector
CopyFrom
Filesystem
}

// Harvester interface exposes methods used by Capabilties Harvest functions
type Harvester interface {
Inspector
Executor
Filesystem
}

// ImagePuller interface exposes methods required to pull an image
Expand Down Expand Up @@ -98,6 +103,11 @@ type CopyFrom interface {
CopyFromContainer(ctx context.Context, container, srcPath string, followSymlink bool) (io.ReadCloser, dockertypes.ContainerPathStat, error)
}

// Filesystem type contains information on the container filesystem
type Filesystem interface {
ContainerFilesystem(ctx context.Context, containerID string) (types.Filesystem, error)
}

// containerLogOptions type contains values used to control logs returned
// from a container
type containerLogOptions struct {
Expand Down Expand Up @@ -269,6 +279,36 @@ func (c *concreteDockerClient) ContainerList(ctx context.Context) ([]string, err
return result, nil
}

func (c *concreteDockerClient) ContainerFilesystem(ctx context.Context, containerID string) (types.Filesystem, error) {
result := types.Filesystem{}

filter := filters.NewArgs()
filter.Add("id", containerID)

options := dockertypes.ContainerListOptions{
All: true,
Filters: filter,
}

containers, err := c.Client.ContainerList(ctx, options)
if err != nil {
return result, err
}

logging.Stderr("[Filesystem] %s", spew.Sprintf("%#+v", containers))

if len(containers) != 1 {
return result, fmt.Errorf("container lookup should return 1 container but returned %d", len(containers))
}

for _, container := range containers {
result.SizeRw = container.SizeRw
result.SizeRootFs = container.SizeRootFs
}

return result, nil
}

// stripDockerLogsHeader (DEPRECATED) strips the Docker logs header and aims to return a string
func stripDockerLogsHeader(rawlogs string) string {
headerLength := 8
Expand Down
11 changes: 11 additions & 0 deletions test/mocks/dockerclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

dockertypes "github.com/docker/docker/api/types"
dockercontainer "github.com/docker/docker/api/types/container"
"github.com/puppetlabs/lumogon/types"
"github.com/puppetlabs/lumogon/utils"
)

Expand All @@ -30,6 +31,7 @@ type MockDockerClient struct {
ContainerExecInspectFn func(ctx context.Context, execID string) (dockertypes.ContainerExecInspect, error)
ImageInspectFn func(ctx context.Context, imageName string) (dockertypes.ImageInspect, error)
CopyFromContainerFn func(ctx context.Context, container, srcPath string, followSymlink bool) (io.ReadCloser, dockertypes.ContainerPathStat, error)
ContainerFilesystemFn func(ctx context.Context, containerID string) (types.Filesystem, error)
}

// ImagePull is a mock implementation of dockeradapter.ImagePull
Expand Down Expand Up @@ -196,3 +198,12 @@ func (c MockDockerClient) CopyFromContainer(ctx context.Context, container, srcP
}
panic(fmt.Sprintf("No function defined for: %s", utils.CurrentFunctionName()))
}

// ContainerFilesystem is a mock implementation of dockeradapter.ContainerFilesystem
func (c MockDockerClient) ContainerFilesystem(ctx context.Context, containerID string) (types.Filesystem, error) {
if c.ContainerFilesystemFn != nil {
fmt.Println("[MockDockerClient] In ", utils.CurrentFunctionName())
return c.ContainerFilesystemFn(ctx, containerID)
}
panic(fmt.Sprintf("No function defined for: %s", utils.CurrentFunctionName()))
}
7 changes: 7 additions & 0 deletions types/filesystem.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package types

// Filesystem captures size information for a container's filesystem and root filesystem
type Filesystem struct {
SizeRw int64 `json:"sizerw"`
SizeRootFs int64 `json:"sizerootfs"`
}