Merge pull request #55188 from mindprince/accelerator-monitoring

Automatic merge from submit-queue (batch tested with PRs 55798, 49579, 54862, 55188, 51990). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Add monitoring support for hardware accelerators

Currently only NVIDIA GPU monitoring is implemented.

Feature repo issue: https://github.com/kubernetes/features/issues/369
cAdvisor PR: https://github.com/google/cadvisor/pull/1762

/kind feature
/sig node
/sig instrumentation
/area hw-accelerators

**Release note**:
```release-note
Kubelet now exposes metrics for NVIDIA GPUs attached to the containers.
```
pull/6/head
Kubernetes Submit Queue 2017-11-16 03:09:21 -08:00 committed by GitHub
commit 779105673a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
301 changed files with 10090 additions and 9000 deletions

242
Godeps/Godeps.json generated
View File

@ -993,71 +993,6 @@
"Comment": "docs-v1.12.0-rc4-2016-07-15-7401-g4f3616fb1",
"Rev": "4f3616fb1c112e206b88cb7a9922bf49067a7756"
},
{
"ImportPath": "github.com/docker/engine-api/client",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/client/transport",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/client/transport/cancellable",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/blkiodev",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/container",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/filters",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/network",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/reference",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/registry",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/strslice",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/time",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/engine-api/types/versions",
"Comment": "v0.3.1-78-gdea108d",
"Rev": "dea108d3aa0c67d7162a3fd8aa65f38a430019fd"
},
{
"ImportPath": "github.com/docker/go-connections/nat",
"Comment": "v0.3.0",
@ -1374,210 +1309,215 @@
"ImportPath": "github.com/google/btree",
"Rev": "7d79101e329e5a3adf994758c578dab82b90c017"
},
{
"ImportPath": "github.com/google/cadvisor/accelerators",
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/api",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/cache/memory",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/client/v2",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/collector",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container/common",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container/crio",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container/docker",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container/libcontainer",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container/raw",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container/rkt",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/container/systemd",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/devicemapper",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/events",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/fs",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/healthz",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/http",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/http/mux",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/info/v1",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/info/v2",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/machine",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/manager",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/manager/watcher",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/manager/watcher/raw",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/manager/watcher/rkt",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/metrics",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/pages",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/pages/static",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/storage",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/summary",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils/cloudinfo",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils/cpuload",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils/cpuload/netlink",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils/docker",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils/oomparser",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils/sysfs",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/utils/sysinfo",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/validate",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/version",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/cadvisor/zfs",
"Comment": "v0.27.2",
"Rev": "4957b7a942b01fe044a9ca8ba2dc9f5ca997431c"
"Comment": "v0.28.0",
"Rev": "3d2e7fcfa396ab4f193c7720b6a6dc3133b6f50a"
},
{
"ImportPath": "github.com/google/certificate-transparency/go",
@ -1973,6 +1913,10 @@
"ImportPath": "github.com/miekg/dns",
"Rev": "5d001d020961ae1c184f9f8152fdc73810481677"
},
{
"ImportPath": "github.com/mindprince/gonvml",
"Rev": "fee913ce8fb235edf54739d259ca0ecc226c7b8a"
},
{
"ImportPath": "github.com/mistifyio/go-zfs",
"Comment": "v2.1.1-5-g1b4ae6f",
@ -2763,11 +2707,11 @@
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/sys/windows",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/text/cases",

2995
Godeps/LICENSES generated

File diff suppressed because it is too large Load Diff

View File

@ -109,6 +109,8 @@ type ContainerStats struct {
// Stats pertaining to memory (RAM) resources.
// +optional
Memory *MemoryStats `json:"memory,omitempty"`
// Metrics for Accelerators. Each Accelerator corresponds to one element in the array.
Accelerators []AcceleratorStats `json:"accelerators,omitempty"`
// Stats pertaining to container rootfs usage of filesystem resources.
// Rootfs.UsedBytes is the number of bytes used for the container write layer.
// +optional
@ -188,6 +190,30 @@ type MemoryStats struct {
MajorPageFaults *uint64 `json:"majorPageFaults,omitempty"`
}
// AcceleratorStats contains stats for accelerators attached to the container.
type AcceleratorStats struct {
// Make of the accelerator (nvidia, amd, google etc.)
Make string `json:"make"`
// Model of the accelerator (tesla-p100, tesla-k80 etc.)
Model string `json:"model"`
// ID of the accelerator.
ID string `json:"id"`
// Total accelerator memory.
// unit: bytes
MemoryTotal uint64 `json:"memory_total"`
// Total accelerator memory allocated.
// unit: bytes
MemoryUsed uint64 `json:"memory_used"`
// Percent of time over the past sample period (10s) during which
// the accelerator was actively processing.
DutyCycle uint64 `json:"duty_cycle"`
}
// VolumeStats contains data about Volume filesystem usage.
type VolumeStats struct {
// Embedded FsStats

View File

@ -46,7 +46,7 @@ func TestSummaryProvider(t *testing.T) {
node = &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "test-node"}}
nodeConfig = cm.NodeConfig{
RuntimeCgroupsName: "/runtime",
SystemCgroupsName: "/system",
SystemCgroupsName: "/misc",
KubeletCgroupsName: "/kubelet",
}
cgroupStatsMap = map[string]struct {
@ -55,7 +55,7 @@ func TestSummaryProvider(t *testing.T) {
}{
"/": {cs: getContainerStats(), ns: getNetworkStats()},
"/runtime": {cs: getContainerStats(), ns: getNetworkStats()},
"/system": {cs: getContainerStats(), ns: getNetworkStats()},
"/misc": {cs: getContainerStats(), ns: getNetworkStats()},
"/kubelet": {cs: getContainerStats(), ns: getNetworkStats()},
}
)
@ -71,7 +71,7 @@ func TestSummaryProvider(t *testing.T) {
On("RootFsStats").Return(rootFsStats, nil).
On("GetCgroupStats", "/").Return(cgroupStatsMap["/"].cs, cgroupStatsMap["/"].ns, nil).
On("GetCgroupStats", "/runtime").Return(cgroupStatsMap["/runtime"].cs, cgroupStatsMap["/runtime"].ns, nil).
On("GetCgroupStats", "/system").Return(cgroupStatsMap["/system"].cs, cgroupStatsMap["/system"].ns, nil).
On("GetCgroupStats", "/misc").Return(cgroupStatsMap["/misc"].cs, cgroupStatsMap["/misc"].ns, nil).
On("GetCgroupStats", "/kubelet").Return(cgroupStatsMap["/kubelet"].cs, cgroupStatsMap["/kubelet"].ns, nil)
provider := NewSummaryProvider(mockStatsProvider)
@ -87,29 +87,30 @@ func TestSummaryProvider(t *testing.T) {
assert.Equal(summary.Node.Runtime, &statsapi.RuntimeStats{ImageFs: imageFsStats})
assert.Equal(len(summary.Node.SystemContainers), 3)
assert.Contains(summary.Node.SystemContainers,
statsapi.ContainerStats{
Name: "kubelet",
StartTime: cgroupStatsMap["/kubelet"].cs.StartTime,
CPU: cgroupStatsMap["/kubelet"].cs.CPU,
Memory: cgroupStatsMap["/kubelet"].cs.Memory,
UserDefinedMetrics: cgroupStatsMap["/kubelet"].cs.UserDefinedMetrics,
},
statsapi.ContainerStats{
Name: "system",
StartTime: cgroupStatsMap["/system"].cs.StartTime,
CPU: cgroupStatsMap["/system"].cs.CPU,
Memory: cgroupStatsMap["/system"].cs.Memory,
UserDefinedMetrics: cgroupStatsMap["/system"].cs.UserDefinedMetrics,
},
statsapi.ContainerStats{
Name: "runtime",
StartTime: cgroupStatsMap["/runtime"].cs.StartTime,
CPU: cgroupStatsMap["/runtime"].cs.CPU,
Memory: cgroupStatsMap["/runtime"].cs.Memory,
UserDefinedMetrics: cgroupStatsMap["/runtime"].cs.UserDefinedMetrics,
},
)
assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
Name: "kubelet",
StartTime: cgroupStatsMap["/kubelet"].cs.StartTime,
CPU: cgroupStatsMap["/kubelet"].cs.CPU,
Memory: cgroupStatsMap["/kubelet"].cs.Memory,
Accelerators: cgroupStatsMap["/kubelet"].cs.Accelerators,
UserDefinedMetrics: cgroupStatsMap["/kubelet"].cs.UserDefinedMetrics,
})
assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
Name: "misc",
StartTime: cgroupStatsMap["/misc"].cs.StartTime,
CPU: cgroupStatsMap["/misc"].cs.CPU,
Memory: cgroupStatsMap["/misc"].cs.Memory,
Accelerators: cgroupStatsMap["/misc"].cs.Accelerators,
UserDefinedMetrics: cgroupStatsMap["/misc"].cs.UserDefinedMetrics,
})
assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{
Name: "runtime",
StartTime: cgroupStatsMap["/runtime"].cs.StartTime,
CPU: cgroupStatsMap["/runtime"].cs.CPU,
Memory: cgroupStatsMap["/runtime"].cs.Memory,
Accelerators: cgroupStatsMap["/runtime"].cs.Accelerators,
UserDefinedMetrics: cgroupStatsMap["/runtime"].cs.UserDefinedMetrics,
})
assert.Equal(summary.Pods, podStats)
}

View File

@ -119,6 +119,17 @@ func cadvisorInfoToContainerStats(name string, info *cadvisorapiv2.ContainerInfo
}
}
for _, acc := range cstat.Accelerators {
result.Accelerators = append(result.Accelerators, statsapi.AcceleratorStats{
Make: acc.Make,
Model: acc.Model,
ID: acc.ID,
MemoryTotal: acc.MemoryTotal,
MemoryUsed: acc.MemoryUsed,
DutyCycle: acc.DutyCycle,
})
}
result.UserDefinedMetrics = cadvisorInfoToUserDefinedMetrics(info)
return result

View File

@ -396,11 +396,11 @@
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/sys/windows",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/text/cases",

View File

@ -640,11 +640,11 @@
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/sys/windows",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/text/cases",

View File

@ -312,11 +312,11 @@
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/sys/windows",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/text/cases",

View File

@ -372,11 +372,11 @@
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/sys/windows",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/text/cases",

View File

@ -356,11 +356,11 @@
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/sys/windows",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/text/cases",

View File

@ -180,11 +180,11 @@
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/sys/windows",
"Rev": "7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce"
"Rev": "95c6576299259db960f6c5b9b69ea52422860fce"
},
{
"ImportPath": "golang.org/x/text/cases",

View File

@ -97,6 +97,7 @@ var _ = framework.KubeDescribe("Summary API", func() {
"PageFaults": bounded(1000, 1E9),
"MajorPageFaults": bounded(0, 100000),
}),
"Accelerators": BeEmpty(),
"Rootfs": BeNil(),
"Logs": BeNil(),
"UserDefinedMetrics": BeEmpty(),
@ -145,6 +146,7 @@ var _ = framework.KubeDescribe("Summary API", func() {
"PageFaults": bounded(100, 1000000),
"MajorPageFaults": bounded(0, 10),
}),
"Accelerators": BeEmpty(),
"Rootfs": ptrMatchAllFields(gstruct.Fields{
"Time": recent(maxStatsAge),
"AvailableBytes": fsCapacityBounds,

4
vendor/BUILD vendored
View File

@ -138,8 +138,6 @@ filegroup(
"//vendor/github.com/docker/docker/pkg/system:all-srcs",
"//vendor/github.com/docker/docker/pkg/term:all-srcs",
"//vendor/github.com/docker/docker/pkg/tlsconfig:all-srcs",
"//vendor/github.com/docker/engine-api/client:all-srcs",
"//vendor/github.com/docker/engine-api/types:all-srcs",
"//vendor/github.com/docker/go-connections/nat:all-srcs",
"//vendor/github.com/docker/go-connections/sockets:all-srcs",
"//vendor/github.com/docker/go-connections/tlsconfig:all-srcs",
@ -202,6 +200,7 @@ filegroup(
"//vendor/github.com/golang/protobuf/proto:all-srcs",
"//vendor/github.com/golang/protobuf/ptypes:all-srcs",
"//vendor/github.com/google/btree:all-srcs",
"//vendor/github.com/google/cadvisor/accelerators:all-srcs",
"//vendor/github.com/google/cadvisor/api:all-srcs",
"//vendor/github.com/google/cadvisor/cache/memory:all-srcs",
"//vendor/github.com/google/cadvisor/client/v2:all-srcs",
@ -272,6 +271,7 @@ filegroup(
"//vendor/github.com/mailru/easyjson/jwriter:all-srcs",
"//vendor/github.com/matttproud/golang_protobuf_extensions/pbutil:all-srcs",
"//vendor/github.com/miekg/dns:all-srcs",
"//vendor/github.com/mindprince/gonvml:all-srcs",
"//vendor/github.com/mistifyio/go-zfs:all-srcs",
"//vendor/github.com/mitchellh/go-wordwrap:all-srcs",
"//vendor/github.com/mitchellh/mapstructure:all-srcs",

View File

@ -1,107 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"client.go",
"container_attach.go",
"container_commit.go",
"container_copy.go",
"container_create.go",
"container_diff.go",
"container_exec.go",
"container_export.go",
"container_inspect.go",
"container_kill.go",
"container_list.go",
"container_logs.go",
"container_pause.go",
"container_remove.go",
"container_rename.go",
"container_resize.go",
"container_restart.go",
"container_start.go",
"container_stats.go",
"container_stop.go",
"container_top.go",
"container_unpause.go",
"container_update.go",
"container_wait.go",
"errors.go",
"events.go",
"hijack.go",
"image_build.go",
"image_create.go",
"image_history.go",
"image_import.go",
"image_inspect.go",
"image_list.go",
"image_load.go",
"image_pull.go",
"image_push.go",
"image_remove.go",
"image_save.go",
"image_search.go",
"image_tag.go",
"info.go",
"interface.go",
"login.go",
"network_connect.go",
"network_create.go",
"network_disconnect.go",
"network_inspect.go",
"network_list.go",
"network_remove.go",
"request.go",
"version.go",
"volume_create.go",
"volume_inspect.go",
"volume_list.go",
"volume_remove.go",
] + select({
"@io_bazel_rules_go//go/platform:darwin_amd64": [
"client_darwin.go",
],
"@io_bazel_rules_go//go/platform:linux_amd64": [
"client_unix.go",
],
"@io_bazel_rules_go//go/platform:windows_amd64": [
"client_windows.go",
],
"//conditions:default": [],
}),
importpath = "github.com/docker/engine-api/client",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/docker/distribution/reference:go_default_library",
"//vendor/github.com/docker/engine-api/client/transport:go_default_library",
"//vendor/github.com/docker/engine-api/client/transport/cancellable:go_default_library",
"//vendor/github.com/docker/engine-api/types:go_default_library",
"//vendor/github.com/docker/engine-api/types/container:go_default_library",
"//vendor/github.com/docker/engine-api/types/filters:go_default_library",
"//vendor/github.com/docker/engine-api/types/network:go_default_library",
"//vendor/github.com/docker/engine-api/types/reference:go_default_library",
"//vendor/github.com/docker/engine-api/types/registry:go_default_library",
"//vendor/github.com/docker/engine-api/types/time:go_default_library",
"//vendor/github.com/docker/go-connections/sockets:go_default_library",
"//vendor/github.com/docker/go-connections/tlsconfig:go_default_library",
"//vendor/golang.org/x/net/context:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/docker/engine-api/client/transport:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,141 +0,0 @@
package client
import (
"fmt"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/docker/engine-api/client/transport"
"github.com/docker/go-connections/tlsconfig"
)
// Client is the API client that performs all operations
// against a docker server.
type Client struct {
// proto holds the client protocol i.e. unix.
proto string
// addr holds the client address.
addr string
// basePath holds the path to prepend to the requests.
basePath string
// transport is the interface to send request with, it implements transport.Client.
transport transport.Client
// version of the server to talk to.
version string
// custom http headers configured by users.
customHTTPHeaders map[string]string
}
// NewEnvClient initializes a new API client based on environment variables.
// Use DOCKER_HOST to set the url to the docker server.
// Use DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
// Use DOCKER_CERT_PATH to load the tls certificates from.
// Use DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func NewEnvClient() (*Client, error) {
var client *http.Client
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
options := tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
}
tlsc, err := tlsconfig.Client(options)
if err != nil {
return nil, err
}
client = &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsc,
},
}
}
host := os.Getenv("DOCKER_HOST")
if host == "" {
host = DefaultDockerHost
}
return NewClient(host, os.Getenv("DOCKER_API_VERSION"), client, nil)
}
// NewClient initializes a new API client for the given host and API version.
// It won't send any version information if the version number is empty.
// It uses the given http client as transport.
// It also initializes the custom http headers to add to each request.
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
proto, addr, basePath, err := ParseHost(host)
if err != nil {
return nil, err
}
transport, err := transport.NewTransportWithHTTP(proto, addr, client)
if err != nil {
return nil, err
}
return &Client{
proto: proto,
addr: addr,
basePath: basePath,
transport: transport,
version: version,
customHTTPHeaders: httpHeaders,
}, nil
}
// getAPIPath returns the versioned request path to call the api.
// It appends the query parameters to the path if they are not empty.
func (cli *Client) getAPIPath(p string, query url.Values) string {
var apiPath string
if cli.version != "" {
v := strings.TrimPrefix(cli.version, "v")
apiPath = fmt.Sprintf("%s/v%s%s", cli.basePath, v, p)
} else {
apiPath = fmt.Sprintf("%s%s", cli.basePath, p)
}
u := &url.URL{
Path: apiPath,
}
if len(query) > 0 {
u.RawQuery = query.Encode()
}
return u.String()
}
// ClientVersion returns the version string associated with this
// instance of the Client. Note that this value can be changed
// via the DOCKER_API_VERSION env var.
func (cli *Client) ClientVersion() string {
return cli.version
}
// UpdateClientVersion updates the version string associated with this
// instance of the Client.
func (cli *Client) UpdateClientVersion(v string) {
cli.version = v
}
// ParseHost verifies that the given host strings is valid.
func ParseHost(host string) (string, string, string, error) {
protoAddrParts := strings.SplitN(host, "://", 2)
if len(protoAddrParts) == 1 {
return "", "", "", fmt.Errorf("unable to parse docker host `%s`", host)
}
var basePath string
proto, addr := protoAddrParts[0], protoAddrParts[1]
if proto == "tcp" {
parsed, err := url.Parse("tcp://" + addr)
if err != nil {
return "", "", "", err
}
addr = parsed.Host
basePath = parsed.Path
}
return proto, addr, basePath, nil
}

View File

@ -1,4 +0,0 @@
package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "tcp://127.0.0.1:2375"

View File

@ -1,6 +0,0 @@
// +build linux freebsd solaris openbsd
package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "unix:///var/run/docker.sock"

View File

@ -1,4 +0,0 @@
package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "npipe:////./pipe/docker_engine"

View File

@ -1,34 +0,0 @@
package client
import (
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ContainerAttach attaches a connection to a container in the server.
// It returns a types.HijackedConnection with the hijacked connection
// and the a reader to get output. It's up to the called to close
// the hijacked connection by calling types.HijackedResponse.Close.
func (cli *Client) ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) {
query := url.Values{}
if options.Stream {
query.Set("stream", "1")
}
if options.Stdin {
query.Set("stdin", "1")
}
if options.Stdout {
query.Set("stdout", "1")
}
if options.Stderr {
query.Set("stderr", "1")
}
if options.DetachKeys != "" {
query.Set("detachKeys", options.DetachKeys)
}
headers := map[string][]string{"Content-Type": {"text/plain"}}
return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, headers)
}

View File

@ -1,53 +0,0 @@
package client
import (
"encoding/json"
"errors"
"net/url"
distreference "github.com/docker/distribution/reference"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/reference"
"golang.org/x/net/context"
)
// ContainerCommit applies changes into a container and creates a new tagged image.
func (cli *Client) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error) {
var repository, tag string
if options.Reference != "" {
distributionRef, err := distreference.ParseNamed(options.Reference)
if err != nil {
return types.ContainerCommitResponse{}, err
}
if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
return types.ContainerCommitResponse{}, errors.New("refusing to create a tag with a digest reference")
}
tag = reference.GetTagFromNamedRef(distributionRef)
repository = distributionRef.Name()
}
query := url.Values{}
query.Set("container", container)
query.Set("repo", repository)
query.Set("tag", tag)
query.Set("comment", options.Comment)
query.Set("author", options.Author)
for _, change := range options.Changes {
query.Add("changes", change)
}
if options.Pause != true {
query.Set("pause", "0")
}
var response types.ContainerCommitResponse
resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
if err != nil {
return response, err
}
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View File

@ -1,97 +0,0 @@
package client
import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"path/filepath"
"strings"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
)
// ContainerStatPath returns Stat information about a path inside the container filesystem.
func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (types.ContainerPathStat, error) {
query := url.Values{}
query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API.
urlStr := fmt.Sprintf("/containers/%s/archive", containerID)
response, err := cli.head(ctx, urlStr, query, nil)
if err != nil {
return types.ContainerPathStat{}, err
}
defer ensureReaderClosed(response)
return getContainerPathStatFromHeader(response.header)
}
// CopyToContainer copies content into the container filesystem.
func (cli *Client) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error {
query := url.Values{}
query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API.
// Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
if !options.AllowOverwriteDirWithFile {
query.Set("noOverwriteDirNonDir", "true")
}
apiPath := fmt.Sprintf("/containers/%s/archive", container)
response, err := cli.putRaw(ctx, apiPath, query, content, nil)
if err != nil {
return err
}
defer ensureReaderClosed(response)
if response.statusCode != http.StatusOK {
return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
}
return nil
}
// CopyFromContainer gets the content from the container and returns it as a Reader
// to manipulate it in the host. It's up to the caller to close the reader.
func (cli *Client) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
query := make(url.Values, 1)
query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API.
apiPath := fmt.Sprintf("/containers/%s/archive", container)
response, err := cli.get(ctx, apiPath, query, nil)
if err != nil {
return nil, types.ContainerPathStat{}, err
}
if response.statusCode != http.StatusOK {
return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
}
// In order to get the copy behavior right, we need to know information
// about both the source and the destination. The response headers include
// stat info about the source that we can use in deciding exactly how to
// copy it locally. Along with the stat info about the local destination,
// we have everything we need to handle the multiple possibilities there
// can be when copying a file/dir from one location to another file/dir.
stat, err := getContainerPathStatFromHeader(response.header)
if err != nil {
return nil, stat, fmt.Errorf("unable to get resource stat from response: %s", err)
}
return response.body, stat, err
}
func getContainerPathStatFromHeader(header http.Header) (types.ContainerPathStat, error) {
var stat types.ContainerPathStat
encodedStat := header.Get("X-Docker-Container-Path-Stat")
statDecoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(encodedStat))
err := json.NewDecoder(statDecoder).Decode(&stat)
if err != nil {
err = fmt.Errorf("unable to decode container path stat header: %s", err)
}
return stat, err
}

View File

@ -1,46 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"strings"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/network"
"golang.org/x/net/context"
)
type configWrapper struct {
*container.Config
HostConfig *container.HostConfig
NetworkingConfig *network.NetworkingConfig
}
// ContainerCreate creates a new container based in the given configuration.
// It can be associated with a name, but it's not mandatory.
func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error) {
var response types.ContainerCreateResponse
query := url.Values{}
if containerName != "" {
query.Set("name", containerName)
}
body := configWrapper{
Config: config,
HostConfig: hostConfig,
NetworkingConfig: networkingConfig,
}
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
if err != nil {
if serverResp != nil && serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
return response, imageNotFoundError{config.Image}
}
return response, err
}
err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err
}

View File

@ -1,23 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ContainerDiff shows differences in a container filesystem since it was started.
func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]types.ContainerChange, error) {
var changes []types.ContainerChange
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
if err != nil {
return changes, err
}
err = json.NewDecoder(serverResp.body).Decode(&changes)
ensureReaderClosed(serverResp)
return changes, err
}

View File

@ -1,49 +0,0 @@
package client
import (
"encoding/json"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ContainerExecCreate creates a new exec configuration to run an exec process.
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error) {
var response types.ContainerExecCreateResponse
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
if err != nil {
return response, err
}
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}
// ContainerExecStart starts an exec process already created in the docker host.
func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error {
resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, config, nil)
ensureReaderClosed(resp)
return err
}
// ContainerExecAttach attaches a connection to an exec process in the server.
// It returns a types.HijackedConnection with the hijacked connection
// and the a reader to get output. It's up to the called to close
// the hijacked connection by calling types.HijackedResponse.Close.
func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error) {
headers := map[string][]string{"Content-Type": {"application/json"}}
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers)
}
// ContainerExecInspect returns information about a specific exec process on the docker host.
func (cli *Client) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) {
var response types.ContainerExecInspect
resp, err := cli.get(ctx, "/exec/"+execID+"/json", nil, nil)
if err != nil {
return response, err
}
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View File

@ -1,20 +0,0 @@
package client
import (
"io"
"net/url"
"golang.org/x/net/context"
)
// ContainerExport retrieves the raw contents of a container
// and returns them as an io.ReadCloser. It's up to the caller
// to close the stream.
func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) {
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil)
if err != nil {
return nil, err
}
return serverResp.body, nil
}

View File

@ -1,65 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ContainerInspect returns the container information.
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
if err != nil {
if serverResp.statusCode == http.StatusNotFound {
return types.ContainerJSON{}, containerNotFoundError{containerID}
}
return types.ContainerJSON{}, err
}
var response types.ContainerJSON
err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err
}
// ContainerInspectWithRaw returns the container information and it's raw representation.
func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
query := url.Values{}
if getSize {
query.Set("size", "1")
}
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
if err != nil {
if serverResp.statusCode == http.StatusNotFound {
return types.ContainerJSON{}, nil, containerNotFoundError{containerID}
}
return types.ContainerJSON{}, nil, err
}
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body)
if err != nil {
return types.ContainerJSON{}, nil, err
}
var response types.ContainerJSON
rdr := bytes.NewReader(body)
err = json.NewDecoder(rdr).Decode(&response)
return response, body, err
}
func (cli *Client) containerInspectWithResponse(ctx context.Context, containerID string, query url.Values) (types.ContainerJSON, *serverResponse, error) {
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
if err != nil {
return types.ContainerJSON{}, serverResp, err
}
var response types.ContainerJSON
err = json.NewDecoder(serverResp.body).Decode(&response)
return response, serverResp, err
}

View File

@ -1,17 +0,0 @@
package client
import (
"net/url"
"golang.org/x/net/context"
)
// ContainerKill terminates the container process but does not remove the container from the docker host.
func (cli *Client) ContainerKill(ctx context.Context, containerID, signal string) error {
query := url.Values{}
query.Set("signal", signal)
resp, err := cli.post(ctx, "/containers/"+containerID+"/kill", query, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,56 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"strconv"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"golang.org/x/net/context"
)
// ContainerList returns the list of containers in the docker host.
func (cli *Client) ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error) {
query := url.Values{}
if options.All {
query.Set("all", "1")
}
if options.Limit != -1 {
query.Set("limit", strconv.Itoa(options.Limit))
}
if options.Since != "" {
query.Set("since", options.Since)
}
if options.Before != "" {
query.Set("before", options.Before)
}
if options.Size {
query.Set("size", "1")
}
if options.Filter.Len() > 0 {
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filter)
if err != nil {
return nil, err
}
query.Set("filters", filterJSON)
}
resp, err := cli.get(ctx, "/containers/json", query, nil)
if err != nil {
return nil, err
}
var containers []types.Container
err = json.NewDecoder(resp.body).Decode(&containers)
ensureReaderClosed(resp)
return containers, err
}

View File

@ -1,52 +0,0 @@
package client
import (
"io"
"net/url"
"time"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
timetypes "github.com/docker/engine-api/types/time"
)
// ContainerLogs returns the logs generated by a container in an io.ReadCloser.
// It's up to the caller to close the stream.
func (cli *Client) ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error) {
query := url.Values{}
if options.ShowStdout {
query.Set("stdout", "1")
}
if options.ShowStderr {
query.Set("stderr", "1")
}
if options.Since != "" {
ts, err := timetypes.GetTimestamp(options.Since, time.Now())
if err != nil {
return nil, err
}
query.Set("since", ts)
}
if options.Timestamps {
query.Set("timestamps", "1")
}
if options.Details {
query.Set("details", "1")
}
if options.Follow {
query.Set("follow", "1")
}
query.Set("tail", options.Tail)
resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil)
if err != nil {
return nil, err
}
return resp.body, nil
}

