mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-09 16:00:59 +00:00
Expand Docker and Kubernetes platform projections
This commit is contained in:
parent
d3934e19e3
commit
6346929328
63 changed files with 5858 additions and 258 deletions
|
|
@ -11,7 +11,11 @@ import (
|
|||
"time"
|
||||
|
||||
containertypes "github.com/moby/moby/api/types/container"
|
||||
imagetypes "github.com/moby/moby/api/types/image"
|
||||
networktypes "github.com/moby/moby/api/types/network"
|
||||
systemtypes "github.com/moby/moby/api/types/system"
|
||||
volumetypes "github.com/moby/moby/api/types/volume"
|
||||
dockerclient "github.com/moby/moby/client"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
|
|
@ -30,6 +34,106 @@ func TestBuildHostSecurityInfoAuthorizationPlugins(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCollectDockerNativeInventory(t *testing.T) {
|
||||
createdAt := time.Date(2026, 5, 24, 8, 0, 0, 0, time.UTC)
|
||||
agent := &Agent{
|
||||
logger: zerolog.Nop(),
|
||||
docker: &fakeDockerClient{
|
||||
imageListFn: func(context.Context, dockerImageListOptions) ([]imagetypes.Summary, error) {
|
||||
return []imagetypes.Summary{{
|
||||
ID: " sha256:image1 ",
|
||||
RepoTags: []string{"repo/app:latest", " "},
|
||||
RepoDigests: []string{"repo/app@sha256:abc"},
|
||||
Size: 1024,
|
||||
SharedSize: 256,
|
||||
Containers: 2,
|
||||
Created: createdAt.Unix(),
|
||||
Labels: map[string]string{"tier": "web"},
|
||||
}}, nil
|
||||
},
|
||||
volumeListFn: func(context.Context, dockerVolumeListOptions) ([]volumetypes.Volume, error) {
|
||||
return []volumetypes.Volume{{
|
||||
Name: " app-data ",
|
||||
Driver: " local ",
|
||||
Mountpoint: "/var/lib/docker/volumes/app-data",
|
||||
Scope: " local ",
|
||||
Labels: map[string]string{"backup": "true"},
|
||||
}}, nil
|
||||
},
|
||||
networkListFn: func(context.Context, dockerNetworkListOptions) ([]networktypes.Summary, error) {
|
||||
return []networktypes.Summary{{
|
||||
Network: networktypes.Network{
|
||||
ID: " net1 ",
|
||||
Name: " app-net ",
|
||||
Driver: " bridge ",
|
||||
Scope: " local ",
|
||||
EnableIPv4: true,
|
||||
Attachable: true,
|
||||
IPAM: networktypes.IPAM{Config: []networktypes.IPAMConfig{{
|
||||
Subnet: netip.MustParsePrefix("10.88.0.0/24"),
|
||||
Gateway: netip.MustParseAddr("10.88.0.1"),
|
||||
}}},
|
||||
Labels: map[string]string{"env": "prod"},
|
||||
Options: map[string]string{"mtu": "1500"},
|
||||
},
|
||||
}}, nil
|
||||
},
|
||||
diskUsageFn: func(context.Context, dockerDiskUsageOptions) (dockerclient.DiskUsageResult, error) {
|
||||
return dockerclient.DiskUsageResult{
|
||||
Images: dockerclient.ImagesDiskUsage{
|
||||
TotalCount: 3, ActiveCount: 2, TotalSize: 4096, Reclaimable: 512,
|
||||
},
|
||||
Volumes: dockerclient.VolumesDiskUsage{
|
||||
TotalCount: 1,
|
||||
Items: []volumetypes.Volume{{
|
||||
Name: "app-data",
|
||||
UsageData: &volumetypes.UsageData{Size: 2048, RefCount: 4},
|
||||
}},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
images, err := agent.collectImages(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("collectImages: %v", err)
|
||||
}
|
||||
if len(images) != 1 || images[0].ID != "sha256:image1" || images[0].CreatedAt != createdAt {
|
||||
t.Fatalf("unexpected images: %+v", images)
|
||||
}
|
||||
if len(images[0].RepoTags) != 1 || images[0].RepoTags[0] != "repo/app:latest" {
|
||||
t.Fatalf("expected normalized repo tags, got %#v", images[0].RepoTags)
|
||||
}
|
||||
|
||||
usageResult, storageUsage, err := agent.collectStorageUsage(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("collectStorageUsage: %v", err)
|
||||
}
|
||||
if storageUsage.Images.TotalCount != 3 || storageUsage.Images.ReclaimableBytes != 512 {
|
||||
t.Fatalf("unexpected storage usage: %+v", storageUsage)
|
||||
}
|
||||
|
||||
volumes, err := agent.collectVolumes(context.Background(), usageResult.Volumes.Items)
|
||||
if err != nil {
|
||||
t.Fatalf("collectVolumes: %v", err)
|
||||
}
|
||||
if len(volumes) != 1 || volumes[0].Name != "app-data" || volumes[0].SizeBytes != 2048 || volumes[0].RefCount != 4 {
|
||||
t.Fatalf("unexpected volumes: %+v", volumes)
|
||||
}
|
||||
|
||||
networks, err := agent.collectNetworks(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("collectNetworks: %v", err)
|
||||
}
|
||||
if len(networks) != 1 || networks[0].Name != "app-net" || !networks[0].EnableIPv4 || !networks[0].Attachable {
|
||||
t.Fatalf("unexpected networks: %+v", networks)
|
||||
}
|
||||
if len(networks[0].Subnets) != 1 || networks[0].Subnets[0].Subnet != "10.88.0.0/24" || networks[0].Subnets[0].Gateway != "10.88.0.1" {
|
||||
t.Fatalf("unexpected network subnets: %+v", networks[0].Subnets)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectContainer(t *testing.T) {
|
||||
logger := zerolog.Nop()
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,11 @@ import (
|
|||
"time"
|
||||
|
||||
containertypes "github.com/moby/moby/api/types/container"
|
||||
"github.com/moby/moby/api/types/image"
|
||||
networktypes "github.com/moby/moby/api/types/network"
|
||||
systemtypes "github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/api/types/volume"
|
||||
"github.com/moby/moby/client"
|
||||
agentsdocker "github.com/rcourtman/pulse-go-rewrite/pkg/agents/docker"
|
||||
)
|
||||
|
||||
|
|
@ -116,6 +120,22 @@ func (a *Agent) buildReport(ctx context.Context) (agentsdocker.Report, error) {
|
|||
}
|
||||
|
||||
services, tasks, swarmInfo := a.collectSwarmData(ctx, info, containers)
|
||||
diskUsageResult, storageUsage, err := a.collectStorageUsage(ctx)
|
||||
if err != nil {
|
||||
a.logger.Warn().Err(err).Msg("failed to collect Docker storage usage")
|
||||
}
|
||||
images, err := a.collectImages(ctx)
|
||||
if err != nil {
|
||||
a.logger.Warn().Err(err).Msg("failed to collect Docker images")
|
||||
}
|
||||
volumes, err := a.collectVolumes(ctx, diskUsageResult.Volumes.Items)
|
||||
if err != nil {
|
||||
a.logger.Warn().Err(err).Msg("failed to collect Docker volumes")
|
||||
}
|
||||
networks, err := a.collectNetworks(ctx)
|
||||
if err != nil {
|
||||
a.logger.Warn().Err(err).Msg("failed to collect Docker networks")
|
||||
}
|
||||
|
||||
// Use Docker's MemTotal, but fall back to gopsutil's reading if Docker returns 0.
|
||||
// This can happen in Docker-in-LXC setups where Docker daemon can't read host memory.
|
||||
|
|
@ -161,12 +181,24 @@ func (a *Agent) buildReport(ctx context.Context) (agentsdocker.Report, error) {
|
|||
if a.cfg.IncludeContainers {
|
||||
report.Containers = containers
|
||||
}
|
||||
if len(images) > 0 {
|
||||
report.Images = images
|
||||
}
|
||||
if len(volumes) > 0 {
|
||||
report.Volumes = volumes
|
||||
}
|
||||
if len(networks) > 0 {
|
||||
report.Networks = networks
|
||||
}
|
||||
if a.cfg.IncludeServices && len(services) > 0 {
|
||||
report.Services = services
|
||||
}
|
||||
if a.cfg.IncludeTasks && len(tasks) > 0 {
|
||||
report.Tasks = tasks
|
||||
}
|
||||
if storageUsage != nil {
|
||||
report.StorageUsage = storageUsage
|
||||
}
|
||||
|
||||
if report.Agent.IntervalSeconds <= 0 {
|
||||
report.Agent.IntervalSeconds = int(30 * time.Second / time.Second)
|
||||
|
|
@ -209,6 +241,17 @@ func normalizedNonEmptyStrings(values []string) []string {
|
|||
return normalized
|
||||
}
|
||||
|
||||
func cloneStringMap(src map[string]string) map[string]string {
|
||||
if len(src) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make(map[string]string, len(src))
|
||||
for k, v := range src {
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (a *Agent) collectContainers(ctx context.Context) ([]agentsdocker.Container, error) {
|
||||
options := dockerContainerListOptions{All: true}
|
||||
if len(a.stateFilters) > 0 {
|
||||
|
|
@ -253,6 +296,167 @@ func (a *Agent) collectContainers(ctx context.Context) ([]agentsdocker.Container
|
|||
return containers, nil
|
||||
}
|
||||
|
||||
func (a *Agent) collectImages(ctx context.Context) ([]agentsdocker.Image, error) {
|
||||
list, err := dockerCallWithRetry(ctx, dockerInventoryCallTimeout, func(callCtx context.Context) ([]image.Summary, error) {
|
||||
return a.docker.ImageList(callCtx, dockerImageListOptions{All: true, SharedSize: true})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, annotateDockerConnectionError(err)
|
||||
}
|
||||
|
||||
images := make([]agentsdocker.Image, 0, len(list))
|
||||
for _, summary := range list {
|
||||
images = append(images, agentsdocker.Image{
|
||||
ID: strings.TrimSpace(summary.ID),
|
||||
RepoTags: normalizedNonEmptyStrings(summary.RepoTags),
|
||||
RepoDigests: normalizedNonEmptyStrings(summary.RepoDigests),
|
||||
SizeBytes: summary.Size,
|
||||
SharedSizeBytes: summary.SharedSize,
|
||||
Containers: summary.Containers,
|
||||
CreatedAt: dockerUnixTimestamp(summary.Created),
|
||||
Labels: cloneStringMap(summary.Labels),
|
||||
})
|
||||
}
|
||||
return images, nil
|
||||
}
|
||||
|
||||
func (a *Agent) collectVolumes(ctx context.Context, usageVolumes []volume.Volume) ([]agentsdocker.Volume, error) {
|
||||
usageByName := make(map[string]volume.UsageData, len(usageVolumes))
|
||||
for _, volume := range usageVolumes {
|
||||
name := strings.TrimSpace(volume.Name)
|
||||
if name == "" || volume.UsageData == nil {
|
||||
continue
|
||||
}
|
||||
usageByName[name] = *volume.UsageData
|
||||
}
|
||||
|
||||
list, err := dockerCallWithRetry(ctx, dockerInventoryCallTimeout, func(callCtx context.Context) ([]volume.Volume, error) {
|
||||
return a.docker.VolumeList(callCtx, dockerVolumeListOptions{})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, annotateDockerConnectionError(err)
|
||||
}
|
||||
|
||||
volumes := make([]agentsdocker.Volume, 0, len(list))
|
||||
for _, v := range list {
|
||||
sizeBytes := int64(0)
|
||||
refCount := int64(0)
|
||||
if v.UsageData != nil {
|
||||
sizeBytes = v.UsageData.Size
|
||||
refCount = v.UsageData.RefCount
|
||||
} else if usage, ok := usageByName[strings.TrimSpace(v.Name)]; ok {
|
||||
sizeBytes = usage.Size
|
||||
refCount = usage.RefCount
|
||||
}
|
||||
volumes = append(volumes, agentsdocker.Volume{
|
||||
Name: strings.TrimSpace(v.Name),
|
||||
Driver: strings.TrimSpace(v.Driver),
|
||||
Mountpoint: strings.TrimSpace(v.Mountpoint),
|
||||
Scope: strings.TrimSpace(v.Scope),
|
||||
CreatedAt: strings.TrimSpace(v.CreatedAt),
|
||||
SizeBytes: sizeBytes,
|
||||
RefCount: refCount,
|
||||
Labels: cloneStringMap(v.Labels),
|
||||
Options: cloneStringMap(v.Options),
|
||||
})
|
||||
}
|
||||
return volumes, nil
|
||||
}
|
||||
|
||||
func (a *Agent) collectNetworks(ctx context.Context) ([]agentsdocker.Network, error) {
|
||||
list, err := dockerCallWithRetry(ctx, dockerInventoryCallTimeout, func(callCtx context.Context) ([]networktypes.Summary, error) {
|
||||
return a.docker.NetworkList(callCtx, dockerNetworkListOptions{})
|
||||
})
|
||||
if err != nil {
|
||||
return nil, annotateDockerConnectionError(err)
|
||||
}
|
||||
|
||||
networks := make([]agentsdocker.Network, 0, len(list))
|
||||
for _, n := range list {
|
||||
subnets := make([]agentsdocker.NetworkSubnet, 0, len(n.IPAM.Config))
|
||||
for _, config := range n.IPAM.Config {
|
||||
subnet := ""
|
||||
if config.Subnet.IsValid() {
|
||||
subnet = config.Subnet.String()
|
||||
}
|
||||
gateway := ""
|
||||
if config.Gateway.IsValid() {
|
||||
gateway = config.Gateway.String()
|
||||
}
|
||||
subnets = append(subnets, agentsdocker.NetworkSubnet{
|
||||
Subnet: subnet,
|
||||
Gateway: gateway,
|
||||
})
|
||||
}
|
||||
networks = append(networks, agentsdocker.Network{
|
||||
ID: strings.TrimSpace(n.ID),
|
||||
Name: strings.TrimSpace(n.Name),
|
||||
Driver: strings.TrimSpace(n.Driver),
|
||||
Scope: strings.TrimSpace(n.Scope),
|
||||
CreatedAt: n.Created,
|
||||
EnableIPv4: n.EnableIPv4,
|
||||
EnableIPv6: n.EnableIPv6,
|
||||
Internal: n.Internal,
|
||||
Attachable: n.Attachable,
|
||||
Ingress: n.Ingress,
|
||||
ConfigOnly: n.ConfigOnly,
|
||||
Subnets: subnets,
|
||||
Labels: cloneStringMap(n.Labels),
|
||||
Options: cloneStringMap(n.Options),
|
||||
})
|
||||
}
|
||||
return networks, nil
|
||||
}
|
||||
|
||||
func (a *Agent) collectStorageUsage(ctx context.Context) (client.DiskUsageResult, *agentsdocker.StorageUsage, error) {
|
||||
result, err := dockerCallWithRetry(ctx, dockerInventoryCallTimeout, func(callCtx context.Context) (client.DiskUsageResult, error) {
|
||||
return a.docker.DiskUsage(callCtx, dockerDiskUsageOptions{
|
||||
Containers: true,
|
||||
Images: true,
|
||||
Volumes: true,
|
||||
BuildCache: true,
|
||||
Verbose: true,
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
return client.DiskUsageResult{}, nil, annotateDockerConnectionError(err)
|
||||
}
|
||||
|
||||
return result, &agentsdocker.StorageUsage{
|
||||
Images: agentsdocker.StorageUsageBucket{
|
||||
TotalCount: result.Images.TotalCount,
|
||||
ActiveCount: result.Images.ActiveCount,
|
||||
TotalSizeBytes: result.Images.TotalSize,
|
||||
ReclaimableBytes: result.Images.Reclaimable,
|
||||
},
|
||||
Containers: agentsdocker.StorageUsageBucket{
|
||||
TotalCount: result.Containers.TotalCount,
|
||||
ActiveCount: result.Containers.ActiveCount,
|
||||
TotalSizeBytes: result.Containers.TotalSize,
|
||||
ReclaimableBytes: result.Containers.Reclaimable,
|
||||
},
|
||||
Volumes: agentsdocker.StorageUsageBucket{
|
||||
TotalCount: result.Volumes.TotalCount,
|
||||
ActiveCount: result.Volumes.ActiveCount,
|
||||
TotalSizeBytes: result.Volumes.TotalSize,
|
||||
ReclaimableBytes: result.Volumes.Reclaimable,
|
||||
},
|
||||
BuildCache: agentsdocker.StorageUsageBucket{
|
||||
TotalCount: result.BuildCache.TotalCount,
|
||||
ActiveCount: result.BuildCache.ActiveCount,
|
||||
TotalSizeBytes: result.BuildCache.TotalSize,
|
||||
ReclaimableBytes: result.BuildCache.Reclaimable,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func dockerUnixTimestamp(seconds int64) time.Time {
|
||||
if seconds <= 0 {
|
||||
return time.Time{}
|
||||
}
|
||||
return time.Unix(seconds, 0).UTC()
|
||||
}
|
||||
|
||||
func (a *Agent) pruneStaleCPUSamples(active map[string]struct{}) {
|
||||
a.cpuMu.Lock()
|
||||
defer a.cpuMu.Unlock()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/moby/moby/api/types/network"
|
||||
swarmtypes "github.com/moby/moby/api/types/swarm"
|
||||
systemtypes "github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/api/types/volume"
|
||||
"github.com/moby/moby/client"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
|
@ -91,6 +92,28 @@ type dockerServiceListOptions struct {
|
|||
Status bool
|
||||
}
|
||||
|
||||
type dockerImageListOptions struct {
|
||||
All bool
|
||||
SharedSize bool
|
||||
Filters dockerFilters
|
||||
}
|
||||
|
||||
type dockerVolumeListOptions struct {
|
||||
Filters dockerFilters
|
||||
}
|
||||
|
||||
type dockerNetworkListOptions struct {
|
||||
Filters dockerFilters
|
||||
}
|
||||
|
||||
type dockerDiskUsageOptions struct {
|
||||
Containers bool
|
||||
Images bool
|
||||
BuildCache bool
|
||||
Volumes bool
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
type dockerTaskListOptions struct {
|
||||
Filters dockerFilters
|
||||
}
|
||||
|
|
@ -109,6 +132,10 @@ type dockerClient interface {
|
|||
NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error
|
||||
ContainerStart(ctx context.Context, containerID string, options dockerContainerStartOptions) error
|
||||
ContainerRemove(ctx context.Context, containerID string, options dockerContainerRemoveOptions) error
|
||||
ImageList(ctx context.Context, options dockerImageListOptions) ([]image.Summary, error)
|
||||
VolumeList(ctx context.Context, options dockerVolumeListOptions) ([]volume.Volume, error)
|
||||
NetworkList(ctx context.Context, options dockerNetworkListOptions) ([]network.Summary, error)
|
||||
DiskUsage(ctx context.Context, options dockerDiskUsageOptions) (client.DiskUsageResult, error)
|
||||
ServiceList(ctx context.Context, options dockerServiceListOptions) ([]swarmtypes.Service, error)
|
||||
TaskList(ctx context.Context, options dockerTaskListOptions) ([]swarmtypes.Task, error)
|
||||
ImageInspectWithRaw(ctx context.Context, imageID string) (image.InspectResponse, []byte, error)
|
||||
|
|
@ -229,6 +256,44 @@ func (m *mobyDockerClient) ContainerRemove(ctx context.Context, containerID stri
|
|||
return err
|
||||
}
|
||||
|
||||
func (m *mobyDockerClient) ImageList(ctx context.Context, options dockerImageListOptions) ([]image.Summary, error) {
|
||||
result, err := m.Client.ImageList(ctx, client.ImageListOptions{
|
||||
All: options.All,
|
||||
SharedSize: options.SharedSize,
|
||||
Filters: options.Filters.toClientFilters(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Items, nil
|
||||
}
|
||||
|
||||
func (m *mobyDockerClient) VolumeList(ctx context.Context, options dockerVolumeListOptions) ([]volume.Volume, error) {
|
||||
result, err := m.Client.VolumeList(ctx, client.VolumeListOptions{Filters: options.Filters.toClientFilters()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Items, nil
|
||||
}
|
||||
|
||||
func (m *mobyDockerClient) NetworkList(ctx context.Context, options dockerNetworkListOptions) ([]network.Summary, error) {
|
||||
result, err := m.Client.NetworkList(ctx, client.NetworkListOptions{Filters: options.Filters.toClientFilters()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Items, nil
|
||||
}
|
||||
|
||||
func (m *mobyDockerClient) DiskUsage(ctx context.Context, options dockerDiskUsageOptions) (client.DiskUsageResult, error) {
|
||||
return m.Client.DiskUsage(ctx, client.DiskUsageOptions{
|
||||
Containers: options.Containers,
|
||||
Images: options.Images,
|
||||
BuildCache: options.BuildCache,
|
||||
Volumes: options.Volumes,
|
||||
Verbose: options.Verbose,
|
||||
})
|
||||
}
|
||||
|
||||
func (m *mobyDockerClient) ServiceList(ctx context.Context, options dockerServiceListOptions) ([]swarmtypes.Service, error) {
|
||||
result, err := m.Client.ServiceList(ctx, client.ServiceListOptions{Status: options.Status})
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
const (
|
||||
dockerInfoCallTimeout = 8 * time.Second
|
||||
dockerContainerListCallTimeout = 20 * time.Second
|
||||
dockerInventoryCallTimeout = 20 * time.Second
|
||||
dockerSwarmListCallTimeout = 20 * time.Second
|
||||
dockerCleanupCallTimeout = 15 * time.Second
|
||||
dockerUpdateCallTimeout = 2 * time.Minute
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import (
|
|||
"github.com/moby/moby/api/types/network"
|
||||
swarmtypes "github.com/moby/moby/api/types/swarm"
|
||||
systemtypes "github.com/moby/moby/api/types/system"
|
||||
"github.com/moby/moby/api/types/volume"
|
||||
"github.com/moby/moby/client"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
|
|
@ -30,6 +32,10 @@ type fakeDockerClient struct {
|
|||
networkConnectFn func(ctx context.Context, netName, containerID string, endpoint *network.EndpointSettings) error
|
||||
containerStartFn func(ctx context.Context, id string, opts dockerContainerStartOptions) error
|
||||
containerRemoveFn func(ctx context.Context, id string, opts dockerContainerRemoveOptions) error
|
||||
imageListFn func(ctx context.Context, opts dockerImageListOptions) ([]image.Summary, error)
|
||||
volumeListFn func(ctx context.Context, opts dockerVolumeListOptions) ([]volume.Volume, error)
|
||||
networkListFn func(ctx context.Context, opts dockerNetworkListOptions) ([]network.Summary, error)
|
||||
diskUsageFn func(ctx context.Context, opts dockerDiskUsageOptions) (client.DiskUsageResult, error)
|
||||
serviceListFn func(ctx context.Context, opts dockerServiceListOptions) ([]swarmtypes.Service, error)
|
||||
taskListFn func(ctx context.Context, opts dockerTaskListOptions) ([]swarmtypes.Task, error)
|
||||
imageInspectWithRawFn func(ctx context.Context, imageID string) (image.InspectResponse, []byte, error)
|
||||
|
|
@ -124,6 +130,34 @@ func (f *fakeDockerClient) ContainerRemove(ctx context.Context, id string, opts
|
|||
return f.containerRemoveFn(ctx, id, opts)
|
||||
}
|
||||
|
||||
func (f *fakeDockerClient) ImageList(ctx context.Context, opts dockerImageListOptions) ([]image.Summary, error) {
|
||||
if f.imageListFn == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return f.imageListFn(ctx, opts)
|
||||
}
|
||||
|
||||
func (f *fakeDockerClient) VolumeList(ctx context.Context, opts dockerVolumeListOptions) ([]volume.Volume, error) {
|
||||
if f.volumeListFn == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return f.volumeListFn(ctx, opts)
|
||||
}
|
||||
|
||||
func (f *fakeDockerClient) NetworkList(ctx context.Context, opts dockerNetworkListOptions) ([]network.Summary, error) {
|
||||
if f.networkListFn == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return f.networkListFn(ctx, opts)
|
||||
}
|
||||
|
||||
func (f *fakeDockerClient) DiskUsage(ctx context.Context, opts dockerDiskUsageOptions) (client.DiskUsageResult, error) {
|
||||
if f.diskUsageFn == nil {
|
||||
return client.DiskUsageResult{}, nil
|
||||
}
|
||||
return f.diskUsageFn(ctx, opts)
|
||||
}
|
||||
|
||||
func (f *fakeDockerClient) ServiceList(ctx context.Context, opts dockerServiceListOptions) ([]swarmtypes.Service, error) {
|
||||
if f.serviceListFn == nil {
|
||||
return nil, errors.New("unexpected ServiceList call")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue