diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index f3e5a5e..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,5 +0,0 @@
-FROM golang:1.7.0
-
-RUN apt-get update
-COPY . /go/src/github.com/remind101/dockerdog
-RUN go install github.com/remind101/dockerdog/...
diff --git a/Makefile b/Makefile
index e06119b..d0d5233 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,21 @@
-bin/dockerdog: *.go
- docker build -t remind101/dockerdog .
- docker cp $(shell docker create remind101/dockerdog):/go/bin/dockerdog bin/
+.PHONY: all fmt check lint test bin/dockerdog
+.DEFAULT_GOAL: all
+
+export CGO_ENABLED=0
+
+all: check bin/dockerdog
+
+fmt:
+ go fmt ./...
+
+check: lint test
+
+lint:
+ @test -z $(shell gofmt -l . | tee /dev/stderr) || { echo "files above are not go fmt"; exit 1; }
+ go vet ./...
+
+test:
+ go test ./...
+
+bin/dockerdog:
+ go build -ldflags '-extldflags "-static"' -o $@ .
diff --git a/README.md b/README.md
index 1d17599..879c06c 100644
--- a/README.md
+++ b/README.md
@@ -13,40 +13,38 @@ The DataDog agent has some problems:
## Events
-DockerDog generates counters for all container and image events, and tags them with the events attributes:
-
-**Container events**
-
-```
-docker.events.container.attach
-docker.events.container.commit
-docker.events.container.copy
-docker.events.container.create
-docker.events.container.destroy
-docker.events.container.die
-docker.events.container.exec_create
-docker.events.container.exec_start
-docker.events.container.export
-docker.events.container.kill
-docker.events.container.oom
-docker.events.container.pause
-docker.events.container.rename
-docker.events.container.resize
-docker.events.container.restart
-docker.events.container.start
-docker.events.container.stop
-docker.events.container.top
-docker.events.container.unpause
-docker.events.container.update
-```
-
-**Image events**
+DockerDog generates these counter metrics for the corresponding Docker events:
+
+
+| Metric Name | Tags |
+| --- | --- |
+| `docker.events.container.attach` | |
+| `docker.events.container.create` | |
+| `docker.events.container.destroy` | |
+| `docker.events.container.detach` | |
+| `docker.events.container.die` | `exitCode` |
+| `docker.events.container.exec_create` | |
+| `docker.events.container.exec_detach` | |
+| `docker.events.container.exec_start` | |
+| `docker.events.container.kill` | `signal` |
+| `docker.events.container.oom` | |
+| `docker.events.container.start` | |
+| `docker.events.container.stop` | |
+| `docker.events.image.delete` | |
+| `docker.events.image.import` | |
+| `docker.events.image.load` | |
+| `docker.events.image.pull` | |
+| `docker.events.image.push` | |
+| `docker.events.image.save` | |
+
+
+## Tags from Event Attributes
+
+DockerDog can be configured to map event attributes to metric tags. For
+example, the following command includes the `image` attribute as a tag with key
+`image`, and the `com.example.tags.app.name` attribute as a tag with key
+`app_name`:
```
-docker.events.image.delete
-docker.events.image.import
-docker.events.image.pull
-docker.events.image.push
-docker.events.image.tag
-docker.events.image.untag
+dockerdog -a image -a com.example.tags.app.name:app_name
```
diff --git a/config.json b/config.json
deleted file mode 100644
index 3a262e5..0000000
--- a/config.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "attributes": {
- "image": true
- },
- "events": {
- "image": {
- "actions": {
- "pull": {},
- "delete": {}
- }
- },
- "container": {
- "actions": {
- "create": {},
- "start": {},
- "stop": {},
- "attach": {},
- "detach": {},
- "destroy": {},
- "exec_create": {},
- "exec_detach": {},
- "exec_start": {},
- "die": {
- "attributes": {
- "exitCode": true
- }
- },
- "kill": {
- "attributes": {
- "signal": true
- }
- },
- "oom": {}
- }
- }
- }
-}
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..4a9b595
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,28 @@
+module github.com/remind101/dockerdog
+
+go 1.18
+
+require (
+ github.com/DataDog/datadog-go v0.0.0-20150930140741-b050cd8f4d7c
+ github.com/docker/docker v20.10.17+incompatible
+ github.com/isobit/cli v0.7.2
+)
+
+require (
+ github.com/Microsoft/go-winio v0.5.2 // indirect
+ github.com/docker/distribution v2.8.1+incompatible // indirect
+ github.com/docker/go-connections v0.4.0 // indirect
+ github.com/docker/go-units v0.3.1 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/huandu/xstrings v1.3.2 // indirect
+ github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
+ github.com/morikuni/aec v1.0.0 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
+ github.com/opencontainers/image-spec v1.0.2 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/sirupsen/logrus v1.9.0 // indirect
+ golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
+ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
+ golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
+ gotest.tools/v3 v3.3.0 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..43d8da6
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,96 @@
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
+github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
+github.com/DataDog/datadog-go v0.0.0-20150930140741-b050cd8f4d7c h1:rcRib0z9tIOYz9ZLFAhjrFPz81ksQbXk1Koyk5ue/qM=
+github.com/DataDog/datadog-go v0.0.0-20150930140741-b050cd8f4d7c/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
+github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
+github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
+github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
+github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
+github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-units v0.3.1 h1:QAFdsA6jLCnglbqE6mUsHuPcJlntY94DkxHf4deHKIU=
+github.com/docker/go-units v0.3.1/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
+github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/isobit/cli v0.7.2 h1:k+NGAcWu6RrROO6kdj5/HNdM57dW5O7gJrGxdGGfmoU=
+github.com/isobit/cli v0.7.2/go.mod h1:oYxyNBV/5MOsP2DN/0kuovB2XwAOEmDmHdIUQCGQFD0=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI=
+github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
+github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
+golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
+gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
+gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
diff --git a/main.go b/main.go
index 2f2fce8..d475e87 100644
--- a/main.go
+++ b/main.go
@@ -1,123 +1,134 @@
package main
import (
- "encoding/json"
- "flag"
+ "context"
"fmt"
- "io"
- "log"
- "os"
+ "strings"
"github.com/DataDog/datadog-go/statsd"
- "github.com/fsouza/go-dockerclient"
-)
+ "github.com/isobit/cli"
-// config represents a config file that controls what events and actions to
-// track.
-type config struct {
- // Attributes defines any global attributes to include across all events
- // and actions.
- Attributes map[string]bool `json:"attributes"`
-
- // Events configures the events that should be tracked.
- Events map[string]struct {
- // Actions configures the actions that should be tracked.
- Actions map[string]struct {
- // Attributes configures the attributes in the action
- // that should be included.
- Attributes map[string]bool `json:"attributes"`
- } `json:"actions"`
- } `json:"events"`
-}
+ dockertypes "github.com/docker/docker/api/types"
+ dockerfilters "github.com/docker/docker/api/types/filters"
+ dockerclient "github.com/docker/docker/client"
+)
-// attributes returns a map of the attributes that should be included for a
-// given action.
-func (c *config) attributes(event, action string) map[string]bool {
- attributes := make(map[string]bool)
- for k, v := range c.Attributes {
- attributes[k] = v
- }
- if e, ok := c.Events[event]; ok {
- if a, ok := e.Actions[action]; ok {
- for k, v := range a.Attributes {
- attributes[k] = v
- }
- }
- }
- return attributes
-}
+type DockerDog struct {
+ Debug bool
+ StatsdAddr string
+ AttributeTags []string `cli:"name=attribute-tag,short=a,repeatable"`
-// loadConfig parses the given json config file in r and returns a parsed
-// config.
-func loadConfig(r io.Reader) (*config, error) {
- var c config
- err := json.NewDecoder(r).Decode(&c)
- return &c, err
+ globalAttributeTags map[string]string
+ eventAttributeTags map[string]map[string]string
}
-func main() {
- if err := run(); err != nil {
- log.Fatal(err)
+func NewDockerDog() *DockerDog {
+ return &DockerDog{
+ StatsdAddr: "localhost:8125",
+ globalAttributeTags: map[string]string{},
+ eventAttributeTags: map[string]map[string]string{
+ "container.attach": {},
+ "container.create": {},
+ "container.destroy": {},
+ "container.detach": {},
+ "container.die": {"exitCode": "exitCode"},
+ "container.exec_create": {},
+ "container.exec_detach": {},
+ "container.exec_start": {},
+ "container.kill": {"signal": "signal"},
+ "container.oom": {},
+ "container.start": {},
+ "container.stop": {},
+ "image.delete": {},
+ "image.import": {},
+ "image.load": {},
+ "image.pull": {},
+ "image.push": {},
+ "image.save": {},
+ },
}
}
-func run() error {
- var (
- statsdAddr = flag.String("statsd", "localhost:8126", "Address of statsd")
- )
- flag.Parse()
- args := flag.Args()
- var r io.Reader = os.Stdin
- if len(args) > 0 {
- f, err := os.Open(args[0])
- if err != nil {
- return err
+func (cmd *DockerDog) Before() error {
+ if cmd.AttributeTags != nil {
+ for _, attrTag := range cmd.AttributeTags {
+ if attr, tag, ok := strings.Cut(attrTag, ":"); ok {
+ cmd.globalAttributeTags[attr] = tag
+ } else {
+ cmd.globalAttributeTags[attrTag] = attrTag
+ }
}
- defer f.Close()
- r = f
- }
-
- config, err := loadConfig(r)
- if err != nil {
- return fmt.Errorf("error loading config: %v", err)
}
+ return nil
+}
- s, err := statsd.New(*statsdAddr)
+func (cmd *DockerDog) Run() error {
+ statsd, err := statsd.New(cmd.StatsdAddr)
if err != nil {
- return fmt.Errorf("could not connect to statsd: %v", err)
+ return fmt.Errorf("statsd error: %w", err)
}
- defer s.Close()
+ defer statsd.Close()
- d, err := docker.NewClientFromEnv()
+ docker, err := dockerclient.NewClientWithOpts()
if err != nil {
- return fmt.Errorf("could not connect to Docker daemon: %v", err)
+ return fmt.Errorf("docker error: %w", err)
}
+ defer docker.Close()
- return watch(config, d, s)
-}
-
-func watch(config *config, c *docker.Client, s *statsd.Client) error {
- events := make(chan *docker.APIEvents)
- if err := c.AddEventListener(events); err != nil {
- return fmt.Errorf("could not subscribe event listener: %v", err)
+ filters := dockerfilters.NewArgs()
+ for k, _ := range cmd.eventAttributeTags {
+ if typeName, actionName, ok := strings.Cut(k, "."); ok {
+ filters.Add("type", typeName)
+ filters.Add("event", actionName)
+ }
}
- for event := range events {
- if _, ok := config.Events[event.Type]; !ok {
- continue
- }
+ fmt.Printf("listening to docker events, sending stats to %s\n", cmd.StatsdAddr)
+ events, errs := docker.Events(
+ context.Background(),
+ dockertypes.EventsOptions{
+ Filters: filters,
+ },
+ )
+ for {
+ select {
+ case event := <-events:
+ key := event.Type + "." + event.Action
+
+ attributeTags, ok := cmd.eventAttributeTags[key]
+ if !ok {
+ if cmd.Debug {
+ fmt.Printf("ignoring %s\n", key)
+ }
+ continue
+ }
- enabledAttributes := config.attributes(event.Type, event.Action)
+ tags := []string{}
+ for attr, tag := range cmd.globalAttributeTags {
+ if v, ok := event.Actor.Attributes[attr]; ok {
+ tags = append(tags, fmt.Sprintf("%s:%s", tag, v))
+ }
+ }
+ for attr, tag := range attributeTags {
+ if v, ok := event.Actor.Attributes[attr]; ok {
+ tags = append(tags, fmt.Sprintf("%s:%s", tag, v))
+ }
+ }
- var tags []string
- for k, v := range event.Actor.Attributes {
- if enabledAttributes[k] {
- tags = append(tags, fmt.Sprintf("%s:%s", k, v))
+ metricName := "docker.events." + key
+ if cmd.Debug {
+ fmt.Printf("%s %v\n", metricName, tags)
}
- }
+ statsd.Count(metricName, 1, tags, 1)
- s.Count(fmt.Sprintf("docker.events.%s.%s", event.Type, event.Action), 1, tags, 1)
+ case err := <-errs:
+ return err
+ }
}
+}
- return nil
+func main() {
+ cli.New("dockerdog", NewDockerDog()).
+ Parse().
+ RunFatal()
}
diff --git a/main_test.go b/main_test.go
deleted file mode 100644
index d2dca1b..0000000
--- a/main_test.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package main
-
-import (
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestConfig_Attributes(t *testing.T) {
- config := testConfig(t)
-
- assert.Equal(t, map[string]bool{"image": true}, config.attributes("container", "start"))
- assert.Equal(t, map[string]bool{"image": false}, config.attributes("container", "create"))
- assert.Equal(t, map[string]bool{"image": true, "exitCode": true}, config.attributes("container", "die"))
- assert.Equal(t, map[string]bool{"image": true, "signal": true}, config.attributes("container", "kill"))
-}
-
-const testConfigJson = `{
- "attributes": {
- "image": true
- },
- "events": {
- "image": {
- "actions": {
- "pull": {},
- "delete": {}
- }
- },
- "container": {
- "actions": {
- "create": {
- "attributes": {
- "image": false
- }
- },
- "start": {},
- "die": {
- "attributes": {
- "exitCode": true
- }
- },
- "kill": {
- "attributes": {
- "signal": true
- }
- }
- }
- }
- }
-}`
-
-func testConfig(t testing.TB) *config {
- config, err := loadConfig(strings.NewReader(testConfigJson))
- if err != nil {
- t.Fatal(err)
- }
- return config
-}
diff --git a/vendor/github.com/DataDog/datadog-go/statsd/README.md b/vendor/github.com/DataDog/datadog-go/statsd/README.md
deleted file mode 100644
index c3b462f..0000000
--- a/vendor/github.com/DataDog/datadog-go/statsd/README.md
+++ /dev/null
@@ -1,45 +0,0 @@
-## Overview
-
-Package `statsd` provides a Go [dogstatsd](http://docs.datadoghq.com/guides/dogstatsd/) client. Dogstatsd extends Statsd, adding tags
-and histograms.
-
-## Get the code
-
- $ go get github.com/DataDog/datadog-go/statsd
-
-## Usage
-
-```go
-// Create the client
-c, err := statsd.New("127.0.0.1:8125")
-if err != nil {
- log.Fatal(err)
-}
-// Prefix every metric with the app name
-c.Namespace = "flubber."
-// Send the EC2 availability zone as a tag with every metric
-c.Tags = append(c.Tags, "us-east-1a")
-err = c.Gauge("request.duration", 1.2, nil, 1)
-```
-
-## Buffering Client
-
-Dogstatsd accepts packets with multiple statsd payloads in them. Using the BufferingClient via `NewBufferingClient` will buffer up commands and send them when the buffer is reached or after 100msec.
-
-## Development
-
-Run the tests with:
-
- $ go test
-
-## Documentation
-
-Please see: http://godoc.org/github.com/DataDog/datadog-go/statsd
-
-## License
-
-go-dogstatsd is released under the [MIT license](http://www.opensource.org/licenses/mit-license.php).
-
-## Credits
-
-Original code by [ooyala](https://github.com/ooyala/go-dogstatsd).
diff --git a/vendor/github.com/DataDog/datadog-go/statsd/statsd.go b/vendor/github.com/DataDog/datadog-go/statsd/statsd.go
deleted file mode 100644
index 4038b89..0000000
--- a/vendor/github.com/DataDog/datadog-go/statsd/statsd.go
+++ /dev/null
@@ -1,353 +0,0 @@
-// Copyright 2013 Ooyala, Inc.
-
-/*
-Package statsd provides a Go dogstatsd client. Dogstatsd extends the popular statsd,
-adding tags and histograms and pushing upstream to Datadog.
-
-Refer to http://docs.datadoghq.com/guides/dogstatsd/ for information about DogStatsD.
-
-Example Usage:
-
- // Create the client
- c, err := statsd.New("127.0.0.1:8125")
- if err != nil {
- log.Fatal(err)
- }
- // Prefix every metric with the app name
- c.Namespace = "flubber."
- // Send the EC2 availability zone as a tag with every metric
- c.Tags = append(c.Tags, "us-east-1a")
- err = c.Gauge("request.duration", 1.2, nil, 1)
-
-statsd is based on go-statsd-client.
-*/
-package statsd
-
-import (
- "bytes"
- "fmt"
- "math/rand"
- "net"
- "strconv"
- "strings"
- "sync"
- "time"
-)
-
-// A Client is a handle for sending udp messages to dogstatsd. It is safe to
-// use one Client from multiple goroutines simultaneously.
-type Client struct {
- conn net.Conn
- // Namespace to prepend to all statsd calls
- Namespace string
- // Tags are global tags to be added to every statsd call
- Tags []string
- // BufferLength is the length of the buffer in commands.
- bufferLength int
- flushTime time.Duration
- commands []string
- stop bool
- sync.Mutex
-}
-
-// New returns a pointer to a new Client given an addr in the format "hostname:port".
-func New(addr string) (*Client, error) {
- udpAddr, err := net.ResolveUDPAddr("udp", addr)
- if err != nil {
- return nil, err
- }
- conn, err := net.DialUDP("udp", nil, udpAddr)
- if err != nil {
- return nil, err
- }
- client := &Client{conn: conn}
- return client, nil
-}
-
-// NewBuffered returns a Client that buffers its output and sends it in chunks.
-// Buflen is the length of the buffer in number of commands.
-func NewBuffered(addr string, buflen int) (*Client, error) {
- client, err := New(addr)
- if err != nil {
- return nil, err
- }
- client.bufferLength = buflen
- client.commands = make([]string, 0, buflen)
- client.flushTime = time.Millisecond * 100
- go client.watch()
- return client, nil
-}
-
-// format a message from its name, value, tags and rate. Also adds global
-// namespace and tags.
-func (c *Client) format(name, value string, tags []string, rate float64) string {
- var buf bytes.Buffer
- if c.Namespace != "" {
- buf.WriteString(c.Namespace)
- }
- buf.WriteString(name)
- buf.WriteString(":")
- buf.WriteString(value)
- if rate < 1 {
- buf.WriteString(`|@`)
- buf.WriteString(strconv.FormatFloat(rate, 'f', -1, 64))
- }
-
- tags = append(c.Tags, tags...)
- if len(tags) > 0 {
- buf.WriteString("|#")
- buf.WriteString(tags[0])
- for _, tag := range tags[1:] {
- buf.WriteString(",")
- buf.WriteString(tag)
- }
- }
- return buf.String()
-}
-
-func (c *Client) watch() {
- for _ = range time.Tick(c.flushTime) {
- if c.stop {
- return
- }
- c.Lock()
- if len(c.commands) > 0 {
- // FIXME: eating error here
- c.flush()
- }
- c.Unlock()
- }
-}
-
-func (c *Client) append(cmd string) error {
- c.Lock()
- c.commands = append(c.commands, cmd)
- // if we should flush, lets do it
- if len(c.commands) == c.bufferLength {
- if err := c.flush(); err != nil {
- c.Unlock()
- return err
- }
- }
- c.Unlock()
- return nil
-}
-
-// flush the commands in the buffer. Lock must be held by caller.
-func (c *Client) flush() error {
- data := strings.Join(c.commands, "\n")
- _, err := c.conn.Write([]byte(data))
- // clear the slice with a slice op, doesn't realloc
- c.commands = c.commands[:0]
- return err
-}
-
-func (c *Client) sendMsg(msg string) error {
- // if this client is buffered, then we'll just append this
- if c.bufferLength > 0 {
- return c.append(msg)
- }
- c.Lock()
- _, err := c.conn.Write([]byte(msg))
- c.Unlock()
- return err
-}
-
-// send handles sampling and sends the message over UDP. It also adds global namespace prefixes and tags.
-func (c *Client) send(name, value string, tags []string, rate float64) error {
- if c == nil {
- return nil
- }
- if rate < 1 && rand.Float64() > rate {
- return nil
- }
- data := c.format(name, value, tags, rate)
- return c.sendMsg(data)
-}
-
-// Gauge measures the value of a metric at a particular time.
-func (c *Client) Gauge(name string, value float64, tags []string, rate float64) error {
- stat := fmt.Sprintf("%f|g", value)
- return c.send(name, stat, tags, rate)
-}
-
-// Count tracks how many times something happened per second.
-func (c *Client) Count(name string, value int64, tags []string, rate float64) error {
- stat := fmt.Sprintf("%d|c", value)
- return c.send(name, stat, tags, rate)
-}
-
-// Histogram tracks the statistical distribution of a set of values.
-func (c *Client) Histogram(name string, value float64, tags []string, rate float64) error {
- stat := fmt.Sprintf("%f|h", value)
- return c.send(name, stat, tags, rate)
-}
-
-// Set counts the number of unique elements in a group.
-func (c *Client) Set(name string, value string, tags []string, rate float64) error {
- stat := fmt.Sprintf("%s|s", value)
- return c.send(name, stat, tags, rate)
-}
-
-// TimeInMilliseconds sends timing information in milliseconds.
-// It is flushed by statsd with percentiles, mean and other info (https://github.com/etsy/statsd/blob/master/docs/metric_types.md#timing)
-func (c *Client) TimeInMilliseconds(name string, value float64, tags []string, rate float64) error {
- stat := fmt.Sprintf("%f|ms", value)
- return c.send(name, stat, tags, rate)
-}
-
-// Event sends the provided Event.
-func (c *Client) Event(e *Event) error {
- stat, err := e.Encode(c.Tags...)
- if err != nil {
- return err
- }
- return c.sendMsg(stat)
-}
-
-// SimpleEvent sends an event with the provided title and text.
-func (c *Client) SimpleEvent(title, text string) error {
- e := NewEvent(title, text)
- return c.Event(e)
-}
-
-// Close the client connection.
-func (c *Client) Close() error {
- if c == nil {
- return nil
- }
- c.stop = true
- return c.conn.Close()
-}
-
-// Events support
-
-type eventAlertType string
-
-const (
- // Info is the "info" AlertType for events
- Info eventAlertType = "info"
- // Error is the "error" AlertType for events
- Error eventAlertType = "error"
- // Warning is the "warning" AlertType for events
- Warning eventAlertType = "warning"
- // Success is the "success" AlertType for events
- Success eventAlertType = "success"
-)
-
-type eventPriority string
-
-const (
- // Normal is the "normal" Priority for events
- Normal eventPriority = "normal"
- // Low is the "low" Priority for events
- Low eventPriority = "low"
-)
-
-// An Event is an object that can be posted to your DataDog event stream.
-type Event struct {
- // Title of the event. Required.
- Title string
- // Text is the description of the event. Required.
- Text string
- // Timestamp is a timestamp for the event. If not provided, the dogstatsd
- // server will set this to the current time.
- Timestamp time.Time
- // Hostname for the event.
- Hostname string
- // AggregationKey groups this event with others of the same key.
- AggregationKey string
- // Priority of the event. Can be statsd.Low or statsd.Normal.
- Priority eventPriority
- // SourceTypeName is a source type for the event.
- SourceTypeName string
- // AlertType can be statsd.Info, statsd.Error, statsd.Warning, or statsd.Success.
- // If absent, the default value applied by the dogstatsd server is Info.
- AlertType eventAlertType
- // Tags for the event.
- Tags []string
-}
-
-// NewEvent creates a new event with the given title and text. Error checking
-// against these values is done at send-time, or upon running e.Check.
-func NewEvent(title, text string) *Event {
- return &Event{
- Title: title,
- Text: text,
- }
-}
-
-// Check verifies that an event is valid.
-func (e Event) Check() error {
- if len(e.Title) == 0 {
- return fmt.Errorf("statsd.Event title is required")
- }
- if len(e.Text) == 0 {
- return fmt.Errorf("statsd.Event text is required")
- }
- return nil
-}
-
-// Encode returns the dogstatsd wire protocol representation for an event.
-// Tags may be passed which will be added to the encoded output but not to
-// the Event's list of tags, eg. for default tags.
-func (e Event) Encode(tags ...string) (string, error) {
- err := e.Check()
- if err != nil {
- return "", err
- }
- var buffer bytes.Buffer
- buffer.WriteString("_e{")
- buffer.WriteString(strconv.FormatInt(int64(len(e.Title)), 10))
- buffer.WriteRune(',')
- buffer.WriteString(strconv.FormatInt(int64(len(e.Text)), 10))
- buffer.WriteString("}:")
- buffer.WriteString(e.Title)
- buffer.WriteRune('|')
- buffer.WriteString(e.Text)
-
- if !e.Timestamp.IsZero() {
- buffer.WriteString("|d:")
- buffer.WriteString(strconv.FormatInt(int64(e.Timestamp.Unix()), 10))
- }
-
- if len(e.Hostname) != 0 {
- buffer.WriteString("|h:")
- buffer.WriteString(e.Hostname)
- }
-
- if len(e.AggregationKey) != 0 {
- buffer.WriteString("|k:")
- buffer.WriteString(e.AggregationKey)
-
- }
-
- if len(e.Priority) != 0 {
- buffer.WriteString("|p:")
- buffer.WriteString(string(e.Priority))
- }
-
- if len(e.SourceTypeName) != 0 {
- buffer.WriteString("|s:")
- buffer.WriteString(e.SourceTypeName)
- }
-
- if len(e.AlertType) != 0 {
- buffer.WriteString("|t:")
- buffer.WriteString(string(e.AlertType))
- }
-
- if len(tags)+len(e.Tags) > 0 {
- all := make([]string, 0, len(tags)+len(e.Tags))
- all = append(all, tags...)
- all = append(all, e.Tags...)
- buffer.WriteString("|#")
- buffer.WriteString(all[0])
- for _, tag := range all[1:] {
- buffer.WriteString(",")
- buffer.WriteString(tag)
- }
- }
-
- return buffer.String(), nil
-}
diff --git a/vendor/github.com/DataDog/datadog-go/statsd/statsd_test.go b/vendor/github.com/DataDog/datadog-go/statsd/statsd_test.go
deleted file mode 100644
index 1f12fc0..0000000
--- a/vendor/github.com/DataDog/datadog-go/statsd/statsd_test.go
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright 2013 Ooyala, Inc.
-
-package statsd
-
-import (
- "fmt"
- "io"
- "net"
- "reflect"
- "strings"
- "testing"
-)
-
-var dogstatsdTests = []struct {
- GlobalNamespace string
- GlobalTags []string
- Method string
- Metric string
- Value interface{}
- Tags []string
- Rate float64
- Expected string
-}{
- {"", nil, "Gauge", "test.gauge", 1.0, nil, 1.0, "test.gauge:1.000000|g"},
- {"", nil, "Gauge", "test.gauge", 1.0, nil, 0.999999, "test.gauge:1.000000|g|@0.999999"},
- {"", nil, "Gauge", "test.gauge", 1.0, []string{"tagA"}, 1.0, "test.gauge:1.000000|g|#tagA"},
- {"", nil, "Gauge", "test.gauge", 1.0, []string{"tagA", "tagB"}, 1.0, "test.gauge:1.000000|g|#tagA,tagB"},
- {"", nil, "Gauge", "test.gauge", 1.0, []string{"tagA"}, 0.999999, "test.gauge:1.000000|g|@0.999999|#tagA"},
- {"", nil, "Count", "test.count", int64(1), []string{"tagA"}, 1.0, "test.count:1|c|#tagA"},
- {"", nil, "Count", "test.count", int64(-1), []string{"tagA"}, 1.0, "test.count:-1|c|#tagA"},
- {"", nil, "Histogram", "test.histogram", 2.3, []string{"tagA"}, 1.0, "test.histogram:2.300000|h|#tagA"},
- {"", nil, "Set", "test.set", "uuid", []string{"tagA"}, 1.0, "test.set:uuid|s|#tagA"},
- {"flubber.", nil, "Set", "test.set", "uuid", []string{"tagA"}, 1.0, "flubber.test.set:uuid|s|#tagA"},
- {"", []string{"tagC"}, "Set", "test.set", "uuid", []string{"tagA"}, 1.0, "test.set:uuid|s|#tagC,tagA"},
-}
-
-func assertNotPanics(t *testing.T, f func()) {
- defer func() {
- if r := recover(); r != nil {
- t.Fatal(r)
- }
- }()
- f()
-}
-
-func TestClient(t *testing.T) {
- addr := "localhost:1201"
- udpAddr, err := net.ResolveUDPAddr("udp", addr)
- if err != nil {
- t.Fatal(err)
- }
-
- server, err := net.ListenUDP("udp", udpAddr)
- if err != nil {
- t.Fatal(err)
- }
- defer server.Close()
-
- client, err := New(addr)
- if err != nil {
- t.Fatal(err)
- }
-
- for _, tt := range dogstatsdTests {
- client.Namespace = tt.GlobalNamespace
- client.Tags = tt.GlobalTags
- method := reflect.ValueOf(client).MethodByName(tt.Method)
- e := method.Call([]reflect.Value{
- reflect.ValueOf(tt.Metric),
- reflect.ValueOf(tt.Value),
- reflect.ValueOf(tt.Tags),
- reflect.ValueOf(tt.Rate)})[0]
- errInter := e.Interface()
- if errInter != nil {
- t.Fatal(errInter.(error))
- }
-
- bytes := make([]byte, 1024)
- n, err := server.Read(bytes)
- if err != nil {
- t.Fatal(err)
- }
- message := bytes[:n]
- if string(message) != tt.Expected {
- t.Errorf("Expected: %s. Actual: %s", tt.Expected, string(message))
- }
- }
-}
-
-func TestBufferedClient(t *testing.T) {
- addr := "localhost:1201"
- udpAddr, err := net.ResolveUDPAddr("udp", addr)
- if err != nil {
- t.Fatal(err)
- }
-
- server, err := net.ListenUDP("udp", udpAddr)
- if err != nil {
- t.Fatal(err)
- }
- defer server.Close()
-
- conn, err := net.DialUDP("udp", nil, udpAddr)
- if err != nil {
- t.Fatal(err)
- }
-
- bufferLength := 5
- client := &Client{
- conn: conn,
- commands: make([]string, 0, bufferLength),
- bufferLength: bufferLength,
- }
-
- client.Namespace = "foo."
- client.Tags = []string{"dd:2"}
-
- client.Count("cc", 1, nil, 1)
- client.Gauge("gg", 10, nil, 1)
- client.Histogram("hh", 1, nil, 1)
- client.Set("ss", "ss", nil, 1)
-
- if len(client.commands) != 4 {
- t.Errorf("Expected client to have buffered 4 commands, but found %d\n", len(client.commands))
- }
-
- client.Set("ss", "xx", nil, 1)
- err = client.flush()
- if err != nil {
- t.Errorf("Error sending: %s", err)
- }
-
- if len(client.commands) != 0 {
- t.Errorf("Expecting send to flush commands, but found %d\n", len(client.commands))
- }
-
- buffer := make([]byte, 4096)
- n, err := io.ReadAtLeast(server, buffer, 1)
- result := string(buffer[:n])
-
- if err != nil {
- t.Error(err)
- }
-
- expected := []string{
- `foo.cc:1|c|#dd:2`,
- `foo.gg:10.000000|g|#dd:2`,
- `foo.hh:1.000000|h|#dd:2`,
- `foo.ss:ss|s|#dd:2`,
- `foo.ss:xx|s|#dd:2`,
- }
-
- for i, res := range strings.Split(result, "\n") {
- if res != expected[i] {
- t.Errorf("Got `%s`, expected `%s`", res, expected[i])
- }
- }
-
- client.Event(&Event{Title: "title1", Text: "text1", Priority: Normal, AlertType: Success, Tags: []string{"tagg"}})
- client.SimpleEvent("event1", "text1")
-
- if len(client.commands) != 2 {
- t.Errorf("Expected to find %d commands, but found %d\n", 2, len(client.commands))
- }
-
- err = client.flush()
-
- if err != nil {
- t.Errorf("Error sending: %s", err)
- }
-
- if len(client.commands) != 0 {
- t.Errorf("Expecting send to flush commands, but found %d\n", len(client.commands))
- }
-
- buffer = make([]byte, 1024)
- n, err = io.ReadAtLeast(server, buffer, 1)
- result = string(buffer[:n])
-
- if err != nil {
- t.Error(err)
- }
-
- if n == 0 {
- t.Errorf("Read 0 bytes but expected more.")
- }
-
- expected = []string{
- `_e{6,5}:title1|text1|p:normal|t:success|#dd:2,tagg`,
- `_e{6,5}:event1|text1|#dd:2`,
- }
-
- for i, res := range strings.Split(result, "\n") {
- if res != expected[i] {
- t.Errorf("Got `%s`, expected `%s`", res, expected[i])
- }
- }
-
-}
-
-func TestNilSafe(t *testing.T) {
- var c *Client
- assertNotPanics(t, func() { c.Close() })
- assertNotPanics(t, func() { c.Count("", 0, nil, 1) })
- assertNotPanics(t, func() { c.Histogram("", 0, nil, 1) })
- assertNotPanics(t, func() { c.Gauge("", 0, nil, 1) })
- assertNotPanics(t, func() { c.Set("", "", nil, 1) })
- assertNotPanics(t, func() { c.send("", "", nil, 1) })
-}
-
-func TestEvents(t *testing.T) {
- matrix := []struct {
- event *Event
- encoded string
- }{
- {
- NewEvent("Hello", "Something happened to my event"),
- `_e{5,30}:Hello|Something happened to my event`,
- }, {
- &Event{Title: "hi", Text: "okay", AggregationKey: "foo"},
- `_e{2,4}:hi|okay|k:foo`,
- }, {
- &Event{Title: "hi", Text: "okay", AggregationKey: "foo", AlertType: Info},
- `_e{2,4}:hi|okay|k:foo|t:info`,
- }, {
- &Event{Title: "hi", Text: "w/e", AlertType: Error, Priority: Normal},
- `_e{2,3}:hi|w/e|p:normal|t:error`,
- }, {
- &Event{Title: "hi", Text: "uh", Tags: []string{"host:foo", "app:bar"}},
- `_e{2,2}:hi|uh|#host:foo,app:bar`,
- },
- }
-
- for _, m := range matrix {
- r, err := m.event.Encode()
- if err != nil {
- t.Errorf("Error encoding: %s\n", err)
- continue
- }
- if r != m.encoded {
- t.Errorf("Expected `%s`, got `%s`\n", m.encoded, r)
- }
- }
-
- e := NewEvent("", "hi")
- if _, err := e.Encode(); err == nil {
- t.Errorf("Expected error on empty Title.")
- }
-
- e = NewEvent("hi", "")
- if _, err := e.Encode(); err == nil {
- t.Errorf("Expected error on empty Text.")
- }
-
- e = NewEvent("hello", "world")
- s, err := e.Encode("tag1", "tag2")
- if err != nil {
- t.Error(err)
- }
- expected := "_e{5,5}:hello|world|#tag1,tag2"
- if s != expected {
- t.Errorf("Expected %s, got %s", expected, s)
- }
- if len(e.Tags) != 0 {
- t.Errorf("Modified event in place illegally.")
- }
-}
-
-// These benchmarks show that using a buffer instead of sprintf-ing together
-// a bunch of intermediate strings is 4-5x faster
-
-func BenchmarkFormatNew(b *testing.B) {
- b.StopTimer()
- c := &Client{}
- c.Namespace = "foo.bar."
- c.Tags = []string{"app:foo", "host:bar"}
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- c.format("system.cpu.idle", "10", []string{"foo"}, 1)
- c.format("system.cpu.load", "0.1", nil, 0.9)
- }
-}
-
-// Old formatting function, added to client for tests
-func (c *Client) formatOld(name, value string, tags []string, rate float64) string {
- if rate < 1 {
- value = fmt.Sprintf("%s|@%f", value, rate)
- }
- if c.Namespace != "" {
- name = fmt.Sprintf("%s%s", c.Namespace, name)
- }
-
- tags = append(c.Tags, tags...)
- if len(tags) > 0 {
- value = fmt.Sprintf("%s|#%s", value, strings.Join(tags, ","))
- }
-
- return fmt.Sprintf("%s:%s", name, value)
-
-}
-
-func BenchmarkFormatOld(b *testing.B) {
- b.StopTimer()
- c := &Client{}
- c.Namespace = "foo.bar."
- c.Tags = []string{"app:foo", "host:bar"}
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- c.formatOld("system.cpu.idle", "10", []string{"foo"}, 1)
- c.formatOld("system.cpu.load", "0.1", nil, 0.9)
- }
-}
diff --git a/vendor/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/Sirupsen/logrus/LICENSE
deleted file mode 100644
index f090cb4..0000000
--- a/vendor/github.com/Sirupsen/logrus/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 Simon Eskildsen
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md
deleted file mode 100644
index 6227b3f..0000000
--- a/vendor/github.com/Sirupsen/logrus/README.md
+++ /dev/null
@@ -1,373 +0,0 @@
-# Logrus
[](https://travis-ci.org/Sirupsen/logrus) [][godoc]
-
-Logrus is a structured logger for Go (golang), completely API compatible with
-the standard library logger. [Godoc][godoc]. **Please note the Logrus API is not
-yet stable (pre 1.0), the core API is unlikely to change much but please version
-control your Logrus to make sure you aren't fetching latest `master` on every
-build.**
-
-Nicely color-coded in development (when a TTY is attached, otherwise just
-plain text):
-
-
-
-With `log.Formatter = new(logrus.JSONFormatter)`, for easy parsing by logstash
-or Splunk:
-
-```json
-{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
-ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
-
-{"level":"warning","msg":"The group's number increased tremendously!",
-"number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
-
-{"animal":"walrus","level":"info","msg":"A giant walrus appears!",
-"size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
-
-{"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
-"size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
-
-{"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
-"time":"2014-03-10 19:57:38.562543128 -0400 EDT"}
-```
-
-With the default `log.Formatter = new(logrus.TextFormatter)` when a TTY is not
-attached, the output is compatible with the
-[logfmt](http://godoc.org/github.com/kr/logfmt) format:
-
-```text
-time="2014-04-20 15:36:23.830442383 -0400 EDT" level="info" msg="A group of walrus emerges from the ocean" animal="walrus" size=10
-time="2014-04-20 15:36:23.830584199 -0400 EDT" level="warning" msg="The group's number increased tremendously!" omg=true number=122
-time="2014-04-20 15:36:23.830596521 -0400 EDT" level="info" msg="A giant walrus appears!" animal="walrus" size=10
-time="2014-04-20 15:36:23.830611837 -0400 EDT" level="info" msg="Tremendously sized cow enters the ocean." animal="walrus" size=9
-time="2014-04-20 15:36:23.830626464 -0400 EDT" level="fatal" msg="The ice breaks!" omg=true number=100
-```
-
-#### Example
-
-The simplest way to use Logrus is simply the package-level exported logger:
-
-```go
-package main
-
-import (
- log "github.com/Sirupsen/logrus"
-)
-
-func main() {
- log.WithFields(log.Fields{
- "animal": "walrus",
- }).Info("A walrus appears")
-}
-```
-
-Note that it's completely api-compatible with the stdlib logger, so you can
-replace your `log` imports everywhere with `log "github.com/Sirupsen/logrus"`
-and you'll now have the flexibility of Logrus. You can customize it all you
-want:
-
-```go
-package main
-
-import (
- "os"
- log "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/airbrake"
-)
-
-func init() {
- // Log as JSON instead of the default ASCII formatter.
- log.SetFormatter(&log.JSONFormatter{})
-
- // Use the Airbrake hook to report errors that have Error severity or above to
- // an exception tracker. You can create custom hooks, see the Hooks section.
- log.AddHook(&logrus_airbrake.AirbrakeHook{})
-
- // Output to stderr instead of stdout, could also be a file.
- log.SetOutput(os.Stderr)
-
- // Only log the warning severity or above.
- log.SetLevel(log.WarnLevel)
-}
-
-func main() {
- log.WithFields(log.Fields{
- "animal": "walrus",
- "size": 10,
- }).Info("A group of walrus emerges from the ocean")
-
- log.WithFields(log.Fields{
- "omg": true,
- "number": 122,
- }).Warn("The group's number increased tremendously!")
-
- log.WithFields(log.Fields{
- "omg": true,
- "number": 100,
- }).Fatal("The ice breaks!")
-}
-```
-
-For more advanced usage such as logging to multiple locations from the same
-application, you can also create an instance of the `logrus` Logger:
-
-```go
-package main
-
-import (
- "github.com/Sirupsen/logrus"
-)
-
-// Create a new instance of the logger. You can have any number of instances.
-var log = logrus.New()
-
-func main() {
- // The API for setting attributes is a little different than the package level
- // exported logger. See Godoc.
- log.Out = os.Stderr
-
- log.WithFields(logrus.Fields{
- "animal": "walrus",
- "size": 10,
- }).Info("A group of walrus emerges from the ocean")
-}
-```
-
-#### Fields
-
-Logrus encourages careful, structured logging though logging fields instead of
-long, unparseable error messages. For example, instead of: `log.Fatalf("Failed
-to send event %s to topic %s with key %d")`, you should log the much more
-discoverable:
-
-```go
-log.WithFields(log.Fields{
- "event": event,
- "topic": topic,
- "key": key,
-}).Fatal("Failed to send event")
-```
-
-We've found this API forces you to think about logging in a way that produces
-much more useful logging messages. We've been in countless situations where just
-a single added field to a log statement that was already there would've saved us
-hours. The `WithFields` call is optional.
-
-In general, with Logrus using any of the `printf`-family functions should be
-seen as a hint you should add a field, however, you can still use the
-`printf`-family functions with Logrus.
-
-#### Hooks
-
-You can add hooks for logging levels. For example to send errors to an exception
-tracking service on `Error`, `Fatal` and `Panic`, info to StatsD or log to
-multiple places simultaneously, e.g. syslog.
-
-```go
-// Not the real implementation of the Airbrake hook. Just a simple sample.
-import (
- log "github.com/Sirupsen/logrus"
-)
-
-func init() {
- log.AddHook(new(AirbrakeHook))
-}
-
-type AirbrakeHook struct{}
-
-// `Fire()` takes the entry that the hook is fired for. `entry.Data[]` contains
-// the fields for the entry. See the Fields section of the README.
-func (hook *AirbrakeHook) Fire(entry *logrus.Entry) error {
- err := airbrake.Notify(entry.Data["error"].(error))
- if err != nil {
- log.WithFields(log.Fields{
- "source": "airbrake",
- "endpoint": airbrake.Endpoint,
- }).Info("Failed to send error to Airbrake")
- }
-
- return nil
-}
-
-// `Levels()` returns a slice of `Levels` the hook is fired for.
-func (hook *AirbrakeHook) Levels() []log.Level {
- return []log.Level{
- log.ErrorLevel,
- log.FatalLevel,
- log.PanicLevel,
- }
-}
-```
-
-Logrus comes with built-in hooks. Add those, or your custom hook, in `init`:
-
-```go
-import (
- log "github.com/Sirupsen/logrus"
- "github.com/Sirupsen/logrus/hooks/airbrake"
- "github.com/Sirupsen/logrus/hooks/syslog"
- "log/syslog"
-)
-
-func init() {
- log.AddHook(new(logrus_airbrake.AirbrakeHook))
-
- hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
- if err != nil {
- log.Error("Unable to connect to local syslog daemon")
- } else {
- log.AddHook(hook)
- }
-}
-```
-
-* [`github.com/Sirupsen/logrus/hooks/airbrake`](https://github.com/Sirupsen/logrus/blob/master/hooks/airbrake/airbrake.go)
- Send errors to an exception tracking service compatible with the Airbrake API.
- Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes.
-
-* [`github.com/Sirupsen/logrus/hooks/papertrail`](https://github.com/Sirupsen/logrus/blob/master/hooks/papertrail/papertrail.go)
- Send errors to the Papertrail hosted logging service via UDP.
-
-* [`github.com/Sirupsen/logrus/hooks/syslog`](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go)
- Send errors to remote syslog server.
- Uses standard library `log/syslog` behind the scenes.
-
-* [`github.com/nubo/hiprus`](https://github.com/nubo/hiprus)
- Send errors to a channel in hipchat.
-
-* [`github.com/sebest/logrusly`](https://github.com/sebest/logrusly)
- Send logs to Loggly (https://www.loggly.com/)
-
-* [`github.com/johntdyer/slackrus`](https://github.com/johntdyer/slackrus)
- Hook for Slack chat.
-
-#### Level logging
-
-Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic.
-
-```go
-log.Debug("Useful debugging information.")
-log.Info("Something noteworthy happened!")
-log.Warn("You should probably take a look at this.")
-log.Error("Something failed but I'm not quitting.")
-// Calls os.Exit(1) after logging
-log.Fatal("Bye.")
-// Calls panic() after logging
-log.Panic("I'm bailing.")
-```
-
-You can set the logging level on a `Logger`, then it will only log entries with
-that severity or anything above it:
-
-```go
-// Will log anything that is info or above (warn, error, fatal, panic). Default.
-log.SetLevel(log.InfoLevel)
-```
-
-It may be useful to set `log.Level = logrus.DebugLevel` in a debug or verbose
-environment if your application has that.
-
-#### Entries
-
-Besides the fields added with `WithField` or `WithFields` some fields are
-automatically added to all logging events:
-
-1. `time`. The timestamp when the entry was created.
-2. `msg`. The logging message passed to `{Info,Warn,Error,Fatal,Panic}` after
- the `AddFields` call. E.g. `Failed to send event.`
-3. `level`. The logging level. E.g. `info`.
-
-#### Environments
-
-Logrus has no notion of environment.
-
-If you wish for hooks and formatters to only be used in specific environments,
-you should handle that yourself. For example, if your application has a global
-variable `Environment`, which is a string representation of the environment you
-could do:
-
-```go
-import (
- log "github.com/Sirupsen/logrus"
-)
-
-init() {
- // do something here to set environment depending on an environment variable
- // or command-line flag
- if Environment == "production" {
- log.SetFormatter(logrus.JSONFormatter)
- } else {
- // The TextFormatter is default, you don't actually have to do this.
- log.SetFormatter(logrus.TextFormatter)
- }
-}
-```
-
-This configuration is how `logrus` was intended to be used, but JSON in
-production is mostly only useful if you do log aggregation with tools like
-Splunk or Logstash.
-
-#### Formatters
-
-The built-in logging formatters are:
-
-* `logrus.TextFormatter`. Logs the event in colors if stdout is a tty, otherwise
- without colors.
- * *Note:* to force colored output when there is no TTY, set the `ForceColors`
- field to `true`. To force no colored output even if there is a TTY set the
- `DisableColors` field to `true`
-* `logrus.JSONFormatter`. Logs fields as JSON.
-
-Third party logging formatters:
-
-* [`zalgo`](https://github.com/aybabtme/logzalgo): invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
-
-You can define your formatter by implementing the `Formatter` interface,
-requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
-`Fields` type (`map[string]interface{}`) with all your fields as well as the
-default ones (see Entries section above):
-
-```go
-type MyJSONFormatter struct {
-}
-
-log.SetFormatter(new(MyJSONFormatter))
-
-func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
- // Note this doesn't include Time, Level and Message which are available on
- // the Entry. Consult `godoc` on information about those fields or read the
- // source of the official loggers.
- serialized, err := json.Marshal(entry.Data)
- if err != nil {
- return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
- }
- return append(serialized, '\n'), nil
-}
-```
-
-#### Logger as an `io.Writer`
-
-Logrus can be transormed into an `io.Writer`. That writer is the end of an `io.Pipe` and it is your responsability to close it.
-
-```go
-w := logger.Writer()
-defer w.Close()
-
-srv := http.Server{
- // create a stdlib log.Logger that writes to
- // logrus.Logger.
- ErrorLog: log.New(w, "", 0),
-}
-```
-
-Each line written to that writer will be printed the usual way, using formatters
-and hooks. The level for those entries is `info`.
-
-#### Rotation
-
-Log rotation is not provided with Logrus. Log rotation should be done by an
-external program (like `logrotated(8)`) that can compress and delete old log
-entries. It should not be a feature of the application-level logger.
-
-
-[godoc]: https://godoc.org/github.com/Sirupsen/logrus
diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/Sirupsen/logrus/entry.go
deleted file mode 100644
index 17fe6f7..0000000
--- a/vendor/github.com/Sirupsen/logrus/entry.go
+++ /dev/null
@@ -1,252 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "fmt"
- "io"
- "os"
- "time"
-)
-
-// An entry is the final or intermediate Logrus logging entry. It contains all
-// the fields passed with WithField{,s}. It's finally logged when Debug, Info,
-// Warn, Error, Fatal or Panic is called on it. These objects can be reused and
-// passed around as much as you wish to avoid field duplication.
-type Entry struct {
- Logger *Logger
-
- // Contains all the fields set by the user.
- Data Fields
-
- // Time at which the log entry was created
- Time time.Time
-
- // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic
- Level Level
-
- // Message passed to Debug, Info, Warn, Error, Fatal or Panic
- Message string
-}
-
-func NewEntry(logger *Logger) *Entry {
- return &Entry{
- Logger: logger,
- // Default is three fields, give a little extra room
- Data: make(Fields, 5),
- }
-}
-
-// Returns a reader for the entry, which is a proxy to the formatter.
-func (entry *Entry) Reader() (*bytes.Buffer, error) {
- serialized, err := entry.Logger.Formatter.Format(entry)
- return bytes.NewBuffer(serialized), err
-}
-
-// Returns the string representation from the reader and ultimately the
-// formatter.
-func (entry *Entry) String() (string, error) {
- reader, err := entry.Reader()
- if err != nil {
- return "", err
- }
-
- return reader.String(), err
-}
-
-// Add a single field to the Entry.
-func (entry *Entry) WithField(key string, value interface{}) *Entry {
- return entry.WithFields(Fields{key: value})
-}
-
-// Add a map of fields to the Entry.
-func (entry *Entry) WithFields(fields Fields) *Entry {
- data := Fields{}
- for k, v := range entry.Data {
- data[k] = v
- }
- for k, v := range fields {
- data[k] = v
- }
- return &Entry{Logger: entry.Logger, Data: data}
-}
-
-func (entry *Entry) log(level Level, msg string) {
- entry.Time = time.Now()
- entry.Level = level
- entry.Message = msg
-
- if err := entry.Logger.Hooks.Fire(level, entry); err != nil {
- entry.Logger.mu.Lock()
- fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
- entry.Logger.mu.Unlock()
- }
-
- reader, err := entry.Reader()
- if err != nil {
- entry.Logger.mu.Lock()
- fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
- entry.Logger.mu.Unlock()
- }
-
- entry.Logger.mu.Lock()
- defer entry.Logger.mu.Unlock()
-
- _, err = io.Copy(entry.Logger.Out, reader)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
- }
-
- // To avoid Entry#log() returning a value that only would make sense for
- // panic() to use in Entry#Panic(), we avoid the allocation by checking
- // directly here.
- if level <= PanicLevel {
- panic(entry)
- }
-}
-
-func (entry *Entry) Debug(args ...interface{}) {
- if entry.Logger.Level >= DebugLevel {
- entry.log(DebugLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Print(args ...interface{}) {
- entry.Info(args...)
-}
-
-func (entry *Entry) Info(args ...interface{}) {
- if entry.Logger.Level >= InfoLevel {
- entry.log(InfoLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Warn(args ...interface{}) {
- if entry.Logger.Level >= WarnLevel {
- entry.log(WarnLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Warning(args ...interface{}) {
- entry.Warn(args...)
-}
-
-func (entry *Entry) Error(args ...interface{}) {
- if entry.Logger.Level >= ErrorLevel {
- entry.log(ErrorLevel, fmt.Sprint(args...))
- }
-}
-
-func (entry *Entry) Fatal(args ...interface{}) {
- if entry.Logger.Level >= FatalLevel {
- entry.log(FatalLevel, fmt.Sprint(args...))
- }
- os.Exit(1)
-}
-
-func (entry *Entry) Panic(args ...interface{}) {
- if entry.Logger.Level >= PanicLevel {
- entry.log(PanicLevel, fmt.Sprint(args...))
- }
- panic(fmt.Sprint(args...))
-}
-
-// Entry Printf family functions
-
-func (entry *Entry) Debugf(format string, args ...interface{}) {
- if entry.Logger.Level >= DebugLevel {
- entry.Debug(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Infof(format string, args ...interface{}) {
- if entry.Logger.Level >= InfoLevel {
- entry.Info(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Printf(format string, args ...interface{}) {
- entry.Infof(format, args...)
-}
-
-func (entry *Entry) Warnf(format string, args ...interface{}) {
- if entry.Logger.Level >= WarnLevel {
- entry.Warn(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Warningf(format string, args ...interface{}) {
- entry.Warnf(format, args...)
-}
-
-func (entry *Entry) Errorf(format string, args ...interface{}) {
- if entry.Logger.Level >= ErrorLevel {
- entry.Error(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Fatalf(format string, args ...interface{}) {
- if entry.Logger.Level >= FatalLevel {
- entry.Fatal(fmt.Sprintf(format, args...))
- }
-}
-
-func (entry *Entry) Panicf(format string, args ...interface{}) {
- if entry.Logger.Level >= PanicLevel {
- entry.Panic(fmt.Sprintf(format, args...))
- }
-}
-
-// Entry Println family functions
-
-func (entry *Entry) Debugln(args ...interface{}) {
- if entry.Logger.Level >= DebugLevel {
- entry.Debug(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Infoln(args ...interface{}) {
- if entry.Logger.Level >= InfoLevel {
- entry.Info(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Println(args ...interface{}) {
- entry.Infoln(args...)
-}
-
-func (entry *Entry) Warnln(args ...interface{}) {
- if entry.Logger.Level >= WarnLevel {
- entry.Warn(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Warningln(args ...interface{}) {
- entry.Warnln(args...)
-}
-
-func (entry *Entry) Errorln(args ...interface{}) {
- if entry.Logger.Level >= ErrorLevel {
- entry.Error(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Fatalln(args ...interface{}) {
- if entry.Logger.Level >= FatalLevel {
- entry.Fatal(entry.sprintlnn(args...))
- }
-}
-
-func (entry *Entry) Panicln(args ...interface{}) {
- if entry.Logger.Level >= PanicLevel {
- entry.Panic(entry.sprintlnn(args...))
- }
-}
-
-// Sprintlnn => Sprint no newline. This is to get the behavior of how
-// fmt.Sprintln where spaces are always added between operands, regardless of
-// their type. Instead of vendoring the Sprintln implementation to spare a
-// string allocation, we do the simplest thing.
-func (entry *Entry) sprintlnn(args ...interface{}) string {
- msg := fmt.Sprintln(args...)
- return msg[:len(msg)-1]
-}
diff --git a/vendor/github.com/Sirupsen/logrus/entry_test.go b/vendor/github.com/Sirupsen/logrus/entry_test.go
deleted file mode 100644
index 98717df..0000000
--- a/vendor/github.com/Sirupsen/logrus/entry_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "fmt"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestEntryPanicln(t *testing.T) {
- errBoom := fmt.Errorf("boom time")
-
- defer func() {
- p := recover()
- assert.NotNil(t, p)
-
- switch pVal := p.(type) {
- case *Entry:
- assert.Equal(t, "kaboom", pVal.Message)
- assert.Equal(t, errBoom, pVal.Data["err"])
- default:
- t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
- }
- }()
-
- logger := New()
- logger.Out = &bytes.Buffer{}
- entry := NewEntry(logger)
- entry.WithField("err", errBoom).Panicln("kaboom")
-}
-
-func TestEntryPanicf(t *testing.T) {
- errBoom := fmt.Errorf("boom again")
-
- defer func() {
- p := recover()
- assert.NotNil(t, p)
-
- switch pVal := p.(type) {
- case *Entry:
- assert.Equal(t, "kaboom true", pVal.Message)
- assert.Equal(t, errBoom, pVal.Data["err"])
- default:
- t.Fatalf("want type *Entry, got %T: %#v", pVal, pVal)
- }
- }()
-
- logger := New()
- logger.Out = &bytes.Buffer{}
- entry := NewEntry(logger)
- entry.WithField("err", errBoom).Panicf("kaboom %v", true)
-}
diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/Sirupsen/logrus/exported.go
deleted file mode 100644
index fd092fc..0000000
--- a/vendor/github.com/Sirupsen/logrus/exported.go
+++ /dev/null
@@ -1,186 +0,0 @@
-package logrus
-
-import (
- "io"
-)
-
-var (
- // std is the name of the standard logger in stdlib `log`
- std = New()
-)
-
-func StandardLogger() *Logger {
- return std
-}
-
-// SetOutput sets the standard logger output.
-func SetOutput(out io.Writer) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Out = out
-}
-
-// SetFormatter sets the standard logger formatter.
-func SetFormatter(formatter Formatter) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Formatter = formatter
-}
-
-// SetLevel sets the standard logger level.
-func SetLevel(level Level) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Level = level
-}
-
-// GetLevel returns the standard logger level.
-func GetLevel() Level {
- return std.Level
-}
-
-// AddHook adds a hook to the standard logger hooks.
-func AddHook(hook Hook) {
- std.mu.Lock()
- defer std.mu.Unlock()
- std.Hooks.Add(hook)
-}
-
-// WithField creates an entry from the standard logger and adds a field to
-// it. If you want multiple fields, use `WithFields`.
-//
-// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
-// or Panic on the Entry it returns.
-func WithField(key string, value interface{}) *Entry {
- return std.WithField(key, value)
-}
-
-// WithFields creates an entry from the standard logger and adds multiple
-// fields to it. This is simply a helper for `WithField`, invoking it
-// once for each field.
-//
-// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
-// or Panic on the Entry it returns.
-func WithFields(fields Fields) *Entry {
- return std.WithFields(fields)
-}
-
-// Debug logs a message at level Debug on the standard logger.
-func Debug(args ...interface{}) {
- std.Debug(args...)
-}
-
-// Print logs a message at level Info on the standard logger.
-func Print(args ...interface{}) {
- std.Print(args...)
-}
-
-// Info logs a message at level Info on the standard logger.
-func Info(args ...interface{}) {
- std.Info(args...)
-}
-
-// Warn logs a message at level Warn on the standard logger.
-func Warn(args ...interface{}) {
- std.Warn(args...)
-}
-
-// Warning logs a message at level Warn on the standard logger.
-func Warning(args ...interface{}) {
- std.Warning(args...)
-}
-
-// Error logs a message at level Error on the standard logger.
-func Error(args ...interface{}) {
- std.Error(args...)
-}
-
-// Panic logs a message at level Panic on the standard logger.
-func Panic(args ...interface{}) {
- std.Panic(args...)
-}
-
-// Fatal logs a message at level Fatal on the standard logger.
-func Fatal(args ...interface{}) {
- std.Fatal(args...)
-}
-
-// Debugf logs a message at level Debug on the standard logger.
-func Debugf(format string, args ...interface{}) {
- std.Debugf(format, args...)
-}
-
-// Printf logs a message at level Info on the standard logger.
-func Printf(format string, args ...interface{}) {
- std.Printf(format, args...)
-}
-
-// Infof logs a message at level Info on the standard logger.
-func Infof(format string, args ...interface{}) {
- std.Infof(format, args...)
-}
-
-// Warnf logs a message at level Warn on the standard logger.
-func Warnf(format string, args ...interface{}) {
- std.Warnf(format, args...)
-}
-
-// Warningf logs a message at level Warn on the standard logger.
-func Warningf(format string, args ...interface{}) {
- std.Warningf(format, args...)
-}
-
-// Errorf logs a message at level Error on the standard logger.
-func Errorf(format string, args ...interface{}) {
- std.Errorf(format, args...)
-}
-
-// Panicf logs a message at level Panic on the standard logger.
-func Panicf(format string, args ...interface{}) {
- std.Panicf(format, args...)
-}
-
-// Fatalf logs a message at level Fatal on the standard logger.
-func Fatalf(format string, args ...interface{}) {
- std.Fatalf(format, args...)
-}
-
-// Debugln logs a message at level Debug on the standard logger.
-func Debugln(args ...interface{}) {
- std.Debugln(args...)
-}
-
-// Println logs a message at level Info on the standard logger.
-func Println(args ...interface{}) {
- std.Println(args...)
-}
-
-// Infoln logs a message at level Info on the standard logger.
-func Infoln(args ...interface{}) {
- std.Infoln(args...)
-}
-
-// Warnln logs a message at level Warn on the standard logger.
-func Warnln(args ...interface{}) {
- std.Warnln(args...)
-}
-
-// Warningln logs a message at level Warn on the standard logger.
-func Warningln(args ...interface{}) {
- std.Warningln(args...)
-}
-
-// Errorln logs a message at level Error on the standard logger.
-func Errorln(args ...interface{}) {
- std.Errorln(args...)
-}
-
-// Panicln logs a message at level Panic on the standard logger.
-func Panicln(args ...interface{}) {
- std.Panicln(args...)
-}
-
-// Fatalln logs a message at level Fatal on the standard logger.
-func Fatalln(args ...interface{}) {
- std.Fatalln(args...)
-}
diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/Sirupsen/logrus/formatter.go
deleted file mode 100644
index 038ce9f..0000000
--- a/vendor/github.com/Sirupsen/logrus/formatter.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package logrus
-
-// The Formatter interface is used to implement a custom Formatter. It takes an
-// `Entry`. It exposes all the fields, including the default ones:
-//
-// * `entry.Data["msg"]`. The message passed from Info, Warn, Error ..
-// * `entry.Data["time"]`. The timestamp.
-// * `entry.Data["level"]. The level the entry was logged at.
-//
-// Any additional fields added with `WithField` or `WithFields` are also in
-// `entry.Data`. Format is expected to return an array of bytes which are then
-// logged to `logger.Out`.
-type Formatter interface {
- Format(*Entry) ([]byte, error)
-}
-
-// This is to not silently overwrite `time`, `msg` and `level` fields when
-// dumping it. If this code wasn't there doing:
-//
-// logrus.WithField("level", 1).Info("hello")
-//
-// Would just silently drop the user provided level. Instead with this code
-// it'll logged as:
-//
-// {"level": "info", "fields.level": 1, "msg": "hello", "time": "..."}
-//
-// It's not exported because it's still using Data in an opinionated way. It's to
-// avoid code duplication between the two default formatters.
-func prefixFieldClashes(data Fields) {
- _, ok := data["time"]
- if ok {
- data["fields.time"] = data["time"]
- }
-
- _, ok = data["msg"]
- if ok {
- data["fields.msg"] = data["msg"]
- }
-
- _, ok = data["level"]
- if ok {
- data["fields.level"] = data["level"]
- }
-}
diff --git a/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go b/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go
deleted file mode 100644
index 77989da..0000000
--- a/vendor/github.com/Sirupsen/logrus/formatter_bench_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package logrus
-
-import (
- "testing"
- "time"
-)
-
-// smallFields is a small size data set for benchmarking
-var smallFields = Fields{
- "foo": "bar",
- "baz": "qux",
- "one": "two",
- "three": "four",
-}
-
-// largeFields is a large size data set for benchmarking
-var largeFields = Fields{
- "foo": "bar",
- "baz": "qux",
- "one": "two",
- "three": "four",
- "five": "six",
- "seven": "eight",
- "nine": "ten",
- "eleven": "twelve",
- "thirteen": "fourteen",
- "fifteen": "sixteen",
- "seventeen": "eighteen",
- "nineteen": "twenty",
- "a": "b",
- "c": "d",
- "e": "f",
- "g": "h",
- "i": "j",
- "k": "l",
- "m": "n",
- "o": "p",
- "q": "r",
- "s": "t",
- "u": "v",
- "w": "x",
- "y": "z",
- "this": "will",
- "make": "thirty",
- "entries": "yeah",
-}
-
-func BenchmarkSmallTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{DisableColors: true}, smallFields)
-}
-
-func BenchmarkLargeTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{DisableColors: true}, largeFields)
-}
-
-func BenchmarkSmallColoredTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{ForceColors: true}, smallFields)
-}
-
-func BenchmarkLargeColoredTextFormatter(b *testing.B) {
- doBenchmark(b, &TextFormatter{ForceColors: true}, largeFields)
-}
-
-func BenchmarkSmallJSONFormatter(b *testing.B) {
- doBenchmark(b, &JSONFormatter{}, smallFields)
-}
-
-func BenchmarkLargeJSONFormatter(b *testing.B) {
- doBenchmark(b, &JSONFormatter{}, largeFields)
-}
-
-func doBenchmark(b *testing.B, formatter Formatter, fields Fields) {
- entry := &Entry{
- Time: time.Time{},
- Level: InfoLevel,
- Message: "message",
- Data: fields,
- }
- var d []byte
- var err error
- for i := 0; i < b.N; i++ {
- d, err = formatter.Format(entry)
- if err != nil {
- b.Fatal(err)
- }
- b.SetBytes(int64(len(d)))
- }
-}
diff --git a/vendor/github.com/Sirupsen/logrus/hook_test.go b/vendor/github.com/Sirupsen/logrus/hook_test.go
deleted file mode 100644
index 13f34cb..0000000
--- a/vendor/github.com/Sirupsen/logrus/hook_test.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package logrus
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-type TestHook struct {
- Fired bool
-}
-
-func (hook *TestHook) Fire(entry *Entry) error {
- hook.Fired = true
- return nil
-}
-
-func (hook *TestHook) Levels() []Level {
- return []Level{
- DebugLevel,
- InfoLevel,
- WarnLevel,
- ErrorLevel,
- FatalLevel,
- PanicLevel,
- }
-}
-
-func TestHookFires(t *testing.T) {
- hook := new(TestHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- assert.Equal(t, hook.Fired, false)
-
- log.Print("test")
- }, func(fields Fields) {
- assert.Equal(t, hook.Fired, true)
- })
-}
-
-type ModifyHook struct {
-}
-
-func (hook *ModifyHook) Fire(entry *Entry) error {
- entry.Data["wow"] = "whale"
- return nil
-}
-
-func (hook *ModifyHook) Levels() []Level {
- return []Level{
- DebugLevel,
- InfoLevel,
- WarnLevel,
- ErrorLevel,
- FatalLevel,
- PanicLevel,
- }
-}
-
-func TestHookCanModifyEntry(t *testing.T) {
- hook := new(ModifyHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- log.WithField("wow", "elephant").Print("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["wow"], "whale")
- })
-}
-
-func TestCanFireMultipleHooks(t *testing.T) {
- hook1 := new(ModifyHook)
- hook2 := new(TestHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook1)
- log.Hooks.Add(hook2)
-
- log.WithField("wow", "elephant").Print("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["wow"], "whale")
- assert.Equal(t, hook2.Fired, true)
- })
-}
-
-type ErrorHook struct {
- Fired bool
-}
-
-func (hook *ErrorHook) Fire(entry *Entry) error {
- hook.Fired = true
- return nil
-}
-
-func (hook *ErrorHook) Levels() []Level {
- return []Level{
- ErrorLevel,
- }
-}
-
-func TestErrorHookShouldntFireOnInfo(t *testing.T) {
- hook := new(ErrorHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- log.Info("test")
- }, func(fields Fields) {
- assert.Equal(t, hook.Fired, false)
- })
-}
-
-func TestErrorHookShouldFireOnError(t *testing.T) {
- hook := new(ErrorHook)
-
- LogAndAssertJSON(t, func(log *Logger) {
- log.Hooks.Add(hook)
- log.Error("test")
- }, func(fields Fields) {
- assert.Equal(t, hook.Fired, true)
- })
-}
diff --git a/vendor/github.com/Sirupsen/logrus/hooks.go b/vendor/github.com/Sirupsen/logrus/hooks.go
deleted file mode 100644
index 0da2b36..0000000
--- a/vendor/github.com/Sirupsen/logrus/hooks.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package logrus
-
-// A hook to be fired when logging on the logging levels returned from
-// `Levels()` on your implementation of the interface. Note that this is not
-// fired in a goroutine or a channel with workers, you should handle such
-// functionality yourself if your call is non-blocking and you don't wish for
-// the logging calls for levels returned from `Levels()` to block.
-type Hook interface {
- Levels() []Level
- Fire(*Entry) error
-}
-
-// Internal type for storing the hooks on a logger instance.
-type levelHooks map[Level][]Hook
-
-// Add a hook to an instance of logger. This is called with
-// `log.Hooks.Add(new(MyHook))` where `MyHook` implements the `Hook` interface.
-func (hooks levelHooks) Add(hook Hook) {
- for _, level := range hook.Levels() {
- hooks[level] = append(hooks[level], hook)
- }
-}
-
-// Fire all the hooks for the passed level. Used by `entry.log` to fire
-// appropriate hooks for a log entry.
-func (hooks levelHooks) Fire(level Level, entry *Entry) error {
- for _, hook := range hooks[level] {
- if err := hook.Fire(entry); err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/Sirupsen/logrus/json_formatter.go
deleted file mode 100644
index b09227c..0000000
--- a/vendor/github.com/Sirupsen/logrus/json_formatter.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package logrus
-
-import (
- "encoding/json"
- "fmt"
- "time"
-)
-
-type JSONFormatter struct{}
-
-func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
- data := make(Fields, len(entry.Data)+3)
- for k, v := range entry.Data {
- data[k] = v
- }
- prefixFieldClashes(data)
- data["time"] = entry.Time.Format(time.RFC3339)
- data["msg"] = entry.Message
- data["level"] = entry.Level.String()
-
- serialized, err := json.Marshal(data)
- if err != nil {
- return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
- }
- return append(serialized, '\n'), nil
-}
diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/Sirupsen/logrus/logger.go
deleted file mode 100644
index b392e54..0000000
--- a/vendor/github.com/Sirupsen/logrus/logger.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package logrus
-
-import (
- "io"
- "os"
- "sync"
-)
-
-type Logger struct {
- // The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
- // file, or leave it default which is `os.Stdout`. You can also set this to
- // something more adventorous, such as logging to Kafka.
- Out io.Writer
- // Hooks for the logger instance. These allow firing events based on logging
- // levels and log entries. For example, to send errors to an error tracking
- // service, log to StatsD or dump the core on fatal errors.
- Hooks levelHooks
- // All log entries pass through the formatter before logged to Out. The
- // included formatters are `TextFormatter` and `JSONFormatter` for which
- // TextFormatter is the default. In development (when a TTY is attached) it
- // logs with colors, but to a file it wouldn't. You can easily implement your
- // own that implements the `Formatter` interface, see the `README` or included
- // formatters for examples.
- Formatter Formatter
- // The logging level the logger should log at. This is typically (and defaults
- // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
- // logged. `logrus.Debug` is useful in
- Level Level
- // Used to sync writing to the log.
- mu sync.Mutex
-}
-
-// Creates a new logger. Configuration should be set by changing `Formatter`,
-// `Out` and `Hooks` directly on the default logger instance. You can also just
-// instantiate your own:
-//
-// var log = &Logger{
-// Out: os.Stderr,
-// Formatter: new(JSONFormatter),
-// Hooks: make(levelHooks),
-// Level: logrus.DebugLevel,
-// }
-//
-// It's recommended to make this a global instance called `log`.
-func New() *Logger {
- return &Logger{
- Out: os.Stdout,
- Formatter: new(TextFormatter),
- Hooks: make(levelHooks),
- Level: InfoLevel,
- }
-}
-
-// Adds a field to the log entry, note that you it doesn't log until you call
-// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
-// Ff you want multiple fields, use `WithFields`.
-func (logger *Logger) WithField(key string, value interface{}) *Entry {
- return NewEntry(logger).WithField(key, value)
-}
-
-// Adds a struct of fields to the log entry. All it does is call `WithField` for
-// each `Field`.
-func (logger *Logger) WithFields(fields Fields) *Entry {
- return NewEntry(logger).WithFields(fields)
-}
-
-func (logger *Logger) Debugf(format string, args ...interface{}) {
- NewEntry(logger).Debugf(format, args...)
-}
-
-func (logger *Logger) Infof(format string, args ...interface{}) {
- NewEntry(logger).Infof(format, args...)
-}
-
-func (logger *Logger) Printf(format string, args ...interface{}) {
- NewEntry(logger).Printf(format, args...)
-}
-
-func (logger *Logger) Warnf(format string, args ...interface{}) {
- NewEntry(logger).Warnf(format, args...)
-}
-
-func (logger *Logger) Warningf(format string, args ...interface{}) {
- NewEntry(logger).Warnf(format, args...)
-}
-
-func (logger *Logger) Errorf(format string, args ...interface{}) {
- NewEntry(logger).Errorf(format, args...)
-}
-
-func (logger *Logger) Fatalf(format string, args ...interface{}) {
- NewEntry(logger).Fatalf(format, args...)
-}
-
-func (logger *Logger) Panicf(format string, args ...interface{}) {
- NewEntry(logger).Panicf(format, args...)
-}
-
-func (logger *Logger) Debug(args ...interface{}) {
- NewEntry(logger).Debug(args...)
-}
-
-func (logger *Logger) Info(args ...interface{}) {
- NewEntry(logger).Info(args...)
-}
-
-func (logger *Logger) Print(args ...interface{}) {
- NewEntry(logger).Info(args...)
-}
-
-func (logger *Logger) Warn(args ...interface{}) {
- NewEntry(logger).Warn(args...)
-}
-
-func (logger *Logger) Warning(args ...interface{}) {
- NewEntry(logger).Warn(args...)
-}
-
-func (logger *Logger) Error(args ...interface{}) {
- NewEntry(logger).Error(args...)
-}
-
-func (logger *Logger) Fatal(args ...interface{}) {
- NewEntry(logger).Fatal(args...)
-}
-
-func (logger *Logger) Panic(args ...interface{}) {
- NewEntry(logger).Panic(args...)
-}
-
-func (logger *Logger) Debugln(args ...interface{}) {
- NewEntry(logger).Debugln(args...)
-}
-
-func (logger *Logger) Infoln(args ...interface{}) {
- NewEntry(logger).Infoln(args...)
-}
-
-func (logger *Logger) Println(args ...interface{}) {
- NewEntry(logger).Println(args...)
-}
-
-func (logger *Logger) Warnln(args ...interface{}) {
- NewEntry(logger).Warnln(args...)
-}
-
-func (logger *Logger) Warningln(args ...interface{}) {
- NewEntry(logger).Warnln(args...)
-}
-
-func (logger *Logger) Errorln(args ...interface{}) {
- NewEntry(logger).Errorln(args...)
-}
-
-func (logger *Logger) Fatalln(args ...interface{}) {
- NewEntry(logger).Fatalln(args...)
-}
-
-func (logger *Logger) Panicln(args ...interface{}) {
- NewEntry(logger).Panicln(args...)
-}
diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/Sirupsen/logrus/logrus.go
deleted file mode 100644
index 43ee12e..0000000
--- a/vendor/github.com/Sirupsen/logrus/logrus.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package logrus
-
-import (
- "fmt"
- "log"
-)
-
-// Fields type, used to pass to `WithFields`.
-type Fields map[string]interface{}
-
-// Level type
-type Level uint8
-
-// Convert the Level to a string. E.g. PanicLevel becomes "panic".
-func (level Level) String() string {
- switch level {
- case DebugLevel:
- return "debug"
- case InfoLevel:
- return "info"
- case WarnLevel:
- return "warning"
- case ErrorLevel:
- return "error"
- case FatalLevel:
- return "fatal"
- case PanicLevel:
- return "panic"
- }
-
- return "unknown"
-}
-
-// ParseLevel takes a string level and returns the Logrus log level constant.
-func ParseLevel(lvl string) (Level, error) {
- switch lvl {
- case "panic":
- return PanicLevel, nil
- case "fatal":
- return FatalLevel, nil
- case "error":
- return ErrorLevel, nil
- case "warn", "warning":
- return WarnLevel, nil
- case "info":
- return InfoLevel, nil
- case "debug":
- return DebugLevel, nil
- }
-
- var l Level
- return l, fmt.Errorf("not a valid logrus Level: %q", lvl)
-}
-
-// These are the different logging levels. You can set the logging level to log
-// on your instance of logger, obtained with `logrus.New()`.
-const (
- // PanicLevel level, highest level of severity. Logs and then calls panic with the
- // message passed to Debug, Info, ...
- PanicLevel Level = iota
- // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
- // logging level is set to Panic.
- FatalLevel
- // ErrorLevel level. Logs. Used for errors that should definitely be noted.
- // Commonly used for hooks to send errors to an error tracking service.
- ErrorLevel
- // WarnLevel level. Non-critical entries that deserve eyes.
- WarnLevel
- // InfoLevel level. General operational entries about what's going on inside the
- // application.
- InfoLevel
- // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
- DebugLevel
-)
-
-// Won't compile if StdLogger can't be realized by a log.Logger
-var _ StdLogger = &log.Logger{}
-
-// StdLogger is what your logrus-enabled library should take, that way
-// it'll accept a stdlib logger and a logrus logger. There's no standard
-// interface, this is the closest we get, unfortunately.
-type StdLogger interface {
- Print(...interface{})
- Printf(string, ...interface{})
- Println(...interface{})
-
- Fatal(...interface{})
- Fatalf(string, ...interface{})
- Fatalln(...interface{})
-
- Panic(...interface{})
- Panicf(string, ...interface{})
- Panicln(...interface{})
-}
diff --git a/vendor/github.com/Sirupsen/logrus/logrus_test.go b/vendor/github.com/Sirupsen/logrus/logrus_test.go
deleted file mode 100644
index 7f52c6f..0000000
--- a/vendor/github.com/Sirupsen/logrus/logrus_test.go
+++ /dev/null
@@ -1,283 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "encoding/json"
- "strconv"
- "strings"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func LogAndAssertJSON(t *testing.T, log func(*Logger), assertions func(fields Fields)) {
- var buffer bytes.Buffer
- var fields Fields
-
- logger := New()
- logger.Out = &buffer
- logger.Formatter = new(JSONFormatter)
-
- log(logger)
-
- err := json.Unmarshal(buffer.Bytes(), &fields)
- assert.Nil(t, err)
-
- assertions(fields)
-}
-
-func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields map[string]string)) {
- var buffer bytes.Buffer
-
- logger := New()
- logger.Out = &buffer
- logger.Formatter = &TextFormatter{
- DisableColors: true,
- }
-
- log(logger)
-
- fields := make(map[string]string)
- for _, kv := range strings.Split(buffer.String(), " ") {
- if !strings.Contains(kv, "=") {
- continue
- }
- kvArr := strings.Split(kv, "=")
- key := strings.TrimSpace(kvArr[0])
- val := kvArr[1]
- if kvArr[1][0] == '"' {
- var err error
- val, err = strconv.Unquote(val)
- assert.NoError(t, err)
- }
- fields[key] = val
- }
- assertions(fields)
-}
-
-func TestPrint(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Print("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["level"], "info")
- })
-}
-
-func TestInfo(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["level"], "info")
- })
-}
-
-func TestWarn(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Warn("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["level"], "warning")
- })
-}
-
-func TestInfolnShouldAddSpacesBetweenStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln("test", "test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test test")
- })
-}
-
-func TestInfolnShouldAddSpacesBetweenStringAndNonstring(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln("test", 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test 10")
- })
-}
-
-func TestInfolnShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln(10, 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "10 10")
- })
-}
-
-func TestInfoShouldAddSpacesBetweenTwoNonStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Infoln(10, 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "10 10")
- })
-}
-
-func TestInfoShouldNotAddSpacesBetweenStringAndNonstring(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Info("test", 10)
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test10")
- })
-}
-
-func TestInfoShouldNotAddSpacesBetweenStrings(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.Info("test", "test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "testtest")
- })
-}
-
-func TestWithFieldsShouldAllowAssignments(t *testing.T) {
- var buffer bytes.Buffer
- var fields Fields
-
- logger := New()
- logger.Out = &buffer
- logger.Formatter = new(JSONFormatter)
-
- localLog := logger.WithFields(Fields{
- "key1": "value1",
- })
-
- localLog.WithField("key2", "value2").Info("test")
- err := json.Unmarshal(buffer.Bytes(), &fields)
- assert.Nil(t, err)
-
- assert.Equal(t, "value2", fields["key2"])
- assert.Equal(t, "value1", fields["key1"])
-
- buffer = bytes.Buffer{}
- fields = Fields{}
- localLog.Info("test")
- err = json.Unmarshal(buffer.Bytes(), &fields)
- assert.Nil(t, err)
-
- _, ok := fields["key2"]
- assert.Equal(t, false, ok)
- assert.Equal(t, "value1", fields["key1"])
-}
-
-func TestUserSuppliedFieldDoesNotOverwriteDefaults(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("msg", "hello").Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- })
-}
-
-func TestUserSuppliedMsgFieldHasPrefix(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("msg", "hello").Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["msg"], "test")
- assert.Equal(t, fields["fields.msg"], "hello")
- })
-}
-
-func TestUserSuppliedTimeFieldHasPrefix(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("time", "hello").Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["fields.time"], "hello")
- })
-}
-
-func TestUserSuppliedLevelFieldHasPrefix(t *testing.T) {
- LogAndAssertJSON(t, func(log *Logger) {
- log.WithField("level", 1).Info("test")
- }, func(fields Fields) {
- assert.Equal(t, fields["level"], "info")
- assert.Equal(t, fields["fields.level"], 1)
- })
-}
-
-func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
- LogAndAssertText(t, func(log *Logger) {
- ll := log.WithField("herp", "derp")
- ll.Info("hello")
- ll.Info("bye")
- }, func(fields map[string]string) {
- for _, fieldName := range []string{"fields.level", "fields.time", "fields.msg"} {
- if _, ok := fields[fieldName]; ok {
- t.Fatalf("should not have prefixed %q: %v", fieldName, fields)
- }
- }
- })
-}
-
-func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
-
- var buffer bytes.Buffer
- var fields Fields
-
- logger := New()
- logger.Out = &buffer
- logger.Formatter = new(JSONFormatter)
-
- llog := logger.WithField("context", "eating raw fish")
-
- llog.Info("looks delicious")
-
- err := json.Unmarshal(buffer.Bytes(), &fields)
- assert.NoError(t, err, "should have decoded first message")
- assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
- assert.Equal(t, fields["msg"], "looks delicious")
- assert.Equal(t, fields["context"], "eating raw fish")
-
- buffer.Reset()
-
- llog.Warn("omg it is!")
-
- err = json.Unmarshal(buffer.Bytes(), &fields)
- assert.NoError(t, err, "should have decoded second message")
- assert.Equal(t, len(fields), 4, "should only have msg/time/level/context fields")
- assert.Equal(t, fields["msg"], "omg it is!")
- assert.Equal(t, fields["context"], "eating raw fish")
- assert.Nil(t, fields["fields.msg"], "should not have prefixed previous `msg` entry")
-
-}
-
-func TestConvertLevelToString(t *testing.T) {
- assert.Equal(t, "debug", DebugLevel.String())
- assert.Equal(t, "info", InfoLevel.String())
- assert.Equal(t, "warning", WarnLevel.String())
- assert.Equal(t, "error", ErrorLevel.String())
- assert.Equal(t, "fatal", FatalLevel.String())
- assert.Equal(t, "panic", PanicLevel.String())
-}
-
-func TestParseLevel(t *testing.T) {
- l, err := ParseLevel("panic")
- assert.Nil(t, err)
- assert.Equal(t, PanicLevel, l)
-
- l, err = ParseLevel("fatal")
- assert.Nil(t, err)
- assert.Equal(t, FatalLevel, l)
-
- l, err = ParseLevel("error")
- assert.Nil(t, err)
- assert.Equal(t, ErrorLevel, l)
-
- l, err = ParseLevel("warn")
- assert.Nil(t, err)
- assert.Equal(t, WarnLevel, l)
-
- l, err = ParseLevel("warning")
- assert.Nil(t, err)
- assert.Equal(t, WarnLevel, l)
-
- l, err = ParseLevel("info")
- assert.Nil(t, err)
- assert.Equal(t, InfoLevel, l)
-
- l, err = ParseLevel("debug")
- assert.Nil(t, err)
- assert.Equal(t, DebugLevel, l)
-
- l, err = ParseLevel("invalid")
- assert.Equal(t, "not a valid logrus Level: \"invalid\"", err.Error())
-}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_darwin.go b/vendor/github.com/Sirupsen/logrus/terminal_darwin.go
deleted file mode 100644
index 8fe02a4..0000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_darwin.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2013 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 logrus
-
-import "syscall"
-
-const ioctlReadTermios = syscall.TIOCGETA
-
-type Termios syscall.Termios
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_freebsd.go b/vendor/github.com/Sirupsen/logrus/terminal_freebsd.go
deleted file mode 100644
index 0428ee5..0000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_freebsd.go
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- Go 1.2 doesn't include Termios for FreeBSD. This should be added in 1.3 and this could be merged with terminal_darwin.
-*/
-package logrus
-
-import (
- "syscall"
-)
-
-const ioctlReadTermios = syscall.TIOCGETA
-
-type Termios struct {
- Iflag uint32
- Oflag uint32
- Cflag uint32
- Lflag uint32
- Cc [20]uint8
- Ispeed uint32
- Ospeed uint32
-}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/Sirupsen/logrus/terminal_linux.go
deleted file mode 100644
index a2c0b40..0000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_linux.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2013 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 logrus
-
-import "syscall"
-
-const ioctlReadTermios = syscall.TCGETS
-
-type Termios syscall.Termios
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go b/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
deleted file mode 100644
index 80edd32..0000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2011 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 linux,!appengine darwin freebsd openbsd
-
-package logrus
-
-import (
- "syscall"
- "unsafe"
-)
-
-// IsTerminal returns true if the given file descriptor is a terminal.
-func IsTerminal() bool {
- fd := syscall.Stdout
- var termios Termios
- _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
- return err == 0
-}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_openbsd.go b/vendor/github.com/Sirupsen/logrus/terminal_openbsd.go
deleted file mode 100644
index d238bfa..0000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_openbsd.go
+++ /dev/null
@@ -1,8 +0,0 @@
-
-package logrus
-
-import "syscall"
-
-const ioctlReadTermios = syscall.TIOCGETA
-
-type Termios syscall.Termios
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_windows.go
deleted file mode 100644
index 2e09f6f..0000000
--- a/vendor/github.com/Sirupsen/logrus/terminal_windows.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Based on ssh/terminal:
-// Copyright 2011 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 windows
-
-package logrus
-
-import (
- "syscall"
- "unsafe"
-)
-
-var kernel32 = syscall.NewLazyDLL("kernel32.dll")
-
-var (
- procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
-)
-
-// IsTerminal returns true if the given file descriptor is a terminal.
-func IsTerminal() bool {
- fd := syscall.Stdout
- var st uint32
- r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0)
- return r != 0 && e == 0
-}
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go
deleted file mode 100644
index 78e7889..0000000
--- a/vendor/github.com/Sirupsen/logrus/text_formatter.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "fmt"
- "regexp"
- "sort"
- "strings"
- "time"
-)
-
-const (
- nocolor = 0
- red = 31
- green = 32
- yellow = 33
- blue = 34
-)
-
-var (
- baseTimestamp time.Time
- isTerminal bool
- noQuoteNeeded *regexp.Regexp
-)
-
-func init() {
- baseTimestamp = time.Now()
- isTerminal = IsTerminal()
-}
-
-func miniTS() int {
- return int(time.Since(baseTimestamp) / time.Second)
-}
-
-type TextFormatter struct {
- // Set to true to bypass checking for a TTY before outputting colors.
- ForceColors bool
- DisableColors bool
- // Set to true to disable timestamp logging (useful when the output
- // is redirected to a logging system already adding a timestamp)
- DisableTimestamp bool
-}
-
-func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
-
- var keys []string
- for k := range entry.Data {
- keys = append(keys, k)
- }
- sort.Strings(keys)
-
- b := &bytes.Buffer{}
-
- prefixFieldClashes(entry.Data)
-
- isColored := (f.ForceColors || isTerminal) && !f.DisableColors
-
- if isColored {
- printColored(b, entry, keys)
- } else {
- if !f.DisableTimestamp {
- f.appendKeyValue(b, "time", entry.Time.Format(time.RFC3339))
- }
- f.appendKeyValue(b, "level", entry.Level.String())
- f.appendKeyValue(b, "msg", entry.Message)
- for _, key := range keys {
- f.appendKeyValue(b, key, entry.Data[key])
- }
- }
-
- b.WriteByte('\n')
- return b.Bytes(), nil
-}
-
-func printColored(b *bytes.Buffer, entry *Entry, keys []string) {
- var levelColor int
- switch entry.Level {
- case WarnLevel:
- levelColor = yellow
- case ErrorLevel, FatalLevel, PanicLevel:
- levelColor = red
- default:
- levelColor = blue
- }
-
- levelText := strings.ToUpper(entry.Level.String())[0:4]
-
- fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, miniTS(), entry.Message)
- for _, k := range keys {
- v := entry.Data[k]
- fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%v", levelColor, k, v)
- }
-}
-
-func needsQuoting(text string) bool {
- for _, ch := range text {
- if !((ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch < '9') ||
- ch == '-' || ch == '.') {
- return false
- }
- }
- return true
-}
-
-func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key, value interface{}) {
- switch value.(type) {
- case string:
- if needsQuoting(value.(string)) {
- fmt.Fprintf(b, "%v=%s ", key, value)
- } else {
- fmt.Fprintf(b, "%v=%q ", key, value)
- }
- case error:
- if needsQuoting(value.(error).Error()) {
- fmt.Fprintf(b, "%v=%s ", key, value)
- } else {
- fmt.Fprintf(b, "%v=%q ", key, value)
- }
- default:
- fmt.Fprintf(b, "%v=%v ", key, value)
- }
-}
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter_test.go b/vendor/github.com/Sirupsen/logrus/text_formatter_test.go
deleted file mode 100644
index f604f1b..0000000
--- a/vendor/github.com/Sirupsen/logrus/text_formatter_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package logrus
-
-import (
- "bytes"
- "errors"
-
- "testing"
-)
-
-func TestQuoting(t *testing.T) {
- tf := &TextFormatter{DisableColors: true}
-
- checkQuoting := func(q bool, value interface{}) {
- b, _ := tf.Format(WithField("test", value))
- idx := bytes.Index(b, ([]byte)("test="))
- cont := bytes.Contains(b[idx+5:], []byte{'"'})
- if cont != q {
- if q {
- t.Errorf("quoting expected for: %#v", value)
- } else {
- t.Errorf("quoting not expected for: %#v", value)
- }
- }
- }
-
- checkQuoting(false, "abcd")
- checkQuoting(false, "v1.0")
- checkQuoting(true, "/foobar")
- checkQuoting(true, "x y")
- checkQuoting(true, "x,y")
- checkQuoting(false, errors.New("invalid"))
- checkQuoting(true, errors.New("invalid argument"))
-}
diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/Sirupsen/logrus/writer.go
deleted file mode 100644
index 90d3e01..0000000
--- a/vendor/github.com/Sirupsen/logrus/writer.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package logrus
-
-import (
- "bufio"
- "io"
- "runtime"
-)
-
-func (logger *Logger) Writer() (*io.PipeWriter) {
- reader, writer := io.Pipe()
-
- go logger.writerScanner(reader)
- runtime.SetFinalizer(writer, writerFinalizer)
-
- return writer
-}
-
-func (logger *Logger) writerScanner(reader *io.PipeReader) {
- scanner := bufio.NewScanner(reader)
- for scanner.Scan() {
- logger.Print(scanner.Text())
- }
- if err := scanner.Err(); err != nil {
- logger.Errorf("Error while reading from Writer: %s", err)
- }
- reader.Close()
-}
-
-func writerFinalizer(writer *io.PipeWriter) {
- writer.Close()
-}
diff --git a/vendor/github.com/docker/docker/LICENSE b/vendor/github.com/docker/docker/LICENSE
deleted file mode 100644
index 8f3fee6..0000000
--- a/vendor/github.com/docker/docker/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- https://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- Copyright 2013-2016 Docker, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/github.com/docker/docker/NOTICE b/vendor/github.com/docker/docker/NOTICE
deleted file mode 100644
index 8a37c1c..0000000
--- a/vendor/github.com/docker/docker/NOTICE
+++ /dev/null
@@ -1,19 +0,0 @@
-Docker
-Copyright 2012-2016 Docker, Inc.
-
-This product includes software developed at Docker, Inc. (https://www.docker.com).
-
-This product contains software (https://github.com/kr/pty) developed
-by Keith Rarick, licensed under the MIT License.
-
-The following is courtesy of our legal counsel:
-
-
-Use and transfer of Docker may be subject to certain restrictions by the
-United States and other governments.
-It is your responsibility to ensure that your use and/or transfer does not
-violate applicable laws.
-
-For more information, please see https://www.bis.doc.gov
-
-See also https://www.apache.org/dev/crypto.html and/or seek legal counsel.
diff --git a/vendor/github.com/docker/docker/opts/hosts.go b/vendor/github.com/docker/docker/opts/hosts.go
deleted file mode 100644
index ad16759..0000000
--- a/vendor/github.com/docker/docker/opts/hosts.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package opts
-
-import (
- "fmt"
- "net"
- "net/url"
- "strconv"
- "strings"
-)
-
-var (
- // DefaultHTTPPort Default HTTP Port used if only the protocol is provided to -H flag e.g. docker daemon -H tcp://
- // These are the IANA registered port numbers for use with Docker
- // see http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=docker
- DefaultHTTPPort = 2375 // Default HTTP Port
- // DefaultTLSHTTPPort Default HTTP Port used when TLS enabled
- DefaultTLSHTTPPort = 2376 // Default TLS encrypted HTTP Port
- // DefaultUnixSocket Path for the unix socket.
- // Docker daemon by default always listens on the default unix socket
- DefaultUnixSocket = "/var/run/docker.sock"
- // DefaultTCPHost constant defines the default host string used by docker on Windows
- DefaultTCPHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultHTTPPort)
- // DefaultTLSHost constant defines the default host string used by docker for TLS sockets
- DefaultTLSHost = fmt.Sprintf("tcp://%s:%d", DefaultHTTPHost, DefaultTLSHTTPPort)
- // DefaultNamedPipe defines the default named pipe used by docker on Windows
- DefaultNamedPipe = `//./pipe/docker_engine`
-)
-
-// ValidateHost validates that the specified string is a valid host and returns it.
-func ValidateHost(val string) (string, error) {
- host := strings.TrimSpace(val)
- // The empty string means default and is not handled by parseDockerDaemonHost
- if host != "" {
- _, err := parseDockerDaemonHost(host)
- if err != nil {
- return val, err
- }
- }
- // Note: unlike most flag validators, we don't return the mutated value here
- // we need to know what the user entered later (using ParseHost) to adjust for tls
- return val, nil
-}
-
-// ParseHost and set defaults for a Daemon host string
-func ParseHost(defaultToTLS bool, val string) (string, error) {
- host := strings.TrimSpace(val)
- if host == "" {
- if defaultToTLS {
- host = DefaultTLSHost
- } else {
- host = DefaultHost
- }
- } else {
- var err error
- host, err = parseDockerDaemonHost(host)
- if err != nil {
- return val, err
- }
- }
- return host, nil
-}
-
-// parseDockerDaemonHost parses the specified address and returns an address that will be used as the host.
-// Depending of the address specified, this may return one of the global Default* strings defined in hosts.go.
-func parseDockerDaemonHost(addr string) (string, error) {
- addrParts := strings.Split(addr, "://")
- if len(addrParts) == 1 && addrParts[0] != "" {
- addrParts = []string{"tcp", addrParts[0]}
- }
-
- switch addrParts[0] {
- case "tcp":
- return parseTCPAddr(addrParts[1], DefaultTCPHost)
- case "unix":
- return parseSimpleProtoAddr("unix", addrParts[1], DefaultUnixSocket)
- case "npipe":
- return parseSimpleProtoAddr("npipe", addrParts[1], DefaultNamedPipe)
- case "fd":
- return addr, nil
- default:
- return "", fmt.Errorf("Invalid bind address format: %s", addr)
- }
-}
-
-// parseSimpleProtoAddr parses and validates that the specified address is a valid
-// socket address for simple protocols like unix and npipe. It returns a formatted
-// socket address, either using the address parsed from addr, or the contents of
-// defaultAddr if addr is a blank string.
-func parseSimpleProtoAddr(proto, addr, defaultAddr string) (string, error) {
- addr = strings.TrimPrefix(addr, proto+"://")
- if strings.Contains(addr, "://") {
- return "", fmt.Errorf("Invalid proto, expected %s: %s", proto, addr)
- }
- if addr == "" {
- addr = defaultAddr
- }
- return fmt.Sprintf("%s://%s", proto, addr), nil
-}
-
-// parseTCPAddr parses and validates that the specified address is a valid TCP
-// address. It returns a formatted TCP address, either using the address parsed
-// from tryAddr, or the contents of defaultAddr if tryAddr is a blank string.
-// tryAddr is expected to have already been Trim()'d
-// defaultAddr must be in the full `tcp://host:port` form
-func parseTCPAddr(tryAddr string, defaultAddr string) (string, error) {
- if tryAddr == "" || tryAddr == "tcp://" {
- return defaultAddr, nil
- }
- addr := strings.TrimPrefix(tryAddr, "tcp://")
- if strings.Contains(addr, "://") || addr == "" {
- return "", fmt.Errorf("Invalid proto, expected tcp: %s", tryAddr)
- }
-
- defaultAddr = strings.TrimPrefix(defaultAddr, "tcp://")
- defaultHost, defaultPort, err := net.SplitHostPort(defaultAddr)
- if err != nil {
- return "", err
- }
- // url.Parse fails for trailing colon on IPv6 brackets on Go 1.5, but
- // not 1.4. See https://github.com/golang/go/issues/12200 and
- // https://github.com/golang/go/issues/6530.
- if strings.HasSuffix(addr, "]:") {
- addr += defaultPort
- }
-
- u, err := url.Parse("tcp://" + addr)
- if err != nil {
- return "", err
- }
-
- host, port, err := net.SplitHostPort(u.Host)
- if err != nil {
- return "", fmt.Errorf("Invalid bind address format: %s", tryAddr)
- }
-
- if host == "" {
- host = defaultHost
- }
- if port == "" {
- port = defaultPort
- }
- p, err := strconv.Atoi(port)
- if err != nil && p == 0 {
- return "", fmt.Errorf("Invalid bind address format: %s", tryAddr)
- }
-
- return fmt.Sprintf("tcp://%s%s", net.JoinHostPort(host, port), u.Path), nil
-}
diff --git a/vendor/github.com/docker/docker/opts/hosts_test.go b/vendor/github.com/docker/docker/opts/hosts_test.go
deleted file mode 100644
index dc527e6..0000000
--- a/vendor/github.com/docker/docker/opts/hosts_test.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package opts
-
-import (
- "fmt"
- "testing"
-)
-
-func TestParseHost(t *testing.T) {
- invalid := []string{
- "anything",
- "something with spaces",
- "://",
- "unknown://",
- "tcp://:port",
- "tcp://invalid",
- "tcp://invalid:port",
- }
-
- valid := map[string]string{
- "": DefaultHost,
- " ": DefaultHost,
- " ": DefaultHost,
- "fd://": "fd://",
- "fd://something": "fd://something",
- "tcp://host:": fmt.Sprintf("tcp://host:%d", DefaultHTTPPort),
- "tcp://": DefaultTCPHost,
- "tcp://:2375": fmt.Sprintf("tcp://%s:2375", DefaultHTTPHost),
- "tcp://:2376": fmt.Sprintf("tcp://%s:2376", DefaultHTTPHost),
- "tcp://0.0.0.0:8080": "tcp://0.0.0.0:8080",
- "tcp://192.168.0.0:12000": "tcp://192.168.0.0:12000",
- "tcp://192.168:8080": "tcp://192.168:8080",
- "tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890", // yeah it's valid :P
- " tcp://:7777/path ": fmt.Sprintf("tcp://%s:7777/path", DefaultHTTPHost),
- "tcp://docker.com:2375": "tcp://docker.com:2375",
- "unix://": "unix://" + DefaultUnixSocket,
- "unix://path/to/socket": "unix://path/to/socket",
- "npipe://": "npipe://" + DefaultNamedPipe,
- "npipe:////./pipe/foo": "npipe:////./pipe/foo",
- }
-
- for _, value := range invalid {
- if _, err := ParseHost(false, value); err == nil {
- t.Errorf("Expected an error for %v, got [nil]", value)
- }
- }
-
- for value, expected := range valid {
- if actual, err := ParseHost(false, value); err != nil || actual != expected {
- t.Errorf("Expected for %v [%v], got [%v, %v]", value, expected, actual, err)
- }
- }
-}
-
-func TestParseDockerDaemonHost(t *testing.T) {
- invalids := map[string]string{
- "0.0.0.0": "Invalid bind address format: 0.0.0.0",
- "tcp:a.b.c.d": "Invalid bind address format: tcp:a.b.c.d",
- "tcp:a.b.c.d/path": "Invalid bind address format: tcp:a.b.c.d/path",
- "udp://127.0.0.1": "Invalid bind address format: udp://127.0.0.1",
- "udp://127.0.0.1:2375": "Invalid bind address format: udp://127.0.0.1:2375",
- "tcp://unix:///run/docker.sock": "Invalid bind address format: unix",
- " tcp://:7777/path ": "Invalid bind address format: tcp://:7777/path ",
- "tcp": "Invalid bind address format: tcp",
- "unix": "Invalid bind address format: unix",
- "fd": "Invalid bind address format: fd",
- "": "Invalid bind address format: ",
- }
- valids := map[string]string{
- "0.0.0.1:": "tcp://0.0.0.1:2375",
- "0.0.0.1:5555": "tcp://0.0.0.1:5555",
- "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path",
- "[::1]:": "tcp://[::1]:2375",
- "[::1]:5555/path": "tcp://[::1]:5555/path",
- "[0:0:0:0:0:0:0:1]:": "tcp://[0:0:0:0:0:0:0:1]:2375",
- "[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
- ":6666": fmt.Sprintf("tcp://%s:6666", DefaultHTTPHost),
- ":6666/path": fmt.Sprintf("tcp://%s:6666/path", DefaultHTTPHost),
- "tcp://": DefaultTCPHost,
- "tcp://:7777": fmt.Sprintf("tcp://%s:7777", DefaultHTTPHost),
- "tcp://:7777/path": fmt.Sprintf("tcp://%s:7777/path", DefaultHTTPHost),
- "unix:///run/docker.sock": "unix:///run/docker.sock",
- "unix://": "unix://" + DefaultUnixSocket,
- "fd://": "fd://",
- "fd://something": "fd://something",
- "localhost:": "tcp://localhost:2375",
- "localhost:5555": "tcp://localhost:5555",
- "localhost:5555/path": "tcp://localhost:5555/path",
- }
- for invalidAddr, expectedError := range invalids {
- if addr, err := parseDockerDaemonHost(invalidAddr); err == nil || err.Error() != expectedError {
- t.Errorf("tcp %v address expected error %v return, got %s and addr %v", invalidAddr, expectedError, err, addr)
- }
- }
- for validAddr, expectedAddr := range valids {
- if addr, err := parseDockerDaemonHost(validAddr); err != nil || addr != expectedAddr {
- t.Errorf("%v -> expected %v, got (%v) addr (%v)", validAddr, expectedAddr, err, addr)
- }
- }
-}
-
-func TestParseTCP(t *testing.T) {
- var (
- defaultHTTPHost = "tcp://127.0.0.1:2376"
- )
- invalids := map[string]string{
- "0.0.0.0": "Invalid bind address format: 0.0.0.0",
- "tcp:a.b.c.d": "Invalid bind address format: tcp:a.b.c.d",
- "tcp:a.b.c.d/path": "Invalid bind address format: tcp:a.b.c.d/path",
- "udp://127.0.0.1": "Invalid proto, expected tcp: udp://127.0.0.1",
- "udp://127.0.0.1:2375": "Invalid proto, expected tcp: udp://127.0.0.1:2375",
- }
- valids := map[string]string{
- "": defaultHTTPHost,
- "tcp://": defaultHTTPHost,
- "0.0.0.1:": "tcp://0.0.0.1:2376",
- "0.0.0.1:5555": "tcp://0.0.0.1:5555",
- "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path",
- ":6666": "tcp://127.0.0.1:6666",
- ":6666/path": "tcp://127.0.0.1:6666/path",
- "tcp://:7777": "tcp://127.0.0.1:7777",
- "tcp://:7777/path": "tcp://127.0.0.1:7777/path",
- "[::1]:": "tcp://[::1]:2376",
- "[::1]:5555": "tcp://[::1]:5555",
- "[::1]:5555/path": "tcp://[::1]:5555/path",
- "[0:0:0:0:0:0:0:1]:": "tcp://[0:0:0:0:0:0:0:1]:2376",
- "[0:0:0:0:0:0:0:1]:5555": "tcp://[0:0:0:0:0:0:0:1]:5555",
- "[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
- "localhost:": "tcp://localhost:2376",
- "localhost:5555": "tcp://localhost:5555",
- "localhost:5555/path": "tcp://localhost:5555/path",
- }
- for invalidAddr, expectedError := range invalids {
- if addr, err := parseTCPAddr(invalidAddr, defaultHTTPHost); err == nil || err.Error() != expectedError {
- t.Errorf("tcp %v address expected error %v return, got %s and addr %v", invalidAddr, expectedError, err, addr)
- }
- }
- for validAddr, expectedAddr := range valids {
- if addr, err := parseTCPAddr(validAddr, defaultHTTPHost); err != nil || addr != expectedAddr {
- t.Errorf("%v -> expected %v, got %v and addr %v", validAddr, expectedAddr, err, addr)
- }
- }
-}
-
-func TestParseInvalidUnixAddrInvalid(t *testing.T) {
- if _, err := parseSimpleProtoAddr("unix", "tcp://127.0.0.1", "unix:///var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" {
- t.Fatalf("Expected an error, got %v", err)
- }
- if _, err := parseSimpleProtoAddr("unix", "unix://tcp://127.0.0.1", "/var/run/docker.sock"); err == nil || err.Error() != "Invalid proto, expected unix: tcp://127.0.0.1" {
- t.Fatalf("Expected an error, got %v", err)
- }
- if v, err := parseSimpleProtoAddr("unix", "", "/var/run/docker.sock"); err != nil || v != "unix:///var/run/docker.sock" {
- t.Fatalf("Expected an %v, got %v", v, "unix:///var/run/docker.sock")
- }
-}
diff --git a/vendor/github.com/docker/docker/opts/hosts_unix.go b/vendor/github.com/docker/docker/opts/hosts_unix.go
deleted file mode 100644
index 611407a..0000000
--- a/vendor/github.com/docker/docker/opts/hosts_unix.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !windows
-
-package opts
-
-import "fmt"
-
-// DefaultHost constant defines the default host string used by docker on other hosts than Windows
-var DefaultHost = fmt.Sprintf("unix://%s", DefaultUnixSocket)
diff --git a/vendor/github.com/docker/docker/opts/hosts_windows.go b/vendor/github.com/docker/docker/opts/hosts_windows.go
deleted file mode 100644
index 7c239e0..0000000
--- a/vendor/github.com/docker/docker/opts/hosts_windows.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// +build windows
-
-package opts
-
-// DefaultHost constant defines the default host string used by docker on Windows
-var DefaultHost = "npipe://" + DefaultNamedPipe
diff --git a/vendor/github.com/docker/docker/opts/ip.go b/vendor/github.com/docker/docker/opts/ip.go
deleted file mode 100644
index c7b0dc9..0000000
--- a/vendor/github.com/docker/docker/opts/ip.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package opts
-
-import (
- "fmt"
- "net"
-)
-
-// IPOpt holds an IP. It is used to store values from CLI flags.
-type IPOpt struct {
- *net.IP
-}
-
-// NewIPOpt creates a new IPOpt from a reference net.IP and a
-// string representation of an IP. If the string is not a valid
-// IP it will fallback to the specified reference.
-func NewIPOpt(ref *net.IP, defaultVal string) *IPOpt {
- o := &IPOpt{
- IP: ref,
- }
- o.Set(defaultVal)
- return o
-}
-
-// Set sets an IPv4 or IPv6 address from a given string. If the given
-// string is not parseable as an IP address it returns an error.
-func (o *IPOpt) Set(val string) error {
- ip := net.ParseIP(val)
- if ip == nil {
- return fmt.Errorf("%s is not an ip address", val)
- }
- *o.IP = ip
- return nil
-}
-
-// String returns the IP address stored in the IPOpt. If stored IP is a
-// nil pointer, it returns an empty string.
-func (o *IPOpt) String() string {
- if *o.IP == nil {
- return ""
- }
- return o.IP.String()
-}
diff --git a/vendor/github.com/docker/docker/opts/ip_test.go b/vendor/github.com/docker/docker/opts/ip_test.go
deleted file mode 100644
index 1027d84..0000000
--- a/vendor/github.com/docker/docker/opts/ip_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package opts
-
-import (
- "net"
- "testing"
-)
-
-func TestIpOptString(t *testing.T) {
- addresses := []string{"", "0.0.0.0"}
- var ip net.IP
-
- for _, address := range addresses {
- stringAddress := NewIPOpt(&ip, address).String()
- if stringAddress != address {
- t.Fatalf("IpOpt string should be `%s`, not `%s`", address, stringAddress)
- }
- }
-}
-
-func TestNewIpOptInvalidDefaultVal(t *testing.T) {
- ip := net.IPv4(127, 0, 0, 1)
- defaultVal := "Not an ip"
-
- ipOpt := NewIPOpt(&ip, defaultVal)
-
- expected := "127.0.0.1"
- if ipOpt.String() != expected {
- t.Fatalf("Expected [%v], got [%v]", expected, ipOpt.String())
- }
-}
-
-func TestNewIpOptValidDefaultVal(t *testing.T) {
- ip := net.IPv4(127, 0, 0, 1)
- defaultVal := "192.168.1.1"
-
- ipOpt := NewIPOpt(&ip, defaultVal)
-
- expected := "192.168.1.1"
- if ipOpt.String() != expected {
- t.Fatalf("Expected [%v], got [%v]", expected, ipOpt.String())
- }
-}
-
-func TestIpOptSetInvalidVal(t *testing.T) {
- ip := net.IPv4(127, 0, 0, 1)
- ipOpt := &IPOpt{IP: &ip}
-
- invalidIP := "invalid ip"
- expectedError := "invalid ip is not an ip address"
- err := ipOpt.Set(invalidIP)
- if err == nil || err.Error() != expectedError {
- t.Fatalf("Expected an Error with [%v], got [%v]", expectedError, err.Error())
- }
-}
diff --git a/vendor/github.com/docker/docker/opts/opts.go b/vendor/github.com/docker/docker/opts/opts.go
deleted file mode 100644
index 1b9d6b2..0000000
--- a/vendor/github.com/docker/docker/opts/opts.go
+++ /dev/null
@@ -1,321 +0,0 @@
-package opts
-
-import (
- "fmt"
- "net"
- "regexp"
- "strings"
-
- "github.com/docker/engine-api/types/filters"
-)
-
-var (
- alphaRegexp = regexp.MustCompile(`[a-zA-Z]`)
- domainRegexp = regexp.MustCompile(`^(:?(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]))(:?\.(:?[a-zA-Z0-9]|(:?[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])))*)\.?\s*$`)
-)
-
-// ListOpts holds a list of values and a validation function.
-type ListOpts struct {
- values *[]string
- validator ValidatorFctType
-}
-
-// NewListOpts creates a new ListOpts with the specified validator.
-func NewListOpts(validator ValidatorFctType) ListOpts {
- var values []string
- return *NewListOptsRef(&values, validator)
-}
-
-// NewListOptsRef creates a new ListOpts with the specified values and validator.
-func NewListOptsRef(values *[]string, validator ValidatorFctType) *ListOpts {
- return &ListOpts{
- values: values,
- validator: validator,
- }
-}
-
-func (opts *ListOpts) String() string {
- return fmt.Sprintf("%v", []string((*opts.values)))
-}
-
-// Set validates if needed the input value and adds it to the
-// internal slice.
-func (opts *ListOpts) Set(value string) error {
- if opts.validator != nil {
- v, err := opts.validator(value)
- if err != nil {
- return err
- }
- value = v
- }
- (*opts.values) = append((*opts.values), value)
- return nil
-}
-
-// Delete removes the specified element from the slice.
-func (opts *ListOpts) Delete(key string) {
- for i, k := range *opts.values {
- if k == key {
- (*opts.values) = append((*opts.values)[:i], (*opts.values)[i+1:]...)
- return
- }
- }
-}
-
-// GetMap returns the content of values in a map in order to avoid
-// duplicates.
-func (opts *ListOpts) GetMap() map[string]struct{} {
- ret := make(map[string]struct{})
- for _, k := range *opts.values {
- ret[k] = struct{}{}
- }
- return ret
-}
-
-// GetAll returns the values of slice.
-func (opts *ListOpts) GetAll() []string {
- return (*opts.values)
-}
-
-// GetAllOrEmpty returns the values of the slice
-// or an empty slice when there are no values.
-func (opts *ListOpts) GetAllOrEmpty() []string {
- v := *opts.values
- if v == nil {
- return make([]string, 0)
- }
- return v
-}
-
-// Get checks the existence of the specified key.
-func (opts *ListOpts) Get(key string) bool {
- for _, k := range *opts.values {
- if k == key {
- return true
- }
- }
- return false
-}
-
-// Len returns the amount of element in the slice.
-func (opts *ListOpts) Len() int {
- return len((*opts.values))
-}
-
-// Type returns a string name for this Option type
-func (opts *ListOpts) Type() string {
- return "list"
-}
-
-// NamedOption is an interface that list and map options
-// with names implement.
-type NamedOption interface {
- Name() string
-}
-
-// NamedListOpts is a ListOpts with a configuration name.
-// This struct is useful to keep reference to the assigned
-// field name in the internal configuration struct.
-type NamedListOpts struct {
- name string
- ListOpts
-}
-
-var _ NamedOption = &NamedListOpts{}
-
-// NewNamedListOptsRef creates a reference to a new NamedListOpts struct.
-func NewNamedListOptsRef(name string, values *[]string, validator ValidatorFctType) *NamedListOpts {
- return &NamedListOpts{
- name: name,
- ListOpts: *NewListOptsRef(values, validator),
- }
-}
-
-// Name returns the name of the NamedListOpts in the configuration.
-func (o *NamedListOpts) Name() string {
- return o.name
-}
-
-//MapOpts holds a map of values and a validation function.
-type MapOpts struct {
- values map[string]string
- validator ValidatorFctType
-}
-
-// Set validates if needed the input value and add it to the
-// internal map, by splitting on '='.
-func (opts *MapOpts) Set(value string) error {
- if opts.validator != nil {
- v, err := opts.validator(value)
- if err != nil {
- return err
- }
- value = v
- }
- vals := strings.SplitN(value, "=", 2)
- if len(vals) == 1 {
- (opts.values)[vals[0]] = ""
- } else {
- (opts.values)[vals[0]] = vals[1]
- }
- return nil
-}
-
-// GetAll returns the values of MapOpts as a map.
-func (opts *MapOpts) GetAll() map[string]string {
- return opts.values
-}
-
-func (opts *MapOpts) String() string {
- return fmt.Sprintf("%v", map[string]string((opts.values)))
-}
-
-// Type returns a string name for this Option type
-func (opts *MapOpts) Type() string {
- return "map"
-}
-
-// NewMapOpts creates a new MapOpts with the specified map of values and a validator.
-func NewMapOpts(values map[string]string, validator ValidatorFctType) *MapOpts {
- if values == nil {
- values = make(map[string]string)
- }
- return &MapOpts{
- values: values,
- validator: validator,
- }
-}
-
-// NamedMapOpts is a MapOpts struct with a configuration name.
-// This struct is useful to keep reference to the assigned
-// field name in the internal configuration struct.
-type NamedMapOpts struct {
- name string
- MapOpts
-}
-
-var _ NamedOption = &NamedMapOpts{}
-
-// NewNamedMapOpts creates a reference to a new NamedMapOpts struct.
-func NewNamedMapOpts(name string, values map[string]string, validator ValidatorFctType) *NamedMapOpts {
- return &NamedMapOpts{
- name: name,
- MapOpts: *NewMapOpts(values, validator),
- }
-}
-
-// Name returns the name of the NamedMapOpts in the configuration.
-func (o *NamedMapOpts) Name() string {
- return o.name
-}
-
-// ValidatorFctType defines a validator function that returns a validated string and/or an error.
-type ValidatorFctType func(val string) (string, error)
-
-// ValidatorFctListType defines a validator function that returns a validated list of string and/or an error
-type ValidatorFctListType func(val string) ([]string, error)
-
-// ValidateIPAddress validates an Ip address.
-func ValidateIPAddress(val string) (string, error) {
- var ip = net.ParseIP(strings.TrimSpace(val))
- if ip != nil {
- return ip.String(), nil
- }
- return "", fmt.Errorf("%s is not an ip address", val)
-}
-
-// ValidateDNSSearch validates domain for resolvconf search configuration.
-// A zero length domain is represented by a dot (.).
-func ValidateDNSSearch(val string) (string, error) {
- if val = strings.Trim(val, " "); val == "." {
- return val, nil
- }
- return validateDomain(val)
-}
-
-func validateDomain(val string) (string, error) {
- if alphaRegexp.FindString(val) == "" {
- return "", fmt.Errorf("%s is not a valid domain", val)
- }
- ns := domainRegexp.FindSubmatch([]byte(val))
- if len(ns) > 0 && len(ns[1]) < 255 {
- return string(ns[1]), nil
- }
- return "", fmt.Errorf("%s is not a valid domain", val)
-}
-
-// ValidateLabel validates that the specified string is a valid label, and returns it.
-// Labels are in the form on key=value.
-func ValidateLabel(val string) (string, error) {
- if strings.Count(val, "=") < 1 {
- return "", fmt.Errorf("bad attribute format: %s", val)
- }
- return val, nil
-}
-
-// ValidateSysctl validates a sysctl and returns it.
-func ValidateSysctl(val string) (string, error) {
- validSysctlMap := map[string]bool{
- "kernel.msgmax": true,
- "kernel.msgmnb": true,
- "kernel.msgmni": true,
- "kernel.sem": true,
- "kernel.shmall": true,
- "kernel.shmmax": true,
- "kernel.shmmni": true,
- "kernel.shm_rmid_forced": true,
- }
- validSysctlPrefixes := []string{
- "net.",
- "fs.mqueue.",
- }
- arr := strings.Split(val, "=")
- if len(arr) < 2 {
- return "", fmt.Errorf("sysctl '%s' is not whitelisted", val)
- }
- if validSysctlMap[arr[0]] {
- return val, nil
- }
-
- for _, vp := range validSysctlPrefixes {
- if strings.HasPrefix(arr[0], vp) {
- return val, nil
- }
- }
- return "", fmt.Errorf("sysctl '%s' is not whitelisted", val)
-}
-
-// FilterOpt is a flag type for validating filters
-type FilterOpt struct {
- filter filters.Args
-}
-
-// NewFilterOpt returns a new FilterOpt
-func NewFilterOpt() FilterOpt {
- return FilterOpt{filter: filters.NewArgs()}
-}
-
-func (o *FilterOpt) String() string {
- repr, err := filters.ToParam(o.filter)
- if err != nil {
- return "invalid filters"
- }
- return repr
-}
-
-// Set sets the value of the opt by parsing the command line value
-func (o *FilterOpt) Set(value string) error {
- var err error
- o.filter, err = filters.ParseFlag(value, o.filter)
- return err
-}
-
-// Type returns the option type
-func (o *FilterOpt) Type() string {
- return "filter"
-}
-
-// Value returns the value of this option
-func (o *FilterOpt) Value() filters.Args {
- return o.filter
-}
diff --git a/vendor/github.com/docker/docker/opts/opts_test.go b/vendor/github.com/docker/docker/opts/opts_test.go
deleted file mode 100644
index 9f41e47..0000000
--- a/vendor/github.com/docker/docker/opts/opts_test.go
+++ /dev/null
@@ -1,232 +0,0 @@
-package opts
-
-import (
- "fmt"
- "strings"
- "testing"
-)
-
-func TestValidateIPAddress(t *testing.T) {
- if ret, err := ValidateIPAddress(`1.2.3.4`); err != nil || ret == "" {
- t.Fatalf("ValidateIPAddress(`1.2.3.4`) got %s %s", ret, err)
- }
-
- if ret, err := ValidateIPAddress(`127.0.0.1`); err != nil || ret == "" {
- t.Fatalf("ValidateIPAddress(`127.0.0.1`) got %s %s", ret, err)
- }
-
- if ret, err := ValidateIPAddress(`::1`); err != nil || ret == "" {
- t.Fatalf("ValidateIPAddress(`::1`) got %s %s", ret, err)
- }
-
- if ret, err := ValidateIPAddress(`127`); err == nil || ret != "" {
- t.Fatalf("ValidateIPAddress(`127`) got %s %s", ret, err)
- }
-
- if ret, err := ValidateIPAddress(`random invalid string`); err == nil || ret != "" {
- t.Fatalf("ValidateIPAddress(`random invalid string`) got %s %s", ret, err)
- }
-
-}
-
-func TestMapOpts(t *testing.T) {
- tmpMap := make(map[string]string)
- o := NewMapOpts(tmpMap, logOptsValidator)
- o.Set("max-size=1")
- if o.String() != "map[max-size:1]" {
- t.Errorf("%s != [map[max-size:1]", o.String())
- }
-
- o.Set("max-file=2")
- if len(tmpMap) != 2 {
- t.Errorf("map length %d != 2", len(tmpMap))
- }
-
- if tmpMap["max-file"] != "2" {
- t.Errorf("max-file = %s != 2", tmpMap["max-file"])
- }
-
- if tmpMap["max-size"] != "1" {
- t.Errorf("max-size = %s != 1", tmpMap["max-size"])
- }
- if o.Set("dummy-val=3") == nil {
- t.Errorf("validator is not being called")
- }
-}
-
-func TestListOptsWithoutValidator(t *testing.T) {
- o := NewListOpts(nil)
- o.Set("foo")
- if o.String() != "[foo]" {
- t.Errorf("%s != [foo]", o.String())
- }
- o.Set("bar")
- if o.Len() != 2 {
- t.Errorf("%d != 2", o.Len())
- }
- o.Set("bar")
- if o.Len() != 3 {
- t.Errorf("%d != 3", o.Len())
- }
- if !o.Get("bar") {
- t.Error("o.Get(\"bar\") == false")
- }
- if o.Get("baz") {
- t.Error("o.Get(\"baz\") == true")
- }
- o.Delete("foo")
- if o.String() != "[bar bar]" {
- t.Errorf("%s != [bar bar]", o.String())
- }
- listOpts := o.GetAll()
- if len(listOpts) != 2 || listOpts[0] != "bar" || listOpts[1] != "bar" {
- t.Errorf("Expected [[bar bar]], got [%v]", listOpts)
- }
- mapListOpts := o.GetMap()
- if len(mapListOpts) != 1 {
- t.Errorf("Expected [map[bar:{}]], got [%v]", mapListOpts)
- }
-
-}
-
-func TestListOptsWithValidator(t *testing.T) {
- // Re-using logOptsvalidator (used by MapOpts)
- o := NewListOpts(logOptsValidator)
- o.Set("foo")
- if o.String() != "[]" {
- t.Errorf("%s != []", o.String())
- }
- o.Set("foo=bar")
- if o.String() != "[]" {
- t.Errorf("%s != []", o.String())
- }
- o.Set("max-file=2")
- if o.Len() != 1 {
- t.Errorf("%d != 1", o.Len())
- }
- if !o.Get("max-file=2") {
- t.Error("o.Get(\"max-file=2\") == false")
- }
- if o.Get("baz") {
- t.Error("o.Get(\"baz\") == true")
- }
- o.Delete("max-file=2")
- if o.String() != "[]" {
- t.Errorf("%s != []", o.String())
- }
-}
-
-func TestValidateDNSSearch(t *testing.T) {
- valid := []string{
- `.`,
- `a`,
- `a.`,
- `1.foo`,
- `17.foo`,
- `foo.bar`,
- `foo.bar.baz`,
- `foo.bar.`,
- `foo.bar.baz`,
- `foo1.bar2`,
- `foo1.bar2.baz`,
- `1foo.2bar.`,
- `1foo.2bar.baz`,
- `foo-1.bar-2`,
- `foo-1.bar-2.baz`,
- `foo-1.bar-2.`,
- `foo-1.bar-2.baz`,
- `1-foo.2-bar`,
- `1-foo.2-bar.baz`,
- `1-foo.2-bar.`,
- `1-foo.2-bar.baz`,
- }
-
- invalid := []string{
- ``,
- ` `,
- ` `,
- `17`,
- `17.`,
- `.17`,
- `17-.`,
- `17-.foo`,
- `.foo`,
- `foo-.bar`,
- `-foo.bar`,
- `foo.bar-`,
- `foo.bar-.baz`,
- `foo.-bar`,
- `foo.-bar.baz`,
- `foo.bar.baz.this.should.fail.on.long.name.beause.it.is.longer.thanisshouldbethis.should.fail.on.long.name.beause.it.is.longer.thanisshouldbethis.should.fail.on.long.name.beause.it.is.longer.thanisshouldbethis.should.fail.on.long.name.beause.it.is.longer.thanisshouldbe`,
- }
-
- for _, domain := range valid {
- if ret, err := ValidateDNSSearch(domain); err != nil || ret == "" {
- t.Fatalf("ValidateDNSSearch(`"+domain+"`) got %s %s", ret, err)
- }
- }
-
- for _, domain := range invalid {
- if ret, err := ValidateDNSSearch(domain); err == nil || ret != "" {
- t.Fatalf("ValidateDNSSearch(`"+domain+"`) got %s %s", ret, err)
- }
- }
-}
-
-func TestValidateLabel(t *testing.T) {
- if _, err := ValidateLabel("label"); err == nil || err.Error() != "bad attribute format: label" {
- t.Fatalf("Expected an error [bad attribute format: label], go %v", err)
- }
- if actual, err := ValidateLabel("key1=value1"); err != nil || actual != "key1=value1" {
- t.Fatalf("Expected [key1=value1], got [%v,%v]", actual, err)
- }
- // Validate it's working with more than one =
- if actual, err := ValidateLabel("key1=value1=value2"); err != nil {
- t.Fatalf("Expected [key1=value1=value2], got [%v,%v]", actual, err)
- }
- // Validate it's working with one more
- if actual, err := ValidateLabel("key1=value1=value2=value3"); err != nil {
- t.Fatalf("Expected [key1=value1=value2=value2], got [%v,%v]", actual, err)
- }
-}
-
-func logOptsValidator(val string) (string, error) {
- allowedKeys := map[string]string{"max-size": "1", "max-file": "2"}
- vals := strings.Split(val, "=")
- if allowedKeys[vals[0]] != "" {
- return val, nil
- }
- return "", fmt.Errorf("invalid key %s", vals[0])
-}
-
-func TestNamedListOpts(t *testing.T) {
- var v []string
- o := NewNamedListOptsRef("foo-name", &v, nil)
-
- o.Set("foo")
- if o.String() != "[foo]" {
- t.Errorf("%s != [foo]", o.String())
- }
- if o.Name() != "foo-name" {
- t.Errorf("%s != foo-name", o.Name())
- }
- if len(v) != 1 {
- t.Errorf("expected foo to be in the values, got %v", v)
- }
-}
-
-func TestNamedMapOpts(t *testing.T) {
- tmpMap := make(map[string]string)
- o := NewNamedMapOpts("max-name", tmpMap, nil)
-
- o.Set("max-size=1")
- if o.String() != "map[max-size:1]" {
- t.Errorf("%s != [map[max-size:1]", o.String())
- }
- if o.Name() != "max-name" {
- t.Errorf("%s != max-name", o.Name())
- }
- if _, exist := tmpMap["max-size"]; !exist {
- t.Errorf("expected map-size to be in the values, got %v", tmpMap)
- }
-}
diff --git a/vendor/github.com/docker/docker/opts/opts_unix.go b/vendor/github.com/docker/docker/opts/opts_unix.go
deleted file mode 100644
index f1ce844..0000000
--- a/vendor/github.com/docker/docker/opts/opts_unix.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// +build !windows
-
-package opts
-
-// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. docker daemon -H tcp://:8080
-const DefaultHTTPHost = "localhost"
diff --git a/vendor/github.com/docker/docker/opts/opts_windows.go b/vendor/github.com/docker/docker/opts/opts_windows.go
deleted file mode 100644
index ebe40c9..0000000
--- a/vendor/github.com/docker/docker/opts/opts_windows.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package opts
-
-// TODO Windows. Identify bug in GOLang 1.5.1+ and/or Windows Server 2016 TP5.
-// @jhowardmsft, @swernli.
-//
-// On Windows, this mitigates a problem with the default options of running
-// a docker client against a local docker daemon on TP5.
-//
-// What was found that if the default host is "localhost", even if the client
-// (and daemon as this is local) is not physically on a network, and the DNS
-// cache is flushed (ipconfig /flushdns), then the client will pause for
-// exactly one second when connecting to the daemon for calls. For example
-// using docker run windowsservercore cmd, the CLI will send a create followed
-// by an attach. You see the delay between the attach finishing and the attach
-// being seen by the daemon.
-//
-// Here's some daemon debug logs with additional debug spew put in. The
-// AfterWriteJSON log is the very last thing the daemon does as part of the
-// create call. The POST /attach is the second CLI call. Notice the second
-// time gap.
-//
-// time="2015-11-06T13:38:37.259627400-08:00" level=debug msg="After createRootfs"
-// time="2015-11-06T13:38:37.263626300-08:00" level=debug msg="After setHostConfig"
-// time="2015-11-06T13:38:37.267631200-08:00" level=debug msg="before createContainerPl...."
-// time="2015-11-06T13:38:37.271629500-08:00" level=debug msg=ToDiskLocking....
-// time="2015-11-06T13:38:37.275643200-08:00" level=debug msg="loggin event...."
-// time="2015-11-06T13:38:37.277627600-08:00" level=debug msg="logged event...."
-// time="2015-11-06T13:38:37.279631800-08:00" level=debug msg="In defer func"
-// time="2015-11-06T13:38:37.282628100-08:00" level=debug msg="After daemon.create"
-// time="2015-11-06T13:38:37.286651700-08:00" level=debug msg="return 2"
-// time="2015-11-06T13:38:37.289629500-08:00" level=debug msg="Returned from daemon.ContainerCreate"
-// time="2015-11-06T13:38:37.311629100-08:00" level=debug msg="After WriteJSON"
-// ... 1 second gap here....
-// time="2015-11-06T13:38:38.317866200-08:00" level=debug msg="Calling POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach"
-// time="2015-11-06T13:38:38.326882500-08:00" level=info msg="POST /v1.22/containers/984758282b842f779e805664b2c95d563adc9a979c8a3973e68c807843ee4757/attach?stderr=1&stdin=1&stdout=1&stream=1"
-//
-// We suspect this is either a bug introduced in GOLang 1.5.1, or that a change
-// in GOLang 1.5.1 (from 1.4.3) is exposing a bug in Windows. In theory,
-// the Windows networking stack is supposed to resolve "localhost" internally,
-// without hitting DNS, or even reading the hosts file (which is why localhost
-// is commented out in the hosts file on Windows).
-//
-// We have validated that working around this using the actual IPv4 localhost
-// address does not cause the delay.
-//
-// This does not occur with the docker client built with 1.4.3 on the same
-// Windows build, regardless of whether the daemon is built using 1.5.1
-// or 1.4.3. It does not occur on Linux. We also verified we see the same thing
-// on a cross-compiled Windows binary (from Linux).
-//
-// Final note: This is a mitigation, not a 'real' fix. It is still susceptible
-// to the delay if a user were to do 'docker run -H=tcp://localhost:2375...'
-// explicitly.
-
-// DefaultHTTPHost Default HTTP Host used if only port is provided to -H flag e.g. docker daemon -H tcp://:8080
-const DefaultHTTPHost = "127.0.0.1"
diff --git a/vendor/github.com/docker/docker/pkg/archive/README.md b/vendor/github.com/docker/docker/pkg/archive/README.md
deleted file mode 100644
index 7307d96..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This code provides helper functions for dealing with archive files.
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive.go b/vendor/github.com/docker/docker/pkg/archive/archive.go
deleted file mode 100644
index 4f0b4ff..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive.go
+++ /dev/null
@@ -1,1147 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "bufio"
- "bytes"
- "compress/bzip2"
- "compress/gzip"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "strings"
- "syscall"
-
- "github.com/Sirupsen/logrus"
- "github.com/docker/docker/pkg/fileutils"
- "github.com/docker/docker/pkg/idtools"
- "github.com/docker/docker/pkg/ioutils"
- "github.com/docker/docker/pkg/pools"
- "github.com/docker/docker/pkg/promise"
- "github.com/docker/docker/pkg/system"
-)
-
-type (
- // Archive is a type of io.ReadCloser which has two interfaces Read and Closer.
- Archive io.ReadCloser
- // Reader is a type of io.Reader.
- Reader io.Reader
- // Compression is the state represents if compressed or not.
- Compression int
- // WhiteoutFormat is the format of whiteouts unpacked
- WhiteoutFormat int
- // TarChownOptions wraps the chown options UID and GID.
- TarChownOptions struct {
- UID, GID int
- }
- // TarOptions wraps the tar options.
- TarOptions struct {
- IncludeFiles []string
- ExcludePatterns []string
- Compression Compression
- NoLchown bool
- UIDMaps []idtools.IDMap
- GIDMaps []idtools.IDMap
- ChownOpts *TarChownOptions
- IncludeSourceDir bool
- // WhiteoutFormat is the expected on disk format for whiteout files.
- // This format will be converted to the standard format on pack
- // and from the standard format on unpack.
- WhiteoutFormat WhiteoutFormat
- // When unpacking, specifies whether overwriting a directory with a
- // non-directory is allowed and vice versa.
- NoOverwriteDirNonDir bool
- // For each include when creating an archive, the included name will be
- // replaced with the matching name from this map.
- RebaseNames map[string]string
- }
-
- // Archiver allows the reuse of most utility functions of this package
- // with a pluggable Untar function. Also, to facilitate the passing of
- // specific id mappings for untar, an archiver can be created with maps
- // which will then be passed to Untar operations
- Archiver struct {
- Untar func(io.Reader, string, *TarOptions) error
- UIDMaps []idtools.IDMap
- GIDMaps []idtools.IDMap
- }
-
- // breakoutError is used to differentiate errors related to breaking out
- // When testing archive breakout in the unit tests, this error is expected
- // in order for the test to pass.
- breakoutError error
-)
-
-var (
- // ErrNotImplemented is the error message of function not implemented.
- ErrNotImplemented = errors.New("Function not implemented")
- defaultArchiver = &Archiver{Untar: Untar, UIDMaps: nil, GIDMaps: nil}
-)
-
-const (
- // HeaderSize is the size in bytes of a tar header
- HeaderSize = 512
-)
-
-const (
- // Uncompressed represents the uncompressed.
- Uncompressed Compression = iota
- // Bzip2 is bzip2 compression algorithm.
- Bzip2
- // Gzip is gzip compression algorithm.
- Gzip
- // Xz is xz compression algorithm.
- Xz
-)
-
-const (
- // AUFSWhiteoutFormat is the default format for whitesouts
- AUFSWhiteoutFormat WhiteoutFormat = iota
- // OverlayWhiteoutFormat formats whiteout according to the overlay
- // standard.
- OverlayWhiteoutFormat
-)
-
-// IsArchive checks for the magic bytes of a tar or any supported compression
-// algorithm.
-func IsArchive(header []byte) bool {
- compression := DetectCompression(header)
- if compression != Uncompressed {
- return true
- }
- r := tar.NewReader(bytes.NewBuffer(header))
- _, err := r.Next()
- return err == nil
-}
-
-// IsArchivePath checks if the (possibly compressed) file at the given path
-// starts with a tar file header.
-func IsArchivePath(path string) bool {
- file, err := os.Open(path)
- if err != nil {
- return false
- }
- defer file.Close()
- rdr, err := DecompressStream(file)
- if err != nil {
- return false
- }
- r := tar.NewReader(rdr)
- _, err = r.Next()
- return err == nil
-}
-
-// DetectCompression detects the compression algorithm of the source.
-func DetectCompression(source []byte) Compression {
- for compression, m := range map[Compression][]byte{
- Bzip2: {0x42, 0x5A, 0x68},
- Gzip: {0x1F, 0x8B, 0x08},
- Xz: {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00},
- } {
- if len(source) < len(m) {
- logrus.Debug("Len too short")
- continue
- }
- if bytes.Compare(m, source[:len(m)]) == 0 {
- return compression
- }
- }
- return Uncompressed
-}
-
-func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) {
- args := []string{"xz", "-d", "-c", "-q"}
-
- return cmdStream(exec.Command(args[0], args[1:]...), archive)
-}
-
-// DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive.
-func DecompressStream(archive io.Reader) (io.ReadCloser, error) {
- p := pools.BufioReader32KPool
- buf := p.Get(archive)
- bs, err := buf.Peek(10)
- if err != nil && err != io.EOF {
- // Note: we'll ignore any io.EOF error because there are some odd
- // cases where the layer.tar file will be empty (zero bytes) and
- // that results in an io.EOF from the Peek() call. So, in those
- // cases we'll just treat it as a non-compressed stream and
- // that means just create an empty layer.
- // See Issue 18170
- return nil, err
- }
-
- compression := DetectCompression(bs)
- switch compression {
- case Uncompressed:
- readBufWrapper := p.NewReadCloserWrapper(buf, buf)
- return readBufWrapper, nil
- case Gzip:
- gzReader, err := gzip.NewReader(buf)
- if err != nil {
- return nil, err
- }
- readBufWrapper := p.NewReadCloserWrapper(buf, gzReader)
- return readBufWrapper, nil
- case Bzip2:
- bz2Reader := bzip2.NewReader(buf)
- readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader)
- return readBufWrapper, nil
- case Xz:
- xzReader, chdone, err := xzDecompress(buf)
- if err != nil {
- return nil, err
- }
- readBufWrapper := p.NewReadCloserWrapper(buf, xzReader)
- return ioutils.NewReadCloserWrapper(readBufWrapper, func() error {
- <-chdone
- return readBufWrapper.Close()
- }), nil
- default:
- return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
- }
-}
-
-// CompressStream compresseses the dest with specified compression algorithm.
-func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) {
- p := pools.BufioWriter32KPool
- buf := p.Get(dest)
- switch compression {
- case Uncompressed:
- writeBufWrapper := p.NewWriteCloserWrapper(buf, buf)
- return writeBufWrapper, nil
- case Gzip:
- gzWriter := gzip.NewWriter(dest)
- writeBufWrapper := p.NewWriteCloserWrapper(buf, gzWriter)
- return writeBufWrapper, nil
- case Bzip2, Xz:
- // archive/bzip2 does not support writing, and there is no xz support at all
- // However, this is not a problem as docker only currently generates gzipped tars
- return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
- default:
- return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension())
- }
-}
-
-// Extension returns the extension of a file that uses the specified compression algorithm.
-func (compression *Compression) Extension() string {
- switch *compression {
- case Uncompressed:
- return "tar"
- case Bzip2:
- return "tar.bz2"
- case Gzip:
- return "tar.gz"
- case Xz:
- return "tar.xz"
- }
- return ""
-}
-
-type tarWhiteoutConverter interface {
- ConvertWrite(*tar.Header, string, os.FileInfo) error
- ConvertRead(*tar.Header, string) (bool, error)
-}
-
-type tarAppender struct {
- TarWriter *tar.Writer
- Buffer *bufio.Writer
-
- // for hardlink mapping
- SeenFiles map[uint64]string
- UIDMaps []idtools.IDMap
- GIDMaps []idtools.IDMap
-
- // For packing and unpacking whiteout files in the
- // non standard format. The whiteout files defined
- // by the AUFS standard are used as the tar whiteout
- // standard.
- WhiteoutConverter tarWhiteoutConverter
-}
-
-// canonicalTarName provides a platform-independent and consistent posix-style
-//path for files and directories to be archived regardless of the platform.
-func canonicalTarName(name string, isDir bool) (string, error) {
- name, err := CanonicalTarNameForPath(name)
- if err != nil {
- return "", err
- }
-
- // suffix with '/' for directories
- if isDir && !strings.HasSuffix(name, "/") {
- name += "/"
- }
- return name, nil
-}
-
-// addTarFile adds to the tar archive a file from `path` as `name`
-func (ta *tarAppender) addTarFile(path, name string) error {
- fi, err := os.Lstat(path)
- if err != nil {
- return err
- }
-
- link := ""
- if fi.Mode()&os.ModeSymlink != 0 {
- if link, err = os.Readlink(path); err != nil {
- return err
- }
- }
-
- hdr, err := tar.FileInfoHeader(fi, link)
- if err != nil {
- return err
- }
- hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
-
- name, err = canonicalTarName(name, fi.IsDir())
- if err != nil {
- return fmt.Errorf("tar: cannot canonicalize path: %v", err)
- }
- hdr.Name = name
-
- inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
- if err != nil {
- return err
- }
-
- // if it's not a directory and has more than 1 link,
- // it's hardlinked, so set the type flag accordingly
- if !fi.IsDir() && hasHardlinks(fi) {
- // a link should have a name that it links too
- // and that linked name should be first in the tar archive
- if oldpath, ok := ta.SeenFiles[inode]; ok {
- hdr.Typeflag = tar.TypeLink
- hdr.Linkname = oldpath
- hdr.Size = 0 // This Must be here for the writer math to add up!
- } else {
- ta.SeenFiles[inode] = name
- }
- }
-
- capability, _ := system.Lgetxattr(path, "security.capability")
- if capability != nil {
- hdr.Xattrs = make(map[string]string)
- hdr.Xattrs["security.capability"] = string(capability)
- }
-
- //handle re-mapping container ID mappings back to host ID mappings before
- //writing tar headers/files. We skip whiteout files because they were written
- //by the kernel and already have proper ownership relative to the host
- if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && (ta.UIDMaps != nil || ta.GIDMaps != nil) {
- uid, gid, err := getFileUIDGID(fi.Sys())
- if err != nil {
- return err
- }
- xUID, err := idtools.ToContainer(uid, ta.UIDMaps)
- if err != nil {
- return err
- }
- xGID, err := idtools.ToContainer(gid, ta.GIDMaps)
- if err != nil {
- return err
- }
- hdr.Uid = xUID
- hdr.Gid = xGID
- }
-
- if ta.WhiteoutConverter != nil {
- if err := ta.WhiteoutConverter.ConvertWrite(hdr, path, fi); err != nil {
- return err
- }
- }
-
- if err := ta.TarWriter.WriteHeader(hdr); err != nil {
- return err
- }
-
- if hdr.Typeflag == tar.TypeReg {
- file, err := os.Open(path)
- if err != nil {
- return err
- }
-
- ta.Buffer.Reset(ta.TarWriter)
- defer ta.Buffer.Reset(nil)
- _, err = io.Copy(ta.Buffer, file)
- file.Close()
- if err != nil {
- return err
- }
- err = ta.Buffer.Flush()
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *TarChownOptions) error {
- // hdr.Mode is in linux format, which we can use for sycalls,
- // but for os.Foo() calls we need the mode converted to os.FileMode,
- // so use hdrInfo.Mode() (they differ for e.g. setuid bits)
- hdrInfo := hdr.FileInfo()
-
- switch hdr.Typeflag {
- case tar.TypeDir:
- // Create directory unless it exists as a directory already.
- // In that case we just want to merge the two
- if fi, err := os.Lstat(path); !(err == nil && fi.IsDir()) {
- if err := os.Mkdir(path, hdrInfo.Mode()); err != nil {
- return err
- }
- }
-
- case tar.TypeReg, tar.TypeRegA:
- // Source is regular file
- file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, hdrInfo.Mode())
- if err != nil {
- return err
- }
- if _, err := io.Copy(file, reader); err != nil {
- file.Close()
- return err
- }
- file.Close()
-
- case tar.TypeBlock, tar.TypeChar, tar.TypeFifo:
- // Handle this is an OS-specific way
- if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
- return err
- }
-
- case tar.TypeLink:
- targetPath := filepath.Join(extractDir, hdr.Linkname)
- // check for hardlink breakout
- if !strings.HasPrefix(targetPath, extractDir) {
- return breakoutError(fmt.Errorf("invalid hardlink %q -> %q", targetPath, hdr.Linkname))
- }
- if err := os.Link(targetPath, path); err != nil {
- return err
- }
-
- case tar.TypeSymlink:
- // path -> hdr.Linkname = targetPath
- // e.g. /extractDir/path/to/symlink -> ../2/file = /extractDir/path/2/file
- targetPath := filepath.Join(filepath.Dir(path), hdr.Linkname)
-
- // the reason we don't need to check symlinks in the path (with FollowSymlinkInScope) is because
- // that symlink would first have to be created, which would be caught earlier, at this very check:
- if !strings.HasPrefix(targetPath, extractDir) {
- return breakoutError(fmt.Errorf("invalid symlink %q -> %q", path, hdr.Linkname))
- }
- if err := os.Symlink(hdr.Linkname, path); err != nil {
- return err
- }
-
- case tar.TypeXGlobalHeader:
- logrus.Debug("PAX Global Extended Headers found and ignored")
- return nil
-
- default:
- return fmt.Errorf("Unhandled tar header type %d\n", hdr.Typeflag)
- }
-
- // Lchown is not supported on Windows.
- if Lchown && runtime.GOOS != "windows" {
- if chownOpts == nil {
- chownOpts = &TarChownOptions{UID: hdr.Uid, GID: hdr.Gid}
- }
- if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil {
- return err
- }
- }
-
- var errors []string
- for key, value := range hdr.Xattrs {
- if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil {
- if err == syscall.ENOTSUP {
- // We ignore errors here because not all graphdrivers support
- // xattrs *cough* old versions of AUFS *cough*. However only
- // ENOTSUP should be emitted in that case, otherwise we still
- // bail.
- errors = append(errors, err.Error())
- continue
- }
- return err
- }
-
- }
-
- if len(errors) > 0 {
- logrus.WithFields(logrus.Fields{
- "errors": errors,
- }).Warn("ignored xattrs in archive: underlying filesystem doesn't support them")
- }
-
- // There is no LChmod, so ignore mode for symlink. Also, this
- // must happen after chown, as that can modify the file mode
- if err := handleLChmod(hdr, path, hdrInfo); err != nil {
- return err
- }
-
- aTime := hdr.AccessTime
- if aTime.Before(hdr.ModTime) {
- // Last access time should never be before last modified time.
- aTime = hdr.ModTime
- }
-
- // system.Chtimes doesn't support a NOFOLLOW flag atm
- if hdr.Typeflag == tar.TypeLink {
- if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) {
- if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil {
- return err
- }
- }
- } else if hdr.Typeflag != tar.TypeSymlink {
- if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil {
- return err
- }
- } else {
- ts := []syscall.Timespec{timeToTimespec(aTime), timeToTimespec(hdr.ModTime)}
- if err := system.LUtimesNano(path, ts); err != nil && err != system.ErrNotSupportedPlatform {
- return err
- }
- }
- return nil
-}
-
-// Tar creates an archive from the directory at `path`, and returns it as a
-// stream of bytes.
-func Tar(path string, compression Compression) (io.ReadCloser, error) {
- return TarWithOptions(path, &TarOptions{Compression: compression})
-}
-
-// TarWithOptions creates an archive from the directory at `path`, only including files whose relative
-// paths are included in `options.IncludeFiles` (if non-nil) or not in `options.ExcludePatterns`.
-func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error) {
-
- // Fix the source path to work with long path names. This is a no-op
- // on platforms other than Windows.
- srcPath = fixVolumePathPrefix(srcPath)
-
- patterns, patDirs, exceptions, err := fileutils.CleanPatterns(options.ExcludePatterns)
-
- if err != nil {
- return nil, err
- }
-
- pipeReader, pipeWriter := io.Pipe()
-
- compressWriter, err := CompressStream(pipeWriter, options.Compression)
- if err != nil {
- return nil, err
- }
-
- go func() {
- ta := &tarAppender{
- TarWriter: tar.NewWriter(compressWriter),
- Buffer: pools.BufioWriter32KPool.Get(nil),
- SeenFiles: make(map[uint64]string),
- UIDMaps: options.UIDMaps,
- GIDMaps: options.GIDMaps,
- WhiteoutConverter: getWhiteoutConverter(options.WhiteoutFormat),
- }
-
- defer func() {
- // Make sure to check the error on Close.
- if err := ta.TarWriter.Close(); err != nil {
- logrus.Errorf("Can't close tar writer: %s", err)
- }
- if err := compressWriter.Close(); err != nil {
- logrus.Errorf("Can't close compress writer: %s", err)
- }
- if err := pipeWriter.Close(); err != nil {
- logrus.Errorf("Can't close pipe writer: %s", err)
- }
- }()
-
- // this buffer is needed for the duration of this piped stream
- defer pools.BufioWriter32KPool.Put(ta.Buffer)
-
- // In general we log errors here but ignore them because
- // during e.g. a diff operation the container can continue
- // mutating the filesystem and we can see transient errors
- // from this
-
- stat, err := os.Lstat(srcPath)
- if err != nil {
- return
- }
-
- if !stat.IsDir() {
- // We can't later join a non-dir with any includes because the
- // 'walk' will error if "file/." is stat-ed and "file" is not a
- // directory. So, we must split the source path and use the
- // basename as the include.
- if len(options.IncludeFiles) > 0 {
- logrus.Warn("Tar: Can't archive a file with includes")
- }
-
- dir, base := SplitPathDirEntry(srcPath)
- srcPath = dir
- options.IncludeFiles = []string{base}
- }
-
- if len(options.IncludeFiles) == 0 {
- options.IncludeFiles = []string{"."}
- }
-
- seen := make(map[string]bool)
-
- for _, include := range options.IncludeFiles {
- rebaseName := options.RebaseNames[include]
-
- walkRoot := getWalkRoot(srcPath, include)
- filepath.Walk(walkRoot, func(filePath string, f os.FileInfo, err error) error {
- if err != nil {
- logrus.Errorf("Tar: Can't stat file %s to tar: %s", srcPath, err)
- return nil
- }
-
- relFilePath, err := filepath.Rel(srcPath, filePath)
- if err != nil || (!options.IncludeSourceDir && relFilePath == "." && f.IsDir()) {
- // Error getting relative path OR we are looking
- // at the source directory path. Skip in both situations.
- return nil
- }
-
- if options.IncludeSourceDir && include == "." && relFilePath != "." {
- relFilePath = strings.Join([]string{".", relFilePath}, string(filepath.Separator))
- }
-
- skip := false
-
- // If "include" is an exact match for the current file
- // then even if there's an "excludePatterns" pattern that
- // matches it, don't skip it. IOW, assume an explicit 'include'
- // is asking for that file no matter what - which is true
- // for some files, like .dockerignore and Dockerfile (sometimes)
- if include != relFilePath {
- skip, err = fileutils.OptimizedMatches(relFilePath, patterns, patDirs)
- if err != nil {
- logrus.Errorf("Error matching %s: %v", relFilePath, err)
- return err
- }
- }
-
- if skip {
- // If we want to skip this file and its a directory
- // then we should first check to see if there's an
- // excludes pattern (eg !dir/file) that starts with this
- // dir. If so then we can't skip this dir.
-
- // Its not a dir then so we can just return/skip.
- if !f.IsDir() {
- return nil
- }
-
- // No exceptions (!...) in patterns so just skip dir
- if !exceptions {
- return filepath.SkipDir
- }
-
- dirSlash := relFilePath + string(filepath.Separator)
-
- for _, pat := range patterns {
- if pat[0] != '!' {
- continue
- }
- pat = pat[1:] + string(filepath.Separator)
- if strings.HasPrefix(pat, dirSlash) {
- // found a match - so can't skip this dir
- return nil
- }
- }
-
- // No matching exclusion dir so just skip dir
- return filepath.SkipDir
- }
-
- if seen[relFilePath] {
- return nil
- }
- seen[relFilePath] = true
-
- // Rename the base resource.
- if rebaseName != "" {
- var replacement string
- if rebaseName != string(filepath.Separator) {
- // Special case the root directory to replace with an
- // empty string instead so that we don't end up with
- // double slashes in the paths.
- replacement = rebaseName
- }
-
- relFilePath = strings.Replace(relFilePath, include, replacement, 1)
- }
-
- if err := ta.addTarFile(filePath, relFilePath); err != nil {
- logrus.Errorf("Can't add file %s to tar: %s", filePath, err)
- // if pipe is broken, stop writing tar stream to it
- if err == io.ErrClosedPipe {
- return err
- }
- }
- return nil
- })
- }
- }()
-
- return pipeReader, nil
-}
-
-// Unpack unpacks the decompressedArchive to dest with options.
-func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error {
- tr := tar.NewReader(decompressedArchive)
- trBuf := pools.BufioReader32KPool.Get(nil)
- defer pools.BufioReader32KPool.Put(trBuf)
-
- var dirs []*tar.Header
- remappedRootUID, remappedRootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps)
- if err != nil {
- return err
- }
- whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat)
-
- // Iterate through the files in the archive.
-loop:
- for {
- hdr, err := tr.Next()
- if err == io.EOF {
- // end of tar archive
- break
- }
- if err != nil {
- return err
- }
-
- // Normalize name, for safety and for a simple is-root check
- // This keeps "../" as-is, but normalizes "/../" to "/". Or Windows:
- // This keeps "..\" as-is, but normalizes "\..\" to "\".
- hdr.Name = filepath.Clean(hdr.Name)
-
- for _, exclude := range options.ExcludePatterns {
- if strings.HasPrefix(hdr.Name, exclude) {
- continue loop
- }
- }
-
- // After calling filepath.Clean(hdr.Name) above, hdr.Name will now be in
- // the filepath format for the OS on which the daemon is running. Hence
- // the check for a slash-suffix MUST be done in an OS-agnostic way.
- if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) {
- // Not the root directory, ensure that the parent directory exists
- parent := filepath.Dir(hdr.Name)
- parentPath := filepath.Join(dest, parent)
- if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
- err = idtools.MkdirAllNewAs(parentPath, 0777, remappedRootUID, remappedRootGID)
- if err != nil {
- return err
- }
- }
- }
-
- path := filepath.Join(dest, hdr.Name)
- rel, err := filepath.Rel(dest, path)
- if err != nil {
- return err
- }
- if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
- return breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest))
- }
-
- // If path exits we almost always just want to remove and replace it
- // The only exception is when it is a directory *and* the file from
- // the layer is also a directory. Then we want to merge them (i.e.
- // just apply the metadata from the layer).
- if fi, err := os.Lstat(path); err == nil {
- if options.NoOverwriteDirNonDir && fi.IsDir() && hdr.Typeflag != tar.TypeDir {
- // If NoOverwriteDirNonDir is true then we cannot replace
- // an existing directory with a non-directory from the archive.
- return fmt.Errorf("cannot overwrite directory %q with non-directory %q", path, dest)
- }
-
- if options.NoOverwriteDirNonDir && !fi.IsDir() && hdr.Typeflag == tar.TypeDir {
- // If NoOverwriteDirNonDir is true then we cannot replace
- // an existing non-directory with a directory from the archive.
- return fmt.Errorf("cannot overwrite non-directory %q with directory %q", path, dest)
- }
-
- if fi.IsDir() && hdr.Name == "." {
- continue
- }
-
- if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
- if err := os.RemoveAll(path); err != nil {
- return err
- }
- }
- }
- trBuf.Reset(tr)
-
- // if the options contain a uid & gid maps, convert header uid/gid
- // entries using the maps such that lchown sets the proper mapped
- // uid/gid after writing the file. We only perform this mapping if
- // the file isn't already owned by the remapped root UID or GID, as
- // that specific uid/gid has no mapping from container -> host, and
- // those files already have the proper ownership for inside the
- // container.
- if hdr.Uid != remappedRootUID {
- xUID, err := idtools.ToHost(hdr.Uid, options.UIDMaps)
- if err != nil {
- return err
- }
- hdr.Uid = xUID
- }
- if hdr.Gid != remappedRootGID {
- xGID, err := idtools.ToHost(hdr.Gid, options.GIDMaps)
- if err != nil {
- return err
- }
- hdr.Gid = xGID
- }
-
- if whiteoutConverter != nil {
- writeFile, err := whiteoutConverter.ConvertRead(hdr, path)
- if err != nil {
- return err
- }
- if !writeFile {
- continue
- }
- }
-
- if err := createTarFile(path, dest, hdr, trBuf, !options.NoLchown, options.ChownOpts); err != nil {
- return err
- }
-
- // Directory mtimes must be handled at the end to avoid further
- // file creation in them to modify the directory mtime
- if hdr.Typeflag == tar.TypeDir {
- dirs = append(dirs, hdr)
- }
- }
-
- for _, hdr := range dirs {
- path := filepath.Join(dest, hdr.Name)
-
- if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
- return err
- }
- }
- return nil
-}
-
-// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
-// and unpacks it into the directory at `dest`.
-// The archive may be compressed with one of the following algorithms:
-// identity (uncompressed), gzip, bzip2, xz.
-// FIXME: specify behavior when target path exists vs. doesn't exist.
-func Untar(tarArchive io.Reader, dest string, options *TarOptions) error {
- return untarHandler(tarArchive, dest, options, true)
-}
-
-// UntarUncompressed reads a stream of bytes from `archive`, parses it as a tar archive,
-// and unpacks it into the directory at `dest`.
-// The archive must be an uncompressed stream.
-func UntarUncompressed(tarArchive io.Reader, dest string, options *TarOptions) error {
- return untarHandler(tarArchive, dest, options, false)
-}
-
-// Handler for teasing out the automatic decompression
-func untarHandler(tarArchive io.Reader, dest string, options *TarOptions, decompress bool) error {
- if tarArchive == nil {
- return fmt.Errorf("Empty archive")
- }
- dest = filepath.Clean(dest)
- if options == nil {
- options = &TarOptions{}
- }
- if options.ExcludePatterns == nil {
- options.ExcludePatterns = []string{}
- }
-
- r := tarArchive
- if decompress {
- decompressedArchive, err := DecompressStream(tarArchive)
- if err != nil {
- return err
- }
- defer decompressedArchive.Close()
- r = decompressedArchive
- }
-
- return Unpack(r, dest, options)
-}
-
-// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
-// If either Tar or Untar fails, TarUntar aborts and returns the error.
-func (archiver *Archiver) TarUntar(src, dst string) error {
- logrus.Debugf("TarUntar(%s %s)", src, dst)
- archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})
- if err != nil {
- return err
- }
- defer archive.Close()
-
- var options *TarOptions
- if archiver.UIDMaps != nil || archiver.GIDMaps != nil {
- options = &TarOptions{
- UIDMaps: archiver.UIDMaps,
- GIDMaps: archiver.GIDMaps,
- }
- }
- return archiver.Untar(archive, dst, options)
-}
-
-// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
-// If either Tar or Untar fails, TarUntar aborts and returns the error.
-func TarUntar(src, dst string) error {
- return defaultArchiver.TarUntar(src, dst)
-}
-
-// UntarPath untar a file from path to a destination, src is the source tar file path.
-func (archiver *Archiver) UntarPath(src, dst string) error {
- archive, err := os.Open(src)
- if err != nil {
- return err
- }
- defer archive.Close()
- var options *TarOptions
- if archiver.UIDMaps != nil || archiver.GIDMaps != nil {
- options = &TarOptions{
- UIDMaps: archiver.UIDMaps,
- GIDMaps: archiver.GIDMaps,
- }
- }
- return archiver.Untar(archive, dst, options)
-}
-
-// UntarPath is a convenience function which looks for an archive
-// at filesystem path `src`, and unpacks it at `dst`.
-func UntarPath(src, dst string) error {
- return defaultArchiver.UntarPath(src, dst)
-}
-
-// CopyWithTar creates a tar archive of filesystem path `src`, and
-// unpacks it at filesystem path `dst`.
-// The archive is streamed directly with fixed buffering and no
-// intermediary disk IO.
-func (archiver *Archiver) CopyWithTar(src, dst string) error {
- srcSt, err := os.Stat(src)
- if err != nil {
- return err
- }
- if !srcSt.IsDir() {
- return archiver.CopyFileWithTar(src, dst)
- }
-
- // if this archiver is set up with ID mapping we need to create
- // the new destination directory with the remapped root UID/GID pair
- // as owner
- rootUID, rootGID, err := idtools.GetRootUIDGID(archiver.UIDMaps, archiver.GIDMaps)
- if err != nil {
- return err
- }
- // Create dst, copy src's content into it
- logrus.Debugf("Creating dest directory: %s", dst)
- if err := idtools.MkdirAllNewAs(dst, 0755, rootUID, rootGID); err != nil {
- return err
- }
- logrus.Debugf("Calling TarUntar(%s, %s)", src, dst)
- return archiver.TarUntar(src, dst)
-}
-
-// CopyWithTar creates a tar archive of filesystem path `src`, and
-// unpacks it at filesystem path `dst`.
-// The archive is streamed directly with fixed buffering and no
-// intermediary disk IO.
-func CopyWithTar(src, dst string) error {
- return defaultArchiver.CopyWithTar(src, dst)
-}
-
-// CopyFileWithTar emulates the behavior of the 'cp' command-line
-// for a single file. It copies a regular file from path `src` to
-// path `dst`, and preserves all its metadata.
-func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
- logrus.Debugf("CopyFileWithTar(%s, %s)", src, dst)
- srcSt, err := os.Stat(src)
- if err != nil {
- return err
- }
-
- if srcSt.IsDir() {
- return fmt.Errorf("Can't copy a directory")
- }
-
- // Clean up the trailing slash. This must be done in an operating
- // system specific manner.
- if dst[len(dst)-1] == os.PathSeparator {
- dst = filepath.Join(dst, filepath.Base(src))
- }
- // Create the holding directory if necessary
- if err := system.MkdirAll(filepath.Dir(dst), 0700); err != nil {
- return err
- }
-
- r, w := io.Pipe()
- errC := promise.Go(func() error {
- defer w.Close()
-
- srcF, err := os.Open(src)
- if err != nil {
- return err
- }
- defer srcF.Close()
-
- hdr, err := tar.FileInfoHeader(srcSt, "")
- if err != nil {
- return err
- }
- hdr.Name = filepath.Base(dst)
- hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
-
- remappedRootUID, remappedRootGID, err := idtools.GetRootUIDGID(archiver.UIDMaps, archiver.GIDMaps)
- if err != nil {
- return err
- }
-
- // only perform mapping if the file being copied isn't already owned by the
- // uid or gid of the remapped root in the container
- if remappedRootUID != hdr.Uid {
- xUID, err := idtools.ToHost(hdr.Uid, archiver.UIDMaps)
- if err != nil {
- return err
- }
- hdr.Uid = xUID
- }
- if remappedRootGID != hdr.Gid {
- xGID, err := idtools.ToHost(hdr.Gid, archiver.GIDMaps)
- if err != nil {
- return err
- }
- hdr.Gid = xGID
- }
-
- tw := tar.NewWriter(w)
- defer tw.Close()
- if err := tw.WriteHeader(hdr); err != nil {
- return err
- }
- if _, err := io.Copy(tw, srcF); err != nil {
- return err
- }
- return nil
- })
- defer func() {
- if er := <-errC; err != nil {
- err = er
- }
- }()
-
- err = archiver.Untar(r, filepath.Dir(dst), nil)
- if err != nil {
- r.CloseWithError(err)
- }
- return err
-}
-
-// CopyFileWithTar emulates the behavior of the 'cp' command-line
-// for a single file. It copies a regular file from path `src` to
-// path `dst`, and preserves all its metadata.
-//
-// Destination handling is in an operating specific manner depending
-// where the daemon is running. If `dst` ends with a trailing slash
-// the final destination path will be `dst/base(src)` (Linux) or
-// `dst\base(src)` (Windows).
-func CopyFileWithTar(src, dst string) (err error) {
- return defaultArchiver.CopyFileWithTar(src, dst)
-}
-
-// cmdStream executes a command, and returns its stdout as a stream.
-// If the command fails to run or doesn't complete successfully, an error
-// will be returned, including anything written on stderr.
-func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) {
- chdone := make(chan struct{})
- cmd.Stdin = input
- pipeR, pipeW := io.Pipe()
- cmd.Stdout = pipeW
- var errBuf bytes.Buffer
- cmd.Stderr = &errBuf
-
- // Run the command and return the pipe
- if err := cmd.Start(); err != nil {
- return nil, nil, err
- }
-
- // Copy stdout to the returned pipe
- go func() {
- if err := cmd.Wait(); err != nil {
- pipeW.CloseWithError(fmt.Errorf("%s: %s", err, errBuf.String()))
- } else {
- pipeW.Close()
- }
- close(chdone)
- }()
-
- return pipeR, chdone, nil
-}
-
-// NewTempArchive reads the content of src into a temporary file, and returns the contents
-// of that file as an archive. The archive can only be read once - as soon as reading completes,
-// the file will be deleted.
-func NewTempArchive(src Archive, dir string) (*TempArchive, error) {
- f, err := ioutil.TempFile(dir, "")
- if err != nil {
- return nil, err
- }
- if _, err := io.Copy(f, src); err != nil {
- return nil, err
- }
- if _, err := f.Seek(0, 0); err != nil {
- return nil, err
- }
- st, err := f.Stat()
- if err != nil {
- return nil, err
- }
- size := st.Size()
- return &TempArchive{File: f, Size: size}, nil
-}
-
-// TempArchive is a temporary archive. The archive can only be read once - as soon as reading completes,
-// the file will be deleted.
-type TempArchive struct {
- *os.File
- Size int64 // Pre-computed from Stat().Size() as a convenience
- read int64
- closed bool
-}
-
-// Close closes the underlying file if it's still open, or does a no-op
-// to allow callers to try to close the TempArchive multiple times safely.
-func (archive *TempArchive) Close() error {
- if archive.closed {
- return nil
- }
-
- archive.closed = true
-
- return archive.File.Close()
-}
-
-func (archive *TempArchive) Read(data []byte) (int, error) {
- n, err := archive.File.Read(data)
- archive.read += int64(n)
- if err != nil || archive.read == archive.Size {
- archive.Close()
- os.Remove(archive.File.Name())
- }
- return n, err
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go b/vendor/github.com/docker/docker/pkg/archive/archive_linux.go
deleted file mode 100644
index 86d2c7f..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "os"
- "path/filepath"
- "strings"
- "syscall"
-
- "github.com/docker/docker/pkg/system"
-)
-
-func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
- if format == OverlayWhiteoutFormat {
- return overlayWhiteoutConverter{}
- }
- return nil
-}
-
-type overlayWhiteoutConverter struct{}
-
-func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os.FileInfo) error {
- // convert whiteouts to AUFS format
- if fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 {
- // we just rename the file and make it normal
- hdr.Name = WhiteoutPrefix + hdr.Name
- hdr.Mode = 0600
- hdr.Typeflag = tar.TypeReg
- }
-
- if fi.Mode()&os.ModeDir != 0 {
- // convert opaque dirs to AUFS format by writing an empty file with the prefix
- opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque")
- if err != nil {
- return err
- }
- if opaque != nil && len(opaque) == 1 && opaque[0] == 'y' {
- // create a header for the whiteout file
- // it should inherit some properties from the parent, but be a regular file
- *hdr = tar.Header{
- Typeflag: tar.TypeReg,
- Mode: hdr.Mode & int64(os.ModePerm),
- Name: filepath.Join(hdr.Name, WhiteoutOpaqueDir),
- Size: 0,
- Uid: hdr.Uid,
- Uname: hdr.Uname,
- Gid: hdr.Gid,
- Gname: hdr.Gname,
- AccessTime: hdr.AccessTime,
- ChangeTime: hdr.ChangeTime,
- }
- }
- }
-
- return nil
-}
-
-func (overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (bool, error) {
- base := filepath.Base(path)
- dir := filepath.Dir(path)
-
- // if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay
- if base == WhiteoutOpaqueDir {
- if err := syscall.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}, 0); err != nil {
- return false, err
- }
-
- // don't write the file itself
- return false, nil
- }
-
- // if a file was deleted and we are using overlay, we need to create a character device
- if strings.HasPrefix(base, WhiteoutPrefix) {
- originalBase := base[len(WhiteoutPrefix):]
- originalPath := filepath.Join(dir, originalBase)
-
- if err := syscall.Mknod(originalPath, syscall.S_IFCHR, 0); err != nil {
- return false, err
- }
- if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil {
- return false, err
- }
-
- // don't write the file itself
- return false, nil
- }
-
- return true, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_other.go b/vendor/github.com/docker/docker/pkg/archive/archive_other.go
deleted file mode 100644
index 54acbf2..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive_other.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// +build !linux
-
-package archive
-
-func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_test.go b/vendor/github.com/docker/docker/pkg/archive/archive_test.go
deleted file mode 100644
index 85e4122..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive_test.go
+++ /dev/null
@@ -1,1148 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "strings"
- "testing"
- "time"
-)
-
-var tmp string
-
-func init() {
- tmp = "/tmp/"
- if runtime.GOOS == "windows" {
- tmp = os.Getenv("TEMP") + `\`
- }
-}
-
-func TestIsArchiveNilHeader(t *testing.T) {
- out := IsArchive(nil)
- if out {
- t.Fatalf("isArchive should return false as nil is not a valid archive header")
- }
-}
-
-func TestIsArchiveInvalidHeader(t *testing.T) {
- header := []byte{0x00, 0x01, 0x02}
- out := IsArchive(header)
- if out {
- t.Fatalf("isArchive should return false as %s is not a valid archive header", header)
- }
-}
-
-func TestIsArchiveBzip2(t *testing.T) {
- header := []byte{0x42, 0x5A, 0x68}
- out := IsArchive(header)
- if !out {
- t.Fatalf("isArchive should return true as %s is a bz2 header", header)
- }
-}
-
-func TestIsArchive7zip(t *testing.T) {
- header := []byte{0x50, 0x4b, 0x03, 0x04}
- out := IsArchive(header)
- if out {
- t.Fatalf("isArchive should return false as %s is a 7z header and it is not supported", header)
- }
-}
-
-func TestIsArchivePathDir(t *testing.T) {
- cmd := exec.Command("sh", "-c", "mkdir -p /tmp/archivedir")
- output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("Fail to create an archive file for test : %s.", output)
- }
- if IsArchivePath(tmp + "archivedir") {
- t.Fatalf("Incorrectly recognised directory as an archive")
- }
-}
-
-func TestIsArchivePathInvalidFile(t *testing.T) {
- cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1K count=1 of=/tmp/archive && gzip --stdout /tmp/archive > /tmp/archive.gz")
- output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("Fail to create an archive file for test : %s.", output)
- }
- if IsArchivePath(tmp + "archive") {
- t.Fatalf("Incorrectly recognised invalid tar path as archive")
- }
- if IsArchivePath(tmp + "archive.gz") {
- t.Fatalf("Incorrectly recognised invalid compressed tar path as archive")
- }
-}
-
-func TestIsArchivePathTar(t *testing.T) {
- cmd := exec.Command("sh", "-c", "touch /tmp/archivedata && tar -cf /tmp/archive /tmp/archivedata && gzip --stdout /tmp/archive > /tmp/archive.gz")
- output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("Fail to create an archive file for test : %s.", output)
- }
- if !IsArchivePath(tmp + "/archive") {
- t.Fatalf("Did not recognise valid tar path as archive")
- }
- if !IsArchivePath(tmp + "archive.gz") {
- t.Fatalf("Did not recognise valid compressed tar path as archive")
- }
-}
-
-func TestDecompressStreamGzip(t *testing.T) {
- cmd := exec.Command("sh", "-c", "touch /tmp/archive && gzip -f /tmp/archive")
- output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("Fail to create an archive file for test : %s.", output)
- }
- archive, err := os.Open(tmp + "archive.gz")
- _, err = DecompressStream(archive)
- if err != nil {
- t.Fatalf("Failed to decompress a gzip file.")
- }
-}
-
-func TestDecompressStreamBzip2(t *testing.T) {
- cmd := exec.Command("sh", "-c", "touch /tmp/archive && bzip2 -f /tmp/archive")
- output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("Fail to create an archive file for test : %s.", output)
- }
- archive, err := os.Open(tmp + "archive.bz2")
- _, err = DecompressStream(archive)
- if err != nil {
- t.Fatalf("Failed to decompress a bzip2 file.")
- }
-}
-
-func TestDecompressStreamXz(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("Xz not present in msys2")
- }
- cmd := exec.Command("sh", "-c", "touch /tmp/archive && xz -f /tmp/archive")
- output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("Fail to create an archive file for test : %s.", output)
- }
- archive, err := os.Open(tmp + "archive.xz")
- _, err = DecompressStream(archive)
- if err != nil {
- t.Fatalf("Failed to decompress an xz file.")
- }
-}
-
-func TestCompressStreamXzUnsuported(t *testing.T) {
- dest, err := os.Create(tmp + "dest")
- if err != nil {
- t.Fatalf("Fail to create the destination file")
- }
- _, err = CompressStream(dest, Xz)
- if err == nil {
- t.Fatalf("Should fail as xz is unsupported for compression format.")
- }
-}
-
-func TestCompressStreamBzip2Unsupported(t *testing.T) {
- dest, err := os.Create(tmp + "dest")
- if err != nil {
- t.Fatalf("Fail to create the destination file")
- }
- _, err = CompressStream(dest, Xz)
- if err == nil {
- t.Fatalf("Should fail as xz is unsupported for compression format.")
- }
-}
-
-func TestCompressStreamInvalid(t *testing.T) {
- dest, err := os.Create(tmp + "dest")
- if err != nil {
- t.Fatalf("Fail to create the destination file")
- }
- _, err = CompressStream(dest, -1)
- if err == nil {
- t.Fatalf("Should fail as xz is unsupported for compression format.")
- }
-}
-
-func TestExtensionInvalid(t *testing.T) {
- compression := Compression(-1)
- output := compression.Extension()
- if output != "" {
- t.Fatalf("The extension of an invalid compression should be an empty string.")
- }
-}
-
-func TestExtensionUncompressed(t *testing.T) {
- compression := Uncompressed
- output := compression.Extension()
- if output != "tar" {
- t.Fatalf("The extension of an uncompressed archive should be 'tar'.")
- }
-}
-func TestExtensionBzip2(t *testing.T) {
- compression := Bzip2
- output := compression.Extension()
- if output != "tar.bz2" {
- t.Fatalf("The extension of a bzip2 archive should be 'tar.bz2'")
- }
-}
-func TestExtensionGzip(t *testing.T) {
- compression := Gzip
- output := compression.Extension()
- if output != "tar.gz" {
- t.Fatalf("The extension of a bzip2 archive should be 'tar.gz'")
- }
-}
-func TestExtensionXz(t *testing.T) {
- compression := Xz
- output := compression.Extension()
- if output != "tar.xz" {
- t.Fatalf("The extension of a bzip2 archive should be 'tar.xz'")
- }
-}
-
-func TestCmdStreamLargeStderr(t *testing.T) {
- cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello")
- out, _, err := cmdStream(cmd, nil)
- if err != nil {
- t.Fatalf("Failed to start command: %s", err)
- }
- errCh := make(chan error)
- go func() {
- _, err := io.Copy(ioutil.Discard, out)
- errCh <- err
- }()
- select {
- case err := <-errCh:
- if err != nil {
- t.Fatalf("Command should not have failed (err=%.100s...)", err)
- }
- case <-time.After(5 * time.Second):
- t.Fatalf("Command did not complete in 5 seconds; probable deadlock")
- }
-}
-
-func TestCmdStreamBad(t *testing.T) {
- // TODO Windows: Figure out why this is failing in CI but not locally
- if runtime.GOOS == "windows" {
- t.Skip("Failing on Windows CI machines")
- }
- badCmd := exec.Command("sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1")
- out, _, err := cmdStream(badCmd, nil)
- if err != nil {
- t.Fatalf("Failed to start command: %s", err)
- }
- if output, err := ioutil.ReadAll(out); err == nil {
- t.Fatalf("Command should have failed")
- } else if err.Error() != "exit status 1: error couldn't reverse the phase pulser\n" {
- t.Fatalf("Wrong error value (%s)", err)
- } else if s := string(output); s != "hello\n" {
- t.Fatalf("Command output should be '%s', not '%s'", "hello\\n", output)
- }
-}
-
-func TestCmdStreamGood(t *testing.T) {
- cmd := exec.Command("sh", "-c", "echo hello; exit 0")
- out, _, err := cmdStream(cmd, nil)
- if err != nil {
- t.Fatal(err)
- }
- if output, err := ioutil.ReadAll(out); err != nil {
- t.Fatalf("Command should not have failed (err=%s)", err)
- } else if s := string(output); s != "hello\n" {
- t.Fatalf("Command output should be '%s', not '%s'", "hello\\n", output)
- }
-}
-
-func TestUntarPathWithInvalidDest(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempFolder)
- invalidDestFolder := filepath.Join(tempFolder, "invalidDest")
- // Create a src file
- srcFile := filepath.Join(tempFolder, "src")
- tarFile := filepath.Join(tempFolder, "src.tar")
- os.Create(srcFile)
- os.Create(invalidDestFolder) // being a file (not dir) should cause an error
-
- // Translate back to Unix semantics as next exec.Command is run under sh
- srcFileU := srcFile
- tarFileU := tarFile
- if runtime.GOOS == "windows" {
- tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar"
- srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src"
- }
-
- cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU)
- _, err = cmd.CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
-
- err = UntarPath(tarFile, invalidDestFolder)
- if err == nil {
- t.Fatalf("UntarPath with invalid destination path should throw an error.")
- }
-}
-
-func TestUntarPathWithInvalidSrc(t *testing.T) {
- dest, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatalf("Fail to create the destination file")
- }
- defer os.RemoveAll(dest)
- err = UntarPath("/invalid/path", dest)
- if err == nil {
- t.Fatalf("UntarPath with invalid src path should throw an error.")
- }
-}
-
-func TestUntarPath(t *testing.T) {
- tmpFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tmpFolder)
- srcFile := filepath.Join(tmpFolder, "src")
- tarFile := filepath.Join(tmpFolder, "src.tar")
- os.Create(filepath.Join(tmpFolder, "src"))
-
- destFolder := filepath.Join(tmpFolder, "dest")
- err = os.MkdirAll(destFolder, 0740)
- if err != nil {
- t.Fatalf("Fail to create the destination file")
- }
-
- // Translate back to Unix semantics as next exec.Command is run under sh
- srcFileU := srcFile
- tarFileU := tarFile
- if runtime.GOOS == "windows" {
- tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar"
- srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src"
- }
- cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU)
- _, err = cmd.CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
-
- err = UntarPath(tarFile, destFolder)
- if err != nil {
- t.Fatalf("UntarPath shouldn't throw an error, %s.", err)
- }
- expectedFile := filepath.Join(destFolder, srcFileU)
- _, err = os.Stat(expectedFile)
- if err != nil {
- t.Fatalf("Destination folder should contain the source file but did not.")
- }
-}
-
-// Do the same test as above but with the destination as file, it should fail
-func TestUntarPathWithDestinationFile(t *testing.T) {
- tmpFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tmpFolder)
- srcFile := filepath.Join(tmpFolder, "src")
- tarFile := filepath.Join(tmpFolder, "src.tar")
- os.Create(filepath.Join(tmpFolder, "src"))
-
- // Translate back to Unix semantics as next exec.Command is run under sh
- srcFileU := srcFile
- tarFileU := tarFile
- if runtime.GOOS == "windows" {
- tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar"
- srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src"
- }
- cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU)
- _, err = cmd.CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
- destFile := filepath.Join(tmpFolder, "dest")
- _, err = os.Create(destFile)
- if err != nil {
- t.Fatalf("Fail to create the destination file")
- }
- err = UntarPath(tarFile, destFile)
- if err == nil {
- t.Fatalf("UntarPath should throw an error if the destination if a file")
- }
-}
-
-// Do the same test as above but with the destination folder already exists
-// and the destination file is a directory
-// It's working, see https://github.com/docker/docker/issues/10040
-func TestUntarPathWithDestinationSrcFileAsFolder(t *testing.T) {
- tmpFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tmpFolder)
- srcFile := filepath.Join(tmpFolder, "src")
- tarFile := filepath.Join(tmpFolder, "src.tar")
- os.Create(srcFile)
-
- // Translate back to Unix semantics as next exec.Command is run under sh
- srcFileU := srcFile
- tarFileU := tarFile
- if runtime.GOOS == "windows" {
- tarFileU = "/tmp/" + filepath.Base(filepath.Dir(tarFile)) + "/src.tar"
- srcFileU = "/tmp/" + filepath.Base(filepath.Dir(srcFile)) + "/src"
- }
-
- cmd := exec.Command("sh", "-c", "tar cf "+tarFileU+" "+srcFileU)
- _, err = cmd.CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
- destFolder := filepath.Join(tmpFolder, "dest")
- err = os.MkdirAll(destFolder, 0740)
- if err != nil {
- t.Fatalf("Fail to create the destination folder")
- }
- // Let's create a folder that will has the same path as the extracted file (from tar)
- destSrcFileAsFolder := filepath.Join(destFolder, srcFileU)
- err = os.MkdirAll(destSrcFileAsFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = UntarPath(tarFile, destFolder)
- if err != nil {
- t.Fatalf("UntarPath should throw not throw an error if the extracted file already exists and is a folder")
- }
-}
-
-func TestCopyWithTarInvalidSrc(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(nil)
- }
- destFolder := filepath.Join(tempFolder, "dest")
- invalidSrc := filepath.Join(tempFolder, "doesnotexists")
- err = os.MkdirAll(destFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = CopyWithTar(invalidSrc, destFolder)
- if err == nil {
- t.Fatalf("archiver.CopyWithTar with invalid src path should throw an error.")
- }
-}
-
-func TestCopyWithTarInexistentDestWillCreateIt(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(nil)
- }
- srcFolder := filepath.Join(tempFolder, "src")
- inexistentDestFolder := filepath.Join(tempFolder, "doesnotexists")
- err = os.MkdirAll(srcFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = CopyWithTar(srcFolder, inexistentDestFolder)
- if err != nil {
- t.Fatalf("CopyWithTar with an inexistent folder shouldn't fail.")
- }
- _, err = os.Stat(inexistentDestFolder)
- if err != nil {
- t.Fatalf("CopyWithTar with an inexistent folder should create it.")
- }
-}
-
-// Test CopyWithTar with a file as src
-func TestCopyWithTarSrcFile(t *testing.T) {
- folder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(folder)
- dest := filepath.Join(folder, "dest")
- srcFolder := filepath.Join(folder, "src")
- src := filepath.Join(folder, filepath.Join("src", "src"))
- err = os.MkdirAll(srcFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = os.MkdirAll(dest, 0740)
- if err != nil {
- t.Fatal(err)
- }
- ioutil.WriteFile(src, []byte("content"), 0777)
- err = CopyWithTar(src, dest)
- if err != nil {
- t.Fatalf("archiver.CopyWithTar shouldn't throw an error, %s.", err)
- }
- _, err = os.Stat(dest)
- // FIXME Check the content
- if err != nil {
- t.Fatalf("Destination file should be the same as the source.")
- }
-}
-
-// Test CopyWithTar with a folder as src
-func TestCopyWithTarSrcFolder(t *testing.T) {
- folder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(folder)
- dest := filepath.Join(folder, "dest")
- src := filepath.Join(folder, filepath.Join("src", "folder"))
- err = os.MkdirAll(src, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = os.MkdirAll(dest, 0740)
- if err != nil {
- t.Fatal(err)
- }
- ioutil.WriteFile(filepath.Join(src, "file"), []byte("content"), 0777)
- err = CopyWithTar(src, dest)
- if err != nil {
- t.Fatalf("archiver.CopyWithTar shouldn't throw an error, %s.", err)
- }
- _, err = os.Stat(dest)
- // FIXME Check the content (the file inside)
- if err != nil {
- t.Fatalf("Destination folder should contain the source file but did not.")
- }
-}
-
-func TestCopyFileWithTarInvalidSrc(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempFolder)
- destFolder := filepath.Join(tempFolder, "dest")
- err = os.MkdirAll(destFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- invalidFile := filepath.Join(tempFolder, "doesnotexists")
- err = CopyFileWithTar(invalidFile, destFolder)
- if err == nil {
- t.Fatalf("archiver.CopyWithTar with invalid src path should throw an error.")
- }
-}
-
-func TestCopyFileWithTarInexistentDestWillCreateIt(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(nil)
- }
- defer os.RemoveAll(tempFolder)
- srcFile := filepath.Join(tempFolder, "src")
- inexistentDestFolder := filepath.Join(tempFolder, "doesnotexists")
- _, err = os.Create(srcFile)
- if err != nil {
- t.Fatal(err)
- }
- err = CopyFileWithTar(srcFile, inexistentDestFolder)
- if err != nil {
- t.Fatalf("CopyWithTar with an inexistent folder shouldn't fail.")
- }
- _, err = os.Stat(inexistentDestFolder)
- if err != nil {
- t.Fatalf("CopyWithTar with an inexistent folder should create it.")
- }
- // FIXME Test the src file and content
-}
-
-func TestCopyFileWithTarSrcFolder(t *testing.T) {
- folder, err := ioutil.TempDir("", "docker-archive-copyfilewithtar-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(folder)
- dest := filepath.Join(folder, "dest")
- src := filepath.Join(folder, "srcfolder")
- err = os.MkdirAll(src, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = os.MkdirAll(dest, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = CopyFileWithTar(src, dest)
- if err == nil {
- t.Fatalf("CopyFileWithTar should throw an error with a folder.")
- }
-}
-
-func TestCopyFileWithTarSrcFile(t *testing.T) {
- folder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(folder)
- dest := filepath.Join(folder, "dest")
- srcFolder := filepath.Join(folder, "src")
- src := filepath.Join(folder, filepath.Join("src", "src"))
- err = os.MkdirAll(srcFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- err = os.MkdirAll(dest, 0740)
- if err != nil {
- t.Fatal(err)
- }
- ioutil.WriteFile(src, []byte("content"), 0777)
- err = CopyWithTar(src, dest+"/")
- if err != nil {
- t.Fatalf("archiver.CopyFileWithTar shouldn't throw an error, %s.", err)
- }
- _, err = os.Stat(dest)
- if err != nil {
- t.Fatalf("Destination folder should contain the source file but did not.")
- }
-}
-
-func TestTarFiles(t *testing.T) {
- // TODO Windows: Figure out how to port this test.
- if runtime.GOOS == "windows" {
- t.Skip("Failing on Windows")
- }
- // try without hardlinks
- if err := checkNoChanges(1000, false); err != nil {
- t.Fatal(err)
- }
- // try with hardlinks
- if err := checkNoChanges(1000, true); err != nil {
- t.Fatal(err)
- }
-}
-
-func checkNoChanges(fileNum int, hardlinks bool) error {
- srcDir, err := ioutil.TempDir("", "docker-test-srcDir")
- if err != nil {
- return err
- }
- defer os.RemoveAll(srcDir)
-
- destDir, err := ioutil.TempDir("", "docker-test-destDir")
- if err != nil {
- return err
- }
- defer os.RemoveAll(destDir)
-
- _, err = prepareUntarSourceDirectory(fileNum, srcDir, hardlinks)
- if err != nil {
- return err
- }
-
- err = TarUntar(srcDir, destDir)
- if err != nil {
- return err
- }
-
- changes, err := ChangesDirs(destDir, srcDir)
- if err != nil {
- return err
- }
- if len(changes) > 0 {
- return fmt.Errorf("with %d files and %v hardlinks: expected 0 changes, got %d", fileNum, hardlinks, len(changes))
- }
- return nil
-}
-
-func tarUntar(t *testing.T, origin string, options *TarOptions) ([]Change, error) {
- archive, err := TarWithOptions(origin, options)
- if err != nil {
- t.Fatal(err)
- }
- defer archive.Close()
-
- buf := make([]byte, 10)
- if _, err := archive.Read(buf); err != nil {
- return nil, err
- }
- wrap := io.MultiReader(bytes.NewReader(buf), archive)
-
- detectedCompression := DetectCompression(buf)
- compression := options.Compression
- if detectedCompression.Extension() != compression.Extension() {
- return nil, fmt.Errorf("Wrong compression detected. Actual compression: %s, found %s", compression.Extension(), detectedCompression.Extension())
- }
-
- tmp, err := ioutil.TempDir("", "docker-test-untar")
- if err != nil {
- return nil, err
- }
- defer os.RemoveAll(tmp)
- if err := Untar(wrap, tmp, nil); err != nil {
- return nil, err
- }
- if _, err := os.Stat(tmp); err != nil {
- return nil, err
- }
-
- return ChangesDirs(origin, tmp)
-}
-
-func TestTarUntar(t *testing.T) {
- // TODO Windows: Figure out how to fix this test.
- if runtime.GOOS == "windows" {
- t.Skip("Failing on Windows")
- }
- origin, err := ioutil.TempDir("", "docker-test-untar-origin")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(origin)
- if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(filepath.Join(origin, "2"), []byte("welcome!"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(filepath.Join(origin, "3"), []byte("will be ignored"), 0700); err != nil {
- t.Fatal(err)
- }
-
- for _, c := range []Compression{
- Uncompressed,
- Gzip,
- } {
- changes, err := tarUntar(t, origin, &TarOptions{
- Compression: c,
- ExcludePatterns: []string{"3"},
- })
-
- if err != nil {
- t.Fatalf("Error tar/untar for compression %s: %s", c.Extension(), err)
- }
-
- if len(changes) != 1 || changes[0].Path != "/3" {
- t.Fatalf("Unexpected differences after tarUntar: %v", changes)
- }
- }
-}
-
-func TestTarWithOptions(t *testing.T) {
- // TODO Windows: Figure out how to fix this test.
- if runtime.GOOS == "windows" {
- t.Skip("Failing on Windows")
- }
- origin, err := ioutil.TempDir("", "docker-test-untar-origin")
- if err != nil {
- t.Fatal(err)
- }
- if _, err := ioutil.TempDir(origin, "folder"); err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(origin)
- if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(filepath.Join(origin, "2"), []byte("welcome!"), 0700); err != nil {
- t.Fatal(err)
- }
-
- cases := []struct {
- opts *TarOptions
- numChanges int
- }{
- {&TarOptions{IncludeFiles: []string{"1"}}, 2},
- {&TarOptions{ExcludePatterns: []string{"2"}}, 1},
- {&TarOptions{ExcludePatterns: []string{"1", "folder*"}}, 2},
- {&TarOptions{IncludeFiles: []string{"1", "1"}}, 2},
- {&TarOptions{IncludeFiles: []string{"1"}, RebaseNames: map[string]string{"1": "test"}}, 4},
- }
- for _, testCase := range cases {
- changes, err := tarUntar(t, origin, testCase.opts)
- if err != nil {
- t.Fatalf("Error tar/untar when testing inclusion/exclusion: %s", err)
- }
- if len(changes) != testCase.numChanges {
- t.Errorf("Expected %d changes, got %d for %+v:",
- testCase.numChanges, len(changes), testCase.opts)
- }
- }
-}
-
-// Some tar archives such as http://haproxy.1wt.eu/download/1.5/src/devel/haproxy-1.5-dev21.tar.gz
-// use PAX Global Extended Headers.
-// Failing prevents the archives from being uncompressed during ADD
-func TestTypeXGlobalHeaderDoesNotFail(t *testing.T) {
- hdr := tar.Header{Typeflag: tar.TypeXGlobalHeader}
- tmpDir, err := ioutil.TempDir("", "docker-test-archive-pax-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tmpDir)
- err = createTarFile(filepath.Join(tmpDir, "pax_global_header"), tmpDir, &hdr, nil, true, nil)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-// Some tar have both GNU specific (huge uid) and Ustar specific (long name) things.
-// Not supposed to happen (should use PAX instead of Ustar for long name) but it does and it should still work.
-func TestUntarUstarGnuConflict(t *testing.T) {
- f, err := os.Open("testdata/broken.tar")
- if err != nil {
- t.Fatal(err)
- }
- found := false
- tr := tar.NewReader(f)
- // Iterate through the files in the archive.
- for {
- hdr, err := tr.Next()
- if err == io.EOF {
- // end of tar archive
- break
- }
- if err != nil {
- t.Fatal(err)
- }
- if hdr.Name == "root/.cpanm/work/1395823785.24209/Plack-1.0030/blib/man3/Plack::Middleware::LighttpdScriptNameFix.3pm" {
- found = true
- break
- }
- }
- if !found {
- t.Fatalf("%s not found in the archive", "root/.cpanm/work/1395823785.24209/Plack-1.0030/blib/man3/Plack::Middleware::LighttpdScriptNameFix.3pm")
- }
-}
-
-func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
- fileData := []byte("fooo")
- for n := 0; n < numberOfFiles; n++ {
- fileName := fmt.Sprintf("file-%d", n)
- if err := ioutil.WriteFile(filepath.Join(targetPath, fileName), fileData, 0700); err != nil {
- return 0, err
- }
- if makeLinks {
- if err := os.Link(filepath.Join(targetPath, fileName), filepath.Join(targetPath, fileName+"-link")); err != nil {
- return 0, err
- }
- }
- }
- totalSize := numberOfFiles * len(fileData)
- return totalSize, nil
-}
-
-func BenchmarkTarUntar(b *testing.B) {
- origin, err := ioutil.TempDir("", "docker-test-untar-origin")
- if err != nil {
- b.Fatal(err)
- }
- tempDir, err := ioutil.TempDir("", "docker-test-untar-destination")
- if err != nil {
- b.Fatal(err)
- }
- target := filepath.Join(tempDir, "dest")
- n, err := prepareUntarSourceDirectory(100, origin, false)
- if err != nil {
- b.Fatal(err)
- }
- defer os.RemoveAll(origin)
- defer os.RemoveAll(tempDir)
-
- b.ResetTimer()
- b.SetBytes(int64(n))
- for n := 0; n < b.N; n++ {
- err := TarUntar(origin, target)
- if err != nil {
- b.Fatal(err)
- }
- os.RemoveAll(target)
- }
-}
-
-func BenchmarkTarUntarWithLinks(b *testing.B) {
- origin, err := ioutil.TempDir("", "docker-test-untar-origin")
- if err != nil {
- b.Fatal(err)
- }
- tempDir, err := ioutil.TempDir("", "docker-test-untar-destination")
- if err != nil {
- b.Fatal(err)
- }
- target := filepath.Join(tempDir, "dest")
- n, err := prepareUntarSourceDirectory(100, origin, true)
- if err != nil {
- b.Fatal(err)
- }
- defer os.RemoveAll(origin)
- defer os.RemoveAll(tempDir)
-
- b.ResetTimer()
- b.SetBytes(int64(n))
- for n := 0; n < b.N; n++ {
- err := TarUntar(origin, target)
- if err != nil {
- b.Fatal(err)
- }
- os.RemoveAll(target)
- }
-}
-
-func TestUntarInvalidFilenames(t *testing.T) {
- // TODO Windows: Figure out how to fix this test.
- if runtime.GOOS == "windows" {
- t.Skip("Passes but hits breakoutError: platform and architecture is not supported")
- }
- for i, headers := range [][]*tar.Header{
- {
- {
- Name: "../victim/dotdot",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- {
- {
- // Note the leading slash
- Name: "/../victim/slash-dotdot",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- } {
- if err := testBreakout("untar", "docker-TestUntarInvalidFilenames", headers); err != nil {
- t.Fatalf("i=%d. %v", i, err)
- }
- }
-}
-
-func TestUntarHardlinkToSymlink(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- if runtime.GOOS == "windows" {
- t.Skip("hardlinks on Windows")
- }
- for i, headers := range [][]*tar.Header{
- {
- {
- Name: "symlink1",
- Typeflag: tar.TypeSymlink,
- Linkname: "regfile",
- Mode: 0644,
- },
- {
- Name: "symlink2",
- Typeflag: tar.TypeLink,
- Linkname: "symlink1",
- Mode: 0644,
- },
- {
- Name: "regfile",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- } {
- if err := testBreakout("untar", "docker-TestUntarHardlinkToSymlink", headers); err != nil {
- t.Fatalf("i=%d. %v", i, err)
- }
- }
-}
-
-func TestUntarInvalidHardlink(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- if runtime.GOOS == "windows" {
- t.Skip("hardlinks on Windows")
- }
- for i, headers := range [][]*tar.Header{
- { // try reading victim/hello (../)
- {
- Name: "dotdot",
- Typeflag: tar.TypeLink,
- Linkname: "../victim/hello",
- Mode: 0644,
- },
- },
- { // try reading victim/hello (/../)
- {
- Name: "slash-dotdot",
- Typeflag: tar.TypeLink,
- // Note the leading slash
- Linkname: "/../victim/hello",
- Mode: 0644,
- },
- },
- { // try writing victim/file
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim/file",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- { // try reading victim/hello (hardlink, symlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "symlink",
- Typeflag: tar.TypeSymlink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // Try reading victim/hello (hardlink, hardlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "hardlink",
- Typeflag: tar.TypeLink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // Try removing victim directory (hardlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- } {
- if err := testBreakout("untar", "docker-TestUntarInvalidHardlink", headers); err != nil {
- t.Fatalf("i=%d. %v", i, err)
- }
- }
-}
-
-func TestUntarInvalidSymlink(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- if runtime.GOOS == "windows" {
- t.Skip("hardlinks on Windows")
- }
- for i, headers := range [][]*tar.Header{
- { // try reading victim/hello (../)
- {
- Name: "dotdot",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim/hello",
- Mode: 0644,
- },
- },
- { // try reading victim/hello (/../)
- {
- Name: "slash-dotdot",
- Typeflag: tar.TypeSymlink,
- // Note the leading slash
- Linkname: "/../victim/hello",
- Mode: 0644,
- },
- },
- { // try writing victim/file
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim/file",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- { // try reading victim/hello (symlink, symlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "symlink",
- Typeflag: tar.TypeSymlink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // try reading victim/hello (symlink, hardlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "hardlink",
- Typeflag: tar.TypeLink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // try removing victim directory (symlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- { // try writing to victim/newdir/newfile with a symlink in the path
- {
- // this header needs to be before the next one, or else there is an error
- Name: "dir/loophole",
- Typeflag: tar.TypeSymlink,
- Linkname: "../../victim",
- Mode: 0755,
- },
- {
- Name: "dir/loophole/newdir/newfile",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- } {
- if err := testBreakout("untar", "docker-TestUntarInvalidSymlink", headers); err != nil {
- t.Fatalf("i=%d. %v", i, err)
- }
- }
-}
-
-func TestTempArchiveCloseMultipleTimes(t *testing.T) {
- reader := ioutil.NopCloser(strings.NewReader("hello"))
- tempArchive, err := NewTempArchive(reader, "")
- buf := make([]byte, 10)
- n, err := tempArchive.Read(buf)
- if n != 5 {
- t.Fatalf("Expected to read 5 bytes. Read %d instead", n)
- }
- for i := 0; i < 3; i++ {
- if err = tempArchive.Close(); err != nil {
- t.Fatalf("i=%d. Unexpected error closing temp archive: %v", i, err)
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go b/vendor/github.com/docker/docker/pkg/archive/archive_unix.go
deleted file mode 100644
index fbc3bb8..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// +build !windows
-
-package archive
-
-import (
- "archive/tar"
- "errors"
- "os"
- "path/filepath"
- "syscall"
-
- "github.com/docker/docker/pkg/system"
-)
-
-// fixVolumePathPrefix does platform specific processing to ensure that if
-// the path being passed in is not in a volume path format, convert it to one.
-func fixVolumePathPrefix(srcPath string) string {
- return srcPath
-}
-
-// getWalkRoot calculates the root path when performing a TarWithOptions.
-// We use a separate function as this is platform specific. On Linux, we
-// can't use filepath.Join(srcPath,include) because this will clean away
-// a trailing "." or "/" which may be important.
-func getWalkRoot(srcPath string, include string) string {
- return srcPath + string(filepath.Separator) + include
-}
-
-// CanonicalTarNameForPath returns platform-specific filepath
-// to canonical posix-style path for tar archival. p is relative
-// path.
-func CanonicalTarNameForPath(p string) (string, error) {
- return p, nil // already unix-style
-}
-
-// chmodTarEntry is used to adjust the file permissions used in tar header based
-// on the platform the archival is done.
-
-func chmodTarEntry(perm os.FileMode) os.FileMode {
- return perm // noop for unix as golang APIs provide perm bits correctly
-}
-
-func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (inode uint64, err error) {
- s, ok := stat.(*syscall.Stat_t)
-
- if !ok {
- err = errors.New("cannot convert stat value to syscall.Stat_t")
- return
- }
-
- inode = uint64(s.Ino)
-
- // Currently go does not fill in the major/minors
- if s.Mode&syscall.S_IFBLK != 0 ||
- s.Mode&syscall.S_IFCHR != 0 {
- hdr.Devmajor = int64(major(uint64(s.Rdev)))
- hdr.Devminor = int64(minor(uint64(s.Rdev)))
- }
-
- return
-}
-
-func getFileUIDGID(stat interface{}) (int, int, error) {
- s, ok := stat.(*syscall.Stat_t)
-
- if !ok {
- return -1, -1, errors.New("cannot convert stat value to syscall.Stat_t")
- }
- return int(s.Uid), int(s.Gid), nil
-}
-
-func major(device uint64) uint64 {
- return (device >> 8) & 0xfff
-}
-
-func minor(device uint64) uint64 {
- return (device & 0xff) | ((device >> 12) & 0xfff00)
-}
-
-// handleTarTypeBlockCharFifo is an OS-specific helper function used by
-// createTarFile to handle the following types of header: Block; Char; Fifo
-func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
- mode := uint32(hdr.Mode & 07777)
- switch hdr.Typeflag {
- case tar.TypeBlock:
- mode |= syscall.S_IFBLK
- case tar.TypeChar:
- mode |= syscall.S_IFCHR
- case tar.TypeFifo:
- mode |= syscall.S_IFIFO
- }
-
- if err := system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))); err != nil {
- return err
- }
- return nil
-}
-
-func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {
- if hdr.Typeflag == tar.TypeLink {
- if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) {
- if err := os.Chmod(path, hdrInfo.Mode()); err != nil {
- return err
- }
- }
- } else if hdr.Typeflag != tar.TypeSymlink {
- if err := os.Chmod(path, hdrInfo.Mode()); err != nil {
- return err
- }
- }
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_unix_test.go b/vendor/github.com/docker/docker/pkg/archive/archive_unix_test.go
deleted file mode 100644
index 548391b..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive_unix_test.go
+++ /dev/null
@@ -1,245 +0,0 @@
-// +build !windows
-
-package archive
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "syscall"
- "testing"
-
- "github.com/docker/docker/pkg/system"
-)
-
-func TestCanonicalTarNameForPath(t *testing.T) {
- cases := []struct{ in, expected string }{
- {"foo", "foo"},
- {"foo/bar", "foo/bar"},
- {"foo/dir/", "foo/dir/"},
- }
- for _, v := range cases {
- if out, err := CanonicalTarNameForPath(v.in); err != nil {
- t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err)
- } else if out != v.expected {
- t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out)
- }
- }
-}
-
-func TestCanonicalTarName(t *testing.T) {
- cases := []struct {
- in string
- isDir bool
- expected string
- }{
- {"foo", false, "foo"},
- {"foo", true, "foo/"},
- {"foo/bar", false, "foo/bar"},
- {"foo/bar", true, "foo/bar/"},
- }
- for _, v := range cases {
- if out, err := canonicalTarName(v.in, v.isDir); err != nil {
- t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err)
- } else if out != v.expected {
- t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out)
- }
- }
-}
-
-func TestChmodTarEntry(t *testing.T) {
- cases := []struct {
- in, expected os.FileMode
- }{
- {0000, 0000},
- {0777, 0777},
- {0644, 0644},
- {0755, 0755},
- {0444, 0444},
- }
- for _, v := range cases {
- if out := chmodTarEntry(v.in); out != v.expected {
- t.Fatalf("wrong chmod. expected:%v got:%v", v.expected, out)
- }
- }
-}
-
-func TestTarWithHardLink(t *testing.T) {
- origin, err := ioutil.TempDir("", "docker-test-tar-hardlink")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(origin)
- if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := os.Link(filepath.Join(origin, "1"), filepath.Join(origin, "2")); err != nil {
- t.Fatal(err)
- }
-
- var i1, i2 uint64
- if i1, err = getNlink(filepath.Join(origin, "1")); err != nil {
- t.Fatal(err)
- }
- // sanity check that we can hardlink
- if i1 != 2 {
- t.Skipf("skipping since hardlinks don't work here; expected 2 links, got %d", i1)
- }
-
- dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dest)
-
- // we'll do this in two steps to separate failure
- fh, err := Tar(origin, Uncompressed)
- if err != nil {
- t.Fatal(err)
- }
-
- // ensure we can read the whole thing with no error, before writing back out
- buf, err := ioutil.ReadAll(fh)
- if err != nil {
- t.Fatal(err)
- }
-
- bRdr := bytes.NewReader(buf)
- err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed})
- if err != nil {
- t.Fatal(err)
- }
-
- if i1, err = getInode(filepath.Join(dest, "1")); err != nil {
- t.Fatal(err)
- }
- if i2, err = getInode(filepath.Join(dest, "2")); err != nil {
- t.Fatal(err)
- }
-
- if i1 != i2 {
- t.Errorf("expected matching inodes, but got %d and %d", i1, i2)
- }
-}
-
-func getNlink(path string) (uint64, error) {
- stat, err := os.Stat(path)
- if err != nil {
- return 0, err
- }
- statT, ok := stat.Sys().(*syscall.Stat_t)
- if !ok {
- return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
- }
- // We need this conversion on ARM64
- return uint64(statT.Nlink), nil
-}
-
-func getInode(path string) (uint64, error) {
- stat, err := os.Stat(path)
- if err != nil {
- return 0, err
- }
- statT, ok := stat.Sys().(*syscall.Stat_t)
- if !ok {
- return 0, fmt.Errorf("expected type *syscall.Stat_t, got %t", stat.Sys())
- }
- return statT.Ino, nil
-}
-
-func TestTarWithBlockCharFifo(t *testing.T) {
- origin, err := ioutil.TempDir("", "docker-test-tar-hardlink")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(origin)
- if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := system.Mknod(filepath.Join(origin, "2"), syscall.S_IFBLK, int(system.Mkdev(int64(12), int64(5)))); err != nil {
- t.Fatal(err)
- }
- if err := system.Mknod(filepath.Join(origin, "3"), syscall.S_IFCHR, int(system.Mkdev(int64(12), int64(5)))); err != nil {
- t.Fatal(err)
- }
- if err := system.Mknod(filepath.Join(origin, "4"), syscall.S_IFIFO, int(system.Mkdev(int64(12), int64(5)))); err != nil {
- t.Fatal(err)
- }
-
- dest, err := ioutil.TempDir("", "docker-test-tar-hardlink-dest")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dest)
-
- // we'll do this in two steps to separate failure
- fh, err := Tar(origin, Uncompressed)
- if err != nil {
- t.Fatal(err)
- }
-
- // ensure we can read the whole thing with no error, before writing back out
- buf, err := ioutil.ReadAll(fh)
- if err != nil {
- t.Fatal(err)
- }
-
- bRdr := bytes.NewReader(buf)
- err = Untar(bRdr, dest, &TarOptions{Compression: Uncompressed})
- if err != nil {
- t.Fatal(err)
- }
-
- changes, err := ChangesDirs(origin, dest)
- if err != nil {
- t.Fatal(err)
- }
- if len(changes) > 0 {
- t.Fatalf("Tar with special device (block, char, fifo) should keep them (recreate them when untar) : %v", changes)
- }
-}
-
-// TestTarUntarWithXattr is Unix as Lsetxattr is not supported on Windows
-func TestTarUntarWithXattr(t *testing.T) {
- origin, err := ioutil.TempDir("", "docker-test-untar-origin")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(origin)
- if err := ioutil.WriteFile(filepath.Join(origin, "1"), []byte("hello world"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(filepath.Join(origin, "2"), []byte("welcome!"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(filepath.Join(origin, "3"), []byte("will be ignored"), 0700); err != nil {
- t.Fatal(err)
- }
- if err := system.Lsetxattr(filepath.Join(origin, "2"), "security.capability", []byte{0x00}, 0); err != nil {
- t.Fatal(err)
- }
-
- for _, c := range []Compression{
- Uncompressed,
- Gzip,
- } {
- changes, err := tarUntar(t, origin, &TarOptions{
- Compression: c,
- ExcludePatterns: []string{"3"},
- })
-
- if err != nil {
- t.Fatalf("Error tar/untar for compression %s: %s", c.Extension(), err)
- }
-
- if len(changes) != 1 || changes[0].Path != "/3" {
- t.Fatalf("Unexpected differences after tarUntar: %v", changes)
- }
- capability, _ := system.Lgetxattr(filepath.Join(origin, "2"), "security.capability")
- if capability == nil && capability[0] != 0x00 {
- t.Fatalf("Untar should have kept the 'security.capability' xattr.")
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go b/vendor/github.com/docker/docker/pkg/archive/archive_windows.go
deleted file mode 100644
index 5c3a1be..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// +build windows
-
-package archive
-
-import (
- "archive/tar"
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/docker/docker/pkg/longpath"
-)
-
-// fixVolumePathPrefix does platform specific processing to ensure that if
-// the path being passed in is not in a volume path format, convert it to one.
-func fixVolumePathPrefix(srcPath string) string {
- return longpath.AddPrefix(srcPath)
-}
-
-// getWalkRoot calculates the root path when performing a TarWithOptions.
-// We use a separate function as this is platform specific.
-func getWalkRoot(srcPath string, include string) string {
- return filepath.Join(srcPath, include)
-}
-
-// CanonicalTarNameForPath returns platform-specific filepath
-// to canonical posix-style path for tar archival. p is relative
-// path.
-func CanonicalTarNameForPath(p string) (string, error) {
- // windows: convert windows style relative path with backslashes
- // into forward slashes. Since windows does not allow '/' or '\'
- // in file names, it is mostly safe to replace however we must
- // check just in case
- if strings.Contains(p, "/") {
- return "", fmt.Errorf("Windows path contains forward slash: %s", p)
- }
- return strings.Replace(p, string(os.PathSeparator), "/", -1), nil
-
-}
-
-// chmodTarEntry is used to adjust the file permissions used in tar header based
-// on the platform the archival is done.
-func chmodTarEntry(perm os.FileMode) os.FileMode {
- perm &= 0755
- // Add the x bit: make everything +x from windows
- perm |= 0111
-
- return perm
-}
-
-func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (inode uint64, err error) {
- // do nothing. no notion of Rdev, Inode, Nlink in stat on Windows
- return
-}
-
-// handleTarTypeBlockCharFifo is an OS-specific helper function used by
-// createTarFile to handle the following types of header: Block; Char; Fifo
-func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
- return nil
-}
-
-func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {
- return nil
-}
-
-func getFileUIDGID(stat interface{}) (int, int, error) {
- // no notion of file ownership mapping yet on Windows
- return 0, 0, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_windows_test.go b/vendor/github.com/docker/docker/pkg/archive/archive_windows_test.go
deleted file mode 100644
index 0c6733d..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/archive_windows_test.go
+++ /dev/null
@@ -1,91 +0,0 @@
-// +build windows
-
-package archive
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
- "testing"
-)
-
-func TestCopyFileWithInvalidDest(t *testing.T) {
- // TODO Windows: This is currently failing. Not sure what has
- // recently changed in CopyWithTar as used to pass. Further investigation
- // is required.
- t.Skip("Currently fails")
- folder, err := ioutil.TempDir("", "docker-archive-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(folder)
- dest := "c:dest"
- srcFolder := filepath.Join(folder, "src")
- src := filepath.Join(folder, "src", "src")
- err = os.MkdirAll(srcFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- ioutil.WriteFile(src, []byte("content"), 0777)
- err = CopyWithTar(src, dest)
- if err == nil {
- t.Fatalf("archiver.CopyWithTar should throw an error on invalid dest.")
- }
-}
-
-func TestCanonicalTarNameForPath(t *testing.T) {
- cases := []struct {
- in, expected string
- shouldFail bool
- }{
- {"foo", "foo", false},
- {"foo/bar", "___", true}, // unix-styled windows path must fail
- {`foo\bar`, "foo/bar", false},
- }
- for _, v := range cases {
- if out, err := CanonicalTarNameForPath(v.in); err != nil && !v.shouldFail {
- t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err)
- } else if v.shouldFail && err == nil {
- t.Fatalf("canonical path call should have failed with error. in=%s out=%s", v.in, out)
- } else if !v.shouldFail && out != v.expected {
- t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out)
- }
- }
-}
-
-func TestCanonicalTarName(t *testing.T) {
- cases := []struct {
- in string
- isDir bool
- expected string
- }{
- {"foo", false, "foo"},
- {"foo", true, "foo/"},
- {`foo\bar`, false, "foo/bar"},
- {`foo\bar`, true, "foo/bar/"},
- }
- for _, v := range cases {
- if out, err := canonicalTarName(v.in, v.isDir); err != nil {
- t.Fatalf("cannot get canonical name for path: %s: %v", v.in, err)
- } else if out != v.expected {
- t.Fatalf("wrong canonical tar name. expected:%s got:%s", v.expected, out)
- }
- }
-}
-
-func TestChmodTarEntry(t *testing.T) {
- cases := []struct {
- in, expected os.FileMode
- }{
- {0000, 0111},
- {0777, 0755},
- {0644, 0755},
- {0755, 0755},
- {0444, 0555},
- }
- for _, v := range cases {
- if out := chmodTarEntry(v.in); out != v.expected {
- t.Fatalf("wrong chmod. expected:%v got:%v", v.expected, out)
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes.go b/vendor/github.com/docker/docker/pkg/archive/changes.go
deleted file mode 100644
index 4e2d8e5..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/changes.go
+++ /dev/null
@@ -1,446 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "sort"
- "strings"
- "syscall"
- "time"
-
- "github.com/Sirupsen/logrus"
- "github.com/docker/docker/pkg/idtools"
- "github.com/docker/docker/pkg/pools"
- "github.com/docker/docker/pkg/system"
-)
-
-// ChangeType represents the change type.
-type ChangeType int
-
-const (
- // ChangeModify represents the modify operation.
- ChangeModify = iota
- // ChangeAdd represents the add operation.
- ChangeAdd
- // ChangeDelete represents the delete operation.
- ChangeDelete
-)
-
-func (c ChangeType) String() string {
- switch c {
- case ChangeModify:
- return "C"
- case ChangeAdd:
- return "A"
- case ChangeDelete:
- return "D"
- }
- return ""
-}
-
-// Change represents a change, it wraps the change type and path.
-// It describes changes of the files in the path respect to the
-// parent layers. The change could be modify, add, delete.
-// This is used for layer diff.
-type Change struct {
- Path string
- Kind ChangeType
-}
-
-func (change *Change) String() string {
- return fmt.Sprintf("%s %s", change.Kind, change.Path)
-}
-
-// for sort.Sort
-type changesByPath []Change
-
-func (c changesByPath) Less(i, j int) bool { return c[i].Path < c[j].Path }
-func (c changesByPath) Len() int { return len(c) }
-func (c changesByPath) Swap(i, j int) { c[j], c[i] = c[i], c[j] }
-
-// Gnu tar and the go tar writer don't have sub-second mtime
-// precision, which is problematic when we apply changes via tar
-// files, we handle this by comparing for exact times, *or* same
-// second count and either a or b having exactly 0 nanoseconds
-func sameFsTime(a, b time.Time) bool {
- return a == b ||
- (a.Unix() == b.Unix() &&
- (a.Nanosecond() == 0 || b.Nanosecond() == 0))
-}
-
-func sameFsTimeSpec(a, b syscall.Timespec) bool {
- return a.Sec == b.Sec &&
- (a.Nsec == b.Nsec || a.Nsec == 0 || b.Nsec == 0)
-}
-
-// Changes walks the path rw and determines changes for the files in the path,
-// with respect to the parent layers
-func Changes(layers []string, rw string) ([]Change, error) {
- return changes(layers, rw, aufsDeletedFile, aufsMetadataSkip)
-}
-
-func aufsMetadataSkip(path string) (skip bool, err error) {
- skip, err = filepath.Match(string(os.PathSeparator)+WhiteoutMetaPrefix+"*", path)
- if err != nil {
- skip = true
- }
- return
-}
-
-func aufsDeletedFile(root, path string, fi os.FileInfo) (string, error) {
- f := filepath.Base(path)
-
- // If there is a whiteout, then the file was removed
- if strings.HasPrefix(f, WhiteoutPrefix) {
- originalFile := f[len(WhiteoutPrefix):]
- return filepath.Join(filepath.Dir(path), originalFile), nil
- }
-
- return "", nil
-}
-
-type skipChange func(string) (bool, error)
-type deleteChange func(string, string, os.FileInfo) (string, error)
-
-func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Change, error) {
- var (
- changes []Change
- changedDirs = make(map[string]struct{})
- )
-
- err := filepath.Walk(rw, func(path string, f os.FileInfo, err error) error {
- if err != nil {
- return err
- }
-
- // Rebase path
- path, err = filepath.Rel(rw, path)
- if err != nil {
- return err
- }
-
- // As this runs on the daemon side, file paths are OS specific.
- path = filepath.Join(string(os.PathSeparator), path)
-
- // Skip root
- if path == string(os.PathSeparator) {
- return nil
- }
-
- if sc != nil {
- if skip, err := sc(path); skip {
- return err
- }
- }
-
- change := Change{
- Path: path,
- }
-
- deletedFile, err := dc(rw, path, f)
- if err != nil {
- return err
- }
-
- // Find out what kind of modification happened
- if deletedFile != "" {
- change.Path = deletedFile
- change.Kind = ChangeDelete
- } else {
- // Otherwise, the file was added
- change.Kind = ChangeAdd
-
- // ...Unless it already existed in a top layer, in which case, it's a modification
- for _, layer := range layers {
- stat, err := os.Stat(filepath.Join(layer, path))
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- if err == nil {
- // The file existed in the top layer, so that's a modification
-
- // However, if it's a directory, maybe it wasn't actually modified.
- // If you modify /foo/bar/baz, then /foo will be part of the changed files only because it's the parent of bar
- if stat.IsDir() && f.IsDir() {
- if f.Size() == stat.Size() && f.Mode() == stat.Mode() && sameFsTime(f.ModTime(), stat.ModTime()) {
- // Both directories are the same, don't record the change
- return nil
- }
- }
- change.Kind = ChangeModify
- break
- }
- }
- }
-
- // If /foo/bar/file.txt is modified, then /foo/bar must be part of the changed files.
- // This block is here to ensure the change is recorded even if the
- // modify time, mode and size of the parent directory in the rw and ro layers are all equal.
- // Check https://github.com/docker/docker/pull/13590 for details.
- if f.IsDir() {
- changedDirs[path] = struct{}{}
- }
- if change.Kind == ChangeAdd || change.Kind == ChangeDelete {
- parent := filepath.Dir(path)
- if _, ok := changedDirs[parent]; !ok && parent != "/" {
- changes = append(changes, Change{Path: parent, Kind: ChangeModify})
- changedDirs[parent] = struct{}{}
- }
- }
-
- // Record change
- changes = append(changes, change)
- return nil
- })
- if err != nil && !os.IsNotExist(err) {
- return nil, err
- }
- return changes, nil
-}
-
-// FileInfo describes the information of a file.
-type FileInfo struct {
- parent *FileInfo
- name string
- stat *system.StatT
- children map[string]*FileInfo
- capability []byte
- added bool
-}
-
-// LookUp looks up the file information of a file.
-func (info *FileInfo) LookUp(path string) *FileInfo {
- // As this runs on the daemon side, file paths are OS specific.
- parent := info
- if path == string(os.PathSeparator) {
- return info
- }
-
- pathElements := strings.Split(path, string(os.PathSeparator))
- for _, elem := range pathElements {
- if elem != "" {
- child := parent.children[elem]
- if child == nil {
- return nil
- }
- parent = child
- }
- }
- return parent
-}
-
-func (info *FileInfo) path() string {
- if info.parent == nil {
- // As this runs on the daemon side, file paths are OS specific.
- return string(os.PathSeparator)
- }
- return filepath.Join(info.parent.path(), info.name)
-}
-
-func (info *FileInfo) addChanges(oldInfo *FileInfo, changes *[]Change) {
-
- sizeAtEntry := len(*changes)
-
- if oldInfo == nil {
- // add
- change := Change{
- Path: info.path(),
- Kind: ChangeAdd,
- }
- *changes = append(*changes, change)
- info.added = true
- }
-
- // We make a copy so we can modify it to detect additions
- // also, we only recurse on the old dir if the new info is a directory
- // otherwise any previous delete/change is considered recursive
- oldChildren := make(map[string]*FileInfo)
- if oldInfo != nil && info.isDir() {
- for k, v := range oldInfo.children {
- oldChildren[k] = v
- }
- }
-
- for name, newChild := range info.children {
- oldChild, _ := oldChildren[name]
- if oldChild != nil {
- // change?
- oldStat := oldChild.stat
- newStat := newChild.stat
- // Note: We can't compare inode or ctime or blocksize here, because these change
- // when copying a file into a container. However, that is not generally a problem
- // because any content change will change mtime, and any status change should
- // be visible when actually comparing the stat fields. The only time this
- // breaks down is if some code intentionally hides a change by setting
- // back mtime
- if statDifferent(oldStat, newStat) ||
- bytes.Compare(oldChild.capability, newChild.capability) != 0 {
- change := Change{
- Path: newChild.path(),
- Kind: ChangeModify,
- }
- *changes = append(*changes, change)
- newChild.added = true
- }
-
- // Remove from copy so we can detect deletions
- delete(oldChildren, name)
- }
-
- newChild.addChanges(oldChild, changes)
- }
- for _, oldChild := range oldChildren {
- // delete
- change := Change{
- Path: oldChild.path(),
- Kind: ChangeDelete,
- }
- *changes = append(*changes, change)
- }
-
- // If there were changes inside this directory, we need to add it, even if the directory
- // itself wasn't changed. This is needed to properly save and restore filesystem permissions.
- // As this runs on the daemon side, file paths are OS specific.
- if len(*changes) > sizeAtEntry && info.isDir() && !info.added && info.path() != string(os.PathSeparator) {
- change := Change{
- Path: info.path(),
- Kind: ChangeModify,
- }
- // Let's insert the directory entry before the recently added entries located inside this dir
- *changes = append(*changes, change) // just to resize the slice, will be overwritten
- copy((*changes)[sizeAtEntry+1:], (*changes)[sizeAtEntry:])
- (*changes)[sizeAtEntry] = change
- }
-
-}
-
-// Changes add changes to file information.
-func (info *FileInfo) Changes(oldInfo *FileInfo) []Change {
- var changes []Change
-
- info.addChanges(oldInfo, &changes)
-
- return changes
-}
-
-func newRootFileInfo() *FileInfo {
- // As this runs on the daemon side, file paths are OS specific.
- root := &FileInfo{
- name: string(os.PathSeparator),
- children: make(map[string]*FileInfo),
- }
- return root
-}
-
-// ChangesDirs compares two directories and generates an array of Change objects describing the changes.
-// If oldDir is "", then all files in newDir will be Add-Changes.
-func ChangesDirs(newDir, oldDir string) ([]Change, error) {
- var (
- oldRoot, newRoot *FileInfo
- )
- if oldDir == "" {
- emptyDir, err := ioutil.TempDir("", "empty")
- if err != nil {
- return nil, err
- }
- defer os.Remove(emptyDir)
- oldDir = emptyDir
- }
- oldRoot, newRoot, err := collectFileInfoForChanges(oldDir, newDir)
- if err != nil {
- return nil, err
- }
-
- return newRoot.Changes(oldRoot), nil
-}
-
-// ChangesSize calculates the size in bytes of the provided changes, based on newDir.
-func ChangesSize(newDir string, changes []Change) int64 {
- var (
- size int64
- sf = make(map[uint64]struct{})
- )
- for _, change := range changes {
- if change.Kind == ChangeModify || change.Kind == ChangeAdd {
- file := filepath.Join(newDir, change.Path)
- fileInfo, err := os.Lstat(file)
- if err != nil {
- logrus.Errorf("Can not stat %q: %s", file, err)
- continue
- }
-
- if fileInfo != nil && !fileInfo.IsDir() {
- if hasHardlinks(fileInfo) {
- inode := getIno(fileInfo)
- if _, ok := sf[inode]; !ok {
- size += fileInfo.Size()
- sf[inode] = struct{}{}
- }
- } else {
- size += fileInfo.Size()
- }
- }
- }
- }
- return size
-}
-
-// ExportChanges produces an Archive from the provided changes, relative to dir.
-func ExportChanges(dir string, changes []Change, uidMaps, gidMaps []idtools.IDMap) (Archive, error) {
- reader, writer := io.Pipe()
- go func() {
- ta := &tarAppender{
- TarWriter: tar.NewWriter(writer),
- Buffer: pools.BufioWriter32KPool.Get(nil),
- SeenFiles: make(map[uint64]string),
- UIDMaps: uidMaps,
- GIDMaps: gidMaps,
- }
- // this buffer is needed for the duration of this piped stream
- defer pools.BufioWriter32KPool.Put(ta.Buffer)
-
- sort.Sort(changesByPath(changes))
-
- // In general we log errors here but ignore them because
- // during e.g. a diff operation the container can continue
- // mutating the filesystem and we can see transient errors
- // from this
- for _, change := range changes {
- if change.Kind == ChangeDelete {
- whiteOutDir := filepath.Dir(change.Path)
- whiteOutBase := filepath.Base(change.Path)
- whiteOut := filepath.Join(whiteOutDir, WhiteoutPrefix+whiteOutBase)
- timestamp := time.Now()
- hdr := &tar.Header{
- Name: whiteOut[1:],
- Size: 0,
- ModTime: timestamp,
- AccessTime: timestamp,
- ChangeTime: timestamp,
- }
- if err := ta.TarWriter.WriteHeader(hdr); err != nil {
- logrus.Debugf("Can't write whiteout header: %s", err)
- }
- } else {
- path := filepath.Join(dir, change.Path)
- if err := ta.addTarFile(path, change.Path[1:]); err != nil {
- logrus.Debugf("Can't add file %s to tar: %s", path, err)
- }
- }
- }
-
- // Make sure to check the error on Close.
- if err := ta.TarWriter.Close(); err != nil {
- logrus.Debugf("Can't close layer: %s", err)
- }
- if err := writer.Close(); err != nil {
- logrus.Debugf("failed close Changes writer: %s", err)
- }
- }()
- return reader, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go b/vendor/github.com/docker/docker/pkg/archive/changes_linux.go
deleted file mode 100644
index a4cc0c6..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go
+++ /dev/null
@@ -1,312 +0,0 @@
-package archive
-
-import (
- "bytes"
- "fmt"
- "os"
- "path/filepath"
- "sort"
- "syscall"
- "unsafe"
-
- "github.com/docker/docker/pkg/system"
-)
-
-// walker is used to implement collectFileInfoForChanges on linux. Where this
-// method in general returns the entire contents of two directory trees, we
-// optimize some FS calls out on linux. In particular, we take advantage of the
-// fact that getdents(2) returns the inode of each file in the directory being
-// walked, which, when walking two trees in parallel to generate a list of
-// changes, can be used to prune subtrees without ever having to lstat(2) them
-// directly. Eliminating stat calls in this way can save up to seconds on large
-// images.
-type walker struct {
- dir1 string
- dir2 string
- root1 *FileInfo
- root2 *FileInfo
-}
-
-// collectFileInfoForChanges returns a complete representation of the trees
-// rooted at dir1 and dir2, with one important exception: any subtree or
-// leaf where the inode and device numbers are an exact match between dir1
-// and dir2 will be pruned from the results. This method is *only* to be used
-// to generating a list of changes between the two directories, as it does not
-// reflect the full contents.
-func collectFileInfoForChanges(dir1, dir2 string) (*FileInfo, *FileInfo, error) {
- w := &walker{
- dir1: dir1,
- dir2: dir2,
- root1: newRootFileInfo(),
- root2: newRootFileInfo(),
- }
-
- i1, err := os.Lstat(w.dir1)
- if err != nil {
- return nil, nil, err
- }
- i2, err := os.Lstat(w.dir2)
- if err != nil {
- return nil, nil, err
- }
-
- if err := w.walk("/", i1, i2); err != nil {
- return nil, nil, err
- }
-
- return w.root1, w.root2, nil
-}
-
-// Given a FileInfo, its path info, and a reference to the root of the tree
-// being constructed, register this file with the tree.
-func walkchunk(path string, fi os.FileInfo, dir string, root *FileInfo) error {
- if fi == nil {
- return nil
- }
- parent := root.LookUp(filepath.Dir(path))
- if parent == nil {
- return fmt.Errorf("collectFileInfoForChanges: Unexpectedly no parent for %s", path)
- }
- info := &FileInfo{
- name: filepath.Base(path),
- children: make(map[string]*FileInfo),
- parent: parent,
- }
- cpath := filepath.Join(dir, path)
- stat, err := system.FromStatT(fi.Sys().(*syscall.Stat_t))
- if err != nil {
- return err
- }
- info.stat = stat
- info.capability, _ = system.Lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access
- parent.children[info.name] = info
- return nil
-}
-
-// Walk a subtree rooted at the same path in both trees being iterated. For
-// example, /docker/overlay/1234/a/b/c/d and /docker/overlay/8888/a/b/c/d
-func (w *walker) walk(path string, i1, i2 os.FileInfo) (err error) {
- // Register these nodes with the return trees, unless we're still at the
- // (already-created) roots:
- if path != "/" {
- if err := walkchunk(path, i1, w.dir1, w.root1); err != nil {
- return err
- }
- if err := walkchunk(path, i2, w.dir2, w.root2); err != nil {
- return err
- }
- }
-
- is1Dir := i1 != nil && i1.IsDir()
- is2Dir := i2 != nil && i2.IsDir()
-
- sameDevice := false
- if i1 != nil && i2 != nil {
- si1 := i1.Sys().(*syscall.Stat_t)
- si2 := i2.Sys().(*syscall.Stat_t)
- if si1.Dev == si2.Dev {
- sameDevice = true
- }
- }
-
- // If these files are both non-existent, or leaves (non-dirs), we are done.
- if !is1Dir && !is2Dir {
- return nil
- }
-
- // Fetch the names of all the files contained in both directories being walked:
- var names1, names2 []nameIno
- if is1Dir {
- names1, err = readdirnames(filepath.Join(w.dir1, path)) // getdents(2): fs access
- if err != nil {
- return err
- }
- }
- if is2Dir {
- names2, err = readdirnames(filepath.Join(w.dir2, path)) // getdents(2): fs access
- if err != nil {
- return err
- }
- }
-
- // We have lists of the files contained in both parallel directories, sorted
- // in the same order. Walk them in parallel, generating a unique merged list
- // of all items present in either or both directories.
- var names []string
- ix1 := 0
- ix2 := 0
-
- for {
- if ix1 >= len(names1) {
- break
- }
- if ix2 >= len(names2) {
- break
- }
-
- ni1 := names1[ix1]
- ni2 := names2[ix2]
-
- switch bytes.Compare([]byte(ni1.name), []byte(ni2.name)) {
- case -1: // ni1 < ni2 -- advance ni1
- // we will not encounter ni1 in names2
- names = append(names, ni1.name)
- ix1++
- case 0: // ni1 == ni2
- if ni1.ino != ni2.ino || !sameDevice {
- names = append(names, ni1.name)
- }
- ix1++
- ix2++
- case 1: // ni1 > ni2 -- advance ni2
- // we will not encounter ni2 in names1
- names = append(names, ni2.name)
- ix2++
- }
- }
- for ix1 < len(names1) {
- names = append(names, names1[ix1].name)
- ix1++
- }
- for ix2 < len(names2) {
- names = append(names, names2[ix2].name)
- ix2++
- }
-
- // For each of the names present in either or both of the directories being
- // iterated, stat the name under each root, and recurse the pair of them:
- for _, name := range names {
- fname := filepath.Join(path, name)
- var cInfo1, cInfo2 os.FileInfo
- if is1Dir {
- cInfo1, err = os.Lstat(filepath.Join(w.dir1, fname)) // lstat(2): fs access
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- }
- if is2Dir {
- cInfo2, err = os.Lstat(filepath.Join(w.dir2, fname)) // lstat(2): fs access
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- }
- if err = w.walk(fname, cInfo1, cInfo2); err != nil {
- return err
- }
- }
- return nil
-}
-
-// {name,inode} pairs used to support the early-pruning logic of the walker type
-type nameIno struct {
- name string
- ino uint64
-}
-
-type nameInoSlice []nameIno
-
-func (s nameInoSlice) Len() int { return len(s) }
-func (s nameInoSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s nameInoSlice) Less(i, j int) bool { return s[i].name < s[j].name }
-
-// readdirnames is a hacked-apart version of the Go stdlib code, exposing inode
-// numbers further up the stack when reading directory contents. Unlike
-// os.Readdirnames, which returns a list of filenames, this function returns a
-// list of {filename,inode} pairs.
-func readdirnames(dirname string) (names []nameIno, err error) {
- var (
- size = 100
- buf = make([]byte, 4096)
- nbuf int
- bufp int
- nb int
- )
-
- f, err := os.Open(dirname)
- if err != nil {
- return nil, err
- }
- defer f.Close()
-
- names = make([]nameIno, 0, size) // Empty with room to grow.
- for {
- // Refill the buffer if necessary
- if bufp >= nbuf {
- bufp = 0
- nbuf, err = syscall.ReadDirent(int(f.Fd()), buf) // getdents on linux
- if nbuf < 0 {
- nbuf = 0
- }
- if err != nil {
- return nil, os.NewSyscallError("readdirent", err)
- }
- if nbuf <= 0 {
- break // EOF
- }
- }
-
- // Drain the buffer
- nb, names = parseDirent(buf[bufp:nbuf], names)
- bufp += nb
- }
-
- sl := nameInoSlice(names)
- sort.Sort(sl)
- return sl, nil
-}
-
-// parseDirent is a minor modification of syscall.ParseDirent (linux version)
-// which returns {name,inode} pairs instead of just names.
-func parseDirent(buf []byte, names []nameIno) (consumed int, newnames []nameIno) {
- origlen := len(buf)
- for len(buf) > 0 {
- dirent := (*syscall.Dirent)(unsafe.Pointer(&buf[0]))
- buf = buf[dirent.Reclen:]
- if dirent.Ino == 0 { // File absent in directory.
- continue
- }
- bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
- var name = string(bytes[0:clen(bytes[:])])
- if name == "." || name == ".." { // Useless names
- continue
- }
- names = append(names, nameIno{name, dirent.Ino})
- }
- return origlen - len(buf), names
-}
-
-func clen(n []byte) int {
- for i := 0; i < len(n); i++ {
- if n[i] == 0 {
- return i
- }
- }
- return len(n)
-}
-
-// OverlayChanges walks the path rw and determines changes for the files in the path,
-// with respect to the parent layers
-func OverlayChanges(layers []string, rw string) ([]Change, error) {
- return changes(layers, rw, overlayDeletedFile, nil)
-}
-
-func overlayDeletedFile(root, path string, fi os.FileInfo) (string, error) {
- if fi.Mode()&os.ModeCharDevice != 0 {
- s := fi.Sys().(*syscall.Stat_t)
- if major(uint64(s.Rdev)) == 0 && minor(uint64(s.Rdev)) == 0 {
- return path, nil
- }
- }
- if fi.Mode()&os.ModeDir != 0 {
- opaque, err := system.Lgetxattr(filepath.Join(root, path), "trusted.overlay.opaque")
- if err != nil {
- return "", err
- }
- if opaque != nil && len(opaque) == 1 && opaque[0] == 'y' {
- return path, nil
- }
- }
-
- return "", nil
-
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_other.go b/vendor/github.com/docker/docker/pkg/archive/changes_other.go
deleted file mode 100644
index da70ed3..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/changes_other.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// +build !linux
-
-package archive
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "runtime"
- "strings"
-
- "github.com/docker/docker/pkg/system"
-)
-
-func collectFileInfoForChanges(oldDir, newDir string) (*FileInfo, *FileInfo, error) {
- var (
- oldRoot, newRoot *FileInfo
- err1, err2 error
- errs = make(chan error, 2)
- )
- go func() {
- oldRoot, err1 = collectFileInfo(oldDir)
- errs <- err1
- }()
- go func() {
- newRoot, err2 = collectFileInfo(newDir)
- errs <- err2
- }()
-
- // block until both routines have returned
- for i := 0; i < 2; i++ {
- if err := <-errs; err != nil {
- return nil, nil, err
- }
- }
-
- return oldRoot, newRoot, nil
-}
-
-func collectFileInfo(sourceDir string) (*FileInfo, error) {
- root := newRootFileInfo()
-
- err := filepath.Walk(sourceDir, func(path string, f os.FileInfo, err error) error {
- if err != nil {
- return err
- }
-
- // Rebase path
- relPath, err := filepath.Rel(sourceDir, path)
- if err != nil {
- return err
- }
-
- // As this runs on the daemon side, file paths are OS specific.
- relPath = filepath.Join(string(os.PathSeparator), relPath)
-
- // See https://github.com/golang/go/issues/9168 - bug in filepath.Join.
- // Temporary workaround. If the returned path starts with two backslashes,
- // trim it down to a single backslash. Only relevant on Windows.
- if runtime.GOOS == "windows" {
- if strings.HasPrefix(relPath, `\\`) {
- relPath = relPath[1:]
- }
- }
-
- if relPath == string(os.PathSeparator) {
- return nil
- }
-
- parent := root.LookUp(filepath.Dir(relPath))
- if parent == nil {
- return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath)
- }
-
- info := &FileInfo{
- name: filepath.Base(relPath),
- children: make(map[string]*FileInfo),
- parent: parent,
- }
-
- s, err := system.Lstat(path)
- if err != nil {
- return err
- }
- info.stat = s
-
- info.capability, _ = system.Lgetxattr(path, "security.capability")
-
- parent.children[info.name] = info
-
- return nil
- })
- if err != nil {
- return nil, err
- }
- return root, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_posix_test.go b/vendor/github.com/docker/docker/pkg/archive/changes_posix_test.go
deleted file mode 100644
index 5a3282b..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/changes_posix_test.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path"
- "sort"
- "testing"
-)
-
-func TestHardLinkOrder(t *testing.T) {
- names := []string{"file1.txt", "file2.txt", "file3.txt"}
- msg := []byte("Hey y'all")
-
- // Create dir
- src, err := ioutil.TempDir("", "docker-hardlink-test-src-")
- if err != nil {
- t.Fatal(err)
- }
- //defer os.RemoveAll(src)
- for _, name := range names {
- func() {
- fh, err := os.Create(path.Join(src, name))
- if err != nil {
- t.Fatal(err)
- }
- defer fh.Close()
- if _, err = fh.Write(msg); err != nil {
- t.Fatal(err)
- }
- }()
- }
- // Create dest, with changes that includes hardlinks
- dest, err := ioutil.TempDir("", "docker-hardlink-test-dest-")
- if err != nil {
- t.Fatal(err)
- }
- os.RemoveAll(dest) // we just want the name, at first
- if err := copyDir(src, dest); err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dest)
- for _, name := range names {
- for i := 0; i < 5; i++ {
- if err := os.Link(path.Join(dest, name), path.Join(dest, fmt.Sprintf("%s.link%d", name, i))); err != nil {
- t.Fatal(err)
- }
- }
- }
-
- // get changes
- changes, err := ChangesDirs(dest, src)
- if err != nil {
- t.Fatal(err)
- }
-
- // sort
- sort.Sort(changesByPath(changes))
-
- // ExportChanges
- ar, err := ExportChanges(dest, changes, nil, nil)
- if err != nil {
- t.Fatal(err)
- }
- hdrs, err := walkHeaders(ar)
- if err != nil {
- t.Fatal(err)
- }
-
- // reverse sort
- sort.Sort(sort.Reverse(changesByPath(changes)))
- // ExportChanges
- arRev, err := ExportChanges(dest, changes, nil, nil)
- if err != nil {
- t.Fatal(err)
- }
- hdrsRev, err := walkHeaders(arRev)
- if err != nil {
- t.Fatal(err)
- }
-
- // line up the two sets
- sort.Sort(tarHeaders(hdrs))
- sort.Sort(tarHeaders(hdrsRev))
-
- // compare Size and LinkName
- for i := range hdrs {
- if hdrs[i].Name != hdrsRev[i].Name {
- t.Errorf("headers - expected name %q; but got %q", hdrs[i].Name, hdrsRev[i].Name)
- }
- if hdrs[i].Size != hdrsRev[i].Size {
- t.Errorf("headers - %q expected size %d; but got %d", hdrs[i].Name, hdrs[i].Size, hdrsRev[i].Size)
- }
- if hdrs[i].Typeflag != hdrsRev[i].Typeflag {
- t.Errorf("headers - %q expected type %d; but got %d", hdrs[i].Name, hdrs[i].Typeflag, hdrsRev[i].Typeflag)
- }
- if hdrs[i].Linkname != hdrsRev[i].Linkname {
- t.Errorf("headers - %q expected linkname %q; but got %q", hdrs[i].Name, hdrs[i].Linkname, hdrsRev[i].Linkname)
- }
- }
-
-}
-
-type tarHeaders []tar.Header
-
-func (th tarHeaders) Len() int { return len(th) }
-func (th tarHeaders) Swap(i, j int) { th[j], th[i] = th[i], th[j] }
-func (th tarHeaders) Less(i, j int) bool { return th[i].Name < th[j].Name }
-
-func walkHeaders(r io.Reader) ([]tar.Header, error) {
- t := tar.NewReader(r)
- headers := []tar.Header{}
- for {
- hdr, err := t.Next()
- if err != nil {
- if err == io.EOF {
- break
- }
- return headers, err
- }
- headers = append(headers, *hdr)
- }
- return headers, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_test.go b/vendor/github.com/docker/docker/pkg/archive/changes_test.go
deleted file mode 100644
index 8a2d0e8..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/changes_test.go
+++ /dev/null
@@ -1,565 +0,0 @@
-package archive
-
-import (
- "io/ioutil"
- "os"
- "os/exec"
- "path"
- "runtime"
- "sort"
- "testing"
- "time"
-
- "github.com/docker/docker/pkg/system"
-)
-
-func max(x, y int) int {
- if x >= y {
- return x
- }
- return y
-}
-
-func copyDir(src, dst string) error {
- cmd := exec.Command("cp", "-a", src, dst)
- if err := cmd.Run(); err != nil {
- return err
- }
- return nil
-}
-
-type FileType uint32
-
-const (
- Regular FileType = iota
- Dir
- Symlink
-)
-
-type FileData struct {
- filetype FileType
- path string
- contents string
- permissions os.FileMode
-}
-
-func createSampleDir(t *testing.T, root string) {
- files := []FileData{
- {Regular, "file1", "file1\n", 0600},
- {Regular, "file2", "file2\n", 0666},
- {Regular, "file3", "file3\n", 0404},
- {Regular, "file4", "file4\n", 0600},
- {Regular, "file5", "file5\n", 0600},
- {Regular, "file6", "file6\n", 0600},
- {Regular, "file7", "file7\n", 0600},
- {Dir, "dir1", "", 0740},
- {Regular, "dir1/file1-1", "file1-1\n", 01444},
- {Regular, "dir1/file1-2", "file1-2\n", 0666},
- {Dir, "dir2", "", 0700},
- {Regular, "dir2/file2-1", "file2-1\n", 0666},
- {Regular, "dir2/file2-2", "file2-2\n", 0666},
- {Dir, "dir3", "", 0700},
- {Regular, "dir3/file3-1", "file3-1\n", 0666},
- {Regular, "dir3/file3-2", "file3-2\n", 0666},
- {Dir, "dir4", "", 0700},
- {Regular, "dir4/file3-1", "file4-1\n", 0666},
- {Regular, "dir4/file3-2", "file4-2\n", 0666},
- {Symlink, "symlink1", "target1", 0666},
- {Symlink, "symlink2", "target2", 0666},
- {Symlink, "symlink3", root + "/file1", 0666},
- {Symlink, "symlink4", root + "/symlink3", 0666},
- {Symlink, "dirSymlink", root + "/dir1", 0740},
- }
-
- now := time.Now()
- for _, info := range files {
- p := path.Join(root, info.path)
- if info.filetype == Dir {
- if err := os.MkdirAll(p, info.permissions); err != nil {
- t.Fatal(err)
- }
- } else if info.filetype == Regular {
- if err := ioutil.WriteFile(p, []byte(info.contents), info.permissions); err != nil {
- t.Fatal(err)
- }
- } else if info.filetype == Symlink {
- if err := os.Symlink(info.contents, p); err != nil {
- t.Fatal(err)
- }
- }
-
- if info.filetype != Symlink {
- // Set a consistent ctime, atime for all files and dirs
- if err := system.Chtimes(p, now, now); err != nil {
- t.Fatal(err)
- }
- }
- }
-}
-
-func TestChangeString(t *testing.T) {
- modifiyChange := Change{"change", ChangeModify}
- toString := modifiyChange.String()
- if toString != "C change" {
- t.Fatalf("String() of a change with ChangeModifiy Kind should have been %s but was %s", "C change", toString)
- }
- addChange := Change{"change", ChangeAdd}
- toString = addChange.String()
- if toString != "A change" {
- t.Fatalf("String() of a change with ChangeAdd Kind should have been %s but was %s", "A change", toString)
- }
- deleteChange := Change{"change", ChangeDelete}
- toString = deleteChange.String()
- if toString != "D change" {
- t.Fatalf("String() of a change with ChangeDelete Kind should have been %s but was %s", "D change", toString)
- }
-}
-
-func TestChangesWithNoChanges(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- // as createSampleDir uses symlinks.
- if runtime.GOOS == "windows" {
- t.Skip("symlinks on Windows")
- }
- rwLayer, err := ioutil.TempDir("", "docker-changes-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(rwLayer)
- layer, err := ioutil.TempDir("", "docker-changes-test-layer")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(layer)
- createSampleDir(t, layer)
- changes, err := Changes([]string{layer}, rwLayer)
- if err != nil {
- t.Fatal(err)
- }
- if len(changes) != 0 {
- t.Fatalf("Changes with no difference should have detect no changes, but detected %d", len(changes))
- }
-}
-
-func TestChangesWithChanges(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- // as createSampleDir uses symlinks.
- if runtime.GOOS == "windows" {
- t.Skip("symlinks on Windows")
- }
- // Mock the readonly layer
- layer, err := ioutil.TempDir("", "docker-changes-test-layer")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(layer)
- createSampleDir(t, layer)
- os.MkdirAll(path.Join(layer, "dir1/subfolder"), 0740)
-
- // Mock the RW layer
- rwLayer, err := ioutil.TempDir("", "docker-changes-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(rwLayer)
-
- // Create a folder in RW layer
- dir1 := path.Join(rwLayer, "dir1")
- os.MkdirAll(dir1, 0740)
- deletedFile := path.Join(dir1, ".wh.file1-2")
- ioutil.WriteFile(deletedFile, []byte{}, 0600)
- modifiedFile := path.Join(dir1, "file1-1")
- ioutil.WriteFile(modifiedFile, []byte{0x00}, 01444)
- // Let's add a subfolder for a newFile
- subfolder := path.Join(dir1, "subfolder")
- os.MkdirAll(subfolder, 0740)
- newFile := path.Join(subfolder, "newFile")
- ioutil.WriteFile(newFile, []byte{}, 0740)
-
- changes, err := Changes([]string{layer}, rwLayer)
- if err != nil {
- t.Fatal(err)
- }
-
- expectedChanges := []Change{
- {"/dir1", ChangeModify},
- {"/dir1/file1-1", ChangeModify},
- {"/dir1/file1-2", ChangeDelete},
- {"/dir1/subfolder", ChangeModify},
- {"/dir1/subfolder/newFile", ChangeAdd},
- }
- checkChanges(expectedChanges, changes, t)
-}
-
-// See https://github.com/docker/docker/pull/13590
-func TestChangesWithChangesGH13590(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- // as createSampleDir uses symlinks.
- if runtime.GOOS == "windows" {
- t.Skip("symlinks on Windows")
- }
- baseLayer, err := ioutil.TempDir("", "docker-changes-test.")
- defer os.RemoveAll(baseLayer)
-
- dir3 := path.Join(baseLayer, "dir1/dir2/dir3")
- os.MkdirAll(dir3, 07400)
-
- file := path.Join(dir3, "file.txt")
- ioutil.WriteFile(file, []byte("hello"), 0666)
-
- layer, err := ioutil.TempDir("", "docker-changes-test2.")
- defer os.RemoveAll(layer)
-
- // Test creating a new file
- if err := copyDir(baseLayer+"/dir1", layer+"/"); err != nil {
- t.Fatalf("Cmd failed: %q", err)
- }
-
- os.Remove(path.Join(layer, "dir1/dir2/dir3/file.txt"))
- file = path.Join(layer, "dir1/dir2/dir3/file1.txt")
- ioutil.WriteFile(file, []byte("bye"), 0666)
-
- changes, err := Changes([]string{baseLayer}, layer)
- if err != nil {
- t.Fatal(err)
- }
-
- expectedChanges := []Change{
- {"/dir1/dir2/dir3", ChangeModify},
- {"/dir1/dir2/dir3/file1.txt", ChangeAdd},
- }
- checkChanges(expectedChanges, changes, t)
-
- // Now test changing a file
- layer, err = ioutil.TempDir("", "docker-changes-test3.")
- defer os.RemoveAll(layer)
-
- if err := copyDir(baseLayer+"/dir1", layer+"/"); err != nil {
- t.Fatalf("Cmd failed: %q", err)
- }
-
- file = path.Join(layer, "dir1/dir2/dir3/file.txt")
- ioutil.WriteFile(file, []byte("bye"), 0666)
-
- changes, err = Changes([]string{baseLayer}, layer)
- if err != nil {
- t.Fatal(err)
- }
-
- expectedChanges = []Change{
- {"/dir1/dir2/dir3/file.txt", ChangeModify},
- }
- checkChanges(expectedChanges, changes, t)
-}
-
-// Create a directory, copy it, make sure we report no changes between the two
-func TestChangesDirsEmpty(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- // as createSampleDir uses symlinks.
- if runtime.GOOS == "windows" {
- t.Skip("symlinks on Windows")
- }
- src, err := ioutil.TempDir("", "docker-changes-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(src)
- createSampleDir(t, src)
- dst := src + "-copy"
- if err := copyDir(src, dst); err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(dst)
- changes, err := ChangesDirs(dst, src)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(changes) != 0 {
- t.Fatalf("Reported changes for identical dirs: %v", changes)
- }
- os.RemoveAll(src)
- os.RemoveAll(dst)
-}
-
-func mutateSampleDir(t *testing.T, root string) {
- // Remove a regular file
- if err := os.RemoveAll(path.Join(root, "file1")); err != nil {
- t.Fatal(err)
- }
-
- // Remove a directory
- if err := os.RemoveAll(path.Join(root, "dir1")); err != nil {
- t.Fatal(err)
- }
-
- // Remove a symlink
- if err := os.RemoveAll(path.Join(root, "symlink1")); err != nil {
- t.Fatal(err)
- }
-
- // Rewrite a file
- if err := ioutil.WriteFile(path.Join(root, "file2"), []byte("fileNN\n"), 0777); err != nil {
- t.Fatal(err)
- }
-
- // Replace a file
- if err := os.RemoveAll(path.Join(root, "file3")); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(path.Join(root, "file3"), []byte("fileMM\n"), 0404); err != nil {
- t.Fatal(err)
- }
-
- // Touch file
- if err := system.Chtimes(path.Join(root, "file4"), time.Now().Add(time.Second), time.Now().Add(time.Second)); err != nil {
- t.Fatal(err)
- }
-
- // Replace file with dir
- if err := os.RemoveAll(path.Join(root, "file5")); err != nil {
- t.Fatal(err)
- }
- if err := os.MkdirAll(path.Join(root, "file5"), 0666); err != nil {
- t.Fatal(err)
- }
-
- // Create new file
- if err := ioutil.WriteFile(path.Join(root, "filenew"), []byte("filenew\n"), 0777); err != nil {
- t.Fatal(err)
- }
-
- // Create new dir
- if err := os.MkdirAll(path.Join(root, "dirnew"), 0766); err != nil {
- t.Fatal(err)
- }
-
- // Create a new symlink
- if err := os.Symlink("targetnew", path.Join(root, "symlinknew")); err != nil {
- t.Fatal(err)
- }
-
- // Change a symlink
- if err := os.RemoveAll(path.Join(root, "symlink2")); err != nil {
- t.Fatal(err)
- }
- if err := os.Symlink("target2change", path.Join(root, "symlink2")); err != nil {
- t.Fatal(err)
- }
-
- // Replace dir with file
- if err := os.RemoveAll(path.Join(root, "dir2")); err != nil {
- t.Fatal(err)
- }
- if err := ioutil.WriteFile(path.Join(root, "dir2"), []byte("dir2\n"), 0777); err != nil {
- t.Fatal(err)
- }
-
- // Touch dir
- if err := system.Chtimes(path.Join(root, "dir3"), time.Now().Add(time.Second), time.Now().Add(time.Second)); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestChangesDirsMutated(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- // as createSampleDir uses symlinks.
- if runtime.GOOS == "windows" {
- t.Skip("symlinks on Windows")
- }
- src, err := ioutil.TempDir("", "docker-changes-test")
- if err != nil {
- t.Fatal(err)
- }
- createSampleDir(t, src)
- dst := src + "-copy"
- if err := copyDir(src, dst); err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(src)
- defer os.RemoveAll(dst)
-
- mutateSampleDir(t, dst)
-
- changes, err := ChangesDirs(dst, src)
- if err != nil {
- t.Fatal(err)
- }
-
- sort.Sort(changesByPath(changes))
-
- expectedChanges := []Change{
- {"/dir1", ChangeDelete},
- {"/dir2", ChangeModify},
- {"/dirnew", ChangeAdd},
- {"/file1", ChangeDelete},
- {"/file2", ChangeModify},
- {"/file3", ChangeModify},
- {"/file4", ChangeModify},
- {"/file5", ChangeModify},
- {"/filenew", ChangeAdd},
- {"/symlink1", ChangeDelete},
- {"/symlink2", ChangeModify},
- {"/symlinknew", ChangeAdd},
- }
-
- for i := 0; i < max(len(changes), len(expectedChanges)); i++ {
- if i >= len(expectedChanges) {
- t.Fatalf("unexpected change %s\n", changes[i].String())
- }
- if i >= len(changes) {
- t.Fatalf("no change for expected change %s\n", expectedChanges[i].String())
- }
- if changes[i].Path == expectedChanges[i].Path {
- if changes[i] != expectedChanges[i] {
- t.Fatalf("Wrong change for %s, expected %s, got %s\n", changes[i].Path, changes[i].String(), expectedChanges[i].String())
- }
- } else if changes[i].Path < expectedChanges[i].Path {
- t.Fatalf("unexpected change %s\n", changes[i].String())
- } else {
- t.Fatalf("no change for expected change %s != %s\n", expectedChanges[i].String(), changes[i].String())
- }
- }
-}
-
-func TestApplyLayer(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- // as createSampleDir uses symlinks.
- if runtime.GOOS == "windows" {
- t.Skip("symlinks on Windows")
- }
- src, err := ioutil.TempDir("", "docker-changes-test")
- if err != nil {
- t.Fatal(err)
- }
- createSampleDir(t, src)
- defer os.RemoveAll(src)
- dst := src + "-copy"
- if err := copyDir(src, dst); err != nil {
- t.Fatal(err)
- }
- mutateSampleDir(t, dst)
- defer os.RemoveAll(dst)
-
- changes, err := ChangesDirs(dst, src)
- if err != nil {
- t.Fatal(err)
- }
-
- layer, err := ExportChanges(dst, changes, nil, nil)
- if err != nil {
- t.Fatal(err)
- }
-
- layerCopy, err := NewTempArchive(layer, "")
- if err != nil {
- t.Fatal(err)
- }
-
- if _, err := ApplyLayer(src, layerCopy); err != nil {
- t.Fatal(err)
- }
-
- changes2, err := ChangesDirs(src, dst)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(changes2) != 0 {
- t.Fatalf("Unexpected differences after reapplying mutation: %v", changes2)
- }
-}
-
-func TestChangesSizeWithHardlinks(t *testing.T) {
- // TODO Windows. There may be a way of running this, but turning off for now
- // as createSampleDir uses symlinks.
- if runtime.GOOS == "windows" {
- t.Skip("hardlinks on Windows")
- }
- srcDir, err := ioutil.TempDir("", "docker-test-srcDir")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(srcDir)
-
- destDir, err := ioutil.TempDir("", "docker-test-destDir")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(destDir)
-
- creationSize, err := prepareUntarSourceDirectory(100, destDir, true)
- if err != nil {
- t.Fatal(err)
- }
-
- changes, err := ChangesDirs(destDir, srcDir)
- if err != nil {
- t.Fatal(err)
- }
-
- got := ChangesSize(destDir, changes)
- if got != int64(creationSize) {
- t.Errorf("Expected %d bytes of changes, got %d", creationSize, got)
- }
-}
-
-func TestChangesSizeWithNoChanges(t *testing.T) {
- size := ChangesSize("/tmp", nil)
- if size != 0 {
- t.Fatalf("ChangesSizes with no changes should be 0, was %d", size)
- }
-}
-
-func TestChangesSizeWithOnlyDeleteChanges(t *testing.T) {
- changes := []Change{
- {Path: "deletedPath", Kind: ChangeDelete},
- }
- size := ChangesSize("/tmp", changes)
- if size != 0 {
- t.Fatalf("ChangesSizes with only delete changes should be 0, was %d", size)
- }
-}
-
-func TestChangesSize(t *testing.T) {
- parentPath, err := ioutil.TempDir("", "docker-changes-test")
- defer os.RemoveAll(parentPath)
- addition := path.Join(parentPath, "addition")
- if err := ioutil.WriteFile(addition, []byte{0x01, 0x01, 0x01}, 0744); err != nil {
- t.Fatal(err)
- }
- modification := path.Join(parentPath, "modification")
- if err = ioutil.WriteFile(modification, []byte{0x01, 0x01, 0x01}, 0744); err != nil {
- t.Fatal(err)
- }
- changes := []Change{
- {Path: "addition", Kind: ChangeAdd},
- {Path: "modification", Kind: ChangeModify},
- }
- size := ChangesSize(parentPath, changes)
- if size != 6 {
- t.Fatalf("Expected 6 bytes of changes, got %d", size)
- }
-}
-
-func checkChanges(expectedChanges, changes []Change, t *testing.T) {
- sort.Sort(changesByPath(expectedChanges))
- sort.Sort(changesByPath(changes))
- for i := 0; i < max(len(changes), len(expectedChanges)); i++ {
- if i >= len(expectedChanges) {
- t.Fatalf("unexpected change %s\n", changes[i].String())
- }
- if i >= len(changes) {
- t.Fatalf("no change for expected change %s\n", expectedChanges[i].String())
- }
- if changes[i].Path == expectedChanges[i].Path {
- if changes[i] != expectedChanges[i] {
- t.Fatalf("Wrong change for %s, expected %s, got %s\n", changes[i].Path, changes[i].String(), expectedChanges[i].String())
- }
- } else if changes[i].Path < expectedChanges[i].Path {
- t.Fatalf("unexpected change %s\n", changes[i].String())
- } else {
- t.Fatalf("no change for expected change %s != %s\n", expectedChanges[i].String(), changes[i].String())
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go b/vendor/github.com/docker/docker/pkg/archive/changes_unix.go
deleted file mode 100644
index 3778b73..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// +build !windows
-
-package archive
-
-import (
- "os"
- "syscall"
-
- "github.com/docker/docker/pkg/system"
-)
-
-func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool {
- // Don't look at size for dirs, its not a good measure of change
- if oldStat.Mode() != newStat.Mode() ||
- oldStat.UID() != newStat.UID() ||
- oldStat.GID() != newStat.GID() ||
- oldStat.Rdev() != newStat.Rdev() ||
- // Don't look at size for dirs, its not a good measure of change
- (oldStat.Mode()&syscall.S_IFDIR != syscall.S_IFDIR &&
- (!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) || (oldStat.Size() != newStat.Size()))) {
- return true
- }
- return false
-}
-
-func (info *FileInfo) isDir() bool {
- return info.parent == nil || info.stat.Mode()&syscall.S_IFDIR != 0
-}
-
-func getIno(fi os.FileInfo) uint64 {
- return uint64(fi.Sys().(*syscall.Stat_t).Ino)
-}
-
-func hasHardlinks(fi os.FileInfo) bool {
- return fi.Sys().(*syscall.Stat_t).Nlink > 1
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go b/vendor/github.com/docker/docker/pkg/archive/changes_windows.go
deleted file mode 100644
index af94243..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package archive
-
-import (
- "os"
-
- "github.com/docker/docker/pkg/system"
-)
-
-func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool {
-
- // Don't look at size for dirs, its not a good measure of change
- if oldStat.ModTime() != newStat.ModTime() ||
- oldStat.Mode() != newStat.Mode() ||
- oldStat.Size() != newStat.Size() && !oldStat.IsDir() {
- return true
- }
- return false
-}
-
-func (info *FileInfo) isDir() bool {
- return info.parent == nil || info.stat.IsDir()
-}
-
-func getIno(fi os.FileInfo) (inode uint64) {
- return
-}
-
-func hasHardlinks(fi os.FileInfo) bool {
- return false
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy.go b/vendor/github.com/docker/docker/pkg/archive/copy.go
deleted file mode 100644
index e1fa73f..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/copy.go
+++ /dev/null
@@ -1,458 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "errors"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/Sirupsen/logrus"
- "github.com/docker/docker/pkg/system"
-)
-
-// Errors used or returned by this file.
-var (
- ErrNotDirectory = errors.New("not a directory")
- ErrDirNotExists = errors.New("no such directory")
- ErrCannotCopyDir = errors.New("cannot copy directory")
- ErrInvalidCopySource = errors.New("invalid copy source content")
-)
-
-// PreserveTrailingDotOrSeparator returns the given cleaned path (after
-// processing using any utility functions from the path or filepath stdlib
-// packages) and appends a trailing `/.` or `/` if its corresponding original
-// path (from before being processed by utility functions from the path or
-// filepath stdlib packages) ends with a trailing `/.` or `/`. If the cleaned
-// path already ends in a `.` path segment, then another is not added. If the
-// clean path already ends in a path separator, then another is not added.
-func PreserveTrailingDotOrSeparator(cleanedPath, originalPath string) string {
- // Ensure paths are in platform semantics
- cleanedPath = normalizePath(cleanedPath)
- originalPath = normalizePath(originalPath)
-
- if !specifiesCurrentDir(cleanedPath) && specifiesCurrentDir(originalPath) {
- if !hasTrailingPathSeparator(cleanedPath) {
- // Add a separator if it doesn't already end with one (a cleaned
- // path would only end in a separator if it is the root).
- cleanedPath += string(filepath.Separator)
- }
- cleanedPath += "."
- }
-
- if !hasTrailingPathSeparator(cleanedPath) && hasTrailingPathSeparator(originalPath) {
- cleanedPath += string(filepath.Separator)
- }
-
- return cleanedPath
-}
-
-// assertsDirectory returns whether the given path is
-// asserted to be a directory, i.e., the path ends with
-// a trailing '/' or `/.`, assuming a path separator of `/`.
-func assertsDirectory(path string) bool {
- return hasTrailingPathSeparator(path) || specifiesCurrentDir(path)
-}
-
-// hasTrailingPathSeparator returns whether the given
-// path ends with the system's path separator character.
-func hasTrailingPathSeparator(path string) bool {
- return len(path) > 0 && os.IsPathSeparator(path[len(path)-1])
-}
-
-// specifiesCurrentDir returns whether the given path specifies
-// a "current directory", i.e., the last path segment is `.`.
-func specifiesCurrentDir(path string) bool {
- return filepath.Base(path) == "."
-}
-
-// SplitPathDirEntry splits the given path between its directory name and its
-// basename by first cleaning the path but preserves a trailing "." if the
-// original path specified the current directory.
-func SplitPathDirEntry(path string) (dir, base string) {
- cleanedPath := filepath.Clean(normalizePath(path))
-
- if specifiesCurrentDir(path) {
- cleanedPath += string(filepath.Separator) + "."
- }
-
- return filepath.Dir(cleanedPath), filepath.Base(cleanedPath)
-}
-
-// TarResource archives the resource described by the given CopyInfo to a Tar
-// archive. A non-nil error is returned if sourcePath does not exist or is
-// asserted to be a directory but exists as another type of file.
-//
-// This function acts as a convenient wrapper around TarWithOptions, which
-// requires a directory as the source path. TarResource accepts either a
-// directory or a file path and correctly sets the Tar options.
-func TarResource(sourceInfo CopyInfo) (content Archive, err error) {
- return TarResourceRebase(sourceInfo.Path, sourceInfo.RebaseName)
-}
-
-// TarResourceRebase is like TarResource but renames the first path element of
-// items in the resulting tar archive to match the given rebaseName if not "".
-func TarResourceRebase(sourcePath, rebaseName string) (content Archive, err error) {
- sourcePath = normalizePath(sourcePath)
- if _, err = os.Lstat(sourcePath); err != nil {
- // Catches the case where the source does not exist or is not a
- // directory if asserted to be a directory, as this also causes an
- // error.
- return
- }
-
- // Separate the source path between it's directory and
- // the entry in that directory which we are archiving.
- sourceDir, sourceBase := SplitPathDirEntry(sourcePath)
-
- filter := []string{sourceBase}
-
- logrus.Debugf("copying %q from %q", sourceBase, sourceDir)
-
- return TarWithOptions(sourceDir, &TarOptions{
- Compression: Uncompressed,
- IncludeFiles: filter,
- IncludeSourceDir: true,
- RebaseNames: map[string]string{
- sourceBase: rebaseName,
- },
- })
-}
-
-// CopyInfo holds basic info about the source
-// or destination path of a copy operation.
-type CopyInfo struct {
- Path string
- Exists bool
- IsDir bool
- RebaseName string
-}
-
-// CopyInfoSourcePath stats the given path to create a CopyInfo
-// struct representing that resource for the source of an archive copy
-// operation. The given path should be an absolute local path. A source path
-// has all symlinks evaluated that appear before the last path separator ("/"
-// on Unix). As it is to be a copy source, the path must exist.
-func CopyInfoSourcePath(path string, followLink bool) (CopyInfo, error) {
- // normalize the file path and then evaluate the symbol link
- // we will use the target file instead of the symbol link if
- // followLink is set
- path = normalizePath(path)
-
- resolvedPath, rebaseName, err := ResolveHostSourcePath(path, followLink)
- if err != nil {
- return CopyInfo{}, err
- }
-
- stat, err := os.Lstat(resolvedPath)
- if err != nil {
- return CopyInfo{}, err
- }
-
- return CopyInfo{
- Path: resolvedPath,
- Exists: true,
- IsDir: stat.IsDir(),
- RebaseName: rebaseName,
- }, nil
-}
-
-// CopyInfoDestinationPath stats the given path to create a CopyInfo
-// struct representing that resource for the destination of an archive copy
-// operation. The given path should be an absolute local path.
-func CopyInfoDestinationPath(path string) (info CopyInfo, err error) {
- maxSymlinkIter := 10 // filepath.EvalSymlinks uses 255, but 10 already seems like a lot.
- path = normalizePath(path)
- originalPath := path
-
- stat, err := os.Lstat(path)
-
- if err == nil && stat.Mode()&os.ModeSymlink == 0 {
- // The path exists and is not a symlink.
- return CopyInfo{
- Path: path,
- Exists: true,
- IsDir: stat.IsDir(),
- }, nil
- }
-
- // While the path is a symlink.
- for n := 0; err == nil && stat.Mode()&os.ModeSymlink != 0; n++ {
- if n > maxSymlinkIter {
- // Don't follow symlinks more than this arbitrary number of times.
- return CopyInfo{}, errors.New("too many symlinks in " + originalPath)
- }
-
- // The path is a symbolic link. We need to evaluate it so that the
- // destination of the copy operation is the link target and not the
- // link itself. This is notably different than CopyInfoSourcePath which
- // only evaluates symlinks before the last appearing path separator.
- // Also note that it is okay if the last path element is a broken
- // symlink as the copy operation should create the target.
- var linkTarget string
-
- linkTarget, err = os.Readlink(path)
- if err != nil {
- return CopyInfo{}, err
- }
-
- if !system.IsAbs(linkTarget) {
- // Join with the parent directory.
- dstParent, _ := SplitPathDirEntry(path)
- linkTarget = filepath.Join(dstParent, linkTarget)
- }
-
- path = linkTarget
- stat, err = os.Lstat(path)
- }
-
- if err != nil {
- // It's okay if the destination path doesn't exist. We can still
- // continue the copy operation if the parent directory exists.
- if !os.IsNotExist(err) {
- return CopyInfo{}, err
- }
-
- // Ensure destination parent dir exists.
- dstParent, _ := SplitPathDirEntry(path)
-
- parentDirStat, err := os.Lstat(dstParent)
- if err != nil {
- return CopyInfo{}, err
- }
- if !parentDirStat.IsDir() {
- return CopyInfo{}, ErrNotDirectory
- }
-
- return CopyInfo{Path: path}, nil
- }
-
- // The path exists after resolving symlinks.
- return CopyInfo{
- Path: path,
- Exists: true,
- IsDir: stat.IsDir(),
- }, nil
-}
-
-// PrepareArchiveCopy prepares the given srcContent archive, which should
-// contain the archived resource described by srcInfo, to the destination
-// described by dstInfo. Returns the possibly modified content archive along
-// with the path to the destination directory which it should be extracted to.
-func PrepareArchiveCopy(srcContent Reader, srcInfo, dstInfo CopyInfo) (dstDir string, content Archive, err error) {
- // Ensure in platform semantics
- srcInfo.Path = normalizePath(srcInfo.Path)
- dstInfo.Path = normalizePath(dstInfo.Path)
-
- // Separate the destination path between its directory and base
- // components in case the source archive contents need to be rebased.
- dstDir, dstBase := SplitPathDirEntry(dstInfo.Path)
- _, srcBase := SplitPathDirEntry(srcInfo.Path)
-
- switch {
- case dstInfo.Exists && dstInfo.IsDir:
- // The destination exists as a directory. No alteration
- // to srcContent is needed as its contents can be
- // simply extracted to the destination directory.
- return dstInfo.Path, ioutil.NopCloser(srcContent), nil
- case dstInfo.Exists && srcInfo.IsDir:
- // The destination exists as some type of file and the source
- // content is a directory. This is an error condition since
- // you cannot copy a directory to an existing file location.
- return "", nil, ErrCannotCopyDir
- case dstInfo.Exists:
- // The destination exists as some type of file and the source content
- // is also a file. The source content entry will have to be renamed to
- // have a basename which matches the destination path's basename.
- if len(srcInfo.RebaseName) != 0 {
- srcBase = srcInfo.RebaseName
- }
- return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil
- case srcInfo.IsDir:
- // The destination does not exist and the source content is an archive
- // of a directory. The archive should be extracted to the parent of
- // the destination path instead, and when it is, the directory that is
- // created as a result should take the name of the destination path.
- // The source content entries will have to be renamed to have a
- // basename which matches the destination path's basename.
- if len(srcInfo.RebaseName) != 0 {
- srcBase = srcInfo.RebaseName
- }
- return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil
- case assertsDirectory(dstInfo.Path):
- // The destination does not exist and is asserted to be created as a
- // directory, but the source content is not a directory. This is an
- // error condition since you cannot create a directory from a file
- // source.
- return "", nil, ErrDirNotExists
- default:
- // The last remaining case is when the destination does not exist, is
- // not asserted to be a directory, and the source content is not an
- // archive of a directory. It this case, the destination file will need
- // to be created when the archive is extracted and the source content
- // entry will have to be renamed to have a basename which matches the
- // destination path's basename.
- if len(srcInfo.RebaseName) != 0 {
- srcBase = srcInfo.RebaseName
- }
- return dstDir, RebaseArchiveEntries(srcContent, srcBase, dstBase), nil
- }
-
-}
-
-// RebaseArchiveEntries rewrites the given srcContent archive replacing
-// an occurrence of oldBase with newBase at the beginning of entry names.
-func RebaseArchiveEntries(srcContent Reader, oldBase, newBase string) Archive {
- if oldBase == string(os.PathSeparator) {
- // If oldBase specifies the root directory, use an empty string as
- // oldBase instead so that newBase doesn't replace the path separator
- // that all paths will start with.
- oldBase = ""
- }
-
- rebased, w := io.Pipe()
-
- go func() {
- srcTar := tar.NewReader(srcContent)
- rebasedTar := tar.NewWriter(w)
-
- for {
- hdr, err := srcTar.Next()
- if err == io.EOF {
- // Signals end of archive.
- rebasedTar.Close()
- w.Close()
- return
- }
- if err != nil {
- w.CloseWithError(err)
- return
- }
-
- hdr.Name = strings.Replace(hdr.Name, oldBase, newBase, 1)
-
- if err = rebasedTar.WriteHeader(hdr); err != nil {
- w.CloseWithError(err)
- return
- }
-
- if _, err = io.Copy(rebasedTar, srcTar); err != nil {
- w.CloseWithError(err)
- return
- }
- }
- }()
-
- return rebased
-}
-
-// CopyResource performs an archive copy from the given source path to the
-// given destination path. The source path MUST exist and the destination
-// path's parent directory must exist.
-func CopyResource(srcPath, dstPath string, followLink bool) error {
- var (
- srcInfo CopyInfo
- err error
- )
-
- // Ensure in platform semantics
- srcPath = normalizePath(srcPath)
- dstPath = normalizePath(dstPath)
-
- // Clean the source and destination paths.
- srcPath = PreserveTrailingDotOrSeparator(filepath.Clean(srcPath), srcPath)
- dstPath = PreserveTrailingDotOrSeparator(filepath.Clean(dstPath), dstPath)
-
- if srcInfo, err = CopyInfoSourcePath(srcPath, followLink); err != nil {
- return err
- }
-
- content, err := TarResource(srcInfo)
- if err != nil {
- return err
- }
- defer content.Close()
-
- return CopyTo(content, srcInfo, dstPath)
-}
-
-// CopyTo handles extracting the given content whose
-// entries should be sourced from srcInfo to dstPath.
-func CopyTo(content Reader, srcInfo CopyInfo, dstPath string) error {
- // The destination path need not exist, but CopyInfoDestinationPath will
- // ensure that at least the parent directory exists.
- dstInfo, err := CopyInfoDestinationPath(normalizePath(dstPath))
- if err != nil {
- return err
- }
-
- dstDir, copyArchive, err := PrepareArchiveCopy(content, srcInfo, dstInfo)
- if err != nil {
- return err
- }
- defer copyArchive.Close()
-
- options := &TarOptions{
- NoLchown: true,
- NoOverwriteDirNonDir: true,
- }
-
- return Untar(copyArchive, dstDir, options)
-}
-
-// ResolveHostSourcePath decides real path need to be copied with parameters such as
-// whether to follow symbol link or not, if followLink is true, resolvedPath will return
-// link target of any symbol link file, else it will only resolve symlink of directory
-// but return symbol link file itself without resolving.
-func ResolveHostSourcePath(path string, followLink bool) (resolvedPath, rebaseName string, err error) {
- if followLink {
- resolvedPath, err = filepath.EvalSymlinks(path)
- if err != nil {
- return
- }
-
- resolvedPath, rebaseName = GetRebaseName(path, resolvedPath)
- } else {
- dirPath, basePath := filepath.Split(path)
-
- // if not follow symbol link, then resolve symbol link of parent dir
- var resolvedDirPath string
- resolvedDirPath, err = filepath.EvalSymlinks(dirPath)
- if err != nil {
- return
- }
- // resolvedDirPath will have been cleaned (no trailing path separators) so
- // we can manually join it with the base path element.
- resolvedPath = resolvedDirPath + string(filepath.Separator) + basePath
- if hasTrailingPathSeparator(path) && filepath.Base(path) != filepath.Base(resolvedPath) {
- rebaseName = filepath.Base(path)
- }
- }
- return resolvedPath, rebaseName, nil
-}
-
-// GetRebaseName normalizes and compares path and resolvedPath,
-// return completed resolved path and rebased file name
-func GetRebaseName(path, resolvedPath string) (string, string) {
- // linkTarget will have been cleaned (no trailing path separators and dot) so
- // we can manually join it with them
- var rebaseName string
- if specifiesCurrentDir(path) && !specifiesCurrentDir(resolvedPath) {
- resolvedPath += string(filepath.Separator) + "."
- }
-
- if hasTrailingPathSeparator(path) && !hasTrailingPathSeparator(resolvedPath) {
- resolvedPath += string(filepath.Separator)
- }
-
- if filepath.Base(path) != filepath.Base(resolvedPath) {
- // In the case where the path had a trailing separator and a symlink
- // evaluation has changed the last path component, we will need to
- // rebase the name in the archive that is being copied to match the
- // originally requested name.
- rebaseName = filepath.Base(path)
- }
- return resolvedPath, rebaseName
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go b/vendor/github.com/docker/docker/pkg/archive/copy_unix.go
deleted file mode 100644
index e305b5e..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// +build !windows
-
-package archive
-
-import (
- "path/filepath"
-)
-
-func normalizePath(path string) string {
- return filepath.ToSlash(path)
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_unix_test.go b/vendor/github.com/docker/docker/pkg/archive/copy_unix_test.go
deleted file mode 100644
index ecbfc17..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/copy_unix_test.go
+++ /dev/null
@@ -1,978 +0,0 @@
-// +build !windows
-
-// TODO Windows: Some of these tests may be salvagable and portable to Windows.
-
-package archive
-
-import (
- "bytes"
- "crypto/sha256"
- "encoding/hex"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
- "testing"
-)
-
-func removeAllPaths(paths ...string) {
- for _, path := range paths {
- os.RemoveAll(path)
- }
-}
-
-func getTestTempDirs(t *testing.T) (tmpDirA, tmpDirB string) {
- var err error
-
- if tmpDirA, err = ioutil.TempDir("", "archive-copy-test"); err != nil {
- t.Fatal(err)
- }
-
- if tmpDirB, err = ioutil.TempDir("", "archive-copy-test"); err != nil {
- t.Fatal(err)
- }
-
- return
-}
-
-func isNotDir(err error) bool {
- return strings.Contains(err.Error(), "not a directory")
-}
-
-func joinTrailingSep(pathElements ...string) string {
- joined := filepath.Join(pathElements...)
-
- return fmt.Sprintf("%s%c", joined, filepath.Separator)
-}
-
-func fileContentsEqual(t *testing.T, filenameA, filenameB string) (err error) {
- t.Logf("checking for equal file contents: %q and %q\n", filenameA, filenameB)
-
- fileA, err := os.Open(filenameA)
- if err != nil {
- return
- }
- defer fileA.Close()
-
- fileB, err := os.Open(filenameB)
- if err != nil {
- return
- }
- defer fileB.Close()
-
- hasher := sha256.New()
-
- if _, err = io.Copy(hasher, fileA); err != nil {
- return
- }
-
- hashA := hasher.Sum(nil)
- hasher.Reset()
-
- if _, err = io.Copy(hasher, fileB); err != nil {
- return
- }
-
- hashB := hasher.Sum(nil)
-
- if !bytes.Equal(hashA, hashB) {
- err = fmt.Errorf("file content hashes not equal - expected %s, got %s", hex.EncodeToString(hashA), hex.EncodeToString(hashB))
- }
-
- return
-}
-
-func dirContentsEqual(t *testing.T, newDir, oldDir string) (err error) {
- t.Logf("checking for equal directory contents: %q and %q\n", newDir, oldDir)
-
- var changes []Change
-
- if changes, err = ChangesDirs(newDir, oldDir); err != nil {
- return
- }
-
- if len(changes) != 0 {
- err = fmt.Errorf("expected no changes between directories, but got: %v", changes)
- }
-
- return
-}
-
-func logDirContents(t *testing.T, dirPath string) {
- logWalkedPaths := filepath.WalkFunc(func(path string, info os.FileInfo, err error) error {
- if err != nil {
- t.Errorf("stat error for path %q: %s", path, err)
- return nil
- }
-
- if info.IsDir() {
- path = joinTrailingSep(path)
- }
-
- t.Logf("\t%s", path)
-
- return nil
- })
-
- t.Logf("logging directory contents: %q", dirPath)
-
- if err := filepath.Walk(dirPath, logWalkedPaths); err != nil {
- t.Fatal(err)
- }
-}
-
-func testCopyHelper(t *testing.T, srcPath, dstPath string) (err error) {
- t.Logf("copying from %q to %q (not follow symbol link)", srcPath, dstPath)
-
- return CopyResource(srcPath, dstPath, false)
-}
-
-func testCopyHelperFSym(t *testing.T, srcPath, dstPath string) (err error) {
- t.Logf("copying from %q to %q (follow symbol link)", srcPath, dstPath)
-
- return CopyResource(srcPath, dstPath, true)
-}
-
-// Basic assumptions about SRC and DST:
-// 1. SRC must exist.
-// 2. If SRC ends with a trailing separator, it must be a directory.
-// 3. DST parent directory must exist.
-// 4. If DST exists as a file, it must not end with a trailing separator.
-
-// First get these easy error cases out of the way.
-
-// Test for error when SRC does not exist.
-func TestCopyErrSrcNotExists(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- if _, err := CopyInfoSourcePath(filepath.Join(tmpDirA, "file1"), false); !os.IsNotExist(err) {
- t.Fatalf("expected IsNotExist error, but got %T: %s", err, err)
- }
-}
-
-// Test for error when SRC ends in a trailing
-// path separator but it exists as a file.
-func TestCopyErrSrcNotDir(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- if _, err := CopyInfoSourcePath(joinTrailingSep(tmpDirA, "file1"), false); !isNotDir(err) {
- t.Fatalf("expected IsNotDir error, but got %T: %s", err, err)
- }
-}
-
-// Test for error when SRC is a valid file or directory,
-// but the DST parent directory does not exist.
-func TestCopyErrDstParentNotExists(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- srcInfo := CopyInfo{Path: filepath.Join(tmpDirA, "file1"), Exists: true, IsDir: false}
-
- // Try with a file source.
- content, err := TarResource(srcInfo)
- if err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
- defer content.Close()
-
- // Copy to a file whose parent does not exist.
- if err = CopyTo(content, srcInfo, filepath.Join(tmpDirB, "fakeParentDir", "file1")); err == nil {
- t.Fatal("expected IsNotExist error, but got nil instead")
- }
-
- if !os.IsNotExist(err) {
- t.Fatalf("expected IsNotExist error, but got %T: %s", err, err)
- }
-
- // Try with a directory source.
- srcInfo = CopyInfo{Path: filepath.Join(tmpDirA, "dir1"), Exists: true, IsDir: true}
-
- content, err = TarResource(srcInfo)
- if err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
- defer content.Close()
-
- // Copy to a directory whose parent does not exist.
- if err = CopyTo(content, srcInfo, joinTrailingSep(tmpDirB, "fakeParentDir", "fakeDstDir")); err == nil {
- t.Fatal("expected IsNotExist error, but got nil instead")
- }
-
- if !os.IsNotExist(err) {
- t.Fatalf("expected IsNotExist error, but got %T: %s", err, err)
- }
-}
-
-// Test for error when DST ends in a trailing
-// path separator but exists as a file.
-func TestCopyErrDstNotDir(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- // Try with a file source.
- srcInfo := CopyInfo{Path: filepath.Join(tmpDirA, "file1"), Exists: true, IsDir: false}
-
- content, err := TarResource(srcInfo)
- if err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
- defer content.Close()
-
- if err = CopyTo(content, srcInfo, joinTrailingSep(tmpDirB, "file1")); err == nil {
- t.Fatal("expected IsNotDir error, but got nil instead")
- }
-
- if !isNotDir(err) {
- t.Fatalf("expected IsNotDir error, but got %T: %s", err, err)
- }
-
- // Try with a directory source.
- srcInfo = CopyInfo{Path: filepath.Join(tmpDirA, "dir1"), Exists: true, IsDir: true}
-
- content, err = TarResource(srcInfo)
- if err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
- defer content.Close()
-
- if err = CopyTo(content, srcInfo, joinTrailingSep(tmpDirB, "file1")); err == nil {
- t.Fatal("expected IsNotDir error, but got nil instead")
- }
-
- if !isNotDir(err) {
- t.Fatalf("expected IsNotDir error, but got %T: %s", err, err)
- }
-}
-
-// Possibilities are reduced to the remaining 10 cases:
-//
-// case | srcIsDir | onlyDirContents | dstExists | dstIsDir | dstTrSep | action
-// ===================================================================================================
-// A | no | - | no | - | no | create file
-// B | no | - | no | - | yes | error
-// C | no | - | yes | no | - | overwrite file
-// D | no | - | yes | yes | - | create file in dst dir
-// E | yes | no | no | - | - | create dir, copy contents
-// F | yes | no | yes | no | - | error
-// G | yes | no | yes | yes | - | copy dir and contents
-// H | yes | yes | no | - | - | create dir, copy contents
-// I | yes | yes | yes | no | - | error
-// J | yes | yes | yes | yes | - | copy dir contents
-//
-
-// A. SRC specifies a file and DST (no trailing path separator) doesn't
-// exist. This should create a file with the name DST and copy the
-// contents of the source file into it.
-func TestCopyCaseA(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- srcPath := filepath.Join(tmpDirA, "file1")
- dstPath := filepath.Join(tmpDirB, "itWorks.txt")
-
- var err error
-
- if err = testCopyHelper(t, srcPath, dstPath); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, srcPath, dstPath); err != nil {
- t.Fatal(err)
- }
- os.Remove(dstPath)
-
- symlinkPath := filepath.Join(tmpDirA, "symlink3")
- symlinkPath1 := filepath.Join(tmpDirA, "symlink4")
- linkTarget := filepath.Join(tmpDirA, "file1")
-
- if err = testCopyHelperFSym(t, symlinkPath, dstPath); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, linkTarget, dstPath); err != nil {
- t.Fatal(err)
- }
- os.Remove(dstPath)
- if err = testCopyHelperFSym(t, symlinkPath1, dstPath); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, linkTarget, dstPath); err != nil {
- t.Fatal(err)
- }
-}
-
-// B. SRC specifies a file and DST (with trailing path separator) doesn't
-// exist. This should cause an error because the copy operation cannot
-// create a directory when copying a single file.
-func TestCopyCaseB(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- srcPath := filepath.Join(tmpDirA, "file1")
- dstDir := joinTrailingSep(tmpDirB, "testDir")
-
- var err error
-
- if err = testCopyHelper(t, srcPath, dstDir); err == nil {
- t.Fatal("expected ErrDirNotExists error, but got nil instead")
- }
-
- if err != ErrDirNotExists {
- t.Fatalf("expected ErrDirNotExists error, but got %T: %s", err, err)
- }
-
- symlinkPath := filepath.Join(tmpDirA, "symlink3")
-
- if err = testCopyHelperFSym(t, symlinkPath, dstDir); err == nil {
- t.Fatal("expected ErrDirNotExists error, but got nil instead")
- }
- if err != ErrDirNotExists {
- t.Fatalf("expected ErrDirNotExists error, but got %T: %s", err, err)
- }
-
-}
-
-// C. SRC specifies a file and DST exists as a file. This should overwrite
-// the file at DST with the contents of the source file.
-func TestCopyCaseC(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcPath := filepath.Join(tmpDirA, "file1")
- dstPath := filepath.Join(tmpDirB, "file2")
-
- var err error
-
- // Ensure they start out different.
- if err = fileContentsEqual(t, srcPath, dstPath); err == nil {
- t.Fatal("expected different file contents")
- }
-
- if err = testCopyHelper(t, srcPath, dstPath); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, srcPath, dstPath); err != nil {
- t.Fatal(err)
- }
-}
-
-// C. Symbol link following version:
-// SRC specifies a file and DST exists as a file. This should overwrite
-// the file at DST with the contents of the source file.
-func TestCopyCaseCFSym(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- symlinkPathBad := filepath.Join(tmpDirA, "symlink1")
- symlinkPath := filepath.Join(tmpDirA, "symlink3")
- linkTarget := filepath.Join(tmpDirA, "file1")
- dstPath := filepath.Join(tmpDirB, "file2")
-
- var err error
-
- // first to test broken link
- if err = testCopyHelperFSym(t, symlinkPathBad, dstPath); err == nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- // test symbol link -> symbol link -> target
- // Ensure they start out different.
- if err = fileContentsEqual(t, linkTarget, dstPath); err == nil {
- t.Fatal("expected different file contents")
- }
-
- if err = testCopyHelperFSym(t, symlinkPath, dstPath); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, linkTarget, dstPath); err != nil {
- t.Fatal(err)
- }
-}
-
-// D. SRC specifies a file and DST exists as a directory. This should place
-// a copy of the source file inside it using the basename from SRC. Ensure
-// this works whether DST has a trailing path separator or not.
-func TestCopyCaseD(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcPath := filepath.Join(tmpDirA, "file1")
- dstDir := filepath.Join(tmpDirB, "dir1")
- dstPath := filepath.Join(dstDir, "file1")
-
- var err error
-
- // Ensure that dstPath doesn't exist.
- if _, err = os.Stat(dstPath); !os.IsNotExist(err) {
- t.Fatalf("did not expect dstPath %q to exist", dstPath)
- }
-
- if err = testCopyHelper(t, srcPath, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, srcPath, dstPath); err != nil {
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "dir1")
-
- if err = testCopyHelper(t, srcPath, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, srcPath, dstPath); err != nil {
- t.Fatal(err)
- }
-}
-
-// D. Symbol link following version:
-// SRC specifies a file and DST exists as a directory. This should place
-// a copy of the source file inside it using the basename from SRC. Ensure
-// this works whether DST has a trailing path separator or not.
-func TestCopyCaseDFSym(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcPath := filepath.Join(tmpDirA, "symlink4")
- linkTarget := filepath.Join(tmpDirA, "file1")
- dstDir := filepath.Join(tmpDirB, "dir1")
- dstPath := filepath.Join(dstDir, "symlink4")
-
- var err error
-
- // Ensure that dstPath doesn't exist.
- if _, err = os.Stat(dstPath); !os.IsNotExist(err) {
- t.Fatalf("did not expect dstPath %q to exist", dstPath)
- }
-
- if err = testCopyHelperFSym(t, srcPath, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, linkTarget, dstPath); err != nil {
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "dir1")
-
- if err = testCopyHelperFSym(t, srcPath, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = fileContentsEqual(t, linkTarget, dstPath); err != nil {
- t.Fatal(err)
- }
-}
-
-// E. SRC specifies a directory and DST does not exist. This should create a
-// directory at DST and copy the contents of the SRC directory into the DST
-// directory. Ensure this works whether DST has a trailing path separator or
-// not.
-func TestCopyCaseE(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- srcDir := filepath.Join(tmpDirA, "dir1")
- dstDir := filepath.Join(tmpDirB, "testDir")
-
- var err error
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, srcDir); err != nil {
- t.Log("dir contents not equal")
- logDirContents(t, tmpDirA)
- logDirContents(t, tmpDirB)
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "testDir")
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, srcDir); err != nil {
- t.Fatal(err)
- }
-}
-
-// E. Symbol link following version:
-// SRC specifies a directory and DST does not exist. This should create a
-// directory at DST and copy the contents of the SRC directory into the DST
-// directory. Ensure this works whether DST has a trailing path separator or
-// not.
-func TestCopyCaseEFSym(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- srcDir := filepath.Join(tmpDirA, "dirSymlink")
- linkTarget := filepath.Join(tmpDirA, "dir1")
- dstDir := filepath.Join(tmpDirB, "testDir")
-
- var err error
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, linkTarget); err != nil {
- t.Log("dir contents not equal")
- logDirContents(t, tmpDirA)
- logDirContents(t, tmpDirB)
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "testDir")
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, linkTarget); err != nil {
- t.Fatal(err)
- }
-}
-
-// F. SRC specifies a directory and DST exists as a file. This should cause an
-// error as it is not possible to overwrite a file with a directory.
-func TestCopyCaseF(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcDir := filepath.Join(tmpDirA, "dir1")
- symSrcDir := filepath.Join(tmpDirA, "dirSymlink")
- dstFile := filepath.Join(tmpDirB, "file1")
-
- var err error
-
- if err = testCopyHelper(t, srcDir, dstFile); err == nil {
- t.Fatal("expected ErrCannotCopyDir error, but got nil instead")
- }
-
- if err != ErrCannotCopyDir {
- t.Fatalf("expected ErrCannotCopyDir error, but got %T: %s", err, err)
- }
-
- // now test with symbol link
- if err = testCopyHelperFSym(t, symSrcDir, dstFile); err == nil {
- t.Fatal("expected ErrCannotCopyDir error, but got nil instead")
- }
-
- if err != ErrCannotCopyDir {
- t.Fatalf("expected ErrCannotCopyDir error, but got %T: %s", err, err)
- }
-}
-
-// G. SRC specifies a directory and DST exists as a directory. This should copy
-// the SRC directory and all its contents to the DST directory. Ensure this
-// works whether DST has a trailing path separator or not.
-func TestCopyCaseG(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcDir := filepath.Join(tmpDirA, "dir1")
- dstDir := filepath.Join(tmpDirB, "dir2")
- resultDir := filepath.Join(dstDir, "dir1")
-
- var err error
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, resultDir, srcDir); err != nil {
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "dir2")
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, resultDir, srcDir); err != nil {
- t.Fatal(err)
- }
-}
-
-// G. Symbol link version:
-// SRC specifies a directory and DST exists as a directory. This should copy
-// the SRC directory and all its contents to the DST directory. Ensure this
-// works whether DST has a trailing path separator or not.
-func TestCopyCaseGFSym(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcDir := filepath.Join(tmpDirA, "dirSymlink")
- linkTarget := filepath.Join(tmpDirA, "dir1")
- dstDir := filepath.Join(tmpDirB, "dir2")
- resultDir := filepath.Join(dstDir, "dirSymlink")
-
- var err error
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, resultDir, linkTarget); err != nil {
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "dir2")
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, resultDir, linkTarget); err != nil {
- t.Fatal(err)
- }
-}
-
-// H. SRC specifies a directory's contents only and DST does not exist. This
-// should create a directory at DST and copy the contents of the SRC
-// directory (but not the directory itself) into the DST directory. Ensure
-// this works whether DST has a trailing path separator or not.
-func TestCopyCaseH(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- srcDir := joinTrailingSep(tmpDirA, "dir1") + "."
- dstDir := filepath.Join(tmpDirB, "testDir")
-
- var err error
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, srcDir); err != nil {
- t.Log("dir contents not equal")
- logDirContents(t, tmpDirA)
- logDirContents(t, tmpDirB)
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "testDir")
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, srcDir); err != nil {
- t.Log("dir contents not equal")
- logDirContents(t, tmpDirA)
- logDirContents(t, tmpDirB)
- t.Fatal(err)
- }
-}
-
-// H. Symbol link following version:
-// SRC specifies a directory's contents only and DST does not exist. This
-// should create a directory at DST and copy the contents of the SRC
-// directory (but not the directory itself) into the DST directory. Ensure
-// this works whether DST has a trailing path separator or not.
-func TestCopyCaseHFSym(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A with some sample files and directories.
- createSampleDir(t, tmpDirA)
-
- srcDir := joinTrailingSep(tmpDirA, "dirSymlink") + "."
- linkTarget := filepath.Join(tmpDirA, "dir1")
- dstDir := filepath.Join(tmpDirB, "testDir")
-
- var err error
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, linkTarget); err != nil {
- t.Log("dir contents not equal")
- logDirContents(t, tmpDirA)
- logDirContents(t, tmpDirB)
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "testDir")
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, linkTarget); err != nil {
- t.Log("dir contents not equal")
- logDirContents(t, tmpDirA)
- logDirContents(t, tmpDirB)
- t.Fatal(err)
- }
-}
-
-// I. SRC specifies a directory's contents only and DST exists as a file. This
-// should cause an error as it is not possible to overwrite a file with a
-// directory.
-func TestCopyCaseI(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcDir := joinTrailingSep(tmpDirA, "dir1") + "."
- symSrcDir := filepath.Join(tmpDirB, "dirSymlink")
- dstFile := filepath.Join(tmpDirB, "file1")
-
- var err error
-
- if err = testCopyHelper(t, srcDir, dstFile); err == nil {
- t.Fatal("expected ErrCannotCopyDir error, but got nil instead")
- }
-
- if err != ErrCannotCopyDir {
- t.Fatalf("expected ErrCannotCopyDir error, but got %T: %s", err, err)
- }
-
- // now try with symbol link of dir
- if err = testCopyHelperFSym(t, symSrcDir, dstFile); err == nil {
- t.Fatal("expected ErrCannotCopyDir error, but got nil instead")
- }
-
- if err != ErrCannotCopyDir {
- t.Fatalf("expected ErrCannotCopyDir error, but got %T: %s", err, err)
- }
-}
-
-// J. SRC specifies a directory's contents only and DST exists as a directory.
-// This should copy the contents of the SRC directory (but not the directory
-// itself) into the DST directory. Ensure this works whether DST has a
-// trailing path separator or not.
-func TestCopyCaseJ(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcDir := joinTrailingSep(tmpDirA, "dir1") + "."
- dstDir := filepath.Join(tmpDirB, "dir5")
-
- var err error
-
- // first to create an empty dir
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, srcDir); err != nil {
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "dir5")
-
- if err = testCopyHelper(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, srcDir); err != nil {
- t.Fatal(err)
- }
-}
-
-// J. Symbol link following version:
-// SRC specifies a directory's contents only and DST exists as a directory.
-// This should copy the contents of the SRC directory (but not the directory
-// itself) into the DST directory. Ensure this works whether DST has a
-// trailing path separator or not.
-func TestCopyCaseJFSym(t *testing.T) {
- tmpDirA, tmpDirB := getTestTempDirs(t)
- defer removeAllPaths(tmpDirA, tmpDirB)
-
- // Load A and B with some sample files and directories.
- createSampleDir(t, tmpDirA)
- createSampleDir(t, tmpDirB)
-
- srcDir := joinTrailingSep(tmpDirA, "dirSymlink") + "."
- linkTarget := filepath.Join(tmpDirA, "dir1")
- dstDir := filepath.Join(tmpDirB, "dir5")
-
- var err error
-
- // first to create an empty dir
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, linkTarget); err != nil {
- t.Fatal(err)
- }
-
- // Now try again but using a trailing path separator for dstDir.
-
- if err = os.RemoveAll(dstDir); err != nil {
- t.Fatalf("unable to remove dstDir: %s", err)
- }
-
- if err = os.MkdirAll(dstDir, os.FileMode(0755)); err != nil {
- t.Fatalf("unable to make dstDir: %s", err)
- }
-
- dstDir = joinTrailingSep(tmpDirB, "dir5")
-
- if err = testCopyHelperFSym(t, srcDir, dstDir); err != nil {
- t.Fatalf("unexpected error %T: %s", err, err)
- }
-
- if err = dirContentsEqual(t, dstDir, linkTarget); err != nil {
- t.Fatal(err)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go b/vendor/github.com/docker/docker/pkg/archive/copy_windows.go
deleted file mode 100644
index 2b775b4..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package archive
-
-import (
- "path/filepath"
-)
-
-func normalizePath(path string) string {
- return filepath.FromSlash(path)
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/diff.go b/vendor/github.com/docker/docker/pkg/archive/diff.go
deleted file mode 100644
index 1b08ad3..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/diff.go
+++ /dev/null
@@ -1,279 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "runtime"
- "strings"
-
- "github.com/Sirupsen/logrus"
- "github.com/docker/docker/pkg/idtools"
- "github.com/docker/docker/pkg/pools"
- "github.com/docker/docker/pkg/system"
-)
-
-// UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be
-// compressed or uncompressed.
-// Returns the size in bytes of the contents of the layer.
-func UnpackLayer(dest string, layer Reader, options *TarOptions) (size int64, err error) {
- tr := tar.NewReader(layer)
- trBuf := pools.BufioReader32KPool.Get(tr)
- defer pools.BufioReader32KPool.Put(trBuf)
-
- var dirs []*tar.Header
- unpackedPaths := make(map[string]struct{})
-
- if options == nil {
- options = &TarOptions{}
- }
- if options.ExcludePatterns == nil {
- options.ExcludePatterns = []string{}
- }
- remappedRootUID, remappedRootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps)
- if err != nil {
- return 0, err
- }
-
- aufsTempdir := ""
- aufsHardlinks := make(map[string]*tar.Header)
-
- if options == nil {
- options = &TarOptions{}
- }
- // Iterate through the files in the archive.
- for {
- hdr, err := tr.Next()
- if err == io.EOF {
- // end of tar archive
- break
- }
- if err != nil {
- return 0, err
- }
-
- size += hdr.Size
-
- // Normalize name, for safety and for a simple is-root check
- hdr.Name = filepath.Clean(hdr.Name)
-
- // Windows does not support filenames with colons in them. Ignore
- // these files. This is not a problem though (although it might
- // appear that it is). Let's suppose a client is running docker pull.
- // The daemon it points to is Windows. Would it make sense for the
- // client to be doing a docker pull Ubuntu for example (which has files
- // with colons in the name under /usr/share/man/man3)? No, absolutely
- // not as it would really only make sense that they were pulling a
- // Windows image. However, for development, it is necessary to be able
- // to pull Linux images which are in the repository.
- //
- // TODO Windows. Once the registry is aware of what images are Windows-
- // specific or Linux-specific, this warning should be changed to an error
- // to cater for the situation where someone does manage to upload a Linux
- // image but have it tagged as Windows inadvertently.
- if runtime.GOOS == "windows" {
- if strings.Contains(hdr.Name, ":") {
- logrus.Warnf("Windows: Ignoring %s (is this a Linux image?)", hdr.Name)
- continue
- }
- }
-
- // Note as these operations are platform specific, so must the slash be.
- if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) {
- // Not the root directory, ensure that the parent directory exists.
- // This happened in some tests where an image had a tarfile without any
- // parent directories.
- parent := filepath.Dir(hdr.Name)
- parentPath := filepath.Join(dest, parent)
-
- if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
- err = system.MkdirAll(parentPath, 0600)
- if err != nil {
- return 0, err
- }
- }
- }
-
- // Skip AUFS metadata dirs
- if strings.HasPrefix(hdr.Name, WhiteoutMetaPrefix) {
- // Regular files inside /.wh..wh.plnk can be used as hardlink targets
- // We don't want this directory, but we need the files in them so that
- // such hardlinks can be resolved.
- if strings.HasPrefix(hdr.Name, WhiteoutLinkDir) && hdr.Typeflag == tar.TypeReg {
- basename := filepath.Base(hdr.Name)
- aufsHardlinks[basename] = hdr
- if aufsTempdir == "" {
- if aufsTempdir, err = ioutil.TempDir("", "dockerplnk"); err != nil {
- return 0, err
- }
- defer os.RemoveAll(aufsTempdir)
- }
- if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil); err != nil {
- return 0, err
- }
- }
-
- if hdr.Name != WhiteoutOpaqueDir {
- continue
- }
- }
- path := filepath.Join(dest, hdr.Name)
- rel, err := filepath.Rel(dest, path)
- if err != nil {
- return 0, err
- }
-
- // Note as these operations are platform specific, so must the slash be.
- if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
- return 0, breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest))
- }
- base := filepath.Base(path)
-
- if strings.HasPrefix(base, WhiteoutPrefix) {
- dir := filepath.Dir(path)
- if base == WhiteoutOpaqueDir {
- _, err := os.Lstat(dir)
- if err != nil {
- return 0, err
- }
- err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- if os.IsNotExist(err) {
- err = nil // parent was deleted
- }
- return err
- }
- if path == dir {
- return nil
- }
- if _, exists := unpackedPaths[path]; !exists {
- err := os.RemoveAll(path)
- return err
- }
- return nil
- })
- if err != nil {
- return 0, err
- }
- } else {
- originalBase := base[len(WhiteoutPrefix):]
- originalPath := filepath.Join(dir, originalBase)
- if err := os.RemoveAll(originalPath); err != nil {
- return 0, err
- }
- }
- } else {
- // If path exits we almost always just want to remove and replace it.
- // The only exception is when it is a directory *and* the file from
- // the layer is also a directory. Then we want to merge them (i.e.
- // just apply the metadata from the layer).
- if fi, err := os.Lstat(path); err == nil {
- if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
- if err := os.RemoveAll(path); err != nil {
- return 0, err
- }
- }
- }
-
- trBuf.Reset(tr)
- srcData := io.Reader(trBuf)
- srcHdr := hdr
-
- // Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so
- // we manually retarget these into the temporary files we extracted them into
- if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), WhiteoutLinkDir) {
- linkBasename := filepath.Base(hdr.Linkname)
- srcHdr = aufsHardlinks[linkBasename]
- if srcHdr == nil {
- return 0, fmt.Errorf("Invalid aufs hardlink")
- }
- tmpFile, err := os.Open(filepath.Join(aufsTempdir, linkBasename))
- if err != nil {
- return 0, err
- }
- defer tmpFile.Close()
- srcData = tmpFile
- }
-
- // if the options contain a uid & gid maps, convert header uid/gid
- // entries using the maps such that lchown sets the proper mapped
- // uid/gid after writing the file. We only perform this mapping if
- // the file isn't already owned by the remapped root UID or GID, as
- // that specific uid/gid has no mapping from container -> host, and
- // those files already have the proper ownership for inside the
- // container.
- if srcHdr.Uid != remappedRootUID {
- xUID, err := idtools.ToHost(srcHdr.Uid, options.UIDMaps)
- if err != nil {
- return 0, err
- }
- srcHdr.Uid = xUID
- }
- if srcHdr.Gid != remappedRootGID {
- xGID, err := idtools.ToHost(srcHdr.Gid, options.GIDMaps)
- if err != nil {
- return 0, err
- }
- srcHdr.Gid = xGID
- }
- if err := createTarFile(path, dest, srcHdr, srcData, true, nil); err != nil {
- return 0, err
- }
-
- // Directory mtimes must be handled at the end to avoid further
- // file creation in them to modify the directory mtime
- if hdr.Typeflag == tar.TypeDir {
- dirs = append(dirs, hdr)
- }
- unpackedPaths[path] = struct{}{}
- }
- }
-
- for _, hdr := range dirs {
- path := filepath.Join(dest, hdr.Name)
- if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
- return 0, err
- }
- }
-
- return size, nil
-}
-
-// ApplyLayer parses a diff in the standard layer format from `layer`,
-// and applies it to the directory `dest`. The stream `layer` can be
-// compressed or uncompressed.
-// Returns the size in bytes of the contents of the layer.
-func ApplyLayer(dest string, layer Reader) (int64, error) {
- return applyLayerHandler(dest, layer, &TarOptions{}, true)
-}
-
-// ApplyUncompressedLayer parses a diff in the standard layer format from
-// `layer`, and applies it to the directory `dest`. The stream `layer`
-// can only be uncompressed.
-// Returns the size in bytes of the contents of the layer.
-func ApplyUncompressedLayer(dest string, layer Reader, options *TarOptions) (int64, error) {
- return applyLayerHandler(dest, layer, options, false)
-}
-
-// do the bulk load of ApplyLayer, but allow for not calling DecompressStream
-func applyLayerHandler(dest string, layer Reader, options *TarOptions, decompress bool) (int64, error) {
- dest = filepath.Clean(dest)
-
- // We need to be able to set any perms
- oldmask, err := system.Umask(0)
- if err != nil {
- return 0, err
- }
- defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform
-
- if decompress {
- layer, err = DecompressStream(layer)
- if err != nil {
- return 0, err
- }
- }
- return UnpackLayer(dest, layer, options)
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/diff_test.go b/vendor/github.com/docker/docker/pkg/archive/diff_test.go
deleted file mode 100644
index 8167941..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/diff_test.go
+++ /dev/null
@@ -1,386 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "reflect"
- "runtime"
- "testing"
-
- "github.com/docker/docker/pkg/ioutils"
-)
-
-func TestApplyLayerInvalidFilenames(t *testing.T) {
- // TODO Windows: Figure out how to fix this test.
- if runtime.GOOS == "windows" {
- t.Skip("Passes but hits breakoutError: platform and architecture is not supported")
- }
- for i, headers := range [][]*tar.Header{
- {
- {
- Name: "../victim/dotdot",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- {
- {
- // Note the leading slash
- Name: "/../victim/slash-dotdot",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- } {
- if err := testBreakout("applylayer", "docker-TestApplyLayerInvalidFilenames", headers); err != nil {
- t.Fatalf("i=%d. %v", i, err)
- }
- }
-}
-
-func TestApplyLayerInvalidHardlink(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("TypeLink support on Windows")
- }
- for i, headers := range [][]*tar.Header{
- { // try reading victim/hello (../)
- {
- Name: "dotdot",
- Typeflag: tar.TypeLink,
- Linkname: "../victim/hello",
- Mode: 0644,
- },
- },
- { // try reading victim/hello (/../)
- {
- Name: "slash-dotdot",
- Typeflag: tar.TypeLink,
- // Note the leading slash
- Linkname: "/../victim/hello",
- Mode: 0644,
- },
- },
- { // try writing victim/file
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim/file",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- { // try reading victim/hello (hardlink, symlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "symlink",
- Typeflag: tar.TypeSymlink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // Try reading victim/hello (hardlink, hardlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "hardlink",
- Typeflag: tar.TypeLink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // Try removing victim directory (hardlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeLink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- } {
- if err := testBreakout("applylayer", "docker-TestApplyLayerInvalidHardlink", headers); err != nil {
- t.Fatalf("i=%d. %v", i, err)
- }
- }
-}
-
-func TestApplyLayerInvalidSymlink(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("TypeSymLink support on Windows")
- }
- for i, headers := range [][]*tar.Header{
- { // try reading victim/hello (../)
- {
- Name: "dotdot",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim/hello",
- Mode: 0644,
- },
- },
- { // try reading victim/hello (/../)
- {
- Name: "slash-dotdot",
- Typeflag: tar.TypeSymlink,
- // Note the leading slash
- Linkname: "/../victim/hello",
- Mode: 0644,
- },
- },
- { // try writing victim/file
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim/file",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- { // try reading victim/hello (symlink, symlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "symlink",
- Typeflag: tar.TypeSymlink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // try reading victim/hello (symlink, hardlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "hardlink",
- Typeflag: tar.TypeLink,
- Linkname: "loophole-victim/hello",
- Mode: 0644,
- },
- },
- { // try removing victim directory (symlink)
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeSymlink,
- Linkname: "../victim",
- Mode: 0755,
- },
- {
- Name: "loophole-victim",
- Typeflag: tar.TypeReg,
- Mode: 0644,
- },
- },
- } {
- if err := testBreakout("applylayer", "docker-TestApplyLayerInvalidSymlink", headers); err != nil {
- t.Fatalf("i=%d. %v", i, err)
- }
- }
-}
-
-func TestApplyLayerWhiteouts(t *testing.T) {
- // TODO Windows: Figure out why this test fails
- if runtime.GOOS == "windows" {
- t.Skip("Failing on Windows")
- }
-
- wd, err := ioutil.TempDir("", "graphdriver-test-whiteouts")
- if err != nil {
- return
- }
- defer os.RemoveAll(wd)
-
- base := []string{
- ".baz",
- "bar/",
- "bar/bax",
- "bar/bay/",
- "baz",
- "foo/",
- "foo/.abc",
- "foo/.bcd/",
- "foo/.bcd/a",
- "foo/cde/",
- "foo/cde/def",
- "foo/cde/efg",
- "foo/fgh",
- "foobar",
- }
-
- type tcase struct {
- change, expected []string
- }
-
- tcases := []tcase{
- {
- base,
- base,
- },
- {
- []string{
- ".bay",
- ".wh.baz",
- "foo/",
- "foo/.bce",
- "foo/.wh..wh..opq",
- "foo/cde/",
- "foo/cde/efg",
- },
- []string{
- ".bay",
- ".baz",
- "bar/",
- "bar/bax",
- "bar/bay/",
- "foo/",
- "foo/.bce",
- "foo/cde/",
- "foo/cde/efg",
- "foobar",
- },
- },
- {
- []string{
- ".bay",
- ".wh..baz",
- ".wh.foobar",
- "foo/",
- "foo/.abc",
- "foo/.wh.cde",
- "bar/",
- },
- []string{
- ".bay",
- "bar/",
- "bar/bax",
- "bar/bay/",
- "foo/",
- "foo/.abc",
- "foo/.bce",
- },
- },
- {
- []string{
- ".abc",
- ".wh..wh..opq",
- "foobar",
- },
- []string{
- ".abc",
- "foobar",
- },
- },
- }
-
- for i, tc := range tcases {
- l, err := makeTestLayer(tc.change)
- if err != nil {
- t.Fatal(err)
- }
-
- _, err = UnpackLayer(wd, l, nil)
- if err != nil {
- t.Fatal(err)
- }
- err = l.Close()
- if err != nil {
- t.Fatal(err)
- }
-
- paths, err := readDirContents(wd)
- if err != nil {
- t.Fatal(err)
- }
-
- if !reflect.DeepEqual(tc.expected, paths) {
- t.Fatalf("invalid files for layer %d: expected %q, got %q", i, tc.expected, paths)
- }
- }
-
-}
-
-func makeTestLayer(paths []string) (rc io.ReadCloser, err error) {
- tmpDir, err := ioutil.TempDir("", "graphdriver-test-mklayer")
- if err != nil {
- return
- }
- defer func() {
- if err != nil {
- os.RemoveAll(tmpDir)
- }
- }()
- for _, p := range paths {
- if p[len(p)-1] == filepath.Separator {
- if err = os.MkdirAll(filepath.Join(tmpDir, p), 0700); err != nil {
- return
- }
- } else {
- if err = ioutil.WriteFile(filepath.Join(tmpDir, p), nil, 0600); err != nil {
- return
- }
- }
- }
- archive, err := Tar(tmpDir, Uncompressed)
- if err != nil {
- return
- }
- return ioutils.NewReadCloserWrapper(archive, func() error {
- err := archive.Close()
- os.RemoveAll(tmpDir)
- return err
- }), nil
-}
-
-func readDirContents(root string) ([]string, error) {
- var files []string
- err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if path == root {
- return nil
- }
- rel, err := filepath.Rel(root, path)
- if err != nil {
- return err
- }
- if info.IsDir() {
- rel = rel + "/"
- }
- files = append(files, rel)
- return nil
- })
- if err != nil {
- return nil, err
- }
- return files, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/example_changes.go b/vendor/github.com/docker/docker/pkg/archive/example_changes.go
deleted file mode 100644
index cedd46a..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/example_changes.go
+++ /dev/null
@@ -1,97 +0,0 @@
-// +build ignore
-
-// Simple tool to create an archive stream from an old and new directory
-//
-// By default it will stream the comparison of two temporary directories with junk files
-package main
-
-import (
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path"
-
- "github.com/Sirupsen/logrus"
- "github.com/docker/docker/pkg/archive"
-)
-
-var (
- flDebug = flag.Bool("D", false, "debugging output")
- flNewDir = flag.String("newdir", "", "")
- flOldDir = flag.String("olddir", "", "")
- log = logrus.New()
-)
-
-func main() {
- flag.Usage = func() {
- fmt.Println("Produce a tar from comparing two directory paths. By default a demo tar is created of around 200 files (including hardlinks)")
- fmt.Printf("%s [OPTIONS]\n", os.Args[0])
- flag.PrintDefaults()
- }
- flag.Parse()
- log.Out = os.Stderr
- if (len(os.Getenv("DEBUG")) > 0) || *flDebug {
- logrus.SetLevel(logrus.DebugLevel)
- }
- var newDir, oldDir string
-
- if len(*flNewDir) == 0 {
- var err error
- newDir, err = ioutil.TempDir("", "docker-test-newDir")
- if err != nil {
- log.Fatal(err)
- }
- defer os.RemoveAll(newDir)
- if _, err := prepareUntarSourceDirectory(100, newDir, true); err != nil {
- log.Fatal(err)
- }
- } else {
- newDir = *flNewDir
- }
-
- if len(*flOldDir) == 0 {
- oldDir, err := ioutil.TempDir("", "docker-test-oldDir")
- if err != nil {
- log.Fatal(err)
- }
- defer os.RemoveAll(oldDir)
- } else {
- oldDir = *flOldDir
- }
-
- changes, err := archive.ChangesDirs(newDir, oldDir)
- if err != nil {
- log.Fatal(err)
- }
-
- a, err := archive.ExportChanges(newDir, changes)
- if err != nil {
- log.Fatal(err)
- }
- defer a.Close()
-
- i, err := io.Copy(os.Stdout, a)
- if err != nil && err != io.EOF {
- log.Fatal(err)
- }
- fmt.Fprintf(os.Stderr, "wrote archive of %d bytes", i)
-}
-
-func prepareUntarSourceDirectory(numberOfFiles int, targetPath string, makeLinks bool) (int, error) {
- fileData := []byte("fooo")
- for n := 0; n < numberOfFiles; n++ {
- fileName := fmt.Sprintf("file-%d", n)
- if err := ioutil.WriteFile(path.Join(targetPath, fileName), fileData, 0700); err != nil {
- return 0, err
- }
- if makeLinks {
- if err := os.Link(path.Join(targetPath, fileName), path.Join(targetPath, fileName+"-link")); err != nil {
- return 0, err
- }
- }
- }
- totalSize := numberOfFiles * len(fileData)
- return totalSize, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/testdata/broken.tar b/vendor/github.com/docker/docker/pkg/archive/testdata/broken.tar
deleted file mode 100644
index 8f10ea6..0000000
Binary files a/vendor/github.com/docker/docker/pkg/archive/testdata/broken.tar and /dev/null differ
diff --git a/vendor/github.com/docker/docker/pkg/archive/time_linux.go b/vendor/github.com/docker/docker/pkg/archive/time_linux.go
deleted file mode 100644
index 3448569..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/time_linux.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package archive
-
-import (
- "syscall"
- "time"
-)
-
-func timeToTimespec(time time.Time) (ts syscall.Timespec) {
- if time.IsZero() {
- // Return UTIME_OMIT special value
- ts.Sec = 0
- ts.Nsec = ((1 << 30) - 2)
- return
- }
- return syscall.NsecToTimespec(time.UnixNano())
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go b/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go
deleted file mode 100644
index e85aac0..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// +build !linux
-
-package archive
-
-import (
- "syscall"
- "time"
-)
-
-func timeToTimespec(time time.Time) (ts syscall.Timespec) {
- nsec := int64(0)
- if !time.IsZero() {
- nsec = time.UnixNano()
- }
- return syscall.NsecToTimespec(nsec)
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/utils_test.go b/vendor/github.com/docker/docker/pkg/archive/utils_test.go
deleted file mode 100644
index 9871903..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/utils_test.go
+++ /dev/null
@@ -1,166 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "time"
-)
-
-var testUntarFns = map[string]func(string, io.Reader) error{
- "untar": func(dest string, r io.Reader) error {
- return Untar(r, dest, nil)
- },
- "applylayer": func(dest string, r io.Reader) error {
- _, err := ApplyLayer(dest, Reader(r))
- return err
- },
-}
-
-// testBreakout is a helper function that, within the provided `tmpdir` directory,
-// creates a `victim` folder with a generated `hello` file in it.
-// `untar` extracts to a directory named `dest`, the tar file created from `headers`.
-//
-// Here are the tested scenarios:
-// - removed `victim` folder (write)
-// - removed files from `victim` folder (write)
-// - new files in `victim` folder (write)
-// - modified files in `victim` folder (write)
-// - file in `dest` with same content as `victim/hello` (read)
-//
-// When using testBreakout make sure you cover one of the scenarios listed above.
-func testBreakout(untarFn string, tmpdir string, headers []*tar.Header) error {
- tmpdir, err := ioutil.TempDir("", tmpdir)
- if err != nil {
- return err
- }
- defer os.RemoveAll(tmpdir)
-
- dest := filepath.Join(tmpdir, "dest")
- if err := os.Mkdir(dest, 0755); err != nil {
- return err
- }
-
- victim := filepath.Join(tmpdir, "victim")
- if err := os.Mkdir(victim, 0755); err != nil {
- return err
- }
- hello := filepath.Join(victim, "hello")
- helloData, err := time.Now().MarshalText()
- if err != nil {
- return err
- }
- if err := ioutil.WriteFile(hello, helloData, 0644); err != nil {
- return err
- }
- helloStat, err := os.Stat(hello)
- if err != nil {
- return err
- }
-
- reader, writer := io.Pipe()
- go func() {
- t := tar.NewWriter(writer)
- for _, hdr := range headers {
- t.WriteHeader(hdr)
- }
- t.Close()
- }()
-
- untar := testUntarFns[untarFn]
- if untar == nil {
- return fmt.Errorf("could not find untar function %q in testUntarFns", untarFn)
- }
- if err := untar(dest, reader); err != nil {
- if _, ok := err.(breakoutError); !ok {
- // If untar returns an error unrelated to an archive breakout,
- // then consider this an unexpected error and abort.
- return err
- }
- // Here, untar detected the breakout.
- // Let's move on verifying that indeed there was no breakout.
- fmt.Printf("breakoutError: %v\n", err)
- }
-
- // Check victim folder
- f, err := os.Open(victim)
- if err != nil {
- // codepath taken if victim folder was removed
- return fmt.Errorf("archive breakout: error reading %q: %v", victim, err)
- }
- defer f.Close()
-
- // Check contents of victim folder
- //
- // We are only interested in getting 2 files from the victim folder, because if all is well
- // we expect only one result, the `hello` file. If there is a second result, it cannot
- // hold the same name `hello` and we assume that a new file got created in the victim folder.
- // That is enough to detect an archive breakout.
- names, err := f.Readdirnames(2)
- if err != nil {
- // codepath taken if victim is not a folder
- return fmt.Errorf("archive breakout: error reading directory content of %q: %v", victim, err)
- }
- for _, name := range names {
- if name != "hello" {
- // codepath taken if new file was created in victim folder
- return fmt.Errorf("archive breakout: new file %q", name)
- }
- }
-
- // Check victim/hello
- f, err = os.Open(hello)
- if err != nil {
- // codepath taken if read permissions were removed
- return fmt.Errorf("archive breakout: could not lstat %q: %v", hello, err)
- }
- defer f.Close()
- b, err := ioutil.ReadAll(f)
- if err != nil {
- return err
- }
- fi, err := f.Stat()
- if err != nil {
- return err
- }
- if helloStat.IsDir() != fi.IsDir() ||
- // TODO: cannot check for fi.ModTime() change
- helloStat.Mode() != fi.Mode() ||
- helloStat.Size() != fi.Size() ||
- !bytes.Equal(helloData, b) {
- // codepath taken if hello has been modified
- return fmt.Errorf("archive breakout: file %q has been modified. Contents: expected=%q, got=%q. FileInfo: expected=%#v, got=%#v", hello, helloData, b, helloStat, fi)
- }
-
- // Check that nothing in dest/ has the same content as victim/hello.
- // Since victim/hello was generated with time.Now(), it is safe to assume
- // that any file whose content matches exactly victim/hello, managed somehow
- // to access victim/hello.
- return filepath.Walk(dest, func(path string, info os.FileInfo, err error) error {
- if info.IsDir() {
- if err != nil {
- // skip directory if error
- return filepath.SkipDir
- }
- // enter directory
- return nil
- }
- if err != nil {
- // skip file if error
- return nil
- }
- b, err := ioutil.ReadFile(path)
- if err != nil {
- // Houston, we have a problem. Aborting (space)walk.
- return err
- }
- if bytes.Equal(helloData, b) {
- return fmt.Errorf("archive breakout: file %q has been accessed via %q", hello, path)
- }
- return nil
- })
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go b/vendor/github.com/docker/docker/pkg/archive/whiteouts.go
deleted file mode 100644
index d20478a..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package archive
-
-// Whiteouts are files with a special meaning for the layered filesystem.
-// Docker uses AUFS whiteout files inside exported archives. In other
-// filesystems these files are generated/handled on tar creation/extraction.
-
-// WhiteoutPrefix prefix means file is a whiteout. If this is followed by a
-// filename this means that file has been removed from the base layer.
-const WhiteoutPrefix = ".wh."
-
-// WhiteoutMetaPrefix prefix means whiteout has a special meaning and is not
-// for removing an actual file. Normally these files are excluded from exported
-// archives.
-const WhiteoutMetaPrefix = WhiteoutPrefix + WhiteoutPrefix
-
-// WhiteoutLinkDir is a directory AUFS uses for storing hardlink links to other
-// layers. Normally these should not go into exported archives and all changed
-// hardlinks should be copied to the top layer.
-const WhiteoutLinkDir = WhiteoutMetaPrefix + "plnk"
-
-// WhiteoutOpaqueDir file means directory has been made opaque - meaning
-// readdir calls to this directory do not follow to lower layers.
-const WhiteoutOpaqueDir = WhiteoutMetaPrefix + ".opq"
diff --git a/vendor/github.com/docker/docker/pkg/archive/wrap.go b/vendor/github.com/docker/docker/pkg/archive/wrap.go
deleted file mode 100644
index dfb335c..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/wrap.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "bytes"
- "io/ioutil"
-)
-
-// Generate generates a new archive from the content provided
-// as input.
-//
-// `files` is a sequence of path/content pairs. A new file is
-// added to the archive for each pair.
-// If the last pair is incomplete, the file is created with an
-// empty content. For example:
-//
-// Generate("foo.txt", "hello world", "emptyfile")
-//
-// The above call will return an archive with 2 files:
-// * ./foo.txt with content "hello world"
-// * ./empty with empty content
-//
-// FIXME: stream content instead of buffering
-// FIXME: specify permissions and other archive metadata
-func Generate(input ...string) (Archive, error) {
- files := parseStringPairs(input...)
- buf := new(bytes.Buffer)
- tw := tar.NewWriter(buf)
- for _, file := range files {
- name, content := file[0], file[1]
- hdr := &tar.Header{
- Name: name,
- Size: int64(len(content)),
- }
- if err := tw.WriteHeader(hdr); err != nil {
- return nil, err
- }
- if _, err := tw.Write([]byte(content)); err != nil {
- return nil, err
- }
- }
- if err := tw.Close(); err != nil {
- return nil, err
- }
- return ioutil.NopCloser(buf), nil
-}
-
-func parseStringPairs(input ...string) (output [][2]string) {
- output = make([][2]string, 0, len(input)/2+1)
- for i := 0; i < len(input); i += 2 {
- var pair [2]string
- pair[0] = input[i]
- if i+1 < len(input) {
- pair[1] = input[i+1]
- }
- output = append(output, pair)
- }
- return
-}
diff --git a/vendor/github.com/docker/docker/pkg/archive/wrap_test.go b/vendor/github.com/docker/docker/pkg/archive/wrap_test.go
deleted file mode 100644
index 46ab366..0000000
--- a/vendor/github.com/docker/docker/pkg/archive/wrap_test.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package archive
-
-import (
- "archive/tar"
- "bytes"
- "io"
- "testing"
-)
-
-func TestGenerateEmptyFile(t *testing.T) {
- archive, err := Generate("emptyFile")
- if err != nil {
- t.Fatal(err)
- }
- if archive == nil {
- t.Fatal("The generated archive should not be nil.")
- }
-
- expectedFiles := [][]string{
- {"emptyFile", ""},
- }
-
- tr := tar.NewReader(archive)
- actualFiles := make([][]string, 0, 10)
- i := 0
- for {
- hdr, err := tr.Next()
- if err == io.EOF {
- break
- }
- if err != nil {
- t.Fatal(err)
- }
- buf := new(bytes.Buffer)
- buf.ReadFrom(tr)
- content := buf.String()
- actualFiles = append(actualFiles, []string{hdr.Name, content})
- i++
- }
- if len(actualFiles) != len(expectedFiles) {
- t.Fatalf("Number of expected file %d, got %d.", len(expectedFiles), len(actualFiles))
- }
- for i := 0; i < len(expectedFiles); i++ {
- actual := actualFiles[i]
- expected := expectedFiles[i]
- if actual[0] != expected[0] {
- t.Fatalf("Expected name '%s', Actual name '%s'", expected[0], actual[0])
- }
- if actual[1] != expected[1] {
- t.Fatalf("Expected content '%s', Actual content '%s'", expected[1], actual[1])
- }
- }
-}
-
-func TestGenerateWithContent(t *testing.T) {
- archive, err := Generate("file", "content")
- if err != nil {
- t.Fatal(err)
- }
- if archive == nil {
- t.Fatal("The generated archive should not be nil.")
- }
-
- expectedFiles := [][]string{
- {"file", "content"},
- }
-
- tr := tar.NewReader(archive)
- actualFiles := make([][]string, 0, 10)
- i := 0
- for {
- hdr, err := tr.Next()
- if err == io.EOF {
- break
- }
- if err != nil {
- t.Fatal(err)
- }
- buf := new(bytes.Buffer)
- buf.ReadFrom(tr)
- content := buf.String()
- actualFiles = append(actualFiles, []string{hdr.Name, content})
- i++
- }
- if len(actualFiles) != len(expectedFiles) {
- t.Fatalf("Number of expected file %d, got %d.", len(expectedFiles), len(actualFiles))
- }
- for i := 0; i < len(expectedFiles); i++ {
- actual := actualFiles[i]
- expected := expectedFiles[i]
- if actual[0] != expected[0] {
- t.Fatalf("Expected name '%s', Actual name '%s'", expected[0], actual[0])
- }
- if actual[1] != expected[1] {
- t.Fatalf("Expected content '%s', Actual content '%s'", expected[1], actual[1])
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils.go
deleted file mode 100644
index 763d8d2..0000000
--- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils.go
+++ /dev/null
@@ -1,283 +0,0 @@
-package fileutils
-
-import (
- "errors"
- "fmt"
- "io"
- "os"
- "path/filepath"
- "regexp"
- "strings"
- "text/scanner"
-
- "github.com/Sirupsen/logrus"
-)
-
-// exclusion returns true if the specified pattern is an exclusion
-func exclusion(pattern string) bool {
- return pattern[0] == '!'
-}
-
-// empty returns true if the specified pattern is empty
-func empty(pattern string) bool {
- return pattern == ""
-}
-
-// CleanPatterns takes a slice of patterns returns a new
-// slice of patterns cleaned with filepath.Clean, stripped
-// of any empty patterns and lets the caller know whether the
-// slice contains any exception patterns (prefixed with !).
-func CleanPatterns(patterns []string) ([]string, [][]string, bool, error) {
- // Loop over exclusion patterns and:
- // 1. Clean them up.
- // 2. Indicate whether we are dealing with any exception rules.
- // 3. Error if we see a single exclusion marker on it's own (!).
- cleanedPatterns := []string{}
- patternDirs := [][]string{}
- exceptions := false
- for _, pattern := range patterns {
- // Eliminate leading and trailing whitespace.
- pattern = strings.TrimSpace(pattern)
- if empty(pattern) {
- continue
- }
- if exclusion(pattern) {
- if len(pattern) == 1 {
- return nil, nil, false, errors.New("Illegal exclusion pattern: !")
- }
- exceptions = true
- }
- pattern = filepath.Clean(pattern)
- cleanedPatterns = append(cleanedPatterns, pattern)
- if exclusion(pattern) {
- pattern = pattern[1:]
- }
- patternDirs = append(patternDirs, strings.Split(pattern, string(os.PathSeparator)))
- }
-
- return cleanedPatterns, patternDirs, exceptions, nil
-}
-
-// Matches returns true if file matches any of the patterns
-// and isn't excluded by any of the subsequent patterns.
-func Matches(file string, patterns []string) (bool, error) {
- file = filepath.Clean(file)
-
- if file == "." {
- // Don't let them exclude everything, kind of silly.
- return false, nil
- }
-
- patterns, patDirs, _, err := CleanPatterns(patterns)
- if err != nil {
- return false, err
- }
-
- return OptimizedMatches(file, patterns, patDirs)
-}
-
-// OptimizedMatches is basically the same as fileutils.Matches() but optimized for archive.go.
-// It will assume that the inputs have been preprocessed and therefore the function
-// doesn't need to do as much error checking and clean-up. This was done to avoid
-// repeating these steps on each file being checked during the archive process.
-// The more generic fileutils.Matches() can't make these assumptions.
-func OptimizedMatches(file string, patterns []string, patDirs [][]string) (bool, error) {
- matched := false
- file = filepath.FromSlash(file)
- parentPath := filepath.Dir(file)
- parentPathDirs := strings.Split(parentPath, string(os.PathSeparator))
-
- for i, pattern := range patterns {
- negative := false
-
- if exclusion(pattern) {
- negative = true
- pattern = pattern[1:]
- }
-
- match, err := regexpMatch(pattern, file)
- if err != nil {
- return false, fmt.Errorf("Error in pattern (%s): %s", pattern, err)
- }
-
- if !match && parentPath != "." {
- // Check to see if the pattern matches one of our parent dirs.
- if len(patDirs[i]) <= len(parentPathDirs) {
- match, _ = regexpMatch(strings.Join(patDirs[i], string(os.PathSeparator)),
- strings.Join(parentPathDirs[:len(patDirs[i])], string(os.PathSeparator)))
- }
- }
-
- if match {
- matched = !negative
- }
- }
-
- if matched {
- logrus.Debugf("Skipping excluded path: %s", file)
- }
-
- return matched, nil
-}
-
-// regexpMatch tries to match the logic of filepath.Match but
-// does so using regexp logic. We do this so that we can expand the
-// wildcard set to include other things, like "**" to mean any number
-// of directories. This means that we should be backwards compatible
-// with filepath.Match(). We'll end up supporting more stuff, due to
-// the fact that we're using regexp, but that's ok - it does no harm.
-//
-// As per the comment in golangs filepath.Match, on Windows, escaping
-// is disabled. Instead, '\\' is treated as path separator.
-func regexpMatch(pattern, path string) (bool, error) {
- regStr := "^"
-
- // Do some syntax checking on the pattern.
- // filepath's Match() has some really weird rules that are inconsistent
- // so instead of trying to dup their logic, just call Match() for its
- // error state and if there is an error in the pattern return it.
- // If this becomes an issue we can remove this since its really only
- // needed in the error (syntax) case - which isn't really critical.
- if _, err := filepath.Match(pattern, path); err != nil {
- return false, err
- }
-
- // Go through the pattern and convert it to a regexp.
- // We use a scanner so we can support utf-8 chars.
- var scan scanner.Scanner
- scan.Init(strings.NewReader(pattern))
-
- sl := string(os.PathSeparator)
- escSL := sl
- if sl == `\` {
- escSL += `\`
- }
-
- for scan.Peek() != scanner.EOF {
- ch := scan.Next()
-
- if ch == '*' {
- if scan.Peek() == '*' {
- // is some flavor of "**"
- scan.Next()
-
- if scan.Peek() == scanner.EOF {
- // is "**EOF" - to align with .gitignore just accept all
- regStr += ".*"
- } else {
- // is "**"
- regStr += "((.*" + escSL + ")|([^" + escSL + "]*))"
- }
-
- // Treat **/ as ** so eat the "/"
- if string(scan.Peek()) == sl {
- scan.Next()
- }
- } else {
- // is "*" so map it to anything but "/"
- regStr += "[^" + escSL + "]*"
- }
- } else if ch == '?' {
- // "?" is any char except "/"
- regStr += "[^" + escSL + "]"
- } else if strings.Index(".$", string(ch)) != -1 {
- // Escape some regexp special chars that have no meaning
- // in golang's filepath.Match
- regStr += `\` + string(ch)
- } else if ch == '\\' {
- // escape next char. Note that a trailing \ in the pattern
- // will be left alone (but need to escape it)
- if sl == `\` {
- // On windows map "\" to "\\", meaning an escaped backslash,
- // and then just continue because filepath.Match on
- // Windows doesn't allow escaping at all
- regStr += escSL
- continue
- }
- if scan.Peek() != scanner.EOF {
- regStr += `\` + string(scan.Next())
- } else {
- regStr += `\`
- }
- } else {
- regStr += string(ch)
- }
- }
-
- regStr += "$"
-
- res, err := regexp.MatchString(regStr, path)
-
- // Map regexp's error to filepath's so no one knows we're not using filepath
- if err != nil {
- err = filepath.ErrBadPattern
- }
-
- return res, err
-}
-
-// CopyFile copies from src to dst until either EOF is reached
-// on src or an error occurs. It verifies src exists and removes
-// the dst if it exists.
-func CopyFile(src, dst string) (int64, error) {
- cleanSrc := filepath.Clean(src)
- cleanDst := filepath.Clean(dst)
- if cleanSrc == cleanDst {
- return 0, nil
- }
- sf, err := os.Open(cleanSrc)
- if err != nil {
- return 0, err
- }
- defer sf.Close()
- if err := os.Remove(cleanDst); err != nil && !os.IsNotExist(err) {
- return 0, err
- }
- df, err := os.Create(cleanDst)
- if err != nil {
- return 0, err
- }
- defer df.Close()
- return io.Copy(df, sf)
-}
-
-// ReadSymlinkedDirectory returns the target directory of a symlink.
-// The target of the symbolic link may not be a file.
-func ReadSymlinkedDirectory(path string) (string, error) {
- var realPath string
- var err error
- if realPath, err = filepath.Abs(path); err != nil {
- return "", fmt.Errorf("unable to get absolute path for %s: %s", path, err)
- }
- if realPath, err = filepath.EvalSymlinks(realPath); err != nil {
- return "", fmt.Errorf("failed to canonicalise path for %s: %s", path, err)
- }
- realPathInfo, err := os.Stat(realPath)
- if err != nil {
- return "", fmt.Errorf("failed to stat target '%s' of '%s': %s", realPath, path, err)
- }
- if !realPathInfo.Mode().IsDir() {
- return "", fmt.Errorf("canonical path points to a file '%s'", realPath)
- }
- return realPath, nil
-}
-
-// CreateIfNotExists creates a file or a directory only if it does not already exist.
-func CreateIfNotExists(path string, isDir bool) error {
- if _, err := os.Stat(path); err != nil {
- if os.IsNotExist(err) {
- if isDir {
- return os.MkdirAll(path, 0755)
- }
- if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
- return err
- }
- f, err := os.OpenFile(path, os.O_CREATE, 0755)
- if err != nil {
- return err
- }
- f.Close()
- }
- }
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_solaris.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_solaris.go
deleted file mode 100644
index 0f2cb7a..0000000
--- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_solaris.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package fileutils
-
-// GetTotalUsedFds Returns the number of used File Descriptors.
-// On Solaris these limits are per process and not systemwide
-func GetTotalUsedFds() int {
- return -1
-}
diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_test.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_test.go
deleted file mode 100644
index 6df1be8..0000000
--- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_test.go
+++ /dev/null
@@ -1,585 +0,0 @@
-package fileutils
-
-import (
- "io/ioutil"
- "os"
- "path"
- "path/filepath"
- "runtime"
- "strings"
- "testing"
-)
-
-// CopyFile with invalid src
-func TestCopyFileWithInvalidSrc(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
- defer os.RemoveAll(tempFolder)
- if err != nil {
- t.Fatal(err)
- }
- bytes, err := CopyFile("/invalid/file/path", path.Join(tempFolder, "dest"))
- if err == nil {
- t.Fatal("Should have fail to copy an invalid src file")
- }
- if bytes != 0 {
- t.Fatal("Should have written 0 bytes")
- }
-
-}
-
-// CopyFile with invalid dest
-func TestCopyFileWithInvalidDest(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
- defer os.RemoveAll(tempFolder)
- if err != nil {
- t.Fatal(err)
- }
- src := path.Join(tempFolder, "file")
- err = ioutil.WriteFile(src, []byte("content"), 0740)
- if err != nil {
- t.Fatal(err)
- }
- bytes, err := CopyFile(src, path.Join(tempFolder, "/invalid/dest/path"))
- if err == nil {
- t.Fatal("Should have fail to copy an invalid src file")
- }
- if bytes != 0 {
- t.Fatal("Should have written 0 bytes")
- }
-
-}
-
-// CopyFile with same src and dest
-func TestCopyFileWithSameSrcAndDest(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
- defer os.RemoveAll(tempFolder)
- if err != nil {
- t.Fatal(err)
- }
- file := path.Join(tempFolder, "file")
- err = ioutil.WriteFile(file, []byte("content"), 0740)
- if err != nil {
- t.Fatal(err)
- }
- bytes, err := CopyFile(file, file)
- if err != nil {
- t.Fatal(err)
- }
- if bytes != 0 {
- t.Fatal("Should have written 0 bytes as it is the same file.")
- }
-}
-
-// CopyFile with same src and dest but path is different and not clean
-func TestCopyFileWithSameSrcAndDestWithPathNameDifferent(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
- defer os.RemoveAll(tempFolder)
- if err != nil {
- t.Fatal(err)
- }
- testFolder := path.Join(tempFolder, "test")
- err = os.MkdirAll(testFolder, 0740)
- if err != nil {
- t.Fatal(err)
- }
- file := path.Join(testFolder, "file")
- sameFile := testFolder + "/../test/file"
- err = ioutil.WriteFile(file, []byte("content"), 0740)
- if err != nil {
- t.Fatal(err)
- }
- bytes, err := CopyFile(file, sameFile)
- if err != nil {
- t.Fatal(err)
- }
- if bytes != 0 {
- t.Fatal("Should have written 0 bytes as it is the same file.")
- }
-}
-
-func TestCopyFile(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
- defer os.RemoveAll(tempFolder)
- if err != nil {
- t.Fatal(err)
- }
- src := path.Join(tempFolder, "src")
- dest := path.Join(tempFolder, "dest")
- ioutil.WriteFile(src, []byte("content"), 0777)
- ioutil.WriteFile(dest, []byte("destContent"), 0777)
- bytes, err := CopyFile(src, dest)
- if err != nil {
- t.Fatal(err)
- }
- if bytes != 7 {
- t.Fatalf("Should have written %d bytes but wrote %d", 7, bytes)
- }
- actual, err := ioutil.ReadFile(dest)
- if err != nil {
- t.Fatal(err)
- }
- if string(actual) != "content" {
- t.Fatalf("Dest content was '%s', expected '%s'", string(actual), "content")
- }
-}
-
-// Reading a symlink to a directory must return the directory
-func TestReadSymlinkedDirectoryExistingDirectory(t *testing.T) {
- // TODO Windows: Port this test
- if runtime.GOOS == "windows" {
- t.Skip("Needs porting to Windows")
- }
- var err error
- if err = os.Mkdir("/tmp/testReadSymlinkToExistingDirectory", 0777); err != nil {
- t.Errorf("failed to create directory: %s", err)
- }
-
- if err = os.Symlink("/tmp/testReadSymlinkToExistingDirectory", "/tmp/dirLinkTest"); err != nil {
- t.Errorf("failed to create symlink: %s", err)
- }
-
- var path string
- if path, err = ReadSymlinkedDirectory("/tmp/dirLinkTest"); err != nil {
- t.Fatalf("failed to read symlink to directory: %s", err)
- }
-
- if path != "/tmp/testReadSymlinkToExistingDirectory" {
- t.Fatalf("symlink returned unexpected directory: %s", path)
- }
-
- if err = os.Remove("/tmp/testReadSymlinkToExistingDirectory"); err != nil {
- t.Errorf("failed to remove temporary directory: %s", err)
- }
-
- if err = os.Remove("/tmp/dirLinkTest"); err != nil {
- t.Errorf("failed to remove symlink: %s", err)
- }
-}
-
-// Reading a non-existing symlink must fail
-func TestReadSymlinkedDirectoryNonExistingSymlink(t *testing.T) {
- var path string
- var err error
- if path, err = ReadSymlinkedDirectory("/tmp/test/foo/Non/ExistingPath"); err == nil {
- t.Fatalf("error expected for non-existing symlink")
- }
-
- if path != "" {
- t.Fatalf("expected empty path, but '%s' was returned", path)
- }
-}
-
-// Reading a symlink to a file must fail
-func TestReadSymlinkedDirectoryToFile(t *testing.T) {
- // TODO Windows: Port this test
- if runtime.GOOS == "windows" {
- t.Skip("Needs porting to Windows")
- }
- var err error
- var file *os.File
-
- if file, err = os.Create("/tmp/testReadSymlinkToFile"); err != nil {
- t.Fatalf("failed to create file: %s", err)
- }
-
- file.Close()
-
- if err = os.Symlink("/tmp/testReadSymlinkToFile", "/tmp/fileLinkTest"); err != nil {
- t.Errorf("failed to create symlink: %s", err)
- }
-
- var path string
- if path, err = ReadSymlinkedDirectory("/tmp/fileLinkTest"); err == nil {
- t.Fatalf("ReadSymlinkedDirectory on a symlink to a file should've failed")
- }
-
- if path != "" {
- t.Fatalf("path should've been empty: %s", path)
- }
-
- if err = os.Remove("/tmp/testReadSymlinkToFile"); err != nil {
- t.Errorf("failed to remove file: %s", err)
- }
-
- if err = os.Remove("/tmp/fileLinkTest"); err != nil {
- t.Errorf("failed to remove symlink: %s", err)
- }
-}
-
-func TestWildcardMatches(t *testing.T) {
- match, _ := Matches("fileutils.go", []string{"*"})
- if match != true {
- t.Errorf("failed to get a wildcard match, got %v", match)
- }
-}
-
-// A simple pattern match should return true.
-func TestPatternMatches(t *testing.T) {
- match, _ := Matches("fileutils.go", []string{"*.go"})
- if match != true {
- t.Errorf("failed to get a match, got %v", match)
- }
-}
-
-// An exclusion followed by an inclusion should return true.
-func TestExclusionPatternMatchesPatternBefore(t *testing.T) {
- match, _ := Matches("fileutils.go", []string{"!fileutils.go", "*.go"})
- if match != true {
- t.Errorf("failed to get true match on exclusion pattern, got %v", match)
- }
-}
-
-// A folder pattern followed by an exception should return false.
-func TestPatternMatchesFolderExclusions(t *testing.T) {
- match, _ := Matches("docs/README.md", []string{"docs", "!docs/README.md"})
- if match != false {
- t.Errorf("failed to get a false match on exclusion pattern, got %v", match)
- }
-}
-
-// A folder pattern followed by an exception should return false.
-func TestPatternMatchesFolderWithSlashExclusions(t *testing.T) {
- match, _ := Matches("docs/README.md", []string{"docs/", "!docs/README.md"})
- if match != false {
- t.Errorf("failed to get a false match on exclusion pattern, got %v", match)
- }
-}
-
-// A folder pattern followed by an exception should return false.
-func TestPatternMatchesFolderWildcardExclusions(t *testing.T) {
- match, _ := Matches("docs/README.md", []string{"docs/*", "!docs/README.md"})
- if match != false {
- t.Errorf("failed to get a false match on exclusion pattern, got %v", match)
- }
-}
-
-// A pattern followed by an exclusion should return false.
-func TestExclusionPatternMatchesPatternAfter(t *testing.T) {
- match, _ := Matches("fileutils.go", []string{"*.go", "!fileutils.go"})
- if match != false {
- t.Errorf("failed to get false match on exclusion pattern, got %v", match)
- }
-}
-
-// A filename evaluating to . should return false.
-func TestExclusionPatternMatchesWholeDirectory(t *testing.T) {
- match, _ := Matches(".", []string{"*.go"})
- if match != false {
- t.Errorf("failed to get false match on ., got %v", match)
- }
-}
-
-// A single ! pattern should return an error.
-func TestSingleExclamationError(t *testing.T) {
- _, err := Matches("fileutils.go", []string{"!"})
- if err == nil {
- t.Errorf("failed to get an error for a single exclamation point, got %v", err)
- }
-}
-
-// A string preceded with a ! should return true from Exclusion.
-func TestExclusion(t *testing.T) {
- exclusion := exclusion("!")
- if !exclusion {
- t.Errorf("failed to get true for a single !, got %v", exclusion)
- }
-}
-
-// Matches with no patterns
-func TestMatchesWithNoPatterns(t *testing.T) {
- matches, err := Matches("/any/path/there", []string{})
- if err != nil {
- t.Fatal(err)
- }
- if matches {
- t.Fatalf("Should not have match anything")
- }
-}
-
-// Matches with malformed patterns
-func TestMatchesWithMalformedPatterns(t *testing.T) {
- matches, err := Matches("/any/path/there", []string{"["})
- if err == nil {
- t.Fatal("Should have failed because of a malformed syntax in the pattern")
- }
- if matches {
- t.Fatalf("Should not have match anything")
- }
-}
-
-// Test lots of variants of patterns & strings
-func TestMatches(t *testing.T) {
- // TODO Windows: Port this test
- if runtime.GOOS == "windows" {
- t.Skip("Needs porting to Windows")
- }
- tests := []struct {
- pattern string
- text string
- pass bool
- }{
- {"**", "file", true},
- {"**", "file/", true},
- {"**/", "file", true}, // weird one
- {"**/", "file/", true},
- {"**", "/", true},
- {"**/", "/", true},
- {"**", "dir/file", true},
- {"**/", "dir/file", false},
- {"**", "dir/file/", true},
- {"**/", "dir/file/", true},
- {"**/**", "dir/file", true},
- {"**/**", "dir/file/", true},
- {"dir/**", "dir/file", true},
- {"dir/**", "dir/file/", true},
- {"dir/**", "dir/dir2/file", true},
- {"dir/**", "dir/dir2/file/", true},
- {"**/dir2/*", "dir/dir2/file", true},
- {"**/dir2/*", "dir/dir2/file/", false},
- {"**/dir2/**", "dir/dir2/dir3/file", true},
- {"**/dir2/**", "dir/dir2/dir3/file/", true},
- {"**file", "file", true},
- {"**file", "dir/file", true},
- {"**/file", "dir/file", true},
- {"**file", "dir/dir/file", true},
- {"**/file", "dir/dir/file", true},
- {"**/file*", "dir/dir/file", true},
- {"**/file*", "dir/dir/file.txt", true},
- {"**/file*txt", "dir/dir/file.txt", true},
- {"**/file*.txt", "dir/dir/file.txt", true},
- {"**/file*.txt*", "dir/dir/file.txt", true},
- {"**/**/*.txt", "dir/dir/file.txt", true},
- {"**/**/*.txt2", "dir/dir/file.txt", false},
- {"**/*.txt", "file.txt", true},
- {"**/**/*.txt", "file.txt", true},
- {"a**/*.txt", "a/file.txt", true},
- {"a**/*.txt", "a/dir/file.txt", true},
- {"a**/*.txt", "a/dir/dir/file.txt", true},
- {"a/*.txt", "a/dir/file.txt", false},
- {"a/*.txt", "a/file.txt", true},
- {"a/*.txt**", "a/file.txt", true},
- {"a[b-d]e", "ae", false},
- {"a[b-d]e", "ace", true},
- {"a[b-d]e", "aae", false},
- {"a[^b-d]e", "aze", true},
- {".*", ".foo", true},
- {".*", "foo", false},
- {"abc.def", "abcdef", false},
- {"abc.def", "abc.def", true},
- {"abc.def", "abcZdef", false},
- {"abc?def", "abcZdef", true},
- {"abc?def", "abcdef", false},
- {"a\\*b", "a*b", true},
- {"a\\", "a", false},
- {"a\\", "a\\", false},
- {"a\\\\", "a\\", true},
- {"**/foo/bar", "foo/bar", true},
- {"**/foo/bar", "dir/foo/bar", true},
- {"**/foo/bar", "dir/dir2/foo/bar", true},
- {"abc/**", "abc", false},
- {"abc/**", "abc/def", true},
- {"abc/**", "abc/def/ghi", true},
- }
-
- for _, test := range tests {
- res, _ := regexpMatch(test.pattern, test.text)
- if res != test.pass {
- t.Fatalf("Failed: %v - res:%v", test, res)
- }
- }
-}
-
-// An empty string should return true from Empty.
-func TestEmpty(t *testing.T) {
- empty := empty("")
- if !empty {
- t.Errorf("failed to get true for an empty string, got %v", empty)
- }
-}
-
-func TestCleanPatterns(t *testing.T) {
- cleaned, _, _, _ := CleanPatterns([]string{"docs", "config"})
- if len(cleaned) != 2 {
- t.Errorf("expected 2 element slice, got %v", len(cleaned))
- }
-}
-
-func TestCleanPatternsStripEmptyPatterns(t *testing.T) {
- cleaned, _, _, _ := CleanPatterns([]string{"docs", "config", ""})
- if len(cleaned) != 2 {
- t.Errorf("expected 2 element slice, got %v", len(cleaned))
- }
-}
-
-func TestCleanPatternsExceptionFlag(t *testing.T) {
- _, _, exceptions, _ := CleanPatterns([]string{"docs", "!docs/README.md"})
- if !exceptions {
- t.Errorf("expected exceptions to be true, got %v", exceptions)
- }
-}
-
-func TestCleanPatternsLeadingSpaceTrimmed(t *testing.T) {
- _, _, exceptions, _ := CleanPatterns([]string{"docs", " !docs/README.md"})
- if !exceptions {
- t.Errorf("expected exceptions to be true, got %v", exceptions)
- }
-}
-
-func TestCleanPatternsTrailingSpaceTrimmed(t *testing.T) {
- _, _, exceptions, _ := CleanPatterns([]string{"docs", "!docs/README.md "})
- if !exceptions {
- t.Errorf("expected exceptions to be true, got %v", exceptions)
- }
-}
-
-func TestCleanPatternsErrorSingleException(t *testing.T) {
- _, _, _, err := CleanPatterns([]string{"!"})
- if err == nil {
- t.Errorf("expected error on single exclamation point, got %v", err)
- }
-}
-
-func TestCleanPatternsFolderSplit(t *testing.T) {
- _, dirs, _, _ := CleanPatterns([]string{"docs/config/CONFIG.md"})
- if dirs[0][0] != "docs" {
- t.Errorf("expected first element in dirs slice to be docs, got %v", dirs[0][1])
- }
- if dirs[0][1] != "config" {
- t.Errorf("expected first element in dirs slice to be config, got %v", dirs[0][1])
- }
-}
-
-func TestCreateIfNotExistsDir(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempFolder)
-
- folderToCreate := filepath.Join(tempFolder, "tocreate")
-
- if err := CreateIfNotExists(folderToCreate, true); err != nil {
- t.Fatal(err)
- }
- fileinfo, err := os.Stat(folderToCreate)
- if err != nil {
- t.Fatalf("Should have create a folder, got %v", err)
- }
-
- if !fileinfo.IsDir() {
- t.Fatalf("Should have been a dir, seems it's not")
- }
-}
-
-func TestCreateIfNotExistsFile(t *testing.T) {
- tempFolder, err := ioutil.TempDir("", "docker-fileutils-test")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempFolder)
-
- fileToCreate := filepath.Join(tempFolder, "file/to/create")
-
- if err := CreateIfNotExists(fileToCreate, false); err != nil {
- t.Fatal(err)
- }
- fileinfo, err := os.Stat(fileToCreate)
- if err != nil {
- t.Fatalf("Should have create a file, got %v", err)
- }
-
- if fileinfo.IsDir() {
- t.Fatalf("Should have been a file, seems it's not")
- }
-}
-
-// These matchTests are stolen from go's filepath Match tests.
-type matchTest struct {
- pattern, s string
- match bool
- err error
-}
-
-var matchTests = []matchTest{
- {"abc", "abc", true, nil},
- {"*", "abc", true, nil},
- {"*c", "abc", true, nil},
- {"a*", "a", true, nil},
- {"a*", "abc", true, nil},
- {"a*", "ab/c", false, nil},
- {"a*/b", "abc/b", true, nil},
- {"a*/b", "a/c/b", false, nil},
- {"a*b*c*d*e*/f", "axbxcxdxe/f", true, nil},
- {"a*b*c*d*e*/f", "axbxcxdxexxx/f", true, nil},
- {"a*b*c*d*e*/f", "axbxcxdxe/xxx/f", false, nil},
- {"a*b*c*d*e*/f", "axbxcxdxexxx/fff", false, nil},
- {"a*b?c*x", "abxbbxdbxebxczzx", true, nil},
- {"a*b?c*x", "abxbbxdbxebxczzy", false, nil},
- {"ab[c]", "abc", true, nil},
- {"ab[b-d]", "abc", true, nil},
- {"ab[e-g]", "abc", false, nil},
- {"ab[^c]", "abc", false, nil},
- {"ab[^b-d]", "abc", false, nil},
- {"ab[^e-g]", "abc", true, nil},
- {"a\\*b", "a*b", true, nil},
- {"a\\*b", "ab", false, nil},
- {"a?b", "a☺b", true, nil},
- {"a[^a]b", "a☺b", true, nil},
- {"a???b", "a☺b", false, nil},
- {"a[^a][^a][^a]b", "a☺b", false, nil},
- {"[a-ζ]*", "α", true, nil},
- {"*[a-ζ]", "A", false, nil},
- {"a?b", "a/b", false, nil},
- {"a*b", "a/b", false, nil},
- {"[\\]a]", "]", true, nil},
- {"[\\-]", "-", true, nil},
- {"[x\\-]", "x", true, nil},
- {"[x\\-]", "-", true, nil},
- {"[x\\-]", "z", false, nil},
- {"[\\-x]", "x", true, nil},
- {"[\\-x]", "-", true, nil},
- {"[\\-x]", "a", false, nil},
- {"[]a]", "]", false, filepath.ErrBadPattern},
- {"[-]", "-", false, filepath.ErrBadPattern},
- {"[x-]", "x", false, filepath.ErrBadPattern},
- {"[x-]", "-", false, filepath.ErrBadPattern},
- {"[x-]", "z", false, filepath.ErrBadPattern},
- {"[-x]", "x", false, filepath.ErrBadPattern},
- {"[-x]", "-", false, filepath.ErrBadPattern},
- {"[-x]", "a", false, filepath.ErrBadPattern},
- {"\\", "a", false, filepath.ErrBadPattern},
- {"[a-b-c]", "a", false, filepath.ErrBadPattern},
- {"[", "a", false, filepath.ErrBadPattern},
- {"[^", "a", false, filepath.ErrBadPattern},
- {"[^bc", "a", false, filepath.ErrBadPattern},
- {"a[", "a", false, filepath.ErrBadPattern}, // was nil but IMO its wrong
- {"a[", "ab", false, filepath.ErrBadPattern},
- {"*x", "xxx", true, nil},
-}
-
-func errp(e error) string {
- if e == nil {
- return ""
- }
- return e.Error()
-}
-
-// TestMatch test's our version of filepath.Match, called regexpMatch.
-func TestMatch(t *testing.T) {
- for _, tt := range matchTests {
- pattern := tt.pattern
- s := tt.s
- if runtime.GOOS == "windows" {
- if strings.Index(pattern, "\\") >= 0 {
- // no escape allowed on windows.
- continue
- }
- pattern = filepath.Clean(pattern)
- s = filepath.Clean(s)
- }
- ok, err := regexpMatch(pattern, s)
- if ok != tt.match || err != tt.err {
- t.Fatalf("Match(%#q, %#q) = %v, %q want %v, %q", pattern, s, ok, errp(err), tt.match, errp(tt.err))
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_unix.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_unix.go
deleted file mode 100644
index d5c3abf..0000000
--- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_unix.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build linux freebsd
-
-package fileutils
-
-import (
- "fmt"
- "io/ioutil"
- "os"
-
- "github.com/Sirupsen/logrus"
-)
-
-// GetTotalUsedFds Returns the number of used File Descriptors by
-// reading it via /proc filesystem.
-func GetTotalUsedFds() int {
- if fds, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/fd", os.Getpid())); err != nil {
- logrus.Errorf("Error opening /proc/%d/fd: %s", os.Getpid(), err)
- } else {
- return len(fds)
- }
- return -1
-}
diff --git a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_windows.go b/vendor/github.com/docker/docker/pkg/fileutils/fileutils_windows.go
deleted file mode 100644
index 5ec21ca..0000000
--- a/vendor/github.com/docker/docker/pkg/fileutils/fileutils_windows.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package fileutils
-
-// GetTotalUsedFds Returns the number of used File Descriptors. Not supported
-// on Windows.
-func GetTotalUsedFds() int {
- return -1
-}
diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir.go b/vendor/github.com/docker/docker/pkg/homedir/homedir.go
deleted file mode 100644
index 8154e83..0000000
--- a/vendor/github.com/docker/docker/pkg/homedir/homedir.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package homedir
-
-import (
- "os"
- "runtime"
-
- "github.com/opencontainers/runc/libcontainer/user"
-)
-
-// Key returns the env var name for the user's home dir based on
-// the platform being run on
-func Key() string {
- if runtime.GOOS == "windows" {
- return "USERPROFILE"
- }
- return "HOME"
-}
-
-// Get returns the home directory of the current user with the help of
-// environment variables depending on the target operating system.
-// Returned path should be used with "path/filepath" to form new paths.
-func Get() string {
- home := os.Getenv(Key())
- if home == "" && runtime.GOOS != "windows" {
- if u, err := user.CurrentUser(); err == nil {
- return u.Home
- }
- }
- return home
-}
-
-// GetShortcutString returns the string that is shortcut to user's home directory
-// in the native shell of the platform running on.
-func GetShortcutString() string {
- if runtime.GOOS == "windows" {
- return "%USERPROFILE%" // be careful while using in format functions
- }
- return "~"
-}
diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_test.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_test.go
deleted file mode 100644
index 7a95cb2..0000000
--- a/vendor/github.com/docker/docker/pkg/homedir/homedir_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package homedir
-
-import (
- "path/filepath"
- "testing"
-)
-
-func TestGet(t *testing.T) {
- home := Get()
- if home == "" {
- t.Fatal("returned home directory is empty")
- }
-
- if !filepath.IsAbs(home) {
- t.Fatalf("returned path is not absolute: %s", home)
- }
-}
-
-func TestGetShortcutString(t *testing.T) {
- shortcut := GetShortcutString()
- if shortcut == "" {
- t.Fatal("returned shortcut string is empty")
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools.go b/vendor/github.com/docker/docker/pkg/idtools/idtools.go
deleted file mode 100644
index 6bca466..0000000
--- a/vendor/github.com/docker/docker/pkg/idtools/idtools.go
+++ /dev/null
@@ -1,197 +0,0 @@
-package idtools
-
-import (
- "bufio"
- "fmt"
- "os"
- "sort"
- "strconv"
- "strings"
-)
-
-// IDMap contains a single entry for user namespace range remapping. An array
-// of IDMap entries represents the structure that will be provided to the Linux
-// kernel for creating a user namespace.
-type IDMap struct {
- ContainerID int `json:"container_id"`
- HostID int `json:"host_id"`
- Size int `json:"size"`
-}
-
-type subIDRange struct {
- Start int
- Length int
-}
-
-type ranges []subIDRange
-
-func (e ranges) Len() int { return len(e) }
-func (e ranges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
-func (e ranges) Less(i, j int) bool { return e[i].Start < e[j].Start }
-
-const (
- subuidFileName string = "/etc/subuid"
- subgidFileName string = "/etc/subgid"
-)
-
-// MkdirAllAs creates a directory (include any along the path) and then modifies
-// ownership to the requested uid/gid. If the directory already exists, this
-// function will still change ownership to the requested uid/gid pair.
-func MkdirAllAs(path string, mode os.FileMode, ownerUID, ownerGID int) error {
- return mkdirAs(path, mode, ownerUID, ownerGID, true, true)
-}
-
-// MkdirAllNewAs creates a directory (include any along the path) and then modifies
-// ownership ONLY of newly created directories to the requested uid/gid. If the
-// directories along the path exist, no change of ownership will be performed
-func MkdirAllNewAs(path string, mode os.FileMode, ownerUID, ownerGID int) error {
- return mkdirAs(path, mode, ownerUID, ownerGID, true, false)
-}
-
-// MkdirAs creates a directory and then modifies ownership to the requested uid/gid.
-// If the directory already exists, this function still changes ownership
-func MkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int) error {
- return mkdirAs(path, mode, ownerUID, ownerGID, false, true)
-}
-
-// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
-// If the maps are empty, then the root uid/gid will default to "real" 0/0
-func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
- var uid, gid int
-
- if uidMap != nil {
- xUID, err := ToHost(0, uidMap)
- if err != nil {
- return -1, -1, err
- }
- uid = xUID
- }
- if gidMap != nil {
- xGID, err := ToHost(0, gidMap)
- if err != nil {
- return -1, -1, err
- }
- gid = xGID
- }
- return uid, gid, nil
-}
-
-// ToContainer takes an id mapping, and uses it to translate a
-// host ID to the remapped ID. If no map is provided, then the translation
-// assumes a 1-to-1 mapping and returns the passed in id
-func ToContainer(hostID int, idMap []IDMap) (int, error) {
- if idMap == nil {
- return hostID, nil
- }
- for _, m := range idMap {
- if (hostID >= m.HostID) && (hostID <= (m.HostID + m.Size - 1)) {
- contID := m.ContainerID + (hostID - m.HostID)
- return contID, nil
- }
- }
- return -1, fmt.Errorf("Host ID %d cannot be mapped to a container ID", hostID)
-}
-
-// ToHost takes an id mapping and a remapped ID, and translates the
-// ID to the mapped host ID. If no map is provided, then the translation
-// assumes a 1-to-1 mapping and returns the passed in id #
-func ToHost(contID int, idMap []IDMap) (int, error) {
- if idMap == nil {
- return contID, nil
- }
- for _, m := range idMap {
- if (contID >= m.ContainerID) && (contID <= (m.ContainerID + m.Size - 1)) {
- hostID := m.HostID + (contID - m.ContainerID)
- return hostID, nil
- }
- }
- return -1, fmt.Errorf("Container ID %d cannot be mapped to a host ID", contID)
-}
-
-// CreateIDMappings takes a requested user and group name and
-// using the data from /etc/sub{uid,gid} ranges, creates the
-// proper uid and gid remapping ranges for that user/group pair
-func CreateIDMappings(username, groupname string) ([]IDMap, []IDMap, error) {
- subuidRanges, err := parseSubuid(username)
- if err != nil {
- return nil, nil, err
- }
- subgidRanges, err := parseSubgid(groupname)
- if err != nil {
- return nil, nil, err
- }
- if len(subuidRanges) == 0 {
- return nil, nil, fmt.Errorf("No subuid ranges found for user %q", username)
- }
- if len(subgidRanges) == 0 {
- return nil, nil, fmt.Errorf("No subgid ranges found for group %q", groupname)
- }
-
- return createIDMap(subuidRanges), createIDMap(subgidRanges), nil
-}
-
-func createIDMap(subidRanges ranges) []IDMap {
- idMap := []IDMap{}
-
- // sort the ranges by lowest ID first
- sort.Sort(subidRanges)
- containerID := 0
- for _, idrange := range subidRanges {
- idMap = append(idMap, IDMap{
- ContainerID: containerID,
- HostID: idrange.Start,
- Size: idrange.Length,
- })
- containerID = containerID + idrange.Length
- }
- return idMap
-}
-
-func parseSubuid(username string) (ranges, error) {
- return parseSubidFile(subuidFileName, username)
-}
-
-func parseSubgid(username string) (ranges, error) {
- return parseSubidFile(subgidFileName, username)
-}
-
-// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid)
-// and return all found ranges for a specified username. If the special value
-// "ALL" is supplied for username, then all ranges in the file will be returned
-func parseSubidFile(path, username string) (ranges, error) {
- var rangeList ranges
-
- subidFile, err := os.Open(path)
- if err != nil {
- return rangeList, err
- }
- defer subidFile.Close()
-
- s := bufio.NewScanner(subidFile)
- for s.Scan() {
- if err := s.Err(); err != nil {
- return rangeList, err
- }
-
- text := strings.TrimSpace(s.Text())
- if text == "" || strings.HasPrefix(text, "#") {
- continue
- }
- parts := strings.Split(text, ":")
- if len(parts) != 3 {
- return rangeList, fmt.Errorf("Cannot parse subuid/gid information: Format not correct for %s file", path)
- }
- if parts[0] == username || username == "ALL" {
- startid, err := strconv.Atoi(parts[1])
- if err != nil {
- return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err)
- }
- length, err := strconv.Atoi(parts[2])
- if err != nil {
- return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err)
- }
- rangeList = append(rangeList, subIDRange{startid, length})
- }
- }
- return rangeList, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go
deleted file mode 100644
index b57d6ef..0000000
--- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// +build !windows
-
-package idtools
-
-import (
- "os"
- "path/filepath"
-
- "github.com/docker/docker/pkg/system"
-)
-
-func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error {
- // make an array containing the original path asked for, plus (for mkAll == true)
- // all path components leading up to the complete path that don't exist before we MkdirAll
- // so that we can chown all of them properly at the end. If chownExisting is false, we won't
- // chown the full directory path if it exists
- var paths []string
- if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
- paths = []string{path}
- } else if err == nil && chownExisting {
- if err := os.Chown(path, ownerUID, ownerGID); err != nil {
- return err
- }
- // short-circuit--we were called with an existing directory and chown was requested
- return nil
- } else if err == nil {
- // nothing to do; directory path fully exists already and chown was NOT requested
- return nil
- }
-
- if mkAll {
- // walk back to "/" looking for directories which do not exist
- // and add them to the paths array for chown after creation
- dirPath := path
- for {
- dirPath = filepath.Dir(dirPath)
- if dirPath == "/" {
- break
- }
- if _, err := os.Stat(dirPath); err != nil && os.IsNotExist(err) {
- paths = append(paths, dirPath)
- }
- }
- if err := system.MkdirAll(path, mode); err != nil && !os.IsExist(err) {
- return err
- }
- } else {
- if err := os.Mkdir(path, mode); err != nil && !os.IsExist(err) {
- return err
- }
- }
- // even if it existed, we will chown the requested path + any subpaths that
- // didn't exist when we called MkdirAll
- for _, pathComponent := range paths {
- if err := os.Chown(pathComponent, ownerUID, ownerGID); err != nil {
- return err
- }
- }
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix_test.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix_test.go
deleted file mode 100644
index 540d307..0000000
--- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix_test.go
+++ /dev/null
@@ -1,271 +0,0 @@
-// +build !windows
-
-package idtools
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "syscall"
- "testing"
-)
-
-type node struct {
- uid int
- gid int
-}
-
-func TestMkdirAllAs(t *testing.T) {
- dirName, err := ioutil.TempDir("", "mkdirall")
- if err != nil {
- t.Fatalf("Couldn't create temp dir: %v", err)
- }
- defer os.RemoveAll(dirName)
-
- testTree := map[string]node{
- "usr": {0, 0},
- "usr/bin": {0, 0},
- "lib": {33, 33},
- "lib/x86_64": {45, 45},
- "lib/x86_64/share": {1, 1},
- }
-
- if err := buildTree(dirName, testTree); err != nil {
- t.Fatal(err)
- }
-
- // test adding a directory to a pre-existing dir; only the new dir is owned by the uid/gid
- if err := MkdirAllAs(filepath.Join(dirName, "usr", "share"), 0755, 99, 99); err != nil {
- t.Fatal(err)
- }
- testTree["usr/share"] = node{99, 99}
- verifyTree, err := readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-
- // test 2-deep new directories--both should be owned by the uid/gid pair
- if err := MkdirAllAs(filepath.Join(dirName, "lib", "some", "other"), 0755, 101, 101); err != nil {
- t.Fatal(err)
- }
- testTree["lib/some"] = node{101, 101}
- testTree["lib/some/other"] = node{101, 101}
- verifyTree, err = readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-
- // test a directory that already exists; should be chowned, but nothing else
- if err := MkdirAllAs(filepath.Join(dirName, "usr"), 0755, 102, 102); err != nil {
- t.Fatal(err)
- }
- testTree["usr"] = node{102, 102}
- verifyTree, err = readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestMkdirAllNewAs(t *testing.T) {
-
- dirName, err := ioutil.TempDir("", "mkdirnew")
- if err != nil {
- t.Fatalf("Couldn't create temp dir: %v", err)
- }
- defer os.RemoveAll(dirName)
-
- testTree := map[string]node{
- "usr": {0, 0},
- "usr/bin": {0, 0},
- "lib": {33, 33},
- "lib/x86_64": {45, 45},
- "lib/x86_64/share": {1, 1},
- }
-
- if err := buildTree(dirName, testTree); err != nil {
- t.Fatal(err)
- }
-
- // test adding a directory to a pre-existing dir; only the new dir is owned by the uid/gid
- if err := MkdirAllNewAs(filepath.Join(dirName, "usr", "share"), 0755, 99, 99); err != nil {
- t.Fatal(err)
- }
- testTree["usr/share"] = node{99, 99}
- verifyTree, err := readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-
- // test 2-deep new directories--both should be owned by the uid/gid pair
- if err := MkdirAllNewAs(filepath.Join(dirName, "lib", "some", "other"), 0755, 101, 101); err != nil {
- t.Fatal(err)
- }
- testTree["lib/some"] = node{101, 101}
- testTree["lib/some/other"] = node{101, 101}
- verifyTree, err = readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-
- // test a directory that already exists; should NOT be chowned
- if err := MkdirAllNewAs(filepath.Join(dirName, "usr"), 0755, 102, 102); err != nil {
- t.Fatal(err)
- }
- verifyTree, err = readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestMkdirAs(t *testing.T) {
-
- dirName, err := ioutil.TempDir("", "mkdir")
- if err != nil {
- t.Fatalf("Couldn't create temp dir: %v", err)
- }
- defer os.RemoveAll(dirName)
-
- testTree := map[string]node{
- "usr": {0, 0},
- }
- if err := buildTree(dirName, testTree); err != nil {
- t.Fatal(err)
- }
-
- // test a directory that already exists; should just chown to the requested uid/gid
- if err := MkdirAs(filepath.Join(dirName, "usr"), 0755, 99, 99); err != nil {
- t.Fatal(err)
- }
- testTree["usr"] = node{99, 99}
- verifyTree, err := readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-
- // create a subdir under a dir which doesn't exist--should fail
- if err := MkdirAs(filepath.Join(dirName, "usr", "bin", "subdir"), 0755, 102, 102); err == nil {
- t.Fatalf("Trying to create a directory with Mkdir where the parent doesn't exist should have failed")
- }
-
- // create a subdir under an existing dir; should only change the ownership of the new subdir
- if err := MkdirAs(filepath.Join(dirName, "usr", "bin"), 0755, 102, 102); err != nil {
- t.Fatal(err)
- }
- testTree["usr/bin"] = node{102, 102}
- verifyTree, err = readTree(dirName, "")
- if err != nil {
- t.Fatal(err)
- }
- if err := compareTrees(testTree, verifyTree); err != nil {
- t.Fatal(err)
- }
-}
-
-func buildTree(base string, tree map[string]node) error {
- for path, node := range tree {
- fullPath := filepath.Join(base, path)
- if err := os.MkdirAll(fullPath, 0755); err != nil {
- return fmt.Errorf("Couldn't create path: %s; error: %v", fullPath, err)
- }
- if err := os.Chown(fullPath, node.uid, node.gid); err != nil {
- return fmt.Errorf("Couldn't chown path: %s; error: %v", fullPath, err)
- }
- }
- return nil
-}
-
-func readTree(base, root string) (map[string]node, error) {
- tree := make(map[string]node)
-
- dirInfos, err := ioutil.ReadDir(base)
- if err != nil {
- return nil, fmt.Errorf("Couldn't read directory entries for %q: %v", base, err)
- }
-
- for _, info := range dirInfos {
- s := &syscall.Stat_t{}
- if err := syscall.Stat(filepath.Join(base, info.Name()), s); err != nil {
- return nil, fmt.Errorf("Can't stat file %q: %v", filepath.Join(base, info.Name()), err)
- }
- tree[filepath.Join(root, info.Name())] = node{int(s.Uid), int(s.Gid)}
- if info.IsDir() {
- // read the subdirectory
- subtree, err := readTree(filepath.Join(base, info.Name()), filepath.Join(root, info.Name()))
- if err != nil {
- return nil, err
- }
- for path, nodeinfo := range subtree {
- tree[path] = nodeinfo
- }
- }
- }
- return tree, nil
-}
-
-func compareTrees(left, right map[string]node) error {
- if len(left) != len(right) {
- return fmt.Errorf("Trees aren't the same size")
- }
- for path, nodeLeft := range left {
- if nodeRight, ok := right[path]; ok {
- if nodeRight.uid != nodeLeft.uid || nodeRight.gid != nodeLeft.gid {
- // mismatch
- return fmt.Errorf("mismatched ownership for %q: expected: %d:%d, got: %d:%d", path,
- nodeLeft.uid, nodeLeft.gid, nodeRight.uid, nodeRight.gid)
- }
- continue
- }
- return fmt.Errorf("right tree didn't contain path %q", path)
- }
- return nil
-}
-
-func TestParseSubidFileWithNewlinesAndComments(t *testing.T) {
- tmpDir, err := ioutil.TempDir("", "parsesubid")
- if err != nil {
- t.Fatal(err)
- }
- fnamePath := filepath.Join(tmpDir, "testsubuid")
- fcontent := `tss:100000:65536
-# empty default subuid/subgid file
-
-dockremap:231072:65536`
- if err := ioutil.WriteFile(fnamePath, []byte(fcontent), 0644); err != nil {
- t.Fatal(err)
- }
- ranges, err := parseSubidFile(fnamePath, "dockremap")
- if err != nil {
- t.Fatal(err)
- }
- if len(ranges) != 1 {
- t.Fatalf("wanted 1 element in ranges, got %d instead", len(ranges))
- }
- if ranges[0].Start != 231072 {
- t.Fatalf("wanted 231072, got %d instead", ranges[0].Start)
- }
- if ranges[0].Length != 65536 {
- t.Fatalf("wanted 65536, got %d instead", ranges[0].Length)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go
deleted file mode 100644
index c9e3c93..0000000
--- a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build windows
-
-package idtools
-
-import (
- "os"
-
- "github.com/docker/docker/pkg/system"
-)
-
-// Platforms such as Windows do not support the UID/GID concept. So make this
-// just a wrapper around system.MkdirAll.
-func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error {
- if err := system.MkdirAll(path, mode); err != nil && !os.IsExist(err) {
- return err
- }
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go
deleted file mode 100644
index 4a4aaed..0000000
--- a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go
+++ /dev/null
@@ -1,188 +0,0 @@
-package idtools
-
-import (
- "fmt"
- "os/exec"
- "path/filepath"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "sync"
-)
-
-// add a user and/or group to Linux /etc/passwd, /etc/group using standard
-// Linux distribution commands:
-// adduser --system --shell /bin/false --disabled-login --disabled-password --no-create-home --group
-// useradd -r -s /bin/false
-
-var (
- once sync.Once
- userCommand string
-
- cmdTemplates = map[string]string{
- "adduser": "--system --shell /bin/false --no-create-home --disabled-login --disabled-password --group %s",
- "useradd": "-r -s /bin/false %s",
- "usermod": "-%s %d-%d %s",
- }
-
- idOutRegexp = regexp.MustCompile(`uid=([0-9]+).*gid=([0-9]+)`)
- // default length for a UID/GID subordinate range
- defaultRangeLen = 65536
- defaultRangeStart = 100000
- userMod = "usermod"
-)
-
-func resolveBinary(binname string) (string, error) {
- binaryPath, err := exec.LookPath(binname)
- if err != nil {
- return "", err
- }
- resolvedPath, err := filepath.EvalSymlinks(binaryPath)
- if err != nil {
- return "", err
- }
- //only return no error if the final resolved binary basename
- //matches what was searched for
- if filepath.Base(resolvedPath) == binname {
- return resolvedPath, nil
- }
- return "", fmt.Errorf("Binary %q does not resolve to a binary of that name in $PATH (%q)", binname, resolvedPath)
-}
-
-// AddNamespaceRangesUser takes a username and uses the standard system
-// utility to create a system user/group pair used to hold the
-// /etc/sub{uid,gid} ranges which will be used for user namespace
-// mapping ranges in containers.
-func AddNamespaceRangesUser(name string) (int, int, error) {
- if err := addUser(name); err != nil {
- return -1, -1, fmt.Errorf("Error adding user %q: %v", name, err)
- }
-
- // Query the system for the created uid and gid pair
- out, err := execCmd("id", name)
- if err != nil {
- return -1, -1, fmt.Errorf("Error trying to find uid/gid for new user %q: %v", name, err)
- }
- matches := idOutRegexp.FindStringSubmatch(strings.TrimSpace(string(out)))
- if len(matches) != 3 {
- return -1, -1, fmt.Errorf("Can't find uid, gid from `id` output: %q", string(out))
- }
- uid, err := strconv.Atoi(matches[1])
- if err != nil {
- return -1, -1, fmt.Errorf("Can't convert found uid (%s) to int: %v", matches[1], err)
- }
- gid, err := strconv.Atoi(matches[2])
- if err != nil {
- return -1, -1, fmt.Errorf("Can't convert found gid (%s) to int: %v", matches[2], err)
- }
-
- // Now we need to create the subuid/subgid ranges for our new user/group (system users
- // do not get auto-created ranges in subuid/subgid)
-
- if err := createSubordinateRanges(name); err != nil {
- return -1, -1, fmt.Errorf("Couldn't create subordinate ID ranges: %v", err)
- }
- return uid, gid, nil
-}
-
-func addUser(userName string) error {
- once.Do(func() {
- // set up which commands are used for adding users/groups dependent on distro
- if _, err := resolveBinary("adduser"); err == nil {
- userCommand = "adduser"
- } else if _, err := resolveBinary("useradd"); err == nil {
- userCommand = "useradd"
- }
- })
- if userCommand == "" {
- return fmt.Errorf("Cannot add user; no useradd/adduser binary found")
- }
- args := fmt.Sprintf(cmdTemplates[userCommand], userName)
- out, err := execCmd(userCommand, args)
- if err != nil {
- return fmt.Errorf("Failed to add user with error: %v; output: %q", err, string(out))
- }
- return nil
-}
-
-func createSubordinateRanges(name string) error {
-
- // first, we should verify that ranges weren't automatically created
- // by the distro tooling
- ranges, err := parseSubuid(name)
- if err != nil {
- return fmt.Errorf("Error while looking for subuid ranges for user %q: %v", name, err)
- }
- if len(ranges) == 0 {
- // no UID ranges; let's create one
- startID, err := findNextUIDRange()
- if err != nil {
- return fmt.Errorf("Can't find available subuid range: %v", err)
- }
- out, err := execCmd(userMod, fmt.Sprintf(cmdTemplates[userMod], "v", startID, startID+defaultRangeLen-1, name))
- if err != nil {
- return fmt.Errorf("Unable to add subuid range to user: %q; output: %s, err: %v", name, out, err)
- }
- }
-
- ranges, err = parseSubgid(name)
- if err != nil {
- return fmt.Errorf("Error while looking for subgid ranges for user %q: %v", name, err)
- }
- if len(ranges) == 0 {
- // no GID ranges; let's create one
- startID, err := findNextGIDRange()
- if err != nil {
- return fmt.Errorf("Can't find available subgid range: %v", err)
- }
- out, err := execCmd(userMod, fmt.Sprintf(cmdTemplates[userMod], "w", startID, startID+defaultRangeLen-1, name))
- if err != nil {
- return fmt.Errorf("Unable to add subgid range to user: %q; output: %s, err: %v", name, out, err)
- }
- }
- return nil
-}
-
-func findNextUIDRange() (int, error) {
- ranges, err := parseSubuid("ALL")
- if err != nil {
- return -1, fmt.Errorf("Couldn't parse all ranges in /etc/subuid file: %v", err)
- }
- sort.Sort(ranges)
- return findNextRangeStart(ranges)
-}
-
-func findNextGIDRange() (int, error) {
- ranges, err := parseSubgid("ALL")
- if err != nil {
- return -1, fmt.Errorf("Couldn't parse all ranges in /etc/subgid file: %v", err)
- }
- sort.Sort(ranges)
- return findNextRangeStart(ranges)
-}
-
-func findNextRangeStart(rangeList ranges) (int, error) {
- startID := defaultRangeStart
- for _, arange := range rangeList {
- if wouldOverlap(arange, startID) {
- startID = arange.Start + arange.Length
- }
- }
- return startID, nil
-}
-
-func wouldOverlap(arange subIDRange, ID int) bool {
- low := ID
- high := ID + defaultRangeLen
- if (low >= arange.Start && low <= arange.Start+arange.Length) ||
- (high <= arange.Start+arange.Length && high >= arange.Start) {
- return true
- }
- return false
-}
-
-func execCmd(cmd, args string) ([]byte, error) {
- execCmd := exec.Command(cmd, strings.Split(args, " ")...)
- return execCmd.CombinedOutput()
-}
diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go
deleted file mode 100644
index d98b354..0000000
--- a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// +build !linux
-
-package idtools
-
-import "fmt"
-
-// AddNamespaceRangesUser takes a name and finds an unused uid, gid pair
-// and calls the appropriate helper function to add the group and then
-// the user to the group in /etc/group and /etc/passwd respectively.
-func AddNamespaceRangesUser(name string) (int, int, error) {
- return -1, -1, fmt.Errorf("No support for adding users or groups on this OS")
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go b/vendor/github.com/docker/docker/pkg/ioutils/buffer.go
deleted file mode 100644
index 3d737b3..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package ioutils
-
-import (
- "errors"
- "io"
-)
-
-var errBufferFull = errors.New("buffer is full")
-
-type fixedBuffer struct {
- buf []byte
- pos int
- lastRead int
-}
-
-func (b *fixedBuffer) Write(p []byte) (int, error) {
- n := copy(b.buf[b.pos:cap(b.buf)], p)
- b.pos += n
-
- if n < len(p) {
- if b.pos == cap(b.buf) {
- return n, errBufferFull
- }
- return n, io.ErrShortWrite
- }
- return n, nil
-}
-
-func (b *fixedBuffer) Read(p []byte) (int, error) {
- n := copy(p, b.buf[b.lastRead:b.pos])
- b.lastRead += n
- return n, nil
-}
-
-func (b *fixedBuffer) Len() int {
- return b.pos - b.lastRead
-}
-
-func (b *fixedBuffer) Cap() int {
- return cap(b.buf)
-}
-
-func (b *fixedBuffer) Reset() {
- b.pos = 0
- b.lastRead = 0
- b.buf = b.buf[:0]
-}
-
-func (b *fixedBuffer) String() string {
- return string(b.buf[b.lastRead:b.pos])
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/buffer_test.go b/vendor/github.com/docker/docker/pkg/ioutils/buffer_test.go
deleted file mode 100644
index 41098fa..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/buffer_test.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package ioutils
-
-import (
- "bytes"
- "testing"
-)
-
-func TestFixedBufferWrite(t *testing.T) {
- buf := &fixedBuffer{buf: make([]byte, 0, 64)}
- n, err := buf.Write([]byte("hello"))
- if err != nil {
- t.Fatal(err)
- }
-
- if n != 5 {
- t.Fatalf("expected 5 bytes written, got %d", n)
- }
-
- if string(buf.buf[:5]) != "hello" {
- t.Fatalf("expected \"hello\", got %q", string(buf.buf[:5]))
- }
-
- n, err = buf.Write(bytes.Repeat([]byte{1}, 64))
- if err != errBufferFull {
- t.Fatalf("expected errBufferFull, got %v - %v", err, buf.buf[:64])
- }
-}
-
-func TestFixedBufferRead(t *testing.T) {
- buf := &fixedBuffer{buf: make([]byte, 0, 64)}
- if _, err := buf.Write([]byte("hello world")); err != nil {
- t.Fatal(err)
- }
-
- b := make([]byte, 5)
- n, err := buf.Read(b)
- if err != nil {
- t.Fatal(err)
- }
-
- if n != 5 {
- t.Fatalf("expected 5 bytes read, got %d - %s", n, buf.String())
- }
-
- if string(b) != "hello" {
- t.Fatalf("expected \"hello\", got %q", string(b))
- }
-
- n, err = buf.Read(b)
- if err != nil {
- t.Fatal(err)
- }
-
- if n != 5 {
- t.Fatalf("expected 5 bytes read, got %d", n)
- }
-
- if string(b) != " worl" {
- t.Fatalf("expected \" worl\", got %s", string(b))
- }
-
- b = b[:1]
- n, err = buf.Read(b)
- if err != nil {
- t.Fatal(err)
- }
-
- if n != 1 {
- t.Fatalf("expected 1 byte read, got %d - %s", n, buf.String())
- }
-
- if string(b) != "d" {
- t.Fatalf("expected \"d\", got %s", string(b))
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go
deleted file mode 100644
index 72a04f3..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go
+++ /dev/null
@@ -1,186 +0,0 @@
-package ioutils
-
-import (
- "errors"
- "io"
- "sync"
-)
-
-// maxCap is the highest capacity to use in byte slices that buffer data.
-const maxCap = 1e6
-
-// minCap is the lowest capacity to use in byte slices that buffer data
-const minCap = 64
-
-// blockThreshold is the minimum number of bytes in the buffer which will cause
-// a write to BytesPipe to block when allocating a new slice.
-const blockThreshold = 1e6
-
-var (
- // ErrClosed is returned when Write is called on a closed BytesPipe.
- ErrClosed = errors.New("write to closed BytesPipe")
-
- bufPools = make(map[int]*sync.Pool)
- bufPoolsLock sync.Mutex
-)
-
-// BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue).
-// All written data may be read at most once. Also, BytesPipe allocates
-// and releases new byte slices to adjust to current needs, so the buffer
-// won't be overgrown after peak loads.
-type BytesPipe struct {
- mu sync.Mutex
- wait *sync.Cond
- buf []*fixedBuffer
- bufLen int
- closeErr error // error to return from next Read. set to nil if not closed.
-}
-
-// NewBytesPipe creates new BytesPipe, initialized by specified slice.
-// If buf is nil, then it will be initialized with slice which cap is 64.
-// buf will be adjusted in a way that len(buf) == 0, cap(buf) == cap(buf).
-func NewBytesPipe() *BytesPipe {
- bp := &BytesPipe{}
- bp.buf = append(bp.buf, getBuffer(minCap))
- bp.wait = sync.NewCond(&bp.mu)
- return bp
-}
-
-// Write writes p to BytesPipe.
-// It can allocate new []byte slices in a process of writing.
-func (bp *BytesPipe) Write(p []byte) (int, error) {
- bp.mu.Lock()
-
- written := 0
-loop0:
- for {
- if bp.closeErr != nil {
- bp.mu.Unlock()
- return written, ErrClosed
- }
-
- if len(bp.buf) == 0 {
- bp.buf = append(bp.buf, getBuffer(64))
- }
- // get the last buffer
- b := bp.buf[len(bp.buf)-1]
-
- n, err := b.Write(p)
- written += n
- bp.bufLen += n
-
- // errBufferFull is an error we expect to get if the buffer is full
- if err != nil && err != errBufferFull {
- bp.wait.Broadcast()
- bp.mu.Unlock()
- return written, err
- }
-
- // if there was enough room to write all then break
- if len(p) == n {
- break
- }
-
- // more data: write to the next slice
- p = p[n:]
-
- // make sure the buffer doesn't grow too big from this write
- for bp.bufLen >= blockThreshold {
- bp.wait.Wait()
- if bp.closeErr != nil {
- continue loop0
- }
- }
-
- // add new byte slice to the buffers slice and continue writing
- nextCap := b.Cap() * 2
- if nextCap > maxCap {
- nextCap = maxCap
- }
- bp.buf = append(bp.buf, getBuffer(nextCap))
- }
- bp.wait.Broadcast()
- bp.mu.Unlock()
- return written, nil
-}
-
-// CloseWithError causes further reads from a BytesPipe to return immediately.
-func (bp *BytesPipe) CloseWithError(err error) error {
- bp.mu.Lock()
- if err != nil {
- bp.closeErr = err
- } else {
- bp.closeErr = io.EOF
- }
- bp.wait.Broadcast()
- bp.mu.Unlock()
- return nil
-}
-
-// Close causes further reads from a BytesPipe to return immediately.
-func (bp *BytesPipe) Close() error {
- return bp.CloseWithError(nil)
-}
-
-// Read reads bytes from BytesPipe.
-// Data could be read only once.
-func (bp *BytesPipe) Read(p []byte) (n int, err error) {
- bp.mu.Lock()
- if bp.bufLen == 0 {
- if bp.closeErr != nil {
- bp.mu.Unlock()
- return 0, bp.closeErr
- }
- bp.wait.Wait()
- if bp.bufLen == 0 && bp.closeErr != nil {
- err := bp.closeErr
- bp.mu.Unlock()
- return 0, err
- }
- }
-
- for bp.bufLen > 0 {
- b := bp.buf[0]
- read, _ := b.Read(p) // ignore error since fixedBuffer doesn't really return an error
- n += read
- bp.bufLen -= read
-
- if b.Len() == 0 {
- // it's empty so return it to the pool and move to the next one
- returnBuffer(b)
- bp.buf[0] = nil
- bp.buf = bp.buf[1:]
- }
-
- if len(p) == read {
- break
- }
-
- p = p[read:]
- }
-
- bp.wait.Broadcast()
- bp.mu.Unlock()
- return
-}
-
-func returnBuffer(b *fixedBuffer) {
- b.Reset()
- bufPoolsLock.Lock()
- pool := bufPools[b.Cap()]
- bufPoolsLock.Unlock()
- if pool != nil {
- pool.Put(b)
- }
-}
-
-func getBuffer(size int) *fixedBuffer {
- bufPoolsLock.Lock()
- pool, ok := bufPools[size]
- if !ok {
- pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }}
- bufPools[size] = pool
- }
- bufPoolsLock.Unlock()
- return pool.Get().(*fixedBuffer)
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe_test.go b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe_test.go
deleted file mode 100644
index 300fb5f..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe_test.go
+++ /dev/null
@@ -1,159 +0,0 @@
-package ioutils
-
-import (
- "crypto/sha1"
- "encoding/hex"
- "math/rand"
- "testing"
- "time"
-)
-
-func TestBytesPipeRead(t *testing.T) {
- buf := NewBytesPipe()
- buf.Write([]byte("12"))
- buf.Write([]byte("34"))
- buf.Write([]byte("56"))
- buf.Write([]byte("78"))
- buf.Write([]byte("90"))
- rd := make([]byte, 4)
- n, err := buf.Read(rd)
- if err != nil {
- t.Fatal(err)
- }
- if n != 4 {
- t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
- }
- if string(rd) != "1234" {
- t.Fatalf("Read %s, but must be %s", rd, "1234")
- }
- n, err = buf.Read(rd)
- if err != nil {
- t.Fatal(err)
- }
- if n != 4 {
- t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 4)
- }
- if string(rd) != "5678" {
- t.Fatalf("Read %s, but must be %s", rd, "5679")
- }
- n, err = buf.Read(rd)
- if err != nil {
- t.Fatal(err)
- }
- if n != 2 {
- t.Fatalf("Wrong number of bytes read: %d, should be %d", n, 2)
- }
- if string(rd[:n]) != "90" {
- t.Fatalf("Read %s, but must be %s", rd, "90")
- }
-}
-
-func TestBytesPipeWrite(t *testing.T) {
- buf := NewBytesPipe()
- buf.Write([]byte("12"))
- buf.Write([]byte("34"))
- buf.Write([]byte("56"))
- buf.Write([]byte("78"))
- buf.Write([]byte("90"))
- if buf.buf[0].String() != "1234567890" {
- t.Fatalf("Buffer %q, must be %q", buf.buf[0].String(), "1234567890")
- }
-}
-
-// Write and read in different speeds/chunk sizes and check valid data is read.
-func TestBytesPipeWriteRandomChunks(t *testing.T) {
- cases := []struct{ iterations, writesPerLoop, readsPerLoop int }{
- {100, 10, 1},
- {1000, 10, 5},
- {1000, 100, 0},
- {1000, 5, 6},
- {10000, 50, 25},
- }
-
- testMessage := []byte("this is a random string for testing")
- // random slice sizes to read and write
- writeChunks := []int{25, 35, 15, 20}
- readChunks := []int{5, 45, 20, 25}
-
- for _, c := range cases {
- // first pass: write directly to hash
- hash := sha1.New()
- for i := 0; i < c.iterations*c.writesPerLoop; i++ {
- if _, err := hash.Write(testMessage[:writeChunks[i%len(writeChunks)]]); err != nil {
- t.Fatal(err)
- }
- }
- expected := hex.EncodeToString(hash.Sum(nil))
-
- // write/read through buffer
- buf := NewBytesPipe()
- hash.Reset()
-
- done := make(chan struct{})
-
- go func() {
- // random delay before read starts
- <-time.After(time.Duration(rand.Intn(10)) * time.Millisecond)
- for i := 0; ; i++ {
- p := make([]byte, readChunks[(c.iterations*c.readsPerLoop+i)%len(readChunks)])
- n, _ := buf.Read(p)
- if n == 0 {
- break
- }
- hash.Write(p[:n])
- }
-
- close(done)
- }()
-
- for i := 0; i < c.iterations; i++ {
- for w := 0; w < c.writesPerLoop; w++ {
- buf.Write(testMessage[:writeChunks[(i*c.writesPerLoop+w)%len(writeChunks)]])
- }
- }
- buf.Close()
- <-done
-
- actual := hex.EncodeToString(hash.Sum(nil))
-
- if expected != actual {
- t.Fatalf("BytesPipe returned invalid data. Expected checksum %v, got %v", expected, actual)
- }
-
- }
-}
-
-func BenchmarkBytesPipeWrite(b *testing.B) {
- testData := []byte("pretty short line, because why not?")
- for i := 0; i < b.N; i++ {
- readBuf := make([]byte, 1024)
- buf := NewBytesPipe()
- go func() {
- var err error
- for err == nil {
- _, err = buf.Read(readBuf)
- }
- }()
- for j := 0; j < 1000; j++ {
- buf.Write(testData)
- }
- buf.Close()
- }
-}
-
-func BenchmarkBytesPipeRead(b *testing.B) {
- rd := make([]byte, 512)
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- buf := NewBytesPipe()
- for j := 0; j < 500; j++ {
- buf.Write(make([]byte, 1024))
- }
- b.StartTimer()
- for j := 0; j < 1000; j++ {
- if n, _ := buf.Read(rd); n != 512 {
- b.Fatalf("Wrong number of bytes: %d", n)
- }
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fmt.go b/vendor/github.com/docker/docker/pkg/ioutils/fmt.go
deleted file mode 100644
index 0b04b0b..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/fmt.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package ioutils
-
-import (
- "fmt"
- "io"
-)
-
-// FprintfIfNotEmpty prints the string value if it's not empty
-func FprintfIfNotEmpty(w io.Writer, format, value string) (int, error) {
- if value != "" {
- return fmt.Fprintf(w, format, value)
- }
- return 0, nil
-}
-
-// FprintfIfTrue prints the boolean value if it's true
-func FprintfIfTrue(w io.Writer, format string, ok bool) (int, error) {
- if ok {
- return fmt.Fprintf(w, format, ok)
- }
- return 0, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fmt_test.go b/vendor/github.com/docker/docker/pkg/ioutils/fmt_test.go
deleted file mode 100644
index 8968863..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/fmt_test.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package ioutils
-
-import "testing"
-
-func TestFprintfIfNotEmpty(t *testing.T) {
- wc := NewWriteCounter(&NopWriter{})
- n, _ := FprintfIfNotEmpty(wc, "foo%s", "")
-
- if wc.Count != 0 || n != 0 {
- t.Errorf("Wrong count: %v vs. %v vs. 0", wc.Count, n)
- }
-
- n, _ = FprintfIfNotEmpty(wc, "foo%s", "bar")
- if wc.Count != 6 || n != 6 {
- t.Errorf("Wrong count: %v vs. %v vs. 6", wc.Count, n)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go
deleted file mode 100644
index ca97670..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package ioutils
-
-import (
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
-)
-
-// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a
-// temporary file and closing it atomically changes the temporary file to
-// destination path. Writing and closing concurrently is not allowed.
-func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) {
- f, err := ioutil.TempFile(filepath.Dir(filename), ".tmp-"+filepath.Base(filename))
- if err != nil {
- return nil, err
- }
- abspath, err := filepath.Abs(filename)
- if err != nil {
- return nil, err
- }
- return &atomicFileWriter{
- f: f,
- fn: abspath,
- }, nil
-}
-
-// AtomicWriteFile atomically writes data to a file named by filename.
-func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error {
- f, err := NewAtomicFileWriter(filename, perm)
- if err != nil {
- return err
- }
- n, err := f.Write(data)
- if err == nil && n < len(data) {
- err = io.ErrShortWrite
- }
- if err1 := f.Close(); err == nil {
- err = err1
- }
- return err
-}
-
-type atomicFileWriter struct {
- f *os.File
- fn string
- writeErr error
-}
-
-func (w *atomicFileWriter) Write(dt []byte) (int, error) {
- n, err := w.f.Write(dt)
- if err != nil {
- w.writeErr = err
- }
- return n, err
-}
-
-func (w *atomicFileWriter) Close() (retErr error) {
- defer func() {
- if retErr != nil {
- os.Remove(w.f.Name())
- }
- }()
- if err := w.f.Sync(); err != nil {
- w.f.Close()
- return err
- }
- if err := w.f.Close(); err != nil {
- return err
- }
- if w.writeErr == nil {
- return os.Rename(w.f.Name(), w.fn)
- }
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters_test.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters_test.go
deleted file mode 100644
index 40717a5..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/fswriters_test.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package ioutils
-
-import (
- "bytes"
- "io/ioutil"
- "os"
- "path/filepath"
- "testing"
-)
-
-func TestAtomicWriteToFile(t *testing.T) {
- tmpDir, err := ioutil.TempDir("", "atomic-writers-test")
- if err != nil {
- t.Fatalf("Error when creating temporary directory: %s", err)
- }
- defer os.RemoveAll(tmpDir)
-
- expected := []byte("barbaz")
- if err := AtomicWriteFile(filepath.Join(tmpDir, "foo"), expected, 0600); err != nil {
- t.Fatalf("Error writing to file: %v", err)
- }
-
- actual, err := ioutil.ReadFile(filepath.Join(tmpDir, "foo"))
- if err != nil {
- t.Fatalf("Error reading from file: %v", err)
- }
-
- if bytes.Compare(actual, expected) != 0 {
- t.Fatalf("Data mismatch, expected %q, got %q", expected, actual)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/multireader.go b/vendor/github.com/docker/docker/pkg/ioutils/multireader.go
deleted file mode 100644
index 0d2d76b..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/multireader.go
+++ /dev/null
@@ -1,226 +0,0 @@
-package ioutils
-
-import (
- "bytes"
- "fmt"
- "io"
- "os"
-)
-
-type pos struct {
- idx int
- offset int64
-}
-
-type multiReadSeeker struct {
- readers []io.ReadSeeker
- pos *pos
- posIdx map[io.ReadSeeker]int
-}
-
-func (r *multiReadSeeker) Seek(offset int64, whence int) (int64, error) {
- var tmpOffset int64
- switch whence {
- case os.SEEK_SET:
- for i, rdr := range r.readers {
- // get size of the current reader
- s, err := rdr.Seek(0, os.SEEK_END)
- if err != nil {
- return -1, err
- }
-
- if offset > tmpOffset+s {
- if i == len(r.readers)-1 {
- rdrOffset := s + (offset - tmpOffset)
- if _, err := rdr.Seek(rdrOffset, os.SEEK_SET); err != nil {
- return -1, err
- }
- r.pos = &pos{i, rdrOffset}
- return offset, nil
- }
-
- tmpOffset += s
- continue
- }
-
- rdrOffset := offset - tmpOffset
- idx := i
-
- rdr.Seek(rdrOffset, os.SEEK_SET)
- // make sure all following readers are at 0
- for _, rdr := range r.readers[i+1:] {
- rdr.Seek(0, os.SEEK_SET)
- }
-
- if rdrOffset == s && i != len(r.readers)-1 {
- idx++
- rdrOffset = 0
- }
- r.pos = &pos{idx, rdrOffset}
- return offset, nil
- }
- case os.SEEK_END:
- for _, rdr := range r.readers {
- s, err := rdr.Seek(0, os.SEEK_END)
- if err != nil {
- return -1, err
- }
- tmpOffset += s
- }
- r.Seek(tmpOffset+offset, os.SEEK_SET)
- return tmpOffset + offset, nil
- case os.SEEK_CUR:
- if r.pos == nil {
- return r.Seek(offset, os.SEEK_SET)
- }
- // Just return the current offset
- if offset == 0 {
- return r.getCurOffset()
- }
-
- curOffset, err := r.getCurOffset()
- if err != nil {
- return -1, err
- }
- rdr, rdrOffset, err := r.getReaderForOffset(curOffset + offset)
- if err != nil {
- return -1, err
- }
-
- r.pos = &pos{r.posIdx[rdr], rdrOffset}
- return curOffset + offset, nil
- default:
- return -1, fmt.Errorf("Invalid whence: %d", whence)
- }
-
- return -1, fmt.Errorf("Error seeking for whence: %d, offset: %d", whence, offset)
-}
-
-func (r *multiReadSeeker) getReaderForOffset(offset int64) (io.ReadSeeker, int64, error) {
- var rdr io.ReadSeeker
- var rdrOffset int64
-
- for i, rdr := range r.readers {
- offsetTo, err := r.getOffsetToReader(rdr)
- if err != nil {
- return nil, -1, err
- }
- if offsetTo > offset {
- rdr = r.readers[i-1]
- rdrOffset = offsetTo - offset
- break
- }
-
- if rdr == r.readers[len(r.readers)-1] {
- rdrOffset = offsetTo + offset
- break
- }
- }
-
- return rdr, rdrOffset, nil
-}
-
-func (r *multiReadSeeker) getCurOffset() (int64, error) {
- var totalSize int64
- for _, rdr := range r.readers[:r.pos.idx+1] {
- if r.posIdx[rdr] == r.pos.idx {
- totalSize += r.pos.offset
- break
- }
-
- size, err := getReadSeekerSize(rdr)
- if err != nil {
- return -1, fmt.Errorf("error getting seeker size: %v", err)
- }
- totalSize += size
- }
- return totalSize, nil
-}
-
-func (r *multiReadSeeker) getOffsetToReader(rdr io.ReadSeeker) (int64, error) {
- var offset int64
- for _, r := range r.readers {
- if r == rdr {
- break
- }
-
- size, err := getReadSeekerSize(rdr)
- if err != nil {
- return -1, err
- }
- offset += size
- }
- return offset, nil
-}
-
-func (r *multiReadSeeker) Read(b []byte) (int, error) {
- if r.pos == nil {
- r.pos = &pos{0, 0}
- }
-
- bCap := int64(cap(b))
- buf := bytes.NewBuffer(nil)
- var rdr io.ReadSeeker
-
- for _, rdr = range r.readers[r.pos.idx:] {
- readBytes, err := io.CopyN(buf, rdr, bCap)
- if err != nil && err != io.EOF {
- return -1, err
- }
- bCap -= readBytes
-
- if bCap == 0 {
- break
- }
- }
-
- rdrPos, err := rdr.Seek(0, os.SEEK_CUR)
- if err != nil {
- return -1, err
- }
- r.pos = &pos{r.posIdx[rdr], rdrPos}
- return buf.Read(b)
-}
-
-func getReadSeekerSize(rdr io.ReadSeeker) (int64, error) {
- // save the current position
- pos, err := rdr.Seek(0, os.SEEK_CUR)
- if err != nil {
- return -1, err
- }
-
- // get the size
- size, err := rdr.Seek(0, os.SEEK_END)
- if err != nil {
- return -1, err
- }
-
- // reset the position
- if _, err := rdr.Seek(pos, os.SEEK_SET); err != nil {
- return -1, err
- }
- return size, nil
-}
-
-// MultiReadSeeker returns a ReadSeeker that's the logical concatenation of the provided
-// input readseekers. After calling this method the initial position is set to the
-// beginning of the first ReadSeeker. At the end of a ReadSeeker, Read always advances
-// to the beginning of the next ReadSeeker and returns EOF at the end of the last ReadSeeker.
-// Seek can be used over the sum of lengths of all readseekers.
-//
-// When a MultiReadSeeker is used, no Read and Seek operations should be made on
-// its ReadSeeker components. Also, users should make no assumption on the state
-// of individual readseekers while the MultiReadSeeker is used.
-func MultiReadSeeker(readers ...io.ReadSeeker) io.ReadSeeker {
- if len(readers) == 1 {
- return readers[0]
- }
- idx := make(map[io.ReadSeeker]int)
- for i, rdr := range readers {
- idx[rdr] = i
- }
- return &multiReadSeeker{
- readers: readers,
- posIdx: idx,
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/multireader_test.go b/vendor/github.com/docker/docker/pkg/ioutils/multireader_test.go
deleted file mode 100644
index de495b5..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/multireader_test.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package ioutils
-
-import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "strings"
- "testing"
-)
-
-func TestMultiReadSeekerReadAll(t *testing.T) {
- str := "hello world"
- s1 := strings.NewReader(str + " 1")
- s2 := strings.NewReader(str + " 2")
- s3 := strings.NewReader(str + " 3")
- mr := MultiReadSeeker(s1, s2, s3)
-
- expectedSize := int64(s1.Len() + s2.Len() + s3.Len())
-
- b, err := ioutil.ReadAll(mr)
- if err != nil {
- t.Fatal(err)
- }
-
- expected := "hello world 1hello world 2hello world 3"
- if string(b) != expected {
- t.Fatalf("ReadAll failed, got: %q, expected %q", string(b), expected)
- }
-
- size, err := mr.Seek(0, os.SEEK_END)
- if err != nil {
- t.Fatal(err)
- }
- if size != expectedSize {
- t.Fatalf("reader size does not match, got %d, expected %d", size, expectedSize)
- }
-
- // Reset the position and read again
- pos, err := mr.Seek(0, os.SEEK_SET)
- if err != nil {
- t.Fatal(err)
- }
- if pos != 0 {
- t.Fatalf("expected position to be set to 0, got %d", pos)
- }
-
- b, err = ioutil.ReadAll(mr)
- if err != nil {
- t.Fatal(err)
- }
-
- if string(b) != expected {
- t.Fatalf("ReadAll failed, got: %q, expected %q", string(b), expected)
- }
-}
-
-func TestMultiReadSeekerReadEach(t *testing.T) {
- str := "hello world"
- s1 := strings.NewReader(str + " 1")
- s2 := strings.NewReader(str + " 2")
- s3 := strings.NewReader(str + " 3")
- mr := MultiReadSeeker(s1, s2, s3)
-
- var totalBytes int64
- for i, s := range []*strings.Reader{s1, s2, s3} {
- sLen := int64(s.Len())
- buf := make([]byte, s.Len())
- expected := []byte(fmt.Sprintf("%s %d", str, i+1))
-
- if _, err := mr.Read(buf); err != nil && err != io.EOF {
- t.Fatal(err)
- }
-
- if !bytes.Equal(buf, expected) {
- t.Fatalf("expected %q to be %q", string(buf), string(expected))
- }
-
- pos, err := mr.Seek(0, os.SEEK_CUR)
- if err != nil {
- t.Fatalf("iteration: %d, error: %v", i+1, err)
- }
-
- // check that the total bytes read is the current position of the seeker
- totalBytes += sLen
- if pos != totalBytes {
- t.Fatalf("expected current position to be: %d, got: %d, iteration: %d", totalBytes, pos, i+1)
- }
-
- // This tests not only that SEEK_SET and SEEK_CUR give the same values, but that the next iteration is in the expected position as well
- newPos, err := mr.Seek(pos, os.SEEK_SET)
- if err != nil {
- t.Fatal(err)
- }
- if newPos != pos {
- t.Fatalf("expected to get same position when calling SEEK_SET with value from SEEK_CUR, cur: %d, set: %d", pos, newPos)
- }
- }
-}
-
-func TestMultiReadSeekerReadSpanningChunks(t *testing.T) {
- str := "hello world"
- s1 := strings.NewReader(str + " 1")
- s2 := strings.NewReader(str + " 2")
- s3 := strings.NewReader(str + " 3")
- mr := MultiReadSeeker(s1, s2, s3)
-
- buf := make([]byte, s1.Len()+3)
- _, err := mr.Read(buf)
- if err != nil {
- t.Fatal(err)
- }
-
- // expected is the contents of s1 + 3 bytes from s2, ie, the `hel` at the end of this string
- expected := "hello world 1hel"
- if string(buf) != expected {
- t.Fatalf("expected %s to be %s", string(buf), expected)
- }
-}
-
-func TestMultiReadSeekerNegativeSeek(t *testing.T) {
- str := "hello world"
- s1 := strings.NewReader(str + " 1")
- s2 := strings.NewReader(str + " 2")
- s3 := strings.NewReader(str + " 3")
- mr := MultiReadSeeker(s1, s2, s3)
-
- s1Len := s1.Len()
- s2Len := s2.Len()
- s3Len := s3.Len()
-
- s, err := mr.Seek(int64(-1*s3.Len()), os.SEEK_END)
- if err != nil {
- t.Fatal(err)
- }
- if s != int64(s1Len+s2Len) {
- t.Fatalf("expected %d to be %d", s, s1.Len()+s2.Len())
- }
-
- buf := make([]byte, s3Len)
- if _, err := mr.Read(buf); err != nil && err != io.EOF {
- t.Fatal(err)
- }
- expected := fmt.Sprintf("%s %d", str, 3)
- if string(buf) != fmt.Sprintf("%s %d", str, 3) {
- t.Fatalf("expected %q to be %q", string(buf), expected)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers.go b/vendor/github.com/docker/docker/pkg/ioutils/readers.go
deleted file mode 100644
index 63f3c07..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/readers.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package ioutils
-
-import (
- "crypto/sha256"
- "encoding/hex"
- "io"
-
- "golang.org/x/net/context"
-)
-
-type readCloserWrapper struct {
- io.Reader
- closer func() error
-}
-
-func (r *readCloserWrapper) Close() error {
- return r.closer()
-}
-
-// NewReadCloserWrapper returns a new io.ReadCloser.
-func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser {
- return &readCloserWrapper{
- Reader: r,
- closer: closer,
- }
-}
-
-type readerErrWrapper struct {
- reader io.Reader
- closer func()
-}
-
-func (r *readerErrWrapper) Read(p []byte) (int, error) {
- n, err := r.reader.Read(p)
- if err != nil {
- r.closer()
- }
- return n, err
-}
-
-// NewReaderErrWrapper returns a new io.Reader.
-func NewReaderErrWrapper(r io.Reader, closer func()) io.Reader {
- return &readerErrWrapper{
- reader: r,
- closer: closer,
- }
-}
-
-// HashData returns the sha256 sum of src.
-func HashData(src io.Reader) (string, error) {
- h := sha256.New()
- if _, err := io.Copy(h, src); err != nil {
- return "", err
- }
- return "sha256:" + hex.EncodeToString(h.Sum(nil)), nil
-}
-
-// OnEOFReader wraps an io.ReadCloser and a function
-// the function will run at the end of file or close the file.
-type OnEOFReader struct {
- Rc io.ReadCloser
- Fn func()
-}
-
-func (r *OnEOFReader) Read(p []byte) (n int, err error) {
- n, err = r.Rc.Read(p)
- if err == io.EOF {
- r.runFunc()
- }
- return
-}
-
-// Close closes the file and run the function.
-func (r *OnEOFReader) Close() error {
- err := r.Rc.Close()
- r.runFunc()
- return err
-}
-
-func (r *OnEOFReader) runFunc() {
- if fn := r.Fn; fn != nil {
- fn()
- r.Fn = nil
- }
-}
-
-// cancelReadCloser wraps an io.ReadCloser with a context for cancelling read
-// operations.
-type cancelReadCloser struct {
- cancel func()
- pR *io.PipeReader // Stream to read from
- pW *io.PipeWriter
-}
-
-// NewCancelReadCloser creates a wrapper that closes the ReadCloser when the
-// context is cancelled. The returned io.ReadCloser must be closed when it is
-// no longer needed.
-func NewCancelReadCloser(ctx context.Context, in io.ReadCloser) io.ReadCloser {
- pR, pW := io.Pipe()
-
- // Create a context used to signal when the pipe is closed
- doneCtx, cancel := context.WithCancel(context.Background())
-
- p := &cancelReadCloser{
- cancel: cancel,
- pR: pR,
- pW: pW,
- }
-
- go func() {
- _, err := io.Copy(pW, in)
- select {
- case <-ctx.Done():
- // If the context was closed, p.closeWithError
- // was already called. Calling it again would
- // change the error that Read returns.
- default:
- p.closeWithError(err)
- }
- in.Close()
- }()
- go func() {
- for {
- select {
- case <-ctx.Done():
- p.closeWithError(ctx.Err())
- case <-doneCtx.Done():
- return
- }
- }
- }()
-
- return p
-}
-
-// Read wraps the Read method of the pipe that provides data from the wrapped
-// ReadCloser.
-func (p *cancelReadCloser) Read(buf []byte) (n int, err error) {
- return p.pR.Read(buf)
-}
-
-// closeWithError closes the wrapper and its underlying reader. It will
-// cause future calls to Read to return err.
-func (p *cancelReadCloser) closeWithError(err error) {
- p.pW.CloseWithError(err)
- p.cancel()
-}
-
-// Close closes the wrapper its underlying reader. It will cause
-// future calls to Read to return io.EOF.
-func (p *cancelReadCloser) Close() error {
- p.closeWithError(io.EOF)
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers_test.go b/vendor/github.com/docker/docker/pkg/ioutils/readers_test.go
deleted file mode 100644
index 9abc105..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/readers_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package ioutils
-
-import (
- "fmt"
- "io/ioutil"
- "strings"
- "testing"
- "time"
-
- "golang.org/x/net/context"
-)
-
-// Implement io.Reader
-type errorReader struct{}
-
-func (r *errorReader) Read(p []byte) (int, error) {
- return 0, fmt.Errorf("Error reader always fail.")
-}
-
-func TestReadCloserWrapperClose(t *testing.T) {
- reader := strings.NewReader("A string reader")
- wrapper := NewReadCloserWrapper(reader, func() error {
- return fmt.Errorf("This will be called when closing")
- })
- err := wrapper.Close()
- if err == nil || !strings.Contains(err.Error(), "This will be called when closing") {
- t.Fatalf("readCloserWrapper should have call the anonymous func and thus, fail.")
- }
-}
-
-func TestReaderErrWrapperReadOnError(t *testing.T) {
- called := false
- reader := &errorReader{}
- wrapper := NewReaderErrWrapper(reader, func() {
- called = true
- })
- _, err := wrapper.Read([]byte{})
- if err == nil || !strings.Contains(err.Error(), "Error reader always fail.") {
- t.Fatalf("readErrWrapper should returned an error")
- }
- if !called {
- t.Fatalf("readErrWrapper should have call the anonymous function on failure")
- }
-}
-
-func TestReaderErrWrapperRead(t *testing.T) {
- reader := strings.NewReader("a string reader.")
- wrapper := NewReaderErrWrapper(reader, func() {
- t.Fatalf("readErrWrapper should not have called the anonymous function")
- })
- // Read 20 byte (should be ok with the string above)
- num, err := wrapper.Read(make([]byte, 20))
- if err != nil {
- t.Fatal(err)
- }
- if num != 16 {
- t.Fatalf("readerErrWrapper should have read 16 byte, but read %d", num)
- }
-}
-
-func TestHashData(t *testing.T) {
- reader := strings.NewReader("hash-me")
- actual, err := HashData(reader)
- if err != nil {
- t.Fatal(err)
- }
- expected := "sha256:4d11186aed035cc624d553e10db358492c84a7cd6b9670d92123c144930450aa"
- if actual != expected {
- t.Fatalf("Expecting %s, got %s", expected, actual)
- }
-}
-
-type perpetualReader struct{}
-
-func (p *perpetualReader) Read(buf []byte) (n int, err error) {
- for i := 0; i != len(buf); i++ {
- buf[i] = 'a'
- }
- return len(buf), nil
-}
-
-func TestCancelReadCloser(t *testing.T) {
- ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond)
- cancelReadCloser := NewCancelReadCloser(ctx, ioutil.NopCloser(&perpetualReader{}))
- for {
- var buf [128]byte
- _, err := cancelReadCloser.Read(buf[:])
- if err == context.DeadlineExceeded {
- break
- } else if err != nil {
- t.Fatalf("got unexpected error: %v", err)
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go b/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go
deleted file mode 100644
index 1539ad2..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// +build !windows
-
-package ioutils
-
-import "io/ioutil"
-
-// TempDir on Unix systems is equivalent to ioutil.TempDir.
-func TempDir(dir, prefix string) (string, error) {
- return ioutil.TempDir(dir, prefix)
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go b/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go
deleted file mode 100644
index c258e5f..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// +build windows
-
-package ioutils
-
-import (
- "io/ioutil"
-
- "github.com/docker/docker/pkg/longpath"
-)
-
-// TempDir is the equivalent of ioutil.TempDir, except that the result is in Windows longpath format.
-func TempDir(dir, prefix string) (string, error) {
- tempDir, err := ioutil.TempDir(dir, prefix)
- if err != nil {
- return "", err
- }
- return longpath.AddPrefix(tempDir), nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go
deleted file mode 100644
index 52a4901..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go
+++ /dev/null
@@ -1,92 +0,0 @@
-package ioutils
-
-import (
- "io"
- "sync"
-)
-
-// WriteFlusher wraps the Write and Flush operation ensuring that every write
-// is a flush. In addition, the Close method can be called to intercept
-// Read/Write calls if the targets lifecycle has already ended.
-type WriteFlusher struct {
- w io.Writer
- flusher flusher
- flushed chan struct{}
- flushedOnce sync.Once
- closed chan struct{}
- closeLock sync.Mutex
-}
-
-type flusher interface {
- Flush()
-}
-
-var errWriteFlusherClosed = io.EOF
-
-func (wf *WriteFlusher) Write(b []byte) (n int, err error) {
- select {
- case <-wf.closed:
- return 0, errWriteFlusherClosed
- default:
- }
-
- n, err = wf.w.Write(b)
- wf.Flush() // every write is a flush.
- return n, err
-}
-
-// Flush the stream immediately.
-func (wf *WriteFlusher) Flush() {
- select {
- case <-wf.closed:
- return
- default:
- }
-
- wf.flushedOnce.Do(func() {
- close(wf.flushed)
- })
- wf.flusher.Flush()
-}
-
-// Flushed returns the state of flushed.
-// If it's flushed, return true, or else it return false.
-func (wf *WriteFlusher) Flushed() bool {
- // BUG(stevvooe): Remove this method. Its use is inherently racy. Seems to
- // be used to detect whether or a response code has been issued or not.
- // Another hook should be used instead.
- var flushed bool
- select {
- case <-wf.flushed:
- flushed = true
- default:
- }
- return flushed
-}
-
-// Close closes the write flusher, disallowing any further writes to the
-// target. After the flusher is closed, all calls to write or flush will
-// result in an error.
-func (wf *WriteFlusher) Close() error {
- wf.closeLock.Lock()
- defer wf.closeLock.Unlock()
-
- select {
- case <-wf.closed:
- return errWriteFlusherClosed
- default:
- close(wf.closed)
- }
- return nil
-}
-
-// NewWriteFlusher returns a new WriteFlusher.
-func NewWriteFlusher(w io.Writer) *WriteFlusher {
- var fl flusher
- if f, ok := w.(flusher); ok {
- fl = f
- } else {
- fl = &NopFlusher{}
- }
- return &WriteFlusher{w: w, flusher: fl, closed: make(chan struct{}), flushed: make(chan struct{})}
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers.go b/vendor/github.com/docker/docker/pkg/ioutils/writers.go
deleted file mode 100644
index ccc7f9c..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/writers.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package ioutils
-
-import "io"
-
-// NopWriter represents a type which write operation is nop.
-type NopWriter struct{}
-
-func (*NopWriter) Write(buf []byte) (int, error) {
- return len(buf), nil
-}
-
-type nopWriteCloser struct {
- io.Writer
-}
-
-func (w *nopWriteCloser) Close() error { return nil }
-
-// NopWriteCloser returns a nopWriteCloser.
-func NopWriteCloser(w io.Writer) io.WriteCloser {
- return &nopWriteCloser{w}
-}
-
-// NopFlusher represents a type which flush operation is nop.
-type NopFlusher struct{}
-
-// Flush is a nop operation.
-func (f *NopFlusher) Flush() {}
-
-type writeCloserWrapper struct {
- io.Writer
- closer func() error
-}
-
-func (r *writeCloserWrapper) Close() error {
- return r.closer()
-}
-
-// NewWriteCloserWrapper returns a new io.WriteCloser.
-func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser {
- return &writeCloserWrapper{
- Writer: r,
- closer: closer,
- }
-}
-
-// WriteCounter wraps a concrete io.Writer and hold a count of the number
-// of bytes written to the writer during a "session".
-// This can be convenient when write return is masked
-// (e.g., json.Encoder.Encode())
-type WriteCounter struct {
- Count int64
- Writer io.Writer
-}
-
-// NewWriteCounter returns a new WriteCounter.
-func NewWriteCounter(w io.Writer) *WriteCounter {
- return &WriteCounter{
- Writer: w,
- }
-}
-
-func (wc *WriteCounter) Write(p []byte) (count int, err error) {
- count, err = wc.Writer.Write(p)
- wc.Count += int64(count)
- return
-}
diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers_test.go b/vendor/github.com/docker/docker/pkg/ioutils/writers_test.go
deleted file mode 100644
index 564b1cd..0000000
--- a/vendor/github.com/docker/docker/pkg/ioutils/writers_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package ioutils
-
-import (
- "bytes"
- "strings"
- "testing"
-)
-
-func TestWriteCloserWrapperClose(t *testing.T) {
- called := false
- writer := bytes.NewBuffer([]byte{})
- wrapper := NewWriteCloserWrapper(writer, func() error {
- called = true
- return nil
- })
- if err := wrapper.Close(); err != nil {
- t.Fatal(err)
- }
- if !called {
- t.Fatalf("writeCloserWrapper should have call the anonymous function.")
- }
-}
-
-func TestNopWriteCloser(t *testing.T) {
- writer := bytes.NewBuffer([]byte{})
- wrapper := NopWriteCloser(writer)
- if err := wrapper.Close(); err != nil {
- t.Fatal("NopWriteCloser always return nil on Close.")
- }
-
-}
-
-func TestNopWriter(t *testing.T) {
- nw := &NopWriter{}
- l, err := nw.Write([]byte{'c'})
- if err != nil {
- t.Fatal(err)
- }
- if l != 1 {
- t.Fatalf("Expected 1 got %d", l)
- }
-}
-
-func TestWriteCounter(t *testing.T) {
- dummy1 := "This is a dummy string."
- dummy2 := "This is another dummy string."
- totalLength := int64(len(dummy1) + len(dummy2))
-
- reader1 := strings.NewReader(dummy1)
- reader2 := strings.NewReader(dummy2)
-
- var buffer bytes.Buffer
- wc := NewWriteCounter(&buffer)
-
- reader1.WriteTo(wc)
- reader2.WriteTo(wc)
-
- if wc.Count != totalLength {
- t.Errorf("Wrong count: %d vs. %d", wc.Count, totalLength)
- }
-
- if buffer.String() != dummy1+dummy2 {
- t.Error("Wrong message written")
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/longpath/longpath.go b/vendor/github.com/docker/docker/pkg/longpath/longpath.go
deleted file mode 100644
index 9b15bff..0000000
--- a/vendor/github.com/docker/docker/pkg/longpath/longpath.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// longpath introduces some constants and helper functions for handling long paths
-// in Windows, which are expected to be prepended with `\\?\` and followed by either
-// a drive letter, a UNC server\share, or a volume identifier.
-
-package longpath
-
-import (
- "strings"
-)
-
-// Prefix is the longpath prefix for Windows file paths.
-const Prefix = `\\?\`
-
-// AddPrefix will add the Windows long path prefix to the path provided if
-// it does not already have it.
-func AddPrefix(path string) string {
- if !strings.HasPrefix(path, Prefix) {
- if strings.HasPrefix(path, `\\`) {
- // This is a UNC path, so we need to add 'UNC' to the path as well.
- path = Prefix + `UNC` + path[1:]
- } else {
- path = Prefix + path
- }
- }
- return path
-}
diff --git a/vendor/github.com/docker/docker/pkg/longpath/longpath_test.go b/vendor/github.com/docker/docker/pkg/longpath/longpath_test.go
deleted file mode 100644
index 01865ef..0000000
--- a/vendor/github.com/docker/docker/pkg/longpath/longpath_test.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package longpath
-
-import (
- "strings"
- "testing"
-)
-
-func TestStandardLongPath(t *testing.T) {
- c := `C:\simple\path`
- longC := AddPrefix(c)
- if !strings.EqualFold(longC, `\\?\C:\simple\path`) {
- t.Errorf("Wrong long path returned. Original = %s ; Long = %s", c, longC)
- }
-}
-
-func TestUNCLongPath(t *testing.T) {
- c := `\\server\share\path`
- longC := AddPrefix(c)
- if !strings.EqualFold(longC, `\\?\UNC\server\share\path`) {
- t.Errorf("Wrong UNC long path returned. Original = %s ; Long = %s", c, longC)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/pools/pools.go b/vendor/github.com/docker/docker/pkg/pools/pools.go
deleted file mode 100644
index 76e84f9..0000000
--- a/vendor/github.com/docker/docker/pkg/pools/pools.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Package pools provides a collection of pools which provide various
-// data types with buffers. These can be used to lower the number of
-// memory allocations and reuse buffers.
-//
-// New pools should be added to this package to allow them to be
-// shared across packages.
-//
-// Utility functions which operate on pools should be added to this
-// package to allow them to be reused.
-package pools
-
-import (
- "bufio"
- "io"
- "sync"
-
- "github.com/docker/docker/pkg/ioutils"
-)
-
-var (
- // BufioReader32KPool is a pool which returns bufio.Reader with a 32K buffer.
- BufioReader32KPool *BufioReaderPool
- // BufioWriter32KPool is a pool which returns bufio.Writer with a 32K buffer.
- BufioWriter32KPool *BufioWriterPool
-)
-
-const buffer32K = 32 * 1024
-
-// BufioReaderPool is a bufio reader that uses sync.Pool.
-type BufioReaderPool struct {
- pool sync.Pool
-}
-
-func init() {
- BufioReader32KPool = newBufioReaderPoolWithSize(buffer32K)
- BufioWriter32KPool = newBufioWriterPoolWithSize(buffer32K)
-}
-
-// newBufioReaderPoolWithSize is unexported because new pools should be
-// added here to be shared where required.
-func newBufioReaderPoolWithSize(size int) *BufioReaderPool {
- pool := sync.Pool{
- New: func() interface{} { return bufio.NewReaderSize(nil, size) },
- }
- return &BufioReaderPool{pool: pool}
-}
-
-// Get returns a bufio.Reader which reads from r. The buffer size is that of the pool.
-func (bufPool *BufioReaderPool) Get(r io.Reader) *bufio.Reader {
- buf := bufPool.pool.Get().(*bufio.Reader)
- buf.Reset(r)
- return buf
-}
-
-// Put puts the bufio.Reader back into the pool.
-func (bufPool *BufioReaderPool) Put(b *bufio.Reader) {
- b.Reset(nil)
- bufPool.pool.Put(b)
-}
-
-// Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy.
-func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
- buf := BufioReader32KPool.Get(src)
- written, err = io.Copy(dst, buf)
- BufioReader32KPool.Put(buf)
- return
-}
-
-// NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back
-// into the pool and closes the reader if it's an io.ReadCloser.
-func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser {
- return ioutils.NewReadCloserWrapper(r, func() error {
- if readCloser, ok := r.(io.ReadCloser); ok {
- readCloser.Close()
- }
- bufPool.Put(buf)
- return nil
- })
-}
-
-// BufioWriterPool is a bufio writer that uses sync.Pool.
-type BufioWriterPool struct {
- pool sync.Pool
-}
-
-// newBufioWriterPoolWithSize is unexported because new pools should be
-// added here to be shared where required.
-func newBufioWriterPoolWithSize(size int) *BufioWriterPool {
- pool := sync.Pool{
- New: func() interface{} { return bufio.NewWriterSize(nil, size) },
- }
- return &BufioWriterPool{pool: pool}
-}
-
-// Get returns a bufio.Writer which writes to w. The buffer size is that of the pool.
-func (bufPool *BufioWriterPool) Get(w io.Writer) *bufio.Writer {
- buf := bufPool.pool.Get().(*bufio.Writer)
- buf.Reset(w)
- return buf
-}
-
-// Put puts the bufio.Writer back into the pool.
-func (bufPool *BufioWriterPool) Put(b *bufio.Writer) {
- b.Reset(nil)
- bufPool.pool.Put(b)
-}
-
-// NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back
-// into the pool and closes the writer if it's an io.Writecloser.
-func (bufPool *BufioWriterPool) NewWriteCloserWrapper(buf *bufio.Writer, w io.Writer) io.WriteCloser {
- return ioutils.NewWriteCloserWrapper(w, func() error {
- buf.Flush()
- if writeCloser, ok := w.(io.WriteCloser); ok {
- writeCloser.Close()
- }
- bufPool.Put(buf)
- return nil
- })
-}
diff --git a/vendor/github.com/docker/docker/pkg/pools/pools_test.go b/vendor/github.com/docker/docker/pkg/pools/pools_test.go
deleted file mode 100644
index 1661b78..0000000
--- a/vendor/github.com/docker/docker/pkg/pools/pools_test.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package pools
-
-import (
- "bufio"
- "bytes"
- "io"
- "strings"
- "testing"
-)
-
-func TestBufioReaderPoolGetWithNoReaderShouldCreateOne(t *testing.T) {
- reader := BufioReader32KPool.Get(nil)
- if reader == nil {
- t.Fatalf("BufioReaderPool should have create a bufio.Reader but did not.")
- }
-}
-
-func TestBufioReaderPoolPutAndGet(t *testing.T) {
- sr := bufio.NewReader(strings.NewReader("foobar"))
- reader := BufioReader32KPool.Get(sr)
- if reader == nil {
- t.Fatalf("BufioReaderPool should not return a nil reader.")
- }
- // verify the first 3 byte
- buf1 := make([]byte, 3)
- _, err := reader.Read(buf1)
- if err != nil {
- t.Fatal(err)
- }
- if actual := string(buf1); actual != "foo" {
- t.Fatalf("The first letter should have been 'foo' but was %v", actual)
- }
- BufioReader32KPool.Put(reader)
- // Try to read the next 3 bytes
- _, err = sr.Read(make([]byte, 3))
- if err == nil || err != io.EOF {
- t.Fatalf("The buffer should have been empty, issue an EOF error.")
- }
-}
-
-type simpleReaderCloser struct {
- io.Reader
- closed bool
-}
-
-func (r *simpleReaderCloser) Close() error {
- r.closed = true
- return nil
-}
-
-func TestNewReadCloserWrapperWithAReadCloser(t *testing.T) {
- br := bufio.NewReader(strings.NewReader(""))
- sr := &simpleReaderCloser{
- Reader: strings.NewReader("foobar"),
- closed: false,
- }
- reader := BufioReader32KPool.NewReadCloserWrapper(br, sr)
- if reader == nil {
- t.Fatalf("NewReadCloserWrapper should not return a nil reader.")
- }
- // Verify the content of reader
- buf := make([]byte, 3)
- _, err := reader.Read(buf)
- if err != nil {
- t.Fatal(err)
- }
- if actual := string(buf); actual != "foo" {
- t.Fatalf("The first 3 letter should have been 'foo' but were %v", actual)
- }
- reader.Close()
- // Read 3 more bytes "bar"
- _, err = reader.Read(buf)
- if err != nil {
- t.Fatal(err)
- }
- if actual := string(buf); actual != "bar" {
- t.Fatalf("The first 3 letter should have been 'bar' but were %v", actual)
- }
- if !sr.closed {
- t.Fatalf("The ReaderCloser should have been closed, it is not.")
- }
-}
-
-func TestBufioWriterPoolGetWithNoReaderShouldCreateOne(t *testing.T) {
- writer := BufioWriter32KPool.Get(nil)
- if writer == nil {
- t.Fatalf("BufioWriterPool should have create a bufio.Writer but did not.")
- }
-}
-
-func TestBufioWriterPoolPutAndGet(t *testing.T) {
- buf := new(bytes.Buffer)
- bw := bufio.NewWriter(buf)
- writer := BufioWriter32KPool.Get(bw)
- if writer == nil {
- t.Fatalf("BufioReaderPool should not return a nil writer.")
- }
- written, err := writer.Write([]byte("foobar"))
- if err != nil {
- t.Fatal(err)
- }
- if written != 6 {
- t.Fatalf("Should have written 6 bytes, but wrote %v bytes", written)
- }
- // Make sure we Flush all the way ?
- writer.Flush()
- bw.Flush()
- if len(buf.Bytes()) != 6 {
- t.Fatalf("The buffer should contain 6 bytes ('foobar') but contains %v ('%v')", buf.Bytes(), string(buf.Bytes()))
- }
- // Reset the buffer
- buf.Reset()
- BufioWriter32KPool.Put(writer)
- // Try to write something
- if _, err = writer.Write([]byte("barfoo")); err != nil {
- t.Fatal(err)
- }
- // If we now try to flush it, it should panic (the writer is nil)
- // recover it
- defer func() {
- if r := recover(); r == nil {
- t.Fatal("Trying to flush the writter should have 'paniced', did not.")
- }
- }()
- writer.Flush()
-}
-
-type simpleWriterCloser struct {
- io.Writer
- closed bool
-}
-
-func (r *simpleWriterCloser) Close() error {
- r.closed = true
- return nil
-}
-
-func TestNewWriteCloserWrapperWithAWriteCloser(t *testing.T) {
- buf := new(bytes.Buffer)
- bw := bufio.NewWriter(buf)
- sw := &simpleWriterCloser{
- Writer: new(bytes.Buffer),
- closed: false,
- }
- bw.Flush()
- writer := BufioWriter32KPool.NewWriteCloserWrapper(bw, sw)
- if writer == nil {
- t.Fatalf("BufioReaderPool should not return a nil writer.")
- }
- written, err := writer.Write([]byte("foobar"))
- if err != nil {
- t.Fatal(err)
- }
- if written != 6 {
- t.Fatalf("Should have written 6 bytes, but wrote %v bytes", written)
- }
- writer.Close()
- if !sw.closed {
- t.Fatalf("The ReaderCloser should have been closed, it is not.")
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/promise/promise.go b/vendor/github.com/docker/docker/pkg/promise/promise.go
deleted file mode 100644
index dd52b90..0000000
--- a/vendor/github.com/docker/docker/pkg/promise/promise.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package promise
-
-// Go is a basic promise implementation: it wraps calls a function in a goroutine,
-// and returns a channel which will later return the function's return value.
-func Go(f func() error) chan error {
- ch := make(chan error, 1)
- go func() {
- ch <- f()
- }()
- return ch
-}
diff --git a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go b/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go
deleted file mode 100644
index 8f67ece..0000000
--- a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy.go
+++ /dev/null
@@ -1,185 +0,0 @@
-package stdcopy
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "sync"
-
- "github.com/Sirupsen/logrus"
-)
-
-// StdType is the type of standard stream
-// a writer can multiplex to.
-type StdType byte
-
-const (
- // Stdin represents standard input stream type.
- Stdin StdType = iota
- // Stdout represents standard output stream type.
- Stdout
- // Stderr represents standard error steam type.
- Stderr
-
- stdWriterPrefixLen = 8
- stdWriterFdIndex = 0
- stdWriterSizeIndex = 4
-
- startingBufLen = 32*1024 + stdWriterPrefixLen + 1
-)
-
-var bufPool = &sync.Pool{New: func() interface{} { return bytes.NewBuffer(nil) }}
-
-// stdWriter is wrapper of io.Writer with extra customized info.
-type stdWriter struct {
- io.Writer
- prefix byte
-}
-
-// Write sends the buffer to the underneath writer.
-// It inserts the prefix header before the buffer,
-// so stdcopy.StdCopy knows where to multiplex the output.
-// It makes stdWriter to implement io.Writer.
-func (w *stdWriter) Write(p []byte) (n int, err error) {
- if w == nil || w.Writer == nil {
- return 0, errors.New("Writer not instantiated")
- }
- if p == nil {
- return 0, nil
- }
-
- header := [stdWriterPrefixLen]byte{stdWriterFdIndex: w.prefix}
- binary.BigEndian.PutUint32(header[stdWriterSizeIndex:], uint32(len(p)))
- buf := bufPool.Get().(*bytes.Buffer)
- buf.Write(header[:])
- buf.Write(p)
-
- n, err = w.Writer.Write(buf.Bytes())
- n -= stdWriterPrefixLen
- if n < 0 {
- n = 0
- }
-
- buf.Reset()
- bufPool.Put(buf)
- return
-}
-
-// NewStdWriter instantiates a new Writer.
-// Everything written to it will be encapsulated using a custom format,
-// and written to the underlying `w` stream.
-// This allows multiple write streams (e.g. stdout and stderr) to be muxed into a single connection.
-// `t` indicates the id of the stream to encapsulate.
-// It can be stdcopy.Stdin, stdcopy.Stdout, stdcopy.Stderr.
-func NewStdWriter(w io.Writer, t StdType) io.Writer {
- return &stdWriter{
- Writer: w,
- prefix: byte(t),
- }
-}
-
-// StdCopy is a modified version of io.Copy.
-//
-// StdCopy will demultiplex `src`, assuming that it contains two streams,
-// previously multiplexed together using a StdWriter instance.
-// As it reads from `src`, StdCopy will write to `dstout` and `dsterr`.
-//
-// StdCopy will read until it hits EOF on `src`. It will then return a nil error.
-// In other words: if `err` is non nil, it indicates a real underlying error.
-//
-// `written` will hold the total number of bytes written to `dstout` and `dsterr`.
-func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) {
- var (
- buf = make([]byte, startingBufLen)
- bufLen = len(buf)
- nr, nw int
- er, ew error
- out io.Writer
- frameSize int
- )
-
- for {
- // Make sure we have at least a full header
- for nr < stdWriterPrefixLen {
- var nr2 int
- nr2, er = src.Read(buf[nr:])
- nr += nr2
- if er == io.EOF {
- if nr < stdWriterPrefixLen {
- logrus.Debugf("Corrupted prefix: %v", buf[:nr])
- return written, nil
- }
- break
- }
- if er != nil {
- logrus.Debugf("Error reading header: %s", er)
- return 0, er
- }
- }
-
- // Check the first byte to know where to write
- switch StdType(buf[stdWriterFdIndex]) {
- case Stdin:
- fallthrough
- case Stdout:
- // Write on stdout
- out = dstout
- case Stderr:
- // Write on stderr
- out = dsterr
- default:
- logrus.Debugf("Error selecting output fd: (%d)", buf[stdWriterFdIndex])
- return 0, fmt.Errorf("Unrecognized input header: %d", buf[stdWriterFdIndex])
- }
-
- // Retrieve the size of the frame
- frameSize = int(binary.BigEndian.Uint32(buf[stdWriterSizeIndex : stdWriterSizeIndex+4]))
- logrus.Debugf("framesize: %d", frameSize)
-
- // Check if the buffer is big enough to read the frame.
- // Extend it if necessary.
- if frameSize+stdWriterPrefixLen > bufLen {
- logrus.Debugf("Extending buffer cap by %d (was %d)", frameSize+stdWriterPrefixLen-bufLen+1, len(buf))
- buf = append(buf, make([]byte, frameSize+stdWriterPrefixLen-bufLen+1)...)
- bufLen = len(buf)
- }
-
- // While the amount of bytes read is less than the size of the frame + header, we keep reading
- for nr < frameSize+stdWriterPrefixLen {
- var nr2 int
- nr2, er = src.Read(buf[nr:])
- nr += nr2
- if er == io.EOF {
- if nr < frameSize+stdWriterPrefixLen {
- logrus.Debugf("Corrupted frame: %v", buf[stdWriterPrefixLen:nr])
- return written, nil
- }
- break
- }
- if er != nil {
- logrus.Debugf("Error reading frame: %s", er)
- return 0, er
- }
- }
-
- // Write the retrieved frame (without header)
- nw, ew = out.Write(buf[stdWriterPrefixLen : frameSize+stdWriterPrefixLen])
- if ew != nil {
- logrus.Debugf("Error writing frame: %s", ew)
- return 0, ew
- }
- // If the frame has not been fully written: error
- if nw != frameSize {
- logrus.Debugf("Error Short Write: (%d on %d)", nw, frameSize)
- return 0, io.ErrShortWrite
- }
- written += int64(nw)
-
- // Move the rest of the buffer to the beginning
- copy(buf, buf[frameSize+stdWriterPrefixLen:])
- // Move the index
- nr -= frameSize + stdWriterPrefixLen
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy_test.go b/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy_test.go
deleted file mode 100644
index 3137a75..0000000
--- a/vendor/github.com/docker/docker/pkg/stdcopy/stdcopy_test.go
+++ /dev/null
@@ -1,260 +0,0 @@
-package stdcopy
-
-import (
- "bytes"
- "errors"
- "io"
- "io/ioutil"
- "strings"
- "testing"
-)
-
-func TestNewStdWriter(t *testing.T) {
- writer := NewStdWriter(ioutil.Discard, Stdout)
- if writer == nil {
- t.Fatalf("NewStdWriter with an invalid StdType should not return nil.")
- }
-}
-
-func TestWriteWithUnitializedStdWriter(t *testing.T) {
- writer := stdWriter{
- Writer: nil,
- prefix: byte(Stdout),
- }
- n, err := writer.Write([]byte("Something here"))
- if n != 0 || err == nil {
- t.Fatalf("Should fail when given an uncomplete or uninitialized StdWriter")
- }
-}
-
-func TestWriteWithNilBytes(t *testing.T) {
- writer := NewStdWriter(ioutil.Discard, Stdout)
- n, err := writer.Write(nil)
- if err != nil {
- t.Fatalf("Shouldn't have fail when given no data")
- }
- if n > 0 {
- t.Fatalf("Write should have written 0 byte, but has written %d", n)
- }
-}
-
-func TestWrite(t *testing.T) {
- writer := NewStdWriter(ioutil.Discard, Stdout)
- data := []byte("Test StdWrite.Write")
- n, err := writer.Write(data)
- if err != nil {
- t.Fatalf("Error while writing with StdWrite")
- }
- if n != len(data) {
- t.Fatalf("Write should have written %d byte but wrote %d.", len(data), n)
- }
-}
-
-type errWriter struct {
- n int
- err error
-}
-
-func (f *errWriter) Write(buf []byte) (int, error) {
- return f.n, f.err
-}
-
-func TestWriteWithWriterError(t *testing.T) {
- expectedError := errors.New("expected")
- expectedReturnedBytes := 10
- writer := NewStdWriter(&errWriter{
- n: stdWriterPrefixLen + expectedReturnedBytes,
- err: expectedError}, Stdout)
- data := []byte("This won't get written, sigh")
- n, err := writer.Write(data)
- if err != expectedError {
- t.Fatalf("Didn't get expected error.")
- }
- if n != expectedReturnedBytes {
- t.Fatalf("Didn't get expected written bytes %d, got %d.",
- expectedReturnedBytes, n)
- }
-}
-
-func TestWriteDoesNotReturnNegativeWrittenBytes(t *testing.T) {
- writer := NewStdWriter(&errWriter{n: -1}, Stdout)
- data := []byte("This won't get written, sigh")
- actual, _ := writer.Write(data)
- if actual != 0 {
- t.Fatalf("Expected returned written bytes equal to 0, got %d", actual)
- }
-}
-
-func getSrcBuffer(stdOutBytes, stdErrBytes []byte) (buffer *bytes.Buffer, err error) {
- buffer = new(bytes.Buffer)
- dstOut := NewStdWriter(buffer, Stdout)
- _, err = dstOut.Write(stdOutBytes)
- if err != nil {
- return
- }
- dstErr := NewStdWriter(buffer, Stderr)
- _, err = dstErr.Write(stdErrBytes)
- return
-}
-
-func TestStdCopyWriteAndRead(t *testing.T) {
- stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
- stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
- buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
- if err != nil {
- t.Fatal(err)
- }
- written, err := StdCopy(ioutil.Discard, ioutil.Discard, buffer)
- if err != nil {
- t.Fatal(err)
- }
- expectedTotalWritten := len(stdOutBytes) + len(stdErrBytes)
- if written != int64(expectedTotalWritten) {
- t.Fatalf("Expected to have total of %d bytes written, got %d", expectedTotalWritten, written)
- }
-}
-
-type customReader struct {
- n int
- err error
- totalCalls int
- correctCalls int
- src *bytes.Buffer
-}
-
-func (f *customReader) Read(buf []byte) (int, error) {
- f.totalCalls++
- if f.totalCalls <= f.correctCalls {
- return f.src.Read(buf)
- }
- return f.n, f.err
-}
-
-func TestStdCopyReturnsErrorReadingHeader(t *testing.T) {
- expectedError := errors.New("error")
- reader := &customReader{
- err: expectedError}
- written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader)
- if written != 0 {
- t.Fatalf("Expected 0 bytes read, got %d", written)
- }
- if err != expectedError {
- t.Fatalf("Didn't get expected error")
- }
-}
-
-func TestStdCopyReturnsErrorReadingFrame(t *testing.T) {
- expectedError := errors.New("error")
- stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
- stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
- buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
- if err != nil {
- t.Fatal(err)
- }
- reader := &customReader{
- correctCalls: 1,
- n: stdWriterPrefixLen + 1,
- err: expectedError,
- src: buffer}
- written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader)
- if written != 0 {
- t.Fatalf("Expected 0 bytes read, got %d", written)
- }
- if err != expectedError {
- t.Fatalf("Didn't get expected error")
- }
-}
-
-func TestStdCopyDetectsCorruptedFrame(t *testing.T) {
- stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
- stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
- buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
- if err != nil {
- t.Fatal(err)
- }
- reader := &customReader{
- correctCalls: 1,
- n: stdWriterPrefixLen + 1,
- err: io.EOF,
- src: buffer}
- written, err := StdCopy(ioutil.Discard, ioutil.Discard, reader)
- if written != startingBufLen {
- t.Fatalf("Expected %d bytes read, got %d", startingBufLen, written)
- }
- if err != nil {
- t.Fatal("Didn't get nil error")
- }
-}
-
-func TestStdCopyWithInvalidInputHeader(t *testing.T) {
- dstOut := NewStdWriter(ioutil.Discard, Stdout)
- dstErr := NewStdWriter(ioutil.Discard, Stderr)
- src := strings.NewReader("Invalid input")
- _, err := StdCopy(dstOut, dstErr, src)
- if err == nil {
- t.Fatal("StdCopy with invalid input header should fail.")
- }
-}
-
-func TestStdCopyWithCorruptedPrefix(t *testing.T) {
- data := []byte{0x01, 0x02, 0x03}
- src := bytes.NewReader(data)
- written, err := StdCopy(nil, nil, src)
- if err != nil {
- t.Fatalf("StdCopy should not return an error with corrupted prefix.")
- }
- if written != 0 {
- t.Fatalf("StdCopy should have written 0, but has written %d", written)
- }
-}
-
-func TestStdCopyReturnsWriteErrors(t *testing.T) {
- stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
- stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
- buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
- if err != nil {
- t.Fatal(err)
- }
- expectedError := errors.New("expected")
-
- dstOut := &errWriter{err: expectedError}
-
- written, err := StdCopy(dstOut, ioutil.Discard, buffer)
- if written != 0 {
- t.Fatalf("StdCopy should have written 0, but has written %d", written)
- }
- if err != expectedError {
- t.Fatalf("Didn't get expected error, got %v", err)
- }
-}
-
-func TestStdCopyDetectsNotFullyWrittenFrames(t *testing.T) {
- stdOutBytes := []byte(strings.Repeat("o", startingBufLen))
- stdErrBytes := []byte(strings.Repeat("e", startingBufLen))
- buffer, err := getSrcBuffer(stdOutBytes, stdErrBytes)
- if err != nil {
- t.Fatal(err)
- }
- dstOut := &errWriter{n: startingBufLen - 10}
-
- written, err := StdCopy(dstOut, ioutil.Discard, buffer)
- if written != 0 {
- t.Fatalf("StdCopy should have return 0 written bytes, but returned %d", written)
- }
- if err != io.ErrShortWrite {
- t.Fatalf("Didn't get expected io.ErrShortWrite error")
- }
-}
-
-func BenchmarkWrite(b *testing.B) {
- w := NewStdWriter(ioutil.Discard, Stdout)
- data := []byte("Test line for testing stdwriter performance\n")
- data = bytes.Repeat(data, 100)
- b.SetBytes(int64(len(data)))
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- if _, err := w.Write(data); err != nil {
- b.Fatal(err)
- }
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes.go b/vendor/github.com/docker/docker/pkg/system/chtimes.go
deleted file mode 100644
index 7637f12..0000000
--- a/vendor/github.com/docker/docker/pkg/system/chtimes.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package system
-
-import (
- "os"
- "syscall"
- "time"
- "unsafe"
-)
-
-var (
- maxTime time.Time
-)
-
-func init() {
- if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 {
- // This is a 64 bit timespec
- // os.Chtimes limits time to the following
- maxTime = time.Unix(0, 1<<63-1)
- } else {
- // This is a 32 bit timespec
- maxTime = time.Unix(1<<31-1, 0)
- }
-}
-
-// Chtimes changes the access time and modified time of a file at the given path
-func Chtimes(name string, atime time.Time, mtime time.Time) error {
- unixMinTime := time.Unix(0, 0)
- unixMaxTime := maxTime
-
- // If the modified time is prior to the Unix Epoch, or after the
- // end of Unix Time, os.Chtimes has undefined behavior
- // default to Unix Epoch in this case, just in case
-
- if atime.Before(unixMinTime) || atime.After(unixMaxTime) {
- atime = unixMinTime
- }
-
- if mtime.Before(unixMinTime) || mtime.After(unixMaxTime) {
- mtime = unixMinTime
- }
-
- if err := os.Chtimes(name, atime, mtime); err != nil {
- return err
- }
-
- // Take platform specific action for setting create time.
- if err := setCTime(name, mtime); err != nil {
- return err
- }
-
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_test.go b/vendor/github.com/docker/docker/pkg/system/chtimes_test.go
deleted file mode 100644
index 5c87df3..0000000
--- a/vendor/github.com/docker/docker/pkg/system/chtimes_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package system
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
- "testing"
- "time"
-)
-
-// prepareTempFile creates a temporary file in a temporary directory.
-func prepareTempFile(t *testing.T) (string, string) {
- dir, err := ioutil.TempDir("", "docker-system-test")
- if err != nil {
- t.Fatal(err)
- }
-
- file := filepath.Join(dir, "exist")
- if err := ioutil.WriteFile(file, []byte("hello"), 0644); err != nil {
- t.Fatal(err)
- }
- return file, dir
-}
-
-// TestChtimes tests Chtimes on a tempfile. Test only mTime, because aTime is OS dependent
-func TestChtimes(t *testing.T) {
- file, dir := prepareTempFile(t)
- defer os.RemoveAll(dir)
-
- beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second)
- unixEpochTime := time.Unix(0, 0)
- afterUnixEpochTime := time.Unix(100, 0)
- unixMaxTime := maxTime
-
- // Test both aTime and mTime set to Unix Epoch
- Chtimes(file, unixEpochTime, unixEpochTime)
-
- f, err := os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- if f.ModTime() != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, f.ModTime())
- }
-
- // Test aTime before Unix Epoch and mTime set to Unix Epoch
- Chtimes(file, beforeUnixEpochTime, unixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- if f.ModTime() != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, f.ModTime())
- }
-
- // Test aTime set to Unix Epoch and mTime before Unix Epoch
- Chtimes(file, unixEpochTime, beforeUnixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- if f.ModTime() != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, f.ModTime())
- }
-
- // Test both aTime and mTime set to after Unix Epoch (valid time)
- Chtimes(file, afterUnixEpochTime, afterUnixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- if f.ModTime() != afterUnixEpochTime {
- t.Fatalf("Expected: %s, got: %s", afterUnixEpochTime, f.ModTime())
- }
-
- // Test both aTime and mTime set to Unix max time
- Chtimes(file, unixMaxTime, unixMaxTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- if f.ModTime().Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
- t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), f.ModTime().Truncate(time.Second))
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_unix.go b/vendor/github.com/docker/docker/pkg/system/chtimes_unix.go
deleted file mode 100644
index 09d58bc..0000000
--- a/vendor/github.com/docker/docker/pkg/system/chtimes_unix.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// +build !windows
-
-package system
-
-import (
- "time"
-)
-
-//setCTime will set the create time on a file. On Unix, the create
-//time is updated as a side effect of setting the modified time, so
-//no action is required.
-func setCTime(path string, ctime time.Time) error {
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_unix_test.go b/vendor/github.com/docker/docker/pkg/system/chtimes_unix_test.go
deleted file mode 100644
index 0aafe1d..0000000
--- a/vendor/github.com/docker/docker/pkg/system/chtimes_unix_test.go
+++ /dev/null
@@ -1,91 +0,0 @@
-// +build !windows
-
-package system
-
-import (
- "os"
- "syscall"
- "testing"
- "time"
-)
-
-// TestChtimes tests Chtimes access time on a tempfile on Linux
-func TestChtimesLinux(t *testing.T) {
- file, dir := prepareTempFile(t)
- defer os.RemoveAll(dir)
-
- beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second)
- unixEpochTime := time.Unix(0, 0)
- afterUnixEpochTime := time.Unix(100, 0)
- unixMaxTime := maxTime
-
- // Test both aTime and mTime set to Unix Epoch
- Chtimes(file, unixEpochTime, unixEpochTime)
-
- f, err := os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- stat := f.Sys().(*syscall.Stat_t)
- aTime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
- if aTime != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
- }
-
- // Test aTime before Unix Epoch and mTime set to Unix Epoch
- Chtimes(file, beforeUnixEpochTime, unixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- stat = f.Sys().(*syscall.Stat_t)
- aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
- if aTime != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
- }
-
- // Test aTime set to Unix Epoch and mTime before Unix Epoch
- Chtimes(file, unixEpochTime, beforeUnixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- stat = f.Sys().(*syscall.Stat_t)
- aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
- if aTime != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
- }
-
- // Test both aTime and mTime set to after Unix Epoch (valid time)
- Chtimes(file, afterUnixEpochTime, afterUnixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- stat = f.Sys().(*syscall.Stat_t)
- aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
- if aTime != afterUnixEpochTime {
- t.Fatalf("Expected: %s, got: %s", afterUnixEpochTime, aTime)
- }
-
- // Test both aTime and mTime set to Unix max time
- Chtimes(file, unixMaxTime, unixMaxTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- stat = f.Sys().(*syscall.Stat_t)
- aTime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
- if aTime.Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
- t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), aTime.Truncate(time.Second))
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go b/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go
deleted file mode 100644
index 2945868..0000000
--- a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// +build windows
-
-package system
-
-import (
- "syscall"
- "time"
-)
-
-//setCTime will set the create time on a file. On Windows, this requires
-//calling SetFileTime and explicitly including the create time.
-func setCTime(path string, ctime time.Time) error {
- ctimespec := syscall.NsecToTimespec(ctime.UnixNano())
- pathp, e := syscall.UTF16PtrFromString(path)
- if e != nil {
- return e
- }
- h, e := syscall.CreateFile(pathp,
- syscall.FILE_WRITE_ATTRIBUTES, syscall.FILE_SHARE_WRITE, nil,
- syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
- if e != nil {
- return e
- }
- defer syscall.Close(h)
- c := syscall.NsecToFiletime(syscall.TimespecToNsec(ctimespec))
- return syscall.SetFileTime(h, &c, nil, nil)
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_windows_test.go b/vendor/github.com/docker/docker/pkg/system/chtimes_windows_test.go
deleted file mode 100644
index be57558..0000000
--- a/vendor/github.com/docker/docker/pkg/system/chtimes_windows_test.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// +build windows
-
-package system
-
-import (
- "os"
- "syscall"
- "testing"
- "time"
-)
-
-// TestChtimes tests Chtimes access time on a tempfile on Windows
-func TestChtimesWindows(t *testing.T) {
- file, dir := prepareTempFile(t)
- defer os.RemoveAll(dir)
-
- beforeUnixEpochTime := time.Unix(0, 0).Add(-100 * time.Second)
- unixEpochTime := time.Unix(0, 0)
- afterUnixEpochTime := time.Unix(100, 0)
- unixMaxTime := maxTime
-
- // Test both aTime and mTime set to Unix Epoch
- Chtimes(file, unixEpochTime, unixEpochTime)
-
- f, err := os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- aTime := time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
- if aTime != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
- }
-
- // Test aTime before Unix Epoch and mTime set to Unix Epoch
- Chtimes(file, beforeUnixEpochTime, unixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
- if aTime != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
- }
-
- // Test aTime set to Unix Epoch and mTime before Unix Epoch
- Chtimes(file, unixEpochTime, beforeUnixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
- if aTime != unixEpochTime {
- t.Fatalf("Expected: %s, got: %s", unixEpochTime, aTime)
- }
-
- // Test both aTime and mTime set to after Unix Epoch (valid time)
- Chtimes(file, afterUnixEpochTime, afterUnixEpochTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
- if aTime != afterUnixEpochTime {
- t.Fatalf("Expected: %s, got: %s", afterUnixEpochTime, aTime)
- }
-
- // Test both aTime and mTime set to Unix max time
- Chtimes(file, unixMaxTime, unixMaxTime)
-
- f, err = os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- aTime = time.Unix(0, f.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds())
- if aTime.Truncate(time.Second) != unixMaxTime.Truncate(time.Second) {
- t.Fatalf("Expected: %s, got: %s", unixMaxTime.Truncate(time.Second), aTime.Truncate(time.Second))
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/errors.go b/vendor/github.com/docker/docker/pkg/system/errors.go
deleted file mode 100644
index 2883189..0000000
--- a/vendor/github.com/docker/docker/pkg/system/errors.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package system
-
-import (
- "errors"
-)
-
-var (
- // ErrNotSupportedPlatform means the platform is not supported.
- ErrNotSupportedPlatform = errors.New("platform and architecture is not supported")
-)
diff --git a/vendor/github.com/docker/docker/pkg/system/events_windows.go b/vendor/github.com/docker/docker/pkg/system/events_windows.go
deleted file mode 100644
index 04e2de7..0000000
--- a/vendor/github.com/docker/docker/pkg/system/events_windows.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package system
-
-// This file implements syscalls for Win32 events which are not implemented
-// in golang.
-
-import (
- "syscall"
- "unsafe"
-)
-
-var (
- procCreateEvent = modkernel32.NewProc("CreateEventW")
- procOpenEvent = modkernel32.NewProc("OpenEventW")
- procSetEvent = modkernel32.NewProc("SetEvent")
- procResetEvent = modkernel32.NewProc("ResetEvent")
- procPulseEvent = modkernel32.NewProc("PulseEvent")
-)
-
-// CreateEvent implements win32 CreateEventW func in golang. It will create an event object.
-func CreateEvent(eventAttributes *syscall.SecurityAttributes, manualReset bool, initialState bool, name string) (handle syscall.Handle, err error) {
- namep, _ := syscall.UTF16PtrFromString(name)
- var _p1 uint32
- if manualReset {
- _p1 = 1
- }
- var _p2 uint32
- if initialState {
- _p2 = 1
- }
- r0, _, e1 := procCreateEvent.Call(uintptr(unsafe.Pointer(eventAttributes)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(namep)))
- use(unsafe.Pointer(namep))
- handle = syscall.Handle(r0)
- if handle == syscall.InvalidHandle {
- err = e1
- }
- return
-}
-
-// OpenEvent implements win32 OpenEventW func in golang. It opens an event object.
-func OpenEvent(desiredAccess uint32, inheritHandle bool, name string) (handle syscall.Handle, err error) {
- namep, _ := syscall.UTF16PtrFromString(name)
- var _p1 uint32
- if inheritHandle {
- _p1 = 1
- }
- r0, _, e1 := procOpenEvent.Call(uintptr(desiredAccess), uintptr(_p1), uintptr(unsafe.Pointer(namep)))
- use(unsafe.Pointer(namep))
- handle = syscall.Handle(r0)
- if handle == syscall.InvalidHandle {
- err = e1
- }
- return
-}
-
-// SetEvent implements win32 SetEvent func in golang.
-func SetEvent(handle syscall.Handle) (err error) {
- return setResetPulse(handle, procSetEvent)
-}
-
-// ResetEvent implements win32 ResetEvent func in golang.
-func ResetEvent(handle syscall.Handle) (err error) {
- return setResetPulse(handle, procResetEvent)
-}
-
-// PulseEvent implements win32 PulseEvent func in golang.
-func PulseEvent(handle syscall.Handle) (err error) {
- return setResetPulse(handle, procPulseEvent)
-}
-
-func setResetPulse(handle syscall.Handle, proc *syscall.LazyProc) (err error) {
- r0, _, _ := proc.Call(uintptr(handle))
- if r0 != 0 {
- err = syscall.Errno(r0)
- }
- return
-}
-
-var temp unsafe.Pointer
-
-// use ensures a variable is kept alive without the GC freeing while still needed
-func use(p unsafe.Pointer) {
- temp = p
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/filesys.go b/vendor/github.com/docker/docker/pkg/system/filesys.go
deleted file mode 100644
index c14feb8..0000000
--- a/vendor/github.com/docker/docker/pkg/system/filesys.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// +build !windows
-
-package system
-
-import (
- "os"
- "path/filepath"
-)
-
-// MkdirAll creates a directory named path along with any necessary parents,
-// with permission specified by attribute perm for all dir created.
-func MkdirAll(path string, perm os.FileMode) error {
- return os.MkdirAll(path, perm)
-}
-
-// IsAbs is a platform-specific wrapper for filepath.IsAbs.
-func IsAbs(path string) bool {
- return filepath.IsAbs(path)
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go
deleted file mode 100644
index 16823d5..0000000
--- a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// +build windows
-
-package system
-
-import (
- "os"
- "path/filepath"
- "regexp"
- "strings"
- "syscall"
-)
-
-// MkdirAll implementation that is volume path aware for Windows.
-func MkdirAll(path string, perm os.FileMode) error {
- if re := regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}$`); re.MatchString(path) {
- return nil
- }
-
- // The rest of this method is copied from os.MkdirAll and should be kept
- // as-is to ensure compatibility.
-
- // Fast path: if we can tell whether path is a directory or file, stop with success or error.
- dir, err := os.Stat(path)
- if err == nil {
- if dir.IsDir() {
- return nil
- }
- return &os.PathError{
- Op: "mkdir",
- Path: path,
- Err: syscall.ENOTDIR,
- }
- }
-
- // Slow path: make sure parent exists and then call Mkdir for path.
- i := len(path)
- for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator.
- i--
- }
-
- j := i
- for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element.
- j--
- }
-
- if j > 1 {
- // Create parent
- err = MkdirAll(path[0:j-1], perm)
- if err != nil {
- return err
- }
- }
-
- // Parent now exists; invoke Mkdir and use its result.
- err = os.Mkdir(path, perm)
- if err != nil {
- // Handle arguments like "foo/." by
- // double-checking that directory doesn't exist.
- dir, err1 := os.Lstat(path)
- if err1 == nil && dir.IsDir() {
- return nil
- }
- return err
- }
- return nil
-}
-
-// IsAbs is a platform-specific wrapper for filepath.IsAbs. On Windows,
-// golang filepath.IsAbs does not consider a path \windows\system32 as absolute
-// as it doesn't start with a drive-letter/colon combination. However, in
-// docker we need to verify things such as WORKDIR /windows/system32 in
-// a Dockerfile (which gets translated to \windows\system32 when being processed
-// by the daemon. This SHOULD be treated as absolute from a docker processing
-// perspective.
-func IsAbs(path string) bool {
- if !filepath.IsAbs(path) {
- if !strings.HasPrefix(path, string(os.PathSeparator)) {
- return false
- }
- }
- return true
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/lstat.go b/vendor/github.com/docker/docker/pkg/system/lstat.go
deleted file mode 100644
index bd23c4d..0000000
--- a/vendor/github.com/docker/docker/pkg/system/lstat.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// +build !windows
-
-package system
-
-import (
- "syscall"
-)
-
-// Lstat takes a path to a file and returns
-// a system.StatT type pertaining to that file.
-//
-// Throws an error if the file does not exist
-func Lstat(path string) (*StatT, error) {
- s := &syscall.Stat_t{}
- if err := syscall.Lstat(path, s); err != nil {
- return nil, err
- }
- return fromStatT(s)
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_unix_test.go b/vendor/github.com/docker/docker/pkg/system/lstat_unix_test.go
deleted file mode 100644
index 062cf53..0000000
--- a/vendor/github.com/docker/docker/pkg/system/lstat_unix_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build linux freebsd
-
-package system
-
-import (
- "os"
- "testing"
-)
-
-// TestLstat tests Lstat for existing and non existing files
-func TestLstat(t *testing.T) {
- file, invalid, _, dir := prepareFiles(t)
- defer os.RemoveAll(dir)
-
- statFile, err := Lstat(file)
- if err != nil {
- t.Fatal(err)
- }
- if statFile == nil {
- t.Fatal("returned empty stat for existing file")
- }
-
- statInvalid, err := Lstat(invalid)
- if err == nil {
- t.Fatal("did not return error for non-existing file")
- }
- if statInvalid != nil {
- t.Fatal("returned non-nil stat for non-existing file")
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_windows.go b/vendor/github.com/docker/docker/pkg/system/lstat_windows.go
deleted file mode 100644
index 49e87eb..0000000
--- a/vendor/github.com/docker/docker/pkg/system/lstat_windows.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// +build windows
-
-package system
-
-import (
- "os"
-)
-
-// Lstat calls os.Lstat to get a fileinfo interface back.
-// This is then copied into our own locally defined structure.
-// Note the Linux version uses fromStatT to do the copy back,
-// but that not strictly necessary when already in an OS specific module.
-func Lstat(path string) (*StatT, error) {
- fi, err := os.Lstat(path)
- if err != nil {
- return nil, err
- }
-
- return &StatT{
- name: fi.Name(),
- size: fi.Size(),
- mode: fi.Mode(),
- modTime: fi.ModTime(),
- isDir: fi.IsDir()}, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo.go b/vendor/github.com/docker/docker/pkg/system/meminfo.go
deleted file mode 100644
index 3b6e947..0000000
--- a/vendor/github.com/docker/docker/pkg/system/meminfo.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package system
-
-// MemInfo contains memory statistics of the host system.
-type MemInfo struct {
- // Total usable RAM (i.e. physical RAM minus a few reserved bits and the
- // kernel binary code).
- MemTotal int64
-
- // Amount of free memory.
- MemFree int64
-
- // Total amount of swap space available.
- SwapTotal int64
-
- // Amount of swap space that is currently unused.
- SwapFree int64
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_linux.go b/vendor/github.com/docker/docker/pkg/system/meminfo_linux.go
deleted file mode 100644
index 385f1d5..0000000
--- a/vendor/github.com/docker/docker/pkg/system/meminfo_linux.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package system
-
-import (
- "bufio"
- "io"
- "os"
- "strconv"
- "strings"
-
- "github.com/docker/go-units"
-)
-
-// ReadMemInfo retrieves memory statistics of the host system and returns a
-// MemInfo type.
-func ReadMemInfo() (*MemInfo, error) {
- file, err := os.Open("/proc/meminfo")
- if err != nil {
- return nil, err
- }
- defer file.Close()
- return parseMemInfo(file)
-}
-
-// parseMemInfo parses the /proc/meminfo file into
-// a MemInfo object given an io.Reader to the file.
-// Throws error if there are problems reading from the file
-func parseMemInfo(reader io.Reader) (*MemInfo, error) {
- meminfo := &MemInfo{}
- scanner := bufio.NewScanner(reader)
- for scanner.Scan() {
- // Expected format: ["MemTotal:", "1234", "kB"]
- parts := strings.Fields(scanner.Text())
-
- // Sanity checks: Skip malformed entries.
- if len(parts) < 3 || parts[2] != "kB" {
- continue
- }
-
- // Convert to bytes.
- size, err := strconv.Atoi(parts[1])
- if err != nil {
- continue
- }
- bytes := int64(size) * units.KiB
-
- switch parts[0] {
- case "MemTotal:":
- meminfo.MemTotal = bytes
- case "MemFree:":
- meminfo.MemFree = bytes
- case "SwapTotal:":
- meminfo.SwapTotal = bytes
- case "SwapFree:":
- meminfo.SwapFree = bytes
- }
-
- }
-
- // Handle errors that may have occurred during the reading of the file.
- if err := scanner.Err(); err != nil {
- return nil, err
- }
-
- return meminfo, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_solaris.go b/vendor/github.com/docker/docker/pkg/system/meminfo_solaris.go
deleted file mode 100644
index 313c601..0000000
--- a/vendor/github.com/docker/docker/pkg/system/meminfo_solaris.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// +build solaris,cgo
-
-package system
-
-import (
- "fmt"
- "unsafe"
-)
-
-// #cgo LDFLAGS: -lkstat
-// #include
-// #include
-// #include
-// #include
-// #include
-// #include
-// struct swaptable *allocSwaptable(int num) {
-// struct swaptable *st;
-// struct swapent *swapent;
-// st = (struct swaptable *)malloc(num * sizeof(swapent_t) + sizeof (int));
-// swapent = st->swt_ent;
-// for (int i = 0; i < num; i++,swapent++) {
-// swapent->ste_path = (char *)malloc(MAXPATHLEN * sizeof (char));
-// }
-// st->swt_n = num;
-// return st;
-//}
-// void freeSwaptable (struct swaptable *st) {
-// struct swapent *swapent = st->swt_ent;
-// for (int i = 0; i < st->swt_n; i++,swapent++) {
-// free(swapent->ste_path);
-// }
-// free(st);
-// }
-// swapent_t getSwapEnt(swapent_t *ent, int i) {
-// return ent[i];
-// }
-// int64_t getPpKernel() {
-// int64_t pp_kernel = 0;
-// kstat_ctl_t *ksc;
-// kstat_t *ks;
-// kstat_named_t *knp;
-// kid_t kid;
-//
-// if ((ksc = kstat_open()) == NULL) {
-// return -1;
-// }
-// if ((ks = kstat_lookup(ksc, "unix", 0, "system_pages")) == NULL) {
-// return -1;
-// }
-// if (((kid = kstat_read(ksc, ks, NULL)) == -1) ||
-// ((knp = kstat_data_lookup(ks, "pp_kernel")) == NULL)) {
-// return -1;
-// }
-// switch (knp->data_type) {
-// case KSTAT_DATA_UINT64:
-// pp_kernel = knp->value.ui64;
-// break;
-// case KSTAT_DATA_UINT32:
-// pp_kernel = knp->value.ui32;
-// break;
-// }
-// pp_kernel *= sysconf(_SC_PAGESIZE);
-// return (pp_kernel > 0 ? pp_kernel : -1);
-// }
-import "C"
-
-// Get the system memory info using sysconf same as prtconf
-func getTotalMem() int64 {
- pagesize := C.sysconf(C._SC_PAGESIZE)
- npages := C.sysconf(C._SC_PHYS_PAGES)
- return int64(pagesize * npages)
-}
-
-func getFreeMem() int64 {
- pagesize := C.sysconf(C._SC_PAGESIZE)
- npages := C.sysconf(C._SC_AVPHYS_PAGES)
- return int64(pagesize * npages)
-}
-
-// ReadMemInfo retrieves memory statistics of the host system and returns a
-// MemInfo type.
-func ReadMemInfo() (*MemInfo, error) {
-
- ppKernel := C.getPpKernel()
- MemTotal := getTotalMem()
- MemFree := getFreeMem()
- SwapTotal, SwapFree, err := getSysSwap()
-
- if ppKernel < 0 || MemTotal < 0 || MemFree < 0 || SwapTotal < 0 ||
- SwapFree < 0 {
- return nil, fmt.Errorf("Error getting system memory info %v\n", err)
- }
-
- meminfo := &MemInfo{}
- // Total memory is total physical memory less than memory locked by kernel
- meminfo.MemTotal = MemTotal - int64(ppKernel)
- meminfo.MemFree = MemFree
- meminfo.SwapTotal = SwapTotal
- meminfo.SwapFree = SwapFree
-
- return meminfo, nil
-}
-
-func getSysSwap() (int64, int64, error) {
- var tSwap int64
- var fSwap int64
- var diskblksPerPage int64
- num, err := C.swapctl(C.SC_GETNSWP, nil)
- if err != nil {
- return -1, -1, err
- }
- st := C.allocSwaptable(num)
- _, err = C.swapctl(C.SC_LIST, unsafe.Pointer(st))
- if err != nil {
- C.freeSwaptable(st)
- return -1, -1, err
- }
-
- diskblksPerPage = int64(C.sysconf(C._SC_PAGESIZE) >> C.DEV_BSHIFT)
- for i := 0; i < int(num); i++ {
- swapent := C.getSwapEnt(&st.swt_ent[0], C.int(i))
- tSwap += int64(swapent.ste_pages) * diskblksPerPage
- fSwap += int64(swapent.ste_free) * diskblksPerPage
- }
- C.freeSwaptable(st)
- return tSwap, fSwap, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_unix_test.go b/vendor/github.com/docker/docker/pkg/system/meminfo_unix_test.go
deleted file mode 100644
index 44f5562..0000000
--- a/vendor/github.com/docker/docker/pkg/system/meminfo_unix_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// +build linux freebsd
-
-package system
-
-import (
- "strings"
- "testing"
-
- "github.com/docker/go-units"
-)
-
-// TestMemInfo tests parseMemInfo with a static meminfo string
-func TestMemInfo(t *testing.T) {
- const input = `
- MemTotal: 1 kB
- MemFree: 2 kB
- SwapTotal: 3 kB
- SwapFree: 4 kB
- Malformed1:
- Malformed2: 1
- Malformed3: 2 MB
- Malformed4: X kB
- `
- meminfo, err := parseMemInfo(strings.NewReader(input))
- if err != nil {
- t.Fatal(err)
- }
- if meminfo.MemTotal != 1*units.KiB {
- t.Fatalf("Unexpected MemTotal: %d", meminfo.MemTotal)
- }
- if meminfo.MemFree != 2*units.KiB {
- t.Fatalf("Unexpected MemFree: %d", meminfo.MemFree)
- }
- if meminfo.SwapTotal != 3*units.KiB {
- t.Fatalf("Unexpected SwapTotal: %d", meminfo.SwapTotal)
- }
- if meminfo.SwapFree != 4*units.KiB {
- t.Fatalf("Unexpected SwapFree: %d", meminfo.SwapFree)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_unsupported.go b/vendor/github.com/docker/docker/pkg/system/meminfo_unsupported.go
deleted file mode 100644
index 3ce019d..0000000
--- a/vendor/github.com/docker/docker/pkg/system/meminfo_unsupported.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// +build !linux,!windows,!solaris
-
-package system
-
-// ReadMemInfo is not supported on platforms other than linux and windows.
-func ReadMemInfo() (*MemInfo, error) {
- return nil, ErrNotSupportedPlatform
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/meminfo_windows.go b/vendor/github.com/docker/docker/pkg/system/meminfo_windows.go
deleted file mode 100644
index d466425..0000000
--- a/vendor/github.com/docker/docker/pkg/system/meminfo_windows.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package system
-
-import (
- "syscall"
- "unsafe"
-)
-
-var (
- modkernel32 = syscall.NewLazyDLL("kernel32.dll")
-
- procGlobalMemoryStatusEx = modkernel32.NewProc("GlobalMemoryStatusEx")
-)
-
-// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366589(v=vs.85).aspx
-// https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx
-type memorystatusex struct {
- dwLength uint32
- dwMemoryLoad uint32
- ullTotalPhys uint64
- ullAvailPhys uint64
- ullTotalPageFile uint64
- ullAvailPageFile uint64
- ullTotalVirtual uint64
- ullAvailVirtual uint64
- ullAvailExtendedVirtual uint64
-}
-
-// ReadMemInfo retrieves memory statistics of the host system and returns a
-// MemInfo type.
-func ReadMemInfo() (*MemInfo, error) {
- msi := &memorystatusex{
- dwLength: 64,
- }
- r1, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(msi)))
- if r1 == 0 {
- return &MemInfo{}, nil
- }
- return &MemInfo{
- MemTotal: int64(msi.ullTotalPhys),
- MemFree: int64(msi.ullAvailPhys),
- SwapTotal: int64(msi.ullTotalPageFile),
- SwapFree: int64(msi.ullAvailPageFile),
- }, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/mknod.go b/vendor/github.com/docker/docker/pkg/system/mknod.go
deleted file mode 100644
index 7395818..0000000
--- a/vendor/github.com/docker/docker/pkg/system/mknod.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build !windows
-
-package system
-
-import (
- "syscall"
-)
-
-// Mknod creates a filesystem node (file, device special file or named pipe) named path
-// with attributes specified by mode and dev.
-func Mknod(path string, mode uint32, dev int) error {
- return syscall.Mknod(path, mode, dev)
-}
-
-// Mkdev is used to build the value of linux devices (in /dev/) which specifies major
-// and minor number of the newly created device special file.
-// Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes.
-// They are, from low to high: the lower 8 bits of the minor, then 12 bits of the major,
-// then the top 12 bits of the minor.
-func Mkdev(major int64, minor int64) uint32 {
- return uint32(((minor & 0xfff00) << 12) | ((major & 0xfff) << 8) | (minor & 0xff))
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_windows.go b/vendor/github.com/docker/docker/pkg/system/mknod_windows.go
deleted file mode 100644
index 2e863c0..0000000
--- a/vendor/github.com/docker/docker/pkg/system/mknod_windows.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build windows
-
-package system
-
-// Mknod is not implemented on Windows.
-func Mknod(path string, mode uint32, dev int) error {
- return ErrNotSupportedPlatform
-}
-
-// Mkdev is not implemented on Windows.
-func Mkdev(major int64, minor int64) uint32 {
- panic("Mkdev not implemented on Windows.")
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/path_unix.go b/vendor/github.com/docker/docker/pkg/system/path_unix.go
deleted file mode 100644
index c607c4d..0000000
--- a/vendor/github.com/docker/docker/pkg/system/path_unix.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// +build !windows
-
-package system
-
-// DefaultPathEnv is unix style list of directories to search for
-// executables. Each directory is separated from the next by a colon
-// ':' character .
-const DefaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
-
-// CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter,
-// is the system drive. This is a no-op on Linux.
-func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) {
- return path, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/path_windows.go b/vendor/github.com/docker/docker/pkg/system/path_windows.go
deleted file mode 100644
index cbfe2c1..0000000
--- a/vendor/github.com/docker/docker/pkg/system/path_windows.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// +build windows
-
-package system
-
-import (
- "fmt"
- "path/filepath"
- "strings"
-)
-
-// DefaultPathEnv is deliberately empty on Windows as the default path will be set by
-// the container. Docker has no context of what the default path should be.
-const DefaultPathEnv = ""
-
-// CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path.
-// This is used, for example, when validating a user provided path in docker cp.
-// If a drive letter is supplied, it must be the system drive. The drive letter
-// is always removed. Also, it translates it to OS semantics (IOW / to \). We
-// need the path in this syntax so that it can ultimately be contatenated with
-// a Windows long-path which doesn't support drive-letters. Examples:
-// C: --> Fail
-// C:\ --> \
-// a --> a
-// /a --> \a
-// d:\ --> Fail
-func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) {
- if len(path) == 2 && string(path[1]) == ":" {
- return "", fmt.Errorf("No relative path specified in %q", path)
- }
- if !filepath.IsAbs(path) || len(path) < 2 {
- return filepath.FromSlash(path), nil
- }
- if string(path[1]) == ":" && !strings.EqualFold(string(path[0]), "c") {
- return "", fmt.Errorf("The specified path is not on the system drive (C:)")
- }
- return filepath.FromSlash(path[2:]), nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/path_windows_test.go b/vendor/github.com/docker/docker/pkg/system/path_windows_test.go
deleted file mode 100644
index eccb26a..0000000
--- a/vendor/github.com/docker/docker/pkg/system/path_windows_test.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// +build windows
-
-package system
-
-import "testing"
-
-// TestCheckSystemDriveAndRemoveDriveLetter tests CheckSystemDriveAndRemoveDriveLetter
-func TestCheckSystemDriveAndRemoveDriveLetter(t *testing.T) {
- // Fails if not C drive.
- path, err := CheckSystemDriveAndRemoveDriveLetter(`d:\`)
- if err == nil || (err != nil && err.Error() != "The specified path is not on the system drive (C:)") {
- t.Fatalf("Expected error for d:")
- }
-
- // Single character is unchanged
- if path, err = CheckSystemDriveAndRemoveDriveLetter("z"); err != nil {
- t.Fatalf("Single character should pass")
- }
- if path != "z" {
- t.Fatalf("Single character should be unchanged")
- }
-
- // Two characters without colon is unchanged
- if path, err = CheckSystemDriveAndRemoveDriveLetter("AB"); err != nil {
- t.Fatalf("2 characters without colon should pass")
- }
- if path != "AB" {
- t.Fatalf("2 characters without colon should be unchanged")
- }
-
- // Abs path without drive letter
- if path, err = CheckSystemDriveAndRemoveDriveLetter(`\l`); err != nil {
- t.Fatalf("abs path no drive letter should pass")
- }
- if path != `\l` {
- t.Fatalf("abs path without drive letter should be unchanged")
- }
-
- // Abs path without drive letter, linux style
- if path, err = CheckSystemDriveAndRemoveDriveLetter(`/l`); err != nil {
- t.Fatalf("abs path no drive letter linux style should pass")
- }
- if path != `\l` {
- t.Fatalf("abs path without drive letter linux failed %s", path)
- }
-
- // Drive-colon should be stripped
- if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:\`); err != nil {
- t.Fatalf("An absolute path should pass")
- }
- if path != `\` {
- t.Fatalf(`An absolute path should have been shortened to \ %s`, path)
- }
-
- // Verify with a linux-style path
- if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:/`); err != nil {
- t.Fatalf("An absolute path should pass")
- }
- if path != `\` {
- t.Fatalf(`A linux style absolute path should have been shortened to \ %s`, path)
- }
-
- // Failure on c:
- if path, err = CheckSystemDriveAndRemoveDriveLetter(`c:`); err == nil {
- t.Fatalf("c: should fail")
- }
- if err.Error() != `No relative path specified in "c:"` {
- t.Fatalf(path, err)
- }
-
- // Failure on d:
- if path, err = CheckSystemDriveAndRemoveDriveLetter(`d:`); err == nil {
- t.Fatalf("c: should fail")
- }
- if err.Error() != `No relative path specified in "d:"` {
- t.Fatalf(path, err)
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat.go b/vendor/github.com/docker/docker/pkg/system/stat.go
deleted file mode 100644
index 087034c..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build !windows
-
-package system
-
-import (
- "syscall"
-)
-
-// StatT type contains status of a file. It contains metadata
-// like permission, owner, group, size, etc about a file.
-type StatT struct {
- mode uint32
- uid uint32
- gid uint32
- rdev uint64
- size int64
- mtim syscall.Timespec
-}
-
-// Mode returns file's permission mode.
-func (s StatT) Mode() uint32 {
- return s.mode
-}
-
-// UID returns file's user id of owner.
-func (s StatT) UID() uint32 {
- return s.uid
-}
-
-// GID returns file's group id of owner.
-func (s StatT) GID() uint32 {
- return s.gid
-}
-
-// Rdev returns file's device ID (if it's special file).
-func (s StatT) Rdev() uint64 {
- return s.rdev
-}
-
-// Size returns file's size.
-func (s StatT) Size() int64 {
- return s.size
-}
-
-// Mtim returns file's last modification time.
-func (s StatT) Mtim() syscall.Timespec {
- return s.mtim
-}
-
-// GetLastModification returns file's last modification time.
-func (s StatT) GetLastModification() syscall.Timespec {
- return s.Mtim()
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat_freebsd.go b/vendor/github.com/docker/docker/pkg/system/stat_freebsd.go
deleted file mode 100644
index d0fb6f1..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat_freebsd.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package system
-
-import (
- "syscall"
-)
-
-// fromStatT converts a syscall.Stat_t type to a system.Stat_t type
-func fromStatT(s *syscall.Stat_t) (*StatT, error) {
- return &StatT{size: s.Size,
- mode: uint32(s.Mode),
- uid: s.Uid,
- gid: s.Gid,
- rdev: uint64(s.Rdev),
- mtim: s.Mtimespec}, nil
-}
-
-// Stat takes a path to a file and returns
-// a system.Stat_t type pertaining to that file.
-//
-// Throws an error if the file does not exist
-func Stat(path string) (*StatT, error) {
- s := &syscall.Stat_t{}
- if err := syscall.Stat(path, s); err != nil {
- return nil, err
- }
- return fromStatT(s)
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat_linux.go b/vendor/github.com/docker/docker/pkg/system/stat_linux.go
deleted file mode 100644
index 8b1eded..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat_linux.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package system
-
-import (
- "syscall"
-)
-
-// fromStatT converts a syscall.Stat_t type to a system.Stat_t type
-func fromStatT(s *syscall.Stat_t) (*StatT, error) {
- return &StatT{size: s.Size,
- mode: s.Mode,
- uid: s.Uid,
- gid: s.Gid,
- rdev: s.Rdev,
- mtim: s.Mtim}, nil
-}
-
-// FromStatT exists only on linux, and loads a system.StatT from a
-// syscal.Stat_t.
-func FromStatT(s *syscall.Stat_t) (*StatT, error) {
- return fromStatT(s)
-}
-
-// Stat takes a path to a file and returns
-// a system.StatT type pertaining to that file.
-//
-// Throws an error if the file does not exist
-func Stat(path string) (*StatT, error) {
- s := &syscall.Stat_t{}
- if err := syscall.Stat(path, s); err != nil {
- return nil, err
- }
- return fromStatT(s)
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go b/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go
deleted file mode 100644
index 3c3b71f..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package system
-
-import (
- "syscall"
-)
-
-// fromStatT creates a system.StatT type from a syscall.Stat_t type
-func fromStatT(s *syscall.Stat_t) (*StatT, error) {
- return &StatT{size: s.Size,
- mode: uint32(s.Mode),
- uid: s.Uid,
- gid: s.Gid,
- rdev: uint64(s.Rdev),
- mtim: s.Mtim}, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat_solaris.go b/vendor/github.com/docker/docker/pkg/system/stat_solaris.go
deleted file mode 100644
index 0216985..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat_solaris.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// +build solaris
-
-package system
-
-import (
- "syscall"
-)
-
-// fromStatT creates a system.StatT type from a syscall.Stat_t type
-func fromStatT(s *syscall.Stat_t) (*StatT, error) {
- return &StatT{size: s.Size,
- mode: uint32(s.Mode),
- uid: s.Uid,
- gid: s.Gid,
- rdev: uint64(s.Rdev),
- mtim: s.Mtim}, nil
-}
-
-// FromStatT loads a system.StatT from a syscal.Stat_t.
-func FromStatT(s *syscall.Stat_t) (*StatT, error) {
- return fromStatT(s)
-}
-
-// Stat takes a path to a file and returns
-// a system.StatT type pertaining to that file.
-//
-// Throws an error if the file does not exist
-func Stat(path string) (*StatT, error) {
- s := &syscall.Stat_t{}
- if err := syscall.Stat(path, s); err != nil {
- return nil, err
- }
- return fromStatT(s)
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat_unix_test.go b/vendor/github.com/docker/docker/pkg/system/stat_unix_test.go
deleted file mode 100644
index dee8d30..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat_unix_test.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// +build linux freebsd
-
-package system
-
-import (
- "os"
- "syscall"
- "testing"
-)
-
-// TestFromStatT tests fromStatT for a tempfile
-func TestFromStatT(t *testing.T) {
- file, _, _, dir := prepareFiles(t)
- defer os.RemoveAll(dir)
-
- stat := &syscall.Stat_t{}
- err := syscall.Lstat(file, stat)
-
- s, err := fromStatT(stat)
- if err != nil {
- t.Fatal(err)
- }
-
- if stat.Mode != s.Mode() {
- t.Fatal("got invalid mode")
- }
- if stat.Uid != s.UID() {
- t.Fatal("got invalid uid")
- }
- if stat.Gid != s.GID() {
- t.Fatal("got invalid gid")
- }
- if stat.Rdev != s.Rdev() {
- t.Fatal("got invalid rdev")
- }
- if stat.Mtim != s.Mtim() {
- t.Fatal("got invalid mtim")
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat_unsupported.go b/vendor/github.com/docker/docker/pkg/system/stat_unsupported.go
deleted file mode 100644
index f53e9de..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat_unsupported.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// +build !linux,!windows,!freebsd,!solaris,!openbsd
-
-package system
-
-import (
- "syscall"
-)
-
-// fromStatT creates a system.StatT type from a syscall.Stat_t type
-func fromStatT(s *syscall.Stat_t) (*StatT, error) {
- return &StatT{size: s.Size,
- mode: uint32(s.Mode),
- uid: s.Uid,
- gid: s.Gid,
- rdev: uint64(s.Rdev),
- mtim: s.Mtimespec}, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/stat_windows.go b/vendor/github.com/docker/docker/pkg/system/stat_windows.go
deleted file mode 100644
index 39490c6..0000000
--- a/vendor/github.com/docker/docker/pkg/system/stat_windows.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// +build windows
-
-package system
-
-import (
- "os"
- "time"
-)
-
-// StatT type contains status of a file. It contains metadata
-// like name, permission, size, etc about a file.
-type StatT struct {
- name string
- size int64
- mode os.FileMode
- modTime time.Time
- isDir bool
-}
-
-// Name returns file's name.
-func (s StatT) Name() string {
- return s.name
-}
-
-// Size returns file's size.
-func (s StatT) Size() int64 {
- return s.size
-}
-
-// Mode returns file's permission mode.
-func (s StatT) Mode() os.FileMode {
- return s.mode
-}
-
-// ModTime returns file's last modification time.
-func (s StatT) ModTime() time.Time {
- return s.modTime
-}
-
-// IsDir returns whether file is actually a directory.
-func (s StatT) IsDir() bool {
- return s.isDir
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/syscall_unix.go b/vendor/github.com/docker/docker/pkg/system/syscall_unix.go
deleted file mode 100644
index 3ae9128..0000000
--- a/vendor/github.com/docker/docker/pkg/system/syscall_unix.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// +build linux freebsd
-
-package system
-
-import "syscall"
-
-// Unmount is a platform-specific helper function to call
-// the unmount syscall.
-func Unmount(dest string) error {
- return syscall.Unmount(dest, 0)
-}
-
-// CommandLineToArgv should not be used on Unix.
-// It simply returns commandLine in the only element in the returned array.
-func CommandLineToArgv(commandLine string) ([]string, error) {
- return []string{commandLine}, nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/syscall_windows.go b/vendor/github.com/docker/docker/pkg/system/syscall_windows.go
deleted file mode 100644
index f5f2d56..0000000
--- a/vendor/github.com/docker/docker/pkg/system/syscall_windows.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package system
-
-import (
- "syscall"
- "unsafe"
-
- "github.com/Sirupsen/logrus"
-)
-
-var (
- ntuserApiset = syscall.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
- procGetVersionExW = modkernel32.NewProc("GetVersionExW")
-)
-
-// OSVersion is a wrapper for Windows version information
-// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
-type OSVersion struct {
- Version uint32
- MajorVersion uint8
- MinorVersion uint8
- Build uint16
-}
-
-// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
-type osVersionInfoEx struct {
- OSVersionInfoSize uint32
- MajorVersion uint32
- MinorVersion uint32
- BuildNumber uint32
- PlatformID uint32
- CSDVersion [128]uint16
- ServicePackMajor uint16
- ServicePackMinor uint16
- SuiteMask uint16
- ProductType byte
- Reserve byte
-}
-
-// GetOSVersion gets the operating system version on Windows. Note that
-// docker.exe must be manifested to get the correct version information.
-func GetOSVersion() OSVersion {
- var err error
- osv := OSVersion{}
- osv.Version, err = syscall.GetVersion()
- if err != nil {
- // GetVersion never fails.
- panic(err)
- }
- osv.MajorVersion = uint8(osv.Version & 0xFF)
- osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
- osv.Build = uint16(osv.Version >> 16)
- return osv
-}
-
-// IsWindowsClient returns true if the SKU is client
-func IsWindowsClient() bool {
- osviex := &osVersionInfoEx{OSVersionInfoSize: 284}
- r1, _, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(osviex)))
- if r1 == 0 {
- logrus.Warnf("GetVersionExW failed - assuming server SKU: %v", err)
- return false
- }
- const verNTWorkstation = 0x00000001
- return osviex.ProductType == verNTWorkstation
-}
-
-// Unmount is a platform-specific helper function to call
-// the unmount syscall. Not supported on Windows
-func Unmount(dest string) error {
- return nil
-}
-
-// CommandLineToArgv wraps the Windows syscall to turn a commandline into an argument array.
-func CommandLineToArgv(commandLine string) ([]string, error) {
- var argc int32
-
- argsPtr, err := syscall.UTF16PtrFromString(commandLine)
- if err != nil {
- return nil, err
- }
-
- argv, err := syscall.CommandLineToArgv(argsPtr, &argc)
- if err != nil {
- return nil, err
- }
- defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv))))
-
- newArgs := make([]string, argc)
- for i, v := range (*argv)[:argc] {
- newArgs[i] = string(syscall.UTF16ToString((*v)[:]))
- }
-
- return newArgs, nil
-}
-
-// HasWin32KSupport determines whether containers that depend on win32k can
-// run on this machine. Win32k is the driver used to implement windowing.
-func HasWin32KSupport() bool {
- // For now, check for ntuser API support on the host. In the future, a host
- // may support win32k in containers even if the host does not support ntuser
- // APIs.
- return ntuserApiset.Load() == nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/syscall_windows_test.go b/vendor/github.com/docker/docker/pkg/system/syscall_windows_test.go
deleted file mode 100644
index 4886b2b..0000000
--- a/vendor/github.com/docker/docker/pkg/system/syscall_windows_test.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package system
-
-import "testing"
-
-func TestHasWin32KSupport(t *testing.T) {
- s := HasWin32KSupport() // make sure this doesn't panic
-
- t.Logf("win32k: %v", s) // will be different on different platforms -- informative only
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/umask.go b/vendor/github.com/docker/docker/pkg/system/umask.go
deleted file mode 100644
index 3d0146b..0000000
--- a/vendor/github.com/docker/docker/pkg/system/umask.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build !windows
-
-package system
-
-import (
- "syscall"
-)
-
-// Umask sets current process's file mode creation mask to newmask
-// and returns oldmask.
-func Umask(newmask int) (oldmask int, err error) {
- return syscall.Umask(newmask), nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/umask_windows.go b/vendor/github.com/docker/docker/pkg/system/umask_windows.go
deleted file mode 100644
index 13f1de1..0000000
--- a/vendor/github.com/docker/docker/pkg/system/umask_windows.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// +build windows
-
-package system
-
-// Umask is not supported on the windows platform.
-func Umask(newmask int) (oldmask int, err error) {
- // should not be called on cli code path
- return 0, ErrNotSupportedPlatform
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_darwin.go b/vendor/github.com/docker/docker/pkg/system/utimes_darwin.go
deleted file mode 100644
index 0a16197..0000000
--- a/vendor/github.com/docker/docker/pkg/system/utimes_darwin.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package system
-
-import "syscall"
-
-// LUtimesNano is not supported by darwin platform.
-func LUtimesNano(path string, ts []syscall.Timespec) error {
- return ErrNotSupportedPlatform
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_freebsd.go b/vendor/github.com/docker/docker/pkg/system/utimes_freebsd.go
deleted file mode 100644
index e2eac3b..0000000
--- a/vendor/github.com/docker/docker/pkg/system/utimes_freebsd.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package system
-
-import (
- "syscall"
- "unsafe"
-)
-
-// LUtimesNano is used to change access and modification time of the specified path.
-// It's used for symbol link file because syscall.UtimesNano doesn't support a NOFOLLOW flag atm.
-func LUtimesNano(path string, ts []syscall.Timespec) error {
- var _path *byte
- _path, err := syscall.BytePtrFromString(path)
- if err != nil {
- return err
- }
-
- if _, _, err := syscall.Syscall(syscall.SYS_LUTIMES, uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), 0); err != 0 && err != syscall.ENOSYS {
- return err
- }
-
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_linux.go b/vendor/github.com/docker/docker/pkg/system/utimes_linux.go
deleted file mode 100644
index fc8a1ab..0000000
--- a/vendor/github.com/docker/docker/pkg/system/utimes_linux.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package system
-
-import (
- "syscall"
- "unsafe"
-)
-
-// LUtimesNano is used to change access and modification time of the specified path.
-// It's used for symbol link file because syscall.UtimesNano doesn't support a NOFOLLOW flag atm.
-func LUtimesNano(path string, ts []syscall.Timespec) error {
- // These are not currently available in syscall
- atFdCwd := -100
- atSymLinkNoFollow := 0x100
-
- var _path *byte
- _path, err := syscall.BytePtrFromString(path)
- if err != nil {
- return err
- }
-
- if _, _, err := syscall.Syscall6(syscall.SYS_UTIMENSAT, uintptr(atFdCwd), uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), uintptr(atSymLinkNoFollow), 0, 0); err != 0 && err != syscall.ENOSYS {
- return err
- }
-
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_unix_test.go b/vendor/github.com/docker/docker/pkg/system/utimes_unix_test.go
deleted file mode 100644
index 1ee0d09..0000000
--- a/vendor/github.com/docker/docker/pkg/system/utimes_unix_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// +build linux freebsd
-
-package system
-
-import (
- "io/ioutil"
- "os"
- "path/filepath"
- "syscall"
- "testing"
-)
-
-// prepareFiles creates files for testing in the temp directory
-func prepareFiles(t *testing.T) (string, string, string, string) {
- dir, err := ioutil.TempDir("", "docker-system-test")
- if err != nil {
- t.Fatal(err)
- }
-
- file := filepath.Join(dir, "exist")
- if err := ioutil.WriteFile(file, []byte("hello"), 0644); err != nil {
- t.Fatal(err)
- }
-
- invalid := filepath.Join(dir, "doesnt-exist")
-
- symlink := filepath.Join(dir, "symlink")
- if err := os.Symlink(file, symlink); err != nil {
- t.Fatal(err)
- }
-
- return file, invalid, symlink, dir
-}
-
-func TestLUtimesNano(t *testing.T) {
- file, invalid, symlink, dir := prepareFiles(t)
- defer os.RemoveAll(dir)
-
- before, err := os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
-
- ts := []syscall.Timespec{{0, 0}, {0, 0}}
- if err := LUtimesNano(symlink, ts); err != nil {
- t.Fatal(err)
- }
-
- symlinkInfo, err := os.Lstat(symlink)
- if err != nil {
- t.Fatal(err)
- }
- if before.ModTime().Unix() == symlinkInfo.ModTime().Unix() {
- t.Fatal("The modification time of the symlink should be different")
- }
-
- fileInfo, err := os.Stat(file)
- if err != nil {
- t.Fatal(err)
- }
- if before.ModTime().Unix() != fileInfo.ModTime().Unix() {
- t.Fatal("The modification time of the file should be same")
- }
-
- if err := LUtimesNano(invalid, ts); err == nil {
- t.Fatal("Doesn't return an error on a non-existing file")
- }
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go b/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go
deleted file mode 100644
index 50c3a04..0000000
--- a/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// +build !linux,!freebsd,!darwin
-
-package system
-
-import "syscall"
-
-// LUtimesNano is not supported on platforms other than linux, freebsd and darwin.
-func LUtimesNano(path string, ts []syscall.Timespec) error {
- return ErrNotSupportedPlatform
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go
deleted file mode 100644
index d2e2c05..0000000
--- a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package system
-
-import (
- "syscall"
- "unsafe"
-)
-
-// Lgetxattr retrieves the value of the extended attribute identified by attr
-// and associated with the given path in the file system.
-// It will returns a nil slice and nil error if the xattr is not set.
-func Lgetxattr(path string, attr string) ([]byte, error) {
- pathBytes, err := syscall.BytePtrFromString(path)
- if err != nil {
- return nil, err
- }
- attrBytes, err := syscall.BytePtrFromString(attr)
- if err != nil {
- return nil, err
- }
-
- dest := make([]byte, 128)
- destBytes := unsafe.Pointer(&dest[0])
- sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
- if errno == syscall.ENODATA {
- return nil, nil
- }
- if errno == syscall.ERANGE {
- dest = make([]byte, sz)
- destBytes := unsafe.Pointer(&dest[0])
- sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
- }
- if errno != 0 {
- return nil, errno
- }
-
- return dest[:sz], nil
-}
-
-var _zero uintptr
-
-// Lsetxattr sets the value of the extended attribute identified by attr
-// and associated with the given path in the file system.
-func Lsetxattr(path string, attr string, data []byte, flags int) error {
- pathBytes, err := syscall.BytePtrFromString(path)
- if err != nil {
- return err
- }
- attrBytes, err := syscall.BytePtrFromString(attr)
- if err != nil {
- return err
- }
- var dataBytes unsafe.Pointer
- if len(data) > 0 {
- dataBytes = unsafe.Pointer(&data[0])
- } else {
- dataBytes = unsafe.Pointer(&_zero)
- }
- _, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
- if errno != 0 {
- return errno
- }
- return nil
-}
diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go b/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go
deleted file mode 100644
index 0114f22..0000000
--- a/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build !linux
-
-package system
-
-// Lgetxattr is not supported on platforms other than linux.
-func Lgetxattr(path string, attr string) ([]byte, error) {
- return nil, ErrNotSupportedPlatform
-}
-
-// Lsetxattr is not supported on platforms other than linux.
-func Lsetxattr(path string, attr string, data []byte, flags int) error {
- return ErrNotSupportedPlatform
-}
diff --git a/vendor/github.com/docker/engine-api/LICENSE b/vendor/github.com/docker/engine-api/LICENSE
deleted file mode 100644
index c157bff..0000000
--- a/vendor/github.com/docker/engine-api/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- https://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- Copyright 2015-2016 Docker, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/github.com/docker/engine-api/types/filters/parse.go b/vendor/github.com/docker/engine-api/types/filters/parse.go
deleted file mode 100644
index dc2c48b..0000000
--- a/vendor/github.com/docker/engine-api/types/filters/parse.go
+++ /dev/null
@@ -1,307 +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
- return fieldValues[source]
-}
-
-// UniqueExactMatch returns true if there is only one filter and the source matches exactly this one.
-func (filters Args) UniqueExactMatch(field, source 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 len(filters.fields[field]) != 1 {
- return false
- }
-
- // try to match full name value to avoid O(N) regular expression matching
- return fieldValues[source]
-}
-
-// 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
-}
diff --git a/vendor/github.com/docker/engine-api/types/filters/parse_test.go b/vendor/github.com/docker/engine-api/types/filters/parse_test.go
deleted file mode 100644
index b2ed27b..0000000
--- a/vendor/github.com/docker/engine-api/types/filters/parse_test.go
+++ /dev/null
@@ -1,417 +0,0 @@
-package filters
-
-import (
- "fmt"
- "testing"
-)
-
-func TestParseArgs(t *testing.T) {
- // equivalent of `docker ps -f 'created=today' -f 'image.name=ubuntu*' -f 'image.name=*untu'`
- flagArgs := []string{
- "created=today",
- "image.name=ubuntu*",
- "image.name=*untu",
- }
- var (
- args = NewArgs()
- err error
- )
- for i := range flagArgs {
- args, err = ParseFlag(flagArgs[i], args)
- if err != nil {
- t.Errorf("failed to parse %s: %s", flagArgs[i], err)
- }
- }
- if len(args.Get("created")) != 1 {
- t.Errorf("failed to set this arg")
- }
- if len(args.Get("image.name")) != 2 {
- t.Errorf("the args should have collapsed")
- }
-}
-
-func TestParseArgsEdgeCase(t *testing.T) {
- var filters Args
- args, err := ParseFlag("", filters)
- if err != nil {
- t.Fatal(err)
- }
- if args.Len() != 0 {
- t.Fatalf("Expected an empty Args (map), got %v", args)
- }
- if args, err = ParseFlag("anything", args); err == nil || err != ErrBadFormat {
- t.Fatalf("Expected ErrBadFormat, got %v", err)
- }
-}
-
-func TestToParam(t *testing.T) {
- fields := map[string]map[string]bool{
- "created": {"today": true},
- "image.name": {"ubuntu*": true, "*untu": true},
- }
- a := Args{fields: fields}
-
- _, err := ToParam(a)
- if err != nil {
- t.Errorf("failed to marshal the filters: %s", err)
- }
-}
-
-func TestToParamWithVersion(t *testing.T) {
- fields := map[string]map[string]bool{
- "created": {"today": true},
- "image.name": {"ubuntu*": true, "*untu": true},
- }
- a := Args{fields: fields}
-
- str1, err := ToParamWithVersion("1.21", a)
- if err != nil {
- t.Errorf("failed to marshal the filters with version < 1.22: %s", err)
- }
- str2, err := ToParamWithVersion("1.22", a)
- if err != nil {
- t.Errorf("failed to marshal the filters with version >= 1.22: %s", err)
- }
- if str1 != `{"created":["today"],"image.name":["*untu","ubuntu*"]}` &&
- str1 != `{"created":["today"],"image.name":["ubuntu*","*untu"]}` {
- t.Errorf("incorrectly marshaled the filters: %s", str1)
- }
- if str2 != `{"created":{"today":true},"image.name":{"*untu":true,"ubuntu*":true}}` &&
- str2 != `{"created":{"today":true},"image.name":{"ubuntu*":true,"*untu":true}}` {
- t.Errorf("incorrectly marshaled the filters: %s", str2)
- }
-}
-
-func TestFromParam(t *testing.T) {
- invalids := []string{
- "anything",
- "['a','list']",
- "{'key': 'value'}",
- `{"key": "value"}`,
- }
- valid := map[*Args][]string{
- &Args{fields: map[string]map[string]bool{"key": {"value": true}}}: {
- `{"key": ["value"]}`,
- `{"key": {"value": true}}`,
- },
- &Args{fields: map[string]map[string]bool{"key": {"value1": true, "value2": true}}}: {
- `{"key": ["value1", "value2"]}`,
- `{"key": {"value1": true, "value2": true}}`,
- },
- &Args{fields: map[string]map[string]bool{"key1": {"value1": true}, "key2": {"value2": true}}}: {
- `{"key1": ["value1"], "key2": ["value2"]}`,
- `{"key1": {"value1": true}, "key2": {"value2": true}}`,
- },
- }
-
- for _, invalid := range invalids {
- if _, err := FromParam(invalid); err == nil {
- t.Fatalf("Expected an error with %v, got nothing", invalid)
- }
- }
-
- for expectedArgs, matchers := range valid {
- for _, json := range matchers {
- args, err := FromParam(json)
- if err != nil {
- t.Fatal(err)
- }
- if args.Len() != expectedArgs.Len() {
- t.Fatalf("Expected %v, go %v", expectedArgs, args)
- }
- for key, expectedValues := range expectedArgs.fields {
- values := args.Get(key)
-
- if len(values) != len(expectedValues) {
- t.Fatalf("Expected %v, go %v", expectedArgs, args)
- }
-
- for _, v := range values {
- if !expectedValues[v] {
- t.Fatalf("Expected %v, go %v", expectedArgs, args)
- }
- }
- }
- }
- }
-}
-
-func TestEmpty(t *testing.T) {
- a := Args{}
- v, err := ToParam(a)
- if err != nil {
- t.Errorf("failed to marshal the filters: %s", err)
- }
- v1, err := FromParam(v)
- if err != nil {
- t.Errorf("%s", err)
- }
- if a.Len() != v1.Len() {
- t.Errorf("these should both be empty sets")
- }
-}
-
-func TestArgsMatchKVListEmptySources(t *testing.T) {
- args := NewArgs()
- if !args.MatchKVList("created", map[string]string{}) {
- t.Fatalf("Expected true for (%v,created), got true", args)
- }
-
- args = Args{map[string]map[string]bool{"created": {"today": true}}}
- if args.MatchKVList("created", map[string]string{}) {
- t.Fatalf("Expected false for (%v,created), got true", args)
- }
-}
-
-func TestArgsMatchKVList(t *testing.T) {
- // Not empty sources
- sources := map[string]string{
- "key1": "value1",
- "key2": "value2",
- "key3": "value3",
- }
-
- matches := map[*Args]string{
- &Args{}: "field",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"today": true},
- "labels": map[string]bool{"key1": true}},
- }: "labels",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"today": true},
- "labels": map[string]bool{"key1=value1": true}},
- }: "labels",
- }
-
- for args, field := range matches {
- if args.MatchKVList(field, sources) != true {
- t.Fatalf("Expected true for %v on %v, got false", sources, args)
- }
- }
-
- differs := map[*Args]string{
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"today": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"today": true},
- "labels": map[string]bool{"key4": true}},
- }: "labels",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"today": true},
- "labels": map[string]bool{"key1=value3": true}},
- }: "labels",
- }
-
- for args, field := range differs {
- if args.MatchKVList(field, sources) != false {
- t.Fatalf("Expected false for %v on %v, got true", sources, args)
- }
- }
-}
-
-func TestArgsMatch(t *testing.T) {
- source := "today"
-
- matches := map[*Args]string{
- &Args{}: "field",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"today": true}},
- }: "today",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"to*": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"to(.*)": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"tod": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"anyting": true, "to*": true}},
- }: "created",
- }
-
- for args, field := range matches {
- if args.Match(field, source) != true {
- t.Fatalf("Expected true for %v on %v, got false", source, args)
- }
- }
-
- differs := map[*Args]string{
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"tomorrow": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"to(day": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"tom(.*)": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"tom": true}},
- }: "created",
- &Args{map[string]map[string]bool{
- "created": map[string]bool{"today1": true},
- "labels": map[string]bool{"today": true}},
- }: "created",
- }
-
- for args, field := range differs {
- if args.Match(field, source) != false {
- t.Fatalf("Expected false for %v on %v, got true", source, args)
- }
- }
-}
-
-func TestAdd(t *testing.T) {
- f := NewArgs()
- f.Add("status", "running")
- v := f.fields["status"]
- if len(v) != 1 || !v["running"] {
- t.Fatalf("Expected to include a running status, got %v", v)
- }
-
- f.Add("status", "paused")
- if len(v) != 2 || !v["paused"] {
- t.Fatalf("Expected to include a paused status, got %v", v)
- }
-}
-
-func TestDel(t *testing.T) {
- f := NewArgs()
- f.Add("status", "running")
- f.Del("status", "running")
- v := f.fields["status"]
- if v["running"] {
- t.Fatalf("Expected to not include a running status filter, got true")
- }
-}
-
-func TestLen(t *testing.T) {
- f := NewArgs()
- if f.Len() != 0 {
- t.Fatalf("Expected to not include any field")
- }
- f.Add("status", "running")
- if f.Len() != 1 {
- t.Fatalf("Expected to include one field")
- }
-}
-
-func TestExactMatch(t *testing.T) {
- f := NewArgs()
-
- if !f.ExactMatch("status", "running") {
- t.Fatalf("Expected to match `running` when there are no filters, got false")
- }
-
- f.Add("status", "running")
- f.Add("status", "pause*")
-
- if !f.ExactMatch("status", "running") {
- t.Fatalf("Expected to match `running` with one of the filters, got false")
- }
-
- if f.ExactMatch("status", "paused") {
- t.Fatalf("Expected to not match `paused` with one of the filters, got true")
- }
-}
-
-func TestOnlyOneExactMatch(t *testing.T) {
- f := NewArgs()
-
- if !f.UniqueExactMatch("status", "running") {
- t.Fatalf("Expected to match `running` when there are no filters, got false")
- }
-
- f.Add("status", "running")
-
- if !f.UniqueExactMatch("status", "running") {
- t.Fatalf("Expected to match `running` with one of the filters, got false")
- }
-
- if f.UniqueExactMatch("status", "paused") {
- t.Fatalf("Expected to not match `paused` with one of the filters, got true")
- }
-
- f.Add("status", "pause")
- if f.UniqueExactMatch("status", "running") {
- t.Fatalf("Expected to not match only `running` with two filters, got true")
- }
-}
-
-func TestInclude(t *testing.T) {
- f := NewArgs()
- if f.Include("status") {
- t.Fatalf("Expected to not include a status key, got true")
- }
- f.Add("status", "running")
- if !f.Include("status") {
- t.Fatalf("Expected to include a status key, got false")
- }
-}
-
-func TestValidate(t *testing.T) {
- f := NewArgs()
- f.Add("status", "running")
-
- valid := map[string]bool{
- "status": true,
- "dangling": true,
- }
-
- if err := f.Validate(valid); err != nil {
- t.Fatal(err)
- }
-
- f.Add("bogus", "running")
- if err := f.Validate(valid); err == nil {
- t.Fatalf("Expected to return an error, got nil")
- }
-}
-
-func TestWalkValues(t *testing.T) {
- f := NewArgs()
- f.Add("status", "running")
- f.Add("status", "paused")
-
- f.WalkValues("status", func(value string) error {
- if value != "running" && value != "paused" {
- t.Fatalf("Unexpected value %s", value)
- }
- return nil
- })
-
- err := f.WalkValues("status", func(value string) error {
- return fmt.Errorf("return")
- })
- if err == nil {
- t.Fatalf("Expected to get an error, got nil")
- }
-
- err = f.WalkValues("foo", func(value string) error {
- return fmt.Errorf("return")
- })
- if err != nil {
- t.Fatalf("Expected to not iterate when the field doesn't exist, got %v", err)
- }
-}
-
-func TestFuzzyMatch(t *testing.T) {
- f := NewArgs()
- f.Add("container", "foo")
-
- cases := map[string]bool{
- "foo": true,
- "foobar": true,
- "barfoo": false,
- "bar": false,
- }
- for source, match := range cases {
- got := f.FuzzyMatch("container", source)
- if got != match {
- t.Fatalf("Expected %v, got %v: %s", match, got, source)
- }
- }
-}
diff --git a/vendor/github.com/docker/engine-api/types/versions/README.md b/vendor/github.com/docker/engine-api/types/versions/README.md
deleted file mode 100644
index cdac50a..0000000
--- a/vendor/github.com/docker/engine-api/types/versions/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-## Legacy API type versions
-
-This package includes types for legacy API versions. The stable version of the API types live in `api/types/*.go`.
-
-Consider moving a type here when you need to keep backwards compatibility in the API. This legacy types are organized by the latest API version they appear in. For instance, types in the `v1p19` package are valid for API versions below or equal `1.19`. Types in the `v1p20` package are valid for the API version `1.20`, since the versions below that will use the legacy types in `v1p19`.
-
-### Package name conventions
-
-The package name convention is to use `v` as a prefix for the version number and `p`(patch) as a separator. We use this nomenclature due to a few restrictions in the Go package name convention:
-
-1. We cannot use `.` because it's interpreted by the language, think of `v1.20.CallFunction`.
-2. We cannot use `_` because golint complains about it. The code is actually valid, but it looks probably more weird: `v1_20.CallFunction`.
-
-For instance, if you want to modify a type that was available in the version `1.21` of the API but it will have different fields in the version `1.22`, you want to create a new package under `api/types/versions/v1p21`.
diff --git a/vendor/github.com/docker/engine-api/types/versions/compare.go b/vendor/github.com/docker/engine-api/types/versions/compare.go
deleted file mode 100644
index 611d4fe..0000000
--- a/vendor/github.com/docker/engine-api/types/versions/compare.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package versions
-
-import (
- "strconv"
- "strings"
-)
-
-// compare compares two version strings
-// returns -1 if v1 < v2, 1 if v1 > v2, 0 otherwise.
-func compare(v1, v2 string) int {
- var (
- currTab = strings.Split(v1, ".")
- otherTab = strings.Split(v2, ".")
- )
-
- max := len(currTab)
- if len(otherTab) > max {
- max = len(otherTab)
- }
- for i := 0; i < max; i++ {
- var currInt, otherInt int
-
- if len(currTab) > i {
- currInt, _ = strconv.Atoi(currTab[i])
- }
- if len(otherTab) > i {
- otherInt, _ = strconv.Atoi(otherTab[i])
- }
- if currInt > otherInt {
- return 1
- }
- if otherInt > currInt {
- return -1
- }
- }
- return 0
-}
-
-// LessThan checks if a version is less than another
-func LessThan(v, other string) bool {
- return compare(v, other) == -1
-}
-
-// LessThanOrEqualTo checks if a version is less than or equal to another
-func LessThanOrEqualTo(v, other string) bool {
- return compare(v, other) <= 0
-}
-
-// GreaterThan checks if a version is greater than another
-func GreaterThan(v, other string) bool {
- return compare(v, other) == 1
-}
-
-// GreaterThanOrEqualTo checks if a version is greater than or equal to another
-func GreaterThanOrEqualTo(v, other string) bool {
- return compare(v, other) >= 0
-}
-
-// Equal checks if a version is equal to another
-func Equal(v, other string) bool {
- return compare(v, other) == 0
-}
diff --git a/vendor/github.com/docker/engine-api/types/versions/compare_test.go b/vendor/github.com/docker/engine-api/types/versions/compare_test.go
deleted file mode 100644
index c2b9686..0000000
--- a/vendor/github.com/docker/engine-api/types/versions/compare_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package versions
-
-import (
- "testing"
-)
-
-func assertVersion(t *testing.T, a, b string, result int) {
- if r := compare(a, b); r != result {
- t.Fatalf("Unexpected version comparison result. Found %d, expected %d", r, result)
- }
-}
-
-func TestCompareVersion(t *testing.T) {
- assertVersion(t, "1.12", "1.12", 0)
- assertVersion(t, "1.0.0", "1", 0)
- assertVersion(t, "1", "1.0.0", 0)
- assertVersion(t, "1.05.00.0156", "1.0.221.9289", 1)
- assertVersion(t, "1", "1.0.1", -1)
- assertVersion(t, "1.0.1", "1", 1)
- assertVersion(t, "1.0.1", "1.0.2", -1)
- assertVersion(t, "1.0.2", "1.0.3", -1)
- assertVersion(t, "1.0.3", "1.1", -1)
- assertVersion(t, "1.1", "1.1.1", -1)
- assertVersion(t, "1.1.1", "1.1.2", -1)
- assertVersion(t, "1.1.2", "1.2", -1)
-}
diff --git a/vendor/github.com/docker/go-units/CONTRIBUTING.md b/vendor/github.com/docker/go-units/CONTRIBUTING.md
deleted file mode 100644
index 9ea86d7..0000000
--- a/vendor/github.com/docker/go-units/CONTRIBUTING.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Contributing to go-units
-
-Want to hack on go-units? Awesome! Here are instructions to get you started.
-
-go-units is a part of the [Docker](https://www.docker.com) project, and follows
-the same rules and principles. If you're already familiar with the way
-Docker does things, you'll feel right at home.
-
-Otherwise, go read Docker's
-[contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md),
-[issue triaging](https://github.com/docker/docker/blob/master/project/ISSUE-TRIAGE.md),
-[review process](https://github.com/docker/docker/blob/master/project/REVIEWING.md) and
-[branches and tags](https://github.com/docker/docker/blob/master/project/BRANCHES-AND-TAGS.md).
-
-### Sign your work
-
-The sign-off is a simple line at the end of the explanation for the patch. Your
-signature certifies that you wrote the patch or otherwise have the right to pass
-it on as an open-source patch. The rules are pretty simple: if you can certify
-the below (from [developercertificate.org](http://developercertificate.org/)):
-
-```
-Developer Certificate of Origin
-Version 1.1
-
-Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
-660 York Street, Suite 102,
-San Francisco, CA 94110 USA
-
-Everyone is permitted to copy and distribute verbatim copies of this
-license document, but changing it is not allowed.
-
-Developer's Certificate of Origin 1.1
-
-By making a contribution to this project, I certify that:
-
-(a) The contribution was created in whole or in part by me and I
- have the right to submit it under the open source license
- indicated in the file; or
-
-(b) The contribution is based upon previous work that, to the best
- of my knowledge, is covered under an appropriate open source
- license and I have the right under that license to submit that
- work with modifications, whether created in whole or in part
- by me, under the same open source license (unless I am
- permitted to submit under a different license), as indicated
- in the file; or
-
-(c) The contribution was provided directly to me by some other
- person who certified (a), (b) or (c) and I have not modified
- it.
-
-(d) I understand and agree that this project and the contribution
- are public and that a record of the contribution (including all
- personal information I submit with it, including my sign-off) is
- maintained indefinitely and may be redistributed consistent with
- this project or the open source license(s) involved.
-```
-
-Then you just add a line to every git commit message:
-
- Signed-off-by: Joe Smith
-
-Use your real name (sorry, no pseudonyms or anonymous contributions.)
-
-If you set your `user.name` and `user.email` git configs, you can sign your
-commit automatically with `git commit -s`.
diff --git a/vendor/github.com/docker/go-units/LICENSE b/vendor/github.com/docker/go-units/LICENSE
deleted file mode 100644
index b55b37b..0000000
--- a/vendor/github.com/docker/go-units/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- https://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- Copyright 2015 Docker, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/github.com/docker/go-units/MAINTAINERS b/vendor/github.com/docker/go-units/MAINTAINERS
deleted file mode 100644
index 477be8b..0000000
--- a/vendor/github.com/docker/go-units/MAINTAINERS
+++ /dev/null
@@ -1,27 +0,0 @@
-# go-connections maintainers file
-#
-# This file describes who runs the docker/go-connections project and how.
-# This is a living document - if you see something out of date or missing, speak up!
-#
-# It is structured to be consumable by both humans and programs.
-# To extract its contents programmatically, use any TOML-compliant parser.
-#
-# This file is compiled into the MAINTAINERS file in docker/opensource.
-#
-[Org]
- [Org."Core maintainers"]
- people = [
- "calavera",
- ]
-
-[people]
-
-# A reference list of all people associated with the project.
-# All other sections should refer to people by their canonical key
-# in the people section.
-
- # ADD YOURSELF HERE IN ALPHABETICAL ORDER
- [people.calavera]
- Name = "David Calavera"
- Email = "david.calavera@gmail.com"
- GitHub = "calavera"
diff --git a/vendor/github.com/docker/go-units/README.md b/vendor/github.com/docker/go-units/README.md
deleted file mode 100644
index 4f70a4e..0000000
--- a/vendor/github.com/docker/go-units/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-[](https://godoc.org/github.com/docker/go-units)
-
-# Introduction
-
-go-units is a library to transform human friendly measurements into machine friendly values.
-
-## Usage
-
-See the [docs in godoc](https://godoc.org/github.com/docker/go-units) for examples and documentation.
-
-## Copyright and license
-
-Copyright © 2015 Docker, Inc.
-
-go-units is licensed under the Apache License, Version 2.0.
-See [LICENSE](LICENSE) for the full text of the license.
diff --git a/vendor/github.com/docker/go-units/circle.yml b/vendor/github.com/docker/go-units/circle.yml
deleted file mode 100644
index 9043b35..0000000
--- a/vendor/github.com/docker/go-units/circle.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-dependencies:
- post:
- # install golint
- - go get github.com/golang/lint/golint
-
-test:
- pre:
- # run analysis before tests
- - go vet ./...
- - test -z "$(golint ./... | tee /dev/stderr)"
- - test -z "$(gofmt -s -l . | tee /dev/stderr)"
diff --git a/vendor/github.com/docker/go-units/duration.go b/vendor/github.com/docker/go-units/duration.go
deleted file mode 100644
index c219a8a..0000000
--- a/vendor/github.com/docker/go-units/duration.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Package units provides helper function to parse and print size and time units
-// in human-readable format.
-package units
-
-import (
- "fmt"
- "time"
-)
-
-// HumanDuration returns a human-readable approximation of a duration
-// (eg. "About a minute", "4 hours ago", etc.).
-func HumanDuration(d time.Duration) string {
- if seconds := int(d.Seconds()); seconds < 1 {
- return "Less than a second"
- } else if seconds < 60 {
- return fmt.Sprintf("%d seconds", seconds)
- } else if minutes := int(d.Minutes()); minutes == 1 {
- return "About a minute"
- } else if minutes < 60 {
- return fmt.Sprintf("%d minutes", minutes)
- } else if hours := int(d.Hours()); hours == 1 {
- return "About an hour"
- } else if hours < 48 {
- return fmt.Sprintf("%d hours", hours)
- } else if hours < 24*7*2 {
- return fmt.Sprintf("%d days", hours/24)
- } else if hours < 24*30*3 {
- return fmt.Sprintf("%d weeks", hours/24/7)
- } else if hours < 24*365*2 {
- return fmt.Sprintf("%d months", hours/24/30)
- }
- return fmt.Sprintf("%d years", int(d.Hours())/24/365)
-}
diff --git a/vendor/github.com/docker/go-units/duration_test.go b/vendor/github.com/docker/go-units/duration_test.go
deleted file mode 100644
index 63baa51..0000000
--- a/vendor/github.com/docker/go-units/duration_test.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package units
-
-import (
- "fmt"
- "testing"
- "time"
-)
-
-func ExampleHumanDuration() {
- fmt.Println(HumanDuration(450 * time.Millisecond))
- fmt.Println(HumanDuration(47 * time.Second))
- fmt.Println(HumanDuration(1 * time.Minute))
- fmt.Println(HumanDuration(3 * time.Minute))
- fmt.Println(HumanDuration(35 * time.Minute))
- fmt.Println(HumanDuration(35*time.Minute + 40*time.Second))
- fmt.Println(HumanDuration(1 * time.Hour))
- fmt.Println(HumanDuration(1*time.Hour + 45*time.Minute))
- fmt.Println(HumanDuration(3 * time.Hour))
- fmt.Println(HumanDuration(3*time.Hour + 59*time.Minute))
- fmt.Println(HumanDuration(3*time.Hour + 60*time.Minute))
- fmt.Println(HumanDuration(24 * time.Hour))
- fmt.Println(HumanDuration(24*time.Hour + 12*time.Hour))
- fmt.Println(HumanDuration(2 * 24 * time.Hour))
- fmt.Println(HumanDuration(7 * 24 * time.Hour))
- fmt.Println(HumanDuration(13*24*time.Hour + 5*time.Hour))
- fmt.Println(HumanDuration(2 * 7 * 24 * time.Hour))
- fmt.Println(HumanDuration(2*7*24*time.Hour + 4*24*time.Hour))
- fmt.Println(HumanDuration(3 * 7 * 24 * time.Hour))
- fmt.Println(HumanDuration(4 * 7 * 24 * time.Hour))
- fmt.Println(HumanDuration(4*7*24*time.Hour + 3*24*time.Hour))
- fmt.Println(HumanDuration(1 * 30 * 24 * time.Hour))
- fmt.Println(HumanDuration(1*30*24*time.Hour + 2*7*24*time.Hour))
- fmt.Println(HumanDuration(2 * 30 * 24 * time.Hour))
- fmt.Println(HumanDuration(3*30*24*time.Hour + 1*7*24*time.Hour))
- fmt.Println(HumanDuration(5*30*24*time.Hour + 2*7*24*time.Hour))
- fmt.Println(HumanDuration(13 * 30 * 24 * time.Hour))
- fmt.Println(HumanDuration(23 * 30 * 24 * time.Hour))
- fmt.Println(HumanDuration(24 * 30 * 24 * time.Hour))
- fmt.Println(HumanDuration(24*30*24*time.Hour + 2*7*24*time.Hour))
- fmt.Println(HumanDuration(3*365*24*time.Hour + 2*30*24*time.Hour))
-}
-
-func TestHumanDuration(t *testing.T) {
- // Useful duration abstractions
- day := 24 * time.Hour
- week := 7 * day
- month := 30 * day
- year := 365 * day
-
- assertEquals(t, "Less than a second", HumanDuration(450*time.Millisecond))
- assertEquals(t, "47 seconds", HumanDuration(47*time.Second))
- assertEquals(t, "About a minute", HumanDuration(1*time.Minute))
- assertEquals(t, "3 minutes", HumanDuration(3*time.Minute))
- assertEquals(t, "35 minutes", HumanDuration(35*time.Minute))
- assertEquals(t, "35 minutes", HumanDuration(35*time.Minute+40*time.Second))
- assertEquals(t, "About an hour", HumanDuration(1*time.Hour))
- assertEquals(t, "About an hour", HumanDuration(1*time.Hour+45*time.Minute))
- assertEquals(t, "3 hours", HumanDuration(3*time.Hour))
- assertEquals(t, "3 hours", HumanDuration(3*time.Hour+59*time.Minute))
- assertEquals(t, "4 hours", HumanDuration(3*time.Hour+60*time.Minute))
- assertEquals(t, "24 hours", HumanDuration(24*time.Hour))
- assertEquals(t, "36 hours", HumanDuration(1*day+12*time.Hour))
- assertEquals(t, "2 days", HumanDuration(2*day))
- assertEquals(t, "7 days", HumanDuration(7*day))
- assertEquals(t, "13 days", HumanDuration(13*day+5*time.Hour))
- assertEquals(t, "2 weeks", HumanDuration(2*week))
- assertEquals(t, "2 weeks", HumanDuration(2*week+4*day))
- assertEquals(t, "3 weeks", HumanDuration(3*week))
- assertEquals(t, "4 weeks", HumanDuration(4*week))
- assertEquals(t, "4 weeks", HumanDuration(4*week+3*day))
- assertEquals(t, "4 weeks", HumanDuration(1*month))
- assertEquals(t, "6 weeks", HumanDuration(1*month+2*week))
- assertEquals(t, "8 weeks", HumanDuration(2*month))
- assertEquals(t, "3 months", HumanDuration(3*month+1*week))
- assertEquals(t, "5 months", HumanDuration(5*month+2*week))
- assertEquals(t, "13 months", HumanDuration(13*month))
- assertEquals(t, "23 months", HumanDuration(23*month))
- assertEquals(t, "24 months", HumanDuration(24*month))
- assertEquals(t, "2 years", HumanDuration(24*month+2*week))
- assertEquals(t, "3 years", HumanDuration(3*year+2*month))
-}
diff --git a/vendor/github.com/docker/go-units/size.go b/vendor/github.com/docker/go-units/size.go
deleted file mode 100644
index f5b82ea..0000000
--- a/vendor/github.com/docker/go-units/size.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package units
-
-import (
- "fmt"
- "regexp"
- "strconv"
- "strings"
-)
-
-// See: http://en.wikipedia.org/wiki/Binary_prefix
-const (
- // Decimal
-
- KB = 1000
- MB = 1000 * KB
- GB = 1000 * MB
- TB = 1000 * GB
- PB = 1000 * TB
-
- // Binary
-
- KiB = 1024
- MiB = 1024 * KiB
- GiB = 1024 * MiB
- TiB = 1024 * GiB
- PiB = 1024 * TiB
-)
-
-type unitMap map[string]int64
-
-var (
- decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB}
- binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB}
- sizeRegex = regexp.MustCompile(`^(\d+(\.\d+)*) ?([kKmMgGtTpP])?[bB]?$`)
-)
-
-var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
-var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
-
-// CustomSize returns a human-readable approximation of a size
-// using custom format.
-func CustomSize(format string, size float64, base float64, _map []string) string {
- i := 0
- unitsLimit := len(_map) - 1
- for size >= base && i < unitsLimit {
- size = size / base
- i++
- }
- return fmt.Sprintf(format, size, _map[i])
-}
-
-// HumanSize returns a human-readable approximation of a size
-// capped at 4 valid numbers (eg. "2.746 MB", "796 KB").
-func HumanSize(size float64) string {
- return CustomSize("%.4g %s", size, 1000.0, decimapAbbrs)
-}
-
-// BytesSize returns a human-readable size in bytes, kibibytes,
-// mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB").
-func BytesSize(size float64) string {
- return CustomSize("%.4g %s", size, 1024.0, binaryAbbrs)
-}
-
-// FromHumanSize returns an integer from a human-readable specification of a
-// size using SI standard (eg. "44kB", "17MB").
-func FromHumanSize(size string) (int64, error) {
- return parseSize(size, decimalMap)
-}
-
-// RAMInBytes parses a human-readable string representing an amount of RAM
-// in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and
-// returns the number of bytes, or -1 if the string is unparseable.
-// Units are case-insensitive, and the 'b' suffix is optional.
-func RAMInBytes(size string) (int64, error) {
- return parseSize(size, binaryMap)
-}
-
-// Parses the human-readable size string into the amount it represents.
-func parseSize(sizeStr string, uMap unitMap) (int64, error) {
- matches := sizeRegex.FindStringSubmatch(sizeStr)
- if len(matches) != 4 {
- return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
- }
-
- size, err := strconv.ParseFloat(matches[1], 64)
- if err != nil {
- return -1, err
- }
-
- unitPrefix := strings.ToLower(matches[3])
- if mul, ok := uMap[unitPrefix]; ok {
- size *= float64(mul)
- }
-
- return int64(size), nil
-}
diff --git a/vendor/github.com/docker/go-units/size_test.go b/vendor/github.com/docker/go-units/size_test.go
deleted file mode 100644
index 7b75a0b..0000000
--- a/vendor/github.com/docker/go-units/size_test.go
+++ /dev/null
@@ -1,165 +0,0 @@
-package units
-
-import (
- "fmt"
- "reflect"
- "runtime"
- "strings"
- "testing"
-)
-
-func ExampleBytesSize() {
- fmt.Println(BytesSize(1024))
- fmt.Println(BytesSize(1024 * 1024))
- fmt.Println(BytesSize(1048576))
- fmt.Println(BytesSize(2 * MiB))
- fmt.Println(BytesSize(3.42 * GiB))
- fmt.Println(BytesSize(5.372 * TiB))
- fmt.Println(BytesSize(2.22 * PiB))
-}
-
-func ExampleHumanSize() {
- fmt.Println(HumanSize(1000))
- fmt.Println(HumanSize(1024))
- fmt.Println(HumanSize(1000000))
- fmt.Println(HumanSize(1048576))
- fmt.Println(HumanSize(2 * MB))
- fmt.Println(HumanSize(float64(3.42 * GB)))
- fmt.Println(HumanSize(float64(5.372 * TB)))
- fmt.Println(HumanSize(float64(2.22 * PB)))
-}
-
-func ExampleFromHumanSize() {
- fmt.Println(FromHumanSize("32"))
- fmt.Println(FromHumanSize("32b"))
- fmt.Println(FromHumanSize("32B"))
- fmt.Println(FromHumanSize("32k"))
- fmt.Println(FromHumanSize("32K"))
- fmt.Println(FromHumanSize("32kb"))
- fmt.Println(FromHumanSize("32Kb"))
- fmt.Println(FromHumanSize("32Mb"))
- fmt.Println(FromHumanSize("32Gb"))
- fmt.Println(FromHumanSize("32Tb"))
- fmt.Println(FromHumanSize("32Pb"))
-}
-
-func ExampleRAMInBytes() {
- fmt.Println(RAMInBytes("32"))
- fmt.Println(RAMInBytes("32b"))
- fmt.Println(RAMInBytes("32B"))
- fmt.Println(RAMInBytes("32k"))
- fmt.Println(RAMInBytes("32K"))
- fmt.Println(RAMInBytes("32kb"))
- fmt.Println(RAMInBytes("32Kb"))
- fmt.Println(RAMInBytes("32Mb"))
- fmt.Println(RAMInBytes("32Gb"))
- fmt.Println(RAMInBytes("32Tb"))
- fmt.Println(RAMInBytes("32Pb"))
- fmt.Println(RAMInBytes("32PB"))
- fmt.Println(RAMInBytes("32P"))
-}
-
-func TestBytesSize(t *testing.T) {
- assertEquals(t, "1 KiB", BytesSize(1024))
- assertEquals(t, "1 MiB", BytesSize(1024*1024))
- assertEquals(t, "1 MiB", BytesSize(1048576))
- assertEquals(t, "2 MiB", BytesSize(2*MiB))
- assertEquals(t, "3.42 GiB", BytesSize(3.42*GiB))
- assertEquals(t, "5.372 TiB", BytesSize(5.372*TiB))
- assertEquals(t, "2.22 PiB", BytesSize(2.22*PiB))
- assertEquals(t, "1.049e+06 YiB", BytesSize(KiB*KiB*KiB*KiB*KiB*PiB))
-}
-
-func TestHumanSize(t *testing.T) {
- assertEquals(t, "1 kB", HumanSize(1000))
- assertEquals(t, "1.024 kB", HumanSize(1024))
- assertEquals(t, "1 MB", HumanSize(1000000))
- assertEquals(t, "1.049 MB", HumanSize(1048576))
- assertEquals(t, "2 MB", HumanSize(2*MB))
- assertEquals(t, "3.42 GB", HumanSize(float64(3.42*GB)))
- assertEquals(t, "5.372 TB", HumanSize(float64(5.372*TB)))
- assertEquals(t, "2.22 PB", HumanSize(float64(2.22*PB)))
- assertEquals(t, "1e+04 YB", HumanSize(float64(10000000000000*PB)))
-}
-
-func TestFromHumanSize(t *testing.T) {
- assertSuccessEquals(t, 32, FromHumanSize, "32")
- assertSuccessEquals(t, 32, FromHumanSize, "32b")
- assertSuccessEquals(t, 32, FromHumanSize, "32B")
- assertSuccessEquals(t, 32*KB, FromHumanSize, "32k")
- assertSuccessEquals(t, 32*KB, FromHumanSize, "32K")
- assertSuccessEquals(t, 32*KB, FromHumanSize, "32kb")
- assertSuccessEquals(t, 32*KB, FromHumanSize, "32Kb")
- assertSuccessEquals(t, 32*MB, FromHumanSize, "32Mb")
- assertSuccessEquals(t, 32*GB, FromHumanSize, "32Gb")
- assertSuccessEquals(t, 32*TB, FromHumanSize, "32Tb")
- assertSuccessEquals(t, 32*PB, FromHumanSize, "32Pb")
-
- assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5kB")
- assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5 kB")
- assertSuccessEquals(t, 32, FromHumanSize, "32.5 B")
-
- assertError(t, FromHumanSize, "")
- assertError(t, FromHumanSize, "hello")
- assertError(t, FromHumanSize, "-32")
- assertError(t, FromHumanSize, ".3kB")
- assertError(t, FromHumanSize, " 32 ")
- assertError(t, FromHumanSize, "32m b")
- assertError(t, FromHumanSize, "32bm")
-}
-
-func TestRAMInBytes(t *testing.T) {
- assertSuccessEquals(t, 32, RAMInBytes, "32")
- assertSuccessEquals(t, 32, RAMInBytes, "32b")
- assertSuccessEquals(t, 32, RAMInBytes, "32B")
- assertSuccessEquals(t, 32*KiB, RAMInBytes, "32k")
- assertSuccessEquals(t, 32*KiB, RAMInBytes, "32K")
- assertSuccessEquals(t, 32*KiB, RAMInBytes, "32kb")
- assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kb")
- assertSuccessEquals(t, 32*MiB, RAMInBytes, "32Mb")
- assertSuccessEquals(t, 32*GiB, RAMInBytes, "32Gb")
- assertSuccessEquals(t, 32*TiB, RAMInBytes, "32Tb")
- assertSuccessEquals(t, 32*PiB, RAMInBytes, "32Pb")
- assertSuccessEquals(t, 32*PiB, RAMInBytes, "32PB")
- assertSuccessEquals(t, 32*PiB, RAMInBytes, "32P")
-
- assertSuccessEquals(t, 32, RAMInBytes, "32.3")
- tmp := 32.3 * MiB
- assertSuccessEquals(t, int64(tmp), RAMInBytes, "32.3 mb")
-
- assertError(t, RAMInBytes, "")
- assertError(t, RAMInBytes, "hello")
- assertError(t, RAMInBytes, "-32")
- assertError(t, RAMInBytes, " 32 ")
- assertError(t, RAMInBytes, "32m b")
- assertError(t, RAMInBytes, "32bm")
-}
-
-func assertEquals(t *testing.T, expected, actual interface{}) {
- if expected != actual {
- t.Errorf("Expected '%v' but got '%v'", expected, actual)
- }
-}
-
-// func that maps to the parse function signatures as testing abstraction
-type parseFn func(string) (int64, error)
-
-// Define 'String()' for pretty-print
-func (fn parseFn) String() string {
- fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
- return fnName[strings.LastIndex(fnName, ".")+1:]
-}
-
-func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {
- res, err := fn(arg)
- if err != nil || res != expected {
- t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err)
- }
-}
-
-func assertError(t *testing.T, fn parseFn, arg string) {
- res, err := fn(arg)
- if err == nil && res != -1 {
- t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res)
- }
-}
diff --git a/vendor/github.com/docker/go-units/ulimit.go b/vendor/github.com/docker/go-units/ulimit.go
deleted file mode 100644
index 5ac7fd8..0000000
--- a/vendor/github.com/docker/go-units/ulimit.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package units
-
-import (
- "fmt"
- "strconv"
- "strings"
-)
-
-// Ulimit is a human friendly version of Rlimit.
-type Ulimit struct {
- Name string
- Hard int64
- Soft int64
-}
-
-// Rlimit specifies the resource limits, such as max open files.
-type Rlimit struct {
- Type int `json:"type,omitempty"`
- Hard uint64 `json:"hard,omitempty"`
- Soft uint64 `json:"soft,omitempty"`
-}
-
-const (
- // magic numbers for making the syscall
- // some of these are defined in the syscall package, but not all.
- // Also since Windows client doesn't get access to the syscall package, need to
- // define these here
- rlimitAs = 9
- rlimitCore = 4
- rlimitCPU = 0
- rlimitData = 2
- rlimitFsize = 1
- rlimitLocks = 10
- rlimitMemlock = 8
- rlimitMsgqueue = 12
- rlimitNice = 13
- rlimitNofile = 7
- rlimitNproc = 6
- rlimitRss = 5
- rlimitRtprio = 14
- rlimitRttime = 15
- rlimitSigpending = 11
- rlimitStack = 3
-)
-
-var ulimitNameMapping = map[string]int{
- //"as": rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container.
- "core": rlimitCore,
- "cpu": rlimitCPU,
- "data": rlimitData,
- "fsize": rlimitFsize,
- "locks": rlimitLocks,
- "memlock": rlimitMemlock,
- "msgqueue": rlimitMsgqueue,
- "nice": rlimitNice,
- "nofile": rlimitNofile,
- "nproc": rlimitNproc,
- "rss": rlimitRss,
- "rtprio": rlimitRtprio,
- "rttime": rlimitRttime,
- "sigpending": rlimitSigpending,
- "stack": rlimitStack,
-}
-
-// ParseUlimit parses and returns a Ulimit from the specified string.
-func ParseUlimit(val string) (*Ulimit, error) {
- parts := strings.SplitN(val, "=", 2)
- if len(parts) != 2 {
- return nil, fmt.Errorf("invalid ulimit argument: %s", val)
- }
-
- if _, exists := ulimitNameMapping[parts[0]]; !exists {
- return nil, fmt.Errorf("invalid ulimit type: %s", parts[0])
- }
-
- var (
- soft int64
- hard = &soft // default to soft in case no hard was set
- temp int64
- err error
- )
- switch limitVals := strings.Split(parts[1], ":"); len(limitVals) {
- case 2:
- temp, err = strconv.ParseInt(limitVals[1], 10, 64)
- if err != nil {
- return nil, err
- }
- hard = &temp
- fallthrough
- case 1:
- soft, err = strconv.ParseInt(limitVals[0], 10, 64)
- if err != nil {
- return nil, err
- }
- default:
- return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1])
- }
-
- if soft > *hard {
- return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, *hard)
- }
-
- return &Ulimit{Name: parts[0], Soft: soft, Hard: *hard}, nil
-}
-
-// GetRlimit returns the RLimit corresponding to Ulimit.
-func (u *Ulimit) GetRlimit() (*Rlimit, error) {
- t, exists := ulimitNameMapping[u.Name]
- if !exists {
- return nil, fmt.Errorf("invalid ulimit name %s", u.Name)
- }
-
- return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil
-}
-
-func (u *Ulimit) String() string {
- return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard)
-}
diff --git a/vendor/github.com/docker/go-units/ulimit_test.go b/vendor/github.com/docker/go-units/ulimit_test.go
deleted file mode 100644
index 3e7f10f..0000000
--- a/vendor/github.com/docker/go-units/ulimit_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package units
-
-import (
- "fmt"
- "strconv"
- "testing"
-)
-
-func ExampleParseUlimit() {
- fmt.Println(ParseUlimit("nofile=512:1024"))
- fmt.Println(ParseUlimit("nofile=1024"))
- fmt.Println(ParseUlimit("cpu=2:4"))
- fmt.Println(ParseUlimit("cpu=6"))
-}
-
-func TestParseUlimitValid(t *testing.T) {
- u1 := &Ulimit{"nofile", 1024, 512}
- if u2, _ := ParseUlimit("nofile=512:1024"); *u1 != *u2 {
- t.Fatalf("expected %q, but got %q", u1, u2)
- }
-}
-
-func TestParseUlimitInvalidLimitType(t *testing.T) {
- if _, err := ParseUlimit("notarealtype=1024:1024"); err == nil {
- t.Fatalf("expected error on invalid ulimit type")
- }
-}
-
-func TestParseUlimitBadFormat(t *testing.T) {
- if _, err := ParseUlimit("nofile:1024:1024"); err == nil {
- t.Fatal("expected error on bad syntax")
- }
-
- if _, err := ParseUlimit("nofile"); err == nil {
- t.Fatal("expected error on bad syntax")
- }
-
- if _, err := ParseUlimit("nofile="); err == nil {
- t.Fatal("expected error on bad syntax")
- }
- if _, err := ParseUlimit("nofile=:"); err == nil {
- t.Fatal("expected error on bad syntax")
- }
- if _, err := ParseUlimit("nofile=:1024"); err == nil {
- t.Fatal("expected error on bad syntax")
- }
-}
-
-func TestParseUlimitHardLessThanSoft(t *testing.T) {
- if _, err := ParseUlimit("nofile=1024:1"); err == nil {
- t.Fatal("expected error on hard limit less than soft limit")
- }
-}
-
-func TestParseUlimitInvalidValueType(t *testing.T) {
- if _, err := ParseUlimit("nofile=asdf"); err == nil {
- t.Fatal("expected error on bad value type, but got no error")
- } else if _, ok := err.(*strconv.NumError); !ok {
- t.Fatalf("expected error on bad value type, but got `%s`", err)
- }
-
- if _, err := ParseUlimit("nofile=1024:asdf"); err == nil {
- t.Fatal("expected error on bad value type, but got no error")
- } else if _, ok := err.(*strconv.NumError); !ok {
- t.Fatalf("expected error on bad value type, but got `%s`", err)
- }
-}
-
-func TestUlimitStringOutput(t *testing.T) {
- u := &Ulimit{"nofile", 1024, 512}
- if s := u.String(); s != "nofile=512:1024" {
- t.Fatal("expected String to return nofile=512:1024, but got", s)
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/AUTHORS b/vendor/github.com/fsouza/go-dockerclient/AUTHORS
deleted file mode 100644
index 9fa7f59..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/AUTHORS
+++ /dev/null
@@ -1,140 +0,0 @@
-# This is the official list of go-dockerclient authors for copyright purposes.
-
-Abhishek Chanda
-Adam Bell-Hanssen
-Adrien Kohlbecker
-Aldrin Leal
-Andreas Jaekle
-Andrews Medina
-Andrey Sibiryov
-Andy Goldstein
-Antonio Murdaca
-Artem Sidorenko
-Ben Marini
-Ben McCann
-Ben Parees
-Benno van den Berg
-Bradley Cicenas
-Brendan Fosberry
-Brian Lalor
-Brian P. Hamachek
-Brian Palmer
-Bryan Boreham
-Burke Libbey
-Carlos Diaz-Padron
-Carson A
-Cesar Wong
-Cezar Sa Espinola
-Cheah Chu Yeow
-cheneydeng
-Chris Bednarski
-CMGS
-Colin Hebert
-Craig Jellick
-Dan Williams
-Daniel, Dao Quang Minh
-Daniel Garcia
-Daniel Hiltgen
-Darren Shepherd
-Dave Choi
-David Huie
-Dawn Chen
-Dinesh Subhraveti
-Drew Wells
-Ed
-Elias G. Schneevoigt
-Erez Horev
-Eric Anderson
-Ewout Prangsma
-Fabio Rehm
-Fatih Arslan
-Flavia Missi
-Francisco Souza
-Frank Groeneveld
-George Moura
-Grégoire Delattre
-Guillermo Álvarez Fernández
-Harry Zhang
-He Simei
-Ivan Mikushin
-James Bardin
-James Nugent
-Jari Kolehmainen
-Jason Wilder
-Jawher Moussa
-Jean-Baptiste Dalido
-Jeff Mitchell
-Jeffrey Hulten
-Jen Andre
-Jérôme Laurens
-Johan Euphrosine
-John Hughes
-Kamil Domanski
-Karan Misra
-Ken Herner
-Kim, Hirokuni
-Kostas Lekkas
-Kyle Allan
-Liron Levin
-Lior Yankovich
-Liu Peng
-Lorenz Leutgeb
-Lucas Clemente
-Lucas Weiblen
-Lyon Hill
-Mantas Matelis
-Mariusz Borsa
-Martin Sweeney
-Máximo Cuadros Ortiz
-Michael Schmatz
-Michal Fojtik
-Mike Dillon
-Mrunal Patel
-Nate Jones
-Nguyen Sy Thanh Son
-Nicholas Van Wiggeren
-Nick Ethier
-Omeid Matten
-Orivej Desh
-Paul Bellamy
-Paul Morie
-Paul Weil
-Peter Edge
-Peter Jihoon Kim
-Phil Lu
-Philippe Lafoucrière
-Rafe Colton
-Raphaël Pinson
-Rob Miller
-Robbert Klarenbeek
-Robert Williamson
-Roman Khlystik
-Salvador Gironès
-Sam Rijs
-Sami Wagiaalla
-Samuel Archambault
-Samuel Karp
-Seth Jennings
-Silas Sewell
-Simon Eskildsen
-Simon Menke
-Skolos
-Soulou
-Sridhar Ratnakumar
-Summer Mousa
-Sunjin Lee
-Tarsis Azevedo
-Tim Schindler
-Timothy St. Clair
-Tobi Knaup
-Tom Wilkie
-Tonic
-ttyh061
-Victor Marmol
-Vincenzo Prignano
-Vlad Alexandru Ionescu
-Wiliam Souza
-Xh4n3
-Ye Yin
-Yu, Zou
-Yuriy Bogdanov
diff --git a/vendor/github.com/fsouza/go-dockerclient/DOCKER-LICENSE b/vendor/github.com/fsouza/go-dockerclient/DOCKER-LICENSE
deleted file mode 100644
index 7066344..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/DOCKER-LICENSE
+++ /dev/null
@@ -1,6 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
-You can find the Docker license at the following link:
-https://raw.githubusercontent.com/docker/docker/master/LICENSE
diff --git a/vendor/github.com/fsouza/go-dockerclient/LICENSE b/vendor/github.com/fsouza/go-dockerclient/LICENSE
deleted file mode 100644
index b1cdd4c..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-Copyright (c) 2016, go-dockerclient 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.
-
-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 HOLDER 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.
diff --git a/vendor/github.com/fsouza/go-dockerclient/Makefile b/vendor/github.com/fsouza/go-dockerclient/Makefile
deleted file mode 100644
index 8c17390..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-.PHONY: \
- all \
- lint \
- vet \
- fmt \
- fmtcheck \
- pretest \
- test \
- integration \
- clean
-
-all: test
-
-lint:
- @ go get -v github.com/golang/lint/golint
- @ export output="$$(golint . | grep -v 'type name will be used as docker.DockerInfo')"; \
- [ -n "$${output}" ] && echo "$${output}" && export status=1; \
- exit $${status:-0}
-
-vet:
- go vet ./...
-
-fmt:
- gofmt -s -w .
-
-fmtcheck:
- @ export output="$$(gofmt -s -d .)"; \
- [ -n "$${output}" ] && echo "$${output}" && export status=1; \
- exit $${status:-0}
-testdeps:
- go get -d -t ./...
-
-pretest: testdeps lint vet fmtcheck
-
-gotest:
- go test $(GO_TEST_FLAGS) ./...
-
-test: pretest gotest
-
-integration:
- go test -tags docker_integration -run TestIntegration -v
-
-clean:
- go clean ./...
diff --git a/vendor/github.com/fsouza/go-dockerclient/README.markdown b/vendor/github.com/fsouza/go-dockerclient/README.markdown
deleted file mode 100644
index f638ec3..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/README.markdown
+++ /dev/null
@@ -1,99 +0,0 @@
-# go-dockerclient
-
-[](https://travis-ci.org/fsouza/go-dockerclient)
-[](https://godoc.org/github.com/fsouza/go-dockerclient)
-
-This package presents a client for the Docker remote API. It also provides
-support for the extensions in the [Swarm API](https://docs.docker.com/swarm/swarm-api/).
-It currently supports the Docker API up to version 1.23.
-
-This package also provides support for docker's network API, which is a simple
-passthrough to the libnetwork remote API. Note that docker's network API is
-only available in docker 1.8 and above, and only enabled in docker if
-DOCKER_EXPERIMENTAL is defined during the docker build process.
-
-For more details, check the [remote API documentation](http://docs.docker.com/engine/reference/api/docker_remote_api/).
-
-## Example
-
-```go
-package main
-
-import (
- "fmt"
-
- "github.com/fsouza/go-dockerclient"
-)
-
-func main() {
- endpoint := "unix:///var/run/docker.sock"
- client, _ := docker.NewClient(endpoint)
- imgs, _ := client.ListImages(docker.ListImagesOptions{All: false})
- for _, img := range imgs {
- fmt.Println("ID: ", img.ID)
- fmt.Println("RepoTags: ", img.RepoTags)
- fmt.Println("Created: ", img.Created)
- fmt.Println("Size: ", img.Size)
- fmt.Println("VirtualSize: ", img.VirtualSize)
- fmt.Println("ParentId: ", img.ParentID)
- }
-}
-```
-
-## Using with TLS
-
-In order to instantiate the client for a TLS-enabled daemon, you should use NewTLSClient, passing the endpoint and path for key and certificates as parameters.
-
-```go
-package main
-
-import (
- "fmt"
-
- "github.com/fsouza/go-dockerclient"
-)
-
-func main() {
- endpoint := "tcp://[ip]:[port]"
- path := os.Getenv("DOCKER_CERT_PATH")
- ca := fmt.Sprintf("%s/ca.pem", path)
- cert := fmt.Sprintf("%s/cert.pem", path)
- key := fmt.Sprintf("%s/key.pem", path)
- client, _ := docker.NewTLSClient(endpoint, cert, key, ca)
- // use client
-}
-```
-
-If using [docker-machine](https://docs.docker.com/machine/), or another application that exports environment variables
-`DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH`, you can use NewClientFromEnv.
-
-
-```go
-package main
-
-import (
- "fmt"
-
- "github.com/fsouza/go-dockerclient"
-)
-
-func main() {
- client, _ := docker.NewClientFromEnv()
- // use client
-}
-```
-
-See the documentation for more details.
-
-## Developing
-
-All development commands can be seen in the [Makefile](Makefile).
-
-Commited code must pass:
-
-* [golint](https://github.com/golang/lint)
-* [go vet](https://godoc.org/golang.org/x/tools/cmd/vet)
-* [gofmt](https://golang.org/cmd/gofmt)
-* [go test](https://golang.org/cmd/go/#hdr-Test_packages)
-
-Running `make test` will check all of these. If your editor does not automatically call gofmt, `make fmt` will format all go files in this repository.
diff --git a/vendor/github.com/fsouza/go-dockerclient/auth.go b/vendor/github.com/fsouza/go-dockerclient/auth.go
deleted file mode 100644
index 95596d7..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/auth.go
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path"
- "strings"
-)
-
-// ErrCannotParseDockercfg is the error returned by NewAuthConfigurations when the dockercfg cannot be parsed.
-var ErrCannotParseDockercfg = errors.New("Failed to read authentication from dockercfg")
-
-// AuthConfiguration represents authentication options to use in the PushImage
-// method. It represents the authentication in the Docker index server.
-type AuthConfiguration struct {
- Username string `json:"username,omitempty"`
- Password string `json:"password,omitempty"`
- Email string `json:"email,omitempty"`
- ServerAddress string `json:"serveraddress,omitempty"`
-}
-
-// AuthConfigurations represents authentication options to use for the
-// PushImage method accommodating the new X-Registry-Config header
-type AuthConfigurations struct {
- Configs map[string]AuthConfiguration `json:"configs"`
-}
-
-// AuthConfigurations119 is used to serialize a set of AuthConfigurations
-// for Docker API >= 1.19.
-type AuthConfigurations119 map[string]AuthConfiguration
-
-// dockerConfig represents a registry authentation configuration from the
-// .dockercfg file.
-type dockerConfig struct {
- Auth string `json:"auth"`
- Email string `json:"email"`
-}
-
-// NewAuthConfigurationsFromDockerCfg returns AuthConfigurations from the
-// ~/.dockercfg file.
-func NewAuthConfigurationsFromDockerCfg() (*AuthConfigurations, error) {
- var r io.Reader
- var err error
- p := path.Join(os.Getenv("HOME"), ".docker", "config.json")
- r, err = os.Open(p)
- if err != nil {
- p := path.Join(os.Getenv("HOME"), ".dockercfg")
- r, err = os.Open(p)
- if err != nil {
- return nil, err
- }
- }
- return NewAuthConfigurations(r)
-}
-
-// NewAuthConfigurations returns AuthConfigurations from a JSON encoded string in the
-// same format as the .dockercfg file.
-func NewAuthConfigurations(r io.Reader) (*AuthConfigurations, error) {
- var auth *AuthConfigurations
- confs, err := parseDockerConfig(r)
- if err != nil {
- return nil, err
- }
- auth, err = authConfigs(confs)
- if err != nil {
- return nil, err
- }
- return auth, nil
-}
-
-func parseDockerConfig(r io.Reader) (map[string]dockerConfig, error) {
- buf := new(bytes.Buffer)
- buf.ReadFrom(r)
- byteData := buf.Bytes()
-
- confsWrapper := struct {
- Auths map[string]dockerConfig `json:"auths"`
- }{}
- if err := json.Unmarshal(byteData, &confsWrapper); err == nil {
- if len(confsWrapper.Auths) > 0 {
- return confsWrapper.Auths, nil
- }
- }
-
- var confs map[string]dockerConfig
- if err := json.Unmarshal(byteData, &confs); err != nil {
- return nil, err
- }
- return confs, nil
-}
-
-// authConfigs converts a dockerConfigs map to a AuthConfigurations object.
-func authConfigs(confs map[string]dockerConfig) (*AuthConfigurations, error) {
- c := &AuthConfigurations{
- Configs: make(map[string]AuthConfiguration),
- }
- for reg, conf := range confs {
- data, err := base64.StdEncoding.DecodeString(conf.Auth)
- if err != nil {
- return nil, err
- }
- userpass := strings.SplitN(string(data), ":", 2)
- if len(userpass) != 2 {
- return nil, ErrCannotParseDockercfg
- }
- c.Configs[reg] = AuthConfiguration{
- Email: conf.Email,
- Username: userpass[0],
- Password: userpass[1],
- ServerAddress: reg,
- }
- }
- return c, nil
-}
-
-// AuthStatus returns the authentication status for Docker API versions >= 1.23.
-type AuthStatus struct {
- Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
- IdentityToken string `json:"IdentityToken,omitempty" yaml:"IdentityToken,omitempty"`
-}
-
-// AuthCheck validates the given credentials. It returns nil if successful.
-//
-// For Docker API versions >= 1.23, the AuthStatus struct will be populated, otherwise it will be empty.`
-//
-// See https://goo.gl/6nsZkH for more details.
-func (c *Client) AuthCheck(conf *AuthConfiguration) (AuthStatus, error) {
- var authStatus AuthStatus
- if conf == nil {
- return authStatus, fmt.Errorf("conf is nil")
- }
- resp, err := c.do("POST", "/auth", doOptions{data: conf})
- if err != nil {
- return authStatus, err
- }
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return authStatus, err
- }
- if len(data) == 0 {
- return authStatus, nil
- }
- if err := json.Unmarshal(data, &authStatus); err != nil {
- return authStatus, err
- }
- return authStatus, nil
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/auth_test.go b/vendor/github.com/fsouza/go-dockerclient/auth_test.go
deleted file mode 100644
index 51951ab..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/auth_test.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "encoding/base64"
- "fmt"
- "net/http"
- "strings"
- "testing"
-)
-
-func TestAuthLegacyConfig(t *testing.T) {
- auth := base64.StdEncoding.EncodeToString([]byte("user:pa:ss"))
- read := strings.NewReader(fmt.Sprintf(`{"docker.io":{"auth":"%s","email":"user@example.com"}}`, auth))
- ac, err := NewAuthConfigurations(read)
- if err != nil {
- t.Error(err)
- }
- c, ok := ac.Configs["docker.io"]
- if !ok {
- t.Error("NewAuthConfigurations: Expected Configs to contain docker.io")
- }
- if got, want := c.Email, "user@example.com"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Email: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.Username, "user"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Username: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.Password, "pa:ss"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Password: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.ServerAddress, "docker.io"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].ServerAddress: wrong result. Want %q. Got %q`, want, got)
- }
-}
-
-func TestAuthBadConfig(t *testing.T) {
- auth := base64.StdEncoding.EncodeToString([]byte("userpass"))
- read := strings.NewReader(fmt.Sprintf(`{"docker.io":{"auth":"%s","email":"user@example.com"}}`, auth))
- ac, err := NewAuthConfigurations(read)
- if err != ErrCannotParseDockercfg {
- t.Errorf("Incorrect error returned %v\n", err)
- }
- if ac != nil {
- t.Errorf("Invalid auth configuration returned, should be nil %v\n", ac)
- }
-}
-
-func TestAuthAndOtherFields(t *testing.T) {
- auth := base64.StdEncoding.EncodeToString([]byte("user:pass"))
- read := strings.NewReader(fmt.Sprintf(`{
- "auths":{"docker.io":{"auth":"%s","email":"user@example.com"}},
- "detachKeys": "ctrl-e,e",
- "HttpHeaders": { "MyHeader": "MyValue" }}`, auth))
-
- ac, err := NewAuthConfigurations(read)
- if err != nil {
- t.Error(err)
- }
- c, ok := ac.Configs["docker.io"]
- if !ok {
- t.Error("NewAuthConfigurations: Expected Configs to contain docker.io")
- }
- if got, want := c.Email, "user@example.com"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Email: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.Username, "user"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Username: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.Password, "pass"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Password: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.ServerAddress, "docker.io"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].ServerAddress: wrong result. Want %q. Got %q`, want, got)
- }
-}
-func TestAuthConfig(t *testing.T) {
- auth := base64.StdEncoding.EncodeToString([]byte("user:pass"))
- read := strings.NewReader(fmt.Sprintf(`{"auths":{"docker.io":{"auth":"%s","email":"user@example.com"}}}`, auth))
- ac, err := NewAuthConfigurations(read)
- if err != nil {
- t.Error(err)
- }
- c, ok := ac.Configs["docker.io"]
- if !ok {
- t.Error("NewAuthConfigurations: Expected Configs to contain docker.io")
- }
- if got, want := c.Email, "user@example.com"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Email: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.Username, "user"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Username: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.Password, "pass"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].Password: wrong result. Want %q. Got %q`, want, got)
- }
- if got, want := c.ServerAddress, "docker.io"; got != want {
- t.Errorf(`AuthConfigurations.Configs["docker.io"].ServerAddress: wrong result. Want %q. Got %q`, want, got)
- }
-}
-
-func TestAuthCheck(t *testing.T) {
- fakeRT := &FakeRoundTripper{status: http.StatusOK}
- client := newTestClient(fakeRT)
- if _, err := client.AuthCheck(nil); err == nil {
- t.Fatalf("expected error on nil auth config")
- }
- // test good auth
- if _, err := client.AuthCheck(&AuthConfiguration{}); err != nil {
- t.Fatal(err)
- }
- *fakeRT = FakeRoundTripper{status: http.StatusUnauthorized}
- if _, err := client.AuthCheck(&AuthConfiguration{}); err == nil {
- t.Fatal("expected failure from unauthorized auth")
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/build_test.go b/vendor/github.com/fsouza/go-dockerclient/build_test.go
deleted file mode 100644
index 3a0a52a..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/build_test.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package docker
-
-import (
- "bytes"
- "io"
- "io/ioutil"
- "net/http"
- "os"
- "reflect"
- "testing"
-
- "github.com/docker/docker/pkg/archive"
-)
-
-func TestBuildImageMultipleContextsError(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Name: "testImage",
- NoCache: true,
- SuppressOutput: true,
- RmTmpContainer: true,
- ForceRmTmpContainer: true,
- InputStream: &buf,
- OutputStream: &buf,
- ContextDir: "testing/data",
- }
- err := client.BuildImage(opts)
- if err != ErrMultipleContexts {
- t.Errorf("BuildImage: providing both InputStream and ContextDir should produce an error")
- }
-}
-
-func TestBuildImageContextDirDockerignoreParsing(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
-
- if err := os.Symlink("doesnotexist", "testing/data/symlink"); err != nil {
- t.Errorf("error creating symlink on demand: %s", err)
- }
- defer func() {
- if err := os.Remove("testing/data/symlink"); err != nil {
- t.Errorf("error removing symlink on demand: %s", err)
- }
- }()
-
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Name: "testImage",
- NoCache: true,
- SuppressOutput: true,
- RmTmpContainer: true,
- ForceRmTmpContainer: true,
- OutputStream: &buf,
- ContextDir: "testing/data",
- }
- err := client.BuildImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- reqBody := fakeRT.requests[0].Body
- tmpdir, err := unpackBodyTarball(reqBody)
- if err != nil {
- t.Fatal(err)
- }
-
- defer func() {
- if err := os.RemoveAll(tmpdir); err != nil {
- t.Fatal(err)
- }
- }()
-
- files, err := ioutil.ReadDir(tmpdir)
- if err != nil {
- t.Fatal(err)
- }
-
- foundFiles := []string{}
- for _, file := range files {
- foundFiles = append(foundFiles, file.Name())
- }
-
- expectedFiles := []string{
- ".dockerignore",
- "Dockerfile",
- "barfile",
- "ca.pem",
- "cert.pem",
- "key.pem",
- "server.pem",
- "serverkey.pem",
- "symlink",
- }
-
- if !reflect.DeepEqual(expectedFiles, foundFiles) {
- t.Errorf(
- "BuildImage: incorrect files sent in tarball to docker server\nexpected %+v, found %+v",
- expectedFiles, foundFiles,
- )
- }
-}
-
-func TestBuildImageSendXRegistryConfig(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Name: "testImage",
- NoCache: true,
- SuppressOutput: true,
- RmTmpContainer: true,
- ForceRmTmpContainer: true,
- OutputStream: &buf,
- ContextDir: "testing/data",
- AuthConfigs: AuthConfigurations{
- Configs: map[string]AuthConfiguration{
- "quay.io": {
- Username: "foo",
- Password: "bar",
- Email: "baz",
- ServerAddress: "quay.io",
- },
- },
- },
- }
-
- encodedConfig := "eyJjb25maWdzIjp7InF1YXkuaW8iOnsidXNlcm5hbWUiOiJmb28iLCJwYXNzd29yZCI6ImJhciIsImVtYWlsIjoiYmF6Iiwic2VydmVyYWRkcmVzcyI6InF1YXkuaW8ifX19Cg=="
-
- if err := client.BuildImage(opts); err != nil {
- t.Fatal(err)
- }
-
- xRegistryConfig := fakeRT.requests[0].Header["X-Registry-Config"][0]
- if xRegistryConfig != encodedConfig {
- t.Errorf(
- "BuildImage: X-Registry-Config not set currectly: expected %q, got %q",
- encodedConfig,
- xRegistryConfig,
- )
- }
-}
-
-func unpackBodyTarball(req io.ReadCloser) (tmpdir string, err error) {
- tmpdir, err = ioutil.TempDir("", "go-dockerclient-test")
- if err != nil {
- return
- }
- err = archive.Untar(req, tmpdir, &archive.TarOptions{
- Compression: archive.Uncompressed,
- NoLchown: true,
- })
- return
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/cancelable.go b/vendor/github.com/fsouza/go-dockerclient/cancelable.go
deleted file mode 100644
index 375fbd1..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/cancelable.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2016 go-dockerclient 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 docker
-
-import "net/http"
-
-func cancelable(client *http.Client, req *http.Request) func() {
- ch := make(chan struct{})
- req.Cancel = ch
- return func() {
- close(ch)
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/cancelable_go14.go b/vendor/github.com/fsouza/go-dockerclient/cancelable_go14.go
deleted file mode 100644
index 3c20398..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/cancelable_go14.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2016 go-dockerclient 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 docker
-
-import "net/http"
-
-func cancelable(client *http.Client, req *http.Request) func() {
- return func() {
- if rc, ok := client.Transport.(interface {
- CancelRequest(*http.Request)
- }); ok {
- rc.CancelRequest(req)
- }
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/change.go b/vendor/github.com/fsouza/go-dockerclient/change.go
deleted file mode 100644
index d133594..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/change.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 go-dockerclient 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 docker
-
-import "fmt"
-
-// ChangeType is a type for constants indicating the type of change
-// in a container
-type ChangeType int
-
-const (
- // ChangeModify is the ChangeType for container modifications
- ChangeModify ChangeType = iota
-
- // ChangeAdd is the ChangeType for additions to a container
- ChangeAdd
-
- // ChangeDelete is the ChangeType for deletions from a container
- ChangeDelete
-)
-
-// Change represents a change in a container.
-//
-// See https://goo.gl/9GsTIF for more details.
-type Change struct {
- Path string
- Kind ChangeType
-}
-
-func (change *Change) String() string {
- var kind string
- switch change.Kind {
- case ChangeModify:
- kind = "C"
- case ChangeAdd:
- kind = "A"
- case ChangeDelete:
- kind = "D"
- }
- return fmt.Sprintf("%s %s", kind, change.Path)
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/change_test.go b/vendor/github.com/fsouza/go-dockerclient/change_test.go
deleted file mode 100644
index 9418b18..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/change_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 go-dockerclient 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 docker
-
-import "testing"
-
-func TestChangeString(t *testing.T) {
- var tests = []struct {
- change Change
- expected string
- }{
- {Change{"/etc/passwd", ChangeModify}, "C /etc/passwd"},
- {Change{"/etc/passwd", ChangeAdd}, "A /etc/passwd"},
- {Change{"/etc/passwd", ChangeDelete}, "D /etc/passwd"},
- {Change{"/etc/passwd", 33}, " /etc/passwd"},
- }
- for _, tt := range tests {
- if got := tt.change.String(); got != tt.expected {
- t.Errorf("Change.String(): want %q. Got %q.", tt.expected, got)
- }
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/client.go b/vendor/github.com/fsouza/go-dockerclient/client.go
deleted file mode 100644
index 3941157..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/client.go
+++ /dev/null
@@ -1,993 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker provides a client for the Docker remote API.
-//
-// See https://goo.gl/G3plxW for more details on the remote API.
-package docker
-
-import (
- "bufio"
- "bytes"
- "crypto/tls"
- "crypto/x509"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "net/http/httputil"
- "net/url"
- "os"
- "path/filepath"
- "reflect"
- "runtime"
- "strconv"
- "strings"
- "sync/atomic"
- "time"
-
- "github.com/docker/docker/opts"
- "github.com/docker/docker/pkg/homedir"
- "github.com/docker/docker/pkg/stdcopy"
- "github.com/hashicorp/go-cleanhttp"
-)
-
-const userAgent = "go-dockerclient"
-
-var (
- // ErrInvalidEndpoint is returned when the endpoint is not a valid HTTP URL.
- ErrInvalidEndpoint = errors.New("invalid endpoint")
-
- // ErrConnectionRefused is returned when the client cannot connect to the given endpoint.
- ErrConnectionRefused = errors.New("cannot connect to Docker endpoint")
-
- // ErrInactivityTimeout is returned when a streamable call has been inactive for some time.
- ErrInactivityTimeout = errors.New("inactivity time exceeded timeout")
-
- apiVersion112, _ = NewAPIVersion("1.12")
-
- apiVersion119, _ = NewAPIVersion("1.19")
-)
-
-// APIVersion is an internal representation of a version of the Remote API.
-type APIVersion []int
-
-// NewAPIVersion returns an instance of APIVersion for the given string.
-//
-// The given string must be in the form .., where ,
-// and are integer numbers.
-func NewAPIVersion(input string) (APIVersion, error) {
- if !strings.Contains(input, ".") {
- return nil, fmt.Errorf("Unable to parse version %q", input)
- }
- raw := strings.Split(input, "-")
- arr := strings.Split(raw[0], ".")
- ret := make(APIVersion, len(arr))
- var err error
- for i, val := range arr {
- ret[i], err = strconv.Atoi(val)
- if err != nil {
- return nil, fmt.Errorf("Unable to parse version %q: %q is not an integer", input, val)
- }
- }
- return ret, nil
-}
-
-func (version APIVersion) String() string {
- var str string
- for i, val := range version {
- str += strconv.Itoa(val)
- if i < len(version)-1 {
- str += "."
- }
- }
- return str
-}
-
-// LessThan is a function for comparing APIVersion structs
-func (version APIVersion) LessThan(other APIVersion) bool {
- return version.compare(other) < 0
-}
-
-// LessThanOrEqualTo is a function for comparing APIVersion structs
-func (version APIVersion) LessThanOrEqualTo(other APIVersion) bool {
- return version.compare(other) <= 0
-}
-
-// GreaterThan is a function for comparing APIVersion structs
-func (version APIVersion) GreaterThan(other APIVersion) bool {
- return version.compare(other) > 0
-}
-
-// GreaterThanOrEqualTo is a function for comparing APIVersion structs
-func (version APIVersion) GreaterThanOrEqualTo(other APIVersion) bool {
- return version.compare(other) >= 0
-}
-
-func (version APIVersion) compare(other APIVersion) int {
- for i, v := range version {
- if i <= len(other)-1 {
- otherVersion := other[i]
-
- if v < otherVersion {
- return -1
- } else if v > otherVersion {
- return 1
- }
- }
- }
- if len(version) > len(other) {
- return 1
- }
- if len(version) < len(other) {
- return -1
- }
- return 0
-}
-
-// Client is the basic type of this package. It provides methods for
-// interaction with the API.
-type Client struct {
- SkipServerVersionCheck bool
- HTTPClient *http.Client
- TLSConfig *tls.Config
- Dialer *net.Dialer
-
- endpoint string
- endpointURL *url.URL
- eventMonitor *eventMonitoringState
- requestedAPIVersion APIVersion
- serverAPIVersion APIVersion
- expectedAPIVersion APIVersion
- unixHTTPClient *http.Client
-}
-
-// NewClient returns a Client instance ready for communication with the given
-// server endpoint. It will use the latest remote API version available in the
-// server.
-func NewClient(endpoint string) (*Client, error) {
- client, err := NewVersionedClient(endpoint, "")
- if err != nil {
- return nil, err
- }
- client.SkipServerVersionCheck = true
- return client, nil
-}
-
-// NewTLSClient returns a Client instance ready for TLS communications with the givens
-// server endpoint, key and certificates . It will use the latest remote API version
-// available in the server.
-func NewTLSClient(endpoint string, cert, key, ca string) (*Client, error) {
- client, err := NewVersionedTLSClient(endpoint, cert, key, ca, "")
- if err != nil {
- return nil, err
- }
- client.SkipServerVersionCheck = true
- return client, nil
-}
-
-// NewTLSClientFromBytes returns a Client instance ready for TLS communications with the givens
-// server endpoint, key and certificates (passed inline to the function as opposed to being
-// read from a local file). It will use the latest remote API version available in the server.
-func NewTLSClientFromBytes(endpoint string, certPEMBlock, keyPEMBlock, caPEMCert []byte) (*Client, error) {
- client, err := NewVersionedTLSClientFromBytes(endpoint, certPEMBlock, keyPEMBlock, caPEMCert, "")
- if err != nil {
- return nil, err
- }
- client.SkipServerVersionCheck = true
- return client, nil
-}
-
-// NewVersionedClient returns a Client instance ready for communication with
-// the given server endpoint, using a specific remote API version.
-func NewVersionedClient(endpoint string, apiVersionString string) (*Client, error) {
- u, err := parseEndpoint(endpoint, false)
- if err != nil {
- return nil, err
- }
- var requestedAPIVersion APIVersion
- if strings.Contains(apiVersionString, ".") {
- requestedAPIVersion, err = NewAPIVersion(apiVersionString)
- if err != nil {
- return nil, err
- }
- }
- return &Client{
- HTTPClient: cleanhttp.DefaultClient(),
- Dialer: &net.Dialer{},
- endpoint: endpoint,
- endpointURL: u,
- eventMonitor: new(eventMonitoringState),
- requestedAPIVersion: requestedAPIVersion,
- }, nil
-}
-
-// NewVersionnedTLSClient has been DEPRECATED, please use NewVersionedTLSClient.
-func NewVersionnedTLSClient(endpoint string, cert, key, ca, apiVersionString string) (*Client, error) {
- return NewVersionedTLSClient(endpoint, cert, key, ca, apiVersionString)
-}
-
-// NewVersionedTLSClient returns a Client instance ready for TLS communications with the givens
-// server endpoint, key and certificates, using a specific remote API version.
-func NewVersionedTLSClient(endpoint string, cert, key, ca, apiVersionString string) (*Client, error) {
- certPEMBlock, err := ioutil.ReadFile(cert)
- if err != nil {
- return nil, err
- }
- keyPEMBlock, err := ioutil.ReadFile(key)
- if err != nil {
- return nil, err
- }
- caPEMCert, err := ioutil.ReadFile(ca)
- if err != nil {
- return nil, err
- }
- return NewVersionedTLSClientFromBytes(endpoint, certPEMBlock, keyPEMBlock, caPEMCert, apiVersionString)
-}
-
-// NewClientFromEnv returns a Client instance ready for communication created from
-// Docker's default logic for the environment variables DOCKER_HOST, DOCKER_TLS_VERIFY, and DOCKER_CERT_PATH.
-//
-// See https://github.com/docker/docker/blob/1f963af697e8df3a78217f6fdbf67b8123a7db94/docker/docker.go#L68.
-// See https://github.com/docker/compose/blob/81707ef1ad94403789166d2fe042c8a718a4c748/compose/cli/docker_client.py#L7.
-func NewClientFromEnv() (*Client, error) {
- client, err := NewVersionedClientFromEnv("")
- if err != nil {
- return nil, err
- }
- client.SkipServerVersionCheck = true
- return client, nil
-}
-
-// NewVersionedClientFromEnv returns a Client instance ready for TLS communications created from
-// Docker's default logic for the environment variables DOCKER_HOST, DOCKER_TLS_VERIFY, and DOCKER_CERT_PATH,
-// and using a specific remote API version.
-//
-// See https://github.com/docker/docker/blob/1f963af697e8df3a78217f6fdbf67b8123a7db94/docker/docker.go#L68.
-// See https://github.com/docker/compose/blob/81707ef1ad94403789166d2fe042c8a718a4c748/compose/cli/docker_client.py#L7.
-func NewVersionedClientFromEnv(apiVersionString string) (*Client, error) {
- dockerEnv, err := getDockerEnv()
- if err != nil {
- return nil, err
- }
- dockerHost := dockerEnv.dockerHost
- if dockerEnv.dockerTLSVerify {
- parts := strings.SplitN(dockerEnv.dockerHost, "://", 2)
- if len(parts) != 2 {
- return nil, fmt.Errorf("could not split %s into two parts by ://", dockerHost)
- }
- cert := filepath.Join(dockerEnv.dockerCertPath, "cert.pem")
- key := filepath.Join(dockerEnv.dockerCertPath, "key.pem")
- ca := filepath.Join(dockerEnv.dockerCertPath, "ca.pem")
- return NewVersionedTLSClient(dockerEnv.dockerHost, cert, key, ca, apiVersionString)
- }
- return NewVersionedClient(dockerEnv.dockerHost, apiVersionString)
-}
-
-// NewVersionedTLSClientFromBytes returns a Client instance ready for TLS communications with the givens
-// server endpoint, key and certificates (passed inline to the function as opposed to being
-// read from a local file), using a specific remote API version.
-func NewVersionedTLSClientFromBytes(endpoint string, certPEMBlock, keyPEMBlock, caPEMCert []byte, apiVersionString string) (*Client, error) {
- u, err := parseEndpoint(endpoint, true)
- if err != nil {
- return nil, err
- }
- var requestedAPIVersion APIVersion
- if strings.Contains(apiVersionString, ".") {
- requestedAPIVersion, err = NewAPIVersion(apiVersionString)
- if err != nil {
- return nil, err
- }
- }
- if certPEMBlock == nil || keyPEMBlock == nil {
- return nil, errors.New("Both cert and key are required")
- }
- tlsCert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock)
- if err != nil {
- return nil, err
- }
- tlsConfig := &tls.Config{Certificates: []tls.Certificate{tlsCert}}
- if caPEMCert == nil {
- tlsConfig.InsecureSkipVerify = true
- } else {
- caPool := x509.NewCertPool()
- if !caPool.AppendCertsFromPEM(caPEMCert) {
- return nil, errors.New("Could not add RootCA pem")
- }
- tlsConfig.RootCAs = caPool
- }
- tr := cleanhttp.DefaultTransport()
- tr.TLSClientConfig = tlsConfig
- if err != nil {
- return nil, err
- }
- return &Client{
- HTTPClient: &http.Client{Transport: tr},
- TLSConfig: tlsConfig,
- Dialer: &net.Dialer{},
- endpoint: endpoint,
- endpointURL: u,
- eventMonitor: new(eventMonitoringState),
- requestedAPIVersion: requestedAPIVersion,
- }, nil
-}
-
-func (c *Client) checkAPIVersion() error {
- serverAPIVersionString, err := c.getServerAPIVersionString()
- if err != nil {
- return err
- }
- c.serverAPIVersion, err = NewAPIVersion(serverAPIVersionString)
- if err != nil {
- return err
- }
- if c.requestedAPIVersion == nil {
- c.expectedAPIVersion = c.serverAPIVersion
- } else {
- c.expectedAPIVersion = c.requestedAPIVersion
- }
- return nil
-}
-
-// Endpoint returns the current endpoint. It's useful for getting the endpoint
-// when using functions that get this data from the environment (like
-// NewClientFromEnv.
-func (c *Client) Endpoint() string {
- return c.endpoint
-}
-
-// Ping pings the docker server
-//
-// See https://goo.gl/kQCfJj for more details.
-func (c *Client) Ping() error {
- path := "/_ping"
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- return err
- }
- if resp.StatusCode != http.StatusOK {
- return newError(resp)
- }
- resp.Body.Close()
- return nil
-}
-
-func (c *Client) getServerAPIVersionString() (version string, err error) {
- resp, err := c.do("GET", "/version", doOptions{})
- if err != nil {
- return "", err
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- return "", fmt.Errorf("Received unexpected status %d while trying to retrieve the server version", resp.StatusCode)
- }
- var versionResponse map[string]interface{}
- if err := json.NewDecoder(resp.Body).Decode(&versionResponse); err != nil {
- return "", err
- }
- if version, ok := (versionResponse["ApiVersion"]).(string); ok {
- return version, nil
- }
- return "", nil
-}
-
-type doOptions struct {
- data interface{}
- forceJSON bool
- headers map[string]string
-}
-
-func (c *Client) do(method, path string, doOptions doOptions) (*http.Response, error) {
- var params io.Reader
- if doOptions.data != nil || doOptions.forceJSON {
- buf, err := json.Marshal(doOptions.data)
- if err != nil {
- return nil, err
- }
- params = bytes.NewBuffer(buf)
- }
- if path != "/version" && !c.SkipServerVersionCheck && c.expectedAPIVersion == nil {
- err := c.checkAPIVersion()
- if err != nil {
- return nil, err
- }
- }
- httpClient := c.HTTPClient
- protocol := c.endpointURL.Scheme
- var u string
- if protocol == "unix" {
- httpClient = c.unixClient()
- u = c.getFakeUnixURL(path)
- } else {
- u = c.getURL(path)
- }
- req, err := http.NewRequest(method, u, params)
- if err != nil {
- return nil, err
- }
- req.Header.Set("User-Agent", userAgent)
- if doOptions.data != nil {
- req.Header.Set("Content-Type", "application/json")
- } else if method == "POST" {
- req.Header.Set("Content-Type", "plain/text")
- }
-
- for k, v := range doOptions.headers {
- req.Header.Set(k, v)
- }
- resp, err := httpClient.Do(req)
- if err != nil {
- if strings.Contains(err.Error(), "connection refused") {
- return nil, ErrConnectionRefused
- }
- return nil, err
- }
- if resp.StatusCode < 200 || resp.StatusCode >= 400 {
- return nil, newError(resp)
- }
- return resp, nil
-}
-
-type streamOptions struct {
- setRawTerminal bool
- rawJSONStream bool
- useJSONDecoder bool
- headers map[string]string
- in io.Reader
- stdout io.Writer
- stderr io.Writer
- // timeout is the initial connection timeout
- timeout time.Duration
- // Timeout with no data is received, it's reset every time new data
- // arrives
- inactivityTimeout time.Duration
-}
-
-func (c *Client) stream(method, path string, streamOptions streamOptions) error {
- if (method == "POST" || method == "PUT") && streamOptions.in == nil {
- streamOptions.in = bytes.NewReader(nil)
- }
- if path != "/version" && !c.SkipServerVersionCheck && c.expectedAPIVersion == nil {
- err := c.checkAPIVersion()
- if err != nil {
- return err
- }
- }
- req, err := http.NewRequest(method, c.getURL(path), streamOptions.in)
- if err != nil {
- return err
- }
- req.Header.Set("User-Agent", userAgent)
- if method == "POST" {
- req.Header.Set("Content-Type", "plain/text")
- }
- for key, val := range streamOptions.headers {
- req.Header.Set(key, val)
- }
- var resp *http.Response
- protocol := c.endpointURL.Scheme
- address := c.endpointURL.Path
- if streamOptions.stdout == nil {
- streamOptions.stdout = ioutil.Discard
- }
- if streamOptions.stderr == nil {
- streamOptions.stderr = ioutil.Discard
- }
- cancelRequest := cancelable(c.HTTPClient, req)
- if protocol == "unix" {
- dial, err := c.Dialer.Dial(protocol, address)
- if err != nil {
- return err
- }
- cancelRequest = func() { dial.Close() }
- defer dial.Close()
- breader := bufio.NewReader(dial)
- err = req.Write(dial)
- if err != nil {
- return err
- }
-
- // ReadResponse may hang if server does not replay
- if streamOptions.timeout > 0 {
- dial.SetDeadline(time.Now().Add(streamOptions.timeout))
- }
-
- if resp, err = http.ReadResponse(breader, req); err != nil {
- // Cancel timeout for future I/O operations
- if streamOptions.timeout > 0 {
- dial.SetDeadline(time.Time{})
- }
- if strings.Contains(err.Error(), "connection refused") {
- return ErrConnectionRefused
- }
- return err
- }
- } else {
- if resp, err = c.HTTPClient.Do(req); err != nil {
- if strings.Contains(err.Error(), "connection refused") {
- return ErrConnectionRefused
- }
- return err
- }
- }
- defer resp.Body.Close()
- if resp.StatusCode < 200 || resp.StatusCode >= 400 {
- return newError(resp)
- }
- var canceled uint32
- if streamOptions.inactivityTimeout > 0 {
- ch := handleInactivityTimeout(&streamOptions, cancelRequest, &canceled)
- defer close(ch)
- }
- err = handleStreamResponse(resp, &streamOptions)
- if err != nil {
- if atomic.LoadUint32(&canceled) != 0 {
- return ErrInactivityTimeout
- }
- return err
- }
- return nil
-}
-
-func handleStreamResponse(resp *http.Response, streamOptions *streamOptions) error {
- var err error
- if !streamOptions.useJSONDecoder && resp.Header.Get("Content-Type") != "application/json" {
- if streamOptions.setRawTerminal {
- _, err = io.Copy(streamOptions.stdout, resp.Body)
- } else {
- _, err = stdcopy.StdCopy(streamOptions.stdout, streamOptions.stderr, resp.Body)
- }
- return err
- }
- // if we want to get raw json stream, just copy it back to output
- // without decoding it
- if streamOptions.rawJSONStream {
- _, err = io.Copy(streamOptions.stdout, resp.Body)
- return err
- }
- dec := json.NewDecoder(resp.Body)
- for {
- var m jsonMessage
- if err := dec.Decode(&m); err == io.EOF {
- break
- } else if err != nil {
- return err
- }
- if m.Stream != "" {
- fmt.Fprint(streamOptions.stdout, m.Stream)
- } else if m.Progress != "" {
- fmt.Fprintf(streamOptions.stdout, "%s %s\r", m.Status, m.Progress)
- } else if m.Error != "" {
- return errors.New(m.Error)
- }
- if m.Status != "" {
- fmt.Fprintln(streamOptions.stdout, m.Status)
- }
- }
- return nil
-}
-
-type proxyWriter struct {
- io.Writer
- calls uint64
-}
-
-func (p *proxyWriter) callCount() uint64 {
- return atomic.LoadUint64(&p.calls)
-}
-
-func (p *proxyWriter) Write(data []byte) (int, error) {
- atomic.AddUint64(&p.calls, 1)
- return p.Writer.Write(data)
-}
-
-func handleInactivityTimeout(options *streamOptions, cancelRequest func(), canceled *uint32) chan<- struct{} {
- done := make(chan struct{})
- proxyStdout := &proxyWriter{Writer: options.stdout}
- proxyStderr := &proxyWriter{Writer: options.stderr}
- options.stdout = proxyStdout
- options.stderr = proxyStderr
- go func() {
- var lastCallCount uint64
- for {
- select {
- case <-time.After(options.inactivityTimeout):
- case <-done:
- return
- }
- curCallCount := proxyStdout.callCount() + proxyStderr.callCount()
- if curCallCount == lastCallCount {
- atomic.AddUint32(canceled, 1)
- cancelRequest()
- return
- }
- lastCallCount = curCallCount
- }
- }()
- return done
-}
-
-type hijackOptions struct {
- success chan struct{}
- setRawTerminal bool
- in io.Reader
- stdout io.Writer
- stderr io.Writer
- data interface{}
-}
-
-// CloseWaiter is an interface with methods for closing the underlying resource
-// and then waiting for it to finish processing.
-type CloseWaiter interface {
- io.Closer
- Wait() error
-}
-
-type waiterFunc func() error
-
-func (w waiterFunc) Wait() error { return w() }
-
-type closerFunc func() error
-
-func (c closerFunc) Close() error { return c() }
-
-func (c *Client) hijack(method, path string, hijackOptions hijackOptions) (CloseWaiter, error) {
- if path != "/version" && !c.SkipServerVersionCheck && c.expectedAPIVersion == nil {
- err := c.checkAPIVersion()
- if err != nil {
- return nil, err
- }
- }
- var params io.Reader
- if hijackOptions.data != nil {
- buf, err := json.Marshal(hijackOptions.data)
- if err != nil {
- return nil, err
- }
- params = bytes.NewBuffer(buf)
- }
- req, err := http.NewRequest(method, c.getURL(path), params)
- if err != nil {
- return nil, err
- }
- req.Header.Set("Content-Type", "application/json")
- req.Header.Set("Connection", "Upgrade")
- req.Header.Set("Upgrade", "tcp")
- protocol := c.endpointURL.Scheme
- address := c.endpointURL.Path
- if protocol != "unix" {
- protocol = "tcp"
- address = c.endpointURL.Host
- }
- var dial net.Conn
- if c.TLSConfig != nil && protocol != "unix" {
- dial, err = tlsDialWithDialer(c.Dialer, protocol, address, c.TLSConfig)
- if err != nil {
- return nil, err
- }
- } else {
- dial, err = c.Dialer.Dial(protocol, address)
- if err != nil {
- return nil, err
- }
- }
-
- errs := make(chan error)
- quit := make(chan struct{})
- go func() {
- clientconn := httputil.NewClientConn(dial, nil)
- defer clientconn.Close()
- clientconn.Do(req)
- if hijackOptions.success != nil {
- hijackOptions.success <- struct{}{}
- <-hijackOptions.success
- }
- rwc, br := clientconn.Hijack()
- defer rwc.Close()
-
- errChanOut := make(chan error, 1)
- errChanIn := make(chan error, 1)
- if hijackOptions.stdout == nil && hijackOptions.stderr == nil {
- close(errChanOut)
- } else {
- // Only copy if hijackOptions.stdout and/or hijackOptions.stderr is actually set.
- // Otherwise, if the only stream you care about is stdin, your attach session
- // will "hang" until the container terminates, even though you're not reading
- // stdout/stderr
- if hijackOptions.stdout == nil {
- hijackOptions.stdout = ioutil.Discard
- }
- if hijackOptions.stderr == nil {
- hijackOptions.stderr = ioutil.Discard
- }
-
- go func() {
- defer func() {
- if hijackOptions.in != nil {
- if closer, ok := hijackOptions.in.(io.Closer); ok {
- closer.Close()
- }
- errChanIn <- nil
- }
- }()
-
- var err error
- if hijackOptions.setRawTerminal {
- _, err = io.Copy(hijackOptions.stdout, br)
- } else {
- _, err = stdcopy.StdCopy(hijackOptions.stdout, hijackOptions.stderr, br)
- }
- errChanOut <- err
- }()
- }
-
- go func() {
- var err error
- if hijackOptions.in != nil {
- _, err = io.Copy(rwc, hijackOptions.in)
- }
- errChanIn <- err
- rwc.(interface {
- CloseWrite() error
- }).CloseWrite()
- }()
-
- var errIn error
- select {
- case errIn = <-errChanIn:
- case <-quit:
- return
- }
-
- var errOut error
- select {
- case errOut = <-errChanOut:
- case <-quit:
- return
- }
-
- if errIn != nil {
- errs <- errIn
- } else {
- errs <- errOut
- }
- }()
-
- return struct {
- closerFunc
- waiterFunc
- }{
- closerFunc(func() error { close(quit); return nil }),
- waiterFunc(func() error { return <-errs }),
- }, nil
-}
-
-func (c *Client) getURL(path string) string {
- urlStr := strings.TrimRight(c.endpointURL.String(), "/")
- if c.endpointURL.Scheme == "unix" {
- urlStr = ""
- }
- if c.requestedAPIVersion != nil {
- return fmt.Sprintf("%s/v%s%s", urlStr, c.requestedAPIVersion, path)
- }
- return fmt.Sprintf("%s%s", urlStr, path)
-}
-
-// getFakeUnixURL returns the URL needed to make an HTTP request over a UNIX
-// domain socket to the given path.
-func (c *Client) getFakeUnixURL(path string) string {
- u := *c.endpointURL // Copy.
-
- // Override URL so that net/http will not complain.
- u.Scheme = "http"
- u.Host = "unix.sock" // Doesn't matter what this is - it's not used.
- u.Path = ""
- urlStr := strings.TrimRight(u.String(), "/")
- if c.requestedAPIVersion != nil {
- return fmt.Sprintf("%s/v%s%s", urlStr, c.requestedAPIVersion, path)
- }
- return fmt.Sprintf("%s%s", urlStr, path)
-}
-
-func (c *Client) unixClient() *http.Client {
- if c.unixHTTPClient != nil {
- return c.unixHTTPClient
- }
- socketPath := c.endpointURL.Path
- tr := cleanhttp.DefaultTransport()
- tr.Dial = func(network, addr string) (net.Conn, error) {
- return c.Dialer.Dial("unix", socketPath)
- }
- c.unixHTTPClient = &http.Client{Transport: tr}
- return c.unixHTTPClient
-}
-
-type jsonMessage struct {
- Status string `json:"status,omitempty"`
- Progress string `json:"progress,omitempty"`
- Error string `json:"error,omitempty"`
- Stream string `json:"stream,omitempty"`
-}
-
-func queryString(opts interface{}) string {
- if opts == nil {
- return ""
- }
- value := reflect.ValueOf(opts)
- if value.Kind() == reflect.Ptr {
- value = value.Elem()
- }
- if value.Kind() != reflect.Struct {
- return ""
- }
- items := url.Values(map[string][]string{})
- for i := 0; i < value.NumField(); i++ {
- field := value.Type().Field(i)
- if field.PkgPath != "" {
- continue
- }
- key := field.Tag.Get("qs")
- if key == "" {
- key = strings.ToLower(field.Name)
- } else if key == "-" {
- continue
- }
- addQueryStringValue(items, key, value.Field(i))
- }
- return items.Encode()
-}
-
-func addQueryStringValue(items url.Values, key string, v reflect.Value) {
- switch v.Kind() {
- case reflect.Bool:
- if v.Bool() {
- items.Add(key, "1")
- }
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- if v.Int() > 0 {
- items.Add(key, strconv.FormatInt(v.Int(), 10))
- }
- case reflect.Float32, reflect.Float64:
- if v.Float() > 0 {
- items.Add(key, strconv.FormatFloat(v.Float(), 'f', -1, 64))
- }
- case reflect.String:
- if v.String() != "" {
- items.Add(key, v.String())
- }
- case reflect.Ptr:
- if !v.IsNil() {
- if b, err := json.Marshal(v.Interface()); err == nil {
- items.Add(key, string(b))
- }
- }
- case reflect.Map:
- if len(v.MapKeys()) > 0 {
- if b, err := json.Marshal(v.Interface()); err == nil {
- items.Add(key, string(b))
- }
- }
- case reflect.Array, reflect.Slice:
- vLen := v.Len()
- if vLen > 0 {
- for i := 0; i < vLen; i++ {
- addQueryStringValue(items, key, v.Index(i))
- }
- }
- }
-}
-
-// Error represents failures in the API. It represents a failure from the API.
-type Error struct {
- Status int
- Message string
-}
-
-func newError(resp *http.Response) *Error {
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return &Error{Status: resp.StatusCode, Message: fmt.Sprintf("cannot read body, err: %v", err)}
- }
- return &Error{Status: resp.StatusCode, Message: string(data)}
-}
-
-func (e *Error) Error() string {
- return fmt.Sprintf("API error (%d): %s", e.Status, e.Message)
-}
-
-func parseEndpoint(endpoint string, tls bool) (*url.URL, error) {
- if endpoint != "" && !strings.Contains(endpoint, "://") {
- endpoint = "tcp://" + endpoint
- }
- u, err := url.Parse(endpoint)
- if err != nil {
- return nil, ErrInvalidEndpoint
- }
- if tls {
- u.Scheme = "https"
- }
- switch u.Scheme {
- case "unix":
- return u, nil
- case "http", "https", "tcp":
- _, port, err := net.SplitHostPort(u.Host)
- if err != nil {
- if e, ok := err.(*net.AddrError); ok {
- if e.Err == "missing port in address" {
- return u, nil
- }
- }
- return nil, ErrInvalidEndpoint
- }
- number, err := strconv.ParseInt(port, 10, 64)
- if err == nil && number > 0 && number < 65536 {
- if u.Scheme == "tcp" {
- if tls {
- u.Scheme = "https"
- } else {
- u.Scheme = "http"
- }
- }
- return u, nil
- }
- return nil, ErrInvalidEndpoint
- default:
- return nil, ErrInvalidEndpoint
- }
-}
-
-type dockerEnv struct {
- dockerHost string
- dockerTLSVerify bool
- dockerCertPath string
-}
-
-func getDockerEnv() (*dockerEnv, error) {
- dockerHost := os.Getenv("DOCKER_HOST")
- var err error
- if dockerHost == "" {
- dockerHost, err = DefaultDockerHost()
- if err != nil {
- return nil, err
- }
- }
- dockerTLSVerify := os.Getenv("DOCKER_TLS_VERIFY") != ""
- var dockerCertPath string
- if dockerTLSVerify {
- dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
- if dockerCertPath == "" {
- home := homedir.Get()
- if home == "" {
- return nil, errors.New("environment variable HOME must be set if DOCKER_CERT_PATH is not set")
- }
- dockerCertPath = filepath.Join(home, ".docker")
- dockerCertPath, err = filepath.Abs(dockerCertPath)
- if err != nil {
- return nil, err
- }
- }
- }
- return &dockerEnv{
- dockerHost: dockerHost,
- dockerTLSVerify: dockerTLSVerify,
- dockerCertPath: dockerCertPath,
- }, nil
-}
-
-// DefaultDockerHost returns the default docker socket for the current OS
-func DefaultDockerHost() (string, error) {
- var defaultHost string
- if runtime.GOOS == "windows" {
- // If we do not have a host, default to TCP socket on Windows
- defaultHost = fmt.Sprintf("tcp://%s:%d", opts.DefaultHTTPHost, opts.DefaultHTTPPort)
- } else {
- // If we do not have a host, default to unix socket
- defaultHost = fmt.Sprintf("unix://%s", opts.DefaultUnixSocket)
- }
- return opts.ValidateHost(defaultHost)
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/client_test.go b/vendor/github.com/fsouza/go-dockerclient/client_test.go
deleted file mode 100644
index 5f848a6..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/client_test.go
+++ /dev/null
@@ -1,600 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "net"
- "net/http"
- "net/http/httptest"
- "net/url"
- "os"
- "path/filepath"
- "reflect"
- "strconv"
- "strings"
- "testing"
- "time"
-
- "github.com/hashicorp/go-cleanhttp"
-)
-
-func TestNewAPIClient(t *testing.T) {
- endpoint := "http://localhost:4243"
- client, err := NewClient(endpoint)
- if err != nil {
- t.Fatal(err)
- }
- if client.endpoint != endpoint {
- t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
- }
- // test unix socket endpoints
- endpoint = "unix:///var/run/docker.sock"
- client, err = NewClient(endpoint)
- if err != nil {
- t.Fatal(err)
- }
- if client.endpoint != endpoint {
- t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
- }
- if !client.SkipServerVersionCheck {
- t.Error("Expected SkipServerVersionCheck to be true, got false")
- }
- if client.requestedAPIVersion != nil {
- t.Errorf("Expected requestedAPIVersion to be nil, got %#v.", client.requestedAPIVersion)
- }
-}
-
-func newTLSClient(endpoint string) (*Client, error) {
- return NewTLSClient(endpoint,
- "testing/data/cert.pem",
- "testing/data/key.pem",
- "testing/data/ca.pem")
-}
-
-func TestNewTSLAPIClient(t *testing.T) {
- endpoint := "https://localhost:4243"
- client, err := newTLSClient(endpoint)
- if err != nil {
- t.Fatal(err)
- }
- if client.endpoint != endpoint {
- t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
- }
- if !client.SkipServerVersionCheck {
- t.Error("Expected SkipServerVersionCheck to be true, got false")
- }
- if client.requestedAPIVersion != nil {
- t.Errorf("Expected requestedAPIVersion to be nil, got %#v.", client.requestedAPIVersion)
- }
-}
-
-func TestNewVersionedClient(t *testing.T) {
- endpoint := "http://localhost:4243"
- client, err := NewVersionedClient(endpoint, "1.12")
- if err != nil {
- t.Fatal(err)
- }
- if client.endpoint != endpoint {
- t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
- }
- if reqVersion := client.requestedAPIVersion.String(); reqVersion != "1.12" {
- t.Errorf("Wrong requestAPIVersion. Want %q. Got %q.", "1.12", reqVersion)
- }
- if client.SkipServerVersionCheck {
- t.Error("Expected SkipServerVersionCheck to be false, got true")
- }
-}
-
-func TestNewVersionedClientFromEnv(t *testing.T) {
- endpoint := "tcp://localhost:2376"
- endpointURL := "http://localhost:2376"
- os.Setenv("DOCKER_HOST", endpoint)
- os.Setenv("DOCKER_TLS_VERIFY", "")
- client, err := NewVersionedClientFromEnv("1.12")
- if err != nil {
- t.Fatal(err)
- }
- if client.endpoint != endpoint {
- t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
- }
- if client.endpointURL.String() != endpointURL {
- t.Errorf("Expected endpointURL %s. Got %s.", endpoint, client.endpoint)
- }
- if reqVersion := client.requestedAPIVersion.String(); reqVersion != "1.12" {
- t.Errorf("Wrong requestAPIVersion. Want %q. Got %q.", "1.12", reqVersion)
- }
- if client.SkipServerVersionCheck {
- t.Error("Expected SkipServerVersionCheck to be false, got true")
- }
-}
-
-func TestNewVersionedClientFromEnvTLS(t *testing.T) {
- endpoint := "tcp://localhost:2376"
- endpointURL := "https://localhost:2376"
- base, _ := os.Getwd()
- os.Setenv("DOCKER_CERT_PATH", filepath.Join(base, "/testing/data/"))
- os.Setenv("DOCKER_HOST", endpoint)
- os.Setenv("DOCKER_TLS_VERIFY", "1")
- client, err := NewVersionedClientFromEnv("1.12")
- if err != nil {
- t.Fatal(err)
- }
- if client.endpoint != endpoint {
- t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
- }
- if client.endpointURL.String() != endpointURL {
- t.Errorf("Expected endpointURL %s. Got %s.", endpoint, client.endpoint)
- }
- if reqVersion := client.requestedAPIVersion.String(); reqVersion != "1.12" {
- t.Errorf("Wrong requestAPIVersion. Want %q. Got %q.", "1.12", reqVersion)
- }
- if client.SkipServerVersionCheck {
- t.Error("Expected SkipServerVersionCheck to be false, got true")
- }
-}
-
-func TestNewTLSVersionedClient(t *testing.T) {
- certPath := "testing/data/cert.pem"
- keyPath := "testing/data/key.pem"
- caPath := "testing/data/ca.pem"
- endpoint := "https://localhost:4243"
- client, err := NewVersionedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
- if err != nil {
- t.Fatal(err)
- }
- if client.endpoint != endpoint {
- t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
- }
- if reqVersion := client.requestedAPIVersion.String(); reqVersion != "1.14" {
- t.Errorf("Wrong requestAPIVersion. Want %q. Got %q.", "1.14", reqVersion)
- }
- if client.SkipServerVersionCheck {
- t.Error("Expected SkipServerVersionCheck to be false, got true")
- }
-}
-
-func TestNewTLSVersionedClientInvalidCA(t *testing.T) {
- certPath := "testing/data/cert.pem"
- keyPath := "testing/data/key.pem"
- caPath := "testing/data/key.pem"
- endpoint := "https://localhost:4243"
- _, err := NewVersionedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
- if err == nil {
- t.Errorf("Expected invalid ca at %s", caPath)
- }
-}
-
-func TestNewClientInvalidEndpoint(t *testing.T) {
- cases := []string{
- "htp://localhost:3243", "http://localhost:a",
- "", "http://localhost:8080:8383", "http://localhost:65536",
- "https://localhost:-20",
- }
- for _, c := range cases {
- client, err := NewClient(c)
- if client != nil {
- t.Errorf("Want client for invalid endpoint, got %#v.", client)
- }
- if !reflect.DeepEqual(err, ErrInvalidEndpoint) {
- t.Errorf("NewClient(%q): Got invalid error for invalid endpoint. Want %#v. Got %#v.", c, ErrInvalidEndpoint, err)
- }
- }
-}
-
-func TestNewClientNoSchemeEndpoint(t *testing.T) {
- cases := []string{"localhost", "localhost:8080"}
- for _, c := range cases {
- client, err := NewClient(c)
- if client == nil {
- t.Errorf("Want client for scheme-less endpoint, got ")
- }
- if err != nil {
- t.Errorf("Got unexpected error scheme-less endpoint: %q", err)
- }
- }
-}
-
-func TestNewTLSClient(t *testing.T) {
- var tests = []struct {
- endpoint string
- expected string
- }{
- {"tcp://localhost:2376", "https"},
- {"tcp://localhost:2375", "https"},
- {"tcp://localhost:4000", "https"},
- {"http://localhost:4000", "https"},
- }
- for _, tt := range tests {
- client, err := newTLSClient(tt.endpoint)
- if err != nil {
- t.Error(err)
- }
- got := client.endpointURL.Scheme
- if got != tt.expected {
- t.Errorf("endpointURL.Scheme: Got %s. Want %s.", got, tt.expected)
- }
- }
-}
-
-func TestEndpoint(t *testing.T) {
- client, err := NewVersionedClient("http://localhost:4243", "1.12")
- if err != nil {
- t.Fatal(err)
- }
- if endpoint := client.Endpoint(); endpoint != client.endpoint {
- t.Errorf("Client.Endpoint(): want %q. Got %q", client.endpoint, endpoint)
- }
-}
-
-func TestGetURL(t *testing.T) {
- var tests = []struct {
- endpoint string
- path string
- expected string
- }{
- {"http://localhost:4243/", "/", "http://localhost:4243/"},
- {"http://localhost:4243", "/", "http://localhost:4243/"},
- {"http://localhost:4243", "/containers/ps", "http://localhost:4243/containers/ps"},
- {"tcp://localhost:4243", "/containers/ps", "http://localhost:4243/containers/ps"},
- {"http://localhost:4243/////", "/", "http://localhost:4243/"},
- {"unix:///var/run/docker.socket", "/containers", "/containers"},
- }
- for _, tt := range tests {
- client, _ := NewClient(tt.endpoint)
- client.endpoint = tt.endpoint
- client.SkipServerVersionCheck = true
- got := client.getURL(tt.path)
- if got != tt.expected {
- t.Errorf("getURL(%q): Got %s. Want %s.", tt.path, got, tt.expected)
- }
- }
-}
-
-func TestGetFakeUnixURL(t *testing.T) {
- var tests = []struct {
- endpoint string
- path string
- expected string
- }{
- {"unix://var/run/docker.sock", "/", "http://unix.sock/"},
- {"unix://var/run/docker.socket", "/", "http://unix.sock/"},
- {"unix://var/run/docker.sock", "/containers/ps", "http://unix.sock/containers/ps"},
- }
- for _, tt := range tests {
- client, _ := NewClient(tt.endpoint)
- client.endpoint = tt.endpoint
- client.SkipServerVersionCheck = true
- got := client.getFakeUnixURL(tt.path)
- if got != tt.expected {
- t.Errorf("getURL(%q): Got %s. Want %s.", tt.path, got, tt.expected)
- }
- }
-}
-
-func TestError(t *testing.T) {
- fakeBody := ioutil.NopCloser(bytes.NewBufferString("bad parameter"))
- resp := &http.Response{
- StatusCode: 400,
- Body: fakeBody,
- }
- err := newError(resp)
- expected := Error{Status: 400, Message: "bad parameter"}
- if !reflect.DeepEqual(expected, *err) {
- t.Errorf("Wrong error type. Want %#v. Got %#v.", expected, *err)
- }
- message := "API error (400): bad parameter"
- if err.Error() != message {
- t.Errorf("Wrong error message. Want %q. Got %q.", message, err.Error())
- }
-}
-
-func TestQueryString(t *testing.T) {
- v := float32(2.4)
- f32QueryString := fmt.Sprintf("w=%s&x=10&y=10.35", strconv.FormatFloat(float64(v), 'f', -1, 64))
- jsonPerson := url.QueryEscape(`{"Name":"gopher","age":4}`)
- var tests = []struct {
- input interface{}
- want string
- }{
- {&ListContainersOptions{All: true}, "all=1"},
- {ListContainersOptions{All: true}, "all=1"},
- {ListContainersOptions{Before: "something"}, "before=something"},
- {ListContainersOptions{Before: "something", Since: "other"}, "before=something&since=other"},
- {ListContainersOptions{Filters: map[string][]string{"status": {"paused", "running"}}}, "filters=%7B%22status%22%3A%5B%22paused%22%2C%22running%22%5D%7D"},
- {dumb{X: 10, Y: 10.35000}, "x=10&y=10.35"},
- {dumb{W: v, X: 10, Y: 10.35000}, f32QueryString},
- {dumb{X: 10, Y: 10.35000, Z: 10}, "x=10&y=10.35&zee=10"},
- {dumb{v: 4, X: 10, Y: 10.35000}, "x=10&y=10.35"},
- {dumb{T: 10, Y: 10.35000}, "y=10.35"},
- {dumb{Person: &person{Name: "gopher", Age: 4}}, "p=" + jsonPerson},
- {nil, ""},
- {10, ""},
- {"not_a_struct", ""},
- }
- for _, tt := range tests {
- got := queryString(tt.input)
- if got != tt.want {
- t.Errorf("queryString(%v). Want %q. Got %q.", tt.input, tt.want, got)
- }
- }
-}
-
-func TestAPIVersions(t *testing.T) {
- var tests = []struct {
- a string
- b string
- expectedALessThanB bool
- expectedALessThanOrEqualToB bool
- expectedAGreaterThanB bool
- expectedAGreaterThanOrEqualToB bool
- }{
- {"1.11", "1.11", false, true, false, true},
- {"1.10", "1.11", true, true, false, false},
- {"1.11", "1.10", false, false, true, true},
-
- {"1.11-ubuntu0", "1.11", false, true, false, true},
- {"1.10", "1.11-el7", true, true, false, false},
-
- {"1.9", "1.11", true, true, false, false},
- {"1.11", "1.9", false, false, true, true},
-
- {"1.1.1", "1.1", false, false, true, true},
- {"1.1", "1.1.1", true, true, false, false},
-
- {"2.1", "1.1.1", false, false, true, true},
- {"2.1", "1.3.1", false, false, true, true},
- {"1.1.1", "2.1", true, true, false, false},
- {"1.3.1", "2.1", true, true, false, false},
- }
-
- for _, tt := range tests {
- a, _ := NewAPIVersion(tt.a)
- b, _ := NewAPIVersion(tt.b)
-
- if tt.expectedALessThanB && !a.LessThan(b) {
- t.Errorf("Expected %#v < %#v", a, b)
- }
- if tt.expectedALessThanOrEqualToB && !a.LessThanOrEqualTo(b) {
- t.Errorf("Expected %#v <= %#v", a, b)
- }
- if tt.expectedAGreaterThanB && !a.GreaterThan(b) {
- t.Errorf("Expected %#v > %#v", a, b)
- }
- if tt.expectedAGreaterThanOrEqualToB && !a.GreaterThanOrEqualTo(b) {
- t.Errorf("Expected %#v >= %#v", a, b)
- }
- }
-}
-
-func TestPing(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- err := client.Ping()
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestPingFailing(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusInternalServerError}
- client := newTestClient(fakeRT)
- err := client.Ping()
- if err == nil {
- t.Fatal("Expected non nil error, got nil")
- }
- expectedErrMsg := "API error (500): "
- if err.Error() != expectedErrMsg {
- t.Fatalf("Expected error to be %q, got: %q", expectedErrMsg, err.Error())
- }
-}
-
-func TestPingFailingWrongStatus(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusAccepted}
- client := newTestClient(fakeRT)
- err := client.Ping()
- if err == nil {
- t.Fatal("Expected non nil error, got nil")
- }
- expectedErrMsg := "API error (202): "
- if err.Error() != expectedErrMsg {
- t.Fatalf("Expected error to be %q, got: %q", expectedErrMsg, err.Error())
- }
-}
-
-func TestPingErrorWithUnixSocket(t *testing.T) {
- go func() {
- li, err := net.Listen("unix", "/tmp/echo.sock")
- if err != nil {
- t.Fatal(err)
- }
- defer li.Close()
- if err != nil {
- t.Fatalf("Expected to get listener, but failed: %#v", err)
- }
-
- fd, err := li.Accept()
- if err != nil {
- t.Fatalf("Expected to accept connection, but failed: %#v", err)
- }
-
- buf := make([]byte, 512)
- nr, err := fd.Read(buf)
-
- // Create invalid response message to trigger error.
- data := buf[0:nr]
- for i := 0; i < 10; i++ {
- data[i] = 63
- }
-
- _, err = fd.Write(data)
- if err != nil {
- t.Fatalf("Expected to write to socket, but failed: %#v", err)
- }
-
- return
- }()
-
- // Wait for unix socket to listen
- time.Sleep(10 * time.Millisecond)
-
- endpoint := "unix:///tmp/echo.sock"
- u, _ := parseEndpoint(endpoint, false)
- client := Client{
- HTTPClient: cleanhttp.DefaultClient(),
- Dialer: &net.Dialer{},
- endpoint: endpoint,
- endpointURL: u,
- SkipServerVersionCheck: true,
- }
-
- err := client.Ping()
- if err == nil {
- t.Fatal("Expected non nil error, got nil")
- }
-}
-
-func TestClientStreamTimeoutNotHit(t *testing.T) {
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- for i := 0; i < 5; i++ {
- fmt.Fprintf(w, "%d\n", i)
- if f, ok := w.(http.Flusher); ok {
- f.Flush()
- }
- time.Sleep(100 * time.Millisecond)
- }
- }))
- client, err := NewClient(srv.URL)
- if err != nil {
- t.Fatal(err)
- }
- var w bytes.Buffer
- err = client.stream("POST", "/image/create", streamOptions{
- setRawTerminal: true,
- stdout: &w,
- inactivityTimeout: 300 * time.Millisecond,
- })
- if err != nil {
- t.Fatal(err)
- }
- expected := "0\n1\n2\n3\n4\n"
- result := w.String()
- if result != expected {
- t.Fatalf("expected stream result %q, got: %q", expected, result)
- }
-}
-
-func TestClientStreamTimeout(t *testing.T) {
- srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- for i := 0; i < 5; i++ {
- fmt.Fprintf(w, "%d\n", i)
- if f, ok := w.(http.Flusher); ok {
- f.Flush()
- }
- time.Sleep(500 * time.Millisecond)
- }
- }))
- client, err := NewClient(srv.URL)
- if err != nil {
- t.Fatal(err)
- }
- var w bytes.Buffer
- err = client.stream("POST", "/image/create", streamOptions{
- setRawTerminal: true,
- stdout: &w,
- inactivityTimeout: 100 * time.Millisecond,
- })
- if err != ErrInactivityTimeout {
- t.Fatalf("expected request canceled error, got: %s", err)
- }
- expected := "0\n"
- result := w.String()
- if result != expected {
- t.Fatalf("expected stream result %q, got: %q", expected, result)
- }
-}
-
-func TestClientStreamTimeoutUnixSocket(t *testing.T) {
- l, err := net.Listen("unix", "/tmp/docker_test.sock")
- if err != nil {
- t.Fatal(err)
- }
- defer l.Close()
- go func() {
- http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- for i := 0; i < 5; i++ {
- fmt.Fprintf(w, "%d\n", i)
- if f, ok := w.(http.Flusher); ok {
- f.Flush()
- }
- time.Sleep(500 * time.Millisecond)
- }
- }))
- }()
- client, err := NewClient("unix:///tmp/docker_test.sock")
- if err != nil {
- t.Fatal(err)
- }
- var w bytes.Buffer
- err = client.stream("POST", "/image/create", streamOptions{
- setRawTerminal: true,
- stdout: &w,
- inactivityTimeout: 100 * time.Millisecond,
- })
- if err != ErrInactivityTimeout {
- t.Fatalf("expected request canceled error, got: %s", err)
- }
- expected := "0\n"
- result := w.String()
- if result != expected {
- t.Fatalf("expected stream result %q, got: %q", expected, result)
- }
-}
-
-type FakeRoundTripper struct {
- message string
- status int
- header map[string]string
- requests []*http.Request
-}
-
-func (rt *FakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
- body := strings.NewReader(rt.message)
- rt.requests = append(rt.requests, r)
- res := &http.Response{
- StatusCode: rt.status,
- Body: ioutil.NopCloser(body),
- Header: make(http.Header),
- }
- for k, v := range rt.header {
- res.Header.Set(k, v)
- }
- return res, nil
-}
-
-func (rt *FakeRoundTripper) Reset() {
- rt.requests = nil
-}
-
-type person struct {
- Name string
- Age int `json:"age"`
-}
-
-type dumb struct {
- T int `qs:"-"`
- v int
- W float32
- X int
- Y float64
- Z int `qs:"zee"`
- Person *person `qs:"p"`
-}
-
-type fakeEndpointURL struct {
- Scheme string
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/container.go b/vendor/github.com/fsouza/go-dockerclient/container.go
deleted file mode 100644
index 81f0168..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/container.go
+++ /dev/null
@@ -1,1343 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strconv"
- "strings"
- "time"
-
- "github.com/docker/go-units"
-)
-
-// ErrContainerAlreadyExists is the error returned by CreateContainer when the
-// container already exists.
-var ErrContainerAlreadyExists = errors.New("container already exists")
-
-// ListContainersOptions specify parameters to the ListContainers function.
-//
-// See https://goo.gl/47a6tO for more details.
-type ListContainersOptions struct {
- All bool
- Size bool
- Limit int
- Since string
- Before string
- Filters map[string][]string
-}
-
-// APIPort is a type that represents a port mapping returned by the Docker API
-type APIPort struct {
- PrivatePort int64 `json:"PrivatePort,omitempty" yaml:"PrivatePort,omitempty"`
- PublicPort int64 `json:"PublicPort,omitempty" yaml:"PublicPort,omitempty"`
- Type string `json:"Type,omitempty" yaml:"Type,omitempty"`
- IP string `json:"IP,omitempty" yaml:"IP,omitempty"`
-}
-
-// APIMount represents a mount point for a container.
-type APIMount struct {
- Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
- Source string `json:"Source,omitempty" yaml:"Source,omitempty"`
- Destination string `json:"Destination,omitempty" yaml:"Destination,omitempty"`
- Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"`
- Mode string `json:"Mode,omitempty" yaml:"Mode,omitempty"`
- RW bool `json:"RW,omitempty" yaml:"RW,omitempty"`
- Propogation string `json:"Propogation,omitempty" yaml:"Propogation,omitempty"`
-}
-
-// APIContainers represents each container in the list returned by
-// ListContainers.
-type APIContainers struct {
- ID string `json:"Id" yaml:"Id"`
- Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
- Command string `json:"Command,omitempty" yaml:"Command,omitempty"`
- Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
- State string `json:"State,omitempty" yaml:"State,omitempty"`
- Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
- Ports []APIPort `json:"Ports,omitempty" yaml:"Ports,omitempty"`
- SizeRw int64 `json:"SizeRw,omitempty" yaml:"SizeRw,omitempty"`
- SizeRootFs int64 `json:"SizeRootFs,omitempty" yaml:"SizeRootFs,omitempty"`
- Names []string `json:"Names,omitempty" yaml:"Names,omitempty"`
- Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
- Networks NetworkList `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty"`
- Mounts []APIMount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"`
-}
-
-// NetworkList encapsulates a map of networks, as returned by the Docker API in
-// ListContainers.
-type NetworkList struct {
- Networks map[string]ContainerNetwork `json:"Networks" yaml:"Networks,omitempty"`
-}
-
-// ListContainers returns a slice of containers matching the given criteria.
-//
-// See https://goo.gl/47a6tO for more details.
-func (c *Client) ListContainers(opts ListContainersOptions) ([]APIContainers, error) {
- path := "/containers/json?" + queryString(opts)
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var containers []APIContainers
- if err := json.NewDecoder(resp.Body).Decode(&containers); err != nil {
- return nil, err
- }
- return containers, nil
-}
-
-// Port represents the port number and the protocol, in the form
-// /. For example: 80/tcp.
-type Port string
-
-// Port returns the number of the port.
-func (p Port) Port() string {
- return strings.Split(string(p), "/")[0]
-}
-
-// Proto returns the name of the protocol.
-func (p Port) Proto() string {
- parts := strings.Split(string(p), "/")
- if len(parts) == 1 {
- return "tcp"
- }
- return parts[1]
-}
-
-// State represents the state of a container.
-type State struct {
- Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
- Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
- Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"`
- Restarting bool `json:"Restarting,omitempty" yaml:"Restarting,omitempty"`
- OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty"`
- RemovalInProgress bool `json:"RemovalInProgress,omitempty" yaml:"RemovalInProgress,omitempty"`
- Dead bool `json:"Dead,omitempty" yaml:"Dead,omitempty"`
- Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"`
- ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
- Error string `json:"Error,omitempty" yaml:"Error,omitempty"`
- StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty"`
- FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"`
-}
-
-// String returns a human-readable description of the state
-func (s *State) String() string {
- if s.Running {
- if s.Paused {
- return fmt.Sprintf("Up %s (Paused)", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
- }
- if s.Restarting {
- return fmt.Sprintf("Restarting (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
- }
-
- return fmt.Sprintf("Up %s", units.HumanDuration(time.Now().UTC().Sub(s.StartedAt)))
- }
-
- if s.RemovalInProgress {
- return "Removal In Progress"
- }
-
- if s.Dead {
- return "Dead"
- }
-
- if s.StartedAt.IsZero() {
- return "Created"
- }
-
- if s.FinishedAt.IsZero() {
- return ""
- }
-
- return fmt.Sprintf("Exited (%d) %s ago", s.ExitCode, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt)))
-}
-
-// StateString returns a single string to describe state
-func (s *State) StateString() string {
- if s.Running {
- if s.Paused {
- return "paused"
- }
- if s.Restarting {
- return "restarting"
- }
- return "running"
- }
-
- if s.Dead {
- return "dead"
- }
-
- if s.StartedAt.IsZero() {
- return "created"
- }
-
- return "exited"
-}
-
-// PortBinding represents the host/container port mapping as returned in the
-// `docker inspect` json
-type PortBinding struct {
- HostIP string `json:"HostIP,omitempty" yaml:"HostIP,omitempty"`
- HostPort string `json:"HostPort,omitempty" yaml:"HostPort,omitempty"`
-}
-
-// PortMapping represents a deprecated field in the `docker inspect` output,
-// and its value as found in NetworkSettings should always be nil
-type PortMapping map[string]string
-
-// ContainerNetwork represents the networking settings of a container per network.
-type ContainerNetwork struct {
- MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
- GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen,omitempty" yaml:"GlobalIPv6PrefixLen,omitempty"`
- GlobalIPv6Address string `json:"GlobalIPv6Address,omitempty" yaml:"GlobalIPv6Address,omitempty"`
- IPv6Gateway string `json:"IPv6Gateway,omitempty" yaml:"IPv6Gateway,omitempty"`
- IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty"`
- IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
- Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty"`
- EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty"`
- NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty"`
-}
-
-// NetworkSettings contains network-related information about a container
-type NetworkSettings struct {
- Networks map[string]ContainerNetwork `json:"Networks,omitempty" yaml:"Networks,omitempty"`
- IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
- IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty"`
- MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
- Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty"`
- Bridge string `json:"Bridge,omitempty" yaml:"Bridge,omitempty"`
- PortMapping map[string]PortMapping `json:"PortMapping,omitempty" yaml:"PortMapping,omitempty"`
- Ports map[Port][]PortBinding `json:"Ports,omitempty" yaml:"Ports,omitempty"`
- NetworkID string `json:"NetworkID,omitempty" yaml:"NetworkID,omitempty"`
- EndpointID string `json:"EndpointID,omitempty" yaml:"EndpointID,omitempty"`
- SandboxKey string `json:"SandboxKey,omitempty" yaml:"SandboxKey,omitempty"`
- GlobalIPv6Address string `json:"GlobalIPv6Address,omitempty" yaml:"GlobalIPv6Address,omitempty"`
- GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen,omitempty" yaml:"GlobalIPv6PrefixLen,omitempty"`
- IPv6Gateway string `json:"IPv6Gateway,omitempty" yaml:"IPv6Gateway,omitempty"`
- LinkLocalIPv6Address string `json:"LinkLocalIPv6Address,omitempty" yaml:"LinkLocalIPv6Address,omitempty"`
- LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen,omitempty" yaml:"LinkLocalIPv6PrefixLen,omitempty"`
- SecondaryIPAddresses []string `json:"SecondaryIPAddresses,omitempty" yaml:"SecondaryIPAddresses,omitempty"`
- SecondaryIPv6Addresses []string `json:"SecondaryIPv6Addresses,omitempty" yaml:"SecondaryIPv6Addresses,omitempty"`
-}
-
-// PortMappingAPI translates the port mappings as contained in NetworkSettings
-// into the format in which they would appear when returned by the API
-func (settings *NetworkSettings) PortMappingAPI() []APIPort {
- var mapping []APIPort
- for port, bindings := range settings.Ports {
- p, _ := parsePort(port.Port())
- if len(bindings) == 0 {
- mapping = append(mapping, APIPort{
- PrivatePort: int64(p),
- Type: port.Proto(),
- })
- continue
- }
- for _, binding := range bindings {
- p, _ := parsePort(port.Port())
- h, _ := parsePort(binding.HostPort)
- mapping = append(mapping, APIPort{
- PrivatePort: int64(p),
- PublicPort: int64(h),
- Type: port.Proto(),
- IP: binding.HostIP,
- })
- }
- }
- return mapping
-}
-
-func parsePort(rawPort string) (int, error) {
- port, err := strconv.ParseUint(rawPort, 10, 16)
- if err != nil {
- return 0, err
- }
- return int(port), nil
-}
-
-// Config is the list of configuration options used when creating a container.
-// Config does not contain the options that are specific to starting a container on a
-// given host. Those are contained in HostConfig
-type Config struct {
- Hostname string `json:"Hostname,omitempty" yaml:"Hostname,omitempty"`
- Domainname string `json:"Domainname,omitempty" yaml:"Domainname,omitempty"`
- User string `json:"User,omitempty" yaml:"User,omitempty"`
- Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
- MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"`
- MemoryReservation int64 `json:"MemoryReservation,omitempty" yaml:"MemoryReservation,omitempty"`
- KernelMemory int64 `json:"KernelMemory,omitempty" yaml:"KernelMemory,omitempty"`
- CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"`
- CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty"`
- AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"`
- AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty"`
- AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty"`
- PortSpecs []string `json:"PortSpecs,omitempty" yaml:"PortSpecs,omitempty"`
- ExposedPorts map[Port]struct{} `json:"ExposedPorts,omitempty" yaml:"ExposedPorts,omitempty"`
- StopSignal string `json:"StopSignal,omitempty" yaml:"StopSignal,omitempty"`
- Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty"`
- OpenStdin bool `json:"OpenStdin,omitempty" yaml:"OpenStdin,omitempty"`
- StdinOnce bool `json:"StdinOnce,omitempty" yaml:"StdinOnce,omitempty"`
- Env []string `json:"Env,omitempty" yaml:"Env,omitempty"`
- Cmd []string `json:"Cmd" yaml:"Cmd"`
- DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.9 and below only
- Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
- Volumes map[string]struct{} `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
- VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty"`
- VolumesFrom string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
- WorkingDir string `json:"WorkingDir,omitempty" yaml:"WorkingDir,omitempty"`
- MacAddress string `json:"MacAddress,omitempty" yaml:"MacAddress,omitempty"`
- Entrypoint []string `json:"Entrypoint" yaml:"Entrypoint"`
- NetworkDisabled bool `json:"NetworkDisabled,omitempty" yaml:"NetworkDisabled,omitempty"`
- SecurityOpts []string `json:"SecurityOpts,omitempty" yaml:"SecurityOpts,omitempty"`
- OnBuild []string `json:"OnBuild,omitempty" yaml:"OnBuild,omitempty"`
- Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"`
- Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
-}
-
-// Mount represents a mount point in the container.
-//
-// It has been added in the version 1.20 of the Docker API, available since
-// Docker 1.8.
-type Mount struct {
- Name string
- Source string
- Destination string
- Driver string
- Mode string
- RW bool
-}
-
-// LogConfig defines the log driver type and the configuration for it.
-type LogConfig struct {
- Type string `json:"Type,omitempty" yaml:"Type,omitempty"`
- Config map[string]string `json:"Config,omitempty" yaml:"Config,omitempty"`
-}
-
-// ULimit defines system-wide resource limitations
-// This can help a lot in system administration, e.g. when a user starts too many processes and therefore makes the system unresponsive for other users.
-type ULimit struct {
- Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
- Soft int64 `json:"Soft,omitempty" yaml:"Soft,omitempty"`
- Hard int64 `json:"Hard,omitempty" yaml:"Hard,omitempty"`
-}
-
-// SwarmNode containers information about which Swarm node the container is on
-type SwarmNode struct {
- ID string `json:"ID,omitempty" yaml:"ID,omitempty"`
- IP string `json:"IP,omitempty" yaml:"IP,omitempty"`
- Addr string `json:"Addr,omitempty" yaml:"Addr,omitempty"`
- Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
- CPUs int64 `json:"CPUs,omitempty" yaml:"CPUs,omitempty"`
- Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
- Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
-}
-
-// GraphDriver contains information about the GraphDriver used by the container
-type GraphDriver struct {
- Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
- Data map[string]string `json:"Data,omitempty" yaml:"Data,omitempty"`
-}
-
-// Container is the type encompasing everything about a container - its config,
-// hostconfig, etc.
-type Container struct {
- ID string `json:"Id" yaml:"Id"`
-
- Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
-
- Path string `json:"Path,omitempty" yaml:"Path,omitempty"`
- Args []string `json:"Args,omitempty" yaml:"Args,omitempty"`
-
- Config *Config `json:"Config,omitempty" yaml:"Config,omitempty"`
- State State `json:"State,omitempty" yaml:"State,omitempty"`
- Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
-
- Node *SwarmNode `json:"Node,omitempty" yaml:"Node,omitempty"`
-
- NetworkSettings *NetworkSettings `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty"`
-
- SysInitPath string `json:"SysInitPath,omitempty" yaml:"SysInitPath,omitempty"`
- ResolvConfPath string `json:"ResolvConfPath,omitempty" yaml:"ResolvConfPath,omitempty"`
- HostnamePath string `json:"HostnamePath,omitempty" yaml:"HostnamePath,omitempty"`
- HostsPath string `json:"HostsPath,omitempty" yaml:"HostsPath,omitempty"`
- LogPath string `json:"LogPath,omitempty" yaml:"LogPath,omitempty"`
- Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
- Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"`
- Mounts []Mount `json:"Mounts,omitempty" yaml:"Mounts,omitempty"`
-
- Volumes map[string]string `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
- VolumesRW map[string]bool `json:"VolumesRW,omitempty" yaml:"VolumesRW,omitempty"`
- HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
- ExecIDs []string `json:"ExecIDs,omitempty" yaml:"ExecIDs,omitempty"`
- GraphDriver *GraphDriver `json:"GraphDriver,omitempty" yaml:"GraphDriver,omitempty"`
-
- RestartCount int `json:"RestartCount,omitempty" yaml:"RestartCount,omitempty"`
-
- AppArmorProfile string `json:"AppArmorProfile,omitempty" yaml:"AppArmorProfile,omitempty"`
-}
-
-// UpdateContainerOptions specify parameters to the UpdateContainer function.
-//
-// See https://goo.gl/Y6fXUy for more details.
-type UpdateContainerOptions struct {
- BlkioWeight int `json:"BlkioWeight"`
- CPUShares int `json:"CpuShares"`
- CPUPeriod int `json:"CpuPeriod"`
- CPUQuota int `json:"CpuQuota"`
- CpusetCpus string `json:"CpusetCpus"`
- CpusetMems string `json:"CpusetMems"`
- Memory int `json:"Memory"`
- MemorySwap int `json:"MemorySwap"`
- MemoryReservation int `json:"MemoryReservation"`
- KernelMemory int `json:"KernelMemory"`
- RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty"`
-}
-
-// UpdateContainer updates the container at ID with the options
-//
-// See https://goo.gl/Y6fXUy for more details.
-func (c *Client) UpdateContainer(id string, opts UpdateContainerOptions) error {
- resp, err := c.do("POST", fmt.Sprintf("/containers/"+id+"/update"), doOptions{data: opts, forceJSON: true})
- if err != nil {
- return err
- }
- defer resp.Body.Close()
- return nil
-}
-
-// RenameContainerOptions specify parameters to the RenameContainer function.
-//
-// See https://goo.gl/laSOIy for more details.
-type RenameContainerOptions struct {
- // ID of container to rename
- ID string `qs:"-"`
-
- // New name
- Name string `json:"name,omitempty" yaml:"name,omitempty"`
-}
-
-// RenameContainer updates and existing containers name
-//
-// See https://goo.gl/laSOIy for more details.
-func (c *Client) RenameContainer(opts RenameContainerOptions) error {
- resp, err := c.do("POST", fmt.Sprintf("/containers/"+opts.ID+"/rename?%s", queryString(opts)), doOptions{})
- if err != nil {
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// InspectContainer returns information about a container by its ID.
-//
-// See https://goo.gl/RdIq0b for more details.
-func (c *Client) InspectContainer(id string) (*Container, error) {
- path := "/containers/" + id + "/json"
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, &NoSuchContainer{ID: id}
- }
- return nil, err
- }
- defer resp.Body.Close()
- var container Container
- if err := json.NewDecoder(resp.Body).Decode(&container); err != nil {
- return nil, err
- }
- return &container, nil
-}
-
-// ContainerChanges returns changes in the filesystem of the given container.
-//
-// See https://goo.gl/9GsTIF for more details.
-func (c *Client) ContainerChanges(id string) ([]Change, error) {
- path := "/containers/" + id + "/changes"
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, &NoSuchContainer{ID: id}
- }
- return nil, err
- }
- defer resp.Body.Close()
- var changes []Change
- if err := json.NewDecoder(resp.Body).Decode(&changes); err != nil {
- return nil, err
- }
- return changes, nil
-}
-
-// CreateContainerOptions specify parameters to the CreateContainer function.
-//
-// See https://goo.gl/WxQzrr for more details.
-type CreateContainerOptions struct {
- Name string
- Config *Config `qs:"-"`
- HostConfig *HostConfig `qs:"-"`
- NetworkingConfig *NetworkingConfig `qs:"-"`
-}
-
-// CreateContainer creates a new container, returning the container instance,
-// or an error in case of failure.
-//
-// See https://goo.gl/WxQzrr for more details.
-func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error) {
- path := "/containers/create?" + queryString(opts)
- resp, err := c.do(
- "POST",
- path,
- doOptions{
- data: struct {
- *Config
- HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
- NetworkingConfig *NetworkingConfig `json:"NetworkingConfig,omitempty" yaml:"NetworkingConfig,omitempty"`
- }{
- opts.Config,
- opts.HostConfig,
- opts.NetworkingConfig,
- },
- },
- )
-
- if e, ok := err.(*Error); ok {
- if e.Status == http.StatusNotFound {
- return nil, ErrNoSuchImage
- }
- if e.Status == http.StatusConflict {
- return nil, ErrContainerAlreadyExists
- }
- }
-
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var container Container
- if err := json.NewDecoder(resp.Body).Decode(&container); err != nil {
- return nil, err
- }
-
- container.Name = opts.Name
-
- return &container, nil
-}
-
-// KeyValuePair is a type for generic key/value pairs as used in the Lxc
-// configuration
-type KeyValuePair struct {
- Key string `json:"Key,omitempty" yaml:"Key,omitempty"`
- Value string `json:"Value,omitempty" yaml:"Value,omitempty"`
-}
-
-// RestartPolicy represents the policy for automatically restarting a container.
-//
-// Possible values are:
-//
-// - always: the docker daemon will always restart the container
-// - on-failure: the docker daemon will restart the container on failures, at
-// most MaximumRetryCount times
-// - unless-stopped: the docker daemon will always restart the container except
-// when user has manually stopped the container
-// - no: the docker daemon will not restart the container automatically
-type RestartPolicy struct {
- Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
- MaximumRetryCount int `json:"MaximumRetryCount,omitempty" yaml:"MaximumRetryCount,omitempty"`
-}
-
-// AlwaysRestart returns a restart policy that tells the Docker daemon to
-// always restart the container.
-func AlwaysRestart() RestartPolicy {
- return RestartPolicy{Name: "always"}
-}
-
-// RestartOnFailure returns a restart policy that tells the Docker daemon to
-// restart the container on failures, trying at most maxRetry times.
-func RestartOnFailure(maxRetry int) RestartPolicy {
- return RestartPolicy{Name: "on-failure", MaximumRetryCount: maxRetry}
-}
-
-// RestartUnlessStopped returns a restart policy that tells the Docker daemon to
-// always restart the container except when user has manually stopped the container.
-func RestartUnlessStopped() RestartPolicy {
- return RestartPolicy{Name: "unless-stopped"}
-}
-
-// NeverRestart returns a restart policy that tells the Docker daemon to never
-// restart the container on failures.
-func NeverRestart() RestartPolicy {
- return RestartPolicy{Name: "no"}
-}
-
-// Device represents a device mapping between the Docker host and the
-// container.
-type Device struct {
- PathOnHost string `json:"PathOnHost,omitempty" yaml:"PathOnHost,omitempty"`
- PathInContainer string `json:"PathInContainer,omitempty" yaml:"PathInContainer,omitempty"`
- CgroupPermissions string `json:"CgroupPermissions,omitempty" yaml:"CgroupPermissions,omitempty"`
-}
-
-// BlockWeight represents a relative device weight for an individual device inside
-// of a container
-//
-// See https://goo.gl/FSdP0H for more details.
-type BlockWeight struct {
- Path string `json:"Path,omitempty"`
- Weight string `json:"Weight,omitempty"`
-}
-
-// BlockLimit represents a read/write limit in IOPS or Bandwidth for a device
-// inside of a container
-//
-// See https://goo.gl/FSdP0H for more details.
-type BlockLimit struct {
- Path string `json:"Path,omitempty"`
- Rate string `json:"Rate,omitempty"`
-}
-
-// HostConfig contains the container options related to starting a container on
-// a given host
-type HostConfig struct {
- Binds []string `json:"Binds,omitempty" yaml:"Binds,omitempty"`
- CapAdd []string `json:"CapAdd,omitempty" yaml:"CapAdd,omitempty"`
- CapDrop []string `json:"CapDrop,omitempty" yaml:"CapDrop,omitempty"`
- GroupAdd []string `json:"GroupAdd,omitempty" yaml:"GroupAdd,omitempty"`
- ContainerIDFile string `json:"ContainerIDFile,omitempty" yaml:"ContainerIDFile,omitempty"`
- LxcConf []KeyValuePair `json:"LxcConf,omitempty" yaml:"LxcConf,omitempty"`
- Privileged bool `json:"Privileged,omitempty" yaml:"Privileged,omitempty"`
- PortBindings map[Port][]PortBinding `json:"PortBindings,omitempty" yaml:"PortBindings,omitempty"`
- Links []string `json:"Links,omitempty" yaml:"Links,omitempty"`
- PublishAllPorts bool `json:"PublishAllPorts,omitempty" yaml:"PublishAllPorts,omitempty"`
- DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.10 and above only
- DNSOptions []string `json:"DnsOptions,omitempty" yaml:"DnsOptions,omitempty"`
- DNSSearch []string `json:"DnsSearch,omitempty" yaml:"DnsSearch,omitempty"`
- ExtraHosts []string `json:"ExtraHosts,omitempty" yaml:"ExtraHosts,omitempty"`
- VolumesFrom []string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
- UsernsMode string `json:"UsernsMode,omitempty" yaml:"UsernsMode,omitempty"`
- NetworkMode string `json:"NetworkMode,omitempty" yaml:"NetworkMode,omitempty"`
- IpcMode string `json:"IpcMode,omitempty" yaml:"IpcMode,omitempty"`
- PidMode string `json:"PidMode,omitempty" yaml:"PidMode,omitempty"`
- UTSMode string `json:"UTSMode,omitempty" yaml:"UTSMode,omitempty"`
- RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty"`
- Devices []Device `json:"Devices,omitempty" yaml:"Devices,omitempty"`
- LogConfig LogConfig `json:"LogConfig,omitempty" yaml:"LogConfig,omitempty"`
- ReadonlyRootfs bool `json:"ReadonlyRootfs,omitempty" yaml:"ReadonlyRootfs,omitempty"`
- SecurityOpt []string `json:"SecurityOpt,omitempty" yaml:"SecurityOpt,omitempty"`
- CgroupParent string `json:"CgroupParent,omitempty" yaml:"CgroupParent,omitempty"`
- Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
- MemoryReservation int64 `json:"MemoryReservation,omitempty" yaml:"MemoryReservation,omitempty"`
- MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"`
- MemorySwappiness int64 `json:"MemorySwappiness,omitempty" yaml:"MemorySwappiness,omitempty"`
- OOMKillDisable bool `json:"OomKillDisable,omitempty" yaml:"OomKillDisable"`
- CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"`
- CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty"`
- CPUSetCPUs string `json:"CpusetCpus,omitempty" yaml:"CpusetCpus,omitempty"`
- CPUSetMEMs string `json:"CpusetMems,omitempty" yaml:"CpusetMems,omitempty"`
- CPUQuota int64 `json:"CpuQuota,omitempty" yaml:"CpuQuota,omitempty"`
- CPUPeriod int64 `json:"CpuPeriod,omitempty" yaml:"CpuPeriod,omitempty"`
- BlkioWeight int64 `json:"BlkioWeight,omitempty" yaml:"BlkioWeight"`
- BlkioWeightDevice []BlockWeight `json:"BlkioWeightDevice,omitempty" yaml:"BlkioWeightDevice"`
- BlkioDeviceReadBps []BlockLimit `json:"BlkioDeviceReadBps,omitempty" yaml:"BlkioDeviceReadBps"`
- BlkioDeviceReadIOps []BlockLimit `json:"BlkioDeviceReadIOps,omitempty" yaml:"BlkioDeviceReadIOps"`
- BlkioDeviceWriteBps []BlockLimit `json:"BlkioDeviceWriteBps,omitempty" yaml:"BlkioDeviceWriteBps"`
- BlkioDeviceWriteIOps []BlockLimit `json:"BlkioDeviceWriteIOps,omitempty" yaml:"BlkioDeviceWriteIOps"`
- Ulimits []ULimit `json:"Ulimits,omitempty" yaml:"Ulimits,omitempty"`
- VolumeDriver string `json:"VolumeDriver,omitempty" yaml:"VolumeDriver,omitempty"`
- OomScoreAdj int `json:"OomScoreAdj,omitempty" yaml:"OomScoreAdj,omitempty"`
- PidsLimit int64 `json:"PidsLimit,omitempty" yaml:"PidsLimit,omitempty"`
- ShmSize int64 `json:"ShmSize,omitempty" yaml:"ShmSize,omitempty"`
-}
-
-// 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]*EndpointConfig // Endpoint configs for each connecting network
-}
-
-// StartContainer starts a container, returning an error in case of failure.
-//
-// See https://goo.gl/MrBAJv for more details.
-func (c *Client) StartContainer(id string, hostConfig *HostConfig) error {
- path := "/containers/" + id + "/start"
- resp, err := c.do("POST", path, doOptions{data: hostConfig, forceJSON: true})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: id, Err: err}
- }
- return err
- }
- if resp.StatusCode == http.StatusNotModified {
- return &ContainerAlreadyRunning{ID: id}
- }
- resp.Body.Close()
- return nil
-}
-
-// StopContainer stops a container, killing it after the given timeout (in
-// seconds).
-//
-// See https://goo.gl/USqsFt for more details.
-func (c *Client) StopContainer(id string, timeout uint) error {
- path := fmt.Sprintf("/containers/%s/stop?t=%d", id, timeout)
- resp, err := c.do("POST", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: id}
- }
- return err
- }
- if resp.StatusCode == http.StatusNotModified {
- return &ContainerNotRunning{ID: id}
- }
- resp.Body.Close()
- return nil
-}
-
-// RestartContainer stops a container, killing it after the given timeout (in
-// seconds), during the stop process.
-//
-// See https://goo.gl/QzsDnz for more details.
-func (c *Client) RestartContainer(id string, timeout uint) error {
- path := fmt.Sprintf("/containers/%s/restart?t=%d", id, timeout)
- resp, err := c.do("POST", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: id}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// PauseContainer pauses the given container.
-//
-// See https://goo.gl/OF7W9X for more details.
-func (c *Client) PauseContainer(id string) error {
- path := fmt.Sprintf("/containers/%s/pause", id)
- resp, err := c.do("POST", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: id}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// UnpauseContainer unpauses the given container.
-//
-// See https://goo.gl/7dwyPA for more details.
-func (c *Client) UnpauseContainer(id string) error {
- path := fmt.Sprintf("/containers/%s/unpause", id)
- resp, err := c.do("POST", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: id}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// TopResult represents the list of processes running in a container, as
-// returned by /containers//top.
-//
-// See https://goo.gl/Rb46aY for more details.
-type TopResult struct {
- Titles []string
- Processes [][]string
-}
-
-// TopContainer returns processes running inside a container
-//
-// See https://goo.gl/Rb46aY for more details.
-func (c *Client) TopContainer(id string, psArgs string) (TopResult, error) {
- var args string
- var result TopResult
- if psArgs != "" {
- args = fmt.Sprintf("?ps_args=%s", psArgs)
- }
- path := fmt.Sprintf("/containers/%s/top%s", id, args)
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return result, &NoSuchContainer{ID: id}
- }
- return result, err
- }
- defer resp.Body.Close()
- if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
- return result, err
- }
- return result, nil
-}
-
-// Stats represents container statistics, returned by /containers//stats.
-//
-// See https://goo.gl/GNmLHb for more details.
-type Stats struct {
- Read time.Time `json:"read,omitempty" yaml:"read,omitempty"`
- PidsStats struct {
- Current uint64 `json:"current,omitempty" yaml:"current,omitempty"`
- } `json:"pids_stats,omitempty" yaml:"pids_stats,omitempty"`
- Network NetworkStats `json:"network,omitempty" yaml:"network,omitempty"`
- Networks map[string]NetworkStats `json:"networks,omitempty" yaml:"networks,omitempty"`
- MemoryStats struct {
- Stats struct {
- TotalPgmafault uint64 `json:"total_pgmafault,omitempty" yaml:"total_pgmafault,omitempty"`
- Cache uint64 `json:"cache,omitempty" yaml:"cache,omitempty"`
- MappedFile uint64 `json:"mapped_file,omitempty" yaml:"mapped_file,omitempty"`
- TotalInactiveFile uint64 `json:"total_inactive_file,omitempty" yaml:"total_inactive_file,omitempty"`
- Pgpgout uint64 `json:"pgpgout,omitempty" yaml:"pgpgout,omitempty"`
- Rss uint64 `json:"rss,omitempty" yaml:"rss,omitempty"`
- TotalMappedFile uint64 `json:"total_mapped_file,omitempty" yaml:"total_mapped_file,omitempty"`
- Writeback uint64 `json:"writeback,omitempty" yaml:"writeback,omitempty"`
- Unevictable uint64 `json:"unevictable,omitempty" yaml:"unevictable,omitempty"`
- Pgpgin uint64 `json:"pgpgin,omitempty" yaml:"pgpgin,omitempty"`
- TotalUnevictable uint64 `json:"total_unevictable,omitempty" yaml:"total_unevictable,omitempty"`
- Pgmajfault uint64 `json:"pgmajfault,omitempty" yaml:"pgmajfault,omitempty"`
- TotalRss uint64 `json:"total_rss,omitempty" yaml:"total_rss,omitempty"`
- TotalRssHuge uint64 `json:"total_rss_huge,omitempty" yaml:"total_rss_huge,omitempty"`
- TotalWriteback uint64 `json:"total_writeback,omitempty" yaml:"total_writeback,omitempty"`
- TotalInactiveAnon uint64 `json:"total_inactive_anon,omitempty" yaml:"total_inactive_anon,omitempty"`
- RssHuge uint64 `json:"rss_huge,omitempty" yaml:"rss_huge,omitempty"`
- HierarchicalMemoryLimit uint64 `json:"hierarchical_memory_limit,omitempty" yaml:"hierarchical_memory_limit,omitempty"`
- TotalPgfault uint64 `json:"total_pgfault,omitempty" yaml:"total_pgfault,omitempty"`
- TotalActiveFile uint64 `json:"total_active_file,omitempty" yaml:"total_active_file,omitempty"`
- ActiveAnon uint64 `json:"active_anon,omitempty" yaml:"active_anon,omitempty"`
- TotalActiveAnon uint64 `json:"total_active_anon,omitempty" yaml:"total_active_anon,omitempty"`
- TotalPgpgout uint64 `json:"total_pgpgout,omitempty" yaml:"total_pgpgout,omitempty"`
- TotalCache uint64 `json:"total_cache,omitempty" yaml:"total_cache,omitempty"`
- InactiveAnon uint64 `json:"inactive_anon,omitempty" yaml:"inactive_anon,omitempty"`
- ActiveFile uint64 `json:"active_file,omitempty" yaml:"active_file,omitempty"`
- Pgfault uint64 `json:"pgfault,omitempty" yaml:"pgfault,omitempty"`
- InactiveFile uint64 `json:"inactive_file,omitempty" yaml:"inactive_file,omitempty"`
- TotalPgpgin uint64 `json:"total_pgpgin,omitempty" yaml:"total_pgpgin,omitempty"`
- HierarchicalMemswLimit uint64 `json:"hierarchical_memsw_limit,omitempty" yaml:"hierarchical_memsw_limit,omitempty"`
- Swap uint64 `json:"swap,omitempty" yaml:"swap,omitempty"`
- } `json:"stats,omitempty" yaml:"stats,omitempty"`
- MaxUsage uint64 `json:"max_usage,omitempty" yaml:"max_usage,omitempty"`
- Usage uint64 `json:"usage,omitempty" yaml:"usage,omitempty"`
- Failcnt uint64 `json:"failcnt,omitempty" yaml:"failcnt,omitempty"`
- Limit uint64 `json:"limit,omitempty" yaml:"limit,omitempty"`
- } `json:"memory_stats,omitempty" yaml:"memory_stats,omitempty"`
- BlkioStats struct {
- IOServiceBytesRecursive []BlkioStatsEntry `json:"io_service_bytes_recursive,omitempty" yaml:"io_service_bytes_recursive,omitempty"`
- IOServicedRecursive []BlkioStatsEntry `json:"io_serviced_recursive,omitempty" yaml:"io_serviced_recursive,omitempty"`
- IOQueueRecursive []BlkioStatsEntry `json:"io_queue_recursive,omitempty" yaml:"io_queue_recursive,omitempty"`
- IOServiceTimeRecursive []BlkioStatsEntry `json:"io_service_time_recursive,omitempty" yaml:"io_service_time_recursive,omitempty"`
- IOWaitTimeRecursive []BlkioStatsEntry `json:"io_wait_time_recursive,omitempty" yaml:"io_wait_time_recursive,omitempty"`
- IOMergedRecursive []BlkioStatsEntry `json:"io_merged_recursive,omitempty" yaml:"io_merged_recursive,omitempty"`
- IOTimeRecursive []BlkioStatsEntry `json:"io_time_recursive,omitempty" yaml:"io_time_recursive,omitempty"`
- SectorsRecursive []BlkioStatsEntry `json:"sectors_recursive,omitempty" yaml:"sectors_recursive,omitempty"`
- } `json:"blkio_stats,omitempty" yaml:"blkio_stats,omitempty"`
- CPUStats CPUStats `json:"cpu_stats,omitempty" yaml:"cpu_stats,omitempty"`
- PreCPUStats CPUStats `json:"precpu_stats,omitempty"`
-}
-
-// NetworkStats is a stats entry for network stats
-type NetworkStats struct {
- RxDropped uint64 `json:"rx_dropped,omitempty" yaml:"rx_dropped,omitempty"`
- RxBytes uint64 `json:"rx_bytes,omitempty" yaml:"rx_bytes,omitempty"`
- RxErrors uint64 `json:"rx_errors,omitempty" yaml:"rx_errors,omitempty"`
- TxPackets uint64 `json:"tx_packets,omitempty" yaml:"tx_packets,omitempty"`
- TxDropped uint64 `json:"tx_dropped,omitempty" yaml:"tx_dropped,omitempty"`
- RxPackets uint64 `json:"rx_packets,omitempty" yaml:"rx_packets,omitempty"`
- TxErrors uint64 `json:"tx_errors,omitempty" yaml:"tx_errors,omitempty"`
- TxBytes uint64 `json:"tx_bytes,omitempty" yaml:"tx_bytes,omitempty"`
-}
-
-// CPUStats is a stats entry for cpu stats
-type CPUStats struct {
- CPUUsage struct {
- PercpuUsage []uint64 `json:"percpu_usage,omitempty" yaml:"percpu_usage,omitempty"`
- UsageInUsermode uint64 `json:"usage_in_usermode,omitempty" yaml:"usage_in_usermode,omitempty"`
- TotalUsage uint64 `json:"total_usage,omitempty" yaml:"total_usage,omitempty"`
- UsageInKernelmode uint64 `json:"usage_in_kernelmode,omitempty" yaml:"usage_in_kernelmode,omitempty"`
- } `json:"cpu_usage,omitempty" yaml:"cpu_usage,omitempty"`
- SystemCPUUsage uint64 `json:"system_cpu_usage,omitempty" yaml:"system_cpu_usage,omitempty"`
- ThrottlingData struct {
- Periods uint64 `json:"periods,omitempty"`
- ThrottledPeriods uint64 `json:"throttled_periods,omitempty"`
- ThrottledTime uint64 `json:"throttled_time,omitempty"`
- } `json:"throttling_data,omitempty" yaml:"throttling_data,omitempty"`
-}
-
-// BlkioStatsEntry is a stats entry for blkio_stats
-type BlkioStatsEntry struct {
- Major uint64 `json:"major,omitempty" yaml:"major,omitempty"`
- Minor uint64 `json:"minor,omitempty" yaml:"minor,omitempty"`
- Op string `json:"op,omitempty" yaml:"op,omitempty"`
- Value uint64 `json:"value,omitempty" yaml:"value,omitempty"`
-}
-
-// StatsOptions specify parameters to the Stats function.
-//
-// See https://goo.gl/GNmLHb for more details.
-type StatsOptions struct {
- ID string
- Stats chan<- *Stats
- Stream bool
- // A flag that enables stopping the stats operation
- Done <-chan bool
- // Initial connection timeout
- Timeout time.Duration
- // Timeout with no data is received, it's reset every time new data
- // arrives
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// Stats sends container statistics for the given container to the given channel.
-//
-// This function is blocking, similar to a streaming call for logs, and should be run
-// on a separate goroutine from the caller. Note that this function will block until
-// the given container is removed, not just exited. When finished, this function
-// will close the given channel. Alternatively, function can be stopped by
-// signaling on the Done channel.
-//
-// See https://goo.gl/GNmLHb for more details.
-func (c *Client) Stats(opts StatsOptions) (retErr error) {
- errC := make(chan error, 1)
- readCloser, writeCloser := io.Pipe()
-
- defer func() {
- close(opts.Stats)
-
- select {
- case err := <-errC:
- if err != nil && retErr == nil {
- retErr = err
- }
- default:
- // No errors
- }
-
- if err := readCloser.Close(); err != nil && retErr == nil {
- retErr = err
- }
- }()
-
- go func() {
- err := c.stream("GET", fmt.Sprintf("/containers/%s/stats?stream=%v", opts.ID, opts.Stream), streamOptions{
- rawJSONStream: true,
- useJSONDecoder: true,
- stdout: writeCloser,
- timeout: opts.Timeout,
- inactivityTimeout: opts.InactivityTimeout,
- })
- if err != nil {
- dockerError, ok := err.(*Error)
- if ok {
- if dockerError.Status == http.StatusNotFound {
- err = &NoSuchContainer{ID: opts.ID}
- }
- }
- }
- if closeErr := writeCloser.Close(); closeErr != nil && err == nil {
- err = closeErr
- }
- errC <- err
- close(errC)
- }()
-
- quit := make(chan struct{})
- defer close(quit)
- go func() {
- // block here waiting for the signal to stop function
- select {
- case <-opts.Done:
- readCloser.Close()
- case <-quit:
- return
- }
- }()
-
- decoder := json.NewDecoder(readCloser)
- stats := new(Stats)
- for err := decoder.Decode(stats); err != io.EOF; err = decoder.Decode(stats) {
- if err != nil {
- return err
- }
- opts.Stats <- stats
- stats = new(Stats)
- }
- return nil
-}
-
-// KillContainerOptions represents the set of options that can be used in a
-// call to KillContainer.
-//
-// See https://goo.gl/hkS9i8 for more details.
-type KillContainerOptions struct {
- // The ID of the container.
- ID string `qs:"-"`
-
- // The signal to send to the container. When omitted, Docker server
- // will assume SIGKILL.
- Signal Signal
-}
-
-// KillContainer sends a signal to a container, returning an error in case of
-// failure.
-//
-// See https://goo.gl/hkS9i8 for more details.
-func (c *Client) KillContainer(opts KillContainerOptions) error {
- path := "/containers/" + opts.ID + "/kill" + "?" + queryString(opts)
- resp, err := c.do("POST", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: opts.ID}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// RemoveContainerOptions encapsulates options to remove a container.
-//
-// See https://goo.gl/RQyX62 for more details.
-type RemoveContainerOptions struct {
- // The ID of the container.
- ID string `qs:"-"`
-
- // A flag that indicates whether Docker should remove the volumes
- // associated to the container.
- RemoveVolumes bool `qs:"v"`
-
- // A flag that indicates whether Docker should remove the container
- // even if it is currently running.
- Force bool
-}
-
-// RemoveContainer removes a container, returning an error in case of failure.
-//
-// See https://goo.gl/RQyX62 for more details.
-func (c *Client) RemoveContainer(opts RemoveContainerOptions) error {
- path := "/containers/" + opts.ID + "?" + queryString(opts)
- resp, err := c.do("DELETE", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: opts.ID}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// UploadToContainerOptions is the set of options that can be used when
-// uploading an archive into a container.
-//
-// See https://goo.gl/Ss97HW for more details.
-type UploadToContainerOptions struct {
- InputStream io.Reader `json:"-" qs:"-"`
- Path string `qs:"path"`
- NoOverwriteDirNonDir bool `qs:"noOverwriteDirNonDir"`
-}
-
-// UploadToContainer uploads a tar archive to be extracted to a path in the
-// filesystem of the container.
-//
-// See https://goo.gl/Ss97HW for more details.
-func (c *Client) UploadToContainer(id string, opts UploadToContainerOptions) error {
- url := fmt.Sprintf("/containers/%s/archive?", id) + queryString(opts)
-
- return c.stream("PUT", url, streamOptions{
- in: opts.InputStream,
- })
-}
-
-// DownloadFromContainerOptions is the set of options that can be used when
-// downloading resources from a container.
-//
-// See https://goo.gl/KnZJDX for more details.
-type DownloadFromContainerOptions struct {
- OutputStream io.Writer `json:"-" qs:"-"`
- Path string `qs:"path"`
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// DownloadFromContainer downloads a tar archive of files or folders in a container.
-//
-// See https://goo.gl/KnZJDX for more details.
-func (c *Client) DownloadFromContainer(id string, opts DownloadFromContainerOptions) error {
- url := fmt.Sprintf("/containers/%s/archive?", id) + queryString(opts)
-
- return c.stream("GET", url, streamOptions{
- setRawTerminal: true,
- stdout: opts.OutputStream,
- inactivityTimeout: opts.InactivityTimeout,
- })
-}
-
-// CopyFromContainerOptions has been DEPRECATED, please use DownloadFromContainerOptions along with DownloadFromContainer.
-//
-// See https://goo.gl/R2jevW for more details.
-type CopyFromContainerOptions struct {
- OutputStream io.Writer `json:"-"`
- Container string `json:"-"`
- Resource string
-}
-
-// CopyFromContainer has been DEPRECATED, please use DownloadFromContainerOptions along with DownloadFromContainer.
-//
-// See https://goo.gl/R2jevW for more details.
-func (c *Client) CopyFromContainer(opts CopyFromContainerOptions) error {
- if opts.Container == "" {
- return &NoSuchContainer{ID: opts.Container}
- }
- url := fmt.Sprintf("/containers/%s/copy", opts.Container)
- resp, err := c.do("POST", url, doOptions{data: opts})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchContainer{ID: opts.Container}
- }
- return err
- }
- defer resp.Body.Close()
- _, err = io.Copy(opts.OutputStream, resp.Body)
- return err
-}
-
-// WaitContainer blocks until the given container stops, return the exit code
-// of the container status.
-//
-// See https://goo.gl/Gc1rge for more details.
-func (c *Client) WaitContainer(id string) (int, error) {
- resp, err := c.do("POST", "/containers/"+id+"/wait", doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return 0, &NoSuchContainer{ID: id}
- }
- return 0, err
- }
- defer resp.Body.Close()
- var r struct{ StatusCode int }
- if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
- return 0, err
- }
- return r.StatusCode, nil
-}
-
-// CommitContainerOptions aggregates parameters to the CommitContainer method.
-//
-// See https://goo.gl/mqfoCw for more details.
-type CommitContainerOptions struct {
- Container string
- Repository string `qs:"repo"`
- Tag string
- Message string `qs:"comment"`
- Author string
- Run *Config `qs:"-"`
-}
-
-// CommitContainer creates a new image from a container's changes.
-//
-// See https://goo.gl/mqfoCw for more details.
-func (c *Client) CommitContainer(opts CommitContainerOptions) (*Image, error) {
- path := "/commit?" + queryString(opts)
- resp, err := c.do("POST", path, doOptions{data: opts.Run})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, &NoSuchContainer{ID: opts.Container}
- }
- return nil, err
- }
- defer resp.Body.Close()
- var image Image
- if err := json.NewDecoder(resp.Body).Decode(&image); err != nil {
- return nil, err
- }
- return &image, nil
-}
-
-// AttachToContainerOptions is the set of options that can be used when
-// attaching to a container.
-//
-// See https://goo.gl/NKpkFk for more details.
-type AttachToContainerOptions struct {
- Container string `qs:"-"`
- InputStream io.Reader `qs:"-"`
- OutputStream io.Writer `qs:"-"`
- ErrorStream io.Writer `qs:"-"`
-
- // Get container logs, sending it to OutputStream.
- Logs bool
-
- // Stream the response?
- Stream bool
-
- // Attach to stdin, and use InputStream.
- Stdin bool
-
- // Attach to stdout, and use OutputStream.
- Stdout bool
-
- // Attach to stderr, and use ErrorStream.
- Stderr bool
-
- // If set, after a successful connect, a sentinel will be sent and then the
- // client will block on receive before continuing.
- //
- // It must be an unbuffered channel. Using a buffered channel can lead
- // to unexpected behavior.
- Success chan struct{}
-
- // Use raw terminal? Usually true when the container contains a TTY.
- RawTerminal bool `qs:"-"`
-}
-
-// AttachToContainer attaches to a container, using the given options.
-//
-// See https://goo.gl/NKpkFk for more details.
-func (c *Client) AttachToContainer(opts AttachToContainerOptions) error {
- cw, err := c.AttachToContainerNonBlocking(opts)
- if err != nil {
- return err
- }
- return cw.Wait()
-}
-
-// AttachToContainerNonBlocking attaches to a container, using the given options.
-// This function does not block.
-//
-// See https://goo.gl/NKpkFk for more details.
-func (c *Client) AttachToContainerNonBlocking(opts AttachToContainerOptions) (CloseWaiter, error) {
- if opts.Container == "" {
- return nil, &NoSuchContainer{ID: opts.Container}
- }
- path := "/containers/" + opts.Container + "/attach?" + queryString(opts)
- return c.hijack("POST", path, hijackOptions{
- success: opts.Success,
- setRawTerminal: opts.RawTerminal,
- in: opts.InputStream,
- stdout: opts.OutputStream,
- stderr: opts.ErrorStream,
- })
-}
-
-// LogsOptions represents the set of options used when getting logs from a
-// container.
-//
-// See https://goo.gl/yl8PGm for more details.
-type LogsOptions struct {
- Container string `qs:"-"`
- OutputStream io.Writer `qs:"-"`
- ErrorStream io.Writer `qs:"-"`
- InactivityTimeout time.Duration `qs:"-"`
- Follow bool
- Stdout bool
- Stderr bool
- Since int64
- Timestamps bool
- Tail string
-
- // Use raw terminal? Usually true when the container contains a TTY.
- RawTerminal bool `qs:"-"`
-}
-
-// Logs gets stdout and stderr logs from the specified container.
-//
-// See https://goo.gl/yl8PGm for more details.
-func (c *Client) Logs(opts LogsOptions) error {
- if opts.Container == "" {
- return &NoSuchContainer{ID: opts.Container}
- }
- if opts.Tail == "" {
- opts.Tail = "all"
- }
- path := "/containers/" + opts.Container + "/logs?" + queryString(opts)
- return c.stream("GET", path, streamOptions{
- setRawTerminal: opts.RawTerminal,
- stdout: opts.OutputStream,
- stderr: opts.ErrorStream,
- inactivityTimeout: opts.InactivityTimeout,
- })
-}
-
-// ResizeContainerTTY resizes the terminal to the given height and width.
-//
-// See https://goo.gl/xERhCc for more details.
-func (c *Client) ResizeContainerTTY(id string, height, width int) error {
- params := make(url.Values)
- params.Set("h", strconv.Itoa(height))
- params.Set("w", strconv.Itoa(width))
- resp, err := c.do("POST", "/containers/"+id+"/resize?"+params.Encode(), doOptions{})
- if err != nil {
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// ExportContainerOptions is the set of parameters to the ExportContainer
-// method.
-//
-// See https://goo.gl/dOkTyk for more details.
-type ExportContainerOptions struct {
- ID string
- OutputStream io.Writer
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// ExportContainer export the contents of container id as tar archive
-// and prints the exported contents to stdout.
-//
-// See https://goo.gl/dOkTyk for more details.
-func (c *Client) ExportContainer(opts ExportContainerOptions) error {
- if opts.ID == "" {
- return &NoSuchContainer{ID: opts.ID}
- }
- url := fmt.Sprintf("/containers/%s/export", opts.ID)
- return c.stream("GET", url, streamOptions{
- setRawTerminal: true,
- stdout: opts.OutputStream,
- inactivityTimeout: opts.InactivityTimeout,
- })
-}
-
-// NoSuchContainer is the error returned when a given container does not exist.
-type NoSuchContainer struct {
- ID string
- Err error
-}
-
-func (err *NoSuchContainer) Error() string {
- if err.Err != nil {
- return err.Err.Error()
- }
- return "No such container: " + err.ID
-}
-
-// ContainerAlreadyRunning is the error returned when a given container is
-// already running.
-type ContainerAlreadyRunning struct {
- ID string
-}
-
-func (err *ContainerAlreadyRunning) Error() string {
- return "Container already running: " + err.ID
-}
-
-// ContainerNotRunning is the error returned when a given container is not
-// running.
-type ContainerNotRunning struct {
- ID string
-}
-
-func (err *ContainerNotRunning) Error() string {
- return "Container not running: " + err.ID
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/container_test.go b/vendor/github.com/fsouza/go-dockerclient/container_test.go
deleted file mode 100644
index 9d6c908..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/container_test.go
+++ /dev/null
@@ -1,2365 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bufio"
- "bytes"
- "encoding/json"
- "errors"
- "io/ioutil"
- "net"
- "net/http"
- "net/http/httptest"
- "net/url"
- "os"
- "reflect"
- "strconv"
- "strings"
- "testing"
- "time"
-
- "github.com/hashicorp/go-cleanhttp"
-)
-
-func TestStateString(t *testing.T) {
- started := time.Now().Add(-3 * time.Hour)
- var tests = []struct {
- input State
- expected string
- }{
- {State{Running: true, Paused: true, StartedAt: started}, "Up 3 hours (Paused)"},
- {State{Running: true, Restarting: true, ExitCode: 7, FinishedAt: started}, "Restarting (7) 3 hours ago"},
- {State{Running: true, StartedAt: started}, "Up 3 hours"},
- {State{RemovalInProgress: true}, "Removal In Progress"},
- {State{Dead: true}, "Dead"},
- {State{}, "Created"},
- {State{StartedAt: started}, ""},
- {State{ExitCode: 7, StartedAt: started, FinishedAt: started}, "Exited (7) 3 hours ago"},
- }
- for _, tt := range tests {
- if got := tt.input.String(); got != tt.expected {
- t.Errorf("State.String(): wrong result. Want %q. Got %q.", tt.expected, got)
- }
- }
-}
-
-func TestStateStateString(t *testing.T) {
- started := time.Now().Add(-3 * time.Hour)
- var tests = []struct {
- input State
- expected string
- }{
- {State{Running: true, Paused: true}, "paused"},
- {State{Running: true, Restarting: true}, "restarting"},
- {State{Running: true}, "running"},
- {State{Dead: true}, "dead"},
- {State{}, "created"},
- {State{StartedAt: started}, "exited"},
- }
- for _, tt := range tests {
- if got := tt.input.StateString(); got != tt.expected {
- t.Errorf("State.String(): wrong result. Want %q. Got %q.", tt.expected, got)
- }
- }
-}
-
-func TestListContainers(t *testing.T) {
- jsonContainers := `[
- {
- "Id": "8dfafdbc3a40",
- "Image": "base:latest",
- "Command": "echo 1",
- "Created": 1367854155,
- "Ports":[{"PrivatePort": 2222, "PublicPort": 3333, "Type": "tcp"}],
- "Status": "Exit 0"
- },
- {
- "Id": "9cd87474be90",
- "Image": "base:latest",
- "Command": "echo 222222",
- "Created": 1367854155,
- "Ports":[{"PrivatePort": 2222, "PublicPort": 3333, "Type": "tcp"}],
- "Status": "Exit 0"
- },
- {
- "Id": "3176a2479c92",
- "Image": "base:latest",
- "Command": "echo 3333333333333333",
- "Created": 1367854154,
- "Ports":[{"PrivatePort": 2221, "PublicPort": 3331, "Type": "tcp"}],
- "Status": "Exit 0"
- },
- {
- "Id": "4cb07b47f9fb",
- "Image": "base:latest",
- "Command": "echo 444444444444444444444444444444444",
- "Ports":[{"PrivatePort": 2223, "PublicPort": 3332, "Type": "tcp"}],
- "Created": 1367854152,
- "Status": "Exit 0"
- }
-]`
- var expected []APIContainers
- err := json.Unmarshal([]byte(jsonContainers), &expected)
- if err != nil {
- t.Fatal(err)
- }
- client := newTestClient(&FakeRoundTripper{message: jsonContainers, status: http.StatusOK})
- containers, err := client.ListContainers(ListContainersOptions{})
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(containers, expected) {
- t.Errorf("ListContainers: Expected %#v. Got %#v.", expected, containers)
- }
-}
-
-func TestListContainersParams(t *testing.T) {
- var tests = []struct {
- input ListContainersOptions
- params map[string][]string
- }{
- {ListContainersOptions{}, map[string][]string{}},
- {ListContainersOptions{All: true}, map[string][]string{"all": {"1"}}},
- {ListContainersOptions{All: true, Limit: 10}, map[string][]string{"all": {"1"}, "limit": {"10"}}},
- {
- ListContainersOptions{All: true, Limit: 10, Since: "adf9983", Before: "abdeef"},
- map[string][]string{"all": {"1"}, "limit": {"10"}, "since": {"adf9983"}, "before": {"abdeef"}},
- },
- {
- ListContainersOptions{Filters: map[string][]string{"status": {"paused", "running"}}},
- map[string][]string{"filters": {"{\"status\":[\"paused\",\"running\"]}"}},
- },
- {
- ListContainersOptions{All: true, Filters: map[string][]string{"exited": {"0"}, "status": {"exited"}}},
- map[string][]string{"all": {"1"}, "filters": {"{\"exited\":[\"0\"],\"status\":[\"exited\"]}"}},
- },
- }
- fakeRT := &FakeRoundTripper{message: "[]", status: http.StatusOK}
- client := newTestClient(fakeRT)
- u, _ := url.Parse(client.getURL("/containers/json"))
- for _, tt := range tests {
- if _, err := client.ListContainers(tt.input); err != nil {
- t.Error(err)
- }
- got := map[string][]string(fakeRT.requests[0].URL.Query())
- if !reflect.DeepEqual(got, tt.params) {
- t.Errorf("Expected %#v, got %#v.", tt.params, got)
- }
- if path := fakeRT.requests[0].URL.Path; path != u.Path {
- t.Errorf("Wrong path on request. Want %q. Got %q.", u.Path, path)
- }
- if meth := fakeRT.requests[0].Method; meth != "GET" {
- t.Errorf("Wrong HTTP method. Want GET. Got %s.", meth)
- }
- fakeRT.Reset()
- }
-}
-
-func TestListContainersFailure(t *testing.T) {
- var tests = []struct {
- status int
- message string
- }{
- {400, "bad parameter"},
- {500, "internal server error"},
- }
- for _, tt := range tests {
- client := newTestClient(&FakeRoundTripper{message: tt.message, status: tt.status})
- expected := Error{Status: tt.status, Message: tt.message}
- containers, err := client.ListContainers(ListContainersOptions{})
- if !reflect.DeepEqual(expected, *err.(*Error)) {
- t.Errorf("Wrong error in ListContainers. Want %#v. Got %#v.", expected, err)
- }
- if len(containers) > 0 {
- t.Errorf("ListContainers failure. Expected empty list. Got %#v.", containers)
- }
- }
-}
-
-func TestInspectContainer(t *testing.T) {
- jsonContainer := `{
- "Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2",
- "AppArmorProfile": "Profile",
- "Created": "2013-05-07T14:51:42.087658+02:00",
- "Path": "date",
- "Args": [],
- "Config": {
- "Hostname": "4fa6e0f0c678",
- "User": "",
- "Memory": 17179869184,
- "MemorySwap": 34359738368,
- "AttachStdin": false,
- "AttachStdout": true,
- "AttachStderr": true,
- "PortSpecs": null,
- "Tty": false,
- "OpenStdin": false,
- "StdinOnce": false,
- "Env": null,
- "Cmd": [
- "date"
- ],
- "Image": "base",
- "Volumes": {},
- "VolumesFrom": "",
- "SecurityOpt": [
- "label:user:USER"
- ],
- "Ulimits": [
- { "Name": "nofile", "Soft": 1024, "Hard": 2048 }
- ]
- },
- "State": {
- "Running": false,
- "Pid": 0,
- "ExitCode": 0,
- "StartedAt": "2013-05-07T14:51:42.087658+02:00",
- "Ghost": false
- },
- "Node": {
- "ID": "4I4E:QR4I:Z733:QEZK:5X44:Q4T7:W2DD:JRDY:KB2O:PODO:Z5SR:XRB6",
- "IP": "192.168.99.105",
- "Addra": "192.168.99.105:2376",
- "Name": "node-01",
- "Cpus": 4,
- "Memory": 1048436736,
- "Labels": {
- "executiondriver": "native-0.2",
- "kernelversion": "3.18.5-tinycore64",
- "operatingsystem": "Boot2Docker 1.5.0 (TCL 5.4); master : a66bce5 - Tue Feb 10 23:31:27 UTC 2015",
- "provider": "virtualbox",
- "storagedriver": "aufs"
- }
- },
- "Image": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
- "NetworkSettings": {
- "IpAddress": "",
- "IpPrefixLen": 0,
- "Gateway": "",
- "Bridge": "",
- "PortMapping": null
- },
- "SysInitPath": "/home/kitty/go/src/github.com/dotcloud/docker/bin/docker",
- "ResolvConfPath": "/etc/resolv.conf",
- "Volumes": {},
- "HostConfig": {
- "Binds": null,
- "ContainerIDFile": "",
- "LxcConf": [],
- "Privileged": false,
- "PortBindings": {
- "80/tcp": [
- {
- "HostIp": "0.0.0.0",
- "HostPort": "49153"
- }
- ]
- },
- "Links": null,
- "PublishAllPorts": false,
- "CgroupParent": "/mesos",
- "Memory": 17179869184,
- "MemorySwap": 34359738368,
- "GroupAdd": ["fake", "12345"],
- "OomScoreAdj": 642
- }
-}`
- var expected Container
- err := json.Unmarshal([]byte(jsonContainer), &expected)
- if err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: jsonContainer, status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c678"
- container, err := client.InspectContainer(id)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(*container, expected) {
- t.Errorf("InspectContainer(%q): Expected %#v. Got %#v.", id, expected, container)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/4fa6e0f0c678/json"))
- if gotPath := fakeRT.requests[0].URL.Path; gotPath != expectedURL.Path {
- t.Errorf("InspectContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestInspectContainerNetwork(t *testing.T) {
- jsonContainer := `{
- "Id": "81e1bbe20b5508349e1c804eb08b7b6ca8366751dbea9f578b3ea0773fa66c1c",
- "Created": "2015-11-12T14:54:04.791485659Z",
- "Path": "consul-template",
- "Args": [
- "-config=/tmp/haproxy.json",
- "-consul=192.168.99.120:8500"
- ],
- "State": {
- "Status": "running",
- "Running": true,
- "Paused": false,
- "Restarting": false,
- "OOMKilled": false,
- "Dead": false,
- "Pid": 3196,
- "ExitCode": 0,
- "Error": "",
- "StartedAt": "2015-11-12T14:54:05.026747471Z",
- "FinishedAt": "0001-01-01T00:00:00Z"
- },
- "Image": "4921c5917fc117df3dec32f4c1976635dc6c56ccd3336fe1db3477f950e78bf7",
- "ResolvConfPath": "/mnt/sda1/var/lib/docker/containers/81e1bbe20b5508349e1c804eb08b7b6ca8366751dbea9f578b3ea0773fa66c1c/resolv.conf",
- "HostnamePath": "/mnt/sda1/var/lib/docker/containers/81e1bbe20b5508349e1c804eb08b7b6ca8366751dbea9f578b3ea0773fa66c1c/hostname",
- "HostsPath": "/mnt/sda1/var/lib/docker/containers/81e1bbe20b5508349e1c804eb08b7b6ca8366751dbea9f578b3ea0773fa66c1c/hosts",
- "LogPath": "/mnt/sda1/var/lib/docker/containers/81e1bbe20b5508349e1c804eb08b7b6ca8366751dbea9f578b3ea0773fa66c1c/81e1bbe20b5508349e1c804eb08b7b6ca8366751dbea9f578b3ea0773fa66c1c-json.log",
- "Node": {
- "ID": "AUIB:LFOT:3LSF:SCFS:OYDQ:NLXD:JZNE:4INI:3DRC:ZFBB:GWCY:DWJK",
- "IP": "192.168.99.121",
- "Addr": "192.168.99.121:2376",
- "Name": "swl-demo1",
- "Cpus": 1,
- "Memory": 2099945472,
- "Labels": {
- "executiondriver": "native-0.2",
- "kernelversion": "4.1.12-boot2docker",
- "operatingsystem": "Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov 3 19:49:22 UTC 2015",
- "provider": "virtualbox",
- "storagedriver": "aufs"
- }
- },
- "Name": "/docker-proxy.swl-demo1",
- "RestartCount": 0,
- "Driver": "aufs",
- "ExecDriver": "native-0.2",
- "MountLabel": "",
- "ProcessLabel": "",
- "AppArmorProfile": "",
- "ExecIDs": null,
- "HostConfig": {
- "Binds": null,
- "ContainerIDFile": "",
- "LxcConf": [],
- "Memory": 0,
- "MemoryReservation": 0,
- "MemorySwap": 0,
- "KernelMemory": 0,
- "CpuShares": 0,
- "CpuPeriod": 0,
- "CpusetCpus": "",
- "CpusetMems": "",
- "CpuQuota": 0,
- "BlkioWeight": 0,
- "OomKillDisable": false,
- "MemorySwappiness": -1,
- "Privileged": false,
- "PortBindings": {
- "443/tcp": [
- {
- "HostIp": "",
- "HostPort": "443"
- }
- ]
- },
- "Links": null,
- "PublishAllPorts": false,
- "Dns": null,
- "DnsOptions": null,
- "DnsSearch": null,
- "ExtraHosts": null,
- "VolumesFrom": null,
- "Devices": [],
- "NetworkMode": "swl-net",
- "IpcMode": "",
- "PidMode": "",
- "UTSMode": "",
- "CapAdd": null,
- "CapDrop": null,
- "GroupAdd": null,
- "RestartPolicy": {
- "Name": "no",
- "MaximumRetryCount": 0
- },
- "SecurityOpt": null,
- "ReadonlyRootfs": false,
- "Ulimits": null,
- "LogConfig": {
- "Type": "json-file",
- "Config": {}
- },
- "CgroupParent": "",
- "ConsoleSize": [
- 0,
- 0
- ],
- "VolumeDriver": ""
- },
- "GraphDriver": {
- "Name": "aufs",
- "Data": null
- },
- "Mounts": [],
- "Config": {
- "Hostname": "81e1bbe20b55",
- "Domainname": "",
- "User": "",
- "AttachStdin": false,
- "AttachStdout": false,
- "AttachStderr": false,
- "ExposedPorts": {
- "443/tcp": {}
- },
- "Tty": false,
- "OpenStdin": false,
- "StdinOnce": false,
- "Env": [
- "DOMAIN=local.auto",
- "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
- "CONSUL_TEMPLATE_VERSION=0.11.1"
- ],
- "Cmd": [
- "-consul=192.168.99.120:8500"
- ],
- "Image": "docker-proxy:latest",
- "Volumes": null,
- "WorkingDir": "",
- "Entrypoint": [
- "consul-template",
- "-config=/tmp/haproxy.json"
- ],
- "OnBuild": null,
- "Labels": {},
- "StopSignal": "SIGTERM"
- },
- "NetworkSettings": {
- "Bridge": "",
- "SandboxID": "c6b903dc5c1a96113a22dbc44709e30194079bd2d262eea1eb4f38d85821f6e1",
- "HairpinMode": false,
- "LinkLocalIPv6Address": "",
- "LinkLocalIPv6PrefixLen": 0,
- "Ports": {
- "443/tcp": [
- {
- "HostIp": "192.168.99.121",
- "HostPort": "443"
- }
- ]
- },
- "SandboxKey": "/var/run/docker/netns/c6b903dc5c1a",
- "SecondaryIPAddresses": null,
- "SecondaryIPv6Addresses": null,
- "EndpointID": "",
- "Gateway": "",
- "GlobalIPv6Address": "",
- "GlobalIPv6PrefixLen": 0,
- "IPAddress": "",
- "IPPrefixLen": 0,
- "IPv6Gateway": "",
- "MacAddress": "",
- "Networks": {
- "swl-net": {
- "NetworkID": "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
- "EndpointID": "683e3092275782a53c3b0968cc7e3a10f23264022ded9cb20490902f96fc5981",
- "Gateway": "",
- "IPAddress": "10.0.0.3",
- "IPPrefixLen": 24,
- "IPv6Gateway": "",
- "GlobalIPv6Address": "",
- "GlobalIPv6PrefixLen": 0,
- "MacAddress": "02:42:0a:00:00:03"
- }
- }
- }
-}`
-
- fakeRT := &FakeRoundTripper{message: jsonContainer, status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "81e1bbe20b55"
- expIP := "10.0.0.3"
- expNetworkID := "7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812"
-
- container, err := client.InspectContainer(id)
- if err != nil {
- t.Fatal(err)
- }
-
- s := reflect.Indirect(reflect.ValueOf(container.NetworkSettings))
- networks := s.FieldByName("Networks")
- if networks.IsValid() {
- var ip string
- for _, net := range networks.MapKeys() {
- if net.Interface().(string) == container.HostConfig.NetworkMode {
- ip = networks.MapIndex(net).FieldByName("IPAddress").Interface().(string)
- t.Logf("%s %v", net, ip)
- }
- }
- if ip != expIP {
- t.Errorf("InspectContainerNetworks(%q): Expected %#v. Got %#v.", id, expIP, ip)
- }
-
- var networkID string
- for _, net := range networks.MapKeys() {
- if net.Interface().(string) == container.HostConfig.NetworkMode {
- networkID = networks.MapIndex(net).FieldByName("NetworkID").Interface().(string)
- t.Logf("%s %v", net, networkID)
- }
- }
- if networkID != expNetworkID {
- t.Errorf("InspectContainerNetworks(%q): Expected %#v. Got %#v.", id, expNetworkID, networkID)
- }
- } else {
- t.Errorf("InspectContainerNetworks(%q): No method Networks for NetworkSettings", id)
- }
-
-}
-
-func TestInspectContainerNegativeSwap(t *testing.T) {
- jsonContainer := `{
- "Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2",
- "Created": "2013-05-07T14:51:42.087658+02:00",
- "Path": "date",
- "Args": [],
- "Config": {
- "Hostname": "4fa6e0f0c678",
- "User": "",
- "Memory": 17179869184,
- "MemorySwap": -1,
- "AttachStdin": false,
- "AttachStdout": true,
- "AttachStderr": true,
- "PortSpecs": null,
- "Tty": false,
- "OpenStdin": false,
- "StdinOnce": false,
- "Env": null,
- "Cmd": [
- "date"
- ],
- "Image": "base",
- "Volumes": {},
- "VolumesFrom": ""
- },
- "State": {
- "Running": false,
- "Pid": 0,
- "ExitCode": 0,
- "StartedAt": "2013-05-07T14:51:42.087658+02:00",
- "Ghost": false
- },
- "Image": "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
- "NetworkSettings": {
- "IpAddress": "",
- "IpPrefixLen": 0,
- "Gateway": "",
- "Bridge": "",
- "PortMapping": null
- },
- "SysInitPath": "/home/kitty/go/src/github.com/dotcloud/docker/bin/docker",
- "ResolvConfPath": "/etc/resolv.conf",
- "Volumes": {},
- "HostConfig": {
- "Binds": null,
- "ContainerIDFile": "",
- "LxcConf": [],
- "Privileged": false,
- "PortBindings": {
- "80/tcp": [
- {
- "HostIp": "0.0.0.0",
- "HostPort": "49153"
- }
- ]
- },
- "Links": null,
- "PublishAllPorts": false
- }
-}`
- var expected Container
- err := json.Unmarshal([]byte(jsonContainer), &expected)
- if err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: jsonContainer, status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c678"
- container, err := client.InspectContainer(id)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(*container, expected) {
- t.Errorf("InspectContainer(%q): Expected %#v. Got %#v.", id, expected, container)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/4fa6e0f0c678/json"))
- if gotPath := fakeRT.requests[0].URL.Path; gotPath != expectedURL.Path {
- t.Errorf("InspectContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestInspectContainerFailure(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "server error", status: 500})
- expected := Error{Status: 500, Message: "server error"}
- container, err := client.InspectContainer("abe033")
- if container != nil {
- t.Errorf("InspectContainer: Expected container, got %#v", container)
- }
- if !reflect.DeepEqual(expected, *err.(*Error)) {
- t.Errorf("InspectContainer: Wrong error information. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestInspectContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: 404})
- container, err := client.InspectContainer("abe033")
- if container != nil {
- t.Errorf("InspectContainer: Expected container, got %#v", container)
- }
- expected := &NoSuchContainer{ID: "abe033"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("InspectContainer: Wrong error information. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestContainerChanges(t *testing.T) {
- jsonChanges := `[
- {
- "Path":"/dev",
- "Kind":0
- },
- {
- "Path":"/dev/kmsg",
- "Kind":1
- },
- {
- "Path":"/test",
- "Kind":1
- }
-]`
- var expected []Change
- err := json.Unmarshal([]byte(jsonChanges), &expected)
- if err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: jsonChanges, status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c678"
- changes, err := client.ContainerChanges(id)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(changes, expected) {
- t.Errorf("ContainerChanges(%q): Expected %#v. Got %#v.", id, expected, changes)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/4fa6e0f0c678/changes"))
- if gotPath := fakeRT.requests[0].URL.Path; gotPath != expectedURL.Path {
- t.Errorf("ContainerChanges(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestContainerChangesFailure(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "server error", status: 500})
- expected := Error{Status: 500, Message: "server error"}
- changes, err := client.ContainerChanges("abe033")
- if changes != nil {
- t.Errorf("ContainerChanges: Expected changes, got %#v", changes)
- }
- if !reflect.DeepEqual(expected, *err.(*Error)) {
- t.Errorf("ContainerChanges: Wrong error information. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestContainerChangesNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: 404})
- changes, err := client.ContainerChanges("abe033")
- if changes != nil {
- t.Errorf("ContainerChanges: Expected changes, got %#v", changes)
- }
- expected := &NoSuchContainer{ID: "abe033"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("ContainerChanges: Wrong error information. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestCreateContainer(t *testing.T) {
- jsonContainer := `{
- "Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2",
- "Warnings": []
-}`
- var expected Container
- err := json.Unmarshal([]byte(jsonContainer), &expected)
- if err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: jsonContainer, status: http.StatusOK}
- client := newTestClient(fakeRT)
- config := Config{AttachStdout: true, AttachStdin: true}
- opts := CreateContainerOptions{Name: "TestCreateContainer", Config: &config}
- container, err := client.CreateContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- if container.ID != id {
- t.Errorf("CreateContainer: wrong ID. Want %q. Got %q.", id, container.ID)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("CreateContainer: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/create"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("CreateContainer: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
- }
- var gotBody Config
- err = json.NewDecoder(req.Body).Decode(&gotBody)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestCreateContainerImageNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "No such image", status: http.StatusNotFound})
- config := Config{AttachStdout: true, AttachStdin: true}
- container, err := client.CreateContainer(CreateContainerOptions{Config: &config})
- if container != nil {
- t.Errorf("CreateContainer: expected container, got %#v.", container)
- }
- if !reflect.DeepEqual(err, ErrNoSuchImage) {
- t.Errorf("CreateContainer: Wrong error type. Want %#v. Got %#v.", ErrNoSuchImage, err)
- }
-}
-
-func TestCreateContainerDuplicateName(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "No such image", status: http.StatusConflict})
- config := Config{AttachStdout: true, AttachStdin: true}
- container, err := client.CreateContainer(CreateContainerOptions{Config: &config})
- if container != nil {
- t.Errorf("CreateContainer: expected container, got %#v.", container)
- }
- if err != ErrContainerAlreadyExists {
- t.Errorf("CreateContainer: Wrong error type. Want %#v. Got %#v.", ErrContainerAlreadyExists, err)
- }
-}
-
-func TestCreateContainerWithHostConfig(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "{}", status: http.StatusOK}
- client := newTestClient(fakeRT)
- config := Config{}
- hostConfig := HostConfig{PublishAllPorts: true}
- opts := CreateContainerOptions{Name: "TestCreateContainerWithHostConfig", Config: &config, HostConfig: &hostConfig}
- _, err := client.CreateContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- var gotBody map[string]interface{}
- err = json.NewDecoder(req.Body).Decode(&gotBody)
- if err != nil {
- t.Fatal(err)
- }
- if _, ok := gotBody["HostConfig"]; !ok {
- t.Errorf("CreateContainer: wrong body. HostConfig was not serialized")
- }
-}
-
-func TestUpdateContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- update := UpdateContainerOptions{Memory: 12345, CpusetMems: "0,1"}
- err := client.UpdateContainer(id, update)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("UpdateContainer: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/update"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("UpdateContainer: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
- }
- expectedContentType := "application/json"
- if contentType := req.Header.Get("Content-Type"); contentType != expectedContentType {
- t.Errorf("UpdateContainer: Wrong content-type in request. Want %q. Got %q.", expectedContentType, contentType)
- }
- var out UpdateContainerOptions
- if err := json.NewDecoder(req.Body).Decode(&out); err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(out, update) {
- t.Errorf("UpdateContainer: wrong body, got: %#v, want %#v", out, update)
- }
-}
-
-func TestStartContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.StartContainer(id, &HostConfig{})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("StartContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/start"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("StartContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
- expectedContentType := "application/json"
- if contentType := req.Header.Get("Content-Type"); contentType != expectedContentType {
- t.Errorf("StartContainer(%q): Wrong content-type in request. Want %q. Got %q.", id, expectedContentType, contentType)
- }
-}
-
-func TestStartContainerNilHostConfig(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.StartContainer(id, nil)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("StartContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/start"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("StartContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
- expectedContentType := "application/json"
- if contentType := req.Header.Get("Content-Type"); contentType != expectedContentType {
- t.Errorf("StartContainer(%q): Wrong content-type in request. Want %q. Got %q.", id, expectedContentType, contentType)
- }
- var buf [4]byte
- req.Body.Read(buf[:])
- if string(buf[:]) != "null" {
- t.Errorf("Startcontainer(%q): Wrong body. Want null. Got %s", id, buf[:])
- }
-}
-
-func TestStartContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- err := client.StartContainer("a2344", &HostConfig{})
- expected := &NoSuchContainer{ID: "a2344", Err: err.(*NoSuchContainer).Err}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("StartContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestStartContainerAlreadyRunning(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "container already running", status: http.StatusNotModified})
- err := client.StartContainer("a2334", &HostConfig{})
- expected := &ContainerAlreadyRunning{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("StartContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestStopContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.StopContainer(id, 10)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("StopContainer(%q, 10): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/stop"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("StopContainer(%q, 10): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestStopContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- err := client.StopContainer("a2334", 10)
- expected := &NoSuchContainer{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("StopContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestStopContainerNotRunning(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "container not running", status: http.StatusNotModified})
- err := client.StopContainer("a2334", 10)
- expected := &ContainerNotRunning{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("StopContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestRestartContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.RestartContainer(id, 10)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("RestartContainer(%q, 10): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/restart"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("RestartContainer(%q, 10): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestRestartContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- err := client.RestartContainer("a2334", 10)
- expected := &NoSuchContainer{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("RestartContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestPauseContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.PauseContainer(id)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("PauseContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/pause"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("PauseContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestPauseContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- err := client.PauseContainer("a2334")
- expected := &NoSuchContainer{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("PauseContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestUnpauseContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.UnpauseContainer(id)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("PauseContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/unpause"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("PauseContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestUnpauseContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- err := client.UnpauseContainer("a2334")
- expected := &NoSuchContainer{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("PauseContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestKillContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.KillContainer(KillContainerOptions{ID: id})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("KillContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/kill"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("KillContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestKillContainerSignal(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.KillContainer(KillContainerOptions{ID: id, Signal: SIGTERM})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("KillContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- if signal := req.URL.Query().Get("signal"); signal != "15" {
- t.Errorf("KillContainer(%q): Wrong query string in request. Want %q. Got %q.", id, "15", signal)
- }
-}
-
-func TestKillContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- err := client.KillContainer(KillContainerOptions{ID: "a2334"})
- expected := &NoSuchContainer{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("KillContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestRemoveContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- opts := RemoveContainerOptions{ID: id}
- err := client.RemoveContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "DELETE" {
- t.Errorf("RemoveContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "DELETE", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("RemoveContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestRemoveContainerRemoveVolumes(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- opts := RemoveContainerOptions{ID: id, RemoveVolumes: true}
- err := client.RemoveContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- params := map[string][]string(req.URL.Query())
- expected := map[string][]string{"v": {"1"}}
- if !reflect.DeepEqual(params, expected) {
- t.Errorf("RemoveContainer(%q): wrong parameters. Want %#v. Got %#v.", id, expected, params)
- }
-}
-
-func TestRemoveContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- err := client.RemoveContainer(RemoveContainerOptions{ID: "a2334"})
- expected := &NoSuchContainer{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("RemoveContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestResizeContainerTTY(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- err := client.ResizeContainerTTY(id, 40, 80)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("ResizeContainerTTY(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/resize"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("ResizeContainerTTY(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
- got := map[string][]string(req.URL.Query())
- expectedParams := map[string][]string{
- "w": {"80"},
- "h": {"40"},
- }
- if !reflect.DeepEqual(got, expectedParams) {
- t.Errorf("Expected %#v, got %#v.", expectedParams, got)
- }
-}
-
-func TestWaitContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: `{"StatusCode": 56}`, status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- status, err := client.WaitContainer(id)
- if err != nil {
- t.Fatal(err)
- }
- if status != 56 {
- t.Errorf("WaitContainer(%q): wrong return. Want 56. Got %d.", id, status)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("WaitContainer(%q): wrong HTTP method. Want %q. Got %q.", id, "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/" + id + "/wait"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("WaitContainer(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestWaitContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- _, err := client.WaitContainer("a2334")
- expected := &NoSuchContainer{ID: "a2334"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("WaitContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestCommitContainer(t *testing.T) {
- response := `{"Id":"596069db4bf5"}`
- client := newTestClient(&FakeRoundTripper{message: response, status: http.StatusOK})
- id := "596069db4bf5"
- image, err := client.CommitContainer(CommitContainerOptions{})
- if err != nil {
- t.Fatal(err)
- }
- if image.ID != id {
- t.Errorf("CommitContainer: Wrong image id. Want %q. Got %q.", id, image.ID)
- }
-}
-
-func TestCommitContainerParams(t *testing.T) {
- cfg := Config{Memory: 67108864}
- json, _ := json.Marshal(&cfg)
- var tests = []struct {
- input CommitContainerOptions
- params map[string][]string
- body []byte
- }{
- {CommitContainerOptions{}, map[string][]string{}, nil},
- {CommitContainerOptions{Container: "44c004db4b17"}, map[string][]string{"container": {"44c004db4b17"}}, nil},
- {
- CommitContainerOptions{Container: "44c004db4b17", Repository: "tsuru/python", Message: "something"},
- map[string][]string{"container": {"44c004db4b17"}, "repo": {"tsuru/python"}, "comment": {"something"}},
- nil,
- },
- {
- CommitContainerOptions{Container: "44c004db4b17", Run: &cfg},
- map[string][]string{"container": {"44c004db4b17"}},
- json,
- },
- }
- fakeRT := &FakeRoundTripper{message: "{}", status: http.StatusOK}
- client := newTestClient(fakeRT)
- u, _ := url.Parse(client.getURL("/commit"))
- for _, tt := range tests {
- if _, err := client.CommitContainer(tt.input); err != nil {
- t.Error(err)
- }
- got := map[string][]string(fakeRT.requests[0].URL.Query())
- if !reflect.DeepEqual(got, tt.params) {
- t.Errorf("Expected %#v, got %#v.", tt.params, got)
- }
- if path := fakeRT.requests[0].URL.Path; path != u.Path {
- t.Errorf("Wrong path on request. Want %q. Got %q.", u.Path, path)
- }
- if meth := fakeRT.requests[0].Method; meth != "POST" {
- t.Errorf("Wrong HTTP method. Want POST. Got %s.", meth)
- }
- if tt.body != nil {
- if requestBody, err := ioutil.ReadAll(fakeRT.requests[0].Body); err == nil {
- if bytes.Compare(requestBody, tt.body) != 0 {
- t.Errorf("Expected body %#v, got %#v", tt.body, requestBody)
- }
- } else {
- t.Errorf("Error reading request body: %#v", err)
- }
- }
- fakeRT.Reset()
- }
-}
-
-func TestCommitContainerFailure(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusInternalServerError})
- _, err := client.CommitContainer(CommitContainerOptions{})
- if err == nil {
- t.Error("Expected non-nil error, got .")
- }
-}
-
-func TestCommitContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- _, err := client.CommitContainer(CommitContainerOptions{})
- expected := &NoSuchContainer{ID: ""}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("CommitContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestAttachToContainerLogs(t *testing.T) {
- var req http.Request
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte{1, 0, 0, 0, 0, 0, 0, 19})
- w.Write([]byte("something happened!"))
- req = *r
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var buf bytes.Buffer
- opts := AttachToContainerOptions{
- Container: "a123456",
- OutputStream: &buf,
- Stdout: true,
- Stderr: true,
- Logs: true,
- }
- err := client.AttachToContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- expected := "something happened!"
- if buf.String() != expected {
- t.Errorf("AttachToContainer for logs: wrong output. Want %q. Got %q.", expected, buf.String())
- }
- if req.Method != "POST" {
- t.Errorf("AttachToContainer: wrong HTTP method. Want POST. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/containers/a123456/attach"))
- if req.URL.Path != u.Path {
- t.Errorf("AttachToContainer for logs: wrong HTTP path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
- expectedQs := map[string][]string{
- "logs": {"1"},
- "stdout": {"1"},
- "stderr": {"1"},
- }
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expectedQs) {
- t.Errorf("AttachToContainer: wrong query string. Want %#v. Got %#v.", expectedQs, got)
- }
-}
-
-func TestAttachToContainer(t *testing.T) {
- var reader = strings.NewReader("send value")
- var req http.Request
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte{1, 0, 0, 0, 0, 0, 0, 5})
- w.Write([]byte("hello"))
- req = *r
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var stdout, stderr bytes.Buffer
- opts := AttachToContainerOptions{
- Container: "a123456",
- OutputStream: &stdout,
- ErrorStream: &stderr,
- InputStream: reader,
- Stdin: true,
- Stdout: true,
- Stderr: true,
- Stream: true,
- RawTerminal: true,
- }
- err := client.AttachToContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- expected := map[string][]string{
- "stdin": {"1"},
- "stdout": {"1"},
- "stderr": {"1"},
- "stream": {"1"},
- }
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("AttachToContainer: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestAttachToContainerSentinel(t *testing.T) {
- var reader = strings.NewReader("send value")
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte{1, 0, 0, 0, 0, 0, 0, 5})
- w.Write([]byte("hello"))
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var stdout, stderr bytes.Buffer
- success := make(chan struct{})
- opts := AttachToContainerOptions{
- Container: "a123456",
- OutputStream: &stdout,
- ErrorStream: &stderr,
- InputStream: reader,
- Stdin: true,
- Stdout: true,
- Stderr: true,
- Stream: true,
- RawTerminal: true,
- Success: success,
- }
- errCh := make(chan error)
- go func() {
- errCh <- client.AttachToContainer(opts)
- }()
- success <- <-success
- if err := <-errCh; err != nil {
- t.Error(err)
- }
-}
-
-func TestAttachToContainerNilStdout(t *testing.T) {
- var reader = strings.NewReader("send value")
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte{1, 0, 0, 0, 0, 0, 0, 5})
- w.Write([]byte("hello"))
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var stderr bytes.Buffer
- opts := AttachToContainerOptions{
- Container: "a123456",
- OutputStream: nil,
- ErrorStream: &stderr,
- InputStream: reader,
- Stdin: true,
- Stdout: true,
- Stderr: true,
- Stream: true,
- RawTerminal: true,
- }
- err := client.AttachToContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestAttachToContainerNilStderr(t *testing.T) {
- var reader = strings.NewReader("send value")
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte{1, 0, 0, 0, 0, 0, 0, 5})
- w.Write([]byte("hello"))
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var stdout bytes.Buffer
- opts := AttachToContainerOptions{
- Container: "a123456",
- OutputStream: &stdout,
- InputStream: reader,
- Stdin: true,
- Stdout: true,
- Stderr: true,
- Stream: true,
- RawTerminal: true,
- }
- err := client.AttachToContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestAttachToContainerStdinOnly(t *testing.T) {
- var reader = strings.NewReader("send value")
- serverFinished := make(chan struct{})
- clientFinished := make(chan struct{})
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusOK)
- hj, ok := w.(http.Hijacker)
- if !ok {
- t.Fatal("cannot hijack server connection")
- }
- conn, _, err := hj.Hijack()
- if err != nil {
- t.Fatal(err)
- }
- // wait for client to indicate it's finished
- <-clientFinished
- // inform test that the server has finished
- close(serverFinished)
- conn.Close()
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- success := make(chan struct{})
- opts := AttachToContainerOptions{
- Container: "a123456",
- InputStream: reader,
- Stdin: true,
- Stdout: false,
- Stderr: false,
- Stream: true,
- RawTerminal: false,
- Success: success,
- }
- go func() {
- if err := client.AttachToContainer(opts); err != nil {
- t.Error(err)
- }
- // client's attach session is over
- close(clientFinished)
- }()
- success <- <-success
- // wait for server to finish handling attach
- <-serverFinished
-}
-
-func TestAttachToContainerRawTerminalFalse(t *testing.T) {
- input := strings.NewReader("send value")
- var req http.Request
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- req = *r
- w.WriteHeader(http.StatusOK)
- hj, ok := w.(http.Hijacker)
- if !ok {
- t.Fatal("cannot hijack server connection")
- }
- conn, _, err := hj.Hijack()
- if err != nil {
- t.Fatal(err)
- }
- conn.Write([]byte{1, 0, 0, 0, 0, 0, 0, 5})
- conn.Write([]byte("hello"))
- conn.Write([]byte{2, 0, 0, 0, 0, 0, 0, 6})
- conn.Write([]byte("hello!"))
- conn.Close()
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var stdout, stderr bytes.Buffer
- opts := AttachToContainerOptions{
- Container: "a123456",
- OutputStream: &stdout,
- ErrorStream: &stderr,
- InputStream: input,
- Stdin: true,
- Stdout: true,
- Stderr: true,
- Stream: true,
- RawTerminal: false,
- }
- client.AttachToContainer(opts)
- expected := map[string][]string{
- "stdin": {"1"},
- "stdout": {"1"},
- "stderr": {"1"},
- "stream": {"1"},
- }
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("AttachToContainer: wrong query string. Want %#v. Got %#v.", expected, got)
- }
- if stdout.String() != "hello" {
- t.Errorf("AttachToContainer: wrong content written to stdout. Want %q. Got %q.", "hello", stdout.String())
- }
- if stderr.String() != "hello!" {
- t.Errorf("AttachToContainer: wrong content written to stderr. Want %q. Got %q.", "hello!", stderr.String())
- }
-}
-
-func TestAttachToContainerWithoutContainer(t *testing.T) {
- var client Client
- err := client.AttachToContainer(AttachToContainerOptions{})
- expected := &NoSuchContainer{ID: ""}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("AttachToContainer: wrong error. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestLogs(t *testing.T) {
- var req http.Request
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- prefix := []byte{1, 0, 0, 0, 0, 0, 0, 19}
- w.Write(prefix)
- w.Write([]byte("something happened!"))
- req = *r
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var buf bytes.Buffer
- opts := LogsOptions{
- Container: "a123456",
- OutputStream: &buf,
- Follow: true,
- Stdout: true,
- Stderr: true,
- Timestamps: true,
- }
- err := client.Logs(opts)
- if err != nil {
- t.Fatal(err)
- }
- expected := "something happened!"
- if buf.String() != expected {
- t.Errorf("Logs: wrong output. Want %q. Got %q.", expected, buf.String())
- }
- if req.Method != "GET" {
- t.Errorf("Logs: wrong HTTP method. Want GET. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/containers/a123456/logs"))
- if req.URL.Path != u.Path {
- t.Errorf("AttachToContainer for logs: wrong HTTP path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
- expectedQs := map[string][]string{
- "follow": {"1"},
- "stdout": {"1"},
- "stderr": {"1"},
- "timestamps": {"1"},
- "tail": {"all"},
- }
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expectedQs) {
- t.Errorf("Logs: wrong query string. Want %#v. Got %#v.", expectedQs, got)
- }
-}
-
-func TestLogsNilStdoutDoesntFail(t *testing.T) {
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- prefix := []byte{1, 0, 0, 0, 0, 0, 0, 19}
- w.Write(prefix)
- w.Write([]byte("something happened!"))
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- opts := LogsOptions{
- Container: "a123456",
- Follow: true,
- Stdout: true,
- Stderr: true,
- Timestamps: true,
- }
- err := client.Logs(opts)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestLogsNilStderrDoesntFail(t *testing.T) {
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- prefix := []byte{2, 0, 0, 0, 0, 0, 0, 19}
- w.Write(prefix)
- w.Write([]byte("something happened!"))
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- opts := LogsOptions{
- Container: "a123456",
- Follow: true,
- Stdout: true,
- Stderr: true,
- Timestamps: true,
- }
- err := client.Logs(opts)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestLogsSpecifyingTail(t *testing.T) {
- var req http.Request
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- prefix := []byte{1, 0, 0, 0, 0, 0, 0, 19}
- w.Write(prefix)
- w.Write([]byte("something happened!"))
- req = *r
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var buf bytes.Buffer
- opts := LogsOptions{
- Container: "a123456",
- OutputStream: &buf,
- Follow: true,
- Stdout: true,
- Stderr: true,
- Timestamps: true,
- Tail: "100",
- }
- err := client.Logs(opts)
- if err != nil {
- t.Fatal(err)
- }
- expected := "something happened!"
- if buf.String() != expected {
- t.Errorf("Logs: wrong output. Want %q. Got %q.", expected, buf.String())
- }
- if req.Method != "GET" {
- t.Errorf("Logs: wrong HTTP method. Want GET. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/containers/a123456/logs"))
- if req.URL.Path != u.Path {
- t.Errorf("AttachToContainer for logs: wrong HTTP path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
- expectedQs := map[string][]string{
- "follow": {"1"},
- "stdout": {"1"},
- "stderr": {"1"},
- "timestamps": {"1"},
- "tail": {"100"},
- }
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expectedQs) {
- t.Errorf("Logs: wrong query string. Want %#v. Got %#v.", expectedQs, got)
- }
-}
-
-func TestLogsRawTerminal(t *testing.T) {
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("something happened!"))
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var buf bytes.Buffer
- opts := LogsOptions{
- Container: "a123456",
- OutputStream: &buf,
- Follow: true,
- RawTerminal: true,
- Stdout: true,
- Stderr: true,
- Timestamps: true,
- Tail: "100",
- }
- err := client.Logs(opts)
- if err != nil {
- t.Fatal(err)
- }
- expected := "something happened!"
- if buf.String() != expected {
- t.Errorf("Logs: wrong output. Want %q. Got %q.", expected, buf.String())
- }
-}
-
-func TestLogsNoContainer(t *testing.T) {
- var client Client
- err := client.Logs(LogsOptions{})
- expected := &NoSuchContainer{ID: ""}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("AttachToContainer: wrong error. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestNoSuchContainerError(t *testing.T) {
- var err = &NoSuchContainer{ID: "i345"}
- expected := "No such container: i345"
- if got := err.Error(); got != expected {
- t.Errorf("NoSuchContainer: wrong message. Want %q. Got %q.", expected, got)
- }
-}
-
-func TestNoSuchContainerErrorMessage(t *testing.T) {
- var err = &NoSuchContainer{ID: "i345", Err: errors.New("some advanced error info")}
- expected := "some advanced error info"
- if got := err.Error(); got != expected {
- t.Errorf("NoSuchContainer: wrong message. Want %q. Got %q.", expected, got)
- }
-}
-
-func TestExportContainer(t *testing.T) {
- content := "exported container tar content"
- out := stdoutMock{bytes.NewBufferString(content)}
- client := newTestClient(&FakeRoundTripper{status: http.StatusOK})
- opts := ExportContainerOptions{ID: "4fa6e0f0c678", OutputStream: out}
- err := client.ExportContainer(opts)
- if err != nil {
- t.Errorf("ExportContainer: caugh error %#v while exporting container, expected nil", err.Error())
- }
- if out.String() != content {
- t.Errorf("ExportContainer: wrong stdout. Want %#v. Got %#v.", content, out.String())
- }
-}
-
-func TestExportContainerViaUnixSocket(t *testing.T) {
- content := "exported container tar content"
- var buf []byte
- out := bytes.NewBuffer(buf)
- tempSocket := tempfile("export_socket")
- defer os.Remove(tempSocket)
- endpoint := "unix://" + tempSocket
- u, _ := parseEndpoint(endpoint, false)
- client := Client{
- HTTPClient: cleanhttp.DefaultClient(),
- Dialer: &net.Dialer{},
- endpoint: endpoint,
- endpointURL: u,
- SkipServerVersionCheck: true,
- }
- listening := make(chan string)
- done := make(chan int)
- containerID := "4fa6e0f0c678"
- go runStreamConnServer(t, "unix", tempSocket, listening, done, containerID)
- <-listening // wait for server to start
- opts := ExportContainerOptions{ID: containerID, OutputStream: out}
- err := client.ExportContainer(opts)
- <-done // make sure server stopped
- if err != nil {
- t.Errorf("ExportContainer: caugh error %#v while exporting container, expected nil", err.Error())
- }
- if out.String() != content {
- t.Errorf("ExportContainer: wrong stdout. Want %#v. Got %#v.", content, out.String())
- }
-}
-
-func runStreamConnServer(t *testing.T, network, laddr string, listening chan<- string, done chan<- int, containerID string) {
- defer close(done)
- l, err := net.Listen(network, laddr)
- if err != nil {
- t.Errorf("Listen(%q, %q) failed: %v", network, laddr, err)
- listening <- ""
- return
- }
- defer l.Close()
- listening <- l.Addr().String()
- c, err := l.Accept()
- if err != nil {
- t.Logf("Accept failed: %v", err)
- return
- }
- defer c.Close()
- breader := bufio.NewReader(c)
- req, err := http.ReadRequest(breader)
- if path := "/containers/" + containerID + "/export"; req.URL.Path != path {
- t.Errorf("wrong path. Want %q. Got %q", path, req.URL.Path)
- return
- }
- c.Write([]byte("HTTP/1.1 200 OK\n\nexported container tar content"))
-}
-
-func tempfile(filename string) string {
- return os.TempDir() + "/" + filename + "." + strconv.Itoa(os.Getpid())
-}
-
-func TestExportContainerNoId(t *testing.T) {
- client := Client{}
- out := stdoutMock{bytes.NewBufferString("")}
- err := client.ExportContainer(ExportContainerOptions{OutputStream: out})
- e, ok := err.(*NoSuchContainer)
- if !ok {
- t.Errorf("ExportContainer: wrong error. Want NoSuchContainer. Got %#v.", e)
- }
- if e.ID != "" {
- t.Errorf("ExportContainer: wrong ID. Want %q. Got %q", "", e.ID)
- }
-}
-
-func TestUploadToContainer(t *testing.T) {
- content := "File content"
- in := stdinMock{bytes.NewBufferString(content)}
- fakeRT := &FakeRoundTripper{status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := UploadToContainerOptions{
- Path: "abc",
- InputStream: in,
- }
- err := client.UploadToContainer("a123456", opts)
- if err != nil {
- t.Errorf("UploadToContainer: caught error %#v while uploading archive to container, expected nil", err)
- }
-
- req := fakeRT.requests[0]
-
- if req.Method != "PUT" {
- t.Errorf("UploadToContainer{Path:abc}: Wrong HTTP method. Want PUT. Got %s", req.Method)
- }
-
- if pathParam := req.URL.Query().Get("path"); pathParam != "abc" {
- t.Errorf("ListImages({Path:abc}): Wrong parameter. Want path=abc. Got path=%s", pathParam)
- }
-
-}
-
-func TestDownloadFromContainer(t *testing.T) {
- filecontent := "File content"
- client := newTestClient(&FakeRoundTripper{message: filecontent, status: http.StatusOK})
-
- var out bytes.Buffer
- opts := DownloadFromContainerOptions{
- OutputStream: &out,
- }
- err := client.DownloadFromContainer("a123456", opts)
- if err != nil {
- t.Errorf("DownloadFromContainer: caught error %#v while downloading from container, expected nil", err.Error())
- }
- if out.String() != filecontent {
- t.Errorf("DownloadFromContainer: wrong stdout. Want %#v. Got %#v.", filecontent, out.String())
- }
-}
-
-func TestCopyFromContainer(t *testing.T) {
- content := "File content"
- out := stdoutMock{bytes.NewBufferString(content)}
- client := newTestClient(&FakeRoundTripper{status: http.StatusOK})
- opts := CopyFromContainerOptions{
- Container: "a123456",
- OutputStream: &out,
- }
- err := client.CopyFromContainer(opts)
- if err != nil {
- t.Errorf("CopyFromContainer: caught error %#v while copying from container, expected nil", err.Error())
- }
- if out.String() != content {
- t.Errorf("CopyFromContainer: wrong stdout. Want %#v. Got %#v.", content, out.String())
- }
-}
-
-func TestCopyFromContainerEmptyContainer(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{status: http.StatusOK})
- err := client.CopyFromContainer(CopyFromContainerOptions{})
- _, ok := err.(*NoSuchContainer)
- if !ok {
- t.Errorf("CopyFromContainer: invalid error returned. Want NoSuchContainer, got %#v.", err)
- }
-}
-
-func TestPassingNameOptToCreateContainerReturnsItInContainer(t *testing.T) {
- jsonContainer := `{
- "Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2",
- "Warnings": []
-}`
- fakeRT := &FakeRoundTripper{message: jsonContainer, status: http.StatusOK}
- client := newTestClient(fakeRT)
- config := Config{AttachStdout: true, AttachStdin: true}
- opts := CreateContainerOptions{Name: "TestCreateContainer", Config: &config}
- container, err := client.CreateContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- if container.Name != "TestCreateContainer" {
- t.Errorf("Container name expected to be TestCreateContainer, was %s", container.Name)
- }
-}
-
-func TestAlwaysRestart(t *testing.T) {
- policy := AlwaysRestart()
- if policy.Name != "always" {
- t.Errorf("AlwaysRestart(): wrong policy name. Want %q. Got %q", "always", policy.Name)
- }
- if policy.MaximumRetryCount != 0 {
- t.Errorf("AlwaysRestart(): wrong MaximumRetryCount. Want 0. Got %d", policy.MaximumRetryCount)
- }
-}
-
-func TestRestartOnFailure(t *testing.T) {
- const retry = 5
- policy := RestartOnFailure(retry)
- if policy.Name != "on-failure" {
- t.Errorf("RestartOnFailure(%d): wrong policy name. Want %q. Got %q", retry, "on-failure", policy.Name)
- }
- if policy.MaximumRetryCount != retry {
- t.Errorf("RestartOnFailure(%d): wrong MaximumRetryCount. Want %d. Got %d", retry, retry, policy.MaximumRetryCount)
- }
-}
-
-func TestRestartUnlessStopped(t *testing.T) {
- policy := RestartUnlessStopped()
- if policy.Name != "unless-stopped" {
- t.Errorf("RestartUnlessStopped(): wrong policy name. Want %q. Got %q", "unless-stopped", policy.Name)
- }
- if policy.MaximumRetryCount != 0 {
- t.Errorf("RestartUnlessStopped(): wrong MaximumRetryCount. Want 0. Got %d", policy.MaximumRetryCount)
- }
-}
-
-func TestNeverRestart(t *testing.T) {
- policy := NeverRestart()
- if policy.Name != "no" {
- t.Errorf("NeverRestart(): wrong policy name. Want %q. Got %q", "always", policy.Name)
- }
- if policy.MaximumRetryCount != 0 {
- t.Errorf("NeverRestart(): wrong MaximumRetryCount. Want 0. Got %d", policy.MaximumRetryCount)
- }
-}
-
-func TestTopContainer(t *testing.T) {
- jsonTop := `{
- "Processes": [
- [
- "ubuntu",
- "3087",
- "815",
- "0",
- "01:44",
- "?",
- "00:00:00",
- "cmd1"
- ],
- [
- "root",
- "3158",
- "3087",
- "0",
- "01:44",
- "?",
- "00:00:01",
- "cmd2"
- ]
- ],
- "Titles": [
- "UID",
- "PID",
- "PPID",
- "C",
- "STIME",
- "TTY",
- "TIME",
- "CMD"
- ]
-}`
- var expected TopResult
- err := json.Unmarshal([]byte(jsonTop), &expected)
- if err != nil {
- t.Fatal(err)
- }
- id := "4fa6e0f0"
- fakeRT := &FakeRoundTripper{message: jsonTop, status: http.StatusOK}
- client := newTestClient(fakeRT)
- processes, err := client.TopContainer(id, "")
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(processes, expected) {
- t.Errorf("TopContainer: Expected %#v. Got %#v.", expected, processes)
- }
- if len(processes.Processes) != 2 || len(processes.Processes[0]) != 8 ||
- processes.Processes[0][7] != "cmd1" {
- t.Errorf("TopContainer: Process list to include cmd1. Got %#v.", processes)
- }
- expectedURI := "/containers/" + id + "/top"
- if !strings.HasSuffix(fakeRT.requests[0].URL.String(), expectedURI) {
- t.Errorf("TopContainer: Expected URI to have %q. Got %q.", expectedURI, fakeRT.requests[0].URL.String())
- }
-}
-
-func TestTopContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- _, err := client.TopContainer("abef348", "")
- expected := &NoSuchContainer{ID: "abef348"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("StopContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestTopContainerWithPsArgs(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "no such container", status: http.StatusNotFound}
- client := newTestClient(fakeRT)
- expectedErr := &NoSuchContainer{ID: "abef348"}
- if _, err := client.TopContainer("abef348", "aux"); !reflect.DeepEqual(expectedErr, err) {
- t.Errorf("TopContainer: Expected %v. Got %v.", expectedErr, err)
- }
- expectedURI := "/containers/abef348/top?ps_args=aux"
- if !strings.HasSuffix(fakeRT.requests[0].URL.String(), expectedURI) {
- t.Errorf("TopContainer: Expected URI to have %q. Got %q.", expectedURI, fakeRT.requests[0].URL.String())
- }
-}
-
-func TestStatsTimeout(t *testing.T) {
- l, err := net.Listen("unix", "/tmp/docker_test.sock")
- if err != nil {
- t.Fatal(err)
- }
- received := make(chan bool)
- defer l.Close()
- go func() {
- conn, err := l.Accept()
- if err != nil {
- t.Logf("Failed to accept connection: %s", err)
- return
- }
- breader := bufio.NewReader(conn)
- req, err := http.ReadRequest(breader)
- if err != nil {
- t.Logf("Failed to read request: %s", err)
- return
- }
- if req.URL.Path != "/containers/c/stats" {
- t.Logf("Wrong URL path for stats: %q", req.URL.Path)
- return
- }
- received <- true
- time.Sleep(2 * time.Second)
- }()
- client, _ := NewClient("unix:///tmp/docker_test.sock")
- client.SkipServerVersionCheck = true
- errC := make(chan error, 1)
- statsC := make(chan *Stats)
- done := make(chan bool)
- defer close(done)
- go func() {
- errC <- client.Stats(StatsOptions{ID: "c", Stats: statsC, Stream: true, Done: done, Timeout: time.Millisecond * 100})
- close(errC)
- }()
- err = <-errC
- e, ok := err.(net.Error)
- if !ok || !e.Timeout() {
- t.Error("Failed to receive timeout exception")
- }
- recvTimeout := 2 * time.Second
- select {
- case <-received:
- return
- case <-time.After(recvTimeout):
- t.Fatalf("Timeout waiting to receive message after %v", recvTimeout)
- }
-}
-
-func TestStats(t *testing.T) {
- jsonStats1 := `{
- "read" : "2015-01-08T22:57:31.547920715Z",
- "network" : {
- "rx_dropped" : 0,
- "rx_bytes" : 648,
- "rx_errors" : 0,
- "tx_packets" : 8,
- "tx_dropped" : 0,
- "rx_packets" : 8,
- "tx_errors" : 0,
- "tx_bytes" : 648
- },
- "networks" : {
- "eth0":{
- "rx_dropped" : 0,
- "rx_bytes" : 648,
- "rx_errors" : 0,
- "tx_packets" : 8,
- "tx_dropped" : 0,
- "rx_packets" : 8,
- "tx_errors" : 0,
- "tx_bytes" : 648
- }
- },
- "memory_stats" : {
- "stats" : {
- "total_pgmajfault" : 0,
- "cache" : 0,
- "mapped_file" : 0,
- "total_inactive_file" : 0,
- "pgpgout" : 414,
- "rss" : 6537216,
- "total_mapped_file" : 0,
- "writeback" : 0,
- "unevictable" : 0,
- "pgpgin" : 477,
- "total_unevictable" : 0,
- "pgmajfault" : 0,
- "total_rss" : 6537216,
- "total_rss_huge" : 6291456,
- "total_writeback" : 0,
- "total_inactive_anon" : 0,
- "rss_huge" : 6291456,
- "hierarchical_memory_limit": 189204833,
- "total_pgfault" : 964,
- "total_active_file" : 0,
- "active_anon" : 6537216,
- "total_active_anon" : 6537216,
- "total_pgpgout" : 414,
- "total_cache" : 0,
- "inactive_anon" : 0,
- "active_file" : 0,
- "pgfault" : 964,
- "inactive_file" : 0,
- "total_pgpgin" : 477,
- "swap" : 47312896,
- "hierarchical_memsw_limit" : 1610612736
- },
- "max_usage" : 6651904,
- "usage" : 6537216,
- "failcnt" : 0,
- "limit" : 67108864
- },
- "blkio_stats": {
- "io_service_bytes_recursive": [
- {
- "major": 8,
- "minor": 0,
- "op": "Read",
- "value": 428795731968
- },
- {
- "major": 8,
- "minor": 0,
- "op": "Write",
- "value": 388177920
- }
- ],
- "io_serviced_recursive": [
- {
- "major": 8,
- "minor": 0,
- "op": "Read",
- "value": 25994442
- },
- {
- "major": 8,
- "minor": 0,
- "op": "Write",
- "value": 1734
- }
- ],
- "io_queue_recursive": [],
- "io_service_time_recursive": [],
- "io_wait_time_recursive": [],
- "io_merged_recursive": [],
- "io_time_recursive": [],
- "sectors_recursive": []
- },
- "cpu_stats" : {
- "cpu_usage" : {
- "percpu_usage" : [
- 16970827,
- 1839451,
- 7107380,
- 10571290
- ],
- "usage_in_usermode" : 10000000,
- "total_usage" : 36488948,
- "usage_in_kernelmode" : 20000000
- },
- "system_cpu_usage" : 20091722000000000
- },
- "precpu_stats" : {
- "cpu_usage" : {
- "percpu_usage" : [
- 16970827,
- 1839451,
- 7107380,
- 10571290
- ],
- "usage_in_usermode" : 10000000,
- "total_usage" : 36488948,
- "usage_in_kernelmode" : 20000000
- },
- "system_cpu_usage" : 20091722000000000
- }
- }`
- // 1 second later, cache is 100
- jsonStats2 := `{
- "read" : "2015-01-08T22:57:32.547920715Z",
- "networks" : {
- "eth0":{
- "rx_dropped" : 0,
- "rx_bytes" : 648,
- "rx_errors" : 0,
- "tx_packets" : 8,
- "tx_dropped" : 0,
- "rx_packets" : 8,
- "tx_errors" : 0,
- "tx_bytes" : 648
- }
- },
- "memory_stats" : {
- "stats" : {
- "total_pgmajfault" : 0,
- "cache" : 100,
- "mapped_file" : 0,
- "total_inactive_file" : 0,
- "pgpgout" : 414,
- "rss" : 6537216,
- "total_mapped_file" : 0,
- "writeback" : 0,
- "unevictable" : 0,
- "pgpgin" : 477,
- "total_unevictable" : 0,
- "pgmajfault" : 0,
- "total_rss" : 6537216,
- "total_rss_huge" : 6291456,
- "total_writeback" : 0,
- "total_inactive_anon" : 0,
- "rss_huge" : 6291456,
- "total_pgfault" : 964,
- "total_active_file" : 0,
- "active_anon" : 6537216,
- "total_active_anon" : 6537216,
- "total_pgpgout" : 414,
- "total_cache" : 0,
- "inactive_anon" : 0,
- "active_file" : 0,
- "pgfault" : 964,
- "inactive_file" : 0,
- "total_pgpgin" : 477,
- "swap" : 47312896,
- "hierarchical_memsw_limit" : 1610612736
- },
- "max_usage" : 6651904,
- "usage" : 6537216,
- "failcnt" : 0,
- "limit" : 67108864
- },
- "blkio_stats": {
- "io_service_bytes_recursive": [
- {
- "major": 8,
- "minor": 0,
- "op": "Read",
- "value": 428795731968
- },
- {
- "major": 8,
- "minor": 0,
- "op": "Write",
- "value": 388177920
- }
- ],
- "io_serviced_recursive": [
- {
- "major": 8,
- "minor": 0,
- "op": "Read",
- "value": 25994442
- },
- {
- "major": 8,
- "minor": 0,
- "op": "Write",
- "value": 1734
- }
- ],
- "io_queue_recursive": [],
- "io_service_time_recursive": [],
- "io_wait_time_recursive": [],
- "io_merged_recursive": [],
- "io_time_recursive": [],
- "sectors_recursive": []
- },
- "cpu_stats" : {
- "cpu_usage" : {
- "percpu_usage" : [
- 16970827,
- 1839451,
- 7107380,
- 10571290
- ],
- "usage_in_usermode" : 10000000,
- "total_usage" : 36488948,
- "usage_in_kernelmode" : 20000000
- },
- "system_cpu_usage" : 20091722000000000
- },
- "precpu_stats" : {
- "cpu_usage" : {
- "percpu_usage" : [
- 16970827,
- 1839451,
- 7107380,
- 10571290
- ],
- "usage_in_usermode" : 10000000,
- "total_usage" : 36488948,
- "usage_in_kernelmode" : 20000000
- },
- "system_cpu_usage" : 20091722000000000
- }
- }`
- var expected1 Stats
- var expected2 Stats
- err := json.Unmarshal([]byte(jsonStats1), &expected1)
- if err != nil {
- t.Fatal(err)
- }
- err = json.Unmarshal([]byte(jsonStats2), &expected2)
- if err != nil {
- t.Fatal(err)
- }
- id := "4fa6e0f0"
-
- var req http.Request
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte(jsonStats1))
- w.Write([]byte(jsonStats2))
- req = *r
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- errC := make(chan error, 1)
- statsC := make(chan *Stats)
- done := make(chan bool)
- defer close(done)
- go func() {
- errC <- client.Stats(StatsOptions{ID: id, Stats: statsC, Stream: true, Done: done})
- close(errC)
- }()
- var resultStats []*Stats
- for {
- stats, ok := <-statsC
- if !ok {
- break
- }
- resultStats = append(resultStats, stats)
- }
- err = <-errC
- if err != nil {
- t.Fatal(err)
- }
- if len(resultStats) != 2 {
- t.Fatalf("Stats: Expected 2 results. Got %d.", len(resultStats))
- }
- if !reflect.DeepEqual(resultStats[0], &expected1) {
- t.Errorf("Stats: Expected:\n%+v\nGot:\n%+v", expected1, resultStats[0])
- }
- if !reflect.DeepEqual(resultStats[1], &expected2) {
- t.Errorf("Stats: Expected:\n%+v\nGot:\n%+v", expected2, resultStats[1])
- }
- if req.Method != "GET" {
- t.Errorf("Stats: wrong HTTP method. Want GET. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/containers/" + id + "/stats"))
- if req.URL.Path != u.Path {
- t.Errorf("Stats: wrong HTTP path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
-}
-
-func TestStatsContainerNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such container", status: http.StatusNotFound})
- statsC := make(chan *Stats)
- done := make(chan bool)
- defer close(done)
- err := client.Stats(StatsOptions{ID: "abef348", Stats: statsC, Stream: true, Done: done})
- expected := &NoSuchContainer{ID: "abef348"}
- if !reflect.DeepEqual(err, expected) {
- t.Errorf("Stats: Wrong error returned. Want %#v. Got %#v.", expected, err)
- }
-}
-
-func TestRenameContainer(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := RenameContainerOptions{ID: "something_old", Name: "something_new"}
- err := client.RenameContainer(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("RenameContainer: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/something_old/rename?name=something_new"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("RenameContainer: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
- }
- expectedValues := expectedURL.Query()["name"]
- actualValues := req.URL.Query()["name"]
- if len(actualValues) != 1 || expectedValues[0] != actualValues[0] {
- t.Errorf("RenameContainer: Wrong params in request. Want %q. Got %q.", expectedValues, actualValues)
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/env.go b/vendor/github.com/fsouza/go-dockerclient/env.go
deleted file mode 100644
index c54b0b0..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/env.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2014 Docker authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the DOCKER-LICENSE file.
-
-package docker
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "strconv"
- "strings"
-)
-
-// Env represents a list of key-pair represented in the form KEY=VALUE.
-type Env []string
-
-// Get returns the string value of the given key.
-func (env *Env) Get(key string) (value string) {
- return env.Map()[key]
-}
-
-// Exists checks whether the given key is defined in the internal Env
-// representation.
-func (env *Env) Exists(key string) bool {
- _, exists := env.Map()[key]
- return exists
-}
-
-// GetBool returns a boolean representation of the given key. The key is false
-// whenever its value if 0, no, false, none or an empty string. Any other value
-// will be interpreted as true.
-func (env *Env) GetBool(key string) (value bool) {
- s := strings.ToLower(strings.Trim(env.Get(key), " \t"))
- if s == "" || s == "0" || s == "no" || s == "false" || s == "none" {
- return false
- }
- return true
-}
-
-// SetBool defines a boolean value to the given key.
-func (env *Env) SetBool(key string, value bool) {
- if value {
- env.Set(key, "1")
- } else {
- env.Set(key, "0")
- }
-}
-
-// GetInt returns the value of the provided key, converted to int.
-//
-// It the value cannot be represented as an integer, it returns -1.
-func (env *Env) GetInt(key string) int {
- return int(env.GetInt64(key))
-}
-
-// SetInt defines an integer value to the given key.
-func (env *Env) SetInt(key string, value int) {
- env.Set(key, strconv.Itoa(value))
-}
-
-// GetInt64 returns the value of the provided key, converted to int64.
-//
-// It the value cannot be represented as an integer, it returns -1.
-func (env *Env) GetInt64(key string) int64 {
- s := strings.Trim(env.Get(key), " \t")
- val, err := strconv.ParseInt(s, 10, 64)
- if err != nil {
- return -1
- }
- return val
-}
-
-// SetInt64 defines an integer (64-bit wide) value to the given key.
-func (env *Env) SetInt64(key string, value int64) {
- env.Set(key, strconv.FormatInt(value, 10))
-}
-
-// GetJSON unmarshals the value of the provided key in the provided iface.
-//
-// iface is a value that can be provided to the json.Unmarshal function.
-func (env *Env) GetJSON(key string, iface interface{}) error {
- sval := env.Get(key)
- if sval == "" {
- return nil
- }
- return json.Unmarshal([]byte(sval), iface)
-}
-
-// SetJSON marshals the given value to JSON format and stores it using the
-// provided key.
-func (env *Env) SetJSON(key string, value interface{}) error {
- sval, err := json.Marshal(value)
- if err != nil {
- return err
- }
- env.Set(key, string(sval))
- return nil
-}
-
-// GetList returns a list of strings matching the provided key. It handles the
-// list as a JSON representation of a list of strings.
-//
-// If the given key matches to a single string, it will return a list
-// containing only the value that matches the key.
-func (env *Env) GetList(key string) []string {
- sval := env.Get(key)
- if sval == "" {
- return nil
- }
- var l []string
- if err := json.Unmarshal([]byte(sval), &l); err != nil {
- l = append(l, sval)
- }
- return l
-}
-
-// SetList stores the given list in the provided key, after serializing it to
-// JSON format.
-func (env *Env) SetList(key string, value []string) error {
- return env.SetJSON(key, value)
-}
-
-// Set defines the value of a key to the given string.
-func (env *Env) Set(key, value string) {
- *env = append(*env, key+"="+value)
-}
-
-// Decode decodes `src` as a json dictionary, and adds each decoded key-value
-// pair to the environment.
-//
-// If `src` cannot be decoded as a json dictionary, an error is returned.
-func (env *Env) Decode(src io.Reader) error {
- m := make(map[string]interface{})
- if err := json.NewDecoder(src).Decode(&m); err != nil {
- return err
- }
- for k, v := range m {
- env.SetAuto(k, v)
- }
- return nil
-}
-
-// SetAuto will try to define the Set* method to call based on the given value.
-func (env *Env) SetAuto(key string, value interface{}) {
- if fval, ok := value.(float64); ok {
- env.SetInt64(key, int64(fval))
- } else if sval, ok := value.(string); ok {
- env.Set(key, sval)
- } else if val, err := json.Marshal(value); err == nil {
- env.Set(key, string(val))
- } else {
- env.Set(key, fmt.Sprintf("%v", value))
- }
-}
-
-// Map returns the map representation of the env.
-func (env *Env) Map() map[string]string {
- if len(*env) == 0 {
- return nil
- }
- m := make(map[string]string)
- for _, kv := range *env {
- parts := strings.SplitN(kv, "=", 2)
- m[parts[0]] = parts[1]
- }
- return m
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/env_test.go b/vendor/github.com/fsouza/go-dockerclient/env_test.go
deleted file mode 100644
index df5169d..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/env_test.go
+++ /dev/null
@@ -1,351 +0,0 @@
-// Copyright 2014 go-dockerclient authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the DOCKER-LICENSE file.
-
-package docker
-
-import (
- "bytes"
- "errors"
- "reflect"
- "sort"
- "testing"
-)
-
-func TestGet(t *testing.T) {
- var tests = []struct {
- input []string
- query string
- expected string
- }{
- {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PATH", "/usr/bin:/bin"},
- {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATH", "/usr/local"},
- {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATHI", ""},
- {[]string{"WAT="}, "WAT", ""},
- }
- for _, tt := range tests {
- env := Env(tt.input)
- got := env.Get(tt.query)
- if got != tt.expected {
- t.Errorf("Env.Get(%q): wrong result. Want %q. Got %q", tt.query, tt.expected, got)
- }
- }
-}
-
-func TestExists(t *testing.T) {
- var tests = []struct {
- input []string
- query string
- expected bool
- }{
- {[]string{"WAT=", "PYTHONPATH=/usr/local"}, "WAT", true},
- {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATH", true},
- {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, "PYTHONPATHI", false},
- }
- for _, tt := range tests {
- env := Env(tt.input)
- got := env.Exists(tt.query)
- if got != tt.expected {
- t.Errorf("Env.Exists(%q): wrong result. Want %v. Got %v", tt.query, tt.expected, got)
- }
- }
-}
-
-func TestGetBool(t *testing.T) {
- var tests = []struct {
- input string
- expected bool
- }{
- {"EMTPY_VAR", false}, {"ZERO_VAR", false}, {"NO_VAR", false},
- {"FALSE_VAR", false}, {"NONE_VAR", false}, {"TRUE_VAR", true},
- {"WAT", true}, {"PATH", true}, {"ONE_VAR", true}, {"NO_VAR_TAB", false},
- }
- env := Env([]string{
- "EMPTY_VAR=", "ZERO_VAR=0", "NO_VAR=no", "FALSE_VAR=false",
- "NONE_VAR=none", "TRUE_VAR=true", "WAT=wat", "PATH=/usr/bin:/bin",
- "ONE_VAR=1", "NO_VAR_TAB=0 \t\t\t",
- })
- for _, tt := range tests {
- got := env.GetBool(tt.input)
- if got != tt.expected {
- t.Errorf("Env.GetBool(%q): wrong result. Want %v. Got %v.", tt.input, tt.expected, got)
- }
- }
-}
-
-func TestSetBool(t *testing.T) {
- var tests = []struct {
- input bool
- expected string
- }{
- {true, "1"}, {false, "0"},
- }
- for _, tt := range tests {
- var env Env
- env.SetBool("SOME", tt.input)
- if got := env.Get("SOME"); got != tt.expected {
- t.Errorf("Env.SetBool(%v): wrong result. Want %q. Got %q", tt.input, tt.expected, got)
- }
- }
-}
-
-func TestGetInt(t *testing.T) {
- var tests = []struct {
- input string
- expected int
- }{
- {"NEGATIVE_INTEGER", -10}, {"NON_INTEGER", -1}, {"ONE", 1}, {"TWO", 2},
- }
- env := Env([]string{"NEGATIVE_INTEGER=-10", "NON_INTEGER=wat", "ONE=1", "TWO=2"})
- for _, tt := range tests {
- got := env.GetInt(tt.input)
- if got != tt.expected {
- t.Errorf("Env.GetInt(%q): wrong result. Want %d. Got %d", tt.input, tt.expected, got)
- }
- }
-}
-
-func TestSetInt(t *testing.T) {
- var tests = []struct {
- input int
- expected string
- }{
- {10, "10"}, {13, "13"}, {7, "7"}, {33, "33"},
- {0, "0"}, {-34, "-34"},
- }
- for _, tt := range tests {
- var env Env
- env.SetInt("SOME", tt.input)
- if got := env.Get("SOME"); got != tt.expected {
- t.Errorf("Env.SetBool(%d): wrong result. Want %q. Got %q", tt.input, tt.expected, got)
- }
- }
-}
-
-func TestGetInt64(t *testing.T) {
- var tests = []struct {
- input string
- expected int64
- }{
- {"NEGATIVE_INTEGER", -10}, {"NON_INTEGER", -1}, {"ONE", 1}, {"TWO", 2},
- }
- env := Env([]string{"NEGATIVE_INTEGER=-10", "NON_INTEGER=wat", "ONE=1", "TWO=2"})
- for _, tt := range tests {
- got := env.GetInt64(tt.input)
- if got != tt.expected {
- t.Errorf("Env.GetInt64(%q): wrong result. Want %d. Got %d", tt.input, tt.expected, got)
- }
- }
-}
-
-func TestSetInt64(t *testing.T) {
- var tests = []struct {
- input int64
- expected string
- }{
- {10, "10"}, {13, "13"}, {7, "7"}, {33, "33"},
- {0, "0"}, {-34, "-34"},
- }
- for _, tt := range tests {
- var env Env
- env.SetInt64("SOME", tt.input)
- if got := env.Get("SOME"); got != tt.expected {
- t.Errorf("Env.SetBool(%d): wrong result. Want %q. Got %q", tt.input, tt.expected, got)
- }
- }
-}
-
-func TestGetJSON(t *testing.T) {
- var p struct {
- Name string `json:"name"`
- Age int `json:"age"`
- }
- var env Env
- env.Set("person", `{"name":"Gopher","age":5}`)
- err := env.GetJSON("person", &p)
- if err != nil {
- t.Error(err)
- }
- if p.Name != "Gopher" {
- t.Errorf("Env.GetJSON(%q): wrong name. Want %q. Got %q", "person", "Gopher", p.Name)
- }
- if p.Age != 5 {
- t.Errorf("Env.GetJSON(%q): wrong age. Want %d. Got %d", "person", 5, p.Age)
- }
-}
-
-func TestGetJSONAbsent(t *testing.T) {
- var l []string
- var env Env
- err := env.GetJSON("person", &l)
- if err != nil {
- t.Error(err)
- }
- if l != nil {
- t.Errorf("Env.GetJSON(): get unexpected list %v", l)
- }
-}
-
-func TestGetJSONFailure(t *testing.T) {
- var p []string
- var env Env
- env.Set("list-person", `{"name":"Gopher","age":5}`)
- err := env.GetJSON("list-person", &p)
- if err == nil {
- t.Errorf("Env.GetJSON(%q): got unexpected error.", "list-person")
- }
-}
-
-func TestSetJSON(t *testing.T) {
- var p1 = struct {
- Name string `json:"name"`
- Age int `json:"age"`
- }{Name: "Gopher", Age: 5}
- var env Env
- err := env.SetJSON("person", p1)
- if err != nil {
- t.Error(err)
- }
- var p2 struct {
- Name string `json:"name"`
- Age int `json:"age"`
- }
- err = env.GetJSON("person", &p2)
- if err != nil {
- t.Error(err)
- }
- if !reflect.DeepEqual(p1, p2) {
- t.Errorf("Env.SetJSON(%q): wrong result. Want %v. Got %v", "person", p1, p2)
- }
-}
-
-func TestSetJSONFailure(t *testing.T) {
- var env Env
- err := env.SetJSON("person", unmarshable{})
- if err == nil {
- t.Error("Env.SetJSON(): got unexpected error")
- }
- if env.Exists("person") {
- t.Errorf("Env.SetJSON(): should not define the key %q, but did", "person")
- }
-}
-
-func TestGetList(t *testing.T) {
- var tests = []struct {
- input string
- expected []string
- }{
- {"WAT=wat", []string{"wat"}},
- {`WAT=["wat","wet","wit","wot","wut"]`, []string{"wat", "wet", "wit", "wot", "wut"}},
- {"WAT=", nil},
- }
- for _, tt := range tests {
- env := Env([]string{tt.input})
- got := env.GetList("WAT")
- if !reflect.DeepEqual(got, tt.expected) {
- t.Errorf("Env.GetList(%q): wrong result. Want %v. Got %v", "WAT", tt.expected, got)
- }
- }
-}
-
-func TestSetList(t *testing.T) {
- list := []string{"a", "b", "c"}
- var env Env
- if err := env.SetList("SOME", list); err != nil {
- t.Error(err)
- }
- if got := env.GetList("SOME"); !reflect.DeepEqual(got, list) {
- t.Errorf("Env.SetList(%v): wrong result. Got %v", list, got)
- }
-}
-
-func TestSet(t *testing.T) {
- var env Env
- env.Set("PATH", "/home/bin:/bin")
- env.Set("SOMETHING", "/usr/bin")
- env.Set("PATH", "/bin")
- if expected, got := "/usr/bin", env.Get("SOMETHING"); got != expected {
- t.Errorf("Env.Set(%q): wrong result. Want %q. Got %q", expected, expected, got)
- }
- if expected, got := "/bin", env.Get("PATH"); got != expected {
- t.Errorf("Env.Set(%q): wrong result. Want %q. Got %q", expected, expected, got)
- }
-}
-
-func TestDecode(t *testing.T) {
- var tests = []struct {
- input string
- expectedOut []string
- expectedErr string
- }{
- {
- `{"PATH":"/usr/bin:/bin","containers":54,"wat":["123","345"]}`,
- []string{"PATH=/usr/bin:/bin", "containers=54", `wat=["123","345"]`},
- "",
- },
- {"}}", nil, "invalid character '}' looking for beginning of value"},
- {`{}`, nil, ""},
- }
- for _, tt := range tests {
- var env Env
- err := env.Decode(bytes.NewBufferString(tt.input))
- if tt.expectedErr == "" {
- if err != nil {
- t.Error(err)
- }
- } else if tt.expectedErr != err.Error() {
- t.Errorf("Env.Decode(): invalid error. Want %q. Got %q.", tt.expectedErr, err)
- }
- got := []string(env)
- sort.Strings(got)
- sort.Strings(tt.expectedOut)
- if !reflect.DeepEqual(got, tt.expectedOut) {
- t.Errorf("Env.Decode(): wrong result. Want %v. Got %v.", tt.expectedOut, got)
- }
- }
-}
-
-func TestSetAuto(t *testing.T) {
- buf := bytes.NewBufferString("oi")
- var tests = []struct {
- input interface{}
- expected string
- }{
- {10, "10"},
- {10.3, "10"},
- {"oi", "oi"},
- {buf, "{}"},
- {unmarshable{}, "{}"},
- }
- for _, tt := range tests {
- var env Env
- env.SetAuto("SOME", tt.input)
- if got := env.Get("SOME"); got != tt.expected {
- t.Errorf("Env.SetAuto(%v): wrong result. Want %q. Got %q", tt.input, tt.expected, got)
- }
- }
-}
-
-func TestMap(t *testing.T) {
- var tests = []struct {
- input []string
- expected map[string]string
- }{
- {[]string{"PATH=/usr/bin:/bin", "PYTHONPATH=/usr/local"}, map[string]string{"PATH": "/usr/bin:/bin", "PYTHONPATH": "/usr/local"}},
- {nil, nil},
- }
- for _, tt := range tests {
- env := Env(tt.input)
- got := env.Map()
- if !reflect.DeepEqual(got, tt.expected) {
- t.Errorf("Env.Map(): wrong result. Want %v. Got %v", tt.expected, got)
- }
- }
-}
-
-type unmarshable struct {
-}
-
-func (unmarshable) MarshalJSON() ([]byte, error) {
- return nil, errors.New("cannot marshal")
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/event.go b/vendor/github.com/fsouza/go-dockerclient/event.go
deleted file mode 100644
index 10cc52c..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/event.go
+++ /dev/null
@@ -1,381 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "math"
- "net"
- "net/http"
- "net/http/httputil"
- "sync"
- "sync/atomic"
- "time"
-)
-
-// APIEvents represents events coming from the Docker API
-// The fields in the Docker API changed in API version 1.22, and
-// events for more than images and containers are now fired off.
-// To maintain forward and backward compatibility, go-dockerclient
-// replicates the event in both the new and old format as faithfully as possible.
-//
-// For events that only exist in 1.22 in later, `Status` is filled in as
-// `"Type:Action"` instead of just `Action` to allow for older clients to
-// differentiate and not break if they rely on the pre-1.22 Status types.
-//
-// The transformEvent method can be consulted for more information about how
-// events are translated from new/old API formats
-type APIEvents struct {
- // New API Fields in 1.22
- Action string `json:"action,omitempty"`
- Type string `json:"type,omitempty"`
- Actor APIActor `json:"actor,omitempty"`
-
- // Old API fields for < 1.22
- Status string `json:"status,omitempty"`
- ID string `json:"id,omitempty"`
- From string `json:"from,omitempty"`
-
- // Fields in both
- Time int64 `json:"time,omitempty"`
- TimeNano int64 `json:"timeNano,omitempty"`
-}
-
-// APIActor represents an actor that accomplishes something for an event
-type APIActor struct {
- ID string `json:"id,omitempty"`
- Attributes map[string]string `json:"attributes,omitempty"`
-}
-
-type eventMonitoringState struct {
- // `sync/atomic` expects the first word in an allocated struct to be 64-bit
- // aligned on both ARM and x86-32. See https://goo.gl/zW7dgq for more details.
- lastSeen int64
- sync.RWMutex
- sync.WaitGroup
- enabled bool
- C chan *APIEvents
- errC chan error
- listeners []chan<- *APIEvents
-}
-
-const (
- maxMonitorConnRetries = 5
- retryInitialWaitTime = 10.
-)
-
-var (
- // ErrNoListeners is the error returned when no listeners are available
- // to receive an event.
- ErrNoListeners = errors.New("no listeners present to receive event")
-
- // ErrListenerAlreadyExists is the error returned when the listerner already
- // exists.
- ErrListenerAlreadyExists = errors.New("listener already exists for docker events")
-
- // EOFEvent is sent when the event listener receives an EOF error.
- EOFEvent = &APIEvents{
- Type: "EOF",
- Status: "EOF",
- }
-)
-
-// AddEventListener adds a new listener to container events in the Docker API.
-//
-// The parameter is a channel through which events will be sent.
-func (c *Client) AddEventListener(listener chan<- *APIEvents) error {
- var err error
- if !c.eventMonitor.isEnabled() {
- err = c.eventMonitor.enableEventMonitoring(c)
- if err != nil {
- return err
- }
- }
- err = c.eventMonitor.addListener(listener)
- if err != nil {
- return err
- }
- return nil
-}
-
-// RemoveEventListener removes a listener from the monitor.
-func (c *Client) RemoveEventListener(listener chan *APIEvents) error {
- err := c.eventMonitor.removeListener(listener)
- if err != nil {
- return err
- }
- if len(c.eventMonitor.listeners) == 0 {
- c.eventMonitor.disableEventMonitoring()
- }
- return nil
-}
-
-func (eventState *eventMonitoringState) addListener(listener chan<- *APIEvents) error {
- eventState.Lock()
- defer eventState.Unlock()
- if listenerExists(listener, &eventState.listeners) {
- return ErrListenerAlreadyExists
- }
- eventState.Add(1)
- eventState.listeners = append(eventState.listeners, listener)
- return nil
-}
-
-func (eventState *eventMonitoringState) removeListener(listener chan<- *APIEvents) error {
- eventState.Lock()
- defer eventState.Unlock()
- if listenerExists(listener, &eventState.listeners) {
- var newListeners []chan<- *APIEvents
- for _, l := range eventState.listeners {
- if l != listener {
- newListeners = append(newListeners, l)
- }
- }
- eventState.listeners = newListeners
- eventState.Add(-1)
- }
- return nil
-}
-
-func (eventState *eventMonitoringState) closeListeners() {
- for _, l := range eventState.listeners {
- close(l)
- eventState.Add(-1)
- }
- eventState.listeners = nil
-}
-
-func listenerExists(a chan<- *APIEvents, list *[]chan<- *APIEvents) bool {
- for _, b := range *list {
- if b == a {
- return true
- }
- }
- return false
-}
-
-func (eventState *eventMonitoringState) enableEventMonitoring(c *Client) error {
- eventState.Lock()
- defer eventState.Unlock()
- if !eventState.enabled {
- eventState.enabled = true
- atomic.StoreInt64(&eventState.lastSeen, 0)
- eventState.C = make(chan *APIEvents, 100)
- eventState.errC = make(chan error, 1)
- go eventState.monitorEvents(c)
- }
- return nil
-}
-
-func (eventState *eventMonitoringState) disableEventMonitoring() error {
- eventState.Lock()
- defer eventState.Unlock()
-
- eventState.closeListeners()
-
- eventState.Wait()
-
- if eventState.enabled {
- eventState.enabled = false
- close(eventState.C)
- close(eventState.errC)
- }
- return nil
-}
-
-func (eventState *eventMonitoringState) monitorEvents(c *Client) {
- var err error
- for eventState.noListeners() {
- time.Sleep(10 * time.Millisecond)
- }
- if err = eventState.connectWithRetry(c); err != nil {
- // terminate if connect failed
- eventState.disableEventMonitoring()
- return
- }
- for eventState.isEnabled() {
- timeout := time.After(100 * time.Millisecond)
- select {
- case ev, ok := <-eventState.C:
- if !ok {
- return
- }
- if ev == EOFEvent {
- eventState.disableEventMonitoring()
- return
- }
- eventState.updateLastSeen(ev)
- go eventState.sendEvent(ev)
- case err = <-eventState.errC:
- if err == ErrNoListeners {
- eventState.disableEventMonitoring()
- return
- } else if err != nil {
- defer func() { go eventState.monitorEvents(c) }()
- return
- }
- case <-timeout:
- continue
- }
- }
-}
-
-func (eventState *eventMonitoringState) connectWithRetry(c *Client) error {
- var retries int
- eventState.RLock()
- eventChan := eventState.C
- errChan := eventState.errC
- eventState.RUnlock()
- err := c.eventHijack(atomic.LoadInt64(&eventState.lastSeen), eventChan, errChan)
- for ; err != nil && retries < maxMonitorConnRetries; retries++ {
- waitTime := int64(retryInitialWaitTime * math.Pow(2, float64(retries)))
- time.Sleep(time.Duration(waitTime) * time.Millisecond)
- eventState.RLock()
- eventChan = eventState.C
- errChan = eventState.errC
- eventState.RUnlock()
- err = c.eventHijack(atomic.LoadInt64(&eventState.lastSeen), eventChan, errChan)
- }
- return err
-}
-
-func (eventState *eventMonitoringState) noListeners() bool {
- eventState.RLock()
- defer eventState.RUnlock()
- return len(eventState.listeners) == 0
-}
-
-func (eventState *eventMonitoringState) isEnabled() bool {
- eventState.RLock()
- defer eventState.RUnlock()
- return eventState.enabled
-}
-
-func (eventState *eventMonitoringState) sendEvent(event *APIEvents) {
- eventState.RLock()
- defer eventState.RUnlock()
- eventState.Add(1)
- defer eventState.Done()
- if eventState.enabled {
- if len(eventState.listeners) == 0 {
- eventState.errC <- ErrNoListeners
- return
- }
-
- for _, listener := range eventState.listeners {
- listener <- event
- }
- }
-}
-
-func (eventState *eventMonitoringState) updateLastSeen(e *APIEvents) {
- eventState.Lock()
- defer eventState.Unlock()
- if atomic.LoadInt64(&eventState.lastSeen) < e.Time {
- atomic.StoreInt64(&eventState.lastSeen, e.Time)
- }
-}
-
-func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan chan error) error {
- uri := "/events"
- if startTime != 0 {
- uri += fmt.Sprintf("?since=%d", startTime)
- }
- protocol := c.endpointURL.Scheme
- address := c.endpointURL.Path
- if protocol != "unix" {
- protocol = "tcp"
- address = c.endpointURL.Host
- }
- var dial net.Conn
- var err error
- if c.TLSConfig == nil {
- dial, err = c.Dialer.Dial(protocol, address)
- } else {
- dial, err = tlsDialWithDialer(c.Dialer, protocol, address, c.TLSConfig)
- }
- if err != nil {
- return err
- }
- conn := httputil.NewClientConn(dial, nil)
- req, err := http.NewRequest("GET", uri, nil)
- if err != nil {
- return err
- }
- res, err := conn.Do(req)
- if err != nil {
- return err
- }
- go func(res *http.Response, conn *httputil.ClientConn) {
- defer conn.Close()
- defer res.Body.Close()
- decoder := json.NewDecoder(res.Body)
- for {
- var event APIEvents
- if err = decoder.Decode(&event); err != nil {
- if err == io.EOF || err == io.ErrUnexpectedEOF {
- c.eventMonitor.RLock()
- if c.eventMonitor.enabled && c.eventMonitor.C == eventChan {
- // Signal that we're exiting.
- eventChan <- EOFEvent
- }
- c.eventMonitor.RUnlock()
- break
- }
- errChan <- err
- }
- if event.Time == 0 {
- continue
- }
- if !c.eventMonitor.isEnabled() || c.eventMonitor.C != eventChan {
- return
- }
- transformEvent(&event)
- eventChan <- &event
- }
- }(res, conn)
- return nil
-}
-
-// transformEvent takes an event and determines what version it is from
-// then populates both versions of the event
-func transformEvent(event *APIEvents) {
- // if event version is <= 1.21 there will be no Action and no Type
- if event.Action == "" && event.Type == "" {
- event.Action = event.Status
- event.Actor.ID = event.ID
- event.Actor.Attributes = map[string]string{}
- switch event.Status {
- case "delete", "import", "pull", "push", "tag", "untag":
- event.Type = "image"
- default:
- event.Type = "container"
- if event.From != "" {
- event.Actor.Attributes["image"] = event.From
- }
- }
- } else {
- if event.Status == "" {
- if event.Type == "image" || event.Type == "container" {
- event.Status = event.Action
- } else {
- // Because just the Status has been overloaded with different Types
- // if an event is not for an image or a container, we prepend the type
- // to avoid problems for people relying on actions being only for
- // images and containers
- event.Status = event.Type + ":" + event.Action
- }
- }
- if event.ID == "" {
- event.ID = event.Actor.ID
- }
- if event.From == "" {
- event.From = event.Actor.Attributes["image"]
- }
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/event_test.go b/vendor/github.com/fsouza/go-dockerclient/event_test.go
deleted file mode 100644
index b94fc28..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/event_test.go
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2014 go-dockerclient 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 docker
-
-import (
- "bufio"
- "crypto/tls"
- "crypto/x509"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "reflect"
- "strings"
- "testing"
- "time"
-)
-
-func TestEventListeners(t *testing.T) {
- testEventListeners("TestEventListeners", t, httptest.NewServer, NewClient)
-}
-
-func TestTLSEventListeners(t *testing.T) {
- testEventListeners("TestTLSEventListeners", t, func(handler http.Handler) *httptest.Server {
- server := httptest.NewUnstartedServer(handler)
-
- cert, err := tls.LoadX509KeyPair("testing/data/server.pem", "testing/data/serverkey.pem")
- if err != nil {
- t.Fatalf("Error loading server key pair: %s", err)
- }
-
- caCert, err := ioutil.ReadFile("testing/data/ca.pem")
- if err != nil {
- t.Fatalf("Error loading ca certificate: %s", err)
- }
- caPool := x509.NewCertPool()
- if !caPool.AppendCertsFromPEM(caCert) {
- t.Fatalf("Could not add ca certificate")
- }
-
- server.TLS = &tls.Config{
- Certificates: []tls.Certificate{cert},
- RootCAs: caPool,
- }
- server.StartTLS()
- return server
- }, func(url string) (*Client, error) {
- return NewTLSClient(url, "testing/data/cert.pem", "testing/data/key.pem", "testing/data/ca.pem")
- })
-}
-
-func testEventListeners(testName string, t *testing.T, buildServer func(http.Handler) *httptest.Server, buildClient func(string) (*Client, error)) {
- response := `{"action":"pull","type":"image","actor":{"id":"busybox:latest","attributes":{}},"time":1442421700,"timeNano":1442421700598988358}
-{"action":"create","type":"container","actor":{"id":"5745704abe9caa5","attributes":{"image":"busybox"}},"time":1442421716,"timeNano":1442421716853979870}
-{"action":"attach","type":"container","actor":{"id":"5745704abe9caa5","attributes":{"image":"busybox"}},"time":1442421716,"timeNano":1442421716894759198}
-{"action":"start","type":"container","actor":{"id":"5745704abe9caa5","attributes":{"image":"busybox"}},"time":1442421716,"timeNano":1442421716983607193}
-{"status":"create","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
-{"status":"start","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
-{"status":"stop","id":"dfdf82bd3881","from":"base:latest","time":1374067966}
-{"status":"destroy","id":"dfdf82bd3881","from":"base:latest","time":1374067970}
-{"Action":"create","Actor":{"Attributes":{"HAProxyMode":"http","HealthCheck":"HttpGet","HealthCheckArgs":"http://127.0.0.1:39051/status/check","ServicePort_8080":"17801","image":"datanerd.us/siteeng/sample-app-go:latest","name":"sample-app-client-go-69818c1223ddb5"},"ID":"a925eaf4084d5c3bcf337b2abb05f566ebb94276dff34f6effb00d8ecd380e16"},"Type":"container","from":"datanerd.us/siteeng/sample-app-go:latest","id":"a925eaf4084d5c3bcf337b2abb05f566ebb94276dff34f6effb00d8ecd380e16","status":"create","time":1459133932,"timeNano":1459133932961735842}`
-
- wantResponse := []*APIEvents{
- {
- Action: "pull",
- Type: "image",
- Actor: APIActor{
- ID: "busybox:latest",
- Attributes: map[string]string{},
- },
-
- Status: "pull",
- ID: "busybox:latest",
-
- Time: 1442421700,
- TimeNano: 1442421700598988358,
- },
- {
- Action: "create",
- Type: "container",
- Actor: APIActor{
- ID: "5745704abe9caa5",
- Attributes: map[string]string{
- "image": "busybox",
- },
- },
-
- Status: "create",
- ID: "5745704abe9caa5",
- From: "busybox",
-
- Time: 1442421716,
- TimeNano: 1442421716853979870,
- },
- {
- Action: "attach",
- Type: "container",
- Actor: APIActor{
- ID: "5745704abe9caa5",
- Attributes: map[string]string{
- "image": "busybox",
- },
- },
-
- Status: "attach",
- ID: "5745704abe9caa5",
- From: "busybox",
-
- Time: 1442421716,
- TimeNano: 1442421716894759198,
- },
- {
- Action: "start",
- Type: "container",
- Actor: APIActor{
- ID: "5745704abe9caa5",
- Attributes: map[string]string{
- "image": "busybox",
- },
- },
-
- Status: "start",
- ID: "5745704abe9caa5",
- From: "busybox",
-
- Time: 1442421716,
- TimeNano: 1442421716983607193,
- },
-
- {
- Action: "create",
- Type: "container",
- Actor: APIActor{
- ID: "dfdf82bd3881",
- Attributes: map[string]string{
- "image": "base:latest",
- },
- },
-
- Status: "create",
- ID: "dfdf82bd3881",
- From: "base:latest",
-
- Time: 1374067924,
- },
- {
- Action: "start",
- Type: "container",
- Actor: APIActor{
- ID: "dfdf82bd3881",
- Attributes: map[string]string{
- "image": "base:latest",
- },
- },
-
- Status: "start",
- ID: "dfdf82bd3881",
- From: "base:latest",
-
- Time: 1374067924,
- },
- {
- Action: "stop",
- Type: "container",
- Actor: APIActor{
- ID: "dfdf82bd3881",
- Attributes: map[string]string{
- "image": "base:latest",
- },
- },
-
- Status: "stop",
- ID: "dfdf82bd3881",
- From: "base:latest",
-
- Time: 1374067966,
- },
- {
- Action: "destroy",
- Type: "container",
- Actor: APIActor{
- ID: "dfdf82bd3881",
- Attributes: map[string]string{
- "image": "base:latest",
- },
- },
-
- Status: "destroy",
- ID: "dfdf82bd3881",
- From: "base:latest",
-
- Time: 1374067970,
- },
- {
- Action: "create",
- Type: "container",
- Status: "create",
- From: "datanerd.us/siteeng/sample-app-go:latest",
- ID: "a925eaf4084d5c3bcf337b2abb05f566ebb94276dff34f6effb00d8ecd380e16",
- Time: 1459133932,
- TimeNano: 1459133932961735842,
- Actor: APIActor{
- ID: "a925eaf4084d5c3bcf337b2abb05f566ebb94276dff34f6effb00d8ecd380e16",
- Attributes: map[string]string{
- "HAProxyMode": "http",
- "HealthCheck": "HttpGet",
- "HealthCheckArgs": "http://127.0.0.1:39051/status/check",
- "ServicePort_8080": "17801",
- "image": "datanerd.us/siteeng/sample-app-go:latest",
- "name": "sample-app-client-go-69818c1223ddb5",
- },
- },
- },
- }
- server := buildServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- rsc := bufio.NewScanner(strings.NewReader(response))
- for rsc.Scan() {
- w.Write([]byte(rsc.Text()))
- w.(http.Flusher).Flush()
- time.Sleep(10 * time.Millisecond)
- }
- }))
- defer server.Close()
-
- client, err := buildClient(server.URL)
- if err != nil {
- t.Errorf("Failed to create client: %s", err)
- }
- client.SkipServerVersionCheck = true
-
- listener := make(chan *APIEvents, 10)
- defer func() {
- time.Sleep(10 * time.Millisecond)
- if err := client.RemoveEventListener(listener); err != nil {
- t.Error(err)
- }
- }()
-
- err = client.AddEventListener(listener)
- if err != nil {
- t.Errorf("Failed to add event listener: %s", err)
- }
-
- timeout := time.After(1 * time.Second)
-
- for i := 0; i < 9; i++ {
- select {
- case msg := <-listener:
- t.Logf("%d: Received: %v", i, msg)
- if !reflect.DeepEqual(msg, wantResponse[i]) {
- t.Fatalf("%d: wanted: %#v\n got: %#v", i, wantResponse[i], msg)
- }
- case <-timeout:
- t.Fatalf("%s timed out waiting on events", testName)
- }
- }
-}
-
-func TestEventListenerReAdding(t *testing.T) {
- endChan := make(chan bool)
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- <-endChan
- }))
-
- client, err := NewClient(server.URL)
- if err != nil {
- t.Errorf("Failed to create client: %s", err)
- }
-
- listener := make(chan *APIEvents, 10)
- if err := client.AddEventListener(listener); err != nil {
- t.Errorf("Failed to add event listener: %s", err)
- }
-
- // Make sure eventHijack() is started with the current eventMonitoringState.
- time.Sleep(10 * time.Millisecond)
-
- if err := client.RemoveEventListener(listener); err != nil {
- t.Errorf("Failed to remove event listener: %s", err)
- }
-
- if err := client.AddEventListener(listener); err != nil {
- t.Errorf("Failed to add event listener: %s", err)
- }
-
- endChan <- true
-
- // Give the goroutine of the first eventHijack() time to handle the EOF.
- time.Sleep(10 * time.Millisecond)
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/example_test.go b/vendor/github.com/fsouza/go-dockerclient/example_test.go
deleted file mode 100644
index 8c2c719..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/example_test.go
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2014 go-dockerclient 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 docker_test
-
-import (
- "archive/tar"
- "bytes"
- "fmt"
- "io"
- "log"
- "time"
-
- "github.com/fsouza/go-dockerclient"
-)
-
-func ExampleClient_AttachToContainer() {
- client, err := docker.NewClient("http://localhost:4243")
- if err != nil {
- log.Fatal(err)
- }
- client.SkipServerVersionCheck = true
- // Reading logs from container a84849 and sending them to buf.
- var buf bytes.Buffer
- err = client.AttachToContainer(docker.AttachToContainerOptions{
- Container: "a84849",
- OutputStream: &buf,
- Logs: true,
- Stdout: true,
- Stderr: true,
- })
- if err != nil {
- log.Fatal(err)
- }
- log.Println(buf.String())
- buf.Reset()
- err = client.AttachToContainer(docker.AttachToContainerOptions{
- Container: "a84849",
- OutputStream: &buf,
- Stdout: true,
- Stream: true,
- })
- if err != nil {
- log.Fatal(err)
- }
- log.Println(buf.String())
-}
-
-func ExampleClient_CopyFromContainer() {
- client, err := docker.NewClient("http://localhost:4243")
- if err != nil {
- log.Fatal(err)
- }
- cid := "a84849"
- var buf bytes.Buffer
- filename := "/tmp/output.txt"
- err = client.CopyFromContainer(docker.CopyFromContainerOptions{
- Container: cid,
- Resource: filename,
- OutputStream: &buf,
- })
- if err != nil {
- log.Fatalf("Error while copying from %s: %s\n", cid, err)
- }
- content := new(bytes.Buffer)
- r := bytes.NewReader(buf.Bytes())
- tr := tar.NewReader(r)
- tr.Next()
- if err != nil && err != io.EOF {
- log.Fatal(err)
- }
- if _, err := io.Copy(content, tr); err != nil {
- log.Fatal(err)
- }
- log.Println(buf.String())
-}
-
-func ExampleClient_BuildImage() {
- client, err := docker.NewClient("http://localhost:4243")
- if err != nil {
- log.Fatal(err)
- }
-
- t := time.Now()
- inputbuf, outputbuf := bytes.NewBuffer(nil), bytes.NewBuffer(nil)
- tr := tar.NewWriter(inputbuf)
- tr.WriteHeader(&tar.Header{Name: "Dockerfile", Size: 10, ModTime: t, AccessTime: t, ChangeTime: t})
- tr.Write([]byte("FROM base\n"))
- tr.Close()
- opts := docker.BuildImageOptions{
- Name: "test",
- InputStream: inputbuf,
- OutputStream: outputbuf,
- }
- if err := client.BuildImage(opts); err != nil {
- log.Fatal(err)
- }
-}
-
-func ExampleClient_ListenEvents() {
- client, err := docker.NewClient("http://localhost:4243")
- if err != nil {
- log.Fatal(err)
- }
-
- listener := make(chan *docker.APIEvents)
- err = client.AddEventListener(listener)
- if err != nil {
- log.Fatal(err)
- }
-
- defer func() {
-
- err = client.RemoveEventListener(listener)
- if err != nil {
- log.Fatal(err)
- }
-
- }()
-
- timeout := time.After(1 * time.Second)
-
- for {
- select {
- case msg := <-listener:
- log.Println(msg)
- case <-timeout:
- break
- }
- }
-
-}
-
-func ExampleEnv_Map() {
- e := docker.Env([]string{"A=1", "B=2", "C=3"})
- envs := e.Map()
- for k, v := range envs {
- fmt.Printf("%s=%q\n", k, v)
- }
-}
-
-func ExampleEnv_SetJSON() {
- type Person struct {
- Name string
- Age int
- }
- p := Person{Name: "Gopher", Age: 4}
- var e docker.Env
- err := e.SetJSON("person", p)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func ExampleEnv_GetJSON() {
- type Person struct {
- Name string
- Age int
- }
- p := Person{Name: "Gopher", Age: 4}
- var e docker.Env
- e.Set("person", `{"name":"Gopher","age":4}`)
- err := e.GetJSON("person", &p)
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/exec.go b/vendor/github.com/fsouza/go-dockerclient/exec.go
deleted file mode 100644
index 1a16da9..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/exec.go
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "strconv"
-)
-
-// Exec is the type representing a `docker exec` instance and containing the
-// instance ID
-type Exec struct {
- ID string `json:"Id,omitempty" yaml:"Id,omitempty"`
-}
-
-// CreateExecOptions specify parameters to the CreateExecContainer function.
-//
-// See https://goo.gl/1KSIb7 for more details
-type CreateExecOptions struct {
- AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"`
- AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty"`
- AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty"`
- Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty"`
- Cmd []string `json:"Cmd,omitempty" yaml:"Cmd,omitempty"`
- Container string `json:"Container,omitempty" yaml:"Container,omitempty"`
- User string `json:"User,omitempty" yaml:"User,omitempty"`
-}
-
-// CreateExec sets up an exec instance in a running container `id`, returning the exec
-// instance, or an error in case of failure.
-//
-// See https://goo.gl/1KSIb7 for more details
-func (c *Client) CreateExec(opts CreateExecOptions) (*Exec, error) {
- path := fmt.Sprintf("/containers/%s/exec", opts.Container)
- resp, err := c.do("POST", path, doOptions{data: opts})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, &NoSuchContainer{ID: opts.Container}
- }
- return nil, err
- }
- defer resp.Body.Close()
- var exec Exec
- if err := json.NewDecoder(resp.Body).Decode(&exec); err != nil {
- return nil, err
- }
-
- return &exec, nil
-}
-
-// StartExecOptions specify parameters to the StartExecContainer function.
-//
-// See https://goo.gl/iQCnto for more details
-type StartExecOptions struct {
- Detach bool `json:"Detach,omitempty" yaml:"Detach,omitempty"`
-
- Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty"`
-
- InputStream io.Reader `qs:"-"`
- OutputStream io.Writer `qs:"-"`
- ErrorStream io.Writer `qs:"-"`
-
- // Use raw terminal? Usually true when the container contains a TTY.
- RawTerminal bool `qs:"-"`
-
- // If set, after a successful connect, a sentinel will be sent and then the
- // client will block on receive before continuing.
- //
- // It must be an unbuffered channel. Using a buffered channel can lead
- // to unexpected behavior.
- Success chan struct{} `json:"-"`
-}
-
-// StartExec starts a previously set up exec instance id. If opts.Detach is
-// true, it returns after starting the exec command. Otherwise, it sets up an
-// interactive session with the exec command.
-//
-// See https://goo.gl/iQCnto for more details
-func (c *Client) StartExec(id string, opts StartExecOptions) error {
- cw, err := c.StartExecNonBlocking(id, opts)
- if err != nil {
- return err
- }
- if cw != nil {
- return cw.Wait()
- }
- return nil
-}
-
-// StartExecNonBlocking starts a previously set up exec instance id. If opts.Detach is
-// true, it returns after starting the exec command. Otherwise, it sets up an
-// interactive session with the exec command.
-//
-// See https://goo.gl/iQCnto for more details
-func (c *Client) StartExecNonBlocking(id string, opts StartExecOptions) (CloseWaiter, error) {
- if id == "" {
- return nil, &NoSuchExec{ID: id}
- }
-
- path := fmt.Sprintf("/exec/%s/start", id)
-
- if opts.Detach {
- resp, err := c.do("POST", path, doOptions{data: opts})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, &NoSuchExec{ID: id}
- }
- return nil, err
- }
- defer resp.Body.Close()
- return nil, nil
- }
-
- return c.hijack("POST", path, hijackOptions{
- success: opts.Success,
- setRawTerminal: opts.RawTerminal,
- in: opts.InputStream,
- stdout: opts.OutputStream,
- stderr: opts.ErrorStream,
- data: opts,
- })
-}
-
-// ResizeExecTTY resizes the tty session used by the exec command id. This API
-// is valid only if Tty was specified as part of creating and starting the exec
-// command.
-//
-// See https://goo.gl/e1JpsA for more details
-func (c *Client) ResizeExecTTY(id string, height, width int) error {
- params := make(url.Values)
- params.Set("h", strconv.Itoa(height))
- params.Set("w", strconv.Itoa(width))
-
- path := fmt.Sprintf("/exec/%s/resize?%s", id, params.Encode())
- resp, err := c.do("POST", path, doOptions{})
- if err != nil {
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// ExecProcessConfig is a type describing the command associated to a Exec
-// instance. It's used in the ExecInspect type.
-type ExecProcessConfig struct {
- Privileged bool `json:"privileged,omitempty" yaml:"privileged,omitempty"`
- User string `json:"user,omitempty" yaml:"user,omitempty"`
- Tty bool `json:"tty,omitempty" yaml:"tty,omitempty"`
- EntryPoint string `json:"entrypoint,omitempty" yaml:"entrypoint,omitempty"`
- Arguments []string `json:"arguments,omitempty" yaml:"arguments,omitempty"`
-}
-
-// ExecInspect is a type with details about a exec instance, including the
-// exit code if the command has finished running. It's returned by a api
-// call to /exec/(id)/json
-//
-// See https://goo.gl/gPtX9R for more details
-type ExecInspect struct {
- ID string `json:"ID,omitempty" yaml:"ID,omitempty"`
- Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
- ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
- OpenStdin bool `json:"OpenStdin,omitempty" yaml:"OpenStdin,omitempty"`
- OpenStderr bool `json:"OpenStderr,omitempty" yaml:"OpenStderr,omitempty"`
- OpenStdout bool `json:"OpenStdout,omitempty" yaml:"OpenStdout,omitempty"`
- ProcessConfig ExecProcessConfig `json:"ProcessConfig,omitempty" yaml:"ProcessConfig,omitempty"`
- Container Container `json:"Container,omitempty" yaml:"Container,omitempty"`
-}
-
-// InspectExec returns low-level information about the exec command id.
-//
-// See https://goo.gl/gPtX9R for more details
-func (c *Client) InspectExec(id string) (*ExecInspect, error) {
- path := fmt.Sprintf("/exec/%s/json", id)
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, &NoSuchExec{ID: id}
- }
- return nil, err
- }
- defer resp.Body.Close()
- var exec ExecInspect
- if err := json.NewDecoder(resp.Body).Decode(&exec); err != nil {
- return nil, err
- }
- return &exec, nil
-}
-
-// NoSuchExec is the error returned when a given exec instance does not exist.
-type NoSuchExec struct {
- ID string
-}
-
-func (err *NoSuchExec) Error() string {
- return "No such exec instance: " + err.ID
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/exec_test.go b/vendor/github.com/fsouza/go-dockerclient/exec_test.go
deleted file mode 100644
index 2dc8d21..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/exec_test.go
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bytes"
- "encoding/json"
- "net/http"
- "net/http/httptest"
- "net/url"
- "reflect"
- "strings"
- "testing"
-)
-
-func TestExecCreate(t *testing.T) {
- jsonContainer := `{"Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"}`
- var expected struct{ ID string }
- err := json.Unmarshal([]byte(jsonContainer), &expected)
- if err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: jsonContainer, status: http.StatusOK}
- client := newTestClient(fakeRT)
- config := CreateExecOptions{
- Container: "test",
- AttachStdin: true,
- AttachStdout: true,
- AttachStderr: false,
- Tty: false,
- Cmd: []string{"touch", "/tmp/file"},
- User: "a-user",
- }
- execObj, err := client.CreateExec(config)
- if err != nil {
- t.Fatal(err)
- }
- expectedID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- if execObj.ID != expectedID {
- t.Errorf("ExecCreate: wrong ID. Want %q. Got %q.", expectedID, execObj.ID)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("ExecCreate: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/containers/test/exec"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
- }
- var gotBody struct{ ID string }
- err = json.NewDecoder(req.Body).Decode(&gotBody)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestExecStartDetached(t *testing.T) {
- execID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- fakeRT := &FakeRoundTripper{status: http.StatusOK}
- client := newTestClient(fakeRT)
- config := StartExecOptions{
- Detach: true,
- }
- err := client.StartExec(execID, config)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("ExecStart: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/exec/" + execID + "/start"))
- if gotPath := req.URL.Path; gotPath != expectedURL.Path {
- t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
- }
- t.Log(req.Body)
- var gotBody struct{ Detach bool }
- err = json.NewDecoder(req.Body).Decode(&gotBody)
- if err != nil {
- t.Fatal(err)
- }
- if !gotBody.Detach {
- t.Fatal("Expected Detach in StartExecOptions to be true")
- }
-}
-
-func TestExecStartAndAttach(t *testing.T) {
- var reader = strings.NewReader("send value")
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte{1, 0, 0, 0, 0, 0, 0, 5})
- w.Write([]byte("hello"))
- }))
- defer server.Close()
- client, _ := NewClient(server.URL)
- client.SkipServerVersionCheck = true
- var stdout, stderr bytes.Buffer
- success := make(chan struct{})
- execID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- opts := StartExecOptions{
- OutputStream: &stdout,
- ErrorStream: &stderr,
- InputStream: reader,
- RawTerminal: true,
- Success: success,
- }
- go func() {
- if err := client.StartExec(execID, opts); err != nil {
- t.Error(err)
- }
- }()
- <-success
-}
-
-func TestExecResize(t *testing.T) {
- execID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
- fakeRT := &FakeRoundTripper{status: http.StatusOK}
- client := newTestClient(fakeRT)
- err := client.ResizeExecTTY(execID, 10, 20)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("ExecStart: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/exec/" + execID + "/resize?h=10&w=20"))
- if gotPath := req.URL.RequestURI(); gotPath != expectedURL.RequestURI() {
- t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
- }
-}
-
-func TestExecInspect(t *testing.T) {
- jsonExec := `{
- "ID": "32adfeeec34250f9530ce1dafd40c6233832315e065ea6b362d745e2f63cde0e",
- "Running": true,
- "ExitCode": 0,
- "ProcessConfig": {
- "privileged": false,
- "user": "",
- "tty": true,
- "entrypoint": "bash",
- "arguments": []
- },
- "OpenStdin": true,
- "OpenStderr": true,
- "OpenStdout": true,
- "Container": {
- "State": {
- "Running": true,
- "Paused": false,
- "Restarting": false,
- "OOMKilled": false,
- "Pid": 29392,
- "ExitCode": 0,
- "Error": "",
- "StartedAt": "2015-01-21T17:08:59.634662178Z",
- "FinishedAt": "0001-01-01T00:00:00Z"
- },
- "ID": "922cd0568714763dc725b24b7c9801016b2a3de68e2a1dc989bf5abf07740521",
- "Created": "2015-01-21T17:08:59.46407212Z",
- "Path": "/bin/bash",
- "Args": [
- "-lc",
- "tsuru_unit_agent http://192.168.50.4:8080 689b30e0ab3adce374346de2e72512138e0e8b75 gtest /var/lib/tsuru/start && tail -f /dev/null"
- ],
- "Config": {
- "Hostname": "922cd0568714",
- "Domainname": "",
- "User": "ubuntu",
- "Memory": 0,
- "MemorySwap": 0,
- "CpuShares": 100,
- "Cpuset": "",
- "AttachStdin": false,
- "AttachStdout": false,
- "AttachStderr": false,
- "PortSpecs": null,
- "ExposedPorts": {
- "8888/tcp": {}
- },
- "Tty": false,
- "OpenStdin": false,
- "StdinOnce": false,
- "Env": [
- "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
- ],
- "Cmd": [
- "/bin/bash",
- "-lc",
- "tsuru_unit_agent http://192.168.50.4:8080 689b30e0ab3adce374346de2e72512138e0e8b75 gtest /var/lib/tsuru/start && tail -f /dev/null"
- ],
- "Image": "tsuru/app-gtest",
- "Volumes": null,
- "WorkingDir": "",
- "Entrypoint": null,
- "NetworkDisabled": false,
- "MacAddress": "",
- "OnBuild": null
- },
- "Image": "a88060b8b54fde0f7168c86742d0ce83b80f3f10925d85c98fdad9ed00bef544",
- "NetworkSettings": {
- "IPAddress": "172.17.0.8",
- "IPPrefixLen": 16,
- "MacAddress": "02:42:ac:11:00:08",
- "LinkLocalIPv6Address": "fe80::42:acff:fe11:8",
- "LinkLocalIPv6PrefixLen": 64,
- "GlobalIPv6Address": "",
- "GlobalIPv6PrefixLen": 0,
- "Gateway": "172.17.42.1",
- "IPv6Gateway": "",
- "Bridge": "docker0",
- "PortMapping": null,
- "Ports": {
- "8888/tcp": [
- {
- "HostIp": "0.0.0.0",
- "HostPort": "49156"
- }
- ]
- }
- },
- "ResolvConfPath": "/var/lib/docker/containers/922cd0568714763dc725b24b7c9801016b2a3de68e2a1dc989bf5abf07740521/resolv.conf",
- "HostnamePath": "/var/lib/docker/containers/922cd0568714763dc725b24b7c9801016b2a3de68e2a1dc989bf5abf07740521/hostname",
- "HostsPath": "/var/lib/docker/containers/922cd0568714763dc725b24b7c9801016b2a3de68e2a1dc989bf5abf07740521/hosts",
- "Name": "/c7e43b72288ee9d0270a",
- "Driver": "aufs",
- "ExecDriver": "native-0.2",
- "MountLabel": "",
- "ProcessLabel": "",
- "AppArmorProfile": "",
- "RestartCount": 0,
- "UpdateDns": false,
- "Volumes": {},
- "VolumesRW": {}
- }
- }`
- var expected ExecInspect
- err := json.Unmarshal([]byte(jsonExec), &expected)
- if err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: jsonExec, status: http.StatusOK}
- client := newTestClient(fakeRT)
- expectedID := "32adfeeec34250f9530ce1dafd40c6233832315e065ea6b362d745e2f63cde0e"
- execObj, err := client.InspectExec(expectedID)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(*execObj, expected) {
- t.Errorf("ExecInspect: Expected %#v. Got %#v.", expected, *execObj)
- }
- req := fakeRT.requests[0]
- if req.Method != "GET" {
- t.Errorf("ExecInspect: wrong HTTP method. Want %q. Got %q.", "GET", req.Method)
- }
- expectedURL, _ := url.Parse(client.getURL("/exec/" + expectedID + "/json"))
- if gotPath := fakeRT.requests[0].URL.Path; gotPath != expectedURL.Path {
- t.Errorf("ExecInspect: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/image.go b/vendor/github.com/fsouza/go-dockerclient/image.go
deleted file mode 100644
index fd51c3f..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/image.go
+++ /dev/null
@@ -1,642 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "io"
- "net/http"
- "net/url"
- "os"
- "time"
-)
-
-// APIImages represent an image returned in the ListImages call.
-type APIImages struct {
- ID string `json:"Id" yaml:"Id"`
- RepoTags []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
- Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
- Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
- VirtualSize int64 `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
- ParentID string `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
- RepoDigests []string `json:"RepoDigests,omitempty" yaml:"RepoDigests,omitempty"`
- Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
-}
-
-// RootFS represents the underlying layers used by an image
-type RootFS struct {
- Type string `json:"Type,omitempty" yaml:"Type,omitempty"`
- Layers []string `json:"Layers,omitempty" yaml:"Layers,omitempty"`
-}
-
-// Image is the type representing a docker image and its various properties
-type Image struct {
- ID string `json:"Id" yaml:"Id"`
- RepoTags []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
- Parent string `json:"Parent,omitempty" yaml:"Parent,omitempty"`
- Comment string `json:"Comment,omitempty" yaml:"Comment,omitempty"`
- Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
- Container string `json:"Container,omitempty" yaml:"Container,omitempty"`
- ContainerConfig Config `json:"ContainerConfig,omitempty" yaml:"ContainerConfig,omitempty"`
- DockerVersion string `json:"DockerVersion,omitempty" yaml:"DockerVersion,omitempty"`
- Author string `json:"Author,omitempty" yaml:"Author,omitempty"`
- Config *Config `json:"Config,omitempty" yaml:"Config,omitempty"`
- Architecture string `json:"Architecture,omitempty" yaml:"Architecture,omitempty"`
- Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
- VirtualSize int64 `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
- RepoDigests []string `json:"RepoDigests,omitempty" yaml:"RepoDigests,omitempty"`
- RootFS *RootFS `json:"RootFS,omitempty" yaml:"RootFS,omitempty"`
-}
-
-// ImagePre012 serves the same purpose as the Image type except that it is for
-// earlier versions of the Docker API (pre-012 to be specific)
-type ImagePre012 struct {
- ID string `json:"id"`
- Parent string `json:"parent,omitempty"`
- Comment string `json:"comment,omitempty"`
- Created time.Time `json:"created"`
- Container string `json:"container,omitempty"`
- ContainerConfig Config `json:"container_config,omitempty"`
- DockerVersion string `json:"docker_version,omitempty"`
- Author string `json:"author,omitempty"`
- Config *Config `json:"config,omitempty"`
- Architecture string `json:"architecture,omitempty"`
- Size int64 `json:"size,omitempty"`
-}
-
-var (
- // ErrNoSuchImage is the error returned when the image does not exist.
- ErrNoSuchImage = errors.New("no such image")
-
- // ErrMissingRepo is the error returned when the remote repository is
- // missing.
- ErrMissingRepo = errors.New("missing remote repository e.g. 'github.com/user/repo'")
-
- // ErrMissingOutputStream is the error returned when no output stream
- // is provided to some calls, like BuildImage.
- ErrMissingOutputStream = errors.New("missing output stream")
-
- // ErrMultipleContexts is the error returned when both a ContextDir and
- // InputStream are provided in BuildImageOptions
- ErrMultipleContexts = errors.New("image build may not be provided BOTH context dir and input stream")
-
- // ErrMustSpecifyNames is the error rreturned when the Names field on
- // ExportImagesOptions is nil or empty
- ErrMustSpecifyNames = errors.New("must specify at least one name to export")
-)
-
-// ListImagesOptions specify parameters to the ListImages function.
-//
-// See https://goo.gl/xBe1u3 for more details.
-type ListImagesOptions struct {
- All bool
- Filters map[string][]string
- Digests bool
- Filter string
-}
-
-// ListImages returns the list of available images in the server.
-//
-// See https://goo.gl/xBe1u3 for more details.
-func (c *Client) ListImages(opts ListImagesOptions) ([]APIImages, error) {
- path := "/images/json?" + queryString(opts)
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var images []APIImages
- if err := json.NewDecoder(resp.Body).Decode(&images); err != nil {
- return nil, err
- }
- return images, nil
-}
-
-// ImageHistory represent a layer in an image's history returned by the
-// ImageHistory call.
-type ImageHistory struct {
- ID string `json:"Id" yaml:"Id"`
- Tags []string `json:"Tags,omitempty" yaml:"Tags,omitempty"`
- Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
- CreatedBy string `json:"CreatedBy,omitempty" yaml:"CreatedBy,omitempty"`
- Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
-}
-
-// ImageHistory returns the history of the image by its name or ID.
-//
-// See https://goo.gl/8bnTId for more details.
-func (c *Client) ImageHistory(name string) ([]ImageHistory, error) {
- resp, err := c.do("GET", "/images/"+name+"/history", doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, ErrNoSuchImage
- }
- return nil, err
- }
- defer resp.Body.Close()
- var history []ImageHistory
- if err := json.NewDecoder(resp.Body).Decode(&history); err != nil {
- return nil, err
- }
- return history, nil
-}
-
-// RemoveImage removes an image by its name or ID.
-//
-// See https://goo.gl/V3ZWnK for more details.
-func (c *Client) RemoveImage(name string) error {
- resp, err := c.do("DELETE", "/images/"+name, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return ErrNoSuchImage
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// RemoveImageOptions present the set of options available for removing an image
-// from a registry.
-//
-// See https://goo.gl/V3ZWnK for more details.
-type RemoveImageOptions struct {
- Force bool `qs:"force"`
- NoPrune bool `qs:"noprune"`
-}
-
-// RemoveImageExtended removes an image by its name or ID.
-// Extra params can be passed, see RemoveImageOptions
-//
-// See https://goo.gl/V3ZWnK for more details.
-func (c *Client) RemoveImageExtended(name string, opts RemoveImageOptions) error {
- uri := fmt.Sprintf("/images/%s?%s", name, queryString(&opts))
- resp, err := c.do("DELETE", uri, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return ErrNoSuchImage
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// InspectImage returns an image by its name or ID.
-//
-// See https://goo.gl/jHPcg6 for more details.
-func (c *Client) InspectImage(name string) (*Image, error) {
- resp, err := c.do("GET", "/images/"+name+"/json", doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, ErrNoSuchImage
- }
- return nil, err
- }
- defer resp.Body.Close()
-
- var image Image
-
- // if the caller elected to skip checking the server's version, assume it's the latest
- if c.SkipServerVersionCheck || c.expectedAPIVersion.GreaterThanOrEqualTo(apiVersion112) {
- if err := json.NewDecoder(resp.Body).Decode(&image); err != nil {
- return nil, err
- }
- } else {
- var imagePre012 ImagePre012
- if err := json.NewDecoder(resp.Body).Decode(&imagePre012); err != nil {
- return nil, err
- }
-
- image.ID = imagePre012.ID
- image.Parent = imagePre012.Parent
- image.Comment = imagePre012.Comment
- image.Created = imagePre012.Created
- image.Container = imagePre012.Container
- image.ContainerConfig = imagePre012.ContainerConfig
- image.DockerVersion = imagePre012.DockerVersion
- image.Author = imagePre012.Author
- image.Config = imagePre012.Config
- image.Architecture = imagePre012.Architecture
- image.Size = imagePre012.Size
- }
-
- return &image, nil
-}
-
-// PushImageOptions represents options to use in the PushImage method.
-//
-// See https://goo.gl/zPtZaT for more details.
-type PushImageOptions struct {
- // Name of the image
- Name string
-
- // Tag of the image
- Tag string
-
- // Registry server to push the image
- Registry string
-
- OutputStream io.Writer `qs:"-"`
- RawJSONStream bool `qs:"-"`
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// PushImage pushes an image to a remote registry, logging progress to w.
-//
-// An empty instance of AuthConfiguration may be used for unauthenticated
-// pushes.
-//
-// See https://goo.gl/zPtZaT for more details.
-func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error {
- if opts.Name == "" {
- return ErrNoSuchImage
- }
- headers, err := headersWithAuth(auth)
- if err != nil {
- return err
- }
- name := opts.Name
- opts.Name = ""
- path := "/images/" + name + "/push?" + queryString(&opts)
- return c.stream("POST", path, streamOptions{
- setRawTerminal: true,
- rawJSONStream: opts.RawJSONStream,
- headers: headers,
- stdout: opts.OutputStream,
- inactivityTimeout: opts.InactivityTimeout,
- })
-}
-
-// PullImageOptions present the set of options available for pulling an image
-// from a registry.
-//
-// See https://goo.gl/iJkZjD for more details.
-type PullImageOptions struct {
- Repository string `qs:"fromImage"`
- Registry string
- Tag string
-
- OutputStream io.Writer `qs:"-"`
- RawJSONStream bool `qs:"-"`
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// PullImage pulls an image from a remote registry, logging progress to
-// opts.OutputStream.
-//
-// See https://goo.gl/iJkZjD for more details.
-func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error {
- if opts.Repository == "" {
- return ErrNoSuchImage
- }
-
- headers, err := headersWithAuth(auth)
- if err != nil {
- return err
- }
- return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream, opts.InactivityTimeout)
-}
-
-func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool, timeout time.Duration) error {
- path := "/images/create?" + qs
- return c.stream("POST", path, streamOptions{
- setRawTerminal: true,
- headers: headers,
- in: in,
- stdout: w,
- rawJSONStream: rawJSONStream,
- inactivityTimeout: timeout,
- })
-}
-
-// LoadImageOptions represents the options for LoadImage Docker API Call
-//
-// See https://goo.gl/JyClMX for more details.
-type LoadImageOptions struct {
- InputStream io.Reader
-}
-
-// LoadImage imports a tarball docker image
-//
-// See https://goo.gl/JyClMX for more details.
-func (c *Client) LoadImage(opts LoadImageOptions) error {
- return c.stream("POST", "/images/load", streamOptions{
- setRawTerminal: true,
- in: opts.InputStream,
- })
-}
-
-// ExportImageOptions represent the options for ExportImage Docker API call.
-//
-// See https://goo.gl/le7vK8 for more details.
-type ExportImageOptions struct {
- Name string
- OutputStream io.Writer
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// ExportImage exports an image (as a tar file) into the stream.
-//
-// See https://goo.gl/le7vK8 for more details.
-func (c *Client) ExportImage(opts ExportImageOptions) error {
- return c.stream("GET", fmt.Sprintf("/images/%s/get", opts.Name), streamOptions{
- setRawTerminal: true,
- stdout: opts.OutputStream,
- inactivityTimeout: opts.InactivityTimeout,
- })
-}
-
-// ExportImagesOptions represent the options for ExportImages Docker API call
-//
-// See https://goo.gl/huC7HA for more details.
-type ExportImagesOptions struct {
- Names []string
- OutputStream io.Writer `qs:"-"`
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// ExportImages exports one or more images (as a tar file) into the stream
-//
-// See https://goo.gl/huC7HA for more details.
-func (c *Client) ExportImages(opts ExportImagesOptions) error {
- if opts.Names == nil || len(opts.Names) == 0 {
- return ErrMustSpecifyNames
- }
- return c.stream("GET", "/images/get?"+queryString(&opts), streamOptions{
- setRawTerminal: true,
- stdout: opts.OutputStream,
- inactivityTimeout: opts.InactivityTimeout,
- })
-}
-
-// ImportImageOptions present the set of informations available for importing
-// an image from a source file or the stdin.
-//
-// See https://goo.gl/iJkZjD for more details.
-type ImportImageOptions struct {
- Repository string `qs:"repo"`
- Source string `qs:"fromSrc"`
- Tag string `qs:"tag"`
-
- InputStream io.Reader `qs:"-"`
- OutputStream io.Writer `qs:"-"`
- RawJSONStream bool `qs:"-"`
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// ImportImage imports an image from a url, a file or stdin
-//
-// See https://goo.gl/iJkZjD for more details.
-func (c *Client) ImportImage(opts ImportImageOptions) error {
- if opts.Repository == "" {
- return ErrNoSuchImage
- }
- if opts.Source != "-" {
- opts.InputStream = nil
- }
- if opts.Source != "-" && !isURL(opts.Source) {
- f, err := os.Open(opts.Source)
- if err != nil {
- return err
- }
- opts.InputStream = f
- opts.Source = "-"
- }
- return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, opts.RawJSONStream, opts.InactivityTimeout)
-}
-
-// BuildImageOptions present the set of informations available for building an
-// image from a tarfile with a Dockerfile in it.
-//
-// For more details about the Docker building process, see
-// http://goo.gl/tlPXPu.
-type BuildImageOptions struct {
- Name string `qs:"t"`
- Dockerfile string `qs:"dockerfile"`
- NoCache bool `qs:"nocache"`
- SuppressOutput bool `qs:"q"`
- Pull bool `qs:"pull"`
- RmTmpContainer bool `qs:"rm"`
- ForceRmTmpContainer bool `qs:"forcerm"`
- Memory int64 `qs:"memory"`
- Memswap int64 `qs:"memswap"`
- CPUShares int64 `qs:"cpushares"`
- CPUQuota int64 `qs:"cpuquota"`
- CPUPeriod int64 `qs:"cpuperiod"`
- CPUSetCPUs string `qs:"cpusetcpus"`
- InputStream io.Reader `qs:"-"`
- OutputStream io.Writer `qs:"-"`
- RawJSONStream bool `qs:"-"`
- Remote string `qs:"remote"`
- Auth AuthConfiguration `qs:"-"` // for older docker X-Registry-Auth header
- AuthConfigs AuthConfigurations `qs:"-"` // for newer docker X-Registry-Config header
- ContextDir string `qs:"-"`
- Ulimits []ULimit `qs:"-"`
- BuildArgs []BuildArg `qs:"-"`
- InactivityTimeout time.Duration `qs:"-"`
-}
-
-// BuildArg represents arguments that can be passed to the image when building
-// it from a Dockerfile.
-//
-// For more details about the Docker building process, see
-// http://goo.gl/tlPXPu.
-type BuildArg struct {
- Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
- Value string `json:"Value,omitempty" yaml:"Value,omitempty"`
-}
-
-// BuildImage builds an image from a tarball's url or a Dockerfile in the input
-// stream.
-//
-// See https://goo.gl/xySxCe for more details.
-func (c *Client) BuildImage(opts BuildImageOptions) error {
- if opts.OutputStream == nil {
- return ErrMissingOutputStream
- }
- headers, err := headersWithAuth(opts.Auth, c.versionedAuthConfigs(opts.AuthConfigs))
- if err != nil {
- return err
- }
-
- if opts.Remote != "" && opts.Name == "" {
- opts.Name = opts.Remote
- }
- if opts.InputStream != nil || opts.ContextDir != "" {
- headers["Content-Type"] = "application/tar"
- } else if opts.Remote == "" {
- return ErrMissingRepo
- }
- if opts.ContextDir != "" {
- if opts.InputStream != nil {
- return ErrMultipleContexts
- }
- var err error
- if opts.InputStream, err = createTarStream(opts.ContextDir, opts.Dockerfile); err != nil {
- return err
- }
- }
-
- qs := queryString(&opts)
- if len(opts.Ulimits) > 0 {
- if b, err := json.Marshal(opts.Ulimits); err == nil {
- item := url.Values(map[string][]string{})
- item.Add("ulimits", string(b))
- qs = fmt.Sprintf("%s&%s", qs, item.Encode())
- }
- }
-
- if len(opts.BuildArgs) > 0 {
- v := make(map[string]string)
- for _, arg := range opts.BuildArgs {
- v[arg.Name] = arg.Value
- }
- if b, err := json.Marshal(v); err == nil {
- item := url.Values(map[string][]string{})
- item.Add("buildargs", string(b))
- qs = fmt.Sprintf("%s&%s", qs, item.Encode())
- }
- }
-
- return c.stream("POST", fmt.Sprintf("/build?%s", qs), streamOptions{
- setRawTerminal: true,
- rawJSONStream: opts.RawJSONStream,
- headers: headers,
- in: opts.InputStream,
- stdout: opts.OutputStream,
- inactivityTimeout: opts.InactivityTimeout,
- })
-}
-
-func (c *Client) versionedAuthConfigs(authConfigs AuthConfigurations) interface{} {
- if c.serverAPIVersion == nil {
- c.checkAPIVersion()
- }
- if c.serverAPIVersion != nil && c.serverAPIVersion.GreaterThanOrEqualTo(apiVersion119) {
- return AuthConfigurations119(authConfigs.Configs)
- }
- return authConfigs
-}
-
-// TagImageOptions present the set of options to tag an image.
-//
-// See https://goo.gl/98ZzkU for more details.
-type TagImageOptions struct {
- Repo string
- Tag string
- Force bool
-}
-
-// TagImage adds a tag to the image identified by the given name.
-//
-// See https://goo.gl/98ZzkU for more details.
-func (c *Client) TagImage(name string, opts TagImageOptions) error {
- if name == "" {
- return ErrNoSuchImage
- }
- resp, err := c.do("POST", fmt.Sprintf("/images/"+name+"/tag?%s",
- queryString(&opts)), doOptions{})
-
- if err != nil {
- return err
- }
-
- defer resp.Body.Close()
-
- if resp.StatusCode == http.StatusNotFound {
- return ErrNoSuchImage
- }
-
- return err
-}
-
-func isURL(u string) bool {
- p, err := url.Parse(u)
- if err != nil {
- return false
- }
- return p.Scheme == "http" || p.Scheme == "https"
-}
-
-func headersWithAuth(auths ...interface{}) (map[string]string, error) {
- var headers = make(map[string]string)
-
- for _, auth := range auths {
- switch auth.(type) {
- case AuthConfiguration:
- var buf bytes.Buffer
- if err := json.NewEncoder(&buf).Encode(auth); err != nil {
- return nil, err
- }
- headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())
- case AuthConfigurations, AuthConfigurations119:
- var buf bytes.Buffer
- if err := json.NewEncoder(&buf).Encode(auth); err != nil {
- return nil, err
- }
- headers["X-Registry-Config"] = base64.URLEncoding.EncodeToString(buf.Bytes())
- }
- }
-
- return headers, nil
-}
-
-// APIImageSearch reflect the result of a search on the Docker Hub.
-//
-// See https://goo.gl/AYjyrF for more details.
-type APIImageSearch struct {
- Description string `json:"description,omitempty" yaml:"description,omitempty"`
- IsOfficial bool `json:"is_official,omitempty" yaml:"is_official,omitempty"`
- IsAutomated bool `json:"is_automated,omitempty" yaml:"is_automated,omitempty"`
- Name string `json:"name,omitempty" yaml:"name,omitempty"`
- StarCount int `json:"star_count,omitempty" yaml:"star_count,omitempty"`
-}
-
-// SearchImages search the docker hub with a specific given term.
-//
-// See https://goo.gl/AYjyrF for more details.
-func (c *Client) SearchImages(term string) ([]APIImageSearch, error) {
- resp, err := c.do("GET", "/images/search?term="+term, doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var searchResult []APIImageSearch
- if err := json.NewDecoder(resp.Body).Decode(&searchResult); err != nil {
- return nil, err
- }
- return searchResult, nil
-}
-
-// SearchImagesEx search the docker hub with a specific given term and authentication.
-//
-// See https://goo.gl/AYjyrF for more details.
-func (c *Client) SearchImagesEx(term string, auth AuthConfiguration) ([]APIImageSearch, error) {
- headers, err := headersWithAuth(auth)
- if err != nil {
- return nil, err
- }
-
- resp, err := c.do("GET", "/images/search?term="+term, doOptions{
- headers: headers,
- })
- if err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- var searchResult []APIImageSearch
- if err := json.NewDecoder(resp.Body).Decode(&searchResult); err != nil {
- return nil, err
- }
-
- return searchResult, nil
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/image_test.go b/vendor/github.com/fsouza/go-dockerclient/image_test.go
deleted file mode 100644
index 1ba35bd..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/image_test.go
+++ /dev/null
@@ -1,1034 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bytes"
- "encoding/base64"
- "encoding/json"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
- "os"
- "reflect"
- "strings"
- "testing"
- "time"
-)
-
-func newTestClient(rt *FakeRoundTripper) Client {
- endpoint := "http://localhost:4243"
- u, _ := parseEndpoint("http://localhost:4243", false)
- testAPIVersion, _ := NewAPIVersion("1.17")
- client := Client{
- HTTPClient: &http.Client{Transport: rt},
- Dialer: &net.Dialer{},
- endpoint: endpoint,
- endpointURL: u,
- SkipServerVersionCheck: true,
- serverAPIVersion: testAPIVersion,
- }
- return client
-}
-
-type stdoutMock struct {
- *bytes.Buffer
-}
-
-func (m stdoutMock) Close() error {
- return nil
-}
-
-type stdinMock struct {
- *bytes.Buffer
-}
-
-func (m stdinMock) Close() error {
- return nil
-}
-
-func TestListImages(t *testing.T) {
- body := `[
- {
- "Repository":"base",
- "Tag":"ubuntu-12.10",
- "Id":"b750fe79269d",
- "Created":1364102658
- },
- {
- "Repository":"base",
- "Tag":"ubuntu-quantal",
- "Id":"b750fe79269d",
- "Created":1364102658
- },
- {
- "RepoTag": [
- "ubuntu:12.04",
- "ubuntu:precise",
- "ubuntu:latest"
- ],
- "Id": "8dbd9e392a964c",
- "Created": 1365714795,
- "Size": 131506275,
- "VirtualSize": 131506275
- },
- {
- "RepoTag": [
- "ubuntu:12.10",
- "ubuntu:quantal"
- ],
- "ParentId": "27cf784147099545",
- "Id": "b750fe79269d2e",
- "Created": 1364102658,
- "Size": 24653,
- "VirtualSize": 180116135
- }
-]`
- var expected []APIImages
- err := json.Unmarshal([]byte(body), &expected)
- if err != nil {
- t.Fatal(err)
- }
- client := newTestClient(&FakeRoundTripper{message: body, status: http.StatusOK})
- images, err := client.ListImages(ListImagesOptions{})
- if err != nil {
- t.Error(err)
- }
- if !reflect.DeepEqual(images, expected) {
- t.Errorf("ListImages: Wrong return value. Want %#v. Got %#v.", expected, images)
- }
-}
-
-func TestListImagesParameters(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "null", status: http.StatusOK}
- client := newTestClient(fakeRT)
- _, err := client.ListImages(ListImagesOptions{All: false})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "GET" {
- t.Errorf("ListImages({All: false}: Wrong HTTP method. Want GET. Got %s.", req.Method)
- }
- if all := req.URL.Query().Get("all"); all != "0" && all != "" {
- t.Errorf("ListImages({All: false}): Wrong parameter. Want all=0 or not present at all. Got all=%s", all)
- }
- fakeRT.Reset()
- _, err = client.ListImages(ListImagesOptions{All: true})
- if err != nil {
- t.Fatal(err)
- }
- req = fakeRT.requests[0]
- if all := req.URL.Query().Get("all"); all != "1" {
- t.Errorf("ListImages({All: true}): Wrong parameter. Want all=1. Got all=%s", all)
- }
- fakeRT.Reset()
- _, err = client.ListImages(ListImagesOptions{Filters: map[string][]string{
- "dangling": {"true"},
- }})
- if err != nil {
- t.Fatal(err)
- }
- req = fakeRT.requests[0]
- body := req.URL.Query().Get("filters")
- var filters map[string][]string
- err = json.Unmarshal([]byte(body), &filters)
- if err != nil {
- t.Fatal(err)
- }
- if len(filters["dangling"]) != 1 || filters["dangling"][0] != "true" {
- t.Errorf("ListImages(dangling=[true]): Wrong filter map. Want dangling=[true], got dangling=%v", filters["dangling"])
- }
-}
-
-func TestImageHistory(t *testing.T) {
- body := `[
- {
- "Id": "25daec02219d2d852f7526137213a9b199926b4b24e732eab5b8bc6c49bd470e",
- "Tags": [
- "debian:7.6",
- "debian:latest",
- "debian:7",
- "debian:wheezy"
- ],
- "Created": 1409856216,
- "CreatedBy": "/bin/sh -c #(nop) CMD [/bin/bash]"
- },
- {
- "Id": "41026a5347fb5be6ed16115bf22df8569697139f246186de9ae8d4f67c335dce",
- "Created": 1409856213,
- "CreatedBy": "/bin/sh -c #(nop) ADD file:1ee9e97209d00e3416a4543b23574cc7259684741a46bbcbc755909b8a053a38 in /",
- "Size": 85178663
- },
- {
- "Id": "511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158",
- "Tags": [
- "scratch:latest"
- ],
- "Created": 1371157430
- }
-]`
- var expected []ImageHistory
- err := json.Unmarshal([]byte(body), &expected)
- if err != nil {
- t.Fatal(err)
- }
- client := newTestClient(&FakeRoundTripper{message: body, status: http.StatusOK})
- history, err := client.ImageHistory("debian:latest")
- if err != nil {
- t.Error(err)
- }
- if !reflect.DeepEqual(history, expected) {
- t.Errorf("ImageHistory: Wrong return value. Want %#v. Got %#v.", expected, history)
- }
-}
-
-func TestRemoveImage(t *testing.T) {
- name := "test"
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- err := client.RemoveImage(name)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedMethod := "DELETE"
- if req.Method != expectedMethod {
- t.Errorf("RemoveImage(%q): Wrong HTTP method. Want %s. Got %s.", name, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/images/" + name))
- if req.URL.Path != u.Path {
- t.Errorf("RemoveImage(%q): Wrong request path. Want %q. Got %q.", name, u.Path, req.URL.Path)
- }
-}
-
-func TestRemoveImageNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such image", status: http.StatusNotFound})
- err := client.RemoveImage("test:")
- if err != ErrNoSuchImage {
- t.Errorf("RemoveImage: wrong error. Want %#v. Got %#v.", ErrNoSuchImage, err)
- }
-}
-
-func TestRemoveImageExtended(t *testing.T) {
- name := "test"
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- err := client.RemoveImageExtended(name, RemoveImageOptions{Force: true, NoPrune: true})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedMethod := "DELETE"
- if req.Method != expectedMethod {
- t.Errorf("RemoveImage(%q): Wrong HTTP method. Want %s. Got %s.", name, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/images/" + name))
- if req.URL.Path != u.Path {
- t.Errorf("RemoveImage(%q): Wrong request path. Want %q. Got %q.", name, u.Path, req.URL.Path)
- }
- expectedQuery := "force=1&noprune=1"
- if query := req.URL.Query().Encode(); query != expectedQuery {
- t.Errorf("PushImage: Wrong query string. Want %q. Got %q.", expectedQuery, query)
- }
-}
-
-func TestInspectImage(t *testing.T) {
- body := `{
- "Id":"b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
- "Parent":"27cf784147099545",
- "Created":"2013-03-23T22:24:18.818426Z",
- "Container":"3d67245a8d72ecf13f33dffac9f79dcdf70f75acb84d308770391510e0c23ad0",
- "ContainerConfig":{"Memory":1},
- "VirtualSize":12345,
- "RootFS": {
- "Type": "layers",
- "Layers": [
- "sha256:05a0deb2e405eb3095ab646dc1695a26bffe8bd4071e3af90efcf16e9d3f6d93",
- "sha256:4c5db681b9aa9ab1cf666ec969a810c8ff4410e70e06394670dc4f3bf595532f"
- ]
- }
-}`
-
- created, err := time.Parse(time.RFC3339Nano, "2013-03-23T22:24:18.818426Z")
- if err != nil {
- t.Fatal(err)
- }
-
- expected := Image{
- ID: "b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc",
- Parent: "27cf784147099545",
- Created: created,
- Container: "3d67245a8d72ecf13f33dffac9f79dcdf70f75acb84d308770391510e0c23ad0",
- ContainerConfig: Config{
- Memory: 1,
- },
- VirtualSize: 12345,
- RootFS: &RootFS{
- Type: "layers",
- Layers: []string{
- "sha256:05a0deb2e405eb3095ab646dc1695a26bffe8bd4071e3af90efcf16e9d3f6d93",
- "sha256:4c5db681b9aa9ab1cf666ec969a810c8ff4410e70e06394670dc4f3bf595532f",
- },
- },
- }
- fakeRT := &FakeRoundTripper{message: body, status: http.StatusOK}
- client := newTestClient(fakeRT)
- image, err := client.InspectImage(expected.ID)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(*image, expected) {
- t.Errorf("InspectImage(%q): Wrong image returned. Want %#v. Got %#v.", expected.ID, expected, *image)
- }
- req := fakeRT.requests[0]
- if req.Method != "GET" {
- t.Errorf("InspectImage(%q): Wrong HTTP method. Want GET. Got %s.", expected.ID, req.Method)
- }
- u, _ := url.Parse(client.getURL("/images/" + expected.ID + "/json"))
- if req.URL.Path != u.Path {
- t.Errorf("InspectImage(%q): Wrong request URL. Want %q. Got %q.", expected.ID, u.Path, req.URL.Path)
- }
-}
-
-func TestInspectImageNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such image", status: http.StatusNotFound})
- name := "test"
- image, err := client.InspectImage(name)
- if image != nil {
- t.Errorf("InspectImage(%q): expected image, got %#v.", name, image)
- }
- if err != ErrNoSuchImage {
- t.Errorf("InspectImage(%q): wrong error. Want %#v. Got %#v.", name, ErrNoSuchImage, err)
- }
-}
-
-func TestPushImage(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "Pushing 1/100", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- err := client.PushImage(PushImageOptions{Name: "test", OutputStream: &buf}, AuthConfiguration{})
- if err != nil {
- t.Fatal(err)
- }
- expected := "Pushing 1/100"
- if buf.String() != expected {
- t.Errorf("PushImage: Wrong output. Want %q. Got %q.", expected, buf.String())
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("PushImage: Wrong HTTP method. Want POST. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/images/test/push"))
- if req.URL.Path != u.Path {
- t.Errorf("PushImage: Wrong request path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
- if query := req.URL.Query().Encode(); query != "" {
- t.Errorf("PushImage: Wrong query string. Want no parameters, got %q.", query)
- }
-
- auth, err := base64.URLEncoding.DecodeString(req.Header.Get("X-Registry-Auth"))
- if err != nil {
- t.Errorf("PushImage: caught error decoding auth. %#v", err.Error())
- }
- if strings.TrimSpace(string(auth)) != "{}" {
- t.Errorf("PushImage: wrong body. Want %q. Got %q.",
- base64.URLEncoding.EncodeToString([]byte("{}")), req.Header.Get("X-Registry-Auth"))
- }
-}
-
-func TestPushImageWithRawJSON(t *testing.T) {
- body := `
- {"status":"Pushing..."}
- {"status":"Pushing", "progress":"1/? (n/a)", "progressDetail":{"current":1}}}
- {"status":"Image successfully pushed"}
- `
- fakeRT := &FakeRoundTripper{
- message: body,
- status: http.StatusOK,
- header: map[string]string{
- "Content-Type": "application/json",
- },
- }
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
-
- err := client.PushImage(PushImageOptions{
- Name: "test",
- OutputStream: &buf,
- RawJSONStream: true,
- }, AuthConfiguration{})
- if err != nil {
- t.Fatal(err)
- }
- if buf.String() != body {
- t.Errorf("PushImage: Wrong raw output. Want %q. Got %q.", body, buf.String())
- }
-}
-
-func TestPushImageWithAuthentication(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "Pushing 1/100", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- inputAuth := AuthConfiguration{
- Username: "gopher",
- Password: "gopher123",
- Email: "gopher@tsuru.io",
- }
- err := client.PushImage(PushImageOptions{Name: "test", OutputStream: &buf}, inputAuth)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- var gotAuth AuthConfiguration
-
- auth, err := base64.URLEncoding.DecodeString(req.Header.Get("X-Registry-Auth"))
- if err != nil {
- t.Errorf("PushImage: caught error decoding auth. %#v", err.Error())
- }
-
- err = json.Unmarshal(auth, &gotAuth)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(gotAuth, inputAuth) {
- t.Errorf("PushImage: wrong auth configuration. Want %#v. Got %#v.", inputAuth, gotAuth)
- }
-}
-
-func TestPushImageCustomRegistry(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "Pushing 1/100", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var authConfig AuthConfiguration
- var buf bytes.Buffer
- opts := PushImageOptions{
- Name: "test", Registry: "docker.tsuru.io",
- OutputStream: &buf,
- }
- err := client.PushImage(opts, authConfig)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedQuery := "registry=docker.tsuru.io"
- if query := req.URL.Query().Encode(); query != expectedQuery {
- t.Errorf("PushImage: Wrong query string. Want %q. Got %q.", expectedQuery, query)
- }
-}
-
-func TestPushImageNoName(t *testing.T) {
- client := Client{}
- err := client.PushImage(PushImageOptions{}, AuthConfiguration{})
- if err != ErrNoSuchImage {
- t.Errorf("PushImage: got wrong error. Want %#v. Got %#v.", ErrNoSuchImage, err)
- }
-}
-
-func TestPullImage(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "Pulling 1/100", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- err := client.PullImage(PullImageOptions{Repository: "base", OutputStream: &buf},
- AuthConfiguration{})
- if err != nil {
- t.Fatal(err)
- }
- expected := "Pulling 1/100"
- if buf.String() != expected {
- t.Errorf("PullImage: Wrong output. Want %q. Got %q.", expected, buf.String())
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("PullImage: Wrong HTTP method. Want POST. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/images/create"))
- if req.URL.Path != u.Path {
- t.Errorf("PullImage: Wrong request path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
- expectedQuery := "fromImage=base"
- if query := req.URL.Query().Encode(); query != expectedQuery {
- t.Errorf("PullImage: Wrong query strin. Want %q. Got %q.", expectedQuery, query)
- }
-}
-
-func TestPullImageWithRawJSON(t *testing.T) {
- body := `
- {"status":"Pulling..."}
- {"status":"Pulling", "progress":"1 B/ 100 B", "progressDetail":{"current":1, "total":100}}
- `
- fakeRT := &FakeRoundTripper{
- message: body,
- status: http.StatusOK,
- header: map[string]string{
- "Content-Type": "application/json",
- },
- }
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- err := client.PullImage(PullImageOptions{
- Repository: "base",
- OutputStream: &buf,
- RawJSONStream: true,
- }, AuthConfiguration{})
- if err != nil {
- t.Fatal(err)
- }
- if buf.String() != body {
- t.Errorf("PullImage: Wrong raw output. Want %q. Got %q", body, buf.String())
- }
-}
-
-func TestPullImageWithoutOutputStream(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "Pulling 1/100", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := PullImageOptions{
- Repository: "base",
- Registry: "docker.tsuru.io",
- }
- err := client.PullImage(opts, AuthConfiguration{})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"fromImage": {"base"}, "registry": {"docker.tsuru.io"}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("PullImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestPullImageCustomRegistry(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "Pulling 1/100", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := PullImageOptions{
- Repository: "base",
- Registry: "docker.tsuru.io",
- OutputStream: &buf,
- }
- err := client.PullImage(opts, AuthConfiguration{})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"fromImage": {"base"}, "registry": {"docker.tsuru.io"}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("PullImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestPullImageTag(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "Pulling 1/100", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := PullImageOptions{
- Repository: "base",
- Registry: "docker.tsuru.io",
- Tag: "latest",
- OutputStream: &buf,
- }
- err := client.PullImage(opts, AuthConfiguration{})
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"fromImage": {"base"}, "registry": {"docker.tsuru.io"}, "tag": {"latest"}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("PullImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestPullImageNoRepository(t *testing.T) {
- var opts PullImageOptions
- client := Client{}
- err := client.PullImage(opts, AuthConfiguration{})
- if err != ErrNoSuchImage {
- t.Errorf("PullImage: got wrong error. Want %#v. Got %#v.", ErrNoSuchImage, err)
- }
-}
-
-func TestImportImageFromUrl(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := ImportImageOptions{
- Source: "http://mycompany.com/file.tar",
- Repository: "testimage",
- Tag: "tag",
- OutputStream: &buf,
- }
- err := client.ImportImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"fromSrc": {opts.Source}, "repo": {opts.Repository}, "tag": {opts.Tag}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("ImportImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestImportImageFromInput(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- in := bytes.NewBufferString("tar content")
- var buf bytes.Buffer
- opts := ImportImageOptions{
- Source: "-", Repository: "testimage",
- InputStream: in, OutputStream: &buf,
- Tag: "tag",
- }
- err := client.ImportImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"fromSrc": {opts.Source}, "repo": {opts.Repository}, "tag": {opts.Tag}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("ImportImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
- body, err := ioutil.ReadAll(req.Body)
- if err != nil {
- t.Errorf("ImportImage: caugth error while reading body %#v", err.Error())
- }
- e := "tar content"
- if string(body) != e {
- t.Errorf("ImportImage: wrong body. Want %#v. Got %#v.", e, string(body))
- }
-}
-
-func TestImportImageDoesNotPassesInputIfSourceIsNotDash(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- in := bytes.NewBufferString("foo")
- opts := ImportImageOptions{
- Source: "http://test.com/container.tar", Repository: "testimage",
- InputStream: in, OutputStream: &buf,
- }
- err := client.ImportImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"fromSrc": {opts.Source}, "repo": {opts.Repository}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("ImportImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
- body, err := ioutil.ReadAll(req.Body)
- if err != nil {
- t.Errorf("ImportImage: caugth error while reading body %#v", err.Error())
- }
- if string(body) != "" {
- t.Errorf("ImportImage: wrong body. Want nothing. Got %#v.", string(body))
- }
-}
-
-func TestImportImageShouldPassTarContentToBodyWhenSourceIsFilePath(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- tarPath := "testing/data/container.tar"
- opts := ImportImageOptions{
- Source: tarPath, Repository: "testimage",
- OutputStream: &buf,
- }
- err := client.ImportImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- tar, err := os.Open(tarPath)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- tarContent, err := ioutil.ReadAll(tar)
- body, err := ioutil.ReadAll(req.Body)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(tarContent, body) {
- t.Errorf("ImportImage: wrong body. Want %#v content. Got %#v.", tarPath, body)
- }
-}
-
-func TestImportImageShouldChangeSourceToDashWhenItsAFilePath(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- tarPath := "testing/data/container.tar"
- opts := ImportImageOptions{
- Source: tarPath, Repository: "testimage",
- OutputStream: &buf,
- }
- err := client.ImportImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"fromSrc": {"-"}, "repo": {opts.Repository}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("ImportImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestBuildImageParameters(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Name: "testImage",
- NoCache: true,
- SuppressOutput: true,
- Pull: true,
- RmTmpContainer: true,
- ForceRmTmpContainer: true,
- Memory: 1024,
- Memswap: 2048,
- CPUShares: 10,
- CPUQuota: 7500,
- CPUPeriod: 100000,
- CPUSetCPUs: "0-3",
- Ulimits: []ULimit{{Name: "nofile", Soft: 100, Hard: 200}},
- BuildArgs: []BuildArg{{Name: "SOME_VAR", Value: "some_value"}},
- InputStream: &buf,
- OutputStream: &buf,
- }
- err := client.BuildImage(opts)
- if err != nil && strings.Index(err.Error(), "build image fail") == -1 {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{
- "t": {opts.Name},
- "nocache": {"1"},
- "q": {"1"},
- "pull": {"1"},
- "rm": {"1"},
- "forcerm": {"1"},
- "memory": {"1024"},
- "memswap": {"2048"},
- "cpushares": {"10"},
- "cpuquota": {"7500"},
- "cpuperiod": {"100000"},
- "cpusetcpus": {"0-3"},
- "ulimits": {`[{"Name":"nofile","Soft":100,"Hard":200}]`},
- "buildargs": {`{"SOME_VAR":"some_value"}`},
- }
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("BuildImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestBuildImageParametersForRemoteBuild(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Name: "testImage",
- Remote: "testing/data/container.tar",
- SuppressOutput: true,
- OutputStream: &buf,
- }
- err := client.BuildImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"t": {opts.Name}, "remote": {opts.Remote}, "q": {"1"}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("BuildImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestBuildImageMissingRepoAndNilInput(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Name: "testImage",
- SuppressOutput: true,
- OutputStream: &buf,
- }
- err := client.BuildImage(opts)
- if err != ErrMissingRepo {
- t.Errorf("BuildImage: wrong error returned. Want %#v. Got %#v.", ErrMissingRepo, err)
- }
-}
-
-func TestBuildImageMissingOutputStream(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := BuildImageOptions{Name: "testImage"}
- err := client.BuildImage(opts)
- if err != ErrMissingOutputStream {
- t.Errorf("BuildImage: wrong error returned. Want %#v. Got %#v.", ErrMissingOutputStream, err)
- }
-}
-
-func TestBuildImageWithRawJSON(t *testing.T) {
- body := `
- {"stream":"Step 0 : FROM ubuntu:latest\n"}
- {"stream":" ---\u003e 4300eb9d3c8d\n"}
- {"stream":"Step 1 : MAINTAINER docker \n"}
- {"stream":" ---\u003e Using cache\n"}
- {"stream":" ---\u003e 3a3ed758c370\n"}
- {"stream":"Step 2 : CMD /usr/bin/top\n"}
- {"stream":" ---\u003e Running in 36b1479cc2e4\n"}
- {"stream":" ---\u003e 4b6188aebe39\n"}
- {"stream":"Removing intermediate container 36b1479cc2e4\n"}
- {"stream":"Successfully built 4b6188aebe39\n"}
- `
- fakeRT := &FakeRoundTripper{
- message: body,
- status: http.StatusOK,
- header: map[string]string{
- "Content-Type": "application/json",
- },
- }
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Name: "testImage",
- RmTmpContainer: true,
- InputStream: &buf,
- OutputStream: &buf,
- RawJSONStream: true,
- }
- err := client.BuildImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- if buf.String() != body {
- t.Errorf("BuildImage: Wrong raw output. Want %q. Got %q.", body, buf.String())
- }
-}
-
-func TestBuildImageRemoteWithoutName(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- var buf bytes.Buffer
- opts := BuildImageOptions{
- Remote: "testing/data/container.tar",
- SuppressOutput: true,
- OutputStream: &buf,
- }
- err := client.BuildImage(opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := map[string][]string{"t": {opts.Remote}, "remote": {opts.Remote}, "q": {"1"}}
- got := map[string][]string(req.URL.Query())
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("BuildImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestTagImageParameters(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := TagImageOptions{Repo: "testImage"}
- err := client.TagImage("base", opts)
- if err != nil && strings.Index(err.Error(), "tag image fail") == -1 {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expected := "http://localhost:4243/images/base/tag?repo=testImage"
- got := req.URL.String()
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("TagImage: wrong query string. Want %#v. Got %#v.", expected, got)
- }
-}
-
-func TestTagImageMissingRepo(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := TagImageOptions{Repo: "testImage"}
- err := client.TagImage("", opts)
- if err != ErrNoSuchImage {
- t.Errorf("TestTag: wrong error returned. Want %#v. Got %#v.",
- ErrNoSuchImage, err)
- }
-}
-
-func TestIsUrl(t *testing.T) {
- url := "http://foo.bar/"
- result := isURL(url)
- if !result {
- t.Errorf("isURL: wrong match. Expected %#v to be a url. Got %#v.", url, result)
- }
- url = "/foo/bar.tar"
- result = isURL(url)
- if result {
- t.Errorf("isURL: wrong match. Expected %#v to not be a url. Got %#v", url, result)
- }
-}
-
-func TestLoadImage(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- tar, err := os.Open("testing/data/container.tar")
- if err != nil {
- t.Fatal(err)
- } else {
- defer tar.Close()
- }
- opts := LoadImageOptions{InputStream: tar}
- err = client.LoadImage(opts)
- if nil != err {
- t.Error(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "POST" {
- t.Errorf("LoadImage: wrong method. Expected %q. Got %q.", "POST", req.Method)
- }
- if req.URL.Path != "/images/load" {
- t.Errorf("LoadImage: wrong URL. Expected %q. Got %q.", "/images/load", req.URL.Path)
- }
-}
-
-func TestExportImage(t *testing.T) {
- var buf bytes.Buffer
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := ExportImageOptions{Name: "testimage", OutputStream: &buf}
- err := client.ExportImage(opts)
- if nil != err {
- t.Error(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "GET" {
- t.Errorf("ExportImage: wrong method. Expected %q. Got %q.", "GET", req.Method)
- }
- expectedPath := "/images/testimage/get"
- if req.URL.Path != expectedPath {
- t.Errorf("ExportIMage: wrong path. Expected %q. Got %q.", expectedPath, req.URL.Path)
- }
-}
-
-func TestExportImages(t *testing.T) {
- var buf bytes.Buffer
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := ExportImagesOptions{Names: []string{"testimage1", "testimage2:latest"}, OutputStream: &buf}
- err := client.ExportImages(opts)
- if nil != err {
- t.Error(err)
- }
- req := fakeRT.requests[0]
- if req.Method != "GET" {
- t.Errorf("ExportImage: wrong method. Expected %q. Got %q.", "GET", req.Method)
- }
- expected := "http://localhost:4243/images/get?names=testimage1&names=testimage2%3Alatest"
- got := req.URL.String()
- if !reflect.DeepEqual(got, expected) {
- t.Errorf("ExportIMage: wrong path. Expected %q. Got %q.", expected, got)
- }
-}
-
-func TestExportImagesNoNames(t *testing.T) {
- var buf bytes.Buffer
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := ExportImagesOptions{Names: []string{}, OutputStream: &buf}
- err := client.ExportImages(opts)
- if err == nil {
- t.Error("Expected an error")
- }
- if err != ErrMustSpecifyNames {
- t.Error(err)
- }
-}
-
-func TestSearchImages(t *testing.T) {
- body := `[
- {
- "description":"A container with Cassandra 2.0.3",
- "is_official":true,
- "is_automated":true,
- "name":"poklet/cassandra",
- "star_count":17
- },
- {
- "description":"A container with Cassandra 2.0.3",
- "is_official":true,
- "is_automated":false,
- "name":"poklet/cassandra",
- "star_count":17
- }
- ,
- {
- "description":"A container with Cassandra 2.0.3",
- "is_official":false,
- "is_automated":true,
- "name":"poklet/cassandra",
- "star_count":17
- }
-]`
- var expected []APIImageSearch
- err := json.Unmarshal([]byte(body), &expected)
- if err != nil {
- t.Fatal(err)
- }
- client := newTestClient(&FakeRoundTripper{message: body, status: http.StatusOK})
- result, err := client.SearchImages("cassandra")
- if err != nil {
- t.Error(err)
- }
- if !reflect.DeepEqual(result, expected) {
- t.Errorf("SearchImages: Wrong return value. Want %#v. Got %#v.", expected, result)
- }
-}
-
-func TestSearchImagesEx(t *testing.T) {
- body := `[
- {
- "description":"A container with Cassandra 2.0.3",
- "is_official":true,
- "is_automated":true,
- "name":"poklet/cassandra",
- "star_count":17
- },
- {
- "description":"A container with Cassandra 2.0.3",
- "is_official":true,
- "is_automated":false,
- "name":"poklet/cassandra",
- "star_count":17
- }
- ,
- {
- "description":"A container with Cassandra 2.0.3",
- "is_official":false,
- "is_automated":true,
- "name":"poklet/cassandra",
- "star_count":17
- }
-]`
- var expected []APIImageSearch
- err := json.Unmarshal([]byte(body), &expected)
- if err != nil {
- t.Fatal(err)
- }
- client := newTestClient(&FakeRoundTripper{message: body, status: http.StatusOK})
- auth := AuthConfiguration{}
- result, err := client.SearchImagesEx("cassandra", auth)
- if err != nil {
- t.Error(err)
- }
- if !reflect.DeepEqual(result, expected) {
- t.Errorf("SearchImages: Wrong return value. Want %#v. Got %#v.", expected, result)
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/integration_test.go b/vendor/github.com/fsouza/go-dockerclient/integration_test.go
deleted file mode 100644
index f13c2a7..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/integration_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker_integration
-
-package docker
-
-import (
- "bytes"
- "os"
- "testing"
-)
-
-var dockerEndpoint string
-
-func init() {
- dockerEndpoint = os.Getenv("DOCKER_HOST")
- if dockerEndpoint == "" {
- dockerEndpoint = "unix:///var/run/docker.sock"
- }
-}
-
-func TestIntegrationPullCreateStartLogs(t *testing.T) {
- imageName := pullImage(t)
- client := getClient()
- hostConfig := HostConfig{PublishAllPorts: true}
- createOpts := CreateContainerOptions{
- Config: &Config{
- Image: imageName,
- Cmd: []string{"cat", "/home/gopher/file.txt"},
- User: "gopher",
- },
- HostConfig: &hostConfig,
- }
- container, err := client.CreateContainer(createOpts)
- if err != nil {
- t.Fatal(err)
- }
- err = client.StartContainer(container.ID, &hostConfig)
- if err != nil {
- t.Fatal(err)
- }
- status, err := client.WaitContainer(container.ID)
- if err != nil {
- t.Error(err)
- }
- if status != 0 {
- t.Errorf("WaitContainer(%q): wrong status. Want 0. Got %d", container.ID, status)
- }
- var stdout, stderr bytes.Buffer
- logsOpts := LogsOptions{
- Container: container.ID,
- OutputStream: &stdout,
- ErrorStream: &stderr,
- Stdout: true,
- Stderr: true,
- }
- err = client.Logs(logsOpts)
- if err != nil {
- t.Error(err)
- }
- if stderr.String() != "" {
- t.Errorf("Got unexpected stderr from logs: %q", stderr.String())
- }
- expected := `Welcome to reality, wake up and rejoice
-Welcome to reality, you've made the right choice
-Welcome to reality, and let them hear your voice, shout it out!
-`
- if stdout.String() != expected {
- t.Errorf("Got wrong stdout from logs.\nWant:\n%#v.\n\nGot:\n%#v.", expected, stdout.String())
- }
-}
-
-func pullImage(t *testing.T) string {
- imageName := "fsouza/go-dockerclient-integration"
- var buf bytes.Buffer
- pullOpts := PullImageOptions{
- Repository: imageName,
- OutputStream: &buf,
- }
- client := getClient()
- err := client.PullImage(pullOpts, AuthConfiguration{})
- if err != nil {
- t.Logf("Pull output: %s", buf.String())
- t.Fatal(err)
- }
- return imageName
-}
-
-func getClient() *Client {
- client, _ := NewClient(dockerEndpoint)
- return client
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/misc.go b/vendor/github.com/fsouza/go-dockerclient/misc.go
deleted file mode 100644
index ce9e975..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/misc.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "encoding/json"
- "strings"
-)
-
-// Version returns version information about the docker server.
-//
-// See https://goo.gl/ND9R8L for more details.
-func (c *Client) Version() (*Env, error) {
- resp, err := c.do("GET", "/version", doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var env Env
- if err := env.Decode(resp.Body); err != nil {
- return nil, err
- }
- return &env, nil
-}
-
-// DockerInfo contains information about the Docker server
-//
-// See https://goo.gl/bHUoz9 for more details.
-type DockerInfo struct {
- ID string
- Containers int
- ContainersRunning int
- ContainersPaused int
- ContainersStopped int
- Images int
- Driver string
- DriverStatus [][2]string
- SystemStatus [][2]string
- Plugins PluginsInfo
- MemoryLimit bool
- SwapLimit bool
- KernelMemory bool
- CPUCfsPeriod bool `json:"CpuCfsPeriod"`
- CPUCfsQuota bool `json:"CpuCfsQuota"`
- CPUShares bool
- CPUSet bool
- IPv4Forwarding bool
- BridgeNfIptables bool
- BridgeNfIP6tables bool `json:"BridgeNfIp6tables"`
- Debug bool
- NFd int
- OomKillDisable bool
- NGoroutines int
- SystemTime string
- ExecutionDriver string
- LoggingDriver string
- CgroupDriver string
- NEventsListener int
- KernelVersion string
- OperatingSystem string
- OSType string
- Architecture string
- IndexServerAddress string
- NCPU int
- MemTotal int64
- DockerRootDir string
- HTTPProxy string `json:"HttpProxy"`
- HTTPSProxy string `json:"HttpsProxy"`
- NoProxy string
- Name string
- Labels []string
- ExperimentalBuild bool
- ServerVersion string
- ClusterStore string
- ClusterAdvertise string
-}
-
-// PluginsInfo is a struct with the plugins registered with the docker daemon
-//
-// for more information, see: https://goo.gl/bHUoz9
-type PluginsInfo struct {
- // List of Volume plugins registered
- Volume []string
- // List of Network plugins registered
- Network []string
- // List of Authorization plugins registered
- Authorization []string
-}
-
-// Info returns system-wide information about the Docker server.
-//
-// See https://goo.gl/ElTHi2 for more details.
-func (c *Client) Info() (*DockerInfo, error) {
- resp, err := c.do("GET", "/info", doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var info DockerInfo
- if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
- return nil, err
- }
- return &info, nil
-}
-
-// ParseRepositoryTag gets the name of the repository and returns it splitted
-// in two parts: the repository and the tag.
-//
-// Some examples:
-//
-// localhost.localdomain:5000/samalba/hipache:latest -> localhost.localdomain:5000/samalba/hipache, latest
-// localhost.localdomain:5000/samalba/hipache -> localhost.localdomain:5000/samalba/hipache, ""
-func ParseRepositoryTag(repoTag string) (repository string, tag string) {
- n := strings.LastIndex(repoTag, ":")
- if n < 0 {
- return repoTag, ""
- }
- if tag := repoTag[n+1:]; !strings.Contains(tag, "/") {
- return repoTag[:n], tag
- }
- return repoTag, ""
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/misc_test.go b/vendor/github.com/fsouza/go-dockerclient/misc_test.go
deleted file mode 100644
index 824e5a4..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/misc_test.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2014 go-dockerclient 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 docker
-
-import (
- "net/http"
- "net/url"
- "reflect"
- "testing"
-)
-
-type DockerVersion struct {
- Version string
- GitCommit string
- GoVersion string
-}
-
-func TestVersion(t *testing.T) {
- body := `{
- "Version":"0.2.2",
- "GitCommit":"5a2a5cc+CHANGES",
- "GoVersion":"go1.0.3"
-}`
- fakeRT := FakeRoundTripper{message: body, status: http.StatusOK}
- client := newTestClient(&fakeRT)
- expected := DockerVersion{
- Version: "0.2.2",
- GitCommit: "5a2a5cc+CHANGES",
- GoVersion: "go1.0.3",
- }
- version, err := client.Version()
- if err != nil {
- t.Fatal(err)
- }
-
- if result := version.Get("Version"); result != expected.Version {
- t.Errorf("Version(): Wrong result. Want %#v. Got %#v.", expected.Version, version.Get("Version"))
- }
- if result := version.Get("GitCommit"); result != expected.GitCommit {
- t.Errorf("GitCommit(): Wrong result. Want %#v. Got %#v.", expected.GitCommit, version.Get("GitCommit"))
- }
- if result := version.Get("GoVersion"); result != expected.GoVersion {
- t.Errorf("GoVersion(): Wrong result. Want %#v. Got %#v.", expected.GoVersion, version.Get("GoVersion"))
- }
- req := fakeRT.requests[0]
- if req.Method != "GET" {
- t.Errorf("Version(): wrong request method. Want GET. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/version"))
- if req.URL.Path != u.Path {
- t.Errorf("Version(): wrong request path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
-}
-
-func TestVersionError(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "internal error", status: http.StatusInternalServerError}
- client := newTestClient(fakeRT)
- version, err := client.Version()
- if version != nil {
- t.Errorf("Version(): expected value, got %#v.", version)
- }
- if err == nil {
- t.Error("Version(): unexpected error")
- }
-}
-
-func TestInfo(t *testing.T) {
- body := `{
- "Containers":11,
- "Images":16,
- "Debug":false,
- "NFd":11,
- "NGoroutines":21,
- "MemoryLimit":true,
- "SwapLimit":false
-}`
- fakeRT := FakeRoundTripper{message: body, status: http.StatusOK}
- client := newTestClient(&fakeRT)
- expected := &DockerInfo{
- Containers: 11,
- Images: 16,
- Debug: false,
- NFd: 11,
- NGoroutines: 21,
- MemoryLimit: true,
- SwapLimit: false,
- }
- info, err := client.Info()
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(expected, info) {
- t.Errorf("Info(): Wrong result.\nWant %#v.\nGot %#v.", expected, info)
- }
- req := fakeRT.requests[0]
- if req.Method != "GET" {
- t.Errorf("Info(): Wrong HTTP method. Want GET. Got %s.", req.Method)
- }
- u, _ := url.Parse(client.getURL("/info"))
- if req.URL.Path != u.Path {
- t.Errorf("Info(): Wrong request path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
-}
-
-func TestInfoError(t *testing.T) {
- fakeRT := &FakeRoundTripper{message: "internal error", status: http.StatusInternalServerError}
- client := newTestClient(fakeRT)
- version, err := client.Info()
- if version != nil {
- t.Errorf("Info(): expected value, got %#v.", version)
- }
- if err == nil {
- t.Error("Info(): unexpected error")
- }
-}
-
-func TestParseRepositoryTag(t *testing.T) {
- var tests = []struct {
- input string
- expectedRepo string
- expectedTag string
- }{
- {
- "localhost.localdomain:5000/samalba/hipache:latest",
- "localhost.localdomain:5000/samalba/hipache",
- "latest",
- },
- {
- "localhost.localdomain:5000/samalba/hipache",
- "localhost.localdomain:5000/samalba/hipache",
- "",
- },
- {
- "tsuru/python",
- "tsuru/python",
- "",
- },
- {
- "tsuru/python:2.7",
- "tsuru/python",
- "2.7",
- },
- }
- for _, tt := range tests {
- repo, tag := ParseRepositoryTag(tt.input)
- if repo != tt.expectedRepo {
- t.Errorf("ParseRepositoryTag(%q): wrong repository. Want %q. Got %q", tt.input, tt.expectedRepo, repo)
- }
- if tag != tt.expectedTag {
- t.Errorf("ParseRepositoryTag(%q): wrong tag. Want %q. Got %q", tt.input, tt.expectedTag, tag)
- }
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/network.go b/vendor/github.com/fsouza/go-dockerclient/network.go
deleted file mode 100644
index 07a1a57..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/network.go
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bytes"
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
-)
-
-// ErrNetworkAlreadyExists is the error returned by CreateNetwork when the
-// network already exists.
-var ErrNetworkAlreadyExists = errors.New("network already exists")
-
-// Network represents a network.
-//
-// See https://goo.gl/6GugX3 for more details.
-type Network struct {
- Name string
- ID string `json:"Id"`
- Scope string
- Driver string
- IPAM IPAMOptions
- Containers map[string]Endpoint
- Options map[string]string
- Internal bool
- EnableIPv6 bool `json:"EnableIPv6"`
-}
-
-// Endpoint contains network resources allocated and used for a container in a network
-//
-// See https://goo.gl/6GugX3 for more details.
-type Endpoint struct {
- Name string
- ID string `json:"EndpointID"`
- MacAddress string
- IPv4Address string
- IPv6Address string
-}
-
-// ListNetworks returns all networks.
-//
-// See https://goo.gl/6GugX3 for more details.
-func (c *Client) ListNetworks() ([]Network, error) {
- resp, err := c.do("GET", "/networks", doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var networks []Network
- if err := json.NewDecoder(resp.Body).Decode(&networks); err != nil {
- return nil, err
- }
- return networks, nil
-}
-
-// NetworkFilterOpts is an aggregation of key=value that Docker
-// uses to filter networks
-type NetworkFilterOpts map[string]map[string]bool
-
-// FilteredListNetworks returns all networks with the filters applied
-//
-// See goo.gl/zd2mx4 for more details.
-func (c *Client) FilteredListNetworks(opts NetworkFilterOpts) ([]Network, error) {
- params := bytes.NewBuffer(nil)
- if err := json.NewEncoder(params).Encode(&opts); err != nil {
- return nil, err
- }
- path := "/networks?filters=" + params.String()
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var networks []Network
- if err := json.NewDecoder(resp.Body).Decode(&networks); err != nil {
- return nil, err
- }
- return networks, nil
-}
-
-// NetworkInfo returns information about a network by its ID.
-//
-// See https://goo.gl/6GugX3 for more details.
-func (c *Client) NetworkInfo(id string) (*Network, error) {
- path := "/networks/" + id
- resp, err := c.do("GET", path, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, &NoSuchNetwork{ID: id}
- }
- return nil, err
- }
- defer resp.Body.Close()
- var network Network
- if err := json.NewDecoder(resp.Body).Decode(&network); err != nil {
- return nil, err
- }
- return &network, nil
-}
-
-// CreateNetworkOptions specify parameters to the CreateNetwork function and
-// (for now) is the expected body of the "create network" http request message
-//
-// See https://goo.gl/6GugX3 for more details.
-type CreateNetworkOptions struct {
- Name string `json:"Name"`
- CheckDuplicate bool `json:"CheckDuplicate"`
- Driver string `json:"Driver"`
- IPAM IPAMOptions `json:"IPAM"`
- Options map[string]interface{} `json:"Options"`
- Internal bool `json:"Internal"`
- EnableIPv6 bool `json:"EnableIPv6"`
-}
-
-// IPAMOptions controls IP Address Management when creating a network
-//
-// See https://goo.gl/T8kRVH for more details.
-type IPAMOptions struct {
- Driver string `json:"Driver"`
- Config []IPAMConfig `json:"Config"`
-}
-
-// IPAMConfig represents IPAM configurations
-//
-// See https://goo.gl/T8kRVH for more details.
-type IPAMConfig struct {
- Subnet string `json:",omitempty"`
- IPRange string `json:",omitempty"`
- Gateway string `json:",omitempty"`
- AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
-}
-
-// CreateNetwork creates a new network, returning the network instance,
-// or an error in case of failure.
-//
-// See https://goo.gl/6GugX3 for more details.
-func (c *Client) CreateNetwork(opts CreateNetworkOptions) (*Network, error) {
- resp, err := c.do(
- "POST",
- "/networks/create",
- doOptions{
- data: opts,
- },
- )
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusConflict {
- return nil, ErrNetworkAlreadyExists
- }
- return nil, err
- }
- defer resp.Body.Close()
-
- type createNetworkResponse struct {
- ID string
- }
- var (
- network Network
- cnr createNetworkResponse
- )
- if err := json.NewDecoder(resp.Body).Decode(&cnr); err != nil {
- return nil, err
- }
-
- network.Name = opts.Name
- network.ID = cnr.ID
- network.Driver = opts.Driver
-
- return &network, nil
-}
-
-// RemoveNetwork removes a network or returns an error in case of failure.
-//
-// See https://goo.gl/6GugX3 for more details.
-func (c *Client) RemoveNetwork(id string) error {
- resp, err := c.do("DELETE", "/networks/"+id, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchNetwork{ID: id}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// NetworkConnectionOptions specify parameters to the ConnectNetwork and
-// DisconnectNetwork function.
-//
-// See https://goo.gl/RV7BJU for more details.
-type NetworkConnectionOptions struct {
- Container string
-
- // EndpointConfig is only applicable to the ConnectNetwork call
- EndpointConfig *EndpointConfig `json:"EndpointConfig,omitempty"`
-
- // Force is only applicable to the DisconnectNetwork call
- Force bool
-}
-
-// EndpointConfig stores network endpoint details
-//
-// See https://goo.gl/RV7BJU for more details.
-type EndpointConfig struct {
- IPAMConfig *EndpointIPAMConfig
- Links []string
- Aliases []string
- NetworkID string
- EndpointID string
- Gateway string
- IPAddress string
- IPPrefixLen int
- IPv6Gateway string
- GlobalIPv6Address string
- GlobalIPv6PrefixLen int
- MacAddress string
-}
-
-// EndpointIPAMConfig represents IPAM configurations for an
-// endpoint
-//
-// See https://goo.gl/RV7BJU for more details.
-type EndpointIPAMConfig struct {
- IPv4Address string `json:",omitempty"`
- IPv6Address string `json:",omitempty"`
-}
-
-// ConnectNetwork adds a container to a network or returns an error in case of
-// failure.
-//
-// See https://goo.gl/6GugX3 for more details.
-func (c *Client) ConnectNetwork(id string, opts NetworkConnectionOptions) error {
- resp, err := c.do("POST", "/networks/"+id+"/connect", doOptions{data: opts})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchNetworkOrContainer{NetworkID: id, ContainerID: opts.Container}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// DisconnectNetwork removes a container from a network or returns an error in
-// case of failure.
-//
-// See https://goo.gl/6GugX3 for more details.
-func (c *Client) DisconnectNetwork(id string, opts NetworkConnectionOptions) error {
- resp, err := c.do("POST", "/networks/"+id+"/disconnect", doOptions{data: opts})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return &NoSuchNetworkOrContainer{NetworkID: id, ContainerID: opts.Container}
- }
- return err
- }
- resp.Body.Close()
- return nil
-}
-
-// NoSuchNetwork is the error returned when a given network does not exist.
-type NoSuchNetwork struct {
- ID string
-}
-
-func (err *NoSuchNetwork) Error() string {
- return fmt.Sprintf("No such network: %s", err.ID)
-}
-
-// NoSuchNetworkOrContainer is the error returned when a given network or
-// container does not exist.
-type NoSuchNetworkOrContainer struct {
- NetworkID string
- ContainerID string
-}
-
-func (err *NoSuchNetworkOrContainer) Error() string {
- return fmt.Sprintf("No such network (%s) or container (%s)", err.NetworkID, err.ContainerID)
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/network_test.go b/vendor/github.com/fsouza/go-dockerclient/network_test.go
deleted file mode 100644
index 3f9ac06..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/network_test.go
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "bytes"
- "encoding/json"
- "net/http"
- "net/url"
- "reflect"
- "testing"
-)
-
-func TestListNetworks(t *testing.T) {
- jsonNetworks := `[
- {
- "ID": "8dfafdbc3a40",
- "Name": "blah",
- "Type": "bridge",
- "Endpoints":[{"ID": "918c11c8288a", "Name": "dsafdsaf", "Network": "8dfafdbc3a40"}]
- },
- {
- "ID": "9fb1e39c",
- "Name": "foo",
- "Type": "bridge",
- "Endpoints":[{"ID": "c080be979dda", "Name": "lllll2222", "Network": "9fb1e39c"}]
- }
-]`
- var expected []Network
- err := json.Unmarshal([]byte(jsonNetworks), &expected)
- if err != nil {
- t.Fatal(err)
- }
- client := newTestClient(&FakeRoundTripper{message: jsonNetworks, status: http.StatusOK})
- containers, err := client.ListNetworks()
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(containers, expected) {
- t.Errorf("ListNetworks: Expected %#v. Got %#v.", expected, containers)
- }
-}
-
-func TestFilteredListNetworks(t *testing.T) {
- jsonNetworks := `[
- {
- "ID": "9fb1e39c",
- "Name": "foo",
- "Type": "bridge",
- "Endpoints":[{"ID": "c080be979dda", "Name": "lllll2222", "Network": "9fb1e39c"}]
- }
-]`
- var expected []Network
- err := json.Unmarshal([]byte(jsonNetworks), &expected)
- if err != nil {
- t.Fatal(err)
- }
- wantQuery := "filters={\"name\":{\"blah\":true}}\n"
- fakeRT := &FakeRoundTripper{message: jsonNetworks, status: http.StatusOK}
- client := newTestClient(fakeRT)
- opts := NetworkFilterOpts{
- "name": map[string]bool{"blah": true},
- }
- containers, err := client.FilteredListNetworks(opts)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(containers, expected) {
- t.Errorf("ListNetworks: Expected %#v. Got %#v.", expected, containers)
- }
- query := fakeRT.requests[0].URL.RawQuery
- if query != wantQuery {
- t.Errorf("FilteredListNetworks: Expected query: %q, got: %q", wantQuery, query)
- }
-}
-
-func TestNetworkInfo(t *testing.T) {
- jsonNetwork := `{
- "ID": "8dfafdbc3a40",
- "Name": "blah",
- "Type": "bridge",
- "Endpoints":[{"ID": "918c11c8288a", "Name": "dsafdsaf", "Network": "8dfafdbc3a40"}]
- }`
- var expected Network
- err := json.Unmarshal([]byte(jsonNetwork), &expected)
- if err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: jsonNetwork, status: http.StatusOK}
- client := newTestClient(fakeRT)
- id := "8dfafdbc3a40"
- network, err := client.NetworkInfo(id)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(*network, expected) {
- t.Errorf("NetworkInfo(%q): Expected %#v. Got %#v.", id, expected, network)
- }
- expectedURL, _ := url.Parse(client.getURL("/networks/8dfafdbc3a40"))
- if gotPath := fakeRT.requests[0].URL.Path; gotPath != expectedURL.Path {
- t.Errorf("NetworkInfo(%q): Wrong path in request. Want %q. Got %q.", id, expectedURL.Path, gotPath)
- }
-}
-
-func TestNetworkCreate(t *testing.T) {
- jsonID := `{"ID": "8dfafdbc3a40"}`
- jsonNetwork := `{
- "ID": "8dfafdbc3a40",
- "Name": "foobar",
- "Driver": "bridge"
- }`
- var expected Network
- err := json.Unmarshal([]byte(jsonNetwork), &expected)
- if err != nil {
- t.Fatal(err)
- }
-
- client := newTestClient(&FakeRoundTripper{message: jsonID, status: http.StatusOK})
- opts := CreateNetworkOptions{"foobar", false, "bridge", IPAMOptions{}, nil, false, false}
- network, err := client.CreateNetwork(opts)
- if err != nil {
- t.Fatal(err)
- }
-
- if !reflect.DeepEqual(*network, expected) {
- t.Errorf("CreateNetwork: Expected %#v. Got %#v.", expected, network)
- }
-}
-
-func TestNetworkRemove(t *testing.T) {
- id := "8dfafdbc3a40"
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- err := client.RemoveNetwork(id)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedMethod := "DELETE"
- if req.Method != expectedMethod {
- t.Errorf("RemoveNetwork(%q): Wrong HTTP method. Want %s. Got %s.", id, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/networks/" + id))
- if req.URL.Path != u.Path {
- t.Errorf("RemoveNetwork(%q): Wrong request path. Want %q. Got %q.", id, u.Path, req.URL.Path)
- }
-}
-
-func TestNetworkConnect(t *testing.T) {
- id := "8dfafdbc3a40"
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- opts := NetworkConnectionOptions{Container: "foobar"}
- err := client.ConnectNetwork(id, opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedMethod := "POST"
- if req.Method != expectedMethod {
- t.Errorf("ConnectNetwork(%q): Wrong HTTP method. Want %s. Got %s.", id, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/networks/" + id + "/connect"))
- if req.URL.Path != u.Path {
- t.Errorf("ConnectNetwork(%q): Wrong request path. Want %q. Got %q.", id, u.Path, req.URL.Path)
- }
-}
-
-func TestNetworkConnectWithEndpoint(t *testing.T) {
- wantJSON := `{"Container":"foobar","EndpointConfig":{"IPAMConfig":{"IPv4Address":"8.8.8.8"},"Links":null,"Aliases":null},"Force":false}`
- var wantObj NetworkConnectionOptions
- json.NewDecoder(bytes.NewBuffer([]byte(wantJSON))).Decode(&wantObj)
- id := "8dfafdbc3a40"
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- opts := NetworkConnectionOptions{
- Container: "foobar",
- EndpointConfig: &EndpointConfig{
- IPAMConfig: &EndpointIPAMConfig{
- IPv4Address: "8.8.8.8",
- },
- },
- }
- err := client.ConnectNetwork(id, opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedMethod := "POST"
- if req.Method != expectedMethod {
- t.Errorf("ConnectNetwork(%q): Wrong HTTP method. Want %s. Got %s.", id, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/networks/" + id + "/connect"))
- if req.URL.Path != u.Path {
- t.Errorf("ConnectNetwork(%q): Wrong request path. Want %q. Got %q.", id, u.Path, req.URL.Path)
- }
- var in NetworkConnectionOptions
- if err := json.NewDecoder(req.Body).Decode(&in); err != nil {
- t.Errorf("ConnectNetwork: error parsing JSON data sent: %q", err)
- }
- if !reflect.DeepEqual(in, wantObj) {
- t.Errorf("ConnectNetwork: wanted %#v send, got: %#v", wantObj, in)
- }
-}
-
-func TestNetworkConnectNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such network container", status: http.StatusNotFound})
- opts := NetworkConnectionOptions{Container: "foobar"}
- err := client.ConnectNetwork("8dfafdbc3a40", opts)
- if serr, ok := err.(*NoSuchNetworkOrContainer); !ok {
- t.Errorf("ConnectNetwork: wrong error type: %s.", serr)
- }
-}
-
-func TestNetworkDisconnect(t *testing.T) {
- id := "8dfafdbc3a40"
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- opts := NetworkConnectionOptions{Container: "foobar"}
- err := client.DisconnectNetwork(id, opts)
- if err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedMethod := "POST"
- if req.Method != expectedMethod {
- t.Errorf("DisconnectNetwork(%q): Wrong HTTP method. Want %s. Got %s.", id, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/networks/" + id + "/disconnect"))
- if req.URL.Path != u.Path {
- t.Errorf("DisconnectNetwork(%q): Wrong request path. Want %q. Got %q.", id, u.Path, req.URL.Path)
- }
-}
-
-func TestNetworkDisconnectNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such network container", status: http.StatusNotFound})
- opts := NetworkConnectionOptions{Container: "foobar"}
- err := client.DisconnectNetwork("8dfafdbc3a40", opts)
- if serr, ok := err.(*NoSuchNetworkOrContainer); !ok {
- t.Errorf("DisconnectNetwork: wrong error type: %s.", serr)
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/signal.go b/vendor/github.com/fsouza/go-dockerclient/signal.go
deleted file mode 100644
index 16aa003..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/signal.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 go-dockerclient 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 docker
-
-// Signal represents a signal that can be send to the container on
-// KillContainer call.
-type Signal int
-
-// These values represent all signals available on Linux, where containers will
-// be running.
-const (
- SIGABRT = Signal(0x6)
- SIGALRM = Signal(0xe)
- SIGBUS = Signal(0x7)
- SIGCHLD = Signal(0x11)
- SIGCLD = Signal(0x11)
- SIGCONT = Signal(0x12)
- SIGFPE = Signal(0x8)
- SIGHUP = Signal(0x1)
- SIGILL = Signal(0x4)
- SIGINT = Signal(0x2)
- SIGIO = Signal(0x1d)
- SIGIOT = Signal(0x6)
- SIGKILL = Signal(0x9)
- SIGPIPE = Signal(0xd)
- SIGPOLL = Signal(0x1d)
- SIGPROF = Signal(0x1b)
- SIGPWR = Signal(0x1e)
- SIGQUIT = Signal(0x3)
- SIGSEGV = Signal(0xb)
- SIGSTKFLT = Signal(0x10)
- SIGSTOP = Signal(0x13)
- SIGSYS = Signal(0x1f)
- SIGTERM = Signal(0xf)
- SIGTRAP = Signal(0x5)
- SIGTSTP = Signal(0x14)
- SIGTTIN = Signal(0x15)
- SIGTTOU = Signal(0x16)
- SIGUNUSED = Signal(0x1f)
- SIGURG = Signal(0x17)
- SIGUSR1 = Signal(0xa)
- SIGUSR2 = Signal(0xc)
- SIGVTALRM = Signal(0x1a)
- SIGWINCH = Signal(0x1c)
- SIGXCPU = Signal(0x18)
- SIGXFSZ = Signal(0x19)
-)
diff --git a/vendor/github.com/fsouza/go-dockerclient/tar.go b/vendor/github.com/fsouza/go-dockerclient/tar.go
deleted file mode 100644
index 11e51b4..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/tar.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "path"
- "path/filepath"
- "strings"
-
- "github.com/docker/docker/pkg/archive"
- "github.com/docker/docker/pkg/fileutils"
-)
-
-func createTarStream(srcPath, dockerfilePath string) (io.ReadCloser, error) {
- excludes, err := parseDockerignore(srcPath)
- if err != nil {
- return nil, err
- }
-
- includes := []string{"."}
-
- // If .dockerignore mentions .dockerignore or the Dockerfile
- // then make sure we send both files over to the daemon
- // because Dockerfile is, obviously, needed no matter what, and
- // .dockerignore is needed to know if either one needs to be
- // removed. The deamon will remove them for us, if needed, after it
- // parses the Dockerfile.
- //
- // https://github.com/docker/docker/issues/8330
- //
- forceIncludeFiles := []string{".dockerignore", dockerfilePath}
-
- for _, includeFile := range forceIncludeFiles {
- if includeFile == "" {
- continue
- }
- keepThem, err := fileutils.Matches(includeFile, excludes)
- if err != nil {
- return nil, fmt.Errorf("cannot match .dockerfile: '%s', error: %s", includeFile, err)
- }
- if keepThem {
- includes = append(includes, includeFile)
- }
- }
-
- if err := validateContextDirectory(srcPath, excludes); err != nil {
- return nil, err
- }
- tarOpts := &archive.TarOptions{
- ExcludePatterns: excludes,
- IncludeFiles: includes,
- Compression: archive.Uncompressed,
- NoLchown: true,
- }
- return archive.TarWithOptions(srcPath, tarOpts)
-}
-
-// validateContextDirectory checks if all the contents of the directory
-// can be read and returns an error if some files can't be read.
-// Symlinks which point to non-existing files don't trigger an error
-func validateContextDirectory(srcPath string, excludes []string) error {
- return filepath.Walk(filepath.Join(srcPath, "."), func(filePath string, f os.FileInfo, err error) error {
- // skip this directory/file if it's not in the path, it won't get added to the context
- if relFilePath, err := filepath.Rel(srcPath, filePath); err != nil {
- return err
- } else if skip, err := fileutils.Matches(relFilePath, excludes); err != nil {
- return err
- } else if skip {
- if f.IsDir() {
- return filepath.SkipDir
- }
- return nil
- }
-
- if err != nil {
- if os.IsPermission(err) {
- return fmt.Errorf("can't stat '%s'", filePath)
- }
- if os.IsNotExist(err) {
- return nil
- }
- return err
- }
-
- // skip checking if symlinks point to non-existing files, such symlinks can be useful
- // also skip named pipes, because they hanging on open
- if f.Mode()&(os.ModeSymlink|os.ModeNamedPipe) != 0 {
- return nil
- }
-
- if !f.IsDir() {
- currentFile, err := os.Open(filePath)
- if err != nil && os.IsPermission(err) {
- return fmt.Errorf("no permission to read from '%s'", filePath)
- }
- currentFile.Close()
- }
- return nil
- })
-}
-
-func parseDockerignore(root string) ([]string, error) {
- var excludes []string
- ignore, err := ioutil.ReadFile(path.Join(root, ".dockerignore"))
- if err != nil && !os.IsNotExist(err) {
- return excludes, fmt.Errorf("error reading .dockerignore: '%s'", err)
- }
- excludes = strings.Split(string(ignore), "\n")
-
- return excludes, nil
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/tls.go b/vendor/github.com/fsouza/go-dockerclient/tls.go
deleted file mode 100644
index bb5790b..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/tls.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2014 go-dockerclient authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
-// The content is borrowed from Docker's own source code to provide a simple
-// tls based dialer
-
-package docker
-
-import (
- "crypto/tls"
- "errors"
- "net"
- "strings"
- "time"
-)
-
-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 cwc, ok := c.rawConn.(interface {
- CloseWrite() error
- }); ok {
- return cwc.CloseWrite()
- }
- return nil
-}
-
-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("")
- })
- }
-
- rawConn, err := dialer.Dial(network, addr)
- if err != nil {
- return nil, err
- }
-
- 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.
- config = copyTLSConfig(config)
- config.ServerName = hostname
- }
-
- 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
-}
-
-// this exists to silent an error message in go vet
-func copyTLSConfig(cfg *tls.Config) *tls.Config {
- return &tls.Config{
- Certificates: cfg.Certificates,
- CipherSuites: cfg.CipherSuites,
- ClientAuth: cfg.ClientAuth,
- ClientCAs: cfg.ClientCAs,
- ClientSessionCache: cfg.ClientSessionCache,
- CurvePreferences: cfg.CurvePreferences,
- InsecureSkipVerify: cfg.InsecureSkipVerify,
- MaxVersion: cfg.MaxVersion,
- MinVersion: cfg.MinVersion,
- NameToCertificate: cfg.NameToCertificate,
- NextProtos: cfg.NextProtos,
- PreferServerCipherSuites: cfg.PreferServerCipherSuites,
- Rand: cfg.Rand,
- RootCAs: cfg.RootCAs,
- ServerName: cfg.ServerName,
- SessionTicketKey: cfg.SessionTicketKey,
- SessionTicketsDisabled: cfg.SessionTicketsDisabled,
- }
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/volume.go b/vendor/github.com/fsouza/go-dockerclient/volume.go
deleted file mode 100644
index 5fe8ee3..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/volume.go
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "encoding/json"
- "errors"
- "net/http"
-)
-
-var (
- // ErrNoSuchVolume is the error returned when the volume does not exist.
- ErrNoSuchVolume = errors.New("no such volume")
-
- // ErrVolumeInUse is the error returned when the volume requested to be removed is still in use.
- ErrVolumeInUse = errors.New("volume in use and cannot be removed")
-)
-
-// Volume represents a volume.
-//
-// See https://goo.gl/FZA4BK for more details.
-type Volume struct {
- Name string `json:"Name" yaml:"Name"`
- Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"`
- Mountpoint string `json:"Mountpoint,omitempty" yaml:"Mountpoint,omitempty"`
- Labels map[string]string `json:"Labels,omitempty" yaml:"Labels,omitempty"`
-}
-
-// ListVolumesOptions specify parameters to the ListVolumes function.
-//
-// See https://goo.gl/FZA4BK for more details.
-type ListVolumesOptions struct {
- Filters map[string][]string
-}
-
-// ListVolumes returns a list of available volumes in the server.
-//
-// See https://goo.gl/FZA4BK for more details.
-func (c *Client) ListVolumes(opts ListVolumesOptions) ([]Volume, error) {
- resp, err := c.do("GET", "/volumes?"+queryString(opts), doOptions{})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- m := make(map[string]interface{})
- if err := json.NewDecoder(resp.Body).Decode(&m); err != nil {
- return nil, err
- }
- var volumes []Volume
- volumesJSON, ok := m["Volumes"]
- if !ok {
- return volumes, nil
- }
- data, err := json.Marshal(volumesJSON)
- if err != nil {
- return nil, err
- }
- if err := json.Unmarshal(data, &volumes); err != nil {
- return nil, err
- }
- return volumes, nil
-}
-
-// CreateVolumeOptions specify parameters to the CreateVolume function.
-//
-// See https://goo.gl/pBUbZ9 for more details.
-type CreateVolumeOptions struct {
- Name string
- Driver string
- DriverOpts map[string]string
-}
-
-// CreateVolume creates a volume on the server.
-//
-// See https://goo.gl/pBUbZ9 for more details.
-func (c *Client) CreateVolume(opts CreateVolumeOptions) (*Volume, error) {
- resp, err := c.do("POST", "/volumes/create", doOptions{data: opts})
- if err != nil {
- return nil, err
- }
- defer resp.Body.Close()
- var volume Volume
- if err := json.NewDecoder(resp.Body).Decode(&volume); err != nil {
- return nil, err
- }
- return &volume, nil
-}
-
-// InspectVolume returns a volume by its name.
-//
-// See https://goo.gl/0g9A6i for more details.
-func (c *Client) InspectVolume(name string) (*Volume, error) {
- resp, err := c.do("GET", "/volumes/"+name, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
- return nil, ErrNoSuchVolume
- }
- return nil, err
- }
- defer resp.Body.Close()
- var volume Volume
- if err := json.NewDecoder(resp.Body).Decode(&volume); err != nil {
- return nil, err
- }
- return &volume, nil
-}
-
-// RemoveVolume removes a volume by its name.
-//
-// See https://goo.gl/79GNQz for more details.
-func (c *Client) RemoveVolume(name string) error {
- resp, err := c.do("DELETE", "/volumes/"+name, doOptions{})
- if err != nil {
- if e, ok := err.(*Error); ok {
- if e.Status == http.StatusNotFound {
- return ErrNoSuchVolume
- }
- if e.Status == http.StatusConflict {
- return ErrVolumeInUse
- }
- }
- return nil
- }
- defer resp.Body.Close()
- return nil
-}
diff --git a/vendor/github.com/fsouza/go-dockerclient/volume_test.go b/vendor/github.com/fsouza/go-dockerclient/volume_test.go
deleted file mode 100644
index e6bcca9..0000000
--- a/vendor/github.com/fsouza/go-dockerclient/volume_test.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2015 go-dockerclient 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 docker
-
-import (
- "encoding/json"
- "net/http"
- "net/url"
- "reflect"
- "testing"
-)
-
-func TestListVolumes(t *testing.T) {
- volumesData := `[
- {
- "Name": "tardis",
- "Driver": "local",
- "Mountpoint": "/var/lib/docker/volumes/tardis"
- },
- {
- "Name": "foo",
- "Driver": "bar",
- "Mountpoint": "/var/lib/docker/volumes/bar"
- }
-]`
- body := `{ "Volumes": ` + volumesData + ` }`
- var expected []Volume
- if err := json.Unmarshal([]byte(volumesData), &expected); err != nil {
- t.Fatal(err)
- }
- client := newTestClient(&FakeRoundTripper{message: body, status: http.StatusOK})
- volumes, err := client.ListVolumes(ListVolumesOptions{})
- if err != nil {
- t.Error(err)
- }
- if !reflect.DeepEqual(volumes, expected) {
- t.Errorf("ListVolumes: Wrong return value. Want %#v. Got %#v.", expected, volumes)
- }
-}
-
-func TestCreateVolume(t *testing.T) {
- body := `{
- "Name": "tardis",
- "Driver": "local",
- "Mountpoint": "/var/lib/docker/volumes/tardis"
- }`
- var expected Volume
- if err := json.Unmarshal([]byte(body), &expected); err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: body, status: http.StatusOK}
- client := newTestClient(fakeRT)
- volume, err := client.CreateVolume(
- CreateVolumeOptions{
- Name: "tardis",
- Driver: "local",
- DriverOpts: map[string]string{
- "foo": "bar",
- },
- },
- )
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(volume, &expected) {
- t.Errorf("CreateVolume: Wrong return value. Want %#v. Got %#v.", expected, volume)
- }
- req := fakeRT.requests[0]
- expectedMethod := "POST"
- if req.Method != expectedMethod {
- t.Errorf("CreateVolume(): Wrong HTTP method. Want %s. Got %s.", expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/volumes/create"))
- if req.URL.Path != u.Path {
- t.Errorf("CreateVolume(): Wrong request path. Want %q. Got %q.", u.Path, req.URL.Path)
- }
-}
-
-func TestInspectVolume(t *testing.T) {
- body := `{
- "Name": "tardis",
- "Driver": "local",
- "Mountpoint": "/var/lib/docker/volumes/tardis"
- }`
- var expected Volume
- if err := json.Unmarshal([]byte(body), &expected); err != nil {
- t.Fatal(err)
- }
- fakeRT := &FakeRoundTripper{message: body, status: http.StatusOK}
- client := newTestClient(fakeRT)
- name := "tardis"
- volume, err := client.InspectVolume(name)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(volume, &expected) {
- t.Errorf("InspectVolume: Wrong return value. Want %#v. Got %#v.", expected, volume)
- }
- req := fakeRT.requests[0]
- expectedMethod := "GET"
- if req.Method != expectedMethod {
- t.Errorf("InspectVolume(%q): Wrong HTTP method. Want %s. Got %s.", name, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/volumes/" + name))
- if req.URL.Path != u.Path {
- t.Errorf("CreateVolume(%q): Wrong request path. Want %q. Got %q.", name, u.Path, req.URL.Path)
- }
-}
-
-func TestRemoveVolume(t *testing.T) {
- name := "test"
- fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
- client := newTestClient(fakeRT)
- if err := client.RemoveVolume(name); err != nil {
- t.Fatal(err)
- }
- req := fakeRT.requests[0]
- expectedMethod := "DELETE"
- if req.Method != expectedMethod {
- t.Errorf("RemoveVolume(%q): Wrong HTTP method. Want %s. Got %s.", name, expectedMethod, req.Method)
- }
- u, _ := url.Parse(client.getURL("/volumes/" + name))
- if req.URL.Path != u.Path {
- t.Errorf("RemoveVolume(%q): Wrong request path. Want %q. Got %q.", name, u.Path, req.URL.Path)
- }
-}
-
-func TestRemoveVolumeNotFound(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "no such volume", status: http.StatusNotFound})
- if err := client.RemoveVolume("test:"); err != ErrNoSuchVolume {
- t.Errorf("RemoveVolume: wrong error. Want %#v. Got %#v.", ErrNoSuchVolume, err)
- }
-}
-
-func TestRemoveVolumeInUse(t *testing.T) {
- client := newTestClient(&FakeRoundTripper{message: "volume in use and cannot be removed", status: http.StatusConflict})
- if err := client.RemoveVolume("test:"); err != ErrVolumeInUse {
- t.Errorf("RemoveVolume: wrong error. Want %#v. Got %#v.", ErrVolumeInUse, err)
- }
-}
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/LICENSE b/vendor/github.com/hashicorp/go-cleanhttp/LICENSE
deleted file mode 100644
index e87a115..0000000
--- a/vendor/github.com/hashicorp/go-cleanhttp/LICENSE
+++ /dev/null
@@ -1,363 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. "Contributor"
-
- means each individual or legal entity that creates, contributes to the
- creation of, or owns Covered Software.
-
-1.2. "Contributor Version"
-
- means the combination of the Contributions of others (if any) used by a
- Contributor and that particular Contributor's Contribution.
-
-1.3. "Contribution"
-
- means Covered Software of a particular Contributor.
-
-1.4. "Covered Software"
-
- means Source Code Form to which the initial Contributor has attached the
- notice in Exhibit A, the Executable Form of such Source Code Form, and
- Modifications of such Source Code Form, in each case including portions
- thereof.
-
-1.5. "Incompatible With Secondary Licenses"
- means
-
- a. that the initial Contributor has attached the notice described in
- Exhibit B to the Covered Software; or
-
- b. that the Covered Software was made available under the terms of
- version 1.1 or earlier of the License, but not also under the terms of
- a Secondary License.
-
-1.6. "Executable Form"
-
- means any form of the work other than Source Code Form.
-
-1.7. "Larger Work"
-
- means a work that combines Covered Software with other material, in a
- separate file or files, that is not Covered Software.
-
-1.8. "License"
-
- means this document.
-
-1.9. "Licensable"
-
- means having the right to grant, to the maximum extent possible, whether
- at the time of the initial grant or subsequently, any and all of the
- rights conveyed by this License.
-
-1.10. "Modifications"
-
- means any of the following:
-
- a. any file in Source Code Form that results from an addition to,
- deletion from, or modification of the contents of Covered Software; or
-
- b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. "Patent Claims" of a Contributor
-
- means any patent claim(s), including without limitation, method,
- process, and apparatus claims, in any patent Licensable by such
- Contributor that would be infringed, but for the grant of the License,
- by the making, using, selling, offering for sale, having made, import,
- or transfer of either its Contributions or its Contributor Version.
-
-1.12. "Secondary License"
-
- means either the GNU General Public License, Version 2.0, the GNU Lesser
- General Public License, Version 2.1, the GNU Affero General Public
- License, Version 3.0, or any later versions of those licenses.
-
-1.13. "Source Code Form"
-
- means the form of the work preferred for making modifications.
-
-1.14. "You" (or "Your")
-
- means an individual or a legal entity exercising rights under this
- License. For legal entities, "You" includes any entity that controls, is
- controlled by, or is under common control with You. For purposes of this
- definition, "control" means (a) the power, direct or indirect, to cause
- the direction or management of such entity, whether by contract or
- otherwise, or (b) ownership of more than fifty percent (50%) of the
- outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
- Each Contributor hereby grants You a world-wide, royalty-free,
- non-exclusive license:
-
- a. under intellectual property rights (other than patent or trademark)
- Licensable by such Contributor to use, reproduce, make available,
- modify, display, perform, distribute, and otherwise exploit its
- Contributions, either on an unmodified basis, with Modifications, or
- as part of a Larger Work; and
-
- b. under Patent Claims of such Contributor to make, use, sell, offer for
- sale, have made, import, and otherwise transfer either its
- Contributions or its Contributor Version.
-
-2.2. Effective Date
-
- The licenses granted in Section 2.1 with respect to any Contribution
- become effective for each Contribution on the date the Contributor first
- distributes such Contribution.
-
-2.3. Limitations on Grant Scope
-
- The licenses granted in this Section 2 are the only rights granted under
- this License. No additional rights or licenses will be implied from the
- distribution or licensing of Covered Software under this License.
- Notwithstanding Section 2.1(b) above, no patent license is granted by a
- Contributor:
-
- a. for any code that a Contributor has removed from Covered Software; or
-
- b. for infringements caused by: (i) Your and any other third party's
- modifications of Covered Software, or (ii) the combination of its
- Contributions with other software (except as part of its Contributor
- Version); or
-
- c. under Patent Claims infringed by Covered Software in the absence of
- its Contributions.
-
- This License does not grant any rights in the trademarks, service marks,
- or logos of any Contributor (except as may be necessary to comply with
- the notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
- No Contributor makes additional grants as a result of Your choice to
- distribute the Covered Software under a subsequent version of this
- License (see Section 10.2) or under the terms of a Secondary License (if
- permitted under the terms of Section 3.3).
-
-2.5. Representation
-
- Each Contributor represents that the Contributor believes its
- Contributions are its original creation(s) or it has sufficient rights to
- grant the rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
- This License is not intended to limit any rights You have under
- applicable copyright doctrines of fair use, fair dealing, or other
- equivalents.
-
-2.7. Conditions
-
- Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
- Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
- All distribution of Covered Software in Source Code Form, including any
- Modifications that You create or to which You contribute, must be under
- the terms of this License. You must inform recipients that the Source
- Code Form of the Covered Software is governed by the terms of this
- License, and how they can obtain a copy of this License. You may not
- attempt to alter or restrict the recipients' rights in the Source Code
- Form.
-
-3.2. Distribution of Executable Form
-
- If You distribute Covered Software in Executable Form then:
-
- a. such Covered Software must also be made available in Source Code Form,
- as described in Section 3.1, and You must inform recipients of the
- Executable Form how they can obtain a copy of such Source Code Form by
- reasonable means in a timely manner, at a charge no more than the cost
- of distribution to the recipient; and
-
- b. You may distribute such Executable Form under the terms of this
- License, or sublicense it under different terms, provided that the
- license for the Executable Form does not attempt to limit or alter the
- recipients' rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
- You may create and distribute a Larger Work under terms of Your choice,
- provided that You also comply with the requirements of this License for
- the Covered Software. If the Larger Work is a combination of Covered
- Software with a work governed by one or more Secondary Licenses, and the
- Covered Software is not Incompatible With Secondary Licenses, this
- License permits You to additionally distribute such Covered Software
- under the terms of such Secondary License(s), so that the recipient of
- the Larger Work may, at their option, further distribute the Covered
- Software under the terms of either this License or such Secondary
- License(s).
-
-3.4. Notices
-
- You may not remove or alter the substance of any license notices
- (including copyright notices, patent notices, disclaimers of warranty, or
- limitations of liability) contained within the Source Code Form of the
- Covered Software, except that You may alter any license notices to the
- extent required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
- You may choose to offer, and to charge a fee for, warranty, support,
- indemnity or liability obligations to one or more recipients of Covered
- Software. However, You may do so only on Your own behalf, and not on
- behalf of any Contributor. You must make it absolutely clear that any
- such warranty, support, indemnity, or liability obligation is offered by
- You alone, and You hereby agree to indemnify every Contributor for any
- liability incurred by such Contributor as a result of warranty, support,
- indemnity or liability terms You offer. You may include additional
- disclaimers of warranty and limitations of liability specific to any
- jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
- If it is impossible for You to comply with any of the terms of this License
- with respect to some or all of the Covered Software due to statute,
- judicial order, or regulation then You must: (a) comply with the terms of
- this License to the maximum extent possible; and (b) describe the
- limitations and the code they affect. Such description must be placed in a
- text file included with all distributions of the Covered Software under
- this License. Except to the extent prohibited by statute or regulation,
- such description must be sufficiently detailed for a recipient of ordinary
- skill to be able to understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
- fail to comply with any of its terms. However, if You become compliant,
- then the rights granted under this License from a particular Contributor
- are reinstated (a) provisionally, unless and until such Contributor
- explicitly and finally terminates Your grants, and (b) on an ongoing
- basis, if such Contributor fails to notify You of the non-compliance by
- some reasonable means prior to 60 days after You have come back into
- compliance. Moreover, Your grants from a particular Contributor are
- reinstated on an ongoing basis if such Contributor notifies You of the
- non-compliance by some reasonable means, this is the first time You have
- received notice of non-compliance with this License from such
- Contributor, and You become compliant prior to 30 days after Your receipt
- of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
- infringement claim (excluding declaratory judgment actions,
- counter-claims, and cross-claims) alleging that a Contributor Version
- directly or indirectly infringes any patent, then the rights granted to
- You by any and all Contributors for the Covered Software under Section
- 2.1 of this License shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
- license agreements (excluding distributors and resellers) which have been
- validly granted by You or Your distributors under this License prior to
- termination shall survive termination.
-
-6. Disclaimer of Warranty
-
- Covered Software is provided under this License on an "as is" basis,
- without warranty of any kind, either expressed, implied, or statutory,
- including, without limitation, warranties that the Covered Software is free
- of defects, merchantable, fit for a particular purpose or non-infringing.
- The entire risk as to the quality and performance of the Covered Software
- is with You. Should any Covered Software prove defective in any respect,
- You (not any Contributor) assume the cost of any necessary servicing,
- repair, or correction. This disclaimer of warranty constitutes an essential
- part of this License. No use of any Covered Software is authorized under
- this License except under this disclaimer.
-
-7. Limitation of Liability
-
- Under no circumstances and under no legal theory, whether tort (including
- negligence), contract, or otherwise, shall any Contributor, or anyone who
- distributes Covered Software as permitted above, be liable to You for any
- direct, indirect, special, incidental, or consequential damages of any
- character including, without limitation, damages for lost profits, loss of
- goodwill, work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses, even if such party shall have been
- informed of the possibility of such damages. This limitation of liability
- shall not apply to liability for death or personal injury resulting from
- such party's negligence to the extent applicable law prohibits such
- limitation. Some jurisdictions do not allow the exclusion or limitation of
- incidental or consequential damages, so this exclusion and limitation may
- not apply to You.
-
-8. Litigation
-
- Any litigation relating to this License may be brought only in the courts
- of a jurisdiction where the defendant maintains its principal place of
- business and such litigation shall be governed by laws of that
- jurisdiction, without reference to its conflict-of-law provisions. Nothing
- in this Section shall prevent a party's ability to bring cross-claims or
- counter-claims.
-
-9. Miscellaneous
-
- This License represents the complete agreement concerning the subject
- matter hereof. If any provision of this License is held to be
- unenforceable, such provision shall be reformed only to the extent
- necessary to make it enforceable. Any law or regulation which provides that
- the language of a contract shall be construed against the drafter shall not
- be used to construe this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
- Mozilla Foundation is the license steward. Except as provided in Section
- 10.3, no one other than the license steward has the right to modify or
- publish new versions of this License. Each version will be given a
- distinguishing version number.
-
-10.2. Effect of New Versions
-
- You may distribute the Covered Software under the terms of the version
- of the License under which You originally received the Covered Software,
- or under the terms of any subsequent version published by the license
- steward.
-
-10.3. Modified Versions
-
- If you create software not governed by this License, and you want to
- create a new license for such software, you may create and use a
- modified version of this License if you rename the license and remove
- any references to the name of the license steward (except to note that
- such modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary
- Licenses If You choose to distribute Source Code Form that is
- Incompatible With Secondary Licenses under the terms of this version of
- the License, the notice described in Exhibit B of this License must be
- attached.
-
-Exhibit A - Source Code Form License Notice
-
- This Source Code Form is subject to the
- terms of the Mozilla Public License, v.
- 2.0. If a copy of the MPL was not
- distributed with this file, You can
- obtain one at
- http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular file,
-then You may include the notice in a location (such as a LICENSE file in a
-relevant directory) where a recipient would be likely to look for such a
-notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - "Incompatible With Secondary Licenses" Notice
-
- This Source Code Form is "Incompatible
- With Secondary Licenses", as defined by
- the Mozilla Public License, v. 2.0.
-
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/README.md b/vendor/github.com/hashicorp/go-cleanhttp/README.md
deleted file mode 100644
index 036e531..0000000
--- a/vendor/github.com/hashicorp/go-cleanhttp/README.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# cleanhttp
-
-Functions for accessing "clean" Go http.Client values
-
--------------
-
-The Go standard library contains a default `http.Client` called
-`http.DefaultClient`. It is a common idiom in Go code to start with
-`http.DefaultClient` and tweak it as necessary, and in fact, this is
-encouraged; from the `http` package documentation:
-
-> The Client's Transport typically has internal state (cached TCP connections),
-so Clients should be reused instead of created as needed. Clients are safe for
-concurrent use by multiple goroutines.
-
-Unfortunately, this is a shared value, and it is not uncommon for libraries to
-assume that they are free to modify it at will. With enough dependencies, it
-can be very easy to encounter strange problems and race conditions due to
-manipulation of this shared value across libraries and goroutines (clients are
-safe for concurrent use, but writing values to the client struct itself is not
-protected).
-
-Making things worse is the fact that a bare `http.Client` will use a default
-`http.Transport` called `http.DefaultTransport`, which is another global value
-that behaves the same way. So it is not simply enough to replace
-`http.DefaultClient` with `&http.Client{}`.
-
-This repository provides some simple functions to get a "clean" `http.Client`
--- one that uses the same default values as the Go standard library, but
-returns a client that does not share any state with other clients.
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go b/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
deleted file mode 100644
index f4596d8..0000000
--- a/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package cleanhttp
-
-import (
- "net"
- "net/http"
- "time"
-)
-
-// DefaultTransport returns a new http.Transport with the same default values
-// as http.DefaultTransport, but with idle connections and keepalives disabled.
-func DefaultTransport() *http.Transport {
- transport := DefaultPooledTransport()
- transport.DisableKeepAlives = true
- transport.MaxIdleConnsPerHost = -1
- return transport
-}
-
-// DefaultPooledTransport returns a new http.Transport with similar default
-// values to http.DefaultTransport. Do not use this for transient transports as
-// it can leak file descriptors over time. Only use this for transports that
-// will be re-used for the same host(s).
-func DefaultPooledTransport() *http.Transport {
- transport := &http.Transport{
- Proxy: http.ProxyFromEnvironment,
- Dial: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 30 * time.Second,
- }).Dial,
- TLSHandshakeTimeout: 10 * time.Second,
- DisableKeepAlives: false,
- MaxIdleConnsPerHost: 1,
- }
- return transport
-}
-
-// DefaultClient returns a new http.Client with similar default values to
-// http.Client, but with a non-shared Transport, idle connections disabled, and
-// keepalives disabled.
-func DefaultClient() *http.Client {
- return &http.Client{
- Transport: DefaultTransport(),
- }
-}
-
-// DefaultPooledClient returns a new http.Client with the same default values
-// as http.Client, but with a shared Transport. Do not use this function
-// for transient clients as it can leak file descriptors over time. Only use
-// this for clients that will be re-used for the same host(s).
-func DefaultPooledClient() *http.Client {
- return &http.Client{
- Transport: DefaultPooledTransport(),
- }
-}
diff --git a/vendor/github.com/hashicorp/go-cleanhttp/doc.go b/vendor/github.com/hashicorp/go-cleanhttp/doc.go
deleted file mode 100644
index 0584109..0000000
--- a/vendor/github.com/hashicorp/go-cleanhttp/doc.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Package cleanhttp offers convenience utilities for acquiring "clean"
-// http.Transport and http.Client structs.
-//
-// Values set on http.DefaultClient and http.DefaultTransport affect all
-// callers. This can have detrimental effects, esepcially in TLS contexts,
-// where client or root certificates set to talk to multiple endpoints can end
-// up displacing each other, leading to hard-to-debug issues. This package
-// provides non-shared http.Client and http.Transport structs to ensure that
-// the configuration will not be overwritten by other parts of the application
-// or dependencies.
-//
-// The DefaultClient and DefaultTransport functions disable idle connections
-// and keepalives. Without ensuring that idle connections are closed before
-// garbage collection, short-term clients/transports can leak file descriptors,
-// eventually leading to "too many open files" errors. If you will be
-// connecting to the same hosts repeatedly from the same client, you can use
-// DefaultPooledClient to receive a client that has connection pooling
-// semantics similar to http.DefaultClient.
-//
-package cleanhttp
diff --git a/vendor/github.com/opencontainers/runc/LICENSE b/vendor/github.com/opencontainers/runc/LICENSE
deleted file mode 100644
index 2744858..0000000
--- a/vendor/github.com/opencontainers/runc/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- Copyright 2014 Docker, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/vendor/github.com/opencontainers/runc/NOTICE b/vendor/github.com/opencontainers/runc/NOTICE
deleted file mode 100644
index 5c97abc..0000000
--- a/vendor/github.com/opencontainers/runc/NOTICE
+++ /dev/null
@@ -1,17 +0,0 @@
-runc
-
-Copyright 2012-2015 Docker, Inc.
-
-This product includes software developed at Docker, Inc. (http://www.docker.com).
-
-The following is courtesy of our legal counsel:
-
-
-Use and transfer of Docker may be subject to certain restrictions by the
-United States and other governments.
-It is your responsibility to ensure that your use and/or transfer does not
-violate applicable laws.
-
-For more information, please see http://www.bis.doc.gov
-
-See also http://www.apache.org/dev/crypto.html and/or seek legal counsel.
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/MAINTAINERS b/vendor/github.com/opencontainers/runc/libcontainer/user/MAINTAINERS
deleted file mode 100644
index edbe200..0000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/MAINTAINERS
+++ /dev/null
@@ -1,2 +0,0 @@
-Tianon Gravi (@tianon)
-Aleksa Sarai (@cyphar)
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup.go b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup.go
deleted file mode 100644
index ab1439f..0000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package user
-
-import (
- "errors"
- "syscall"
-)
-
-var (
- // The current operating system does not provide the required data for user lookups.
- ErrUnsupported = errors.New("user lookup: operating system does not provide passwd-formatted data")
- // No matching entries found in file.
- ErrNoPasswdEntries = errors.New("no matching entries in passwd file")
- ErrNoGroupEntries = errors.New("no matching entries in group file")
-)
-
-func lookupUser(filter func(u User) bool) (User, error) {
- // Get operating system-specific passwd reader-closer.
- passwd, err := GetPasswd()
- if err != nil {
- return User{}, err
- }
- defer passwd.Close()
-
- // Get the users.
- users, err := ParsePasswdFilter(passwd, filter)
- if err != nil {
- return User{}, err
- }
-
- // No user entries found.
- if len(users) == 0 {
- return User{}, ErrNoPasswdEntries
- }
-
- // Assume the first entry is the "correct" one.
- return users[0], nil
-}
-
-// CurrentUser looks up the current user by their user id in /etc/passwd. If the
-// user cannot be found (or there is no /etc/passwd file on the filesystem),
-// then CurrentUser returns an error.
-func CurrentUser() (User, error) {
- return LookupUid(syscall.Getuid())
-}
-
-// LookupUser looks up a user by their username in /etc/passwd. If the user
-// cannot be found (or there is no /etc/passwd file on the filesystem), then
-// LookupUser returns an error.
-func LookupUser(username string) (User, error) {
- return lookupUser(func(u User) bool {
- return u.Name == username
- })
-}
-
-// LookupUid looks up a user by their user id in /etc/passwd. If the user cannot
-// be found (or there is no /etc/passwd file on the filesystem), then LookupId
-// returns an error.
-func LookupUid(uid int) (User, error) {
- return lookupUser(func(u User) bool {
- return u.Uid == uid
- })
-}
-
-func lookupGroup(filter func(g Group) bool) (Group, error) {
- // Get operating system-specific group reader-closer.
- group, err := GetGroup()
- if err != nil {
- return Group{}, err
- }
- defer group.Close()
-
- // Get the users.
- groups, err := ParseGroupFilter(group, filter)
- if err != nil {
- return Group{}, err
- }
-
- // No user entries found.
- if len(groups) == 0 {
- return Group{}, ErrNoGroupEntries
- }
-
- // Assume the first entry is the "correct" one.
- return groups[0], nil
-}
-
-// CurrentGroup looks up the current user's group by their primary group id's
-// entry in /etc/passwd. If the group cannot be found (or there is no
-// /etc/group file on the filesystem), then CurrentGroup returns an error.
-func CurrentGroup() (Group, error) {
- return LookupGid(syscall.Getgid())
-}
-
-// LookupGroup looks up a group by its name in /etc/group. If the group cannot
-// be found (or there is no /etc/group file on the filesystem), then LookupGroup
-// returns an error.
-func LookupGroup(groupname string) (Group, error) {
- return lookupGroup(func(g Group) bool {
- return g.Name == groupname
- })
-}
-
-// LookupGid looks up a group by its group id in /etc/group. If the group cannot
-// be found (or there is no /etc/group file on the filesystem), then LookupGid
-// returns an error.
-func LookupGid(gid int) (Group, error) {
- return lookupGroup(func(g Group) bool {
- return g.Gid == gid
- })
-}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
deleted file mode 100644
index 758b734..0000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package user
-
-import (
- "io"
- "os"
-)
-
-// Unix-specific path to the passwd and group formatted files.
-const (
- unixPasswdPath = "/etc/passwd"
- unixGroupPath = "/etc/group"
-)
-
-func GetPasswdPath() (string, error) {
- return unixPasswdPath, nil
-}
-
-func GetPasswd() (io.ReadCloser, error) {
- return os.Open(unixPasswdPath)
-}
-
-func GetGroupPath() (string, error) {
- return unixGroupPath, nil
-}
-
-func GetGroup() (io.ReadCloser, error) {
- return os.Open(unixGroupPath)
-}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unsupported.go b/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unsupported.go
deleted file mode 100644
index 7217948..0000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unsupported.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
-
-package user
-
-import "io"
-
-func GetPasswdPath() (string, error) {
- return "", ErrUnsupported
-}
-
-func GetPasswd() (io.ReadCloser, error) {
- return nil, ErrUnsupported
-}
-
-func GetGroupPath() (string, error) {
- return "", ErrUnsupported
-}
-
-func GetGroup() (io.ReadCloser, error) {
- return nil, ErrUnsupported
-}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
deleted file mode 100644
index 43fd39e..0000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/user.go
+++ /dev/null
@@ -1,441 +0,0 @@
-package user
-
-import (
- "bufio"
- "fmt"
- "io"
- "os"
- "strconv"
- "strings"
-)
-
-const (
- minId = 0
- maxId = 1<<31 - 1 //for 32-bit systems compatibility
-)
-
-var (
- ErrRange = fmt.Errorf("uids and gids must be in range %d-%d", minId, maxId)
-)
-
-type User struct {
- Name string
- Pass string
- Uid int
- Gid int
- Gecos string
- Home string
- Shell string
-}
-
-type Group struct {
- Name string
- Pass string
- Gid int
- List []string
-}
-
-func parseLine(line string, v ...interface{}) {
- if line == "" {
- return
- }
-
- parts := strings.Split(line, ":")
- for i, p := range parts {
- // Ignore cases where we don't have enough fields to populate the arguments.
- // Some configuration files like to misbehave.
- if len(v) <= i {
- break
- }
-
- // Use the type of the argument to figure out how to parse it, scanf() style.
- // This is legit.
- switch e := v[i].(type) {
- case *string:
- *e = p
- case *int:
- // "numbers", with conversion errors ignored because of some misbehaving configuration files.
- *e, _ = strconv.Atoi(p)
- case *[]string:
- // Comma-separated lists.
- if p != "" {
- *e = strings.Split(p, ",")
- } else {
- *e = []string{}
- }
- default:
- // Someone goof'd when writing code using this function. Scream so they can hear us.
- panic(fmt.Sprintf("parseLine only accepts {*string, *int, *[]string} as arguments! %#v is not a pointer!", e))
- }
- }
-}
-
-func ParsePasswdFile(path string) ([]User, error) {
- passwd, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer passwd.Close()
- return ParsePasswd(passwd)
-}
-
-func ParsePasswd(passwd io.Reader) ([]User, error) {
- return ParsePasswdFilter(passwd, nil)
-}
-
-func ParsePasswdFileFilter(path string, filter func(User) bool) ([]User, error) {
- passwd, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer passwd.Close()
- return ParsePasswdFilter(passwd, filter)
-}
-
-func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
- if r == nil {
- return nil, fmt.Errorf("nil source for passwd-formatted data")
- }
-
- var (
- s = bufio.NewScanner(r)
- out = []User{}
- )
-
- for s.Scan() {
- if err := s.Err(); err != nil {
- return nil, err
- }
-
- line := strings.TrimSpace(s.Text())
- if line == "" {
- continue
- }
-
- // see: man 5 passwd
- // name:password:UID:GID:GECOS:directory:shell
- // Name:Pass:Uid:Gid:Gecos:Home:Shell
- // root:x:0:0:root:/root:/bin/bash
- // adm:x:3:4:adm:/var/adm:/bin/false
- p := User{}
- parseLine(line, &p.Name, &p.Pass, &p.Uid, &p.Gid, &p.Gecos, &p.Home, &p.Shell)
-
- if filter == nil || filter(p) {
- out = append(out, p)
- }
- }
-
- return out, nil
-}
-
-func ParseGroupFile(path string) ([]Group, error) {
- group, err := os.Open(path)
- if err != nil {
- return nil, err
- }
-
- defer group.Close()
- return ParseGroup(group)
-}
-
-func ParseGroup(group io.Reader) ([]Group, error) {
- return ParseGroupFilter(group, nil)
-}
-
-func ParseGroupFileFilter(path string, filter func(Group) bool) ([]Group, error) {
- group, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer group.Close()
- return ParseGroupFilter(group, filter)
-}
-
-func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
- if r == nil {
- return nil, fmt.Errorf("nil source for group-formatted data")
- }
-
- var (
- s = bufio.NewScanner(r)
- out = []Group{}
- )
-
- for s.Scan() {
- if err := s.Err(); err != nil {
- return nil, err
- }
-
- text := s.Text()
- if text == "" {
- continue
- }
-
- // see: man 5 group
- // group_name:password:GID:user_list
- // Name:Pass:Gid:List
- // root:x:0:root
- // adm:x:4:root,adm,daemon
- p := Group{}
- parseLine(text, &p.Name, &p.Pass, &p.Gid, &p.List)
-
- if filter == nil || filter(p) {
- out = append(out, p)
- }
- }
-
- return out, nil
-}
-
-type ExecUser struct {
- Uid int
- Gid int
- Sgids []int
- Home string
-}
-
-// GetExecUserPath is a wrapper for GetExecUser. It reads data from each of the
-// given file paths and uses that data as the arguments to GetExecUser. If the
-// files cannot be opened for any reason, the error is ignored and a nil
-// io.Reader is passed instead.
-func GetExecUserPath(userSpec string, defaults *ExecUser, passwdPath, groupPath string) (*ExecUser, error) {
- passwd, err := os.Open(passwdPath)
- if err != nil {
- passwd = nil
- } else {
- defer passwd.Close()
- }
-
- group, err := os.Open(groupPath)
- if err != nil {
- group = nil
- } else {
- defer group.Close()
- }
-
- return GetExecUser(userSpec, defaults, passwd, group)
-}
-
-// GetExecUser parses a user specification string (using the passwd and group
-// readers as sources for /etc/passwd and /etc/group data, respectively). In
-// the case of blank fields or missing data from the sources, the values in
-// defaults is used.
-//
-// GetExecUser will return an error if a user or group literal could not be
-// found in any entry in passwd and group respectively.
-//
-// Examples of valid user specifications are:
-// * ""
-// * "user"
-// * "uid"
-// * "user:group"
-// * "uid:gid
-// * "user:gid"
-// * "uid:group"
-//
-// It should be noted that if you specify a numeric user or group id, they will
-// not be evaluated as usernames (only the metadata will be filled). So attempting
-// to parse a user with user.Name = "1337" will produce the user with a UID of
-// 1337.
-func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (*ExecUser, error) {
- if defaults == nil {
- defaults = new(ExecUser)
- }
-
- // Copy over defaults.
- user := &ExecUser{
- Uid: defaults.Uid,
- Gid: defaults.Gid,
- Sgids: defaults.Sgids,
- Home: defaults.Home,
- }
-
- // Sgids slice *cannot* be nil.
- if user.Sgids == nil {
- user.Sgids = []int{}
- }
-
- // Allow for userArg to have either "user" syntax, or optionally "user:group" syntax
- var userArg, groupArg string
- parseLine(userSpec, &userArg, &groupArg)
-
- // Convert userArg and groupArg to be numeric, so we don't have to execute
- // Atoi *twice* for each iteration over lines.
- uidArg, uidErr := strconv.Atoi(userArg)
- gidArg, gidErr := strconv.Atoi(groupArg)
-
- // Find the matching user.
- users, err := ParsePasswdFilter(passwd, func(u User) bool {
- if userArg == "" {
- // Default to current state of the user.
- return u.Uid == user.Uid
- }
-
- if uidErr == nil {
- // If the userArg is numeric, always treat it as a UID.
- return uidArg == u.Uid
- }
-
- return u.Name == userArg
- })
-
- // If we can't find the user, we have to bail.
- if err != nil && passwd != nil {
- if userArg == "" {
- userArg = strconv.Itoa(user.Uid)
- }
- return nil, fmt.Errorf("unable to find user %s: %v", userArg, err)
- }
-
- var matchedUserName string
- if len(users) > 0 {
- // First match wins, even if there's more than one matching entry.
- matchedUserName = users[0].Name
- user.Uid = users[0].Uid
- user.Gid = users[0].Gid
- user.Home = users[0].Home
- } else if userArg != "" {
- // If we can't find a user with the given username, the only other valid
- // option is if it's a numeric username with no associated entry in passwd.
-
- if uidErr != nil {
- // Not numeric.
- return nil, fmt.Errorf("unable to find user %s: %v", userArg, ErrNoPasswdEntries)
- }
- user.Uid = uidArg
-
- // Must be inside valid uid range.
- if user.Uid < minId || user.Uid > maxId {
- return nil, ErrRange
- }
-
- // Okay, so it's numeric. We can just roll with this.
- }
-
- // On to the groups. If we matched a username, we need to do this because of
- // the supplementary group IDs.
- if groupArg != "" || matchedUserName != "" {
- groups, err := ParseGroupFilter(group, func(g Group) bool {
- // If the group argument isn't explicit, we'll just search for it.
- if groupArg == "" {
- // Check if user is a member of this group.
- for _, u := range g.List {
- if u == matchedUserName {
- return true
- }
- }
- return false
- }
-
- if gidErr == nil {
- // If the groupArg is numeric, always treat it as a GID.
- return gidArg == g.Gid
- }
-
- return g.Name == groupArg
- })
- if err != nil && group != nil {
- return nil, fmt.Errorf("unable to find groups for spec %v: %v", matchedUserName, err)
- }
-
- // Only start modifying user.Gid if it is in explicit form.
- if groupArg != "" {
- if len(groups) > 0 {
- // First match wins, even if there's more than one matching entry.
- user.Gid = groups[0].Gid
- } else if groupArg != "" {
- // If we can't find a group with the given name, the only other valid
- // option is if it's a numeric group name with no associated entry in group.
-
- if gidErr != nil {
- // Not numeric.
- return nil, fmt.Errorf("unable to find group %s: %v", groupArg, ErrNoGroupEntries)
- }
- user.Gid = gidArg
-
- // Must be inside valid gid range.
- if user.Gid < minId || user.Gid > maxId {
- return nil, ErrRange
- }
-
- // Okay, so it's numeric. We can just roll with this.
- }
- } else if len(groups) > 0 {
- // Supplementary group ids only make sense if in the implicit form.
- user.Sgids = make([]int, len(groups))
- for i, group := range groups {
- user.Sgids[i] = group.Gid
- }
- }
- }
-
- return user, nil
-}
-
-// GetAdditionalGroups looks up a list of groups by name or group id
-// against the given /etc/group formatted data. If a group name cannot
-// be found, an error will be returned. If a group id cannot be found,
-// or the given group data is nil, the id will be returned as-is
-// provided it is in the legal range.
-func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, error) {
- var groups = []Group{}
- if group != nil {
- var err error
- groups, err = ParseGroupFilter(group, func(g Group) bool {
- for _, ag := range additionalGroups {
- if g.Name == ag || strconv.Itoa(g.Gid) == ag {
- return true
- }
- }
- return false
- })
- if err != nil {
- return nil, fmt.Errorf("Unable to find additional groups %v: %v", additionalGroups, err)
- }
- }
-
- gidMap := make(map[int]struct{})
- for _, ag := range additionalGroups {
- var found bool
- for _, g := range groups {
- // if we found a matched group either by name or gid, take the
- // first matched as correct
- if g.Name == ag || strconv.Itoa(g.Gid) == ag {
- if _, ok := gidMap[g.Gid]; !ok {
- gidMap[g.Gid] = struct{}{}
- found = true
- break
- }
- }
- }
- // we asked for a group but didn't find it. let's check to see
- // if we wanted a numeric group
- if !found {
- gid, err := strconv.Atoi(ag)
- if err != nil {
- return nil, fmt.Errorf("Unable to find group %s", ag)
- }
- // Ensure gid is inside gid range.
- if gid < minId || gid > maxId {
- return nil, ErrRange
- }
- gidMap[gid] = struct{}{}
- }
- }
- gids := []int{}
- for gid := range gidMap {
- gids = append(gids, gid)
- }
- return gids, nil
-}
-
-// GetAdditionalGroupsPath is a wrapper around GetAdditionalGroups
-// that opens the groupPath given and gives it as an argument to
-// GetAdditionalGroups.
-func GetAdditionalGroupsPath(additionalGroups []string, groupPath string) ([]int, error) {
- group, err := os.Open(groupPath)
- if err == nil {
- defer group.Close()
- }
- return GetAdditionalGroups(additionalGroups, group)
-}
diff --git a/vendor/github.com/opencontainers/runc/libcontainer/user/user_test.go b/vendor/github.com/opencontainers/runc/libcontainer/user/user_test.go
deleted file mode 100644
index 8cad2f5..0000000
--- a/vendor/github.com/opencontainers/runc/libcontainer/user/user_test.go
+++ /dev/null
@@ -1,500 +0,0 @@
-package user
-
-import (
- "io"
- "reflect"
- "sort"
- "strconv"
- "strings"
- "testing"
-)
-
-func TestUserParseLine(t *testing.T) {
- var (
- a, b string
- c []string
- d int
- )
-
- parseLine("", &a, &b)
- if a != "" || b != "" {
- t.Fatalf("a and b should be empty ('%v', '%v')", a, b)
- }
-
- parseLine("a", &a, &b)
- if a != "a" || b != "" {
- t.Fatalf("a should be 'a' and b should be empty ('%v', '%v')", a, b)
- }
-
- parseLine("bad boys:corny cows", &a, &b)
- if a != "bad boys" || b != "corny cows" {
- t.Fatalf("a should be 'bad boys' and b should be 'corny cows' ('%v', '%v')", a, b)
- }
-
- parseLine("", &c)
- if len(c) != 0 {
- t.Fatalf("c should be empty (%#v)", c)
- }
-
- parseLine("d,e,f:g:h:i,j,k", &c, &a, &b, &c)
- if a != "g" || b != "h" || len(c) != 3 || c[0] != "i" || c[1] != "j" || c[2] != "k" {
- t.Fatalf("a should be 'g', b should be 'h', and c should be ['i','j','k'] ('%v', '%v', '%#v')", a, b, c)
- }
-
- parseLine("::::::::::", &a, &b, &c)
- if a != "" || b != "" || len(c) != 0 {
- t.Fatalf("a, b, and c should all be empty ('%v', '%v', '%#v')", a, b, c)
- }
-
- parseLine("not a number", &d)
- if d != 0 {
- t.Fatalf("d should be 0 (%v)", d)
- }
-
- parseLine("b:12:c", &a, &d, &b)
- if a != "b" || b != "c" || d != 12 {
- t.Fatalf("a should be 'b' and b should be 'c', and d should be 12 ('%v', '%v', %v)", a, b, d)
- }
-}
-
-func TestUserParsePasswd(t *testing.T) {
- users, err := ParsePasswdFilter(strings.NewReader(`
-root:x:0:0:root:/root:/bin/bash
-adm:x:3:4:adm:/var/adm:/bin/false
-this is just some garbage data
-`), nil)
- if err != nil {
- t.Fatalf("Unexpected error: %v", err)
- }
- if len(users) != 3 {
- t.Fatalf("Expected 3 users, got %v", len(users))
- }
- if users[0].Uid != 0 || users[0].Name != "root" {
- t.Fatalf("Expected users[0] to be 0 - root, got %v - %v", users[0].Uid, users[0].Name)
- }
- if users[1].Uid != 3 || users[1].Name != "adm" {
- t.Fatalf("Expected users[1] to be 3 - adm, got %v - %v", users[1].Uid, users[1].Name)
- }
-}
-
-func TestUserParseGroup(t *testing.T) {
- groups, err := ParseGroupFilter(strings.NewReader(`
-root:x:0:root
-adm:x:4:root,adm,daemon
-this is just some garbage data
-`), nil)
- if err != nil {
- t.Fatalf("Unexpected error: %v", err)
- }
- if len(groups) != 3 {
- t.Fatalf("Expected 3 groups, got %v", len(groups))
- }
- if groups[0].Gid != 0 || groups[0].Name != "root" || len(groups[0].List) != 1 {
- t.Fatalf("Expected groups[0] to be 0 - root - 1 member, got %v - %v - %v", groups[0].Gid, groups[0].Name, len(groups[0].List))
- }
- if groups[1].Gid != 4 || groups[1].Name != "adm" || len(groups[1].List) != 3 {
- t.Fatalf("Expected groups[1] to be 4 - adm - 3 members, got %v - %v - %v", groups[1].Gid, groups[1].Name, len(groups[1].List))
- }
-}
-
-func TestValidGetExecUser(t *testing.T) {
- const passwdContent = `
-root:x:0:0:root user:/root:/bin/bash
-adm:x:42:43:adm:/var/adm:/bin/false
-111:x:222:333::/var/garbage
-odd:x:111:112::/home/odd:::::
-this is just some garbage data
-`
- const groupContent = `
-root:x:0:root
-adm:x:43:
-grp:x:1234:root,adm
-444:x:555:111
-odd:x:444:
-this is just some garbage data
-`
- defaultExecUser := ExecUser{
- Uid: 8888,
- Gid: 8888,
- Sgids: []int{8888},
- Home: "/8888",
- }
-
- tests := []struct {
- ref string
- expected ExecUser
- }{
- {
- ref: "root",
- expected: ExecUser{
- Uid: 0,
- Gid: 0,
- Sgids: []int{0, 1234},
- Home: "/root",
- },
- },
- {
- ref: "adm",
- expected: ExecUser{
- Uid: 42,
- Gid: 43,
- Sgids: []int{1234},
- Home: "/var/adm",
- },
- },
- {
- ref: "root:adm",
- expected: ExecUser{
- Uid: 0,
- Gid: 43,
- Sgids: defaultExecUser.Sgids,
- Home: "/root",
- },
- },
- {
- ref: "adm:1234",
- expected: ExecUser{
- Uid: 42,
- Gid: 1234,
- Sgids: defaultExecUser.Sgids,
- Home: "/var/adm",
- },
- },
- {
- ref: "42:1234",
- expected: ExecUser{
- Uid: 42,
- Gid: 1234,
- Sgids: defaultExecUser.Sgids,
- Home: "/var/adm",
- },
- },
- {
- ref: "1337:1234",
- expected: ExecUser{
- Uid: 1337,
- Gid: 1234,
- Sgids: defaultExecUser.Sgids,
- Home: defaultExecUser.Home,
- },
- },
- {
- ref: "1337",
- expected: ExecUser{
- Uid: 1337,
- Gid: defaultExecUser.Gid,
- Sgids: defaultExecUser.Sgids,
- Home: defaultExecUser.Home,
- },
- },
- {
- ref: "",
- expected: ExecUser{
- Uid: defaultExecUser.Uid,
- Gid: defaultExecUser.Gid,
- Sgids: defaultExecUser.Sgids,
- Home: defaultExecUser.Home,
- },
- },
-
- // Regression tests for #695.
- {
- ref: "111",
- expected: ExecUser{
- Uid: 111,
- Gid: 112,
- Sgids: defaultExecUser.Sgids,
- Home: "/home/odd",
- },
- },
- {
- ref: "111:444",
- expected: ExecUser{
- Uid: 111,
- Gid: 444,
- Sgids: defaultExecUser.Sgids,
- Home: "/home/odd",
- },
- },
- }
-
- for _, test := range tests {
- passwd := strings.NewReader(passwdContent)
- group := strings.NewReader(groupContent)
-
- execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group)
- if err != nil {
- t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error())
- t.Fail()
- continue
- }
-
- if !reflect.DeepEqual(test.expected, *execUser) {
- t.Logf("ref: %v", test.ref)
- t.Logf("got: %#v", execUser)
- t.Logf("expected: %#v", test.expected)
- t.Fail()
- continue
- }
- }
-}
-
-func TestInvalidGetExecUser(t *testing.T) {
- const passwdContent = `
-root:x:0:0:root user:/root:/bin/bash
-adm:x:42:43:adm:/var/adm:/bin/false
--42:x:12:13:broken:/very/broken
-this is just some garbage data
-`
- const groupContent = `
-root:x:0:root
-adm:x:43:
-grp:x:1234:root,adm
-this is just some garbage data
-`
-
- tests := []string{
- // No such user/group.
- "notuser",
- "notuser:notgroup",
- "root:notgroup",
- "notuser:adm",
- "8888:notgroup",
- "notuser:8888",
-
- // Invalid user/group values.
- "-1:0",
- "0:-3",
- "-5:-2",
- "-42",
- "-43",
- }
-
- for _, test := range tests {
- passwd := strings.NewReader(passwdContent)
- group := strings.NewReader(groupContent)
-
- execUser, err := GetExecUser(test, nil, passwd, group)
- if err == nil {
- t.Logf("got unexpected success when parsing '%s': %#v", test, execUser)
- t.Fail()
- continue
- }
- }
-}
-
-func TestGetExecUserNilSources(t *testing.T) {
- const passwdContent = `
-root:x:0:0:root user:/root:/bin/bash
-adm:x:42:43:adm:/var/adm:/bin/false
-this is just some garbage data
-`
- const groupContent = `
-root:x:0:root
-adm:x:43:
-grp:x:1234:root,adm
-this is just some garbage data
-`
-
- defaultExecUser := ExecUser{
- Uid: 8888,
- Gid: 8888,
- Sgids: []int{8888},
- Home: "/8888",
- }
-
- tests := []struct {
- ref string
- passwd, group bool
- expected ExecUser
- }{
- {
- ref: "",
- passwd: false,
- group: false,
- expected: ExecUser{
- Uid: 8888,
- Gid: 8888,
- Sgids: []int{8888},
- Home: "/8888",
- },
- },
- {
- ref: "root",
- passwd: true,
- group: false,
- expected: ExecUser{
- Uid: 0,
- Gid: 0,
- Sgids: []int{8888},
- Home: "/root",
- },
- },
- {
- ref: "0",
- passwd: false,
- group: false,
- expected: ExecUser{
- Uid: 0,
- Gid: 8888,
- Sgids: []int{8888},
- Home: "/8888",
- },
- },
- {
- ref: "0:0",
- passwd: false,
- group: false,
- expected: ExecUser{
- Uid: 0,
- Gid: 0,
- Sgids: []int{8888},
- Home: "/8888",
- },
- },
- }
-
- for _, test := range tests {
- var passwd, group io.Reader
-
- if test.passwd {
- passwd = strings.NewReader(passwdContent)
- }
-
- if test.group {
- group = strings.NewReader(groupContent)
- }
-
- execUser, err := GetExecUser(test.ref, &defaultExecUser, passwd, group)
- if err != nil {
- t.Logf("got unexpected error when parsing '%s': %s", test.ref, err.Error())
- t.Fail()
- continue
- }
-
- if !reflect.DeepEqual(test.expected, *execUser) {
- t.Logf("got: %#v", execUser)
- t.Logf("expected: %#v", test.expected)
- t.Fail()
- continue
- }
- }
-}
-
-func TestGetAdditionalGroups(t *testing.T) {
- const groupContent = `
-root:x:0:root
-adm:x:43:
-grp:x:1234:root,adm
-adm:x:4343:root,adm-duplicate
-this is just some garbage data
-`
- tests := []struct {
- groups []string
- expected []int
- hasError bool
- }{
- {
- // empty group
- groups: []string{},
- expected: []int{},
- },
- {
- // single group
- groups: []string{"adm"},
- expected: []int{43},
- },
- {
- // multiple groups
- groups: []string{"adm", "grp"},
- expected: []int{43, 1234},
- },
- {
- // invalid group
- groups: []string{"adm", "grp", "not-exist"},
- expected: nil,
- hasError: true,
- },
- {
- // group with numeric id
- groups: []string{"43"},
- expected: []int{43},
- },
- {
- // group with unknown numeric id
- groups: []string{"adm", "10001"},
- expected: []int{43, 10001},
- },
- {
- // groups specified twice with numeric and name
- groups: []string{"adm", "43"},
- expected: []int{43},
- },
- {
- // groups with too small id
- groups: []string{"-1"},
- expected: nil,
- hasError: true,
- },
- {
- // groups with too large id
- groups: []string{strconv.Itoa(1 << 31)},
- expected: nil,
- hasError: true,
- },
- }
-
- for _, test := range tests {
- group := strings.NewReader(groupContent)
-
- gids, err := GetAdditionalGroups(test.groups, group)
- if test.hasError && err == nil {
- t.Errorf("Parse(%#v) expects error but has none", test)
- continue
- }
- if !test.hasError && err != nil {
- t.Errorf("Parse(%#v) has error %v", test, err)
- continue
- }
- sort.Sort(sort.IntSlice(gids))
- if !reflect.DeepEqual(gids, test.expected) {
- t.Errorf("Gids(%v), expect %v from groups %v", gids, test.expected, test.groups)
- }
- }
-}
-
-func TestGetAdditionalGroupsNumeric(t *testing.T) {
- tests := []struct {
- groups []string
- expected []int
- hasError bool
- }{
- {
- // numeric groups only
- groups: []string{"1234", "5678"},
- expected: []int{1234, 5678},
- },
- {
- // numeric and alphabetic
- groups: []string{"1234", "fake"},
- expected: nil,
- hasError: true,
- },
- }
-
- for _, test := range tests {
- gids, err := GetAdditionalGroups(test.groups, nil)
- if test.hasError && err == nil {
- t.Errorf("Parse(%#v) expects error but has none", test)
- continue
- }
- if !test.hasError && err != nil {
- t.Errorf("Parse(%#v) has error %v", test, err)
- continue
- }
- sort.Sort(sort.IntSlice(gids))
- if !reflect.DeepEqual(gids, test.expected) {
- t.Errorf("Gids(%v), expect %v from groups %v", gids, test.expected, test.groups)
- }
- }
-}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go
deleted file mode 100644
index 22e3a6b..0000000
--- a/vendor/github.com/stretchr/testify/assert/assertions.go
+++ /dev/null
@@ -1,897 +0,0 @@
-package assert
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "math"
- "reflect"
- "regexp"
- "runtime"
- "strings"
- "time"
- "unicode"
- "unicode/utf8"
-)
-
-// TestingT is an interface wrapper around *testing.T
-type TestingT interface {
- Errorf(format string, args ...interface{})
-}
-
-// Comparison a custom function that returns true on success and false on failure
-type Comparison func() (success bool)
-
-/*
- Helper functions
-*/
-
-// ObjectsAreEqual determines if two objects are considered equal.
-//
-// This function does no assertion of any kind.
-func ObjectsAreEqual(expected, actual interface{}) bool {
-
- if expected == nil || actual == nil {
- return expected == actual
- }
-
- if reflect.DeepEqual(expected, actual) {
- return true
- }
-
- return false
-
-}
-
-// ObjectsAreEqualValues gets whether two objects are equal, or if their
-// values are equal.
-func ObjectsAreEqualValues(expected, actual interface{}) bool {
- if ObjectsAreEqual(expected, actual) {
- return true
- }
-
- actualType := reflect.TypeOf(actual)
- expectedValue := reflect.ValueOf(expected)
- if expectedValue.Type().ConvertibleTo(actualType) {
- // Attempt comparison after type conversion
- if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) {
- return true
- }
- }
-
- return false
-}
-
-/* CallerInfo is necessary because the assert functions use the testing object
-internally, causing it to print the file:line of the assert method, rather than where
-the problem actually occured in calling code.*/
-
-// CallerInfo returns an array of strings containing the file and line number
-// of each stack frame leading from the current test to the assert call that
-// failed.
-func CallerInfo() []string {
-
- pc := uintptr(0)
- file := ""
- line := 0
- ok := false
- name := ""
-
- callers := []string{}
- for i := 0; ; i++ {
- pc, file, line, ok = runtime.Caller(i)
- if !ok {
- return nil
- }
-
- // This is a huge edge case, but it will panic if this is the case, see #180
- if file == "" {
- break
- }
-
- parts := strings.Split(file, "/")
- dir := parts[len(parts)-2]
- file = parts[len(parts)-1]
- if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
- callers = append(callers, fmt.Sprintf("%s:%d", file, line))
- }
-
- f := runtime.FuncForPC(pc)
- if f == nil {
- break
- }
- name = f.Name()
- // Drop the package
- segments := strings.Split(name, ".")
- name = segments[len(segments)-1]
- if isTest(name, "Test") ||
- isTest(name, "Benchmark") ||
- isTest(name, "Example") {
- break
- }
- }
-
- return callers
-}
-
-// Stolen from the `go test` tool.
-// isTest tells whether name looks like a test (or benchmark, according to prefix).
-// It is a Test (say) if there is a character after Test that is not a lower-case letter.
-// We don't want TesticularCancer.
-func isTest(name, prefix string) bool {
- if !strings.HasPrefix(name, prefix) {
- return false
- }
- if len(name) == len(prefix) { // "Test" is ok
- return true
- }
- rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
- return !unicode.IsLower(rune)
-}
-
-// getWhitespaceString returns a string that is long enough to overwrite the default
-// output from the go testing framework.
-func getWhitespaceString() string {
-
- _, file, line, ok := runtime.Caller(1)
- if !ok {
- return ""
- }
- parts := strings.Split(file, "/")
- file = parts[len(parts)-1]
-
- return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
-
-}
-
-func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
- if len(msgAndArgs) == 0 || msgAndArgs == nil {
- return ""
- }
- if len(msgAndArgs) == 1 {
- return msgAndArgs[0].(string)
- }
- if len(msgAndArgs) > 1 {
- return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
- }
- return ""
-}
-
-// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's
-// test printing (see inner comment for specifics)
-func indentMessageLines(message string, tabs int) string {
- outBuf := new(bytes.Buffer)
-
- for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
- if i != 0 {
- outBuf.WriteRune('\n')
- }
- for ii := 0; ii < tabs; ii++ {
- outBuf.WriteRune('\t')
- // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter
- // by 1 prematurely.
- if ii == 0 && i > 0 {
- ii++
- }
- }
- outBuf.WriteString(scanner.Text())
- }
-
- return outBuf.String()
-}
-
-// Fail reports a failure through
-func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
-
- message := messageFromMsgAndArgs(msgAndArgs...)
-
- errorTrace := strings.Join(CallerInfo(), "\n\r\t\t\t")
- if len(message) > 0 {
- t.Errorf("\r%s\r\tError Trace:\t%s\n"+
- "\r\tError:%s\n"+
- "\r\tMessages:\t%s\n\r",
- getWhitespaceString(),
- errorTrace,
- indentMessageLines(failureMessage, 2),
- message)
- } else {
- t.Errorf("\r%s\r\tError Trace:\t%s\n"+
- "\r\tError:%s\n\r",
- getWhitespaceString(),
- errorTrace,
- indentMessageLines(failureMessage, 2))
- }
-
- return false
-}
-
-// Implements asserts that an object is implemented by the specified interface.
-//
-// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
-func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
-
- interfaceType := reflect.TypeOf(interfaceObject).Elem()
-
- if !reflect.TypeOf(object).Implements(interfaceType) {
- return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
- }
-
- return true
-
-}
-
-// IsType asserts that the specified objects are of the same type.
-func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
-
- if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
- return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
- }
-
- return true
-}
-
-// Equal asserts that two objects are equal.
-//
-// assert.Equal(t, 123, 123, "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- if !ObjectsAreEqual(expected, actual) {
- return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
- " != %#v (actual)", expected, actual), msgAndArgs...)
- }
-
- return true
-
-}
-
-// EqualValues asserts that two objects are equal or convertable to the same types
-// and equal.
-//
-// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- if !ObjectsAreEqualValues(expected, actual) {
- return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
- " != %#v (actual)", expected, actual), msgAndArgs...)
- }
-
- return true
-
-}
-
-// Exactly asserts that two objects are equal is value and type.
-//
-// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- aType := reflect.TypeOf(expected)
- bType := reflect.TypeOf(actual)
-
- if aType != bType {
- return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
- }
-
- return Equal(t, expected, actual, msgAndArgs...)
-
-}
-
-// NotNil asserts that the specified object is not nil.
-//
-// assert.NotNil(t, err, "err should be something")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- if !isNil(object) {
- return true
- }
- return Fail(t, "Expected value not to be nil.", msgAndArgs...)
-}
-
-// isNil checks if a specified object is nil or not, without Failing.
-func isNil(object interface{}) bool {
- if object == nil {
- return true
- }
-
- value := reflect.ValueOf(object)
- kind := value.Kind()
- if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
- return true
- }
-
- return false
-}
-
-// Nil asserts that the specified object is nil.
-//
-// assert.Nil(t, err, "err should be nothing")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
- if isNil(object) {
- return true
- }
- return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
-}
-
-var numericZeros = []interface{}{
- int(0),
- int8(0),
- int16(0),
- int32(0),
- int64(0),
- uint(0),
- uint8(0),
- uint16(0),
- uint32(0),
- uint64(0),
- float32(0),
- float64(0),
-}
-
-// isEmpty gets whether the specified object is considered empty or not.
-func isEmpty(object interface{}) bool {
-
- if object == nil {
- return true
- } else if object == "" {
- return true
- } else if object == false {
- return true
- }
-
- for _, v := range numericZeros {
- if object == v {
- return true
- }
- }
-
- objValue := reflect.ValueOf(object)
-
- switch objValue.Kind() {
- case reflect.Map:
- fallthrough
- case reflect.Slice, reflect.Chan:
- {
- return (objValue.Len() == 0)
- }
- case reflect.Ptr:
- {
- switch object.(type) {
- case *time.Time:
- return object.(*time.Time).IsZero()
- default:
- return false
- }
- }
- }
- return false
-}
-
-// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
-// a slice or a channel with len == 0.
-//
-// assert.Empty(t, obj)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
-
- pass := isEmpty(object)
- if !pass {
- Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
- }
-
- return pass
-
-}
-
-// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
-// a slice or a channel with len == 0.
-//
-// if assert.NotEmpty(t, obj) {
-// assert.Equal(t, "two", obj[1])
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
-
- pass := !isEmpty(object)
- if !pass {
- Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
- }
-
- return pass
-
-}
-
-// getLen try to get length of object.
-// return (false, 0) if impossible.
-func getLen(x interface{}) (ok bool, length int) {
- v := reflect.ValueOf(x)
- defer func() {
- if e := recover(); e != nil {
- ok = false
- }
- }()
- return true, v.Len()
-}
-
-// Len asserts that the specified object has specific length.
-// Len also fails if the object has a type that len() not accept.
-//
-// assert.Len(t, mySlice, 3, "The size of slice is not 3")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
- ok, l := getLen(object)
- if !ok {
- return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
- }
-
- if l != length {
- return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
- }
- return true
-}
-
-// True asserts that the specified value is true.
-//
-// assert.True(t, myBool, "myBool should be true")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
-
- if value != true {
- return Fail(t, "Should be true", msgAndArgs...)
- }
-
- return true
-
-}
-
-// False asserts that the specified value is true.
-//
-// assert.False(t, myBool, "myBool should be false")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
-
- if value != false {
- return Fail(t, "Should be false", msgAndArgs...)
- }
-
- return true
-
-}
-
-// NotEqual asserts that the specified values are NOT equal.
-//
-// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
-
- if ObjectsAreEqual(expected, actual) {
- return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
- }
-
- return true
-
-}
-
-// containsElement try loop over the list check if the list includes the element.
-// return (false, false) if impossible.
-// return (true, false) if element was not found.
-// return (true, true) if element was found.
-func includeElement(list interface{}, element interface{}) (ok, found bool) {
-
- listValue := reflect.ValueOf(list)
- elementValue := reflect.ValueOf(element)
- defer func() {
- if e := recover(); e != nil {
- ok = false
- found = false
- }
- }()
-
- if reflect.TypeOf(list).Kind() == reflect.String {
- return true, strings.Contains(listValue.String(), elementValue.String())
- }
-
- for i := 0; i < listValue.Len(); i++ {
- if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
- return true, true
- }
- }
- return true, false
-
-}
-
-// Contains asserts that the specified string or list(array, slice...) contains the
-// specified substring or element.
-//
-// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
-// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
-
- ok, found := includeElement(s, contains)
- if !ok {
- return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
- }
- if !found {
- return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
- }
-
- return true
-
-}
-
-// NotContains asserts that the specified string or list(array, slice...) does NOT contain the
-// specified substring or element.
-//
-// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
-// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
-
- ok, found := includeElement(s, contains)
- if !ok {
- return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
- }
- if found {
- return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
- }
-
- return true
-
-}
-
-// Condition uses a Comparison to assert a complex condition.
-func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
- result := comp()
- if !result {
- Fail(t, "Condition failed!", msgAndArgs...)
- }
- return result
-}
-
-// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
-// methods, and represents a simple func that takes no arguments, and returns nothing.
-type PanicTestFunc func()
-
-// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
-func didPanic(f PanicTestFunc) (bool, interface{}) {
-
- didPanic := false
- var message interface{}
- func() {
-
- defer func() {
- if message = recover(); message != nil {
- didPanic = true
- }
- }()
-
- // call the target function
- f()
-
- }()
-
- return didPanic, message
-
-}
-
-// Panics asserts that the code inside the specified PanicTestFunc panics.
-//
-// assert.Panics(t, func(){
-// GoCrazy()
-// }, "Calling GoCrazy() should panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
-
- if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
- return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
- }
-
- return true
-}
-
-// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
-//
-// assert.NotPanics(t, func(){
-// RemainCalm()
-// }, "Calling RemainCalm() should NOT panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
-
- if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
- return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
- }
-
- return true
-}
-
-// WithinDuration asserts that the two times are within duration delta of each other.
-//
-// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
-
- dt := expected.Sub(actual)
- if dt < -delta || dt > delta {
- return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
- }
-
- return true
-}
-
-func toFloat(x interface{}) (float64, bool) {
- var xf float64
- xok := true
-
- switch xn := x.(type) {
- case uint8:
- xf = float64(xn)
- case uint16:
- xf = float64(xn)
- case uint32:
- xf = float64(xn)
- case uint64:
- xf = float64(xn)
- case int:
- xf = float64(xn)
- case int8:
- xf = float64(xn)
- case int16:
- xf = float64(xn)
- case int32:
- xf = float64(xn)
- case int64:
- xf = float64(xn)
- case float32:
- xf = float64(xn)
- case float64:
- xf = float64(xn)
- default:
- xok = false
- }
-
- return xf, xok
-}
-
-// InDelta asserts that the two numerals are within delta of each other.
-//
-// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
-
- af, aok := toFloat(expected)
- bf, bok := toFloat(actual)
-
- if !aok || !bok {
- return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
- }
-
- if math.IsNaN(af) {
- return Fail(t, fmt.Sprintf("Actual must not be NaN"), msgAndArgs...)
- }
-
- if math.IsNaN(bf) {
- return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...)
- }
-
- dt := af - bf
- if dt < -delta || dt > delta {
- return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
- }
-
- return true
-}
-
-// InDeltaSlice is the same as InDelta, except it compares two slices.
-func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
- if expected == nil || actual == nil ||
- reflect.TypeOf(actual).Kind() != reflect.Slice ||
- reflect.TypeOf(expected).Kind() != reflect.Slice {
- return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
- }
-
- actualSlice := reflect.ValueOf(actual)
- expectedSlice := reflect.ValueOf(expected)
-
- for i := 0; i < actualSlice.Len(); i++ {
- result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
- if !result {
- return result
- }
- }
-
- return true
-}
-
-// min(|expected|, |actual|) * epsilon
-func calcEpsilonDelta(expected, actual interface{}, epsilon float64) float64 {
- af, aok := toFloat(expected)
- bf, bok := toFloat(actual)
-
- if !aok || !bok {
- // invalid input
- return 0
- }
-
- if af < 0 {
- af = -af
- }
- if bf < 0 {
- bf = -bf
- }
- var delta float64
- if af < bf {
- delta = af * epsilon
- } else {
- delta = bf * epsilon
- }
- return delta
-}
-
-// InEpsilon asserts that expected and actual have a relative error less than epsilon
-//
-// Returns whether the assertion was successful (true) or not (false).
-func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
- delta := calcEpsilonDelta(expected, actual, epsilon)
-
- return InDelta(t, expected, actual, delta, msgAndArgs...)
-}
-
-// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
-func InEpsilonSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
- if expected == nil || actual == nil ||
- reflect.TypeOf(actual).Kind() != reflect.Slice ||
- reflect.TypeOf(expected).Kind() != reflect.Slice {
- return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...)
- }
-
- actualSlice := reflect.ValueOf(actual)
- expectedSlice := reflect.ValueOf(expected)
-
- for i := 0; i < actualSlice.Len(); i++ {
- result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
- if !result {
- return result
- }
- }
-
- return true
-}
-
-/*
- Errors
-*/
-
-// NoError asserts that a function returned no error (i.e. `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.NoError(t, err) {
-// assert.Equal(t, actualObj, expectedObj)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
- if isNil(err) {
- return true
- }
-
- return Fail(t, fmt.Sprintf("No error is expected but got %v", err), msgAndArgs...)
-}
-
-// Error asserts that a function returned an error (i.e. not `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(t, err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
-
- message := messageFromMsgAndArgs(msgAndArgs...)
- return NotNil(t, err, "An error is expected but got nil. %s", message)
-
-}
-
-// EqualError asserts that a function returned an error (i.e. not `nil`)
-// and that it is equal to the provided error.
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(t, err, "An error was expected") {
-// assert.Equal(t, err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
-
- message := messageFromMsgAndArgs(msgAndArgs...)
- if !NotNil(t, theError, "An error is expected but got nil. %s", message) {
- return false
- }
- s := "An error with value \"%s\" is expected but got \"%s\". %s"
- return Equal(t, errString, theError.Error(),
- s, errString, theError.Error(), message)
-}
-
-// matchRegexp return true if a specified regexp matches a string.
-func matchRegexp(rx interface{}, str interface{}) bool {
-
- var r *regexp.Regexp
- if rr, ok := rx.(*regexp.Regexp); ok {
- r = rr
- } else {
- r = regexp.MustCompile(fmt.Sprint(rx))
- }
-
- return (r.FindStringIndex(fmt.Sprint(str)) != nil)
-
-}
-
-// Regexp asserts that a specified regexp matches a string.
-//
-// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
-// assert.Regexp(t, "start...$", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
-
- match := matchRegexp(rx, str)
-
- if !match {
- Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...)
- }
-
- return match
-}
-
-// NotRegexp asserts that a specified regexp does not match a string.
-//
-// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
-// assert.NotRegexp(t, "^start", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
- match := matchRegexp(rx, str)
-
- if match {
- Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...)
- }
-
- return !match
-
-}
-
-// Zero asserts that i is the zero value for its type and returns the truth.
-func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
- if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
- return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
- }
- return true
-}
-
-// NotZero asserts that i is not the zero value for its type and returns the truth.
-func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
- if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
- return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
- }
- return true
-}
diff --git a/vendor/github.com/stretchr/testify/assert/assertions_test.go b/vendor/github.com/stretchr/testify/assert/assertions_test.go
deleted file mode 100644
index 9c5bef8..0000000
--- a/vendor/github.com/stretchr/testify/assert/assertions_test.go
+++ /dev/null
@@ -1,911 +0,0 @@
-package assert
-
-import (
- "errors"
- "io"
- "math"
- "reflect"
- "regexp"
- "testing"
- "time"
-)
-
-var (
- i interface{}
- zeros = []interface{}{
- false,
- byte(0),
- complex64(0),
- complex128(0),
- float32(0),
- float64(0),
- int(0),
- int8(0),
- int16(0),
- int32(0),
- int64(0),
- rune(0),
- uint(0),
- uint8(0),
- uint16(0),
- uint32(0),
- uint64(0),
- uintptr(0),
- "",
- [0]interface{}{},
- []interface{}(nil),
- struct{ x int }{},
- (*interface{})(nil),
- (func())(nil),
- nil,
- interface{}(nil),
- map[interface{}]interface{}(nil),
- (chan interface{})(nil),
- (<-chan interface{})(nil),
- (chan<- interface{})(nil),
- }
- nonZeros = []interface{}{
- true,
- byte(1),
- complex64(1),
- complex128(1),
- float32(1),
- float64(1),
- int(1),
- int8(1),
- int16(1),
- int32(1),
- int64(1),
- rune(1),
- uint(1),
- uint8(1),
- uint16(1),
- uint32(1),
- uint64(1),
- uintptr(1),
- "s",
- [1]interface{}{1},
- []interface{}{},
- struct{ x int }{1},
- (*interface{})(&i),
- (func())(func() {}),
- interface{}(1),
- map[interface{}]interface{}{},
- (chan interface{})(make(chan interface{})),
- (<-chan interface{})(make(chan interface{})),
- (chan<- interface{})(make(chan interface{})),
- }
-)
-
-// AssertionTesterInterface defines an interface to be used for testing assertion methods
-type AssertionTesterInterface interface {
- TestMethod()
-}
-
-// AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface
-type AssertionTesterConformingObject struct {
-}
-
-func (a *AssertionTesterConformingObject) TestMethod() {
-}
-
-// AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface
-type AssertionTesterNonConformingObject struct {
-}
-
-func TestObjectsAreEqual(t *testing.T) {
-
- if !ObjectsAreEqual("Hello World", "Hello World") {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual(123, 123) {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual(123.5, 123.5) {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual([]byte("Hello World"), []byte("Hello World")) {
- t.Error("objectsAreEqual should return true")
- }
- if !ObjectsAreEqual(nil, nil) {
- t.Error("objectsAreEqual should return true")
- }
- if ObjectsAreEqual(map[int]int{5: 10}, map[int]int{10: 20}) {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual('x', "x") {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual("x", 'x') {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual(0, 0.1) {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual(0.1, 0) {
- t.Error("objectsAreEqual should return false")
- }
- if ObjectsAreEqual(uint32(10), int32(10)) {
- t.Error("objectsAreEqual should return false")
- }
- if !ObjectsAreEqualValues(uint32(10), int32(10)) {
- t.Error("ObjectsAreEqualValues should return true")
- }
-
-}
-
-func TestImplements(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) {
- t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface")
- }
- if Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) {
- t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface")
- }
-
-}
-
-func TestIsType(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
- t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject")
- }
- if IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) {
- t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject")
- }
-
-}
-
-func TestEqual(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Equal(mockT, "Hello World", "Hello World") {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, 123, 123) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, 123.5, 123.5) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, []byte("Hello World"), []byte("Hello World")) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, nil, nil) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, int32(123), int32(123)) {
- t.Error("Equal should return true")
- }
- if !Equal(mockT, uint64(123), uint64(123)) {
- t.Error("Equal should return true")
- }
-
-}
-
-func TestNotNil(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !NotNil(mockT, new(AssertionTesterConformingObject)) {
- t.Error("NotNil should return true: object is not nil")
- }
- if NotNil(mockT, nil) {
- t.Error("NotNil should return false: object is nil")
- }
- if NotNil(mockT, (*struct{})(nil)) {
- t.Error("NotNil should return false: object is (*struct{})(nil)")
- }
-
-}
-
-func TestNil(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Nil(mockT, nil) {
- t.Error("Nil should return true: object is nil")
- }
- if !Nil(mockT, (*struct{})(nil)) {
- t.Error("Nil should return true: object is (*struct{})(nil)")
- }
- if Nil(mockT, new(AssertionTesterConformingObject)) {
- t.Error("Nil should return false: object is not nil")
- }
-
-}
-
-func TestTrue(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !True(mockT, true) {
- t.Error("True should return true")
- }
- if True(mockT, false) {
- t.Error("True should return false")
- }
-
-}
-
-func TestFalse(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !False(mockT, false) {
- t.Error("False should return true")
- }
- if False(mockT, true) {
- t.Error("False should return false")
- }
-
-}
-
-func TestExactly(t *testing.T) {
-
- mockT := new(testing.T)
-
- a := float32(1)
- b := float64(1)
- c := float32(1)
- d := float32(2)
-
- if Exactly(mockT, a, b) {
- t.Error("Exactly should return false")
- }
- if Exactly(mockT, a, d) {
- t.Error("Exactly should return false")
- }
- if !Exactly(mockT, a, c) {
- t.Error("Exactly should return true")
- }
-
- if Exactly(mockT, nil, a) {
- t.Error("Exactly should return false")
- }
- if Exactly(mockT, a, nil) {
- t.Error("Exactly should return false")
- }
-
-}
-
-func TestNotEqual(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !NotEqual(mockT, "Hello World", "Hello World!") {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, 123, 1234) {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, 123.5, 123.55) {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, []byte("Hello World"), []byte("Hello World!")) {
- t.Error("NotEqual should return true")
- }
- if !NotEqual(mockT, nil, new(AssertionTesterConformingObject)) {
- t.Error("NotEqual should return true")
- }
- funcA := func() int { return 23 }
- funcB := func() int { return 42 }
- if !NotEqual(mockT, funcA, funcB) {
- t.Error("NotEqual should return true")
- }
-
- if NotEqual(mockT, "Hello World", "Hello World") {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, 123, 123) {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, 123.5, 123.5) {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, []byte("Hello World"), []byte("Hello World")) {
- t.Error("NotEqual should return false")
- }
- if NotEqual(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
- t.Error("NotEqual should return false")
- }
-}
-
-type A struct {
- Name, Value string
-}
-
-func TestContains(t *testing.T) {
-
- mockT := new(testing.T)
- list := []string{"Foo", "Bar"}
- complexList := []*A{
- {"b", "c"},
- {"d", "e"},
- {"g", "h"},
- {"j", "k"},
- }
-
- if !Contains(mockT, "Hello World", "Hello") {
- t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
- }
- if Contains(mockT, "Hello World", "Salut") {
- t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"")
- }
-
- if !Contains(mockT, list, "Bar") {
- t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Bar\"")
- }
- if Contains(mockT, list, "Salut") {
- t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"")
- }
- if !Contains(mockT, complexList, &A{"g", "h"}) {
- t.Error("Contains should return true: complexList contains {\"g\", \"h\"}")
- }
- if Contains(mockT, complexList, &A{"g", "e"}) {
- t.Error("Contains should return false: complexList contains {\"g\", \"e\"}")
- }
-}
-
-func TestNotContains(t *testing.T) {
-
- mockT := new(testing.T)
- list := []string{"Foo", "Bar"}
-
- if !NotContains(mockT, "Hello World", "Hello!") {
- t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
- }
- if NotContains(mockT, "Hello World", "Hello") {
- t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"")
- }
-
- if !NotContains(mockT, list, "Foo!") {
- t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"")
- }
- if NotContains(mockT, list, "Foo") {
- t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
- }
-
-}
-
-func Test_includeElement(t *testing.T) {
-
- list1 := []string{"Foo", "Bar"}
- list2 := []int{1, 2}
-
- ok, found := includeElement("Hello World", "World")
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list1, "Foo")
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list1, "Bar")
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list2, 1)
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list2, 2)
- True(t, ok)
- True(t, found)
-
- ok, found = includeElement(list1, "Foo!")
- True(t, ok)
- False(t, found)
-
- ok, found = includeElement(list2, 3)
- True(t, ok)
- False(t, found)
-
- ok, found = includeElement(list2, "1")
- True(t, ok)
- False(t, found)
-
- ok, found = includeElement(1433, "1")
- False(t, ok)
- False(t, found)
-
-}
-
-func TestCondition(t *testing.T) {
- mockT := new(testing.T)
-
- if !Condition(mockT, func() bool { return true }, "Truth") {
- t.Error("Condition should return true")
- }
-
- if Condition(mockT, func() bool { return false }, "Lie") {
- t.Error("Condition should return false")
- }
-
-}
-
-func TestDidPanic(t *testing.T) {
-
- if funcDidPanic, _ := didPanic(func() {
- panic("Panic!")
- }); !funcDidPanic {
- t.Error("didPanic should return true")
- }
-
- if funcDidPanic, _ := didPanic(func() {
- }); funcDidPanic {
- t.Error("didPanic should return false")
- }
-
-}
-
-func TestPanics(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !Panics(mockT, func() {
- panic("Panic!")
- }) {
- t.Error("Panics should return true")
- }
-
- if Panics(mockT, func() {
- }) {
- t.Error("Panics should return false")
- }
-
-}
-
-func TestNotPanics(t *testing.T) {
-
- mockT := new(testing.T)
-
- if !NotPanics(mockT, func() {
- }) {
- t.Error("NotPanics should return true")
- }
-
- if NotPanics(mockT, func() {
- panic("Panic!")
- }) {
- t.Error("NotPanics should return false")
- }
-
-}
-
-func TestNoError(t *testing.T) {
-
- mockT := new(testing.T)
-
- // start with a nil error
- var err error
-
- True(t, NoError(mockT, err), "NoError should return True for nil arg")
-
- // now set an error
- err = errors.New("some error")
-
- False(t, NoError(mockT, err), "NoError with error should return False")
-
-}
-
-func TestError(t *testing.T) {
-
- mockT := new(testing.T)
-
- // start with a nil error
- var err error
-
- False(t, Error(mockT, err), "Error should return False for nil arg")
-
- // now set an error
- err = errors.New("some error")
-
- True(t, Error(mockT, err), "Error with error should return True")
-
-}
-
-func TestEqualError(t *testing.T) {
- mockT := new(testing.T)
-
- // start with a nil error
- var err error
- False(t, EqualError(mockT, err, ""),
- "EqualError should return false for nil arg")
-
- // now set an error
- err = errors.New("some error")
- False(t, EqualError(mockT, err, "Not some error"),
- "EqualError should return false for different error string")
- True(t, EqualError(mockT, err, "some error"),
- "EqualError should return true")
-}
-
-func Test_isEmpty(t *testing.T) {
-
- chWithValue := make(chan struct{}, 1)
- chWithValue <- struct{}{}
-
- True(t, isEmpty(""))
- True(t, isEmpty(nil))
- True(t, isEmpty([]string{}))
- True(t, isEmpty(0))
- True(t, isEmpty(int32(0)))
- True(t, isEmpty(int64(0)))
- True(t, isEmpty(false))
- True(t, isEmpty(map[string]string{}))
- True(t, isEmpty(new(time.Time)))
- True(t, isEmpty(make(chan struct{})))
- False(t, isEmpty("something"))
- False(t, isEmpty(errors.New("something")))
- False(t, isEmpty([]string{"something"}))
- False(t, isEmpty(1))
- False(t, isEmpty(true))
- False(t, isEmpty(map[string]string{"Hello": "World"}))
- False(t, isEmpty(chWithValue))
-
-}
-
-func TestEmpty(t *testing.T) {
-
- mockT := new(testing.T)
- chWithValue := make(chan struct{}, 1)
- chWithValue <- struct{}{}
-
- True(t, Empty(mockT, ""), "Empty string is empty")
- True(t, Empty(mockT, nil), "Nil is empty")
- True(t, Empty(mockT, []string{}), "Empty string array is empty")
- True(t, Empty(mockT, 0), "Zero int value is empty")
- True(t, Empty(mockT, false), "False value is empty")
- True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty")
-
- False(t, Empty(mockT, "something"), "Non Empty string is not empty")
- False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty")
- False(t, Empty(mockT, []string{"something"}), "Non empty string array is not empty")
- False(t, Empty(mockT, 1), "Non-zero int value is not empty")
- False(t, Empty(mockT, true), "True value is not empty")
- False(t, Empty(mockT, chWithValue), "Channel with values is not empty")
-}
-
-func TestNotEmpty(t *testing.T) {
-
- mockT := new(testing.T)
- chWithValue := make(chan struct{}, 1)
- chWithValue <- struct{}{}
-
- False(t, NotEmpty(mockT, ""), "Empty string is empty")
- False(t, NotEmpty(mockT, nil), "Nil is empty")
- False(t, NotEmpty(mockT, []string{}), "Empty string array is empty")
- False(t, NotEmpty(mockT, 0), "Zero int value is empty")
- False(t, NotEmpty(mockT, false), "False value is empty")
- False(t, NotEmpty(mockT, make(chan struct{})), "Channel without values is empty")
-
- True(t, NotEmpty(mockT, "something"), "Non Empty string is not empty")
- True(t, NotEmpty(mockT, errors.New("something")), "Non nil object is not empty")
- True(t, NotEmpty(mockT, []string{"something"}), "Non empty string array is not empty")
- True(t, NotEmpty(mockT, 1), "Non-zero int value is not empty")
- True(t, NotEmpty(mockT, true), "True value is not empty")
- True(t, NotEmpty(mockT, chWithValue), "Channel with values is not empty")
-}
-
-func Test_getLen(t *testing.T) {
- falseCases := []interface{}{
- nil,
- 0,
- true,
- false,
- 'A',
- struct{}{},
- }
- for _, v := range falseCases {
- ok, l := getLen(v)
- False(t, ok, "Expected getLen fail to get length of %#v", v)
- Equal(t, 0, l, "getLen should return 0 for %#v", v)
- }
-
- ch := make(chan int, 5)
- ch <- 1
- ch <- 2
- ch <- 3
- trueCases := []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 3},
- {[...]int{1, 2, 3}, 3},
- {"ABC", 3},
- {map[int]int{1: 2, 2: 4, 3: 6}, 3},
- {ch, 3},
-
- {[]int{}, 0},
- {map[int]int{}, 0},
- {make(chan int), 0},
-
- {[]int(nil), 0},
- {map[int]int(nil), 0},
- {(chan int)(nil), 0},
- }
-
- for _, c := range trueCases {
- ok, l := getLen(c.v)
- True(t, ok, "Expected getLen success to get length of %#v", c.v)
- Equal(t, c.l, l)
- }
-}
-
-func TestLen(t *testing.T) {
- mockT := new(testing.T)
-
- False(t, Len(mockT, nil, 0), "nil does not have length")
- False(t, Len(mockT, 0, 0), "int does not have length")
- False(t, Len(mockT, true, 0), "true does not have length")
- False(t, Len(mockT, false, 0), "false does not have length")
- False(t, Len(mockT, 'A', 0), "Rune does not have length")
- False(t, Len(mockT, struct{}{}, 0), "Struct does not have length")
-
- ch := make(chan int, 5)
- ch <- 1
- ch <- 2
- ch <- 3
-
- cases := []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 3},
- {[...]int{1, 2, 3}, 3},
- {"ABC", 3},
- {map[int]int{1: 2, 2: 4, 3: 6}, 3},
- {ch, 3},
-
- {[]int{}, 0},
- {map[int]int{}, 0},
- {make(chan int), 0},
-
- {[]int(nil), 0},
- {map[int]int(nil), 0},
- {(chan int)(nil), 0},
- }
-
- for _, c := range cases {
- True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l)
- }
-
- cases = []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 4},
- {[...]int{1, 2, 3}, 2},
- {"ABC", 2},
- {map[int]int{1: 2, 2: 4, 3: 6}, 4},
- {ch, 2},
-
- {[]int{}, 1},
- {map[int]int{}, 1},
- {make(chan int), 1},
-
- {[]int(nil), 1},
- {map[int]int(nil), 1},
- {(chan int)(nil), 1},
- }
-
- for _, c := range cases {
- False(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l)
- }
-}
-
-func TestWithinDuration(t *testing.T) {
-
- mockT := new(testing.T)
- a := time.Now()
- b := a.Add(10 * time.Second)
-
- True(t, WithinDuration(mockT, a, b, 10*time.Second), "A 10s difference is within a 10s time difference")
- True(t, WithinDuration(mockT, b, a, 10*time.Second), "A 10s difference is within a 10s time difference")
-
- False(t, WithinDuration(mockT, a, b, 9*time.Second), "A 10s difference is not within a 9s time difference")
- False(t, WithinDuration(mockT, b, a, 9*time.Second), "A 10s difference is not within a 9s time difference")
-
- False(t, WithinDuration(mockT, a, b, -9*time.Second), "A 10s difference is not within a 9s time difference")
- False(t, WithinDuration(mockT, b, a, -9*time.Second), "A 10s difference is not within a 9s time difference")
-
- False(t, WithinDuration(mockT, a, b, -11*time.Second), "A 10s difference is not within a 9s time difference")
- False(t, WithinDuration(mockT, b, a, -11*time.Second), "A 10s difference is not within a 9s time difference")
-}
-
-func TestInDelta(t *testing.T) {
- mockT := new(testing.T)
-
- True(t, InDelta(mockT, 1.001, 1, 0.01), "|1.001 - 1| <= 0.01")
- True(t, InDelta(mockT, 1, 1.001, 0.01), "|1 - 1.001| <= 0.01")
- True(t, InDelta(mockT, 1, 2, 1), "|1 - 2| <= 1")
- False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail")
- False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail")
- False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail")
- False(t, InDelta(mockT, 42, math.NaN(), 0.01), "Expected NaN for actual to fail")
- False(t, InDelta(mockT, math.NaN(), 42, 0.01), "Expected NaN for expected to fail")
-
- cases := []struct {
- a, b interface{}
- delta float64
- }{
- {uint8(2), uint8(1), 1},
- {uint16(2), uint16(1), 1},
- {uint32(2), uint32(1), 1},
- {uint64(2), uint64(1), 1},
-
- {int(2), int(1), 1},
- {int8(2), int8(1), 1},
- {int16(2), int16(1), 1},
- {int32(2), int32(1), 1},
- {int64(2), int64(1), 1},
-
- {float32(2), float32(1), 1},
- {float64(2), float64(1), 1},
- }
-
- for _, tc := range cases {
- True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta)
- }
-}
-
-func TestInDeltaSlice(t *testing.T) {
- mockT := new(testing.T)
-
- True(t, InDeltaSlice(mockT,
- []float64{1.001, 0.999},
- []float64{1, 1},
- 0.1), "{1.001, 0.009} is element-wise close to {1, 1} in delta=0.1")
-
- True(t, InDeltaSlice(mockT,
- []float64{1, 2},
- []float64{0, 3},
- 1), "{1, 2} is element-wise close to {0, 3} in delta=1")
-
- False(t, InDeltaSlice(mockT,
- []float64{1, 2},
- []float64{0, 3},
- 0.1), "{1, 2} is not element-wise close to {0, 3} in delta=0.1")
-
- False(t, InDeltaSlice(mockT, "", nil, 1), "Expected non numeral slices to fail")
-}
-
-func TestInEpsilon(t *testing.T) {
- mockT := new(testing.T)
-
- cases := []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), uint16(2), .001},
- {2.1, 2.2, 0.1},
- {2.2, 2.1, 0.1},
- {-2.1, -2.2, 0.1},
- {-2.2, -2.1, 0.1},
- {uint64(100), uint8(101), 0.01},
- {0.1, -0.1, 2},
- }
-
- for _, tc := range cases {
- True(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-
- cases = []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), int16(-2), .001},
- {uint64(100), uint8(102), 0.01},
- {2.1, 2.2, 0.001},
- {2.2, 2.1, 0.001},
- {2.1, -2.2, 1},
- {2.1, "bla-bla", 0},
- {0.1, -0.1, 1.99},
- }
-
- for _, tc := range cases {
- False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-
-}
-
-func TestInEpsilonSlice(t *testing.T) {
- mockT := new(testing.T)
-
- True(t, InEpsilonSlice(mockT,
- []float64{2.2, 2.0},
- []float64{2.1, 2.1},
- 0.06), "{2.2, 2.0} is element-wise close to {2.1, 2.1} in espilon=0.06")
-
- False(t, InEpsilonSlice(mockT,
- []float64{2.2, 2.0},
- []float64{2.1, 2.1},
- 0.04), "{2.2, 2.0} is not element-wise close to {2.1, 2.1} in espilon=0.04")
-
- False(t, InEpsilonSlice(mockT, "", nil, 1), "Expected non numeral slices to fail")
-}
-
-func TestRegexp(t *testing.T) {
- mockT := new(testing.T)
-
- cases := []struct {
- rx, str string
- }{
- {"^start", "start of the line"},
- {"end$", "in the end"},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"},
- }
-
- for _, tc := range cases {
- True(t, Regexp(mockT, tc.rx, tc.str))
- True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- False(t, NotRegexp(mockT, tc.rx, tc.str))
- False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- }
-
- cases = []struct {
- rx, str string
- }{
- {"^asdfastart", "Not the start of the line"},
- {"end$", "in the end."},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"},
- }
-
- for _, tc := range cases {
- False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str)
- False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- True(t, NotRegexp(mockT, tc.rx, tc.str))
- True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str))
- }
-}
-
-func testAutogeneratedFunction() {
- defer func() {
- if err := recover(); err == nil {
- panic("did not panic")
- }
- CallerInfo()
- }()
- t := struct {
- io.Closer
- }{}
- var c io.Closer
- c = t
- c.Close()
-}
-
-func TestCallerInfoWithAutogeneratedFunctions(t *testing.T) {
- NotPanics(t, func() {
- testAutogeneratedFunction()
- })
-}
-
-func TestZero(t *testing.T) {
- mockT := new(testing.T)
-
- for _, test := range zeros {
- True(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-
- for _, test := range nonZeros {
- False(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-}
-
-func TestNotZero(t *testing.T) {
- mockT := new(testing.T)
-
- for _, test := range zeros {
- False(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-
- for _, test := range nonZeros {
- True(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
- }
-}
diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go
deleted file mode 100644
index c9dccc4..0000000
--- a/vendor/github.com/stretchr/testify/assert/doc.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.
-//
-// Example Usage
-//
-// The following is a complete example using assert in a standard test function:
-// import (
-// "testing"
-// "github.com/stretchr/testify/assert"
-// )
-//
-// func TestSomething(t *testing.T) {
-//
-// var a string = "Hello"
-// var b string = "Hello"
-//
-// assert.Equal(t, a, b, "The two words should be the same.")
-//
-// }
-//
-// if you assert many times, use the format below:
-//
-// import (
-// "testing"
-// "github.com/stretchr/testify/assert"
-// )
-//
-// func TestSomething(t *testing.T) {
-// assert := assert.New(t)
-//
-// var a string = "Hello"
-// var b string = "Hello"
-//
-// assert.Equal(a, b, "The two words should be the same.")
-// }
-//
-// Assertions
-//
-// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
-// All assertion functions take, as the first argument, the `*testing.T` object provided by the
-// testing framework. This allows the assertion funcs to write the failings and other details to
-// the correct place.
-//
-// Every assertion function also takes an optional string message as the final argument,
-// allowing custom error messages to be appended to the message the assertion method outputs.
-package assert
diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go
deleted file mode 100644
index ac9dc9d..0000000
--- a/vendor/github.com/stretchr/testify/assert/errors.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package assert
-
-import (
- "errors"
-)
-
-// AnError is an error instance useful for testing. If the code does not care
-// about error specifics, and only needs to return the error for example, this
-// error should be used to make the test code more readable.
-var AnError = errors.New("assert.AnError general error for testing")
diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go
deleted file mode 100644
index dc14771..0000000
--- a/vendor/github.com/stretchr/testify/assert/forward_assertions.go
+++ /dev/null
@@ -1,275 +0,0 @@
-package assert
-
-import "time"
-
-// Assertions provides assertion methods around the
-// TestingT interface.
-type Assertions struct {
- t TestingT
-}
-
-// New makes a new Assertions object for the specified TestingT.
-func New(t TestingT) *Assertions {
- return &Assertions{
- t: t,
- }
-}
-
-// Fail reports a failure through
-func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
- return Fail(a.t, failureMessage, msgAndArgs...)
-}
-
-// Implements asserts that an object is implemented by the specified interface.
-//
-// assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
-func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
- return Implements(a.t, interfaceObject, object, msgAndArgs...)
-}
-
-// IsType asserts that the specified objects are of the same type.
-func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
- return IsType(a.t, expectedType, object, msgAndArgs...)
-}
-
-// Equal asserts that two objects are equal.
-//
-// assert.Equal(123, 123, "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return Equal(a.t, expected, actual, msgAndArgs...)
-}
-
-// EqualValues asserts that two objects are equal or convertable to the same types
-// and equal.
-//
-// assert.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return EqualValues(a.t, expected, actual, msgAndArgs...)
-}
-
-// Exactly asserts that two objects are equal is value and type.
-//
-// assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return Exactly(a.t, expected, actual, msgAndArgs...)
-}
-
-// NotNil asserts that the specified object is not nil.
-//
-// assert.NotNil(err, "err should be something")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
- return NotNil(a.t, object, msgAndArgs...)
-}
-
-// Nil asserts that the specified object is nil.
-//
-// assert.Nil(err, "err should be nothing")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
- return Nil(a.t, object, msgAndArgs...)
-}
-
-// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or a
-// slice with len == 0.
-//
-// assert.Empty(obj)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
- return Empty(a.t, object, msgAndArgs...)
-}
-
-// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a
-// slice with len == 0.
-//
-// if assert.NotEmpty(obj) {
-// assert.Equal("two", obj[1])
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
- return NotEmpty(a.t, object, msgAndArgs...)
-}
-
-// Len asserts that the specified object has specific length.
-// Len also fails if the object has a type that len() not accept.
-//
-// assert.Len(mySlice, 3, "The size of slice is not 3")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
- return Len(a.t, object, length, msgAndArgs...)
-}
-
-// True asserts that the specified value is true.
-//
-// assert.True(myBool, "myBool should be true")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
- return True(a.t, value, msgAndArgs...)
-}
-
-// False asserts that the specified value is true.
-//
-// assert.False(myBool, "myBool should be false")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
- return False(a.t, value, msgAndArgs...)
-}
-
-// NotEqual asserts that the specified values are NOT equal.
-//
-// assert.NotEqual(obj1, obj2, "two objects shouldn't be equal")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool {
- return NotEqual(a.t, expected, actual, msgAndArgs...)
-}
-
-// Contains asserts that the specified string contains the specified substring.
-//
-// assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool {
- return Contains(a.t, s, contains, msgAndArgs...)
-}
-
-// NotContains asserts that the specified string does NOT contain the specified substring.
-//
-// assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool {
- return NotContains(a.t, s, contains, msgAndArgs...)
-}
-
-// Condition uses a Comparison to assert a complex condition.
-func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
- return Condition(a.t, comp, msgAndArgs...)
-}
-
-// Panics asserts that the code inside the specified PanicTestFunc panics.
-//
-// assert.Panics(func(){
-// GoCrazy()
-// }, "Calling GoCrazy() should panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
- return Panics(a.t, f, msgAndArgs...)
-}
-
-// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
-//
-// assert.NotPanics(func(){
-// RemainCalm()
-// }, "Calling RemainCalm() should NOT panic")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
- return NotPanics(a.t, f, msgAndArgs...)
-}
-
-// WithinDuration asserts that the two times are within duration delta of each other.
-//
-// assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
- return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
-}
-
-// InDelta asserts that the two numerals are within delta of each other.
-//
-// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
- return InDelta(a.t, expected, actual, delta, msgAndArgs...)
-}
-
-// InEpsilon asserts that expected and actual have a relative error less than epsilon
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
- return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
-}
-
-// NoError asserts that a function returned no error (i.e. `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.NoError(err) {
-// assert.Equal(actualObj, expectedObj)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool {
- return NoError(a.t, theError, msgAndArgs...)
-}
-
-// Error asserts that a function returned an error (i.e. not `nil`).
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(err, "An error was expected") {
-// assert.Equal(err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool {
- return Error(a.t, theError, msgAndArgs...)
-}
-
-// EqualError asserts that a function returned an error (i.e. not `nil`)
-// and that it is equal to the provided error.
-//
-// actualObj, err := SomeFunction()
-// if assert.Error(err, "An error was expected") {
-// assert.Equal(err, expectedError)
-// }
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
- return EqualError(a.t, theError, errString, msgAndArgs...)
-}
-
-// Regexp asserts that a specified regexp matches a string.
-//
-// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
-// assert.Regexp(t, "start...$", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
- return Regexp(a.t, rx, str, msgAndArgs...)
-}
-
-// NotRegexp asserts that a specified regexp does not match a string.
-//
-// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
-// assert.NotRegexp(t, "^start", "it's not starting")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
- return NotRegexp(a.t, rx, str, msgAndArgs...)
-}
-
-// Zero asserts that i is the zero value for its type and returns the truth.
-func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
- return Zero(a.t, i, msgAndArgs...)
-}
-
-// NotZero asserts that i is not the zero value for its type and returns the truth.
-func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
- return NotZero(a.t, i, msgAndArgs...)
-}
diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions_test.go b/vendor/github.com/stretchr/testify/assert/forward_assertions_test.go
deleted file mode 100644
index 280d0ab..0000000
--- a/vendor/github.com/stretchr/testify/assert/forward_assertions_test.go
+++ /dev/null
@@ -1,537 +0,0 @@
-package assert
-
-import (
- "errors"
- "regexp"
- "testing"
- "time"
-)
-
-func TestImplementsWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) {
- t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface")
- }
- if assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) {
- t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface")
- }
-}
-
-func TestIsTypeWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
- t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject")
- }
- if assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) {
- t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject")
- }
-
-}
-
-func TestEqualWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.Equal("Hello World", "Hello World") {
- t.Error("Equal should return true")
- }
- if !assert.Equal(123, 123) {
- t.Error("Equal should return true")
- }
- if !assert.Equal(123.5, 123.5) {
- t.Error("Equal should return true")
- }
- if !assert.Equal([]byte("Hello World"), []byte("Hello World")) {
- t.Error("Equal should return true")
- }
- if !assert.Equal(nil, nil) {
- t.Error("Equal should return true")
- }
-}
-
-func TestEqualValuesWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.EqualValues(uint32(10), int32(10)) {
- t.Error("EqualValues should return true")
- }
-}
-
-func TestNotNilWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.NotNil(new(AssertionTesterConformingObject)) {
- t.Error("NotNil should return true: object is not nil")
- }
- if assert.NotNil(nil) {
- t.Error("NotNil should return false: object is nil")
- }
-
-}
-
-func TestNilWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.Nil(nil) {
- t.Error("Nil should return true: object is nil")
- }
- if assert.Nil(new(AssertionTesterConformingObject)) {
- t.Error("Nil should return false: object is not nil")
- }
-
-}
-
-func TestTrueWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.True(true) {
- t.Error("True should return true")
- }
- if assert.True(false) {
- t.Error("True should return false")
- }
-
-}
-
-func TestFalseWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- if !assert.False(false) {
- t.Error("False should return true")
- }
- if assert.False(true) {
- t.Error("False should return false")
- }
-
-}
-
-func TestExactlyWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- a := float32(1)
- b := float64(1)
- c := float32(1)
- d := float32(2)
-
- if assert.Exactly(a, b) {
- t.Error("Exactly should return false")
- }
- if assert.Exactly(a, d) {
- t.Error("Exactly should return false")
- }
- if !assert.Exactly(a, c) {
- t.Error("Exactly should return true")
- }
-
- if assert.Exactly(nil, a) {
- t.Error("Exactly should return false")
- }
- if assert.Exactly(a, nil) {
- t.Error("Exactly should return false")
- }
-
-}
-
-func TestNotEqualWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.NotEqual("Hello World", "Hello World!") {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual(123, 1234) {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual(123.5, 123.55) {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual([]byte("Hello World"), []byte("Hello World!")) {
- t.Error("NotEqual should return true")
- }
- if !assert.NotEqual(nil, new(AssertionTesterConformingObject)) {
- t.Error("NotEqual should return true")
- }
-}
-
-func TestContainsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
- list := []string{"Foo", "Bar"}
-
- if !assert.Contains("Hello World", "Hello") {
- t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
- }
- if assert.Contains("Hello World", "Salut") {
- t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"")
- }
-
- if !assert.Contains(list, "Foo") {
- t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
- }
- if assert.Contains(list, "Salut") {
- t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"")
- }
-
-}
-
-func TestNotContainsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
- list := []string{"Foo", "Bar"}
-
- if !assert.NotContains("Hello World", "Hello!") {
- t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
- }
- if assert.NotContains("Hello World", "Hello") {
- t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"")
- }
-
- if !assert.NotContains(list, "Foo!") {
- t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"")
- }
- if assert.NotContains(list, "Foo") {
- t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
- }
-
-}
-
-func TestConditionWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.Condition(func() bool { return true }, "Truth") {
- t.Error("Condition should return true")
- }
-
- if assert.Condition(func() bool { return false }, "Lie") {
- t.Error("Condition should return false")
- }
-
-}
-
-func TestDidPanicWrapper(t *testing.T) {
-
- if funcDidPanic, _ := didPanic(func() {
- panic("Panic!")
- }); !funcDidPanic {
- t.Error("didPanic should return true")
- }
-
- if funcDidPanic, _ := didPanic(func() {
- }); funcDidPanic {
- t.Error("didPanic should return false")
- }
-
-}
-
-func TestPanicsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.Panics(func() {
- panic("Panic!")
- }) {
- t.Error("Panics should return true")
- }
-
- if assert.Panics(func() {
- }) {
- t.Error("Panics should return false")
- }
-
-}
-
-func TestNotPanicsWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- if !assert.NotPanics(func() {
- }) {
- t.Error("NotPanics should return true")
- }
-
- if assert.NotPanics(func() {
- panic("Panic!")
- }) {
- t.Error("NotPanics should return false")
- }
-
-}
-
-func TestNoErrorWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- // start with a nil error
- var err error
-
- assert.True(mockAssert.NoError(err), "NoError should return True for nil arg")
-
- // now set an error
- err = errors.New("Some error")
-
- assert.False(mockAssert.NoError(err), "NoError with error should return False")
-
-}
-
-func TestErrorWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- // start with a nil error
- var err error
-
- assert.False(mockAssert.Error(err), "Error should return False for nil arg")
-
- // now set an error
- err = errors.New("Some error")
-
- assert.True(mockAssert.Error(err), "Error with error should return True")
-
-}
-
-func TestEqualErrorWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- // start with a nil error
- var err error
- assert.False(mockAssert.EqualError(err, ""),
- "EqualError should return false for nil arg")
-
- // now set an error
- err = errors.New("some error")
- assert.False(mockAssert.EqualError(err, "Not some error"),
- "EqualError should return false for different error string")
- assert.True(mockAssert.EqualError(err, "some error"),
- "EqualError should return true")
-}
-
-func TestEmptyWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.True(mockAssert.Empty(""), "Empty string is empty")
- assert.True(mockAssert.Empty(nil), "Nil is empty")
- assert.True(mockAssert.Empty([]string{}), "Empty string array is empty")
- assert.True(mockAssert.Empty(0), "Zero int value is empty")
- assert.True(mockAssert.Empty(false), "False value is empty")
-
- assert.False(mockAssert.Empty("something"), "Non Empty string is not empty")
- assert.False(mockAssert.Empty(errors.New("something")), "Non nil object is not empty")
- assert.False(mockAssert.Empty([]string{"something"}), "Non empty string array is not empty")
- assert.False(mockAssert.Empty(1), "Non-zero int value is not empty")
- assert.False(mockAssert.Empty(true), "True value is not empty")
-
-}
-
-func TestNotEmptyWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.False(mockAssert.NotEmpty(""), "Empty string is empty")
- assert.False(mockAssert.NotEmpty(nil), "Nil is empty")
- assert.False(mockAssert.NotEmpty([]string{}), "Empty string array is empty")
- assert.False(mockAssert.NotEmpty(0), "Zero int value is empty")
- assert.False(mockAssert.NotEmpty(false), "False value is empty")
-
- assert.True(mockAssert.NotEmpty("something"), "Non Empty string is not empty")
- assert.True(mockAssert.NotEmpty(errors.New("something")), "Non nil object is not empty")
- assert.True(mockAssert.NotEmpty([]string{"something"}), "Non empty string array is not empty")
- assert.True(mockAssert.NotEmpty(1), "Non-zero int value is not empty")
- assert.True(mockAssert.NotEmpty(true), "True value is not empty")
-
-}
-
-func TestLenWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.False(mockAssert.Len(nil, 0), "nil does not have length")
- assert.False(mockAssert.Len(0, 0), "int does not have length")
- assert.False(mockAssert.Len(true, 0), "true does not have length")
- assert.False(mockAssert.Len(false, 0), "false does not have length")
- assert.False(mockAssert.Len('A', 0), "Rune does not have length")
- assert.False(mockAssert.Len(struct{}{}, 0), "Struct does not have length")
-
- ch := make(chan int, 5)
- ch <- 1
- ch <- 2
- ch <- 3
-
- cases := []struct {
- v interface{}
- l int
- }{
- {[]int{1, 2, 3}, 3},
- {[...]int{1, 2, 3}, 3},
- {"ABC", 3},
- {map[int]int{1: 2, 2: 4, 3: 6}, 3},
- {ch, 3},
-
- {[]int{}, 0},
- {map[int]int{}, 0},
- {make(chan int), 0},
-
- {[]int(nil), 0},
- {map[int]int(nil), 0},
- {(chan int)(nil), 0},
- }
-
- for _, c := range cases {
- assert.True(mockAssert.Len(c.v, c.l), "%#v have %d items", c.v, c.l)
- }
-}
-
-func TestWithinDurationWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
- a := time.Now()
- b := a.Add(10 * time.Second)
-
- assert.True(mockAssert.WithinDuration(a, b, 10*time.Second), "A 10s difference is within a 10s time difference")
- assert.True(mockAssert.WithinDuration(b, a, 10*time.Second), "A 10s difference is within a 10s time difference")
-
- assert.False(mockAssert.WithinDuration(a, b, 9*time.Second), "A 10s difference is not within a 9s time difference")
- assert.False(mockAssert.WithinDuration(b, a, 9*time.Second), "A 10s difference is not within a 9s time difference")
-
- assert.False(mockAssert.WithinDuration(a, b, -9*time.Second), "A 10s difference is not within a 9s time difference")
- assert.False(mockAssert.WithinDuration(b, a, -9*time.Second), "A 10s difference is not within a 9s time difference")
-
- assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference")
- assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference")
-}
-
-func TestInDeltaWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01")
- True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01")
- True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1")
- False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail")
- False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail")
- False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail")
-
- cases := []struct {
- a, b interface{}
- delta float64
- }{
- {uint8(2), uint8(1), 1},
- {uint16(2), uint16(1), 1},
- {uint32(2), uint32(1), 1},
- {uint64(2), uint64(1), 1},
-
- {int(2), int(1), 1},
- {int8(2), int8(1), 1},
- {int16(2), int16(1), 1},
- {int32(2), int32(1), 1},
- {int64(2), int64(1), 1},
-
- {float32(2), float32(1), 1},
- {float64(2), float64(1), 1},
- }
-
- for _, tc := range cases {
- True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta)
- }
-}
-
-func TestInEpsilonWrapper(t *testing.T) {
- assert := New(new(testing.T))
-
- cases := []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), uint16(2), .001},
- {2.1, 2.2, 0.1},
- {2.2, 2.1, 0.1},
- {-2.1, -2.2, 0.1},
- {-2.2, -2.1, 0.1},
- {uint64(100), uint8(101), 0.01},
- {0.1, -0.1, 2},
- }
-
- for _, tc := range cases {
- True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-
- cases = []struct {
- a, b interface{}
- epsilon float64
- }{
- {uint8(2), int16(-2), .001},
- {uint64(100), uint8(102), 0.01},
- {2.1, 2.2, 0.001},
- {2.2, 2.1, 0.001},
- {2.1, -2.2, 1},
- {2.1, "bla-bla", 0},
- {0.1, -0.1, 1.99},
- }
-
- for _, tc := range cases {
- False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
- }
-}
-
-func TestRegexpWrapper(t *testing.T) {
-
- assert := New(new(testing.T))
-
- cases := []struct {
- rx, str string
- }{
- {"^start", "start of the line"},
- {"end$", "in the end"},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"},
- }
-
- for _, tc := range cases {
- True(t, assert.Regexp(tc.rx, tc.str))
- True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
- False(t, assert.NotRegexp(tc.rx, tc.str))
- False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
- }
-
- cases = []struct {
- rx, str string
- }{
- {"^asdfastart", "Not the start of the line"},
- {"end$", "in the end."},
- {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"},
- }
-
- for _, tc := range cases {
- False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str)
- False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
- True(t, assert.NotRegexp(tc.rx, tc.str))
- True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
- }
-}
-
-func TestZeroWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- for _, test := range zeros {
- assert.True(mockAssert.Zero(test), "Zero should return true for %v", test)
- }
-
- for _, test := range nonZeros {
- assert.False(mockAssert.Zero(test), "Zero should return false for %v", test)
- }
-}
-
-func TestNotZeroWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- for _, test := range zeros {
- assert.False(mockAssert.NotZero(test), "Zero should return true for %v", test)
- }
-
- for _, test := range nonZeros {
- assert.True(mockAssert.NotZero(test), "Zero should return false for %v", test)
- }
-}
diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go
deleted file mode 100644
index 437a86c..0000000
--- a/vendor/github.com/stretchr/testify/assert/http_assertions.go
+++ /dev/null
@@ -1,157 +0,0 @@
-package assert
-
-import (
- "fmt"
- "net/http"
- "net/http/httptest"
- "net/url"
- "strings"
-)
-
-// httpCode is a helper that returns HTTP code of the response. It returns -1
-// if building a new request fails.
-func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
- w := httptest.NewRecorder()
- req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
- if err != nil {
- return -1
- }
- handler(w, req)
- return w.Code
-}
-
-// HTTPSuccess asserts that a specified handler returns a success status code.
-//
-// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
- return false
- }
- return code >= http.StatusOK && code <= http.StatusPartialContent
-}
-
-// HTTPRedirect asserts that a specified handler returns a redirect status code.
-//
-// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
- return false
- }
- return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
-}
-
-// HTTPError asserts that a specified handler returns an error status code.
-//
-// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
- code := httpCode(handler, method, url, values)
- if code == -1 {
- return false
- }
- return code >= http.StatusBadRequest
-}
-
-// HTTPBody is a helper that returns HTTP body of the response. It returns
-// empty string if building a new request fails.
-func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
- w := httptest.NewRecorder()
- req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
- if err != nil {
- return ""
- }
- handler(w, req)
- return w.Body.String()
-}
-
-// HTTPBodyContains asserts that a specified handler returns a
-// body that contains a string.
-//
-// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- body := HTTPBody(handler, method, url, values)
-
- contains := strings.Contains(body, fmt.Sprint(str))
- if !contains {
- Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
- }
-
- return contains
-}
-
-// HTTPBodyNotContains asserts that a specified handler returns a
-// body that does not contain a string.
-//
-// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- body := HTTPBody(handler, method, url, values)
-
- contains := strings.Contains(body, fmt.Sprint(str))
- if contains {
- Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
- }
-
- return !contains
-}
-
-//
-// Assertions Wrappers
-//
-
-// HTTPSuccess asserts that a specified handler returns a success status code.
-//
-// assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method, url string, values url.Values) bool {
- return HTTPSuccess(a.t, handler, method, url, values)
-}
-
-// HTTPRedirect asserts that a specified handler returns a redirect status code.
-//
-// assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method, url string, values url.Values) bool {
- return HTTPRedirect(a.t, handler, method, url, values)
-}
-
-// HTTPError asserts that a specified handler returns an error status code.
-//
-// assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPError(handler http.HandlerFunc, method, url string, values url.Values) bool {
- return HTTPError(a.t, handler, method, url, values)
-}
-
-// HTTPBodyContains asserts that a specified handler returns a
-// body that contains a string.
-//
-// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- return HTTPBodyContains(a.t, handler, method, url, values, str)
-}
-
-// HTTPBodyNotContains asserts that a specified handler returns a
-// body that does not contain a string.
-//
-// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
-//
-// Returns whether the assertion was successful (true) or not (false).
-func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
- return HTTPBodyNotContains(a.t, handler, method, url, values, str)
-}
diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions_test.go b/vendor/github.com/stretchr/testify/assert/http_assertions_test.go
deleted file mode 100644
index 684c2d5..0000000
--- a/vendor/github.com/stretchr/testify/assert/http_assertions_test.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package assert
-
-import (
- "fmt"
- "net/http"
- "net/url"
- "testing"
-)
-
-func httpOK(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusOK)
-}
-
-func httpRedirect(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusTemporaryRedirect)
-}
-
-func httpError(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusInternalServerError)
-}
-
-func TestHTTPStatuses(t *testing.T) {
- assert := New(t)
- mockT := new(testing.T)
-
- assert.Equal(HTTPSuccess(mockT, httpOK, "GET", "/", nil), true)
- assert.Equal(HTTPSuccess(mockT, httpRedirect, "GET", "/", nil), false)
- assert.Equal(HTTPSuccess(mockT, httpError, "GET", "/", nil), false)
-
- assert.Equal(HTTPRedirect(mockT, httpOK, "GET", "/", nil), false)
- assert.Equal(HTTPRedirect(mockT, httpRedirect, "GET", "/", nil), true)
- assert.Equal(HTTPRedirect(mockT, httpError, "GET", "/", nil), false)
-
- assert.Equal(HTTPError(mockT, httpOK, "GET", "/", nil), false)
- assert.Equal(HTTPError(mockT, httpRedirect, "GET", "/", nil), false)
- assert.Equal(HTTPError(mockT, httpError, "GET", "/", nil), true)
-}
-
-func TestHTTPStatusesWrapper(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true)
- assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false)
-
- assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true)
- assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false)
-
- assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false)
- assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true)
-}
-
-func httpHelloName(w http.ResponseWriter, r *http.Request) {
- name := r.FormValue("name")
- w.Write([]byte(fmt.Sprintf("Hello, %s!", name)))
-}
-
-func TestHttpBody(t *testing.T) {
- assert := New(t)
- mockT := new(testing.T)
-
- assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-
- assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-}
-
-func TestHttpBodyWrappers(t *testing.T) {
- assert := New(t)
- mockAssert := New(new(testing.T))
-
- assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-
- assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
- assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
- assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
-
-}
diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE
deleted file mode 100644
index 6a66aea..0000000
--- a/vendor/golang.org/x/net/LICENSE
+++ /dev/null
@@ -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.
diff --git a/vendor/golang.org/x/net/PATENTS b/vendor/golang.org/x/net/PATENTS
deleted file mode 100644
index 7330990..0000000
--- a/vendor/golang.org/x/net/PATENTS
+++ /dev/null
@@ -1,22 +0,0 @@
-Additional IP Rights Grant (Patents)
-
-"This implementation" means the copyrightable works distributed by
-Google as part of the Go project.
-
-Google hereby grants to You a perpetual, worldwide, non-exclusive,
-no-charge, royalty-free, irrevocable (except as stated in this section)
-patent license to make, have made, use, offer to sell, sell, import,
-transfer and otherwise run, modify and propagate the contents of this
-implementation of Go, where such license applies only to those patent
-claims, both currently owned or controlled by Google and acquired in
-the future, licensable by Google that are necessarily infringed by this
-implementation of Go. This grant does not include claims that would be
-infringed only as a consequence of further modification of this
-implementation. If you or your agent or exclusive licensee institute or
-order or agree to the institution of patent litigation against any
-entity (including a cross-claim or counterclaim in a lawsuit) alleging
-that this implementation of Go or any code incorporated within this
-implementation of Go constitutes direct or contributory patent
-infringement, or inducement of patent infringement, then any patent
-rights granted to you under this License for this implementation of Go
-shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go
deleted file mode 100644
index 134654c..0000000
--- a/vendor/golang.org/x/net/context/context.go
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2014 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 context defines the Context type, which carries deadlines,
-// cancelation signals, and other request-scoped values across API boundaries
-// and between processes.
-//
-// Incoming requests to a server should create a Context, and outgoing calls to
-// servers should accept a Context. The chain of function calls between must
-// propagate the Context, optionally replacing it with a modified copy created
-// using WithDeadline, WithTimeout, WithCancel, or WithValue.
-//
-// Programs that use Contexts should follow these rules to keep interfaces
-// consistent across packages and enable static analysis tools to check context
-// propagation:
-//
-// Do not store Contexts inside a struct type; instead, pass a Context
-// explicitly to each function that needs it. The Context should be the first
-// parameter, typically named ctx:
-//
-// func DoSomething(ctx context.Context, arg Arg) error {
-// // ... use ctx ...
-// }
-//
-// Do not pass a nil Context, even if a function permits it. Pass context.TODO
-// if you are unsure about which Context to use.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-//
-// The same Context may be passed to functions running in different goroutines;
-// Contexts are safe for simultaneous use by multiple goroutines.
-//
-// See http://blog.golang.org/context for example code for a server that uses
-// Contexts.
-package context // import "golang.org/x/net/context"
-
-import "time"
-
-// A Context carries a deadline, a cancelation signal, and other values across
-// API boundaries.
-//
-// Context's methods may be called by multiple goroutines simultaneously.
-type Context interface {
- // Deadline returns the time when work done on behalf of this context
- // should be canceled. Deadline returns ok==false when no deadline is
- // set. Successive calls to Deadline return the same results.
- Deadline() (deadline time.Time, ok bool)
-
- // Done returns a channel that's closed when work done on behalf of this
- // context should be canceled. Done may return nil if this context can
- // never be canceled. Successive calls to Done return the same value.
- //
- // WithCancel arranges for Done to be closed when cancel is called;
- // WithDeadline arranges for Done to be closed when the deadline
- // expires; WithTimeout arranges for Done to be closed when the timeout
- // elapses.
- //
- // Done is provided for use in select statements:
- //
- // // Stream generates values with DoSomething and sends them to out
- // // until DoSomething returns an error or ctx.Done is closed.
- // func Stream(ctx context.Context, out chan<- Value) error {
- // for {
- // v, err := DoSomething(ctx)
- // if err != nil {
- // return err
- // }
- // select {
- // case <-ctx.Done():
- // return ctx.Err()
- // case out <- v:
- // }
- // }
- // }
- //
- // See http://blog.golang.org/pipelines for more examples of how to use
- // a Done channel for cancelation.
- Done() <-chan struct{}
-
- // Err returns a non-nil error value after Done is closed. Err returns
- // Canceled if the context was canceled or DeadlineExceeded if the
- // context's deadline passed. No other values for Err are defined.
- // After Done is closed, successive calls to Err return the same value.
- Err() error
-
- // Value returns the value associated with this context for key, or nil
- // if no value is associated with key. Successive calls to Value with
- // the same key returns the same result.
- //
- // Use context values only for request-scoped data that transits
- // processes and API boundaries, not for passing optional parameters to
- // functions.
- //
- // A key identifies a specific value in a Context. Functions that wish
- // to store values in Context typically allocate a key in a global
- // variable then use that key as the argument to context.WithValue and
- // Context.Value. A key can be any type that supports equality;
- // packages should define keys as an unexported type to avoid
- // collisions.
- //
- // Packages that define a Context key should provide type-safe accessors
- // for the values stores using that key:
- //
- // // Package user defines a User type that's stored in Contexts.
- // package user
- //
- // import "golang.org/x/net/context"
- //
- // // User is the type of value stored in the Contexts.
- // type User struct {...}
- //
- // // key is an unexported type for keys defined in this package.
- // // This prevents collisions with keys defined in other packages.
- // type key int
- //
- // // userKey is the key for user.User values in Contexts. It is
- // // unexported; clients use user.NewContext and user.FromContext
- // // instead of using this key directly.
- // var userKey key = 0
- //
- // // NewContext returns a new Context that carries value u.
- // func NewContext(ctx context.Context, u *User) context.Context {
- // return context.WithValue(ctx, userKey, u)
- // }
- //
- // // FromContext returns the User value stored in ctx, if any.
- // func FromContext(ctx context.Context) (*User, bool) {
- // u, ok := ctx.Value(userKey).(*User)
- // return u, ok
- // }
- Value(key interface{}) interface{}
-}
-
-// Background returns a non-nil, empty Context. It is never canceled, has no
-// values, and has no deadline. It is typically used by the main function,
-// initialization, and tests, and as the top-level Context for incoming
-// requests.
-func Background() Context {
- return background
-}
-
-// TODO returns a non-nil, empty Context. Code should use context.TODO when
-// it's unclear which Context to use or it is not yet available (because the
-// surrounding function has not yet been extended to accept a Context
-// parameter). TODO is recognized by static analysis tools that determine
-// whether Contexts are propagated correctly in a program.
-func TODO() Context {
- return todo
-}
-
-// A CancelFunc tells an operation to abandon its work.
-// A CancelFunc does not wait for the work to stop.
-// After the first call, subsequent calls to a CancelFunc do nothing.
-type CancelFunc func()
diff --git a/vendor/golang.org/x/net/context/context_test.go b/vendor/golang.org/x/net/context/context_test.go
deleted file mode 100644
index 9554dcf..0000000
--- a/vendor/golang.org/x/net/context/context_test.go
+++ /dev/null
@@ -1,577 +0,0 @@
-// Copyright 2014 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.7
-
-package context
-
-import (
- "fmt"
- "math/rand"
- "runtime"
- "strings"
- "sync"
- "testing"
- "time"
-)
-
-// otherContext is a Context that's not one of the types defined in context.go.
-// This lets us test code paths that differ based on the underlying type of the
-// Context.
-type otherContext struct {
- Context
-}
-
-func TestBackground(t *testing.T) {
- c := Background()
- if c == nil {
- t.Fatalf("Background returned nil")
- }
- select {
- case x := <-c.Done():
- t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
- default:
- }
- if got, want := fmt.Sprint(c), "context.Background"; got != want {
- t.Errorf("Background().String() = %q want %q", got, want)
- }
-}
-
-func TestTODO(t *testing.T) {
- c := TODO()
- if c == nil {
- t.Fatalf("TODO returned nil")
- }
- select {
- case x := <-c.Done():
- t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
- default:
- }
- if got, want := fmt.Sprint(c), "context.TODO"; got != want {
- t.Errorf("TODO().String() = %q want %q", got, want)
- }
-}
-
-func TestWithCancel(t *testing.T) {
- c1, cancel := WithCancel(Background())
-
- if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want {
- t.Errorf("c1.String() = %q want %q", got, want)
- }
-
- o := otherContext{c1}
- c2, _ := WithCancel(o)
- contexts := []Context{c1, o, c2}
-
- for i, c := range contexts {
- if d := c.Done(); d == nil {
- t.Errorf("c[%d].Done() == %v want non-nil", i, d)
- }
- if e := c.Err(); e != nil {
- t.Errorf("c[%d].Err() == %v want nil", i, e)
- }
-
- select {
- case x := <-c.Done():
- t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
- default:
- }
- }
-
- cancel()
- time.Sleep(100 * time.Millisecond) // let cancelation propagate
-
- for i, c := range contexts {
- select {
- case <-c.Done():
- default:
- t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i)
- }
- if e := c.Err(); e != Canceled {
- t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled)
- }
- }
-}
-
-func TestParentFinishesChild(t *testing.T) {
- // Context tree:
- // parent -> cancelChild
- // parent -> valueChild -> timerChild
- parent, cancel := WithCancel(Background())
- cancelChild, stop := WithCancel(parent)
- defer stop()
- valueChild := WithValue(parent, "key", "value")
- timerChild, stop := WithTimeout(valueChild, 10000*time.Hour)
- defer stop()
-
- select {
- case x := <-parent.Done():
- t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
- case x := <-cancelChild.Done():
- t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x)
- case x := <-timerChild.Done():
- t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x)
- case x := <-valueChild.Done():
- t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x)
- default:
- }
-
- // The parent's children should contain the two cancelable children.
- pc := parent.(*cancelCtx)
- cc := cancelChild.(*cancelCtx)
- tc := timerChild.(*timerCtx)
- pc.mu.Lock()
- if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] {
- t.Errorf("bad linkage: pc.children = %v, want %v and %v",
- pc.children, cc, tc)
- }
- pc.mu.Unlock()
-
- if p, ok := parentCancelCtx(cc.Context); !ok || p != pc {
- t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc)
- }
- if p, ok := parentCancelCtx(tc.Context); !ok || p != pc {
- t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc)
- }
-
- cancel()
-
- pc.mu.Lock()
- if len(pc.children) != 0 {
- t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children)
- }
- pc.mu.Unlock()
-
- // parent and children should all be finished.
- check := func(ctx Context, name string) {
- select {
- case <-ctx.Done():
- default:
- t.Errorf("<-%s.Done() blocked, but shouldn't have", name)
- }
- if e := ctx.Err(); e != Canceled {
- t.Errorf("%s.Err() == %v want %v", name, e, Canceled)
- }
- }
- check(parent, "parent")
- check(cancelChild, "cancelChild")
- check(valueChild, "valueChild")
- check(timerChild, "timerChild")
-
- // WithCancel should return a canceled context on a canceled parent.
- precanceledChild := WithValue(parent, "key", "value")
- select {
- case <-precanceledChild.Done():
- default:
- t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
- }
- if e := precanceledChild.Err(); e != Canceled {
- t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled)
- }
-}
-
-func TestChildFinishesFirst(t *testing.T) {
- cancelable, stop := WithCancel(Background())
- defer stop()
- for _, parent := range []Context{Background(), cancelable} {
- child, cancel := WithCancel(parent)
-
- select {
- case x := <-parent.Done():
- t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
- case x := <-child.Done():
- t.Errorf("<-child.Done() == %v want nothing (it should block)", x)
- default:
- }
-
- cc := child.(*cancelCtx)
- pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background()
- if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) {
- t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok)
- }
-
- if pcok {
- pc.mu.Lock()
- if len(pc.children) != 1 || !pc.children[cc] {
- t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
- }
- pc.mu.Unlock()
- }
-
- cancel()
-
- if pcok {
- pc.mu.Lock()
- if len(pc.children) != 0 {
- t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children)
- }
- pc.mu.Unlock()
- }
-
- // child should be finished.
- select {
- case <-child.Done():
- default:
- t.Errorf("<-child.Done() blocked, but shouldn't have")
- }
- if e := child.Err(); e != Canceled {
- t.Errorf("child.Err() == %v want %v", e, Canceled)
- }
-
- // parent should not be finished.
- select {
- case x := <-parent.Done():
- t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
- default:
- }
- if e := parent.Err(); e != nil {
- t.Errorf("parent.Err() == %v want nil", e)
- }
- }
-}
-
-func testDeadline(c Context, wait time.Duration, t *testing.T) {
- select {
- case <-time.After(wait):
- t.Fatalf("context should have timed out")
- case <-c.Done():
- }
- if e := c.Err(); e != DeadlineExceeded {
- t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded)
- }
-}
-
-func TestDeadline(t *testing.T) {
- c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
- if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
- t.Errorf("c.String() = %q want prefix %q", got, prefix)
- }
- testDeadline(c, 200*time.Millisecond, t)
-
- c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
- o := otherContext{c}
- testDeadline(o, 200*time.Millisecond, t)
-
- c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
- o = otherContext{c}
- c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
- testDeadline(c, 200*time.Millisecond, t)
-}
-
-func TestTimeout(t *testing.T) {
- c, _ := WithTimeout(Background(), 100*time.Millisecond)
- if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
- t.Errorf("c.String() = %q want prefix %q", got, prefix)
- }
- testDeadline(c, 200*time.Millisecond, t)
-
- c, _ = WithTimeout(Background(), 100*time.Millisecond)
- o := otherContext{c}
- testDeadline(o, 200*time.Millisecond, t)
-
- c, _ = WithTimeout(Background(), 100*time.Millisecond)
- o = otherContext{c}
- c, _ = WithTimeout(o, 300*time.Millisecond)
- testDeadline(c, 200*time.Millisecond, t)
-}
-
-func TestCanceledTimeout(t *testing.T) {
- c, _ := WithTimeout(Background(), 200*time.Millisecond)
- o := otherContext{c}
- c, cancel := WithTimeout(o, 400*time.Millisecond)
- cancel()
- time.Sleep(100 * time.Millisecond) // let cancelation propagate
- select {
- case <-c.Done():
- default:
- t.Errorf("<-c.Done() blocked, but shouldn't have")
- }
- if e := c.Err(); e != Canceled {
- t.Errorf("c.Err() == %v want %v", e, Canceled)
- }
-}
-
-type key1 int
-type key2 int
-
-var k1 = key1(1)
-var k2 = key2(1) // same int as k1, different type
-var k3 = key2(3) // same type as k2, different int
-
-func TestValues(t *testing.T) {
- check := func(c Context, nm, v1, v2, v3 string) {
- if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
- t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
- }
- if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
- t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
- }
- if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
- t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
- }
- }
-
- c0 := Background()
- check(c0, "c0", "", "", "")
-
- c1 := WithValue(Background(), k1, "c1k1")
- check(c1, "c1", "c1k1", "", "")
-
- if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want {
- t.Errorf("c.String() = %q want %q", got, want)
- }
-
- c2 := WithValue(c1, k2, "c2k2")
- check(c2, "c2", "c1k1", "c2k2", "")
-
- c3 := WithValue(c2, k3, "c3k3")
- check(c3, "c2", "c1k1", "c2k2", "c3k3")
-
- c4 := WithValue(c3, k1, nil)
- check(c4, "c4", "", "c2k2", "c3k3")
-
- o0 := otherContext{Background()}
- check(o0, "o0", "", "", "")
-
- o1 := otherContext{WithValue(Background(), k1, "c1k1")}
- check(o1, "o1", "c1k1", "", "")
-
- o2 := WithValue(o1, k2, "o2k2")
- check(o2, "o2", "c1k1", "o2k2", "")
-
- o3 := otherContext{c4}
- check(o3, "o3", "", "c2k2", "c3k3")
-
- o4 := WithValue(o3, k3, nil)
- check(o4, "o4", "", "c2k2", "")
-}
-
-func TestAllocs(t *testing.T) {
- bg := Background()
- for _, test := range []struct {
- desc string
- f func()
- limit float64
- gccgoLimit float64
- }{
- {
- desc: "Background()",
- f: func() { Background() },
- limit: 0,
- gccgoLimit: 0,
- },
- {
- desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
- f: func() {
- c := WithValue(bg, k1, nil)
- c.Value(k1)
- },
- limit: 3,
- gccgoLimit: 3,
- },
- {
- desc: "WithTimeout(bg, 15*time.Millisecond)",
- f: func() {
- c, _ := WithTimeout(bg, 15*time.Millisecond)
- <-c.Done()
- },
- limit: 8,
- gccgoLimit: 16,
- },
- {
- desc: "WithCancel(bg)",
- f: func() {
- c, cancel := WithCancel(bg)
- cancel()
- <-c.Done()
- },
- limit: 5,
- gccgoLimit: 8,
- },
- {
- desc: "WithTimeout(bg, 100*time.Millisecond)",
- f: func() {
- c, cancel := WithTimeout(bg, 100*time.Millisecond)
- cancel()
- <-c.Done()
- },
- limit: 8,
- gccgoLimit: 25,
- },
- } {
- limit := test.limit
- if runtime.Compiler == "gccgo" {
- // gccgo does not yet do escape analysis.
- // TODO(iant): Remove this when gccgo does do escape analysis.
- limit = test.gccgoLimit
- }
- if n := testing.AllocsPerRun(100, test.f); n > limit {
- t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
- }
- }
-}
-
-func TestSimultaneousCancels(t *testing.T) {
- root, cancel := WithCancel(Background())
- m := map[Context]CancelFunc{root: cancel}
- q := []Context{root}
- // Create a tree of contexts.
- for len(q) != 0 && len(m) < 100 {
- parent := q[0]
- q = q[1:]
- for i := 0; i < 4; i++ {
- ctx, cancel := WithCancel(parent)
- m[ctx] = cancel
- q = append(q, ctx)
- }
- }
- // Start all the cancels in a random order.
- var wg sync.WaitGroup
- wg.Add(len(m))
- for _, cancel := range m {
- go func(cancel CancelFunc) {
- cancel()
- wg.Done()
- }(cancel)
- }
- // Wait on all the contexts in a random order.
- for ctx := range m {
- select {
- case <-ctx.Done():
- case <-time.After(1 * time.Second):
- buf := make([]byte, 10<<10)
- n := runtime.Stack(buf, true)
- t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n])
- }
- }
- // Wait for all the cancel functions to return.
- done := make(chan struct{})
- go func() {
- wg.Wait()
- close(done)
- }()
- select {
- case <-done:
- case <-time.After(1 * time.Second):
- buf := make([]byte, 10<<10)
- n := runtime.Stack(buf, true)
- t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n])
- }
-}
-
-func TestInterlockedCancels(t *testing.T) {
- parent, cancelParent := WithCancel(Background())
- child, cancelChild := WithCancel(parent)
- go func() {
- parent.Done()
- cancelChild()
- }()
- cancelParent()
- select {
- case <-child.Done():
- case <-time.After(1 * time.Second):
- buf := make([]byte, 10<<10)
- n := runtime.Stack(buf, true)
- t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n])
- }
-}
-
-func TestLayersCancel(t *testing.T) {
- testLayers(t, time.Now().UnixNano(), false)
-}
-
-func TestLayersTimeout(t *testing.T) {
- testLayers(t, time.Now().UnixNano(), true)
-}
-
-func testLayers(t *testing.T, seed int64, testTimeout bool) {
- rand.Seed(seed)
- errorf := func(format string, a ...interface{}) {
- t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...)
- }
- const (
- timeout = 200 * time.Millisecond
- minLayers = 30
- )
- type value int
- var (
- vals []*value
- cancels []CancelFunc
- numTimers int
- ctx = Background()
- )
- for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ {
- switch rand.Intn(3) {
- case 0:
- v := new(value)
- ctx = WithValue(ctx, v, v)
- vals = append(vals, v)
- case 1:
- var cancel CancelFunc
- ctx, cancel = WithCancel(ctx)
- cancels = append(cancels, cancel)
- case 2:
- var cancel CancelFunc
- ctx, cancel = WithTimeout(ctx, timeout)
- cancels = append(cancels, cancel)
- numTimers++
- }
- }
- checkValues := func(when string) {
- for _, key := range vals {
- if val := ctx.Value(key).(*value); key != val {
- errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key)
- }
- }
- }
- select {
- case <-ctx.Done():
- errorf("ctx should not be canceled yet")
- default:
- }
- if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) {
- t.Errorf("ctx.String() = %q want prefix %q", s, prefix)
- }
- t.Log(ctx)
- checkValues("before cancel")
- if testTimeout {
- select {
- case <-ctx.Done():
- case <-time.After(timeout + 100*time.Millisecond):
- errorf("ctx should have timed out")
- }
- checkValues("after timeout")
- } else {
- cancel := cancels[rand.Intn(len(cancels))]
- cancel()
- select {
- case <-ctx.Done():
- default:
- errorf("ctx should be canceled")
- }
- checkValues("after cancel")
- }
-}
-
-func TestCancelRemoves(t *testing.T) {
- checkChildren := func(when string, ctx Context, want int) {
- if got := len(ctx.(*cancelCtx).children); got != want {
- t.Errorf("%s: context has %d children, want %d", when, got, want)
- }
- }
-
- ctx, _ := WithCancel(Background())
- checkChildren("after creation", ctx, 0)
- _, cancel := WithCancel(ctx)
- checkChildren("with WithCancel child ", ctx, 1)
- cancel()
- checkChildren("after cancelling WithCancel child", ctx, 0)
-
- ctx, _ = WithCancel(Background())
- checkChildren("after creation", ctx, 0)
- _, cancel = WithTimeout(ctx, 60*time.Minute)
- checkChildren("with WithTimeout child ", ctx, 1)
- cancel()
- checkChildren("after cancelling WithTimeout child", ctx, 0)
-}
diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go
deleted file mode 100644
index f8cda19..0000000
--- a/vendor/golang.org/x/net/context/go17.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2016 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.7
-
-package context
-
-import (
- "context" // standard library's context, as of Go 1.7
- "time"
-)
-
-var (
- todo = context.TODO()
- background = context.Background()
-)
-
-// Canceled is the error returned by Context.Err when the context is canceled.
-var Canceled = context.Canceled
-
-// DeadlineExceeded is the error returned by Context.Err when the context's
-// deadline passes.
-var DeadlineExceeded = context.DeadlineExceeded
-
-// WithCancel returns a copy of parent with a new Done channel. The returned
-// context's Done channel is closed when the returned cancel function is called
-// or when the parent context's Done channel is closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
- ctx, f := context.WithCancel(parent)
- return ctx, CancelFunc(f)
-}
-
-// WithDeadline returns a copy of the parent context with the deadline adjusted
-// to be no later than d. If the parent's deadline is already earlier than d,
-// WithDeadline(parent, d) is semantically equivalent to parent. The returned
-// context's Done channel is closed when the deadline expires, when the returned
-// cancel function is called, or when the parent context's Done channel is
-// closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
- ctx, f := context.WithDeadline(parent, deadline)
- return ctx, CancelFunc(f)
-}
-
-// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete:
-//
-// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
-// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
-// defer cancel() // releases resources if slowOperation completes before timeout elapses
-// return slowOperation(ctx)
-// }
-func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
- return WithDeadline(parent, time.Now().Add(timeout))
-}
-
-// WithValue returns a copy of parent in which the value associated with key is
-// val.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-func WithValue(parent Context, key interface{}, val interface{}) Context {
- return context.WithValue(parent, key, val)
-}
diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go
deleted file mode 100644
index 5a30aca..0000000
--- a/vendor/golang.org/x/net/context/pre_go17.go
+++ /dev/null
@@ -1,300 +0,0 @@
-// Copyright 2014 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.7
-
-package context
-
-import (
- "errors"
- "fmt"
- "sync"
- "time"
-)
-
-// An emptyCtx is never canceled, has no values, and has no deadline. It is not
-// struct{}, since vars of this type must have distinct addresses.
-type emptyCtx int
-
-func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
- return
-}
-
-func (*emptyCtx) Done() <-chan struct{} {
- return nil
-}
-
-func (*emptyCtx) Err() error {
- return nil
-}
-
-func (*emptyCtx) Value(key interface{}) interface{} {
- return nil
-}
-
-func (e *emptyCtx) String() string {
- switch e {
- case background:
- return "context.Background"
- case todo:
- return "context.TODO"
- }
- return "unknown empty Context"
-}
-
-var (
- background = new(emptyCtx)
- todo = new(emptyCtx)
-)
-
-// Canceled is the error returned by Context.Err when the context is canceled.
-var Canceled = errors.New("context canceled")
-
-// DeadlineExceeded is the error returned by Context.Err when the context's
-// deadline passes.
-var DeadlineExceeded = errors.New("context deadline exceeded")
-
-// WithCancel returns a copy of parent with a new Done channel. The returned
-// context's Done channel is closed when the returned cancel function is called
-// or when the parent context's Done channel is closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
- c := newCancelCtx(parent)
- propagateCancel(parent, c)
- return c, func() { c.cancel(true, Canceled) }
-}
-
-// newCancelCtx returns an initialized cancelCtx.
-func newCancelCtx(parent Context) *cancelCtx {
- return &cancelCtx{
- Context: parent,
- done: make(chan struct{}),
- }
-}
-
-// propagateCancel arranges for child to be canceled when parent is.
-func propagateCancel(parent Context, child canceler) {
- if parent.Done() == nil {
- return // parent is never canceled
- }
- if p, ok := parentCancelCtx(parent); ok {
- p.mu.Lock()
- if p.err != nil {
- // parent has already been canceled
- child.cancel(false, p.err)
- } else {
- if p.children == nil {
- p.children = make(map[canceler]bool)
- }
- p.children[child] = true
- }
- p.mu.Unlock()
- } else {
- go func() {
- select {
- case <-parent.Done():
- child.cancel(false, parent.Err())
- case <-child.Done():
- }
- }()
- }
-}
-
-// parentCancelCtx follows a chain of parent references until it finds a
-// *cancelCtx. This function understands how each of the concrete types in this
-// package represents its parent.
-func parentCancelCtx(parent Context) (*cancelCtx, bool) {
- for {
- switch c := parent.(type) {
- case *cancelCtx:
- return c, true
- case *timerCtx:
- return c.cancelCtx, true
- case *valueCtx:
- parent = c.Context
- default:
- return nil, false
- }
- }
-}
-
-// removeChild removes a context from its parent.
-func removeChild(parent Context, child canceler) {
- p, ok := parentCancelCtx(parent)
- if !ok {
- return
- }
- p.mu.Lock()
- if p.children != nil {
- delete(p.children, child)
- }
- p.mu.Unlock()
-}
-
-// A canceler is a context type that can be canceled directly. The
-// implementations are *cancelCtx and *timerCtx.
-type canceler interface {
- cancel(removeFromParent bool, err error)
- Done() <-chan struct{}
-}
-
-// A cancelCtx can be canceled. When canceled, it also cancels any children
-// that implement canceler.
-type cancelCtx struct {
- Context
-
- done chan struct{} // closed by the first cancel call.
-
- mu sync.Mutex
- children map[canceler]bool // set to nil by the first cancel call
- err error // set to non-nil by the first cancel call
-}
-
-func (c *cancelCtx) Done() <-chan struct{} {
- return c.done
-}
-
-func (c *cancelCtx) Err() error {
- c.mu.Lock()
- defer c.mu.Unlock()
- return c.err
-}
-
-func (c *cancelCtx) String() string {
- return fmt.Sprintf("%v.WithCancel", c.Context)
-}
-
-// cancel closes c.done, cancels each of c's children, and, if
-// removeFromParent is true, removes c from its parent's children.
-func (c *cancelCtx) cancel(removeFromParent bool, err error) {
- if err == nil {
- panic("context: internal error: missing cancel error")
- }
- c.mu.Lock()
- if c.err != nil {
- c.mu.Unlock()
- return // already canceled
- }
- c.err = err
- close(c.done)
- for child := range c.children {
- // NOTE: acquiring the child's lock while holding parent's lock.
- child.cancel(false, err)
- }
- c.children = nil
- c.mu.Unlock()
-
- if removeFromParent {
- removeChild(c.Context, c)
- }
-}
-
-// WithDeadline returns a copy of the parent context with the deadline adjusted
-// to be no later than d. If the parent's deadline is already earlier than d,
-// WithDeadline(parent, d) is semantically equivalent to parent. The returned
-// context's Done channel is closed when the deadline expires, when the returned
-// cancel function is called, or when the parent context's Done channel is
-// closed, whichever happens first.
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete.
-func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
- if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
- // The current deadline is already sooner than the new one.
- return WithCancel(parent)
- }
- c := &timerCtx{
- cancelCtx: newCancelCtx(parent),
- deadline: deadline,
- }
- propagateCancel(parent, c)
- d := deadline.Sub(time.Now())
- if d <= 0 {
- c.cancel(true, DeadlineExceeded) // deadline has already passed
- return c, func() { c.cancel(true, Canceled) }
- }
- c.mu.Lock()
- defer c.mu.Unlock()
- if c.err == nil {
- c.timer = time.AfterFunc(d, func() {
- c.cancel(true, DeadlineExceeded)
- })
- }
- return c, func() { c.cancel(true, Canceled) }
-}
-
-// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
-// implement Done and Err. It implements cancel by stopping its timer then
-// delegating to cancelCtx.cancel.
-type timerCtx struct {
- *cancelCtx
- timer *time.Timer // Under cancelCtx.mu.
-
- deadline time.Time
-}
-
-func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
- return c.deadline, true
-}
-
-func (c *timerCtx) String() string {
- return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
-}
-
-func (c *timerCtx) cancel(removeFromParent bool, err error) {
- c.cancelCtx.cancel(false, err)
- if removeFromParent {
- // Remove this timerCtx from its parent cancelCtx's children.
- removeChild(c.cancelCtx.Context, c)
- }
- c.mu.Lock()
- if c.timer != nil {
- c.timer.Stop()
- c.timer = nil
- }
- c.mu.Unlock()
-}
-
-// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
-//
-// Canceling this context releases resources associated with it, so code should
-// call cancel as soon as the operations running in this Context complete:
-//
-// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
-// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
-// defer cancel() // releases resources if slowOperation completes before timeout elapses
-// return slowOperation(ctx)
-// }
-func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
- return WithDeadline(parent, time.Now().Add(timeout))
-}
-
-// WithValue returns a copy of parent in which the value associated with key is
-// val.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-func WithValue(parent Context, key interface{}, val interface{}) Context {
- return &valueCtx{parent, key, val}
-}
-
-// A valueCtx carries a key-value pair. It implements Value for that key and
-// delegates all other calls to the embedded Context.
-type valueCtx struct {
- Context
- key, val interface{}
-}
-
-func (c *valueCtx) String() string {
- return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
-}
-
-func (c *valueCtx) Value(key interface{}) interface{} {
- if c.key == key {
- return c.val
- }
- return c.Context.Value(key)
-}
diff --git a/vendor/golang.org/x/net/context/withtimeout_test.go b/vendor/golang.org/x/net/context/withtimeout_test.go
deleted file mode 100644
index a6754dc..0000000
--- a/vendor/golang.org/x/net/context/withtimeout_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 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 context_test
-
-import (
- "fmt"
- "time"
-
- "golang.org/x/net/context"
-)
-
-func ExampleWithTimeout() {
- // Pass a context with a timeout to tell a blocking function that it
- // should abandon its work after the timeout elapses.
- ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond)
- select {
- case <-time.After(200 * time.Millisecond):
- fmt.Println("overslept")
- case <-ctx.Done():
- fmt.Println(ctx.Err()) // prints "context deadline exceeded"
- }
- // Output:
- // context deadline exceeded
-}
diff --git a/vendor/vendor.json b/vendor/vendor.json
deleted file mode 100644
index 6ab7dfd..0000000
--- a/vendor/vendor.json
+++ /dev/null
@@ -1,133 +0,0 @@
-{
- "comment": "",
- "ignore": "",
- "package": [
- {
- "checksumSHA1": "tGX5p2QIBcRcFlqf7HCMgMUO81I=",
- "path": "github.com/DataDog/datadog-go/statsd",
- "revision": "b050cd8f4d7c394545fd7d966c8e2909ce89d552",
- "revisionTime": "2015-09-30T14:07:41Z"
- },
- {
- "checksumSHA1": "Qt/LbZIDLn5Ve2bLMwxiUNjaXnA=",
- "path": "github.com/Sirupsen/logrus",
- "revision": "467d9d55c2d2c17248441a8fc661561161f40d5e",
- "revisionTime": "2015-02-03T20:19:37Z"
- },
- {
- "checksumSHA1": "r1Ysa3aMAf+5WeefEoCQ0CBxCFY=",
- "path": "github.com/docker/docker/opts",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "QtnIVz87r5s7Xaci0QUDOfW5VPI=",
- "path": "github.com/docker/docker/pkg/archive",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "AdR1jasLkqJRsCFH22tS1iOukEY=",
- "path": "github.com/docker/docker/pkg/fileutils",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "iQlaOTsq2en8kZrOt7pWWVGO+kk=",
- "path": "github.com/docker/docker/pkg/homedir",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "Kao2fJIQGfZ10aP2yGgfMK2ASSQ=",
- "path": "github.com/docker/docker/pkg/idtools",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "jMNt9rbvqc75sgRayJ6BgN4xqwo=",
- "path": "github.com/docker/docker/pkg/ioutils",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "jHb9o47h5I/oIIyT74N1KGQHdgE=",
- "path": "github.com/docker/docker/pkg/longpath",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "vi44v5ooEavXqxD+sNzf/0Aetfk=",
- "path": "github.com/docker/docker/pkg/pools",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "txf3EORYff4hO6PEvwBm2lyh1MU=",
- "path": "github.com/docker/docker/pkg/promise",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "3uz/ivef+IflkDBSB2S5Kc5Xs/I=",
- "path": "github.com/docker/docker/pkg/stdcopy",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "EM3M5Ep/qDCNIjZz01IVHbXoIdc=",
- "path": "github.com/docker/docker/pkg/system",
- "revision": "9cdb6357e2f8c7561ba580c1e16de81d24e1de99",
- "revisionTime": "2016-06-16T05:08:44Z"
- },
- {
- "checksumSHA1": "0UcvIzobM2POYfKb9Lbr5ny6p7M=",
- "path": "github.com/docker/engine-api/types/filters",
- "revision": "f90ecdb1e989f834dabbd91807e891094aa069fe",
- "revisionTime": "2016-06-17T07:31:37Z"
- },
- {
- "checksumSHA1": "cNK87hsbX/Owi42e/69IO5wrw1Y=",
- "path": "github.com/docker/engine-api/types/versions",
- "revision": "f90ecdb1e989f834dabbd91807e891094aa069fe",
- "revisionTime": "2016-06-17T07:31:37Z"
- },
- {
- "checksumSHA1": "cXZVymYfjlT4nwMymGuPCL6hw5Q=",
- "path": "github.com/docker/go-units",
- "revision": "f2d77a61e3c169b43402a0a1e84f06daf29b8190",
- "revisionTime": "2016-06-13T21:20:13Z"
- },
- {
- "checksumSHA1": "7fWXc7aENj056y/gkiegPclsKxM=",
- "path": "github.com/fsouza/go-dockerclient",
- "revision": "3c8f092cb1e9d1e18a07c1d05d993e69a6676097",
- "revisionTime": "2016-06-13T21:15:37Z"
- },
- {
- "checksumSHA1": "Uzyon2091lmwacNsl1hCytjhHtg=",
- "path": "github.com/hashicorp/go-cleanhttp",
- "revision": "ad28ea4487f05916463e2423a55166280e8254b5",
- "revisionTime": "2016-04-07T17:41:26Z"
- },
- {
- "checksumSHA1": "HgqDa4oBBOol5ziacmj/6c55Xtg=",
- "path": "github.com/opencontainers/runc/libcontainer/user",
- "revision": "cc29e3dded8e27ba8f65738f40d251c885030a28",
- "revisionTime": "2016-06-15T20:00:28Z"
- },
- {
- "checksumSHA1": "tz9NvD7STK26zJLr6GWH6NPTO5M=",
- "path": "github.com/stretchr/testify/assert",
- "revision": "f3960ab1f9664ecc4e27c78af27cc9063d745a43",
- "revisionTime": "2015-10-08T00:55:03Z"
- },
- {
- "checksumSHA1": "88lxkrVVZyBqOBOFnNMBwEexiLY=",
- "path": "golang.org/x/net/context",
- "revision": "d7bf3545bb0dacf009c535b3d3fbf53ac0a339ab",
- "revisionTime": "2016-06-13T04:23:54Z"
- }
- ],
- "rootPath": "github.com/remind101/dockerdog"
-}