View File

@ -1,10 +0,0 @@
package client
import "golang.org/x/net/context"
// ContainerPause pauses the main process of a given container without terminating it.
func (cli *Client) ContainerPause(ctx context.Context, containerID string) error {
resp, err := cli.post(ctx, "/containers/"+containerID+"/pause", nil, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,27 +0,0 @@
package client
import (
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ContainerRemove kills and removes a container from the docker host.
func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options types.ContainerRemoveOptions) error {
query := url.Values{}
if options.RemoveVolumes {
query.Set("v", "1")
}
if options.RemoveLinks {
query.Set("link", "1")
}
if options.Force {
query.Set("force", "1")
}
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,16 +0,0 @@
package client
import (
"net/url"
"golang.org/x/net/context"
)
// ContainerRename changes the name of a given container.
func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error {
query := url.Values{}
query.Set("name", newContainerName)
resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,29 +0,0 @@
package client
import (
"net/url"
"strconv"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ContainerResize changes the size of the tty for a container.
func (cli *Client) ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error {
return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width)
}
// ContainerExecResize changes the size of the tty for an exec process running inside a container.
func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error {
return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width)
}
func (cli *Client) resize(ctx context.Context, basePath string, height, width int) error {
query := url.Values{}
query.Set("h", strconv.Itoa(height))
query.Set("w", strconv.Itoa(width))
resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,19 +0,0 @@
package client
import (
"net/url"
"strconv"
"golang.org/x/net/context"
)
// ContainerRestart stops and starts a container again.
// It makes the daemon to wait for the container to be up again for
// a specific amount of time, given the timeout.
func (cli *Client) ContainerRestart(ctx context.Context, containerID string, timeout int) error {
query := url.Values{}
query.Set("t", strconv.Itoa(timeout))
resp, err := cli.post(ctx, "/containers/"+containerID+"/restart", query, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,10 +0,0 @@
package client
import "golang.org/x/net/context"
// ContainerStart sends a request to the docker daemon to start a container.
func (cli *Client) ContainerStart(ctx context.Context, containerID string) error {
resp, err := cli.post(ctx, "/containers/"+containerID+"/start", nil, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,24 +0,0 @@
package client
import (
"io"
"net/url"
"golang.org/x/net/context"
)
// ContainerStats returns near realtime stats for a given container.
// It's up to the caller to close the io.ReadCloser returned.
func (cli *Client) ContainerStats(ctx context.Context, containerID string, stream bool) (io.ReadCloser, error) {
query := url.Values{}
query.Set("stream", "0")
if stream {
query.Set("stream", "1")
}
resp, err := cli.get(ctx, "/containers/"+containerID+"/stats", query, nil)
if err != nil {
return nil, err
}
return resp.body, err
}

View File

@ -1,18 +0,0 @@
package client
import (
"net/url"
"strconv"
"golang.org/x/net/context"
)
// ContainerStop stops a container without terminating the process.
// The process is blocked until the container stops or the timeout expires.
func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout int) error {
query := url.Values{}
query.Set("t", strconv.Itoa(timeout))
resp, err := cli.post(ctx, "/containers/"+containerID+"/stop", query, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,28 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"strings"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ContainerTop shows process information from within a container.
func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (types.ContainerProcessList, error) {
var response types.ContainerProcessList
query := url.Values{}
if len(arguments) > 0 {
query.Set("ps_args", strings.Join(arguments, " "))
}
resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil)
if err != nil {
return response, err
}
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View File

@ -1,10 +0,0 @@
package client
import "golang.org/x/net/context"
// ContainerUnpause resumes the process execution within a container
func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error {
resp, err := cli.post(ctx, "/containers/"+containerID+"/unpause", nil, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,13 +0,0 @@
package client
import (
"github.com/docker/engine-api/types/container"
"golang.org/x/net/context"
)
// ContainerUpdate updates resources of a container
func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) error {
resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,26 +0,0 @@
package client
import (
"encoding/json"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
)
// ContainerWait pauses execution until a container exits.
// It returns the API status code as response of its readiness.
func (cli *Client) ContainerWait(ctx context.Context, containerID string) (int, error) {
resp, err := cli.post(ctx, "/containers/"+containerID+"/wait", nil, nil, nil)
if err != nil {
return -1, err
}
defer ensureReaderClosed(resp)
var res types.ContainerWaitResponse
if err := json.NewDecoder(resp.body).Decode(&res); err != nil {
return -1, err
}
return res.StatusCode, nil
}

View File

@ -1,94 +0,0 @@
package client
import (
"errors"
"fmt"
)
// ErrConnectionFailed is an error raised when the connection between the client and the server failed.
var ErrConnectionFailed = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?")
// imageNotFoundError implements an error returned when an image is not in the docker host.
type imageNotFoundError struct {
imageID string
}
// Error returns a string representation of an imageNotFoundError
func (i imageNotFoundError) Error() string {
return fmt.Sprintf("Error: No such image: %s", i.imageID)
}
// IsErrImageNotFound returns true if the error is caused
// when an image is not found in the docker host.
func IsErrImageNotFound(err error) bool {
_, ok := err.(imageNotFoundError)
return ok
}
// containerNotFoundError implements an error returned when a container is not in the docker host.
type containerNotFoundError struct {
containerID string
}
// Error returns a string representation of a containerNotFoundError
func (e containerNotFoundError) Error() string {
return fmt.Sprintf("Error: No such container: %s", e.containerID)
}
// IsErrContainerNotFound returns true if the error is caused
// when a container is not found in the docker host.
func IsErrContainerNotFound(err error) bool {
_, ok := err.(containerNotFoundError)
return ok
}
// networkNotFoundError implements an error returned when a network is not in the docker host.
type networkNotFoundError struct {
networkID string
}
// Error returns a string representation of a networkNotFoundError
func (e networkNotFoundError) Error() string {
return fmt.Sprintf("Error: No such network: %s", e.networkID)
}
// IsErrNetworkNotFound returns true if the error is caused
// when a network is not found in the docker host.
func IsErrNetworkNotFound(err error) bool {
_, ok := err.(networkNotFoundError)
return ok
}
// volumeNotFoundError implements an error returned when a volume is not in the docker host.
type volumeNotFoundError struct {
volumeID string
}
// Error returns a string representation of a networkNotFoundError
func (e volumeNotFoundError) Error() string {
return fmt.Sprintf("Error: No such volume: %s", e.volumeID)
}
// IsErrVolumeNotFound returns true if the error is caused
// when a volume is not found in the docker host.
func IsErrVolumeNotFound(err error) bool {
_, ok := err.(volumeNotFoundError)
return ok
}
// unauthorizedError represents an authorization error in a remote registry.
type unauthorizedError struct {
cause error
}
// Error returns a string representation of an unauthorizedError
func (u unauthorizedError) Error() string {
return u.cause.Error()
}
// IsErrUnauthorized returns true if the error is caused
// when a remote registry authentication fails
func IsErrUnauthorized(err error) bool {
_, ok := err.(unauthorizedError)
return ok
}

View File

@ -1,48 +0,0 @@
package client
import (
"io"
"net/url"
"time"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
timetypes "github.com/docker/engine-api/types/time"
)
// Events returns a stream of events in the daemon in a ReadCloser.
// It's up to the caller to close the stream.
func (cli *Client) Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error) {
query := url.Values{}
ref := time.Now()
if options.Since != "" {
ts, err := timetypes.GetTimestamp(options.Since, ref)
if err != nil {
return nil, err
}
query.Set("since", ts)
}
if options.Until != "" {
ts, err := timetypes.GetTimestamp(options.Until, ref)
if err != nil {
return nil, err
}
query.Set("until", ts)
}
if options.Filters.Len() > 0 {
filterJSON, err := filters.ToParam(options.Filters)
if err != nil {
return nil, err
}
query.Set("filters", filterJSON)
}
serverResponse, err := cli.get(ctx, "/events", query, nil)
if err != nil {
return nil, err
}
return serverResponse.body, nil
}

View File

@ -1,174 +0,0 @@
package client
import (
"crypto/tls"
"errors"
"fmt"
"net"
"net/http/httputil"
"net/url"
"strings"
"time"
"github.com/docker/engine-api/types"
"github.com/docker/go-connections/sockets"
"golang.org/x/net/context"
)
// tlsClientCon holds tls information and a dialed connection.
type tlsClientCon struct {
*tls.Conn
rawConn net.Conn
}
func (c *tlsClientCon) CloseWrite() error {
// Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
// on its underlying connection.
if conn, ok := c.rawConn.(types.CloseWriter); ok {
return conn.CloseWrite()
}
return nil
}
// postHijacked sends a POST request and hijacks the connection.
func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) {
bodyEncoded, err := encodeData(body)
if err != nil {
return types.HijackedResponse{}, err
}
req, err := cli.newRequest("POST", path, query, bodyEncoded, headers)
if err != nil {
return types.HijackedResponse{}, err
}
req.Host = cli.addr
req.Header.Set("Connection", "Upgrade")
req.Header.Set("Upgrade", "tcp")
conn, err := dial(cli.proto, cli.addr, cli.transport.TLSConfig())
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return types.HijackedResponse{}, fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
}
return types.HijackedResponse{}, err
}
// When we set up a TCP connection for hijack, there could be long periods
// of inactivity (a long running command with no output) that in certain
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
// state. Setting TCP KeepAlive on the socket connection will prohibit
// ECONNTIMEOUT unless the socket connection truly is broken
if tcpConn, ok := conn.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
}
clientconn := httputil.NewClientConn(conn, nil)
defer clientconn.Close()
// Server hijacks the connection, error 'connection closed' expected
_, err = clientconn.Do(req)
rwc, br := clientconn.Hijack()
return types.HijackedResponse{Conn: rwc, Reader: br}, err
}
func tlsDial(network, addr string, config *tls.Config) (net.Conn, error) {
return tlsDialWithDialer(new(net.Dialer), network, addr, config)
}
// We need to copy Go's implementation of tls.Dial (pkg/cryptor/tls/tls.go) in
// order to return our custom tlsClientCon struct which holds both the tls.Conn
// object _and_ its underlying raw connection. The rationale for this is that
// we need to be able to close the write end of the connection when attaching,
// which tls.Conn does not provide.
func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
// We want the Timeout and Deadline values from dialer to cover the
// whole process: TCP connection and TLS handshake. This means that we
// also need to start our own timers now.
timeout := dialer.Timeout
if !dialer.Deadline.IsZero() {
deadlineTimeout := dialer.Deadline.Sub(time.Now())
if timeout == 0 || deadlineTimeout < timeout {
timeout = deadlineTimeout
}
}
var errChannel chan error
if timeout != 0 {
errChannel = make(chan error, 2)
time.AfterFunc(timeout, func() {
errChannel <- errors.New("")
})
}
proxyDialer, err := sockets.DialerFromEnvironment(dialer)
if err != nil {
return nil, err
}
rawConn, err := proxyDialer.Dial(network, addr)
if err != nil {
return nil, err
}
// When we set up a TCP connection for hijack, there could be long periods
// of inactivity (a long running command with no output) that in certain
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
// state. Setting TCP KeepAlive on the socket connection will prohibit
// ECONNTIMEOUT unless the socket connection truly is broken
if tcpConn, ok := rawConn.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
}
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
hostname := addr[:colonPos]
// If no ServerName is set, infer the ServerName
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
c := *config
c.ServerName = hostname
config = &c
}
conn := tls.Client(rawConn, config)
if timeout == 0 {
err = conn.Handshake()
} else {
go func() {
errChannel <- conn.Handshake()
}()
err = <-errChannel
}
if err != nil {
rawConn.Close()
return nil, err
}
// This is Docker difference with standard's crypto/tls package: returned a
// wrapper which holds both the TLS and raw connections.
return &tlsClientCon{conn, rawConn}, nil
}
func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
if tlsConfig != nil && proto != "unix" && proto != "npipe" {
// Notice this isn't Go standard's tls.Dial function
return tlsDial(proto, addr, tlsConfig)
}
if proto == "npipe" {
return sockets.DialPipe(addr, 32*time.Second)
}
return net.Dial(proto, addr)
}

View File

@ -1,135 +0,0 @@
package client
import (
"encoding/base64"
"encoding/json"
"io"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
)
var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
// ImageBuild sends request to the daemon to build images.
// The Body in the response implement an io.ReadCloser and it's up to the caller to
// close it.
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
query, err := imageBuildOptionsToQuery(options)
if err != nil {
return types.ImageBuildResponse{}, err
}
headers := http.Header(make(map[string][]string))
buf, err := json.Marshal(options.AuthConfigs)
if err != nil {
return types.ImageBuildResponse{}, err
}
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
headers.Set("Content-Type", "application/tar")
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
if err != nil {
return types.ImageBuildResponse{}, err
}
osType := getDockerOS(serverResp.header.Get("Server"))
return types.ImageBuildResponse{
Body: serverResp.body,
OSType: osType,
}, nil
}
func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
query := url.Values{
"t": options.Tags,
}
if options.SuppressOutput {
query.Set("q", "1")
}
if options.RemoteContext != "" {
query.Set("remote", options.RemoteContext)
}
if options.NoCache {
query.Set("nocache", "1")
}
if options.Remove {
query.Set("rm", "1")
} else {
query.Set("rm", "0")
}
if options.ForceRemove {
query.Set("forcerm", "1")
}
if options.PullParent {
query.Set("pull", "1")
}
if !container.Isolation.IsDefault(options.Isolation) {
query.Set("isolation", string(options.Isolation))
}
query.Set("cpusetcpus", options.CPUSetCPUs)
query.Set("cpusetmems", options.CPUSetMems)
query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
query.Set("memory", strconv.FormatInt(options.Memory, 10))
query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
query.Set("cgroupparent", options.CgroupParent)
query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
query.Set("dockerfile", options.Dockerfile)
ulimitsJSON, err := json.Marshal(options.Ulimits)
if err != nil {
return query, err
}
query.Set("ulimits", string(ulimitsJSON))
buildArgsJSON, err := json.Marshal(options.BuildArgs)
if err != nil {
return query, err
}
query.Set("buildargs", string(buildArgsJSON))
labelsJSON, err := json.Marshal(options.Labels)
if err != nil {
return query, err
}
query.Set("labels", string(labelsJSON))
return query, nil
}
func getDockerOS(serverHeader string) string {
var osType string
matches := headerRegexp.FindStringSubmatch(serverHeader)
if len(matches) > 0 {
osType = matches[1]
}
return osType
}
// convertKVStringsToMap converts ["key=value"] to {"key":"value"}
func convertKVStringsToMap(values []string) map[string]string {
result := make(map[string]string, len(values))
for _, value := range values {
kv := strings.SplitN(value, "=", 2)
if len(kv) == 1 {
result[kv[0]] = ""
} else {
result[kv[0]] = kv[1]
}
}
return result
}

