From e2228f1b0b6bc078a1dc4662f1e08fb515a76a6a Mon Sep 17 00:00:00 2001 From: Simon Aronsson Date: Wed, 17 Apr 2019 21:28:48 +0200 Subject: [PATCH] improve test coverage and add an api-server mock --- container/client.go | 2 +- container/client_test.go | 15 -- container/container_test.go | 47 +++- container/mocks/ApiServer.go | 49 ++++ container/mocks/data/container_running.json | 233 ++++++++++++++++++++ container/mocks/data/container_stopped.json | 205 +++++++++++++++++ container/mocks/data/containers.json | 113 ++++++++++ container/mocks/data/image01.json | 99 +++++++++ container/mocks/data/image02.json | 92 ++++++++ 9 files changed, 836 insertions(+), 19 deletions(-) delete mode 100644 container/client_test.go create mode 100644 container/mocks/ApiServer.go create mode 100644 container/mocks/data/container_running.json create mode 100644 container/mocks/data/container_stopped.json create mode 100644 container/mocks/data/containers.json create mode 100644 container/mocks/data/image01.json create mode 100644 container/mocks/data/image02.json diff --git a/container/client.go b/container/client.go index 9afda01..94f790e 100644 --- a/container/client.go +++ b/container/client.go @@ -44,7 +44,7 @@ func NewClient(pullImages bool) Client { } type dockerClient struct { - api *dockerclient.Client + api dockerclient.CommonAPIClient pullImages bool } diff --git a/container/client_test.go b/container/client_test.go deleted file mode 100644 index ab3df0d..0000000 --- a/container/client_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package container - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("the client", func() { - When("creating a new client", func() { - It("should return a client for the api", func() { - client := NewClient(false) - Expect(client).NotTo(BeNil()) - }) - }) -}) \ No newline at end of file diff --git a/container/container_test.go b/container/container_test.go index 939ced5..47ec8e0 100644 --- a/container/container_test.go +++ b/container/container_test.go @@ -1,11 +1,13 @@ package container import ( + "github.com/containrrr/watchtower/container/mocks" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" - "testing" + cli "github.com/docker/docker/client" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "testing" ) func TestContainer(t *testing.T) { @@ -14,7 +16,46 @@ func TestContainer(t *testing.T) { } var _ = Describe("the container", func() { - + Describe("the client", func() { + var client Client + BeforeSuite(func() { + server := mocks.NewMockApiServer() + c, _ := cli.NewClientWithOpts( + cli.WithHost(server.URL), + cli.WithHTTPClient(server.Client(), + )) + client = dockerClient{ + api: c, + pullImages: false, + } + }) + It("should return a client for the api", func() { + Expect(client).NotTo(BeNil()) + }) + When("listing containers without any filter", func() { + It("should return all available containers", func() { + containers, err := client.ListContainers(noFilter) + Expect(err).NotTo(HaveOccurred()) + Expect(len(containers) == 2).To(BeTrue()) + }) + }) + When("listing containers with a filter matching nothing", func() { + It("should return an empty array", func() { + filter := filterByNames([]string { "lollercoaster"}, noFilter) + containers, err := client.ListContainers(filter) + Expect(err).NotTo(HaveOccurred()) + Expect(len(containers) == 0).To(BeTrue()) + }) + }) + When("listing containers with a watchtower filter", func() { + It("should return only the watchtower container", func() { + containers, err := client.ListContainers(WatchtowerContainersFilter) + Expect(err).NotTo(HaveOccurred()) + Expect(len(containers) == 1).To(BeTrue()) + Expect(containers[0].ImageName()).To(Equal("containrrr/watchtower:latest")) + }) + }) + }) When("asked for metadata", func() { var c *Container BeforeEach(func() { @@ -148,4 +189,4 @@ func mockContainerWithLabels(labels map[string]string) *Container { }, } return NewContainer(&content, nil) -} \ No newline at end of file +} diff --git a/container/mocks/ApiServer.go b/container/mocks/ApiServer.go new file mode 100644 index 0000000..f63b93b --- /dev/null +++ b/container/mocks/ApiServer.go @@ -0,0 +1,49 @@ +package mocks + +import ( + "fmt" + "github.com/sirupsen/logrus" + "io/ioutil" + "net/http" + "net/http/httptest" + "path/filepath" + "strings" +) + +func NewMockApiServer() *httptest.Server { + return httptest.NewServer(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + logrus.Debug("Mock server has received a HTTP call on ", r.URL) + var response = "" + + if isRequestFor("containers/json?limit=0", r) { + response = getMockJsonFromDisk("./mocks/data/containers.json") + } else if isRequestFor("ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65", r) { + response = getMockJsonFromDisk("./mocks/data/container_stopped.json") + } else if isRequestFor("b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008", r) { + response = getMockJsonFromDisk("./mocks/data/container_running.json") + } else if isRequestFor("sha256:19d07168491a3f9e2798a9bed96544e34d57ddc4757a4ac5bb199dea896c87fd", r) { + response = getMockJsonFromDisk("./mocks/data/image01.json") + } else if isRequestFor("sha256:4dbc5f9c07028a985e14d1393e849ea07f68804c4293050d5a641b138db72daa", r) { + response = getMockJsonFromDisk("./mocks/data/image02.json") + } + fmt.Fprintln(w, response) + }, + )) +} + +func isRequestFor(urlPart string, r *http.Request) bool { + return strings.Contains(r.URL.String(), urlPart) +} + +func getMockJsonFromDisk(relPath string) string { + absPath, _ := filepath.Abs(relPath) + logrus.Error(absPath) + buf, err := ioutil.ReadFile(absPath) + if err != nil { + logrus.Error(err) + return "" + } + return string(buf) +} + diff --git a/container/mocks/data/container_running.json b/container/mocks/data/container_running.json new file mode 100644 index 0000000..2d78bb3 --- /dev/null +++ b/container/mocks/data/container_running.json @@ -0,0 +1,233 @@ +{ + "Id": "b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008", + "Created": "2019-04-04T20:28:32.5710901Z", + "Path": "/portainer", + "Args": [], + "State": { + "Status": "running", + "Running": true, + "Paused": false, + "Restarting": false, + "OOMKilled": false, + "Dead": false, + "Pid": 3854, + "ExitCode": 0, + "Error": "", + "StartedAt": "2019-04-13T22:38:24.498745809Z", + "FinishedAt": "2019-04-13T22:38:18.486292076Z" + }, + "Image": "sha256:19d07168491a3f9e2798a9bed96544e34d57ddc4757a4ac5bb199dea896c87fd", + "ResolvConfPath": "/var/lib/docker/containers/b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008/resolv.conf", + "HostnamePath": "/var/lib/docker/containers/b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008/hostname", + "HostsPath": "/var/lib/docker/containers/b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008/hosts", + "LogPath": "/var/lib/docker/containers/b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008/b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008-json.log", + "Name": "/portainer", + "RestartCount": 0, + "Driver": "overlay2", + "Platform": "linux", + "MountLabel": "", + "ProcessLabel": "", + "AppArmorProfile": "", + "ExecIDs": null, + "HostConfig": { + "Binds": [ + "portainer_data:/data", + "/var/run/docker.sock:/var/run/docker.sock" + ], + "ContainerIDFile": "", + "LogConfig": { + "Type": "json-file", + "Config": {} + }, + "NetworkMode": "default", + "PortBindings": { + "9000/tcp": [ + { + "HostIp": "", + "HostPort": "9000" + } + ] + }, + "RestartPolicy": { + "Name": "always", + "MaximumRetryCount": 0 + }, + "AutoRemove": false, + "VolumeDriver": "", + "VolumesFrom": null, + "CapAdd": null, + "CapDrop": null, + "Dns": [], + "DnsOptions": [], + "DnsSearch": [], + "ExtraHosts": null, + "GroupAdd": null, + "IpcMode": "shareable", + "Cgroup": "", + "Links": null, + "OomScoreAdj": 0, + "PidMode": "", + "Privileged": false, + "PublishAllPorts": false, + "ReadonlyRootfs": false, + "SecurityOpt": null, + "UTSMode": "", + "UsernsMode": "", + "ShmSize": 67108864, + "Runtime": "runc", + "ConsoleSize": [ + 0, + 0 + ], + "Isolation": "", + "CpuShares": 0, + "Memory": 0, + "NanoCpus": 0, + "CgroupParent": "", + "BlkioWeight": 0, + "BlkioWeightDevice": [], + "BlkioDeviceReadBps": null, + "BlkioDeviceWriteBps": null, + "BlkioDeviceReadIOps": null, + "BlkioDeviceWriteIOps": null, + "CpuPeriod": 0, + "CpuQuota": 0, + "CpuRealtimePeriod": 0, + "CpuRealtimeRuntime": 0, + "CpusetCpus": "", + "CpusetMems": "", + "Devices": [], + "DeviceCgroupRules": null, + "DiskQuota": 0, + "KernelMemory": 0, + "MemoryReservation": 0, + "MemorySwap": 0, + "MemorySwappiness": null, + "OomKillDisable": false, + "PidsLimit": 0, + "Ulimits": null, + "CpuCount": 0, + "CpuPercent": 0, + "IOMaximumIOps": 0, + "IOMaximumBandwidth": 0, + "MaskedPaths": [ + "/proc/asound", + "/proc/acpi", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/proc/scsi", + "/sys/firmware" + ], + "ReadonlyPaths": [ + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ] + }, + "GraphDriver": { + "Data": { + "LowerDir": "/var/lib/docker/overlay2/99dedacb757cd8c70ccacbc4b57dd85cb34b1b6fcfd2fd1176332ce5dfa1d38c-init/diff:/var/lib/docker/overlay2/2e0c03c2476f5b4df855cb8b02a88f76d336d7e0becc3e5193906aaa760687fd/diff:/var/lib/docker/overlay2/6c3f44131f6f13c9ea1a99a1b24bf348f70ba3eef244f29202faef3a2216ac11/diff", + "MergedDir": "/var/lib/docker/overlay2/99dedacb757cd8c70ccacbc4b57dd85cb34b1b6fcfd2fd1176332ce5dfa1d38c/merged", + "UpperDir": "/var/lib/docker/overlay2/99dedacb757cd8c70ccacbc4b57dd85cb34b1b6fcfd2fd1176332ce5dfa1d38c/diff", + "WorkDir": "/var/lib/docker/overlay2/99dedacb757cd8c70ccacbc4b57dd85cb34b1b6fcfd2fd1176332ce5dfa1d38c/work" + }, + "Name": "overlay2" + }, + "Mounts": [ + { + "Type": "volume", + "Name": "portainer_data", + "Source": "/var/lib/docker/volumes/portainer_data/_data", + "Destination": "/data", + "Driver": "local", + "Mode": "z", + "RW": true, + "Propagation": "" + }, + { + "Type": "bind", + "Source": "/var/run/docker.sock", + "Destination": "/var/run/docker.sock", + "Mode": "", + "RW": true, + "Propagation": "rprivate" + } + ], + "Config": { + "Hostname": "822f0f2efd78", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "ExposedPorts": { + "9000/tcp": {} + }, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": null, + "Image": "portainer/portainer:latest", + "Volumes": { + "/data": {} + }, + "WorkingDir": "/", + "Entrypoint": [ + "/portainer" + ], + "OnBuild": null, + "Labels": {} + }, + "NetworkSettings": { + "Bridge": "", + "SandboxID": "8819e19588be798020f2d09e36a577c39a47809e68c2769a1525880c0bcd5b11", + "HairpinMode": false, + "LinkLocalIPv6Address": "", + "LinkLocalIPv6PrefixLen": 0, + "Ports": { + "9000/tcp": [ + { + "HostIp": "0.0.0.0", + "HostPort": "9000" + } + ] + }, + "SandboxKey": "/var/run/docker/netns/8819e19588be", + "SecondaryIPAddresses": null, + "SecondaryIPv6Addresses": null, + "EndpointID": "a8bcd737f27edb4d2955f7bce0c777bb2990b792a6b335b0727387624abe0702", + "Gateway": "172.17.0.1", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "IPAddress": "172.17.0.2", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "MacAddress": "02:42:ac:11:00:02", + "Networks": { + "bridge": { + "IPAMConfig": null, + "Links": null, + "Aliases": null, + "NetworkID": "9352796e0330dcf31ce3d44fae4b719304b8b3fd97b02ade3aefb8737251682b", + "EndpointID": "a8bcd737f27edb4d2955f7bce0c777bb2990b792a6b335b0727387624abe0702", + "Gateway": "172.17.0.1", + "IPAddress": "172.17.0.2", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "MacAddress": "02:42:ac:11:00:02", + "DriverOpts": null + } + } + } +} diff --git a/container/mocks/data/container_stopped.json b/container/mocks/data/container_stopped.json new file mode 100644 index 0000000..a4519d7 --- /dev/null +++ b/container/mocks/data/container_stopped.json @@ -0,0 +1,205 @@ +{ + "Id": "ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65", + "Created": "2019-04-10T19:51:22.245041005Z", + "Path": "/watchtower", + "Args": [], + "State": { + "Status": "exited", + "Running": false, + "Paused": false, + "Restarting": false, + "OOMKilled": false, + "Dead": false, + "Pid": 0, + "ExitCode": 1, + "Error": "", + "StartedAt": "2019-04-10T19:51:22.918972606Z", + "FinishedAt": "2019-04-10T19:52:14.265091583Z" + }, + "Image": "sha256:4dbc5f9c07028a985e14d1393e849ea07f68804c4293050d5a641b138db72daa", + "ResolvConfPath": "/var/lib/docker/containers/ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65/resolv.conf", + "HostnamePath": "/var/lib/docker/containers/ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65/hostname", + "HostsPath": "/var/lib/docker/containers/ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65/hosts", + "LogPath": "/var/lib/docker/containers/ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65/ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65-json.log", + "Name": "/watchtower-test", + "RestartCount": 0, + "Driver": "overlay2", + "Platform": "linux", + "MountLabel": "", + "ProcessLabel": "", + "AppArmorProfile": "", + "ExecIDs": null, + "HostConfig": { + "Binds": [ + "/var/run/docker.sock:/var/run/docker.sock" + ], + "ContainerIDFile": "", + "LogConfig": { + "Type": "json-file", + "Config": {} + }, + "NetworkMode": "default", + "PortBindings": {}, + "RestartPolicy": { + "Name": "no", + "MaximumRetryCount": 0 + }, + "AutoRemove": false, + "VolumeDriver": "", + "VolumesFrom": null, + "CapAdd": null, + "CapDrop": null, + "Dns": [], + "DnsOptions": [], + "DnsSearch": [], + "ExtraHosts": null, + "GroupAdd": null, + "IpcMode": "shareable", + "Cgroup": "", + "Links": null, + "OomScoreAdj": 0, + "PidMode": "", + "Privileged": false, + "PublishAllPorts": false, + "ReadonlyRootfs": false, + "SecurityOpt": null, + "UTSMode": "", + "UsernsMode": "", + "ShmSize": 67108864, + "Runtime": "runc", + "ConsoleSize": [ + 0, + 0 + ], + "Isolation": "", + "CpuShares": 0, + "Memory": 0, + "NanoCpus": 0, + "CgroupParent": "", + "BlkioWeight": 0, + "BlkioWeightDevice": [], + "BlkioDeviceReadBps": null, + "BlkioDeviceWriteBps": null, + "BlkioDeviceReadIOps": null, + "BlkioDeviceWriteIOps": null, + "CpuPeriod": 0, + "CpuQuota": 0, + "CpuRealtimePeriod": 0, + "CpuRealtimeRuntime": 0, + "CpusetCpus": "", + "CpusetMems": "", + "Devices": [], + "DeviceCgroupRules": null, + "DiskQuota": 0, + "KernelMemory": 0, + "MemoryReservation": 0, + "MemorySwap": 0, + "MemorySwappiness": null, + "OomKillDisable": false, + "PidsLimit": 0, + "Ulimits": null, + "CpuCount": 0, + "CpuPercent": 0, + "IOMaximumIOps": 0, + "IOMaximumBandwidth": 0, + "MaskedPaths": [ + "/proc/asound", + "/proc/acpi", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/proc/scsi", + "/sys/firmware" + ], + "ReadonlyPaths": [ + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ] + }, + "GraphDriver": { + "Data": { + "LowerDir": "/var/lib/docker/overlay2/9f6b91ea6e142835035d91123bbc7a05224dfa2abd4d020eac42f2ab420ccddc-init/diff:/var/lib/docker/overlay2/cdf82f50bc49177d0c17c24f3eaa29eba607b70cc6a081f77781b21c59a13eb8/diff:/var/lib/docker/overlay2/8108325ee844603c9b08d2772cf6e65dccf31dd5171f265078e5ed79a0ba3c0f/diff:/var/lib/docker/overlay2/e5e0cce6bf91b829a308424d99d7e56a33be3a11414ff5cdc48e762a1342b20f/diff", + "MergedDir": "/var/lib/docker/overlay2/9f6b91ea6e142835035d91123bbc7a05224dfa2abd4d020eac42f2ab420ccddc/merged", + "UpperDir": "/var/lib/docker/overlay2/9f6b91ea6e142835035d91123bbc7a05224dfa2abd4d020eac42f2ab420ccddc/diff", + "WorkDir": "/var/lib/docker/overlay2/9f6b91ea6e142835035d91123bbc7a05224dfa2abd4d020eac42f2ab420ccddc/work" + }, + "Name": "overlay2" + }, + "Mounts": [ + { + "Type": "bind", + "Source": "/var/run/docker.sock", + "Destination": "/var/run/docker.sock", + "Mode": "", + "RW": true, + "Propagation": "rprivate" + } + ], + "Config": { + "Hostname": "ae8964ba86c7", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": true, + "AttachStderr": true, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": null, + "Image": "containrrr/watchtower:latest", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": [ + "/watchtower" + ], + "OnBuild": null, + "Labels": { + "com.centurylinklabs.watchtower": "true" + } + }, + "NetworkSettings": { + "Bridge": "", + "SandboxID": "05627d36c08ed994eebc44a2a8c9365a511756b55c500fb03fd5a14477cd4bf3", + "HairpinMode": false, + "LinkLocalIPv6Address": "", + "LinkLocalIPv6PrefixLen": 0, + "Ports": {}, + "SandboxKey": "/var/run/docker/netns/05627d36c08e", + "SecondaryIPAddresses": null, + "SecondaryIPv6Addresses": null, + "EndpointID": "", + "Gateway": "", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "IPAddress": "", + "IPPrefixLen": 0, + "IPv6Gateway": "", + "MacAddress": "", + "Networks": { + "bridge": { + "IPAMConfig": null, + "Links": null, + "Aliases": null, + "NetworkID": "8fcfd56fa9203bafa98510abb08bff66ad05bef5b6e97d158cbae3397e1e065e", + "EndpointID": "", + "Gateway": "", + "IPAddress": "", + "IPPrefixLen": 0, + "IPv6Gateway": "", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "MacAddress": "", + "DriverOpts": null + } + } + } +} diff --git a/container/mocks/data/containers.json b/container/mocks/data/containers.json new file mode 100644 index 0000000..a40cbf3 --- /dev/null +++ b/container/mocks/data/containers.json @@ -0,0 +1,113 @@ +[ + { + "Id": "ae8964ba86c7cd7522cf84e09781343d88e0e3543281c747d88b27e246578b65", + "Names": [ + "/watchtower-test" + ], + "Image": "containrrr/watchtower:latest", + "ImageID": "sha256:4dbc5f9c07028a985e14d1393e849ea07f68804c4293050d5a641b138db72daa", + "Command": "/watchtower", + "Created": 1554925882, + "Ports": [], + "Labels": { + "com.centurylinklabs.watchtower": "true" + }, + "State": "exited", + "Status": "Exited (1) 6 days ago", + "HostConfig": { + "NetworkMode": "default" + }, + "NetworkSettings": { + "Networks": { + "bridge": { + "IPAMConfig": null, + "Links": null, + "Aliases": null, + "NetworkID": "8fcfd56fa9203bafa98510abb08bff66ad05bef5b6e97d158cbae3397e1e065e", + "EndpointID": "", + "Gateway": "", + "IPAddress": "", + "IPPrefixLen": 0, + "IPv6Gateway": "", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "MacAddress": "", + "DriverOpts": null + } + } + }, + "Mounts": [ + { + "Type": "bind", + "Source": "/var/run/docker.sock", + "Destination": "/var/run/docker.sock", + "Mode": "", + "RW": true, + "Propagation": "rprivate" + } + ] + }, + { + "Id": "b978af0b858aa8855cce46b628817d4ed58e58f2c4f66c9b9c5449134ed4c008", + "Names": [ + "/portainer" + ], + "Image": "portainer/portainer:latest", + "ImageID": "sha256:19d07168491a3f9e2798a9bed96544e34d57ddc4757a4ac5bb199dea896c87fd", + "Command": "/portainer", + "Created": 1554409712, + "Ports": [ + { + "IP": "0.0.0.0", + "PrivatePort": 9000, + "PublicPort": 9000, + "Type": "tcp" + } + ], + "Labels": {}, + "State": "running", + "Status": "Up 3 days", + "HostConfig": { + "NetworkMode": "default" + }, + "NetworkSettings": { + "Networks": { + "bridge": { + "IPAMConfig": null, + "Links": null, + "Aliases": null, + "NetworkID": "9352796e0330dcf31ce3d44fae4b719304b8b3fd97b02ade3aefb8737251682b", + "EndpointID": "a8bcd737f27edb4d2955f7bce0c777bb2990b792a6b335b0727387624abe0702", + "Gateway": "172.17.0.1", + "IPAddress": "172.17.0.2", + "IPPrefixLen": 16, + "IPv6Gateway": "", + "GlobalIPv6Address": "", + "GlobalIPv6PrefixLen": 0, + "MacAddress": "02:42:ac:11:00:02", + "DriverOpts": null + } + } + }, + "Mounts": [ + { + "Type": "volume", + "Name": "portainer_data", + "Source": "/var/lib/docker/volumes/portainer_data/_data", + "Destination": "/data", + "Driver": "local", + "Mode": "z", + "RW": true, + "Propagation": "" + }, + { + "Type": "bind", + "Source": "/var/run/docker.sock", + "Destination": "/var/run/docker.sock", + "Mode": "", + "RW": true, + "Propagation": "rprivate" + } + ] + } +] diff --git a/container/mocks/data/image01.json b/container/mocks/data/image01.json new file mode 100644 index 0000000..685d087 --- /dev/null +++ b/container/mocks/data/image01.json @@ -0,0 +1,99 @@ +{ + "Id": "sha256:19d07168491a3f9e2798a9bed96544e34d57ddc4757a4ac5bb199dea896c87fd", + "RepoTags": [ + "portainer/portainer:latest" + ], + "RepoDigests": [ + "portainer/portainer@sha256:d6cc2c20c0af38d8d557ab994c419c799a10fe825e4aa57fea2e2e507a13747d" + ], + "Parent": "", + "Comment": "", + "Created": "2019-03-05T04:41:17.612066939Z", + "Container": "022100cf79dfee27867d5ff7aa3ff7ecc5cbd486747e808a59b6accd393d65f5", + "ContainerConfig": { + "Hostname": "022100cf79df", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "ExposedPorts": { + "9000/tcp": {} + }, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ", + "ENTRYPOINT [\"/portainer\"]" + ], + "Image": "sha256:9cf3ead5068a16f1bc1e18d6e730940f05fd59f60dfe1f6b3a5956196191dc77", + "Volumes": { + "/data": {} + }, + "WorkingDir": "/", + "Entrypoint": [ + "/portainer" + ], + "OnBuild": null, + "Labels": {} + }, + "DockerVersion": "18.09.2", + "Author": "", + "Config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "ExposedPorts": { + "9000/tcp": {} + }, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": null, + "Image": "sha256:9cf3ead5068a16f1bc1e18d6e730940f05fd59f60dfe1f6b3a5956196191dc77", + "Volumes": { + "/data": {} + }, + "WorkingDir": "/", + "Entrypoint": [ + "/portainer" + ], + "OnBuild": null, + "Labels": null + }, + "Architecture": "amd64", + "Os": "linux", + "Size": 74089106, + "VirtualSize": 74089106, + "GraphDriver": { + "Data": { + "LowerDir": "/var/lib/docker/overlay2/6c3f44131f6f13c9ea1a99a1b24bf348f70ba3eef244f29202faef3a2216ac11/diff", + "MergedDir": "/var/lib/docker/overlay2/2e0c03c2476f5b4df855cb8b02a88f76d336d7e0becc3e5193906aaa760687fd/merged", + "UpperDir": "/var/lib/docker/overlay2/2e0c03c2476f5b4df855cb8b02a88f76d336d7e0becc3e5193906aaa760687fd/diff", + "WorkDir": "/var/lib/docker/overlay2/2e0c03c2476f5b4df855cb8b02a88f76d336d7e0becc3e5193906aaa760687fd/work" + }, + "Name": "overlay2" + }, + "RootFS": { + "Type": "layers", + "Layers": [ + "sha256:dd4969f97241b9aefe2a70f560ce399ee9fa0354301c9aef841082ad52161ec5", + "sha256:e7260fd2a5f240122129b2d421726d7a4a2bda0cc292e962b694196af8856f20" + ] + }, + "Metadata": { + "LastTagTime": "0001-01-01T00:00:00Z" + } +} diff --git a/container/mocks/data/image02.json b/container/mocks/data/image02.json new file mode 100644 index 0000000..64850ba --- /dev/null +++ b/container/mocks/data/image02.json @@ -0,0 +1,92 @@ +{ + "Id": "sha256:4dbc5f9c07028a985e14d1393e849ea07f68804c4293050d5a641b138db72daa", + "RepoTags": [ + "containrrr/watchtower:latest" + ], + "RepoDigests": [], + "Parent": "sha256:2753b9621e0d76153e1725d0cea015baf0ae4d829782a463b4ea9532ec976447", + "Comment": "", + "Created": "2019-04-10T19:49:07.970840451Z", + "Container": "b8387976426946f5c5191255204a66514c5e64be157f792c5bac329bb055041c", + "ContainerConfig": { + "Hostname": "b83879764269", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": [ + "/bin/sh", + "-c", + "#(nop) ", + "ENTRYPOINT [\"/watchtower\"]" + ], + "Image": "sha256:2753b9621e0d76153e1725d0cea015baf0ae4d829782a463b4ea9532ec976447", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": [ + "/watchtower" + ], + "OnBuild": null, + "Labels": { + "com.centurylinklabs.watchtower": "true" + } + }, + "DockerVersion": "18.09.1", + "Author": "", + "Config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + ], + "Cmd": null, + "Image": "sha256:2753b9621e0d76153e1725d0cea015baf0ae4d829782a463b4ea9532ec976447", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": [ + "/watchtower" + ], + "OnBuild": null, + "Labels": { + "com.centurylinklabs.watchtower": "true" + } + }, + "Architecture": "amd64", + "Os": "linux", + "Size": 13005733, + "VirtualSize": 13005733, + "GraphDriver": { + "Data": { + "LowerDir": "/var/lib/docker/overlay2/8108325ee844603c9b08d2772cf6e65dccf31dd5171f265078e5ed79a0ba3c0f/diff:/var/lib/docker/overlay2/e5e0cce6bf91b829a308424d99d7e56a33be3a11414ff5cdc48e762a1342b20f/diff", + "MergedDir": "/var/lib/docker/overlay2/cdf82f50bc49177d0c17c24f3eaa29eba607b70cc6a081f77781b21c59a13eb8/merged", + "UpperDir": "/var/lib/docker/overlay2/cdf82f50bc49177d0c17c24f3eaa29eba607b70cc6a081f77781b21c59a13eb8/diff", + "WorkDir": "/var/lib/docker/overlay2/cdf82f50bc49177d0c17c24f3eaa29eba607b70cc6a081f77781b21c59a13eb8/work" + }, + "Name": "overlay2" + }, + "RootFS": { + "Type": "layers", + "Layers": [ + "sha256:1d3ad125af2c636cdd793fcf94c9d4fd2b5c4c7d63a770a01056719db13c2271", + "sha256:06cfe8fe0892ba4a91cb93e3a25344d4a1c4771cf7297a93e3bd86a1e0fba6eb", + "sha256:f58d451769dc30a938d8dcae22fda2acd816899f65fc6b6fa519ddf230dab447" + ] + }, + "Metadata": { + "LastTagTime": "2019-04-10T19:49:08.03921105Z" + } +}