View File

@ -1,34 +0,0 @@
package client
import (
"io"
"net/url"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/reference"
)
// ImageCreate creates a new image based in the parent options.
// It returns the JSON content in the response body.
func (cli *Client) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) {
repository, tag, err := reference.Parse(parentReference)
if err != nil {
return nil, err
}
query := url.Values{}
query.Set("fromImage", repository)
query.Set("tag", tag)
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
if err != nil {
return nil, err
}
return resp.body, nil
}
func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
return cli.post(ctx, "/images/create", query, nil, headers)
}

View File

@ -1,22 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ImageHistory returns the changes in an image in history format.
func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]types.ImageHistory, error) {
var history []types.ImageHistory
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil)
if err != nil {
return history, err
}
err = json.NewDecoder(serverResp.body).Decode(&history)
ensureReaderClosed(serverResp)
return history, err
}

View File

@ -1,37 +0,0 @@
package client
import (
"io"
"net/url"
"golang.org/x/net/context"
"github.com/docker/distribution/reference"
"github.com/docker/engine-api/types"
)
// ImageImport creates a new image based in the source options.
// It returns the JSON content in the response body.
func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) {
if ref != "" {
//Check if the given image name can be resolved
if _, err := reference.ParseNamed(ref); err != nil {
return nil, err
}
}
query := url.Values{}
query.Set("fromSrc", source.SourceName)
query.Set("repo", ref)
query.Set("tag", options.Tag)
query.Set("message", options.Message)
for _, change := range options.Changes {
query.Add("changes", change)
}
resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil)
if err != nil {
return nil, err
}
return resp.body, nil
}

View File

@ -1,38 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ImageInspectWithRaw returns the image information and its raw representation.
func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string, getSize bool) (types.ImageInspect, []byte, error) {
query := url.Values{}
if getSize {
query.Set("size", "1")
}
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil)
if err != nil {
if serverResp.statusCode == http.StatusNotFound {
return types.ImageInspect{}, nil, imageNotFoundError{imageID}
}
return types.ImageInspect{}, nil, err
}
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body)
if err != nil {
return types.ImageInspect{}, nil, err
}
var response types.ImageInspect
rdr := bytes.NewReader(body)
err = json.NewDecoder(rdr).Decode(&response)
return response, body, err
}

View File

@ -1,40 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"golang.org/x/net/context"
)
// ImageList returns a list of images in the docker host.
func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error) {
var images []types.Image
query := url.Values{}
if options.Filters.Len() > 0 {
filterJSON, err := filters.ToParam(options.Filters)
if err != nil {
return images, err
}
query.Set("filters", filterJSON)
}
if options.MatchName != "" {
// FIXME rename this parameter, to not be confused with the filters flag
query.Set("filter", options.MatchName)
}
if options.All {
query.Set("all", "1")
}
serverResp, err := cli.get(ctx, "/images/json", query, nil)
if err != nil {
return images, err
}
err = json.NewDecoder(serverResp.body).Decode(&images)
ensureReaderClosed(serverResp)
return images, err
}

View File

@ -1,30 +0,0 @@
package client
import (
"io"
"net/url"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
)
// ImageLoad loads an image in the docker host from the client host.
// It's up to the caller to close the io.ReadCloser in the
// ImageLoadResponse returned by this function.
func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) {
v := url.Values{}
v.Set("quiet", "0")
if quiet {
v.Set("quiet", "1")
}
headers := map[string][]string{"Content-Type": {"application/x-tar"}}
resp, err := cli.postRaw(ctx, "/images/load", v, input, headers)
if err != nil {
return types.ImageLoadResponse{}, err
}
return types.ImageLoadResponse{
Body: resp.body,
JSON: resp.header.Get("Content-Type") == "application/json",
}, nil
}

View File

@ -1,46 +0,0 @@
package client
import (
"io"
"net/http"
"net/url"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/reference"
)
// ImagePull requests the docker host to pull an image from a remote registry.
// It executes the privileged function if the operation is unauthorized
// and it tries one more time.
// It's up to the caller to handle the io.ReadCloser and close it properly.
//
// FIXME(vdemeester): there is currently used in a few way in docker/docker
// - if not in trusted content, ref is used to pass the whole reference, and tag is empty
// - if in trusted content, ref is used to pass the reference name, and tag for the digest
func (cli *Client) ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) {
repository, tag, err := reference.Parse(ref)
if err != nil {
return nil, err
}
query := url.Values{}
query.Set("fromImage", repository)
if tag != "" && !options.All {
query.Set("tag", tag)
}
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil {
return nil, privilegeErr
}
resp, err = cli.tryImageCreate(ctx, query, newAuthHeader)
}
if err != nil {
return nil, err
}
return resp.body, nil
}

View File

@ -1,54 +0,0 @@
package client
import (
"errors"
"io"
"net/http"
"net/url"
"golang.org/x/net/context"
distreference "github.com/docker/distribution/reference"
"github.com/docker/engine-api/types"
)
// ImagePush requests the docker host to push an image to a remote registry.
// It executes the privileged function if the operation is unauthorized
// and it tries one more time.
// It's up to the caller to handle the io.ReadCloser and close it properly.
func (cli *Client) ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) {
distributionRef, err := distreference.ParseNamed(ref)
if err != nil {
return nil, err
}
if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
return nil, errors.New("cannot push a digest reference")
}
var tag = ""
if nameTaggedRef, isNamedTagged := distributionRef.(distreference.NamedTagged); isNamedTagged {
tag = nameTaggedRef.Tag()
}
query := url.Values{}
query.Set("tag", tag)
resp, err := cli.tryImagePush(ctx, distributionRef.Name(), query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized {
newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil {
return nil, privilegeErr
}
resp, err = cli.tryImagePush(ctx, distributionRef.Name(), query, newAuthHeader)
}
if err != nil {
return nil, err
}
return resp.body, nil
}
func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.Values, registryAuth string) (*serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
return cli.post(ctx, "/images/"+imageID+"/push", query, nil, headers)
}

View File

@ -1,31 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ImageRemove removes an image from the docker host.
func (cli *Client) ImageRemove(ctx context.Context, imageID string, options types.ImageRemoveOptions) ([]types.ImageDelete, error) {
query := url.Values{}
if options.Force {
query.Set("force", "1")
}
if !options.PruneChildren {
query.Set("noprune", "1")
}
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
if err != nil {
return nil, err
}
var dels []types.ImageDelete
err = json.NewDecoder(resp.body).Decode(&dels)
ensureReaderClosed(resp)
return dels, err
}

View File

@ -1,22 +0,0 @@
package client
import (
"io"
"net/url"
"golang.org/x/net/context"
)
// ImageSave retrieves one or more images from the docker host as an io.ReadCloser.
// It's up to the caller to store the images and close the stream.
func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) {
query := url.Values{
"names": imageIDs,
}
resp, err := cli.get(ctx, "/images/get", query, nil)
if err != nil {
return nil, err
}
return resp.body, nil
}

View File

@ -1,49 +0,0 @@
package client
import (
"encoding/json"
"net/http"
"net/url"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"github.com/docker/engine-api/types/registry"
"golang.org/x/net/context"
)
// ImageSearch makes the docker host to search by a term in a remote registry.
// The list of results is not sorted in any fashion.
func (cli *Client) ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error) {
var results []registry.SearchResult
query := url.Values{}
query.Set("term", term)
if options.Filters.Len() > 0 {
filterJSON, err := filters.ToParam(options.Filters)
if err != nil {
return results, err
}
query.Set("filters", filterJSON)
}
resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized {
newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil {
return results, privilegeErr
}
resp, err = cli.tryImageSearch(ctx, query, newAuthHeader)
}
if err != nil {
return results, err
}
err = json.NewDecoder(resp.body).Decode(&results)
ensureReaderClosed(resp)
return results, err
}
func (cli *Client) tryImageSearch(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
return cli.get(ctx, "/images/search", query, headers)
}

View File

@ -1,38 +0,0 @@
package client
import (
"errors"
"fmt"
"net/url"
"golang.org/x/net/context"
distreference "github.com/docker/distribution/reference"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/reference"
)
// ImageTag tags an image in the docker host
func (cli *Client) ImageTag(ctx context.Context, imageID, ref string, options types.ImageTagOptions) error {
distributionRef, err := distreference.ParseNamed(ref)
if err != nil {
return fmt.Errorf("Error parsing reference: %q is not a valid repository/tag", ref)
}
if _, isCanonical := distributionRef.(distreference.Canonical); isCanonical {
return errors.New("refusing to create a tag with a digest reference")
}
tag := reference.GetTagFromNamedRef(distributionRef)
query := url.Values{}
query.Set("repo", distributionRef.Name())
query.Set("tag", tag)
if options.Force {
query.Set("force", "1")
}
resp, err := cli.post(ctx, "/images/"+imageID+"/tag", query, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,26 +0,0 @@
package client
import (
"encoding/json"
"fmt"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// Info returns information about the docker server.
func (cli *Client) Info(ctx context.Context) (types.Info, error) {
var info types.Info
serverResp, err := cli.get(ctx, "/info", url.Values{}, nil)
if err != nil {
return info, err
}
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil {
return info, fmt.Errorf("Error reading remote info: %v", err)
}
return info, nil
}

View File

@ -1,79 +0,0 @@
package client
import (
"io"
"golang.org/x/net/context"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/filters"
"github.com/docker/engine-api/types/network"
"github.com/docker/engine-api/types/registry"
)
// APIClient is an interface that clients that talk with a docker server must implement.
type APIClient interface {
ClientVersion() string
ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error)
ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.ContainerCommitResponse, error)
ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (types.ContainerCreateResponse, error)
ContainerDiff(ctx context.Context, container string) ([]types.ContainerChange, error)
ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error)
ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.ContainerExecCreateResponse, error)
ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error
ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error
ContainerExport(ctx context.Context, container string) (io.ReadCloser, error)
ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error)
ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error)
ContainerKill(ctx context.Context, container, signal string) error
ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error)
ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error)
ContainerPause(ctx context.Context, container string) error
ContainerRemove(ctx context.Context, container string, options types.ContainerRemoveOptions) error
ContainerRename(ctx context.Context, container, newContainerName string) error
ContainerResize(ctx context.Context, container string, options types.ResizeOptions) error
ContainerRestart(ctx context.Context, container string, timeout int) error
ContainerStatPath(ctx context.Context, container, path string) (types.ContainerPathStat, error)
ContainerStats(ctx context.Context, container string, stream bool) (io.ReadCloser, error)
ContainerStart(ctx context.Context, container string) error
ContainerStop(ctx context.Context, container string, timeout int) error
ContainerTop(ctx context.Context, container string, arguments []string) (types.ContainerProcessList, error)
ContainerUnpause(ctx context.Context, container string) error
ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) error
ContainerWait(ctx context.Context, container string) (int, error)
CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
Events(ctx context.Context, options types.EventsOptions) (io.ReadCloser, error)
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
ImageHistory(ctx context.Context, image string) ([]types.ImageHistory, error)
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
ImageInspectWithRaw(ctx context.Context, image string, getSize bool) (types.ImageInspect, []byte, error)
ImageList(ctx context.Context, options types.ImageListOptions) ([]types.Image, error)
ImageLoad(ctx context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error)
ImagePull(ctx context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error)
ImagePush(ctx context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error)
ImageRemove(ctx context.Context, image string, options types.ImageRemoveOptions) ([]types.ImageDelete, error)
ImageSearch(ctx context.Context, term string, options types.ImageSearchOptions) ([]registry.SearchResult, error)
ImageSave(ctx context.Context, images []string) (io.ReadCloser, error)
ImageTag(ctx context.Context, image, ref string, options types.ImageTagOptions) error
Info(ctx context.Context) (types.Info, error)
NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error
NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error)
NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error
NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error)
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
NetworkRemove(ctx context.Context, networkID string) error
RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error)
ServerVersion(ctx context.Context) (types.Version, error)
UpdateClientVersion(v string)
VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error)
VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error)
VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error)
VolumeRemove(ctx context.Context, volumeID string) error
}
// Ensure that Client always implements APIClient.
var _ APIClient = &Client{}

View File

@ -1,28 +0,0 @@
package client
import (
"encoding/json"
"net/http"
"net/url"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// RegistryLogin authenticates the docker server with a given docker registry.
// It returns UnauthorizerError when the authentication fails.
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (types.AuthResponse, error) {
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
if resp != nil && resp.statusCode == http.StatusUnauthorized {
return types.AuthResponse{}, unauthorizedError{err}
}
if err != nil {
return types.AuthResponse{}, err
}
var response types.AuthResponse
err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err
}

View File

@ -1,18 +0,0 @@
package client
import (
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/network"
"golang.org/x/net/context"
)
// NetworkConnect connects a container to an existent network in the docker host.
func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error {
nc := types.NetworkConnect{
Container: containerID,
EndpointConfig: config,
}
resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,25 +0,0 @@
package client
import (
"encoding/json"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// NetworkCreate creates a new network in the docker host.
func (cli *Client) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) {
networkCreateRequest := types.NetworkCreateRequest{
NetworkCreate: options,
Name: name,
}
var response types.NetworkCreateResponse
serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil)
if err != nil {
return response, err
}
json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err
}

View File

@ -1,14 +0,0 @@
package client
import (
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// NetworkDisconnect disconnects a container from an existent network in the docker host.
func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error {
nd := types.NetworkDisconnect{Container: containerID, Force: force}
resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, nd, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,24 +0,0 @@
package client
import (
"encoding/json"
"net/http"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// NetworkInspect returns the information for a specific network configured in the docker host.
func (cli *Client) NetworkInspect(ctx context.Context, networkID string) (types.NetworkResource, error) {
var networkResource types.NetworkResource
resp, err := cli.get(ctx, "/networks/"+networkID, nil, nil)
if err != nil {
if resp.statusCode == http.StatusNotFound {
return networkResource, networkNotFoundError{networkID}
}
return networkResource, err
}
err = json.NewDecoder(resp.body).Decode(&networkResource)
ensureReaderClosed(resp)
return networkResource, err
}

View File

@ -1,31 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"golang.org/x/net/context"
)
// NetworkList returns the list of networks configured in the docker host.
func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
query := url.Values{}
if options.Filters.Len() > 0 {
filterJSON, err := filters.ToParam(options.Filters)
if err != nil {
return nil, err
}
query.Set("filters", filterJSON)
}
var networkResources []types.NetworkResource
resp, err := cli.get(ctx, "/networks", query, nil)
if err != nil {
return networkResources, err
}
err = json.NewDecoder(resp.body).Decode(&networkResources)
ensureReaderClosed(resp)
return networkResources, err
}

View File

@ -1,10 +0,0 @@
package client
import "golang.org/x/net/context"
// NetworkRemove removes an existent network from the docker host.
func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,185 +0,0 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/docker/engine-api/client/transport/cancellable"
"golang.org/x/net/context"
)
// serverResponse is a wrapper for http API responses.
type serverResponse struct {
body io.ReadCloser
header http.Header
statusCode int
}
// head sends an http request to the docker API using the method HEAD.
func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
return cli.sendRequest(ctx, "HEAD", path, query, nil, headers)
}
// getWithContext sends an http request to the docker API using the method GET with a specific go context.
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
return cli.sendRequest(ctx, "GET", path, query, nil, headers)
}
// postWithContext sends an http request to the docker API using the method POST with a specific go context.
func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
return cli.sendRequest(ctx, "POST", path, query, obj, headers)
}
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
return cli.sendClientRequest(ctx, "POST", path, query, body, headers)
}
// put sends an http request to the docker API using the method PUT.
func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
return cli.sendRequest(ctx, "PUT", path, query, obj, headers)
}
// put sends an http request to the docker API using the method PUT.
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
return cli.sendClientRequest(ctx, "PUT", path, query, body, headers)
}
// delete sends an http request to the docker API using the method DELETE.
func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
return cli.sendRequest(ctx, "DELETE", path, query, nil, headers)
}
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (*serverResponse, error) {
var body io.Reader
if obj != nil {
var err error
body, err = encodeData(obj)
if err != nil {
return nil, err
}
if headers == nil {
headers = make(map[string][]string)
}
headers["Content-Type"] = []string{"application/json"}
}
return cli.sendClientRequest(ctx, method, path, query, body, headers)
}
func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
serverResp := &serverResponse{
body: nil,
statusCode: -1,
}
expectedPayload := (method == "POST" || method == "PUT")
if expectedPayload && body == nil {
body = bytes.NewReader([]byte{})
}
req, err := cli.newRequest(method, path, query, body, headers)
if cli.proto == "unix" || cli.proto == "npipe" {
// For local communications, it doesn't matter what the host is. We just
// need a valid and meaningful host name. (See #189)
req.Host = "docker"
}
req.URL.Host = cli.addr
req.URL.Scheme = cli.transport.Scheme()
if expectedPayload && req.Header.Get("Content-Type") == "" {
req.Header.Set("Content-Type", "text/plain")
}
resp, err := cancellable.Do(ctx, cli.transport, req)
if resp != nil {
serverResp.statusCode = resp.StatusCode
}
if err != nil {
if isTimeout(err) || strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
return serverResp, ErrConnectionFailed
}
if !cli.transport.Secure() && strings.Contains(err.Error(), "malformed HTTP response") {
return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
}
if cli.transport.Secure() && strings.Contains(err.Error(), "remote error: bad certificate") {
return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
}
return serverResp, fmt.Errorf("An error occurred trying to connect: %v", err)
}
if serverResp.statusCode < 200 || serverResp.statusCode >= 400 {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return serverResp, err
}
if len(body) == 0 {
return serverResp, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), req.URL)
}
return serverResp, fmt.Errorf("Error response from daemon: %s", bytes.TrimSpace(body))
}
serverResp.body = resp.Body
serverResp.header = resp.Header
return serverResp, nil
}
func (cli *Client) newRequest(method, path string, query url.Values, body io.Reader, headers map[string][]string) (*http.Request, error) {
apiPath := cli.getAPIPath(path, query)
req, err := http.NewRequest(method, apiPath, body)
if err != nil {
return nil, err
}
// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
// then the user can't change OUR headers
for k, v := range cli.customHTTPHeaders {
req.Header.Set(k, v)
}
if headers != nil {
for k, v := range headers {
req.Header[k] = v
}
}
return req, nil
}
func encodeData(data interface{}) (*bytes.Buffer, error) {
params := bytes.NewBuffer(nil)
if data != nil {
if err := json.NewEncoder(params).Encode(data); err != nil {
return nil, err
}
}
return params, nil
}
func ensureReaderClosed(response *serverResponse) {
if response != nil && response.body != nil {
response.body.Close()
}
}
func isTimeout(err error) bool {
type timeout interface {
Timeout() bool
}
e := err
switch urlErr := err.(type) {
case *url.Error:
e = urlErr.Err
}
t, ok := e.(timeout)
return ok && t.Timeout()
}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"client.go",
"transport.go",
],
importpath = "github.com/docker/engine-api/client/transport",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/docker/go-connections/sockets:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/docker/engine-api/client/transport/cancellable:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,27 +0,0 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,23 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.5
package cancellable
import (
"net/http"
"github.com/docker/engine-api/client/transport"
)
func canceler(client transport.Sender, req *http.Request) func() {
// TODO(djd): Respect any existing value of req.Cancel.
ch := make(chan struct{})
req.Cancel = ch
return func() {
close(ch)
}
}

View File

@ -1,27 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.5
package cancellable
import (
"net/http"
"github.com/docker/engine-api/client/transport"
)
type requestCanceler interface {
CancelRequest(*http.Request)
}
func canceler(client transport.Sender, req *http.Request) func() {
rc, ok := client.(requestCanceler)
if !ok {
return func() {}
}
return func() {
rc.CancelRequest(req)
}
}

View File

@ -1,113 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package cancellable provides helper function to cancel http requests.
package cancellable
import (
"io"
"net/http"
"github.com/docker/engine-api/client/transport"
"golang.org/x/net/context"
)
func nop() {}
var (
testHookContextDoneBeforeHeaders = nop
testHookDoReturned = nop
testHookDidBodyClose = nop
)
// Do sends an HTTP request with the provided transport.Sender and returns an HTTP response.
// If the client is nil, http.DefaultClient is used.
// If the context is canceled or times out, ctx.Err() will be returned.
//
// FORK INFORMATION:
//
// This function deviates from the upstream version in golang.org/x/net/context/ctxhttp by
// taking a Sender interface rather than a *http.Client directly. That allow us to use
// this funcion with mocked clients and hijacked connections.
func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http.Response, error) {
if client == nil {
client = http.DefaultClient
}
// Request cancelation changed in Go 1.5, see canceler.go and canceler_go14.go.
cancel := canceler(client, req)
type responseAndError struct {
resp *http.Response
err error
}
result := make(chan responseAndError, 1)
go func() {
resp, err := client.Do(req)
testHookDoReturned()
result <- responseAndError{resp, err}
}()
var resp *http.Response
select {
case <-ctx.Done():
testHookContextDoneBeforeHeaders()
cancel()
// Clean up after the goroutine calling client.Do:
go func() {
if r := <-result; r.resp != nil && r.resp.Body != nil {
testHookDidBodyClose()
r.resp.Body.Close()
}
}()
return nil, ctx.Err()
case r := <-result:
var err error
resp, err = r.resp, r.err
if err != nil {
return resp, err
}
}
c := make(chan struct{})
go func() {
select {
case <-ctx.Done():
cancel()
case <-c:
// The response's Body is closed.
}
}()
resp.Body = &notifyingReader{resp.Body, c}
return resp, nil
}
// notifyingReader is an io.ReadCloser that closes the notify channel after
// Close is called or a Read fails on the underlying ReadCloser.
type notifyingReader struct {
io.ReadCloser
notify chan<- struct{}
}
func (r *notifyingReader) Read(p []byte) (int, error) {
n, err := r.ReadCloser.Read(p)
if err != nil && r.notify != nil {
close(r.notify)
r.notify = nil
}
return n, err
}
func (r *notifyingReader) Close() error {
err := r.ReadCloser.Close()
if r.notify != nil {
close(r.notify)
r.notify = nil
}
return err
}

View File

@ -1,47 +0,0 @@
package transport
import (
"crypto/tls"
"net/http"
)
// Sender is an interface that clients must implement
// to be able to send requests to a remote connection.
type Sender interface {
// Do sends request to a remote endpoint.
Do(*http.Request) (*http.Response, error)
}
// Client is an interface that abstracts all remote connections.
type Client interface {
Sender
// Secure tells whether the connection is secure or not.
Secure() bool
// Scheme returns the connection protocol the client uses.
Scheme() string
// TLSConfig returns any TLS configuration the client uses.
TLSConfig() *tls.Config
}
// tlsInfo returns information about the TLS configuration.
type tlsInfo struct {
tlsConfig *tls.Config
}
// TLSConfig returns the TLS configuration.
func (t *tlsInfo) TLSConfig() *tls.Config {
return t.tlsConfig
}
// Scheme returns protocol scheme to use.
func (t *tlsInfo) Scheme() string {
if t.tlsConfig != nil {
return "https"
}
return "http"
}
// Secure returns true if there is a TLS configuration.
func (t *tlsInfo) Secure() bool {
return t.tlsConfig != nil
}

View File

@ -1,57 +0,0 @@
// Package transport provides function to send request to remote endpoints.
package transport
import (
"fmt"
"net/http"
"github.com/docker/go-connections/sockets"
)
// apiTransport holds information about the http transport to connect with the API.
type apiTransport struct {
*http.Client
*tlsInfo
transport *http.Transport
}
// NewTransportWithHTTP creates a new transport based on the provided proto, address and http client.
// It uses Docker's default http transport configuration if the client is nil.
// It does not modify the client's transport if it's not nil.
func NewTransportWithHTTP(proto, addr string, client *http.Client) (Client, error) {
var transport *http.Transport
if client != nil {
tr, ok := client.Transport.(*http.Transport)
if !ok {
return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", client.Transport)
}
transport = tr
} else {
transport = defaultTransport(proto, addr)
client = &http.Client{
Transport: transport,
}
}
return &apiTransport{
Client: client,
tlsInfo: &tlsInfo{transport.TLSClientConfig},
transport: transport,
}, nil
}
// CancelRequest stops a request execution.
func (a *apiTransport) CancelRequest(req *http.Request) {
a.transport.CancelRequest(req)
}
// defaultTransport creates a new http.Transport with Docker's
// default transport configuration.
func defaultTransport(proto, addr string) *http.Transport {
tr := new(http.Transport)
sockets.ConfigureTransport(tr, proto, addr)
return tr
}
var _ Client = &apiTransport{}

View File

@ -1,21 +0,0 @@
package client
import (
"encoding/json"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// ServerVersion returns information of the docker client and server host.
func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
resp, err := cli.get(ctx, "/version", nil, nil)
if err != nil {
return types.Version{}, err
}
var server types.Version
err = json.NewDecoder(resp.body).Decode(&server)
ensureReaderClosed(resp)
return server, err
}

View File

@ -1,20 +0,0 @@
package client
import (
"encoding/json"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// VolumeCreate creates a volume in the docker host.
func (cli *Client) VolumeCreate(ctx context.Context, options types.VolumeCreateRequest) (types.Volume, error) {
var volume types.Volume
resp, err := cli.post(ctx, "/volumes/create", nil, options, nil)
if err != nil {
return volume, err
}
err = json.NewDecoder(resp.body).Decode(&volume)
ensureReaderClosed(resp)
return volume, err
}

View File

@ -1,24 +0,0 @@
package client
import (
"encoding/json"
"net/http"
"github.com/docker/engine-api/types"
"golang.org/x/net/context"
)
// VolumeInspect returns the information about a specific volume in the docker host.
func (cli *Client) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) {
var volume types.Volume
resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil)
if err != nil {
if resp.statusCode == http.StatusNotFound {
return volume, volumeNotFoundError{volumeID}
}
return volume, err
}
err = json.NewDecoder(resp.body).Decode(&volume)
ensureReaderClosed(resp)
return volume, err
}

View File

@ -1,32 +0,0 @@
package client
import (
"encoding/json"
"net/url"
"github.com/docker/engine-api/types"
"github.com/docker/engine-api/types/filters"
"golang.org/x/net/context"
)
// VolumeList returns the volumes configured in the docker host.
func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (types.VolumesListResponse, error) {
var volumes types.VolumesListResponse
query := url.Values{}
if filter.Len() > 0 {
filterJSON, err := filters.ToParam(filter)
if err != nil {
return volumes, err
}
query.Set("filters", filterJSON)
}
resp, err := cli.get(ctx, "/volumes", query, nil)
if err != nil {
return volumes, err
}
err = json.NewDecoder(resp.body).Decode(&volumes)
ensureReaderClosed(resp)
return volumes, err
}

View File

@ -1,10 +0,0 @@
package client
import "golang.org/x/net/context"
// VolumeRemove removes a volume from the docker host.
func (cli *Client) VolumeRemove(ctx context.Context, volumeID string) error {
resp, err := cli.delete(ctx, "/volumes/"+volumeID, nil, nil)
ensureReaderClosed(resp)
return err
}

View File

@ -1,48 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"auth.go",
"client.go",
"configs.go",
"seccomp.go",
"stats.go",
"types.go",
],
importpath = "github.com/docker/engine-api/types",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/docker/engine-api/types/container:go_default_library",
"//vendor/github.com/docker/engine-api/types/filters:go_default_library",
"//vendor/github.com/docker/engine-api/types/network:go_default_library",
"//vendor/github.com/docker/engine-api/types/registry:go_default_library",
"//vendor/github.com/docker/go-connections/nat:go_default_library",
"//vendor/github.com/docker/go-units:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/docker/engine-api/types/blkiodev:all-srcs",
"//vendor/github.com/docker/engine-api/types/container:all-srcs",
"//vendor/github.com/docker/engine-api/types/filters:all-srcs",
"//vendor/github.com/docker/engine-api/types/network:all-srcs",
"//vendor/github.com/docker/engine-api/types/reference:all-srcs",
"//vendor/github.com/docker/engine-api/types/registry:all-srcs",
"//vendor/github.com/docker/engine-api/types/strslice:all-srcs",
"//vendor/github.com/docker/engine-api/types/time:all-srcs",
"//vendor/github.com/docker/engine-api/types/versions:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,22 +0,0 @@
package types
// AuthConfig contains authorization information for connecting to a Registry
type AuthConfig struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Auth string `json:"auth,omitempty"`
// Email is an optional value associated with the username.
// This field is deprecated and will be removed in a later
// version of docker.
Email string `json:"email,omitempty"`
ServerAddress string `json:"serveraddress,omitempty"`
// IdentityToken is used to authenticate the user and get
// an access token for the registry.
IdentityToken string `json:"identitytoken,omitempty"`
// RegistryToken is a bearer token to be sent to a registry
RegistryToken string `json:"registrytoken,omitempty"`
}

View File

@ -1,22 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["blkio.go"],
importpath = "github.com/docker/engine-api/types/blkiodev",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,23 +0,0 @@
package blkiodev
import "fmt"
// WeightDevice is a structure that holds device:weight pair
type WeightDevice struct {
Path string
Weight uint16
}
func (w *WeightDevice) String() string {
return fmt.Sprintf("%s:%d", w.Path, w.Weight)
}
// ThrottleDevice is a structure that holds device:rate_per_second pair
type ThrottleDevice struct {
Path string
Rate uint64
}
func (t *ThrottleDevice) String() string {
return fmt.Sprintf("%s:%d", t.Path, t.Rate)
}

View File

@ -1,235 +0,0 @@
package types
import (
"bufio"
"io"
"net"
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/filters"
"github.com/docker/go-units"
)
// ContainerAttachOptions holds parameters to attach to a container.
type ContainerAttachOptions struct {
Stream bool
Stdin bool
Stdout bool
Stderr bool
DetachKeys string
}
// ContainerCommitOptions holds parameters to commit changes into a container.
type ContainerCommitOptions struct {
Reference string
Comment string
Author string
Changes []string
Pause bool
Config *container.Config
}
// ContainerExecInspect holds information returned by exec inspect.
type ContainerExecInspect struct {
ExecID string
ContainerID string
Running bool
ExitCode int
}
// ContainerListOptions holds parameters to list containers with.
type ContainerListOptions struct {
Quiet bool
Size bool
All bool
Latest bool
Since string
Before string
Limit int
Filter filters.Args
}
// ContainerLogsOptions holds parameters to filter logs with.
type ContainerLogsOptions struct {
ShowStdout bool
ShowStderr bool
Since string
Timestamps bool
Follow bool
Tail string
Details bool
}
// ContainerRemoveOptions holds parameters to remove containers.
type ContainerRemoveOptions struct {
RemoveVolumes bool
RemoveLinks bool
Force bool
}
// CopyToContainerOptions holds information
// about files to copy into a container
type CopyToContainerOptions struct {
AllowOverwriteDirWithFile bool
}
// EventsOptions hold parameters to filter events with.
type EventsOptions struct {
Since string
Until string
Filters filters.Args
}
// NetworkListOptions holds parameters to filter the list of networks with.
type NetworkListOptions struct {
Filters filters.Args
}
// HijackedResponse holds connection information for a hijacked request.
type HijackedResponse struct {
Conn net.Conn
Reader *bufio.Reader
}
// Close closes the hijacked connection and reader.
func (h *HijackedResponse) Close() {
h.Conn.Close()
}
// CloseWriter is an interface that implements structs
// that close input streams to prevent from writing.
type CloseWriter interface {
CloseWrite() error
}
// CloseWrite closes a readWriter for writing.
func (h *HijackedResponse) CloseWrite() error {
if conn, ok := h.Conn.(CloseWriter); ok {
return conn.CloseWrite()
}
return nil
}
// ImageBuildOptions holds the information
// necessary to build images.
type ImageBuildOptions struct {
Tags []string
SuppressOutput bool
RemoteContext string
NoCache bool
Remove bool
ForceRemove bool
PullParent bool
Isolation container.Isolation
CPUSetCPUs string
CPUSetMems string
CPUShares int64
CPUQuota int64
CPUPeriod int64
Memory int64
MemorySwap int64
CgroupParent string
ShmSize int64
Dockerfile string
Ulimits []*units.Ulimit
BuildArgs map[string]string
AuthConfigs map[string]AuthConfig
Context io.Reader
Labels map[string]string
}
// ImageBuildResponse holds information
// returned by a server after building
// an image.
type ImageBuildResponse struct {
Body io.ReadCloser
OSType string
}
// ImageCreateOptions holds information to create images.
type ImageCreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
}
// ImageImportSource holds source information for ImageImport
type ImageImportSource struct {
Source io.Reader // Source is the data to send to the server to create this image from (mutually exclusive with SourceName)
SourceName string // SourceName is the name of the image to pull (mutually exclusive with Source)
}
// ImageImportOptions holds information to import images from the client host.
type ImageImportOptions struct {
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image
}
// ImageListOptions holds parameters to filter the list of images with.
type ImageListOptions struct {
MatchName string
All bool
Filters filters.Args
}
// ImageLoadResponse returns information to the client about a load process.
type ImageLoadResponse struct {
// Body must be closed to avoid a resource leak
Body io.ReadCloser
JSON bool
}
// ImagePullOptions holds information to pull images.
type ImagePullOptions struct {
All bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
PrivilegeFunc RequestPrivilegeFunc
}
// RequestPrivilegeFunc is a function interface that
// clients can supply to retry operations after
// getting an authorization error.
// This function returns the registry authentication
// header value in base 64 format, or an error
// if the privilege request fails.
type RequestPrivilegeFunc func() (string, error)
//ImagePushOptions holds information to push images.
type ImagePushOptions ImagePullOptions
// ImageRemoveOptions holds parameters to remove images.
type ImageRemoveOptions struct {
Force bool
PruneChildren bool
}
// ImageSearchOptions holds parameters to search images with.
type ImageSearchOptions struct {
RegistryAuth string
PrivilegeFunc RequestPrivilegeFunc
Filters filters.Args
}
// ImageTagOptions holds parameters to tag an image
type ImageTagOptions struct {
Force bool
}
// ResizeOptions holds parameters to resize a tty.
// It can be used to resize container ttys and
// exec process ttys too.
type ResizeOptions struct {
Height int
Width int
}
// VersionResponse holds version information for the client and the server
type VersionResponse struct {
Client *Version
Server *Version
}
// ServerOK returns true when the client could connect to the docker server
// and parse the information received. It returns false otherwise.
func (v VersionResponse) ServerOK() bool {
return v.Server != nil
}

View File

@ -1,53 +0,0 @@
package types
import (
"github.com/docker/engine-api/types/container"
"github.com/docker/engine-api/types/network"
)
// configs holds structs used for internal communication between the
// frontend (such as an http server) and the backend (such as the
// docker daemon).
// ContainerCreateConfig is the parameter set to ContainerCreate()
type ContainerCreateConfig struct {
Name string
Config *container.Config
HostConfig *container.HostConfig
NetworkingConfig *network.NetworkingConfig
AdjustCPUShares bool
}
// ContainerRmConfig holds arguments for the container remove
// operation. This struct is used to tell the backend what operations
// to perform.
type ContainerRmConfig struct {
ForceRemove, RemoveVolume, RemoveLink bool
}
// ContainerCommitConfig contains build configs for commit operation,
// and is used when making a commit with the current state of the container.
type ContainerCommitConfig struct {
Pause bool
Repo string
Tag string
Author string
Comment string
// merge container config into commit config before commit
MergeConfigs bool
Config *container.Config
}
// ExecConfig is a small subset of the Config struct that holds the configuration
// for the exec feature of docker.
type ExecConfig struct {
User string // User that will run the command
Privileged bool // Is the container in privileged mode
Tty bool // Attach standard streams to a tty.
AttachStdin bool // Attach the standard input, makes possible user interaction
AttachStderr bool // Attach the standard output
AttachStdout bool // Attach the standard error
Detach bool // Execute in detach mode
DetachKeys string // Escape keys for detach
Cmd []string // Execution commands and args
}

View File

@ -1,37 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"config.go",
"host_config.go",
"hostconfig_unix.go",
] + select({
"@io_bazel_rules_go//go/platform:windows_amd64": [
"hostconfig_windows.go",
],
"//conditions:default": [],
}),
importpath = "github.com/docker/engine-api/types/container",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/docker/engine-api/types/blkiodev:go_default_library",
"//vendor/github.com/docker/engine-api/types/strslice:go_default_library",
"//vendor/github.com/docker/go-connections/nat:go_default_library",
"//vendor/github.com/docker/go-units:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,37 +0,0 @@
package container
import (
"github.com/docker/engine-api/types/strslice"
"github.com/docker/go-connections/nat"
)
// Config contains the configuration data about a container.
// It should hold only portable information about the container.
// Here, "portable" means "independent from the host we are running on".
// Non-portable information *should* appear in HostConfig.
// All fields added to this struct must be marked `omitempty` to keep getting
// predictable hashes from the old `v1Compatibility` configuration.
type Config struct {
Hostname string // Hostname
Domainname string // Domainname
User string // User that will run the command(s) inside the container
AttachStdin bool // Attach the standard input, makes possible user interaction
AttachStdout bool // Attach the standard output
AttachStderr bool // Attach the standard error
ExposedPorts map[nat.Port]struct{} `json:",omitempty"` // List of exposed ports
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
OpenStdin bool // Open stdin
StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
Env []string // List of environment variable to set in the container
Cmd strslice.StrSlice // Command to run when starting the container
ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific)
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
Volumes map[string]struct{} // List of volumes (mounts) used for the container
WorkingDir string // Current directory (PWD) in the command will be launched
Entrypoint strslice.StrSlice // Entrypoint to run when starting the container
NetworkDisabled bool `json:",omitempty"` // Is network disabled
MacAddress string `json:",omitempty"` // Mac Address of the container
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
Labels map[string]string // List of labels set to this container
StopSignal string `json:",omitempty"` // Signal to stop a container
}

View File

@ -1,320 +0,0 @@
package container
import (
"strings"
"github.com/docker/engine-api/types/blkiodev"
"github.com/docker/engine-api/types/strslice"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
)
// NetworkMode represents the container network stack.
type NetworkMode string
// Isolation represents the isolation technology of a container. The supported
// values are platform specific
type Isolation string
// IsDefault indicates the default isolation technology of a container. On Linux this
// is the native driver. On Windows, this is a Windows Server Container.
func (i Isolation) IsDefault() bool {
return strings.ToLower(string(i)) == "default" || string(i) == ""
}
// IpcMode represents the container ipc stack.
type IpcMode string
// IsPrivate indicates whether the container uses its private ipc stack.
func (n IpcMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer())
}
// IsHost indicates whether the container uses the host's ipc stack.
func (n IpcMode) IsHost() bool {
return n == "host"
}
// IsContainer indicates whether the container uses a container's ipc stack.
func (n IpcMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container"
}
// Valid indicates whether the ipc stack is valid.
func (n IpcMode) Valid() bool {
parts := strings.Split(string(n), ":")
switch mode := parts[0]; mode {
case "", "host":
case "container":
if len(parts) != 2 || parts[1] == "" {
return false
}
default:
return false
}
return true
}
// Container returns the name of the container ipc stack is going to be used.
func (n IpcMode) Container() string {
parts := strings.SplitN(string(n), ":", 2)
if len(parts) > 1 {
return parts[1]
}
return ""
}
// UsernsMode represents userns mode in the container.
type UsernsMode string
// IsHost indicates whether the container uses the host's userns.
func (n UsernsMode) IsHost() bool {
return n == "host"
}
// IsPrivate indicates whether the container uses the a private userns.
func (n UsernsMode) IsPrivate() bool {
return !(n.IsHost())
}
// Valid indicates whether the userns is valid.
func (n UsernsMode) Valid() bool {
parts := strings.Split(string(n), ":")
switch mode := parts[0]; mode {
case "", "host":
default:
return false
}
return true
}
// CgroupSpec represents the cgroup to use for the container.
type CgroupSpec string
// IsContainer indicates whether the container is using another container cgroup
func (c CgroupSpec) IsContainer() bool {
parts := strings.SplitN(string(c), ":", 2)
return len(parts) > 1 && parts[0] == "container"
}
// Valid indicates whether the cgroup spec is valid.
func (c CgroupSpec) Valid() bool {
return c.IsContainer() || c == ""
}
// Container returns the name of the container whose cgroup will be used.
func (c CgroupSpec) Container() string {
parts := strings.SplitN(string(c), ":", 2)
if len(parts) > 1 {
return parts[1]
}
return ""
}
// UTSMode represents the UTS namespace of the container.
type UTSMode string
// IsPrivate indicates whether the container uses its private UTS namespace.
func (n UTSMode) IsPrivate() bool {
return !(n.IsHost())
}
// IsHost indicates whether the container uses the host's UTS namespace.
func (n UTSMode) IsHost() bool {
return n == "host"
}
// Valid indicates whether the UTS namespace is valid.
func (n UTSMode) Valid() bool {
parts := strings.Split(string(n), ":")
switch mode := parts[0]; mode {
case "", "host":
default:
return false
}
return true
}
// PidMode represents the pid namespace of the container.
type PidMode string
// IsPrivate indicates whether the container uses its own new pid namespace.
func (n PidMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer())
}
// IsHost indicates whether the container uses the host's pid namespace.
func (n PidMode) IsHost() bool {
return n == "host"
}
// IsContainer indicates whether the container uses a container's pid namespace.
func (n PidMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container"
}
// Valid indicates whether the pid namespace is valid.
func (n PidMode) Valid() bool {
parts := strings.Split(string(n), ":")
switch mode := parts[0]; mode {
case "", "host":
case "container":
if len(parts) != 2 || parts[1] == "" {
return false
}
default:
return false
}
return true
}
// Container returns the name of the container whose pid namespace is going to be used.
func (n PidMode) Container() string {
parts := strings.SplitN(string(n), ":", 2)
if len(parts) > 1 {
return parts[1]
}
return ""
}
// DeviceMapping represents the device mapping between the host and the container.
type DeviceMapping struct {
PathOnHost string
PathInContainer string
CgroupPermissions string
}
// RestartPolicy represents the restart policies of the container.
type RestartPolicy struct {
Name string
MaximumRetryCount int
}
// IsNone indicates whether the container has the "no" restart policy.
// This means the container will not automatically restart when exiting.
func (rp *RestartPolicy) IsNone() bool {
return rp.Name == "no"
}
// IsAlways indicates whether the container has the "always" restart policy.
// This means the container will automatically restart regardless of the exit status.
func (rp *RestartPolicy) IsAlways() bool {
return rp.Name == "always"
}
// IsOnFailure indicates whether the container has the "on-failure" restart policy.
// This means the container will automatically restart of exiting with a non-zero exit status.
func (rp *RestartPolicy) IsOnFailure() bool {
return rp.Name == "on-failure"
}
// IsUnlessStopped indicates whether the container has the
// "unless-stopped" restart policy. This means the container will
// automatically restart unless user has put it to stopped state.
func (rp *RestartPolicy) IsUnlessStopped() bool {
return rp.Name == "unless-stopped"
}
// IsSame compares two RestartPolicy to see if they are the same
func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
}
// LogConfig represents the logging configuration of the container.
type LogConfig struct {
Type string
Config map[string]string
}
// Resources contains container's resources (cgroups config, ulimits...)
type Resources struct {
// Applicable to all platforms
CPUShares int64 `json:"CpuShares"` // CPU shares (relative weight vs. other containers)
Memory int64 // Memory limit (in bytes)
// Applicable to UNIX platforms
CgroupParent string // Parent cgroup.
BlkioWeight uint16 // Block IO weight (relative weight vs. other containers)
BlkioWeightDevice []*blkiodev.WeightDevice
BlkioDeviceReadBps []*blkiodev.ThrottleDevice
BlkioDeviceWriteBps []*blkiodev.ThrottleDevice
BlkioDeviceReadIOps []*blkiodev.ThrottleDevice
BlkioDeviceWriteIOps []*blkiodev.ThrottleDevice
CPUPeriod int64 `json:"CpuPeriod"` // CPU CFS (Completely Fair Scheduler) period
CPUQuota int64 `json:"CpuQuota"` // CPU CFS (Completely Fair Scheduler) quota
CpusetCpus string // CpusetCpus 0-2, 0,1
CpusetMems string // CpusetMems 0-2, 0,1
Devices []DeviceMapping // List of devices to map inside the container
DiskQuota int64 // Disk limit (in bytes)
KernelMemory int64 // Kernel memory limit (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
OomKillDisable *bool // Whether to disable OOM Killer or not
PidsLimit int64 // Setting pids limit for a container
Ulimits []*units.Ulimit // List of ulimits to be set in the container
// Applicable to Windows
CPUCount int64 `json:"CpuCount"` // CPU count
CPUPercent int64 `json:"CpuPercent"` // CPU percent
IOMaximumIOps uint64 // Maximum IOps for the container system drive
IOMaximumBandwidth uint64 // Maximum IO in bytes per second for the container system drive
NetworkMaximumBandwidth uint64 // Maximum bandwidth of the network endpoint in bytes per second
}
// UpdateConfig holds the mutable attributes of a Container.
// Those attributes can be updated at runtime.
type UpdateConfig struct {
// Contains container's resources (cgroups, ulimits)
Resources
RestartPolicy RestartPolicy
}
// HostConfig the non-portable Config structure of a container.
// Here, "non-portable" means "dependent of the host we are running on".
// Portable information *should* appear in Config.
type HostConfig struct {
// Applicable to all platforms
Binds []string // List of volume bindings for this container
ContainerIDFile string // File (path) where the containerId is written
LogConfig LogConfig // Configuration of the logs for this container
NetworkMode NetworkMode // Network mode to use for the container
PortBindings nat.PortMap // Port mapping between the exposed port (container) and the host
RestartPolicy RestartPolicy // Restart policy to be used for the container
AutoRemove bool // Automatically remove container when it exits
VolumeDriver string // Name of the volume driver used to mount volumes
VolumesFrom []string // List of volumes to take from other container
// Applicable to UNIX platforms
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
DNS []string `json:"Dns"` // List of DNS server to lookup
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
ExtraHosts []string // List of extra hosts
GroupAdd []string // List of additional groups that the container process will run as
IpcMode IpcMode // IPC namespace to use for the container
Cgroup CgroupSpec // Cgroup to use for the container
Links []string // List of links (in the name:alias form)
OomScoreAdj int // Container preference for OOM-killing
PidMode PidMode // PID namespace to use for the container
Privileged bool // Is the container in privileged mode
PublishAllPorts bool // Should docker publish all exposed port for the container
ReadonlyRootfs bool // Is the container root filesystem in read-only
SecurityOpt []string // List of string values to customize labels for MLS systems, such as SELinux.
StorageOpt map[string]string // Storage driver options per container.
Tmpfs map[string]string `json:",omitempty"` // List of tmpfs (mounts) used for the container
UTSMode UTSMode // UTS namespace to use for the container
UsernsMode UsernsMode // The user namespace to use for the container
ShmSize int64 // Total shm memory usage
Sysctls map[string]string `json:",omitempty"` // List of Namespaced sysctls used for the container
// Applicable to Windows
ConsoleSize [2]int // Initial console size
Isolation Isolation // Isolation technology of the container (eg default, hyperv)
// Contains container's resources (cgroups, ulimits)
Resources
}

View File

@ -1,81 +0,0 @@
// +build !windows
package container
import "strings"
// IsValid indicates if an isolation technology is valid
func (i Isolation) IsValid() bool {
return i.IsDefault()
}
// IsPrivate indicates whether container uses it's private network stack.
func (n NetworkMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer())
}
// IsDefault indicates whether container uses the default network stack.
func (n NetworkMode) IsDefault() bool {
return n == "default"
}
// NetworkName returns the name of the network stack.
func (n NetworkMode) NetworkName() string {
if n.IsBridge() {
return "bridge"
} else if n.IsHost() {
return "host"
} else if n.IsContainer() {
return "container"
} else if n.IsNone() {
return "none"
} else if n.IsDefault() {
return "default"
} else if n.IsUserDefined() {
return n.UserDefined()
}
return ""
}
// IsBridge indicates whether container uses the bridge network stack
func (n NetworkMode) IsBridge() bool {
return n == "bridge"
}
// IsHost indicates whether container uses the host network stack.
func (n NetworkMode) IsHost() bool {
return n == "host"
}
// IsContainer indicates whether container uses a container network stack.
func (n NetworkMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container"
}
// IsNone indicates whether container isn't using a network stack.
func (n NetworkMode) IsNone() bool {
return n == "none"
}
// ConnectedContainer is the id of the container which network this container is connected to.
func (n NetworkMode) ConnectedContainer() string {
parts := strings.SplitN(string(n), ":", 2)
if len(parts) > 1 {
return parts[1]
}
return ""
}
// IsUserDefined indicates user-created network
func (n NetworkMode) IsUserDefined() bool {
return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()
}
//UserDefined indicates user-created network
func (n NetworkMode) UserDefined() string {
if n.IsUserDefined() {
return string(n)
}
return ""
}

View File

@ -1,87 +0,0 @@
package container
import (
"strings"
)
// IsDefault indicates whether container uses the default network stack.
func (n NetworkMode) IsDefault() bool {
return n == "default"
}
// IsNone indicates whether container isn't using a network stack.
func (n NetworkMode) IsNone() bool {
return n == "none"
}
// IsContainer indicates whether container uses a container network stack.
// Returns false as windows doesn't support this mode
func (n NetworkMode) IsContainer() bool {
return false
}
// IsBridge indicates whether container uses the bridge network stack
// in windows it is given the name NAT
func (n NetworkMode) IsBridge() bool {
return n == "nat"
}
// IsHost indicates whether container uses the host network stack.
// returns false as this is not supported by windows
func (n NetworkMode) IsHost() bool {
return false
}
// IsPrivate indicates whether container uses its private network stack.
func (n NetworkMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer())
}
// ConnectedContainer is the id of the container which network this container is connected to.
// Returns blank string on windows
func (n NetworkMode) ConnectedContainer() string {
return ""
}
// IsUserDefined indicates user-created network
func (n NetworkMode) IsUserDefined() bool {
return !n.IsDefault() && !n.IsNone() && !n.IsBridge()
}
// IsHyperV indicates the use of a Hyper-V partition for isolation
func (i Isolation) IsHyperV() bool {
return strings.ToLower(string(i)) == "hyperv"
}
// IsProcess indicates the use of process isolation
func (i Isolation) IsProcess() bool {
return strings.ToLower(string(i)) == "process"
}
// IsValid indicates if an isolation technology is valid
func (i Isolation) IsValid() bool {
return i.IsDefault() || i.IsHyperV() || i.IsProcess()
}
// NetworkName returns the name of the network stack.
func (n NetworkMode) NetworkName() string {
if n.IsDefault() {
return "default"
} else if n.IsBridge() {
return "nat"
} else if n.IsNone() {
return "none"
} else if n.IsUserDefined() {
return n.UserDefined()
}
return ""
}
//UserDefined indicates user-created network
func (n NetworkMode) UserDefined() string {
if n.IsUserDefined() {
return string(n)
}
return ""
}

View File

@ -1,23 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["parse.go"],
importpath = "github.com/docker/engine-api/types/filters",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/docker/engine-api/types/versions:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,295 +0,0 @@
// Package filters provides helper function to parse and handle command line
// filter, used for example in docker ps or docker images commands.
package filters
import (
"encoding/json"
"errors"
"fmt"
"regexp"
"strings"
"github.com/docker/engine-api/types/versions"
)
// Args stores filter arguments as map key:{map key: bool}.
// It contains an aggregation of the map of arguments (which are in the form
// of -f 'key=value') based on the key, and stores values for the same key
// in a map with string keys and boolean values.
// e.g given -f 'label=label1=1' -f 'label=label2=2' -f 'image.name=ubuntu'
// the args will be {"image.name":{"ubuntu":true},"label":{"label1=1":true,"label2=2":true}}
type Args struct {
fields map[string]map[string]bool
}
// NewArgs initializes a new Args struct.
func NewArgs() Args {
return Args{fields: map[string]map[string]bool{}}
}
// ParseFlag parses the argument to the filter flag. Like
//
// `docker ps -f 'created=today' -f 'image.name=ubuntu*'`
//
// If prev map is provided, then it is appended to, and returned. By default a new
// map is created.
func ParseFlag(arg string, prev Args) (Args, error) {
filters := prev
if len(arg) == 0 {
return filters, nil
}
if !strings.Contains(arg, "=") {
return filters, ErrBadFormat
}
f := strings.SplitN(arg, "=", 2)
name := strings.ToLower(strings.TrimSpace(f[0]))
value := strings.TrimSpace(f[1])
filters.Add(name, value)
return filters, nil
}
// ErrBadFormat is an error returned in case of bad format for a filter.
var ErrBadFormat = errors.New("bad format of filter (expected name=value)")
// ToParam packs the Args into a string for easy transport from client to server.
func ToParam(a Args) (string, error) {
// this way we don't URL encode {}, just empty space
if a.Len() == 0 {
return "", nil
}
buf, err := json.Marshal(a.fields)
if err != nil {
return "", err
}
return string(buf), nil
}
// ToParamWithVersion packs the Args into a string for easy transport from client to server.
// The generated string will depend on the specified version (corresponding to the API version).
func ToParamWithVersion(version string, a Args) (string, error) {
// this way we don't URL encode {}, just empty space
if a.Len() == 0 {
return "", nil
}
// for daemons older than v1.10, filter must be of the form map[string][]string
buf := []byte{}
err := errors.New("")
if version != "" && versions.LessThan(version, "1.22") {
buf, err = json.Marshal(convertArgsToSlice(a.fields))
} else {
buf, err = json.Marshal(a.fields)
}
if err != nil {
return "", err
}
return string(buf), nil
}
// FromParam unpacks the filter Args.
func FromParam(p string) (Args, error) {
if len(p) == 0 {
return NewArgs(), nil
}
r := strings.NewReader(p)
d := json.NewDecoder(r)
m := map[string]map[string]bool{}
if err := d.Decode(&m); err != nil {
r.Seek(0, 0)
// Allow parsing old arguments in slice format.
// Because other libraries might be sending them in this format.
deprecated := map[string][]string{}
if deprecatedErr := d.Decode(&deprecated); deprecatedErr == nil {
m = deprecatedArgs(deprecated)
} else {
return NewArgs(), err
}
}
return Args{m}, nil
}
// Get returns the list of values associates with a field.
// It returns a slice of strings to keep backwards compatibility with old code.
func (filters Args) Get(field string) []string {
values := filters.fields[field]
if values == nil {
return make([]string, 0)
}
slice := make([]string, 0, len(values))
for key := range values {
slice = append(slice, key)
}
return slice
}
// Add adds a new value to a filter field.
func (filters Args) Add(name, value string) {
if _, ok := filters.fields[name]; ok {
filters.fields[name][value] = true
} else {
filters.fields[name] = map[string]bool{value: true}
}
}
// Del removes a value from a filter field.
func (filters Args) Del(name, value string) {
if _, ok := filters.fields[name]; ok {
delete(filters.fields[name], value)
}
}
// Len returns the number of fields in the arguments.
func (filters Args) Len() int {
return len(filters.fields)
}
// MatchKVList returns true if the values for the specified field matches the ones
// from the sources.
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
// field is 'label' and sources are {'label1': '1', 'label2': '2'}
// it returns true.
func (filters Args) MatchKVList(field string, sources map[string]string) bool {
fieldValues := filters.fields[field]
//do not filter if there is no filter set or cannot determine filter
if len(fieldValues) == 0 {
return true
}
if sources == nil || len(sources) == 0 {
return false
}
for name2match := range fieldValues {
testKV := strings.SplitN(name2match, "=", 2)
v, ok := sources[testKV[0]]
if !ok {
return false
}
if len(testKV) == 2 && testKV[1] != v {
return false
}
}
return true
}
// Match returns true if the values for the specified field matches the source string
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
// field is 'image.name' and source is 'ubuntu'
// it returns true.
func (filters Args) Match(field, source string) bool {
if filters.ExactMatch(field, source) {
return true
}
fieldValues := filters.fields[field]
for name2match := range fieldValues {
match, err := regexp.MatchString(name2match, source)
if err != nil {
continue
}
if match {
return true
}
}
return false
}
// ExactMatch returns true if the source matches exactly one of the filters.
func (filters Args) ExactMatch(field, source string) bool {
fieldValues, ok := filters.fields[field]
//do not filter if there is no filter set or cannot determine filter
if !ok || len(fieldValues) == 0 {
return true
}
// try to match full name value to avoid O(N) regular expression matching
if fieldValues[source] {
return true
}
return false
}
// FuzzyMatch returns true if the source matches exactly one of the filters,
// or the source has one of the filters as a prefix.
func (filters Args) FuzzyMatch(field, source string) bool {
if filters.ExactMatch(field, source) {
return true
}
fieldValues := filters.fields[field]
for prefix := range fieldValues {
if strings.HasPrefix(source, prefix) {
return true
}
}
return false
}
// Include returns true if the name of the field to filter is in the filters.
func (filters Args) Include(field string) bool {
_, ok := filters.fields[field]
return ok
}
// Validate ensures that all the fields in the filter are valid.
// It returns an error as soon as it finds an invalid field.
func (filters Args) Validate(accepted map[string]bool) error {
for name := range filters.fields {
if !accepted[name] {
return fmt.Errorf("Invalid filter '%s'", name)
}
}
return nil
}
// WalkValues iterates over the list of filtered values for a field.
// It stops the iteration if it finds an error and it returns that error.
func (filters Args) WalkValues(field string, op func(value string) error) error {
if _, ok := filters.fields[field]; !ok {
return nil
}
for v := range filters.fields[field] {
if err := op(v); err != nil {
return err
}
}
return nil
}
func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
m := map[string]map[string]bool{}
for k, v := range d {
values := map[string]bool{}
for _, vv := range v {
values[vv] = true
}
m[k] = values
}
return m
}
func convertArgsToSlice(f map[string]map[string]bool) map[string][]string {
m := map[string][]string{}
for k, v := range f {
values := []string{}
for kk := range v {
if v[kk] {
values = append(values, kk)
}
}
m[k] = values
}
return m
}

View File

@ -1,52 +0,0 @@
package network
// Address represents an IP address
type Address struct {
Addr string
PrefixLen int
}
// IPAM represents IP Address Management
type IPAM struct {
Driver string
Options map[string]string //Per network IPAM driver options
Config []IPAMConfig
}
// IPAMConfig represents IPAM configurations
type IPAMConfig struct {
Subnet string `json:",omitempty"`
IPRange string `json:",omitempty"`
Gateway string `json:",omitempty"`
AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
}
// EndpointIPAMConfig represents IPAM configurations for the endpoint
type EndpointIPAMConfig struct {
IPv4Address string `json:",omitempty"`
IPv6Address string `json:",omitempty"`
}
// EndpointSettings stores the network endpoint details
type EndpointSettings struct {
// Configurations
IPAMConfig *EndpointIPAMConfig
Links []string
Aliases []string
// Operational data
NetworkID string
EndpointID string
Gateway string
IPAddress string
IPPrefixLen int
IPv6Gateway string
GlobalIPv6Address string
GlobalIPv6PrefixLen int
MacAddress string
}
// NetworkingConfig represents the container's networking configuration for each of its interfaces
// Carries the networking configs specified in the `docker run` and `docker network connect` commands
type NetworkingConfig struct {
EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each connecting network
}

View File

@ -1,23 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["image_reference.go"],
importpath = "github.com/docker/engine-api/types/reference",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/docker/distribution/reference:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,34 +0,0 @@
package reference
import (
distreference "github.com/docker/distribution/reference"
)
// Parse parses the given references and returns the repository and
// tag (if present) from it. If there is an error during parsing, it will
// return an error.
func Parse(ref string) (string, string, error) {
distributionRef, err := distreference.ParseNamed(ref)
if err != nil {
return "", "", err
}
tag := GetTagFromNamedRef(distributionRef)
return distributionRef.Name(), tag, nil
}
// GetTagFromNamedRef returns a tag from the specified reference.
// This function is necessary as long as the docker "server" api makes the distinction between repository
// and tags.
func GetTagFromNamedRef(ref distreference.Named) string {
var tag string
switch x := ref.(type) {
case distreference.Digested:
tag = x.Digest().String()
case distreference.NamedTagged:
tag = x.Tag()
default:
tag = "latest"
}
return tag
}

View File

@ -1,22 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["registry.go"],
importpath = "github.com/docker/engine-api/types/registry",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,99 +0,0 @@
package registry
import (
"encoding/json"
"net"
)
// ServiceConfig stores daemon registry services configuration.
type ServiceConfig struct {
InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"`
IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"`
Mirrors []string
}
// NetIPNet is the net.IPNet type, which can be marshalled and
// unmarshalled to JSON
type NetIPNet net.IPNet
// MarshalJSON returns the JSON representation of the IPNet
func (ipnet *NetIPNet) MarshalJSON() ([]byte, error) {
return json.Marshal((*net.IPNet)(ipnet).String())
}
// UnmarshalJSON sets the IPNet from a byte array of JSON
func (ipnet *NetIPNet) UnmarshalJSON(b []byte) (err error) {
var ipnetStr string
if err = json.Unmarshal(b, &ipnetStr); err == nil {
var cidr *net.IPNet
if _, cidr, err = net.ParseCIDR(ipnetStr); err == nil {
*ipnet = NetIPNet(*cidr)
}
}
return
}
// IndexInfo contains information about a registry
//
// RepositoryInfo Examples:
// {
// "Index" : {
// "Name" : "docker.io",
// "Mirrors" : ["https://registry-2.docker.io/v1/", "https://registry-3.docker.io/v1/"],
// "Secure" : true,
// "Official" : true,
// },
// "RemoteName" : "library/debian",
// "LocalName" : "debian",
// "CanonicalName" : "docker.io/debian"
// "Official" : true,
// }
//
// {
// "Index" : {
// "Name" : "127.0.0.1:5000",
// "Mirrors" : [],
// "Secure" : false,
// "Official" : false,
// },
// "RemoteName" : "user/repo",
// "LocalName" : "127.0.0.1:5000/user/repo",
// "CanonicalName" : "127.0.0.1:5000/user/repo",
// "Official" : false,
// }
type IndexInfo struct {
// Name is the name of the registry, such as "docker.io"
Name string
// Mirrors is a list of mirrors, expressed as URIs
Mirrors []string
// Secure is set to false if the registry is part of the list of
// insecure registries. Insecure registries accept HTTP and/or accept
// HTTPS with certificates from unknown CAs.
Secure bool
// Official indicates whether this is an official registry
Official bool
}
// SearchResult describes a search result returned from a registry
type SearchResult struct {
// StarCount indicates the number of stars this repository has
StarCount int `json:"star_count"`
// IsOfficial is true if the result is from an official repository.
IsOfficial bool `json:"is_official"`
// Name is the name of the repository
Name string `json:"name"`
// IsAutomated indicates whether the result is automated
IsAutomated bool `json:"is_automated"`
// Description is a textual description of the repository
Description string `json:"description"`
}
// SearchResults lists a collection search results returned from a registry
type SearchResults struct {
// Query contains the query string that generated the search results
Query string `json:"query"`
// NumResults indicates the number of results the query returned
NumResults int `json:"num_results"`
// Results is a slice containing the actual results for the search
Results []SearchResult `json:"results"`
}

View File

@ -1,68 +0,0 @@
package types
// Seccomp represents the config for a seccomp profile for syscall restriction.
type Seccomp struct {
DefaultAction Action `json:"defaultAction"`
Architectures []Arch `json:"architectures"`
Syscalls []*Syscall `json:"syscalls"`
}
// Arch used for additional architectures
type Arch string
// Additional architectures permitted to be used for system calls
// By default only the native architecture of the kernel is permitted
const (
ArchX86 Arch = "SCMP_ARCH_X86"
ArchX86_64 Arch = "SCMP_ARCH_X86_64"
ArchX32 Arch = "SCMP_ARCH_X32"
ArchARM Arch = "SCMP_ARCH_ARM"
ArchAARCH64 Arch = "SCMP_ARCH_AARCH64"
ArchMIPS Arch = "SCMP_ARCH_MIPS"
ArchMIPS64 Arch = "SCMP_ARCH_MIPS64"
ArchMIPS64N32 Arch = "SCMP_ARCH_MIPS64N32"
ArchMIPSEL Arch = "SCMP_ARCH_MIPSEL"
ArchMIPSEL64 Arch = "SCMP_ARCH_MIPSEL64"
ArchMIPSEL64N32 Arch = "SCMP_ARCH_MIPSEL64N32"
)
// Action taken upon Seccomp rule match
type Action string
// Define actions for Seccomp rules
const (
ActKill Action = "SCMP_ACT_KILL"
ActTrap Action = "SCMP_ACT_TRAP"
ActErrno Action = "SCMP_ACT_ERRNO"
ActTrace Action = "SCMP_ACT_TRACE"
ActAllow Action = "SCMP_ACT_ALLOW"
)
// Operator used to match syscall arguments in Seccomp
type Operator string
// Define operators for syscall arguments in Seccomp
const (
OpNotEqual Operator = "SCMP_CMP_NE"
OpLessThan Operator = "SCMP_CMP_LT"
OpLessEqual Operator = "SCMP_CMP_LE"
OpEqualTo Operator = "SCMP_CMP_EQ"
OpGreaterEqual Operator = "SCMP_CMP_GE"
OpGreaterThan Operator = "SCMP_CMP_GT"
OpMaskedEqual Operator = "SCMP_CMP_MASKED_EQ"
)
// Arg used for matching specific syscall arguments in Seccomp
type Arg struct {
Index uint `json:"index"`
Value uint64 `json:"value"`
ValueTwo uint64 `json:"valueTwo"`
Op Operator `json:"op"`
}
// Syscall is used to match a syscall in Seccomp
type Syscall struct {
Name string `json:"name"`
Action Action `json:"action"`
Args []*Arg `json:"args"`
}

View File

@ -1,115 +0,0 @@
// Package types is used for API stability in the types and response to the
// consumers of the API stats endpoint.
package types
import "time"
// ThrottlingData stores CPU throttling stats of one running container
type ThrottlingData struct {
// Number of periods with throttling active
Periods uint64 `json:"periods"`
// Number of periods when the container hits its throttling limit.
ThrottledPeriods uint64 `json:"throttled_periods"`
// Aggregate time the container was throttled for in nanoseconds.
ThrottledTime uint64 `json:"throttled_time"`
}
// CPUUsage stores All CPU stats aggregated since container inception.
type CPUUsage struct {
// Total CPU time consumed.
// Units: nanoseconds.
TotalUsage uint64 `json:"total_usage"`
// Total CPU time consumed per core.
// Units: nanoseconds.
PercpuUsage []uint64 `json:"percpu_usage"`
// Time spent by tasks of the cgroup in kernel mode.
// Units: nanoseconds.
UsageInKernelmode uint64 `json:"usage_in_kernelmode"`
// Time spent by tasks of the cgroup in user mode.
// Units: nanoseconds.
UsageInUsermode uint64 `json:"usage_in_usermode"`
}
// CPUStats aggregates and wraps all CPU related info of container
type CPUStats struct {
CPUUsage CPUUsage `json:"cpu_usage"`
SystemUsage uint64 `json:"system_cpu_usage"`
ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
}
// MemoryStats aggregates All memory stats since container inception
type MemoryStats struct {
// current res_counter usage for memory
Usage uint64 `json:"usage"`
// maximum usage ever recorded.
MaxUsage uint64 `json:"max_usage"`
// TODO(vishh): Export these as stronger types.
// all the stats exported via memory.stat.
Stats map[string]uint64 `json:"stats"`
// number of times memory usage hits limits.
Failcnt uint64 `json:"failcnt"`
Limit uint64 `json:"limit"`
}
// BlkioStatEntry is one small entity to store a piece of Blkio stats
// TODO Windows: This can be factored out
type BlkioStatEntry struct {
Major uint64 `json:"major"`
Minor uint64 `json:"minor"`
Op string `json:"op"`
Value uint64 `json:"value"`
}
// BlkioStats stores All IO service stats for data read and write
// TODO Windows: This can be factored out
type BlkioStats struct {
// number of bytes transferred to and from the block device
IoServiceBytesRecursive []BlkioStatEntry `json:"io_service_bytes_recursive"`
IoServicedRecursive []BlkioStatEntry `json:"io_serviced_recursive"`
IoQueuedRecursive []BlkioStatEntry `json:"io_queue_recursive"`
IoServiceTimeRecursive []BlkioStatEntry `json:"io_service_time_recursive"`
IoWaitTimeRecursive []BlkioStatEntry `json:"io_wait_time_recursive"`
IoMergedRecursive []BlkioStatEntry `json:"io_merged_recursive"`
IoTimeRecursive []BlkioStatEntry `json:"io_time_recursive"`
SectorsRecursive []BlkioStatEntry `json:"sectors_recursive"`
}
// NetworkStats aggregates All network stats of one container
// TODO Windows: This will require refactoring
type NetworkStats struct {
RxBytes uint64 `json:"rx_bytes"`
RxPackets uint64 `json:"rx_packets"`
RxErrors uint64 `json:"rx_errors"`
RxDropped uint64 `json:"rx_dropped"`
TxBytes uint64 `json:"tx_bytes"`
TxPackets uint64 `json:"tx_packets"`
TxErrors uint64 `json:"tx_errors"`
TxDropped uint64 `json:"tx_dropped"`
}
// PidsStats contains the stats of a container's pids
type PidsStats struct {
// Current is the number of pids in the cgroup
Current uint64 `json:"current,omitempty"`
// Limit is the hard limit on the number of pids in the cgroup.
// A "Limit" of 0 means that there is no limit.
Limit uint64 `json:"limit,omitempty"`
}
// Stats is Ultimate struct aggregating all types of stats of one container
type Stats struct {
Read time.Time `json:"read"`
PreCPUStats CPUStats `json:"precpu_stats,omitempty"`
CPUStats CPUStats `json:"cpu_stats,omitempty"`
MemoryStats MemoryStats `json:"memory_stats,omitempty"`
BlkioStats BlkioStats `json:"blkio_stats,omitempty"`
PidsStats PidsStats `json:"pids_stats,omitempty"`
}
// StatsJSON is newly used Networks
type StatsJSON struct {
Stats
// Networks request version >=1.21
Networks map[string]NetworkStats `json:"networks,omitempty"`
}

View File

@ -1,22 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["strslice.go"],
importpath = "github.com/docker/engine-api/types/strslice",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

Some files were not shown because too many files have changed in this diff Show More