diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0224b73df..a4aecac74 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,9 +53,9 @@ asking for suggestions on how to address the documentation part. ### Build -Use go 1.9.1 or newer. +Requires Go >= 1.9.1. -The first time after you fork or after dependencies get updated, run: +The first time after you clone or after dependencies get updated, run: ```sh make dep diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 000000000..f66f66234 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,604 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/Azure/go-ansiterm" + packages = [".","winterm"] + revision = "19f72df4d05d31cbe1c56bfc8045c96babff6c7e" + +[[projects]] + name = "github.com/Microsoft/go-winio" + packages = ["."] + revision = "78439966b38d69bf38227fbf57ac8a6fee70f69a" + version = "v0.4.5" + +[[projects]] + branch = "master" + name = "github.com/Nvveen/Gotty" + packages = ["."] + revision = "cd527374f1e5bff4938207604a14f2e38a9cf512" + +[[projects]] + name = "github.com/PuerkitoBio/purell" + packages = ["."] + revision = "8a290539e2e8629dbc4e6bad948158f790ec31f4" + version = "v1.0.0" + +[[projects]] + name = "github.com/PuerkitoBio/urlesc" + packages = ["."] + revision = "5bd2802263f21d8788851d5305584c82a5c75d7e" + +[[projects]] + name = "github.com/Shopify/sarama" + packages = ["."] + revision = "4704a3a8c95920361c47e9a2adec13c3d757c757" + +[[projects]] + name = "github.com/apache/thrift" + packages = ["lib/go/thrift"] + revision = "4c30c15924bfbc7c9e6bfc0e82630e97980e556e" + +[[projects]] + name = "github.com/asaskevich/govalidator" + packages = ["."] + revision = "15028e809df8c71964e8efa6c11e81d5c0262302" + +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9" + +[[projects]] + name = "github.com/boltdb/bolt" + packages = ["."] + revision = "fa5367d20c994db73282594be0146ab221657943" + +[[projects]] + name = "github.com/cloudflare/cfssl" + packages = ["api","auth","certdb","config","crypto/pkcs7","csr","errors","helpers","helpers/derhelpers","info","initca","log","ocsp/config","signer","signer/local"] + revision = "7d88da830aad9d533c2fb8532da23f6a75331b52" + +[[projects]] + name = "github.com/coreos/etcd" + packages = ["raft/raftpb"] + revision = "5bb9f9591f01d0a3c61d2eb3a3bb281726005b2b" + +[[projects]] + name = "github.com/coreos/go-semver" + packages = ["semver"] + revision = "8ab6407b697782a06568d4b7f1db25550ec2e4c6" + version = "v0.2.0" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d" + +[[projects]] + branch = "master" + name = "github.com/dchest/siphash" + packages = ["."] + revision = "4ebf1de738443ea7f45f02dc394c4df1942a126d" + +[[projects]] + name = "github.com/docker/distribution" + packages = [".","digestset","manifest","manifest/schema1","manifest/schema2","reference","registry/api/errcode","registry/api/v2","registry/client","registry/client/auth","registry/client/auth/challenge","registry/client/transport","registry/storage/cache","registry/storage/cache/memory"] + revision = "bc3c7b0525e59d3ecfab3e1568350895fd4a462f" + +[[projects]] + name = "github.com/docker/docker" + packages = ["api/types","api/types/blkiodev","api/types/container","api/types/filters","api/types/mount","api/types/network","api/types/registry","api/types/strslice","api/types/swarm","api/types/swarm/runtime","api/types/versions","daemon/cluster/convert","opts","pkg/archive","pkg/fileutils","pkg/homedir","pkg/idtools","pkg/ioutils","pkg/jsonlog","pkg/jsonmessage","pkg/longpath","pkg/mount","pkg/namesgenerator","pkg/pools","pkg/promise","pkg/stdcopy","pkg/system","pkg/term","pkg/term/windows"] + revision = "cdf870bd0b5fa678b10ef2708cca7ad776b4913c" + +[[projects]] + name = "github.com/docker/go-connections" + packages = ["nat"] + revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d" + version = "v0.3.0" + +[[projects]] + branch = "master" + name = "github.com/docker/go-events" + packages = ["."] + revision = "9461782956ad83b30282bf90e31fa6a70c255ba9" + +[[projects]] + name = "github.com/docker/go-units" + packages = ["."] + revision = "0dadbb0345b35ec7ef35e228dabb8de89a65bf52" + version = "v0.3.2" + +[[projects]] + name = "github.com/docker/libkv" + packages = [".","store"] + revision = "93ab0e6c056d325dfbb11e1d58a3b4f5f62e7f3c" + +[[projects]] + name = "github.com/docker/libnetwork" + packages = ["datastore","discoverapi","types"] + revision = "6d098467ec58038b68620a3c2c418936661efa64" + +[[projects]] + branch = "master" + name = "github.com/docker/libtrust" + packages = ["."] + revision = "aabc10ec26b754e797f9028f4589c5b7bd90dc20" + +[[projects]] + name = "github.com/docker/swarmkit" + packages = ["api","api/deepcopy","api/equality","api/genericresource","api/naming","ca","connectionbroker","identity","ioutils","log","manager/raftselector","manager/state","manager/state/store","protobuf/plugin","remotes","watch","watch/queue"] + revision = "bd7bafb8a61de1f5f23c8215ce7b9ecbcb30ff21" + +[[projects]] + branch = "master" + name = "github.com/dustin/go-humanize" + packages = ["."] + revision = "bb3d318650d48840a39aa21a027c6630e198e626" + +[[projects]] + name = "github.com/eapache/go-resiliency" + packages = ["breaker"] + revision = "b1fe83b5b03f624450823b751b662259ffc6af70" + +[[projects]] + branch = "master" + name = "github.com/eapache/go-xerial-snappy" + packages = ["."] + revision = "bb955e01b9346ac19dc29eb16586c90ded99a98c" + +[[projects]] + name = "github.com/eapache/queue" + packages = ["."] + revision = "44cc805cf13205b55f69e14bcb69867d1ae92f98" + version = "v1.1.0" + +[[projects]] + name = "github.com/emicklei/go-restful" + packages = [".","log"] + revision = "ff4f55a206334ef123e4f79bbf348980da81ca46" + +[[projects]] + name = "github.com/emicklei/go-restful-swagger12" + packages = ["."] + revision = "dcef7f55730566d41eae5db10e7d6981829720f6" + version = "1.0.1" + +[[projects]] + branch = "master" + name = "github.com/fnproject/fdk-go" + packages = ["."] + revision = "7c1e1a329cf1004edf545318280d672f35e15081" + +[[projects]] + name = "github.com/fnproject/fn_go" + packages = ["client","client/apps","client/call","client/operations","client/routes","models"] + revision = "7ce3bb2e624df60cdfbfc1ee5483f6df80bb2b1b" + version = "0.2.1" + +[[projects]] + name = "github.com/fsouza/go-dockerclient" + packages = ["."] + revision = "98edf3edfae6a6500fecc69d2bcccf1302544004" + +[[projects]] + name = "github.com/garyburd/redigo" + packages = ["internal","redis"] + revision = "70e1b1943d4fc9c56791abaa6f4d1e727b9ab925" + +[[projects]] + name = "github.com/ghodss/yaml" + packages = ["."] + revision = "73d445a93680fa1a78ae23a5839bad48f32ba1ee" + +[[projects]] + name = "github.com/gin-contrib/cors" + packages = ["."] + revision = "cf4846e6a636a76237a28d9286f163c132e841bc" + version = "v1.2" + +[[projects]] + branch = "master" + name = "github.com/gin-contrib/sse" + packages = ["."] + revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae" + +[[projects]] + name = "github.com/gin-gonic/gin" + packages = [".","binding","json","render"] + revision = "5afc5b19730118c9b8324fe9dd995d44ec65c81a" + +[[projects]] + name = "github.com/go-ini/ini" + packages = ["."] + revision = "c787282c39ac1fc618827141a1f762240def08a3" + +[[projects]] + name = "github.com/go-logfmt/logfmt" + packages = ["."] + revision = "390ab7935ee28ec6b286364bba9b4dd6410cb3d5" + version = "v0.3.0" + +[[projects]] + name = "github.com/go-openapi/analysis" + packages = ["."] + revision = "8ed83f2ea9f00f945516462951a288eaa68bf0d6" + +[[projects]] + name = "github.com/go-openapi/errors" + packages = ["."] + revision = "03cfca65330da08a5a440053faf994a3c682b5bf" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/jsonpointer" + packages = ["."] + revision = "779f45308c19820f1a69e9a4cd965f496e0da10f" + +[[projects]] + name = "github.com/go-openapi/jsonreference" + packages = ["."] + revision = "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" + +[[projects]] + name = "github.com/go-openapi/loads" + packages = ["."] + revision = "a80dea3052f00e5f032e860dd7355cd0cc67e24d" + +[[projects]] + name = "github.com/go-openapi/runtime" + packages = [".","client"] + revision = "d6605b7c17ac3b1033ca794886e6142a4141f5b0" + +[[projects]] + name = "github.com/go-openapi/spec" + packages = ["."] + revision = "3faa0055dbbf2110abc1f3b4e3adbb22721e96e7" + +[[projects]] + branch = "master" + name = "github.com/go-openapi/strfmt" + packages = ["."] + revision = "4dd3d302e100bae008baedc42d446ce83bdd10ad" + +[[projects]] + name = "github.com/go-openapi/swag" + packages = ["."] + revision = "f3f9494671f93fcff853e3c6e9e948b3eb71e590" + +[[projects]] + name = "github.com/go-openapi/validate" + packages = ["."] + revision = "8a82927c942c94794a5cd8b8b50ce2f48a955c0c" + +[[projects]] + name = "github.com/go-sql-driver/mysql" + packages = ["."] + revision = "21d7e97c9f760ca685a01ecea202e1c84276daa1" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = ["gogoproto","proto","protoc-gen-gogo/descriptor","sortkeys","types"] + revision = "c0656edd0d9eab7c66d1eb0c568f9039345796f7" + +[[projects]] + name = "github.com/golang/glog" + packages = ["."] + revision = "44145f04b68cf362d9c4df2182967c2275eaefed" + +[[projects]] + name = "github.com/golang/protobuf" + packages = ["proto","ptypes/any"] + revision = "4bd1920723d7b7c925de087aa32e2187708897f7" + +[[projects]] + branch = "master" + name = "github.com/golang/snappy" + packages = ["."] + revision = "553a641470496b2327abcac10b36396bd98e45c9" + +[[projects]] + branch = "master" + name = "github.com/google/btree" + packages = ["."] + revision = "316fb6d3f031ae8f4d457c6c5186b9e3ded70435" + +[[projects]] + name = "github.com/google/certificate-transparency-go" + packages = [".","asn1","client","jsonclient","tls","x509","x509/pkix"] + revision = "0dac42a6ed448ba220ee315abfaa6d26fd5fc9bb" + +[[projects]] + name = "github.com/google/gofuzz" + packages = ["."] + revision = "44d81051d367757e1c7c6a5a86423ece9afcf63c" + +[[projects]] + branch = "master" + name = "github.com/gorilla/context" + packages = ["."] + revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42" + +[[projects]] + name = "github.com/gorilla/mux" + packages = ["."] + revision = "24fca303ac6da784b9e8269f724ddeb0b2eea5e7" + version = "v1.5.0" + +[[projects]] + name = "github.com/grpc-ecosystem/go-grpc-prometheus" + packages = ["."] + revision = "6b7015e65d366bf3f19b2b2a000a831940f0f7e0" + version = "v1.1" + +[[projects]] + branch = "master" + name = "github.com/hashicorp/go-immutable-radix" + packages = ["."] + revision = "8aac2701530899b64bdea735a1de8da899815220" + +[[projects]] + name = "github.com/hashicorp/go-memdb" + packages = ["."] + revision = "ec43fcf8f202880feb35d2abb40a570c1f4172e9" + +[[projects]] + name = "github.com/hashicorp/golang-lru" + packages = ["simplelru"] + revision = "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" + +[[projects]] + name = "github.com/jmoiron/sqlx" + packages = [".","reflectx"] + revision = "d9bd385d68c068f1fabb5057e3dedcbcbb039d0f" + +[[projects]] + name = "github.com/json-iterator/go" + packages = ["."] + revision = "fdfe0b9a69118ff692d6e1005e9de7e0cffb7d6b" + +[[projects]] + name = "github.com/juju/ratelimit" + packages = ["."] + revision = "5b9ff866471762aa2ab2dced63c9fb6f53921342" + +[[projects]] + branch = "master" + name = "github.com/kr/logfmt" + packages = ["."] + revision = "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" + +[[projects]] + name = "github.com/lib/pq" + packages = [".","oid"] + revision = "23da1db4f16d9658a86ae9b717c245fc078f10f1" + +[[projects]] + branch = "master" + name = "github.com/mailru/easyjson" + packages = ["buffer","jlexer","jwriter"] + revision = "32fa128f234d041f196a9f3e0fea5ac9772c08e1" + +[[projects]] + name = "github.com/mattes/migrate" + packages = [".","database","source"] + revision = "5b98c13eff7657ab49a1a5f705b72f961d7fc558" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "fc9e8d8ef48496124e79ae0df75490096eccf6fe" + version = "v0.0.2" + +[[projects]] + name = "github.com/mattn/go-sqlite3" + packages = ["."] + revision = "05548ff55570cdb9ac72ff4a25a3b5e77a6fb7e5" + +[[projects]] + branch = "master" + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" + +[[projects]] + branch = "master" + name = "github.com/minio/go-homedir" + packages = ["."] + revision = "4d76aabb80b22bad8695d3904e943f1fb5e6199f" + +[[projects]] + name = "github.com/minio/minio-go" + packages = [".","pkg/credentials","pkg/encrypt","pkg/policy","pkg/s3signer","pkg/s3utils","pkg/set"] + revision = "a62e2045a5d3a6630dbb7040260994583ac56b10" + version = "4.0.1" + +[[projects]] + name = "github.com/mitchellh/mapstructure" + packages = ["."] + revision = "d0303fe809921458f417bcf828397a65db30a7e4" + +[[projects]] + name = "github.com/opencontainers/go-digest" + packages = ["."] + revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf" + version = "v1.0.0-rc1" + +[[projects]] + name = "github.com/opencontainers/image-spec" + packages = ["specs-go","specs-go/v1"] + revision = "ebd93fd0782379ca3d821f0fa74f0651a9347a3e" + +[[projects]] + name = "github.com/opencontainers/runc" + packages = ["libcontainer/system","libcontainer/user"] + revision = "ae2948042b08ad3d6d13cd09f40a50ffff4fc688" + +[[projects]] + branch = "master" + name = "github.com/opentracing-contrib/go-observer" + packages = ["."] + revision = "a52f2342449246d5bcc273e65cbdcfa5f7d6c63c" + +[[projects]] + name = "github.com/opentracing/opentracing-go" + packages = [".","ext","log"] + revision = "8ebe5d4e236eed9fd88e593c288bfb804d630b8c" + +[[projects]] + name = "github.com/openzipkin/zipkin-go-opentracing" + packages = [".","flag","thrift/gen-go/scribe","thrift/gen-go/zipkincore","types","wire"] + revision = "9c88fa03bfdfaa5fec7cd1b40f3d10ec15c15fc6" + version = "v0.3.1" + +[[projects]] + name = "github.com/patrickmn/go-cache" + packages = ["."] + revision = "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0" + version = "v2.1.0" + +[[projects]] + branch = "master" + name = "github.com/petar/GoLLRB" + packages = ["llrb"] + revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" + +[[projects]] + name = "github.com/pierrec/lz4" + packages = ["."] + revision = "08c27939df1bd95e881e2c2367a749964ad1fceb" + version = "v1.0.1" + +[[projects]] + branch = "master" + name = "github.com/pierrec/xxHash" + packages = ["xxHash32"] + revision = "a0006b13c722f7f12368c00a3d3c2ae8a999a0c6" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "2b3a18b5f0fb6b4f9190549597d3f962c02bc5eb" + +[[projects]] + name = "github.com/prometheus/client_golang" + packages = ["prometheus","prometheus/promhttp"] + revision = "c5b7fccd204277076155f10851dad72b76a49317" + version = "v0.8.0" + +[[projects]] + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "6f3806018612930941127f2a7c6c453ba2c527d2" + +[[projects]] + name = "github.com/prometheus/common" + packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"] + revision = "2f17f4a9d485bf34b4bfaccc273805040e4f86c8" + +[[projects]] + name = "github.com/prometheus/procfs" + packages = [".","xfs"] + revision = "a1dba9ce8baed984a2495b658c82687f8157b98f" + +[[projects]] + name = "github.com/rcrowley/go-metrics" + packages = ["."] + revision = "1f30fe9094a513ce4c700b9a54458bbb0c96996c" + +[[projects]] + name = "github.com/rdallman/migrate" + packages = [".","database/mysql","database/postgres","database/sqlite3","source","source/go-bindata"] + revision = "bc72eeb997c7334cb5f05f5aefd2d70bc34d71ef" + +[[projects]] + name = "github.com/sirupsen/logrus" + packages = [".","hooks/syslog"] + revision = "89742aefa4b206dcf400792f3bd35b542998eb3b" + +[[projects]] + name = "github.com/spf13/pflag" + packages = ["."] + revision = "9ff6c6923cfffbcd502984b8e0c80539a94968b7" + +[[projects]] + name = "github.com/ugorji/go" + packages = ["codec"] + revision = "ded73eae5db7e7a0ef6f55aace87a2873c5d2b74" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["ocsp","pkcs12","pkcs12/internal/rc2","ssh/terminal"] + revision = "94eea52f7b742c7cbe0b03b22f0c4c8631ece122" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["context","context/ctxhttp","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"] + revision = "a8b9294777976932365dabb6640cf1468d95c70f" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix","windows"] + revision = "8b4580aae2a0dd0c231a45d3ccb8434ff533b840" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = ["cases","collate","collate/build","internal","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","runes","secure/bidirule","secure/precis","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable","width"] + revision = "57961680700a5336d15015c8c50686ca5ba362a4" + +[[projects]] + name = "google.golang.org/genproto" + packages = ["googleapis/rpc/status"] + revision = "09f6ed296fc66555a25fe4ce95173148778dfa85" + +[[projects]] + name = "google.golang.org/grpc" + packages = [".","codes","credentials","grpclb/grpc_lb_v1","grpclog","internal","keepalive","metadata","naming","peer","stats","status","tap","transport"] + revision = "b8669c35455183da6d5c474ea6e72fbf55183274" + version = "v1.5.1" + +[[projects]] + name = "gopkg.in/go-playground/validator.v8" + packages = ["."] + revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf" + version = "v8.18.2" + +[[projects]] + name = "gopkg.in/inf.v0" + packages = ["."] + revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" + version = "v0.9.0" + +[[projects]] + branch = "v2" + name = "gopkg.in/mgo.v2" + packages = ["bson","internal/json"] + revision = "3f83fa5005286a7fe593b055f0d7771a7dce4655" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "53feefa2559fb8dfa8d81baad31be332c97d6c77" + +[[projects]] + name = "k8s.io/apimachinery" + packages = ["pkg/api/equality","pkg/api/errors","pkg/api/meta","pkg/api/resource","pkg/apimachinery","pkg/apimachinery/announced","pkg/apimachinery/registered","pkg/apis/meta/v1","pkg/apis/meta/v1/unstructured","pkg/apis/meta/v1alpha1","pkg/conversion","pkg/conversion/queryparams","pkg/conversion/unstructured","pkg/fields","pkg/labels","pkg/openapi","pkg/runtime","pkg/runtime/schema","pkg/runtime/serializer","pkg/runtime/serializer/json","pkg/runtime/serializer/protobuf","pkg/runtime/serializer/recognizer","pkg/runtime/serializer/streaming","pkg/runtime/serializer/versioning","pkg/selection","pkg/types","pkg/util/clock","pkg/util/diff","pkg/util/errors","pkg/util/framer","pkg/util/intstr","pkg/util/json","pkg/util/net","pkg/util/rand","pkg/util/runtime","pkg/util/sets","pkg/util/validation","pkg/util/validation/field","pkg/util/wait","pkg/util/yaml","pkg/version","pkg/watch","third_party/forked/golang/reflect"] + revision = "1fd2e63a9a370677308a42f24fd40c86438afddf" + +[[projects]] + name = "k8s.io/client-go" + packages = ["discovery","kubernetes","kubernetes/scheme","kubernetes/typed/admissionregistration/v1alpha1","kubernetes/typed/apps/v1beta1","kubernetes/typed/authentication/v1","kubernetes/typed/authentication/v1beta1","kubernetes/typed/authorization/v1","kubernetes/typed/authorization/v1beta1","kubernetes/typed/autoscaling/v1","kubernetes/typed/autoscaling/v2alpha1","kubernetes/typed/batch/v1","kubernetes/typed/batch/v2alpha1","kubernetes/typed/certificates/v1beta1","kubernetes/typed/core/v1","kubernetes/typed/extensions/v1beta1","kubernetes/typed/networking/v1","kubernetes/typed/policy/v1beta1","kubernetes/typed/rbac/v1alpha1","kubernetes/typed/rbac/v1beta1","kubernetes/typed/settings/v1alpha1","kubernetes/typed/storage/v1","kubernetes/typed/storage/v1beta1","pkg/api","pkg/api/v1","pkg/api/v1/ref","pkg/apis/admissionregistration","pkg/apis/admissionregistration/v1alpha1","pkg/apis/apps","pkg/apis/apps/v1beta1","pkg/apis/authentication","pkg/apis/authentication/v1","pkg/apis/authentication/v1beta1","pkg/apis/authorization","pkg/apis/authorization/v1","pkg/apis/authorization/v1beta1","pkg/apis/autoscaling","pkg/apis/autoscaling/v1","pkg/apis/autoscaling/v2alpha1","pkg/apis/batch","pkg/apis/batch/v1","pkg/apis/batch/v2alpha1","pkg/apis/certificates","pkg/apis/certificates/v1beta1","pkg/apis/extensions","pkg/apis/extensions/v1beta1","pkg/apis/networking","pkg/apis/networking/v1","pkg/apis/policy","pkg/apis/policy/v1beta1","pkg/apis/rbac","pkg/apis/rbac/v1alpha1","pkg/apis/rbac/v1beta1","pkg/apis/settings","pkg/apis/settings/v1alpha1","pkg/apis/storage","pkg/apis/storage/v1","pkg/apis/storage/v1beta1","pkg/util","pkg/util/parsers","pkg/version","rest","rest/watch","tools/clientcmd/api","tools/metrics","transport","util/cert","util/flowcontrol","util/integer"] + revision = "d92e8497f71b7b4e0494e5bd204b48d34bd6f254" + version = "v4.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "c0ba99cc154500d7d551e61f56d172037c20d1e3e0b119c486e9aae15680b586" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 000000000..3ae357e5a --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,106 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + +ignored = ["github.com/fnproject/fn/cli"] + +[[constraint]] + name = "github.com/boltdb/bolt" + revision = "fa5367d20c994db73282594be0146ab221657943" + +[[constraint]] + name = "github.com/coreos/go-semver" + version = "^0.2.0" + +[[constraint]] + branch = "master" + name = "github.com/dchest/siphash" + +[[constraint]] + name = "github.com/fnproject/fn_go" + version = "0.2.0" + +[[constraint]] + name = "github.com/gin-contrib/cors" + version = "~1.2.0" + +[[constraint]] + branch = "master" + name = "github.com/go-openapi/strfmt" + +[[constraint]] + branch = "master" + name = "github.com/google/btree" + +[[constraint]] + name = "github.com/minio/minio-go" + version = "4.0.1" + +[[constraint]] + name = "github.com/openzipkin/zipkin-go-opentracing" + version = "0.3.1" + +[[constraint]] + name = "github.com/patrickmn/go-cache" + version = "2.1.0" + +[[constraint]] + name = "github.com/prometheus/client_golang" + version = "0.8.0" + +[[constraint]] + name = "github.com/sirupsen/logrus" + revision = "89742aefa4b206dcf400792f3bd35b542998eb3b" + +[[constraint]] + name = "github.com/docker/docker" + revision = "cdf870bd0b5fa678b10ef2708cca7ad776b4913c" + +[[constraint]] + name = "github.com/docker/cli" + revision = "139fcd3ee95f37f3ac17b1200fb0a63908cb6781" + +[[constraint]] + name = "github.com/docker/distribution" + revision = "bc3c7b0525e59d3ecfab3e1568350895fd4a462f" + +[[constraint]] + name = "github.com/rdallman/migrate" # TODO change to mattes/migrate w/ https://github.com/mattes/migrate/pull/299 + revision = "bc72eeb997c7334cb5f05f5aefd2d70bc34d71ef" + +[[constraint]] + name = "github.com/go-sql-driver/mysql" + revision = "21d7e97c9f760ca685a01ecea202e1c84276daa1" + +[[constraint]] + name = "github.com/opencontainers/go-digest" + revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf" + +[[constraint]] + name = "github.com/opencontainers/runc" + revision = "ae2948042b08ad3d6d13cd09f40a50ffff4fc688" + +[[constraint]] + name = "github.com/Azure/go-ansiterm" + revision = "19f72df4d05d31cbe1c56bfc8045c96babff6c7e" + +[[constraint]] + name = "github.com/prometheus/common" + revision = "2f17f4a9d485bf34b4bfaccc273805040e4f86c8" \ No newline at end of file diff --git a/Makefile b/Makefile index 252fc9d61..53087393d 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,10 @@ .PHONY: all test dep build test-log-datastore checkfmt pull-images api-test fn-test-utils test-middleware test-extensions test-basic test-api dep: - glide install -v + dep ensure --vendor-only dep-up: - glide up -v + dep ensure build: go build -o fnserver @@ -70,10 +70,6 @@ test-build-arm: run: build GIN_MODE=debug ./fnserver -docker-dep: -# todo: need to create a dep tool image for this (or just ditch this) - docker run --rm -it -v ${CURDIR}:/go/src/github.com/fnproject/fn -w /go/src/github.com/fnproject/fn treeder/glide install -v - docker-build: docker build --build-arg HTTPS_PROXY --build-arg HTTP_PROXY -t fnproject/fnserver:latest . diff --git a/api/agent/drivers/docker/registry.go b/api/agent/drivers/docker/registry.go index 1f170ae0d..52d3c49ae 100644 --- a/api/agent/drivers/docker/registry.go +++ b/api/agent/drivers/docker/registry.go @@ -90,7 +90,7 @@ func CheckRegistry(ctx context.Context, image string, config docker.AuthConfigur tran = &retryWrap{cm, tran} - repo, err := registry.NewRepository(ctx, repoNamed, regURL, tran) + repo, err := registry.NewRepository(repoNamed, regURL, tran) if err != nil { return nil, err } diff --git a/glide.lock b/glide.lock deleted file mode 100644 index fa81aa1c2..000000000 --- a/glide.lock +++ /dev/null @@ -1,595 +0,0 @@ -hash: 3fa5b86f68121ba1422761f2937e6a9b7f5c330adc6f84e2f3b7b78b87a747d7 -updated: 2017-12-04T17:26:34.506649Z -imports: -- name: github.com/amir/raidman - version: 1ccc43bfb9c93cb401a4025e49c64ba71e5e668b -- name: github.com/apache/thrift - version: 4c30c15924bfbc7c9e6bfc0e82630e97980e556e - subpackages: - - lib/go/thrift -- name: github.com/asaskevich/govalidator - version: 15028e809df8c71964e8efa6c11e81d5c0262302 -- name: github.com/Azure/go-ansiterm - version: 19f72df4d05d31cbe1c56bfc8045c96babff6c7e - subpackages: - - winterm -- name: github.com/beorn7/perks - version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 - subpackages: - - quantile -- name: github.com/boltdb/bolt - version: fa5367d20c994db73282594be0146ab221657943 -- name: github.com/cactus/go-statsd-client - version: ce77ca9ecdee1c3ffd097e32f9bb832825ccb203 - subpackages: - - statsd -- name: github.com/cloudflare/cfssl - version: 7d88da830aad9d533c2fb8532da23f6a75331b52 - subpackages: - - api - - auth - - certdb - - config - - crypto/pkcs7 - - csr - - errors - - helpers - - helpers/derhelpers - - info - - initca - - log - - ocsp/config - - signer - - signer/local -- name: github.com/coreos/etcd - version: 5bb9f9591f01d0a3c61d2eb3a3bb281726005b2b - subpackages: - - raft/raftpb -- name: github.com/coreos/go-semver - version: 8ab6407b697782a06568d4b7f1db25550ec2e4c6 - subpackages: - - semver -- name: github.com/davecgh/go-spew - version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d - subpackages: - - spew -- name: github.com/dchest/siphash - version: 4ebf1de738443ea7f45f02dc394c4df1942a126d -- name: github.com/dghubble/go-twitter - version: c4115fa44a928413e0b857e0eb47376ffde3a61a - subpackages: - - twitter -- name: github.com/dghubble/oauth1 - version: 7d51c10e15ca32917b32ce43f6e25840d6951db4 -- name: github.com/dgrijalva/jwt-go - version: a539ee1a749a2b895533f979515ac7e6e0f5b650 -- name: github.com/docker/cli - version: 139fcd3ee95f37f3ac17b1200fb0a63908cb6781 - subpackages: - - cli/config/configfile -- name: github.com/docker/distribution - version: 5f6282db7d65e6d72ad7c2cc66310724a57be716 - subpackages: - - digestset - - manifest - - manifest/schema1 - - manifest/schema2 - - reference - - registry/api/errcode - - registry/api/v2 - - registry/client - - registry/client/auth - - registry/client/auth/challenge - - registry/client/transport - - registry/storage/cache - - registry/storage/cache/memory -- name: github.com/docker/docker - version: cdf870bd0b5fa678b10ef2708cca7ad776b4913c - subpackages: - - api/types - - api/types/blkiodev - - api/types/container - - api/types/filters - - api/types/mount - - api/types/network - - api/types/registry - - api/types/strslice - - api/types/swarm - - api/types/swarm/runtime - - api/types/versions - - daemon/cluster/convert - - opts - - pkg/archive - - pkg/fileutils - - pkg/homedir - - pkg/idtools - - pkg/ioutils - - pkg/jsonlog - - pkg/jsonmessage - - pkg/longpath - - pkg/mount - - pkg/namesgenerator - - pkg/pools - - pkg/promise - - pkg/stdcopy - - pkg/system - - pkg/term - - pkg/term/windows -- name: github.com/docker/go-connections - version: 3ede32e2033de7505e6500d6c868c2b9ed9f169d - subpackages: - - nat -- name: github.com/docker/go-events - version: 9461782956ad83b30282bf90e31fa6a70c255ba9 -- name: github.com/docker/go-units - version: 0dadbb0345b35ec7ef35e228dabb8de89a65bf52 -- name: github.com/docker/libkv - version: 93ab0e6c056d325dfbb11e1d58a3b4f5f62e7f3c - subpackages: - - store -- name: github.com/docker/libnetwork - version: 6d098467ec58038b68620a3c2c418936661efa64 - subpackages: - - datastore - - discoverapi - - types -- name: github.com/docker/libtrust - version: aabc10ec26b754e797f9028f4589c5b7bd90dc20 -- name: github.com/docker/swarmkit - version: bd7bafb8a61de1f5f23c8215ce7b9ecbcb30ff21 - subpackages: - - api - - api/deepcopy - - api/equality - - api/genericresource - - api/naming - - ca - - connectionbroker - - identity - - ioutils - - log - - manager/raftselector - - manager/state - - manager/state/store - - protobuf/plugin - - remotes - - watch - - watch/queue -- name: github.com/eapache/go-resiliency - version: b1fe83b5b03f624450823b751b662259ffc6af70 - subpackages: - - breaker -- name: github.com/eapache/go-xerial-snappy - version: bb955e01b9346ac19dc29eb16586c90ded99a98c -- name: github.com/eapache/queue - version: 44cc805cf13205b55f69e14bcb69867d1ae92f98 -- name: github.com/emicklei/go-restful - version: ff4f55a206334ef123e4f79bbf348980da81ca46 - subpackages: - - log -- name: github.com/emicklei/go-restful-swagger12 - version: dcef7f55730566d41eae5db10e7d6981829720f6 -- name: github.com/fnproject/fn_go - version: 7ce3bb2e624df60cdfbfc1ee5483f6df80bb2b1b - subpackages: - - client - - client/apps - - client/call - - client/operations - - client/routes - - models -- name: github.com/fsouza/go-dockerclient - version: 98edf3edfae6a6500fecc69d2bcccf1302544004 -- name: github.com/garyburd/redigo - version: 70e1b1943d4fc9c56791abaa6f4d1e727b9ab925 - subpackages: - - internal - - redis -- name: github.com/ghodss/yaml - version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee -- name: github.com/gin-contrib/cors - version: cf4846e6a636a76237a28d9286f163c132e841bc -- name: github.com/gin-contrib/sse - version: 22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae -- name: github.com/gin-gonic/gin - version: 5afc5b19730118c9b8324fe9dd995d44ec65c81a - subpackages: - - binding - - json - - render -- name: github.com/go-ini/ini - version: c787282c39ac1fc618827141a1f762240def08a3 -- name: github.com/go-logfmt/logfmt - version: 390ab7935ee28ec6b286364bba9b4dd6410cb3d5 -- name: github.com/go-openapi/analysis - version: 8ed83f2ea9f00f945516462951a288eaa68bf0d6 -- name: github.com/go-openapi/errors - version: 03cfca65330da08a5a440053faf994a3c682b5bf -- name: github.com/go-openapi/jsonpointer - version: 779f45308c19820f1a69e9a4cd965f496e0da10f -- name: github.com/go-openapi/jsonreference - version: 13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272 -- name: github.com/go-openapi/loads - version: a80dea3052f00e5f032e860dd7355cd0cc67e24d - subpackages: - - fmts -- name: github.com/go-openapi/runtime - version: d6605b7c17ac3b1033ca794886e6142a4141f5b0 - subpackages: - - client -- name: github.com/go-openapi/spec - version: 3faa0055dbbf2110abc1f3b4e3adbb22721e96e7 -- name: github.com/go-openapi/strfmt - version: 610b6cacdcde6852f4de68998bd20ce1dac85b22 -- name: github.com/go-openapi/swag - version: f3f9494671f93fcff853e3c6e9e948b3eb71e590 -- name: github.com/go-openapi/validate - version: 8a82927c942c94794a5cd8b8b50ce2f48a955c0c -- name: github.com/go-sql-driver/mysql - version: 21d7e97c9f760ca685a01ecea202e1c84276daa1 -- name: github.com/gogo/protobuf - version: c0656edd0d9eab7c66d1eb0c568f9039345796f7 - subpackages: - - gogoproto - - proto - - protoc-gen-gogo/descriptor - - sortkeys - - types -- name: github.com/golang/glog - version: 44145f04b68cf362d9c4df2182967c2275eaefed -- name: github.com/golang/protobuf - version: 4bd1920723d7b7c925de087aa32e2187708897f7 - subpackages: - - proto - - ptypes/any -- name: github.com/golang/snappy - version: 553a641470496b2327abcac10b36396bd98e45c9 -- name: github.com/google/btree - version: 316fb6d3f031ae8f4d457c6c5186b9e3ded70435 -- name: github.com/google/certificate-transparency-go - version: 0dac42a6ed448ba220ee315abfaa6d26fd5fc9bb - repo: https://github.com/google/certificate-transparency-go - subpackages: - - asn1 - - client - - jsonclient - - tls - - x509 - - x509/pkix -- name: github.com/google/gofuzz - version: 44d81051d367757e1c7c6a5a86423ece9afcf63c -- name: github.com/gorilla/context - version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42 -- name: github.com/gorilla/mux - version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 -- name: github.com/grpc-ecosystem/go-grpc-prometheus - version: 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 -- name: github.com/hashicorp/go-immutable-radix - version: 8aac2701530899b64bdea735a1de8da899815220 -- name: github.com/hashicorp/go-memdb - version: ec43fcf8f202880feb35d2abb40a570c1f4172e9 -- name: github.com/hashicorp/golang-lru - version: a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 - subpackages: - - simplelru -- name: github.com/jmoiron/jsonq - version: e874b168d07ecc7808bc950a17998a8aa3141d82 -- name: github.com/jmoiron/sqlx - version: d9bd385d68c068f1fabb5057e3dedcbcbb039d0f - subpackages: - - reflectx -- name: github.com/json-iterator/go - version: fdfe0b9a69118ff692d6e1005e9de7e0cffb7d6b -- name: github.com/juju/ratelimit - version: 5b9ff866471762aa2ab2dced63c9fb6f53921342 -- name: github.com/kr/logfmt - version: b84e30acd515aadc4b783ad4ff83aff3299bdfe0 -- name: github.com/lib/pq - version: 23da1db4f16d9658a86ae9b717c245fc078f10f1 - subpackages: - - oid -- name: github.com/mailru/easyjson - version: 32fa128f234d041f196a9f3e0fea5ac9772c08e1 - subpackages: - - buffer - - jlexer - - jwriter -- name: github.com/mattes/migrate - version: 5b98c13eff7657ab49a1a5f705b72f961d7fc558 - subpackages: - - database - - source -- name: github.com/mattn/go-isatty - version: fc9e8d8ef48496124e79ae0df75490096eccf6fe -- name: github.com/mattn/go-sqlite3 - version: 05548ff55570cdb9ac72ff4a25a3b5e77a6fb7e5 -- name: github.com/matttproud/golang_protobuf_extensions - version: c12348ce28de40eed0136aa2b644d0ee0650e56c - subpackages: - - pbutil -- name: github.com/Microsoft/go-winio - version: 78439966b38d69bf38227fbf57ac8a6fee70f69a -- name: github.com/minio/go-homedir - version: 21304a94172ae3a09dee2cd86a12fb6f842138c7 -- name: github.com/minio/minio-go - version: a62e2045a5d3a6630dbb7040260994583ac56b10 - subpackages: - - pkg/credentials - - pkg/encrypt - - pkg/policy - - pkg/s3signer - - pkg/s3utils - - pkg/set -- name: github.com/mitchellh/mapstructure - version: d0303fe809921458f417bcf828397a65db30a7e4 -- name: github.com/Nvveen/Gotty - version: cd527374f1e5bff4938207604a14f2e38a9cf512 -- name: github.com/opencontainers/go-digest - version: 279bed98673dd5bef374d3b6e4b09e2af76183bf -- name: github.com/opencontainers/image-spec - version: ebd93fd0782379ca3d821f0fa74f0651a9347a3e - subpackages: - - specs-go - - specs-go/v1 -- name: github.com/opencontainers/runc - version: ae2948042b08ad3d6d13cd09f40a50ffff4fc688 - subpackages: - - libcontainer/system - - libcontainer/user -- name: github.com/opentracing-contrib/go-observer - version: a52f2342449246d5bcc273e65cbdcfa5f7d6c63c -- name: github.com/opentracing/opentracing-go - version: 8ebe5d4e236eed9fd88e593c288bfb804d630b8c - subpackages: - - ext - - log -- name: github.com/openzipkin/zipkin-go-opentracing - version: 9c88fa03bfdfaa5fec7cd1b40f3d10ec15c15fc6 - subpackages: - - flag - - thrift/gen-go/scribe - - thrift/gen-go/zipkincore - - types - - wire -- name: github.com/patrickmn/go-cache - version: a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0 -- name: github.com/pierrec/lz4 - version: 08c27939df1bd95e881e2c2367a749964ad1fceb -- name: github.com/pierrec/xxHash - version: a0006b13c722f7f12368c00a3d3c2ae8a999a0c6 - subpackages: - - xxHash32 -- name: github.com/pkg/errors - version: 2b3a18b5f0fb6b4f9190549597d3f962c02bc5eb -- name: github.com/prometheus/client_golang - version: c5b7fccd204277076155f10851dad72b76a49317 - subpackages: - - prometheus - - prometheus/promhttp -- name: github.com/prometheus/client_model - version: 6f3806018612930941127f2a7c6c453ba2c527d2 - subpackages: - - go -- name: github.com/prometheus/common - version: 2f17f4a9d485bf34b4bfaccc273805040e4f86c8 - subpackages: - - expfmt - - internal/bitbucket.org/ww/goautoneg - - model -- name: github.com/prometheus/procfs - version: a1dba9ce8baed984a2495b658c82687f8157b98f - subpackages: - - xfs -- name: github.com/PuerkitoBio/purell - version: 8a290539e2e8629dbc4e6bad948158f790ec31f4 -- name: github.com/PuerkitoBio/urlesc - version: 5bd2802263f21d8788851d5305584c82a5c75d7e -- name: github.com/rcrowley/go-metrics - version: 1f30fe9094a513ce4c700b9a54458bbb0c96996c -- name: github.com/rdallman/migrate - version: bc72eeb997c7334cb5f05f5aefd2d70bc34d71ef - subpackages: - - database/mysql - - database/postgres - - database/sqlite3 - - source - - source/go-bindata -- name: github.com/Shopify/sarama - version: 4704a3a8c95920361c47e9a2adec13c3d757c757 -- name: github.com/sirupsen/logrus - version: 89742aefa4b206dcf400792f3bd35b542998eb3b - subpackages: - - hooks/syslog -- name: github.com/spf13/pflag - version: 9ff6c6923cfffbcd502984b8e0c80539a94968b7 -- name: github.com/ugorji/go - version: ded73eae5db7e7a0ef6f55aace87a2873c5d2b74 - subpackages: - - codec -- name: golang.org/x/crypto - version: 94eea52f7b742c7cbe0b03b22f0c4c8631ece122 - subpackages: - - ocsp - - pkcs12 - - pkcs12/internal/rc2 - - ssh/terminal -- name: golang.org/x/net - version: a8b9294777976932365dabb6640cf1468d95c70f - subpackages: - - context - - context/ctxhttp - - http2 - - http2/hpack - - idna - - internal/timeseries - - lex/httplex - - trace -- name: golang.org/x/sys - version: 8b4580aae2a0dd0c231a45d3ccb8434ff533b840 - subpackages: - - unix - - windows -- name: golang.org/x/text - version: 57961680700a5336d15015c8c50686ca5ba362a4 - subpackages: - - cases - - internal - - internal/tag - - language - - runes - - secure/bidirule - - secure/precis - - transform - - unicode/bidi - - unicode/norm - - width -- name: google.golang.org/genproto - version: 09f6ed296fc66555a25fe4ce95173148778dfa85 - subpackages: - - googleapis/rpc/status -- name: google.golang.org/grpc - version: b8669c35455183da6d5c474ea6e72fbf55183274 - subpackages: - - codes - - credentials - - grpclb/grpc_lb_v1 - - grpclog - - internal - - keepalive - - metadata - - naming - - peer - - stats - - status - - tap - - transport -- name: gopkg.in/go-playground/validator.v8 - version: 5f1438d3fca68893a817e4a66806cea46a9e4ebf -- name: gopkg.in/inf.v0 - version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 -- name: gopkg.in/mgo.v2 - version: 3f83fa5005286a7fe593b055f0d7771a7dce4655 - subpackages: - - bson - - internal/json -- name: gopkg.in/yaml.v2 - version: 53feefa2559fb8dfa8d81baad31be332c97d6c77 -- name: k8s.io/apimachinery - version: 1fd2e63a9a370677308a42f24fd40c86438afddf - subpackages: - - pkg/api/equality - - pkg/api/errors - - pkg/api/meta - - pkg/api/resource - - pkg/apimachinery - - pkg/apimachinery/announced - - pkg/apimachinery/registered - - pkg/apis/meta/v1 - - pkg/apis/meta/v1/unstructured - - pkg/apis/meta/v1alpha1 - - pkg/conversion - - pkg/conversion/queryparams - - pkg/conversion/unstructured - - pkg/fields - - pkg/labels - - pkg/openapi - - pkg/runtime - - pkg/runtime/schema - - pkg/runtime/serializer - - pkg/runtime/serializer/json - - pkg/runtime/serializer/protobuf - - pkg/runtime/serializer/recognizer - - pkg/runtime/serializer/streaming - - pkg/runtime/serializer/versioning - - pkg/selection - - pkg/types - - pkg/util/clock - - pkg/util/diff - - pkg/util/errors - - pkg/util/framer - - pkg/util/intstr - - pkg/util/json - - pkg/util/net - - pkg/util/rand - - pkg/util/runtime - - pkg/util/sets - - pkg/util/validation - - pkg/util/validation/field - - pkg/util/wait - - pkg/util/yaml - - pkg/version - - pkg/watch - - third_party/forked/golang/reflect -- name: k8s.io/client-go - version: d92e8497f71b7b4e0494e5bd204b48d34bd6f254 - subpackages: - - discovery - - kubernetes - - kubernetes/scheme - - kubernetes/typed/admissionregistration/v1alpha1 - - kubernetes/typed/apps/v1beta1 - - kubernetes/typed/authentication/v1 - - kubernetes/typed/authentication/v1beta1 - - kubernetes/typed/authorization/v1 - - kubernetes/typed/authorization/v1beta1 - - kubernetes/typed/autoscaling/v1 - - kubernetes/typed/autoscaling/v2alpha1 - - kubernetes/typed/batch/v1 - - kubernetes/typed/batch/v2alpha1 - - kubernetes/typed/certificates/v1beta1 - - kubernetes/typed/core/v1 - - kubernetes/typed/extensions/v1beta1 - - kubernetes/typed/networking/v1 - - kubernetes/typed/policy/v1beta1 - - kubernetes/typed/rbac/v1alpha1 - - kubernetes/typed/rbac/v1beta1 - - kubernetes/typed/settings/v1alpha1 - - kubernetes/typed/storage/v1 - - kubernetes/typed/storage/v1beta1 - - pkg/api - - pkg/api/v1 - - pkg/api/v1/ref - - pkg/apis/admissionregistration - - pkg/apis/admissionregistration/v1alpha1 - - pkg/apis/apps - - pkg/apis/apps/v1beta1 - - pkg/apis/authentication - - pkg/apis/authentication/v1 - - pkg/apis/authentication/v1beta1 - - pkg/apis/authorization - - pkg/apis/authorization/v1 - - pkg/apis/authorization/v1beta1 - - pkg/apis/autoscaling - - pkg/apis/autoscaling/v1 - - pkg/apis/autoscaling/v2alpha1 - - pkg/apis/batch - - pkg/apis/batch/v1 - - pkg/apis/batch/v2alpha1 - - pkg/apis/certificates - - pkg/apis/certificates/v1beta1 - - pkg/apis/extensions - - pkg/apis/extensions/v1beta1 - - pkg/apis/networking - - pkg/apis/networking/v1 - - pkg/apis/policy - - pkg/apis/policy/v1beta1 - - pkg/apis/rbac - - pkg/apis/rbac/v1alpha1 - - pkg/apis/rbac/v1beta1 - - pkg/apis/settings - - pkg/apis/settings/v1alpha1 - - pkg/apis/storage - - pkg/apis/storage/v1 - - pkg/apis/storage/v1beta1 - - pkg/util - - pkg/util/parsers - - pkg/version - - rest - - rest/watch - - tools/clientcmd/api - - tools/metrics - - transport - - util/cert - - util/flowcontrol - - util/integer -testImports: [] diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index c28da1e4a..000000000 --- a/glide.yaml +++ /dev/null @@ -1,94 +0,0 @@ -package: github.com/fnproject/fn -excludeDirs: -- cli -import: -- package: golang.org/x/crypto - version: master - subpackages: - - pkcs12 -- package: github.com/fnproject/fn_go - version: ^0.2.0 - subpackages: - - models -- package: github.com/sirupsen/logrus - version: 89742aefa4b206dcf400792f3bd35b542998eb3b -- package: github.com/amir/raidman -- package: github.com/boltdb/bolt -- package: github.com/cactus/go-statsd-client - subpackages: - - statsd -- package: github.com/dchest/siphash -- package: github.com/dghubble/go-twitter - subpackages: - - twitter -- package: github.com/dghubble/oauth1 -- package: github.com/dgrijalva/jwt-go -- package: github.com/docker/cli - version: 139fcd3ee95f37f3ac17b1200fb0a63908cb6781 - subpackages: - - cli/config/configfile -- package: github.com/docker/distribution - version: 5f6282db7d65e6d72ad7c2cc66310724a57be716 -- package: github.com/fsouza/go-dockerclient -- package: github.com/garyburd/redigo - subpackages: - - redis -- package: github.com/gin-gonic/gin -- package: github.com/rdallman/migrate - version: bc72eeb997c7334cb5f05f5aefd2d70bc34d71ef -- package: github.com/go-openapi/errors -- package: github.com/go-openapi/loads - subpackages: - - fmts -- package: github.com/go-openapi/runtime - subpackages: - - client -- package: github.com/go-openapi/spec -- package: github.com/go-openapi/strfmt -- package: github.com/go-openapi/swag -- package: github.com/go-openapi/validate -- package: github.com/go-sql-driver/mysql - version: 21d7e97c9f760ca685a01ecea202e1c84276daa1 -- package: github.com/google/btree -- package: github.com/jmoiron/jsonq -- package: github.com/lib/pq -- package: github.com/docker/docker - version: cdf870bd0b5fa678b10ef2708cca7ad776b4913c -- package: github.com/pkg/errors -- package: github.com/jmoiron/sqlx -- package: github.com/mattn/go-sqlite3 -- package: github.com/minio/minio-go -- package: github.com/opentracing/opentracing-go -- package: github.com/openzipkin/zipkin-go-opentracing -- package: github.com/opencontainers/go-digest - version: 279bed98673dd5bef374d3b6e4b09e2af76183bf -- package: github.com/opencontainers/runc - version: ae2948042b08ad3d6d13cd09f40a50ffff4fc688 -- package: github.com/Azure/go-ansiterm - version: 19f72df4d05d31cbe1c56bfc8045c96babff6c7e -- package: github.com/prometheus/common - version: 2f17f4a9d485bf34b4bfaccc273805040e4f86c8 -- package: github.com/prometheus/client_golang -- package: github.com/gin-contrib/cors - version: ~1.2.0 -- package: k8s.io/client-go - version: ^v4.0.0 - subpackages: - - kubernetes -- package: github.com/emicklei/go-restful-swagger12 -- package: golang.org/x/sys - version: master - subpackages: - - unix -- package: golang.org/x/net - version: master - subpackages: - - http2 -- package: golang.org/x/text - version: master -- package: github.com/mailru/easyjson - version: master - subpackages: - - jwriter -testImport: -- package: github.com/patrickmn/go-cache diff --git a/vendor/github.com/amir/raidman/README.md b/vendor/github.com/amir/raidman/README.md deleted file mode 100644 index 5dbe8684e..000000000 --- a/vendor/github.com/amir/raidman/README.md +++ /dev/null @@ -1,73 +0,0 @@ -Raidman -======= - -Go Riemann client - -```go -package main - -import ( - "github.com/amir/raidman" -) - -func main() { - c, err := raidman.Dial("tcp", "localhost:5555") - if err != nil { - panic(err) - } - - var event = &raidman.Event{ - State: "success", - Host: "raidman", - Service: "raidman-sample", - Metric: 100, - Ttl: 10, - } - - // send one event - err = c.Send(event) - if err != nil { - panic(err) - } - - // send multiple events at once - err = c.SendMulti([]*raidman.Event{ - &raidman.Event{ - State: "success", - Host: "raidman", - Service: "raidman-sample", - Metric: 100, - Ttl: 10, - }, - &raidman.Event{ - State: "failure", - Host: "raidman", - Service: "raidman-sample", - Metric: 100, - Ttl: 10, - }, - &raidman.Event{ - State: "success", - Host: "raidman", - Service: "raidman-sample", - Metric: 100, - Ttl: 10, - }, - }) - if err != nil { - panic(err) - } - - events, err := c.Query("host = \"raidman\"") - if err != nil { - panic(err) - } - - if len(events) < 1 { - panic("Submitted event not found") - } - - c.Close() -} - -``` diff --git a/vendor/github.com/amir/raidman/UNLICENSE b/vendor/github.com/amir/raidman/UNLICENSE deleted file mode 100644 index 68a49daad..000000000 --- a/vendor/github.com/amir/raidman/UNLICENSE +++ /dev/null @@ -1,24 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -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 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. - -For more information, please refer to diff --git a/vendor/github.com/amir/raidman/proto/Makefile b/vendor/github.com/amir/raidman/proto/Makefile deleted file mode 100644 index 5349cc839..000000000 --- a/vendor/github.com/amir/raidman/proto/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -proto.pb.go: proto.proto - mkdir -p _pb - protoc --go_out=_pb $< - cat _pb/$@\ - |gofmt >$@ - rm -rf _pb diff --git a/vendor/github.com/amir/raidman/proto/proto.pb.go b/vendor/github.com/amir/raidman/proto/proto.pb.go deleted file mode 100644 index 42eea684d..000000000 --- a/vendor/github.com/amir/raidman/proto/proto.pb.go +++ /dev/null @@ -1,273 +0,0 @@ -// Code generated by protoc-gen-go. -// source: proto.proto -// DO NOT EDIT! - -package proto - -import proto1 "github.com/golang/protobuf/proto" -import json "encoding/json" -import math "math" - -// Reference proto, json, and math imports to suppress error if they are not otherwise used. -var _ = proto1.Marshal -var _ = &json.SyntaxError{} -var _ = math.Inf - -type State struct { - Time *int64 `protobuf:"varint,1,opt,name=time" json:"time,omitempty"` - State *string `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` - Service *string `protobuf:"bytes,3,opt,name=service" json:"service,omitempty"` - Host *string `protobuf:"bytes,4,opt,name=host" json:"host,omitempty"` - Description *string `protobuf:"bytes,5,opt,name=description" json:"description,omitempty"` - Once *bool `protobuf:"varint,6,opt,name=once" json:"once,omitempty"` - Tags []string `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"` - Ttl *float32 `protobuf:"fixed32,8,opt,name=ttl" json:"ttl,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (this *State) Reset() { *this = State{} } -func (this *State) String() string { return proto1.CompactTextString(this) } -func (*State) ProtoMessage() {} - -func (this *State) GetTime() int64 { - if this != nil && this.Time != nil { - return *this.Time - } - return 0 -} - -func (this *State) GetState() string { - if this != nil && this.State != nil { - return *this.State - } - return "" -} - -func (this *State) GetService() string { - if this != nil && this.Service != nil { - return *this.Service - } - return "" -} - -func (this *State) GetHost() string { - if this != nil && this.Host != nil { - return *this.Host - } - return "" -} - -func (this *State) GetDescription() string { - if this != nil && this.Description != nil { - return *this.Description - } - return "" -} - -func (this *State) GetOnce() bool { - if this != nil && this.Once != nil { - return *this.Once - } - return false -} - -func (this *State) GetTags() []string { - if this != nil { - return this.Tags - } - return nil -} - -func (this *State) GetTtl() float32 { - if this != nil && this.Ttl != nil { - return *this.Ttl - } - return 0 -} - -type Event struct { - Time *int64 `protobuf:"varint,1,opt,name=time" json:"time,omitempty"` - State *string `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"` - Service *string `protobuf:"bytes,3,opt,name=service" json:"service,omitempty"` - Host *string `protobuf:"bytes,4,opt,name=host" json:"host,omitempty"` - Description *string `protobuf:"bytes,5,opt,name=description" json:"description,omitempty"` - Tags []string `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"` - Ttl *float32 `protobuf:"fixed32,8,opt,name=ttl" json:"ttl,omitempty"` - Attributes []*Attribute `protobuf:"bytes,9,rep,name=attributes" json:"attributes,omitempty"` - MetricSint64 *int64 `protobuf:"zigzag64,13,opt,name=metric_sint64" json:"metric_sint64,omitempty"` - MetricD *float64 `protobuf:"fixed64,14,opt,name=metric_d" json:"metric_d,omitempty"` - MetricF *float32 `protobuf:"fixed32,15,opt,name=metric_f" json:"metric_f,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (this *Event) Reset() { *this = Event{} } -func (this *Event) String() string { return proto1.CompactTextString(this) } -func (*Event) ProtoMessage() {} - -func (this *Event) GetTime() int64 { - if this != nil && this.Time != nil { - return *this.Time - } - return 0 -} - -func (this *Event) GetState() string { - if this != nil && this.State != nil { - return *this.State - } - return "" -} - -func (this *Event) GetService() string { - if this != nil && this.Service != nil { - return *this.Service - } - return "" -} - -func (this *Event) GetHost() string { - if this != nil && this.Host != nil { - return *this.Host - } - return "" -} - -func (this *Event) GetDescription() string { - if this != nil && this.Description != nil { - return *this.Description - } - return "" -} - -func (this *Event) GetTags() []string { - if this != nil { - return this.Tags - } - return nil -} - -func (this *Event) GetTtl() float32 { - if this != nil && this.Ttl != nil { - return *this.Ttl - } - return 0 -} - -func (this *Event) GetAttributes() []*Attribute { - if this != nil { - return this.Attributes - } - return nil -} - -func (this *Event) GetMetricSint64() int64 { - if this != nil && this.MetricSint64 != nil { - return *this.MetricSint64 - } - return 0 -} - -func (this *Event) GetMetricD() float64 { - if this != nil && this.MetricD != nil { - return *this.MetricD - } - return 0 -} - -func (this *Event) GetMetricF() float32 { - if this != nil && this.MetricF != nil { - return *this.MetricF - } - return 0 -} - -type Query struct { - String_ *string `protobuf:"bytes,1,opt,name=string" json:"string,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (this *Query) Reset() { *this = Query{} } -func (this *Query) String() string { return proto1.CompactTextString(this) } -func (*Query) ProtoMessage() {} - -func (this *Query) GetString_() string { - if this != nil && this.String_ != nil { - return *this.String_ - } - return "" -} - -type Msg struct { - Ok *bool `protobuf:"varint,2,opt,name=ok" json:"ok,omitempty"` - Error *string `protobuf:"bytes,3,opt,name=error" json:"error,omitempty"` - States []*State `protobuf:"bytes,4,rep,name=states" json:"states,omitempty"` - Query *Query `protobuf:"bytes,5,opt,name=query" json:"query,omitempty"` - Events []*Event `protobuf:"bytes,6,rep,name=events" json:"events,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (this *Msg) Reset() { *this = Msg{} } -func (this *Msg) String() string { return proto1.CompactTextString(this) } -func (*Msg) ProtoMessage() {} - -func (this *Msg) GetOk() bool { - if this != nil && this.Ok != nil { - return *this.Ok - } - return false -} - -func (this *Msg) GetError() string { - if this != nil && this.Error != nil { - return *this.Error - } - return "" -} - -func (this *Msg) GetStates() []*State { - if this != nil { - return this.States - } - return nil -} - -func (this *Msg) GetQuery() *Query { - if this != nil { - return this.Query - } - return nil -} - -func (this *Msg) GetEvents() []*Event { - if this != nil { - return this.Events - } - return nil -} - -type Attribute struct { - Key *string `protobuf:"bytes,1,req,name=key" json:"key,omitempty"` - Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - XXX_unrecognized []byte `json:"-"` -} - -func (this *Attribute) Reset() { *this = Attribute{} } -func (this *Attribute) String() string { return proto1.CompactTextString(this) } -func (*Attribute) ProtoMessage() {} - -func (this *Attribute) GetKey() string { - if this != nil && this.Key != nil { - return *this.Key - } - return "" -} - -func (this *Attribute) GetValue() string { - if this != nil && this.Value != nil { - return *this.Value - } - return "" -} - -func init() { -} diff --git a/vendor/github.com/amir/raidman/proto/proto.proto b/vendor/github.com/amir/raidman/proto/proto.proto deleted file mode 100644 index 3e946a3a0..000000000 --- a/vendor/github.com/amir/raidman/proto/proto.proto +++ /dev/null @@ -1,45 +0,0 @@ -option java_package = "com.aphyr.riemann"; -option java_outer_classname = "Proto"; - -message State { - optional int64 time = 1; - optional string state = 2; - optional string service = 3; - optional string host = 4; - optional string description = 5; - optional bool once = 6; - repeated string tags = 7; - optional float ttl = 8; -} - -message Event { - optional int64 time = 1; - optional string state = 2; - optional string service = 3; - optional string host = 4; - optional string description = 5; - repeated string tags = 7; - optional float ttl = 8; - repeated Attribute attributes = 9; - - optional sint64 metric_sint64 = 13; - optional double metric_d = 14; - optional float metric_f = 15; -} - -message Query { - optional string string = 1; -} - -message Msg { - optional bool ok = 2; - optional string error = 3; - repeated State states = 4; - optional Query query = 5; - repeated Event events = 6; -} - -message Attribute { - required string key = 1; - optional string value = 2; -} diff --git a/vendor/github.com/amir/raidman/raidman.go b/vendor/github.com/amir/raidman/raidman.go deleted file mode 100644 index 81ff052bd..000000000 --- a/vendor/github.com/amir/raidman/raidman.go +++ /dev/null @@ -1,341 +0,0 @@ -// Go Riemann client -package raidman - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "net" - "net/url" - "os" - "reflect" - "sync" - "time" - - "github.com/amir/raidman/proto" - pb "github.com/golang/protobuf/proto" - "golang.org/x/net/proxy" -) - -type network interface { - Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) -} - -type tcp struct{} - -type udp struct{} - -// Client represents a connection to a Riemann server -type Client struct { - sync.Mutex - net network - connection net.Conn - timeout time.Duration -} - -// An Event represents a single Riemann event -type Event struct { - Ttl float32 `json:"ttl,omitempty"` - Time int64 `json:"time,omitempty"` - Tags []string `json:"tags,omitempty"` - Host string `json:"host,omitempty"` // Defaults to os.Hostname() - State string `json:"state,omitempty"` - Service string `json:"service,omitempty"` - Metric interface{} `json:"metric,omitempty"` // Could be Int, Float32, Float64 - Description string `json:"description,omitempty"` - Attributes map[string]string `json:"attributes,omitempty"` -} - -// Dial establishes a connection to a Riemann server at addr, on the network -// netwrk, with a timeout of timeout -// -// Known networks are "tcp", "tcp4", "tcp6", "udp", "udp4", and "udp6". -func DialWithTimeout(netwrk, addr string, timeout time.Duration) (c *Client, err error) { - c = new(Client) - - var cnet network - switch netwrk { - case "tcp", "tcp4", "tcp6": - cnet = new(tcp) - case "udp", "udp4", "udp6": - cnet = new(udp) - default: - return nil, fmt.Errorf("dial %q: unsupported network %q", netwrk, netwrk) - } - - dialer, err := newDialer() - if err != nil { - return nil, err - } - - c.net = cnet - c.timeout = timeout - c.connection, err = dialer.Dial(netwrk, addr) - if err != nil { - return nil, err - } - - return c, nil -} - -func newDialer() (proxy.Dialer, error) { - var proxyUrl = os.Getenv("RIEMANN_PROXY") - var dialer proxy.Dialer = proxy.Direct - - // Get a proxy Dialer that will create the connection on our - // behalf via the SOCKS5 proxy. Specify the authentication - // and re-create the dialer/transport/client if tor's - // IsolateSOCKSAuth is needed. - if len(proxyUrl) > 0 { - u, err := url.Parse(proxyUrl) - if err != nil { - return nil, fmt.Errorf("failed to obtain proxy dialer: %v\n", err) - } - if dialer, err = proxy.FromURL(u, dialer); err != nil { - return nil, fmt.Errorf("failed to parse " + proxyUrl + " as a proxy: " + err.Error()) - } - } - - return dialer, nil -} - -// Dial establishes a connection to a Riemann server at addr, on the network -// netwrk. -// -// Known networks are "tcp", "tcp4", "tcp6", "udp", "udp4", and "udp6". -func Dial(netwrk, addr string) (c *Client, err error) { - return DialWithTimeout(netwrk, addr, 0) -} - -func (network *tcp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) { - msg := &proto.Msg{} - data, err := pb.Marshal(message) - if err != nil { - return msg, err - } - b := new(bytes.Buffer) - if err = binary.Write(b, binary.BigEndian, uint32(len(data))); err != nil { - return msg, err - } - if _, err = conn.Write(b.Bytes()); err != nil { - return msg, err - } - if _, err = conn.Write(data); err != nil { - return msg, err - } - var header uint32 - if err = binary.Read(conn, binary.BigEndian, &header); err != nil { - return msg, err - } - response := make([]byte, header) - if err = readFully(conn, response); err != nil { - return msg, err - } - if err = pb.Unmarshal(response, msg); err != nil { - return msg, err - } - if msg.GetOk() != true { - return msg, errors.New(msg.GetError()) - } - return msg, nil -} - -func readFully(r io.Reader, p []byte) error { - for len(p) > 0 { - n, err := r.Read(p) - p = p[n:] - if err != nil { - return err - } - } - return nil -} - -func (network *udp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) { - data, err := pb.Marshal(message) - if err != nil { - return nil, err - } - if _, err = conn.Write(data); err != nil { - return nil, err - } - - return nil, nil -} - -func isZero(v reflect.Value) bool { - switch v.Kind() { - case reflect.Map: - return v.IsNil() - case reflect.Slice: - zero := true - for i := 0; i < v.Len(); i++ { - zero = zero && isZero(v.Index(i)) - } - return zero - } - zero := reflect.Zero(v.Type()) - return v.Interface() == zero.Interface() -} - -func eventToPbEvent(event *Event) (*proto.Event, error) { - var e proto.Event - - if event.Host == "" { - event.Host, _ = os.Hostname() - } - t := reflect.ValueOf(&e).Elem() - s := reflect.ValueOf(event).Elem() - typeOfEvent := s.Type() - for i := 0; i < s.NumField(); i++ { - f := s.Field(i) - value := reflect.ValueOf(f.Interface()) - if !isZero(f) { - name := typeOfEvent.Field(i).Name - switch name { - case "State", "Service", "Host", "Description": - tmp := reflect.ValueOf(pb.String(value.String())) - t.FieldByName(name).Set(tmp) - case "Ttl": - tmp := reflect.ValueOf(pb.Float32(float32(value.Float()))) - t.FieldByName(name).Set(tmp) - case "Time": - tmp := reflect.ValueOf(pb.Int64(value.Int())) - t.FieldByName(name).Set(tmp) - case "Tags": - tmp := reflect.ValueOf(value.Interface().([]string)) - t.FieldByName(name).Set(tmp) - case "Metric": - switch reflect.TypeOf(f.Interface()).Kind() { - case reflect.Int, reflect.Int64: - tmp := reflect.ValueOf(pb.Int64(int64(value.Int()))) - t.FieldByName("MetricSint64").Set(tmp) - case reflect.Uint64: - tmp := reflect.ValueOf(pb.Int64(int64(value.Uint()))) - t.FieldByName("MetricSint64").Set(tmp) - case reflect.Float32: - tmp := reflect.ValueOf(pb.Float32(float32(value.Float()))) - t.FieldByName("MetricF").Set(tmp) - case reflect.Float64: - tmp := reflect.ValueOf(pb.Float64(value.Float())) - t.FieldByName("MetricD").Set(tmp) - default: - return nil, fmt.Errorf("Metric of invalid type (type %v)", - reflect.TypeOf(f.Interface()).Kind()) - } - case "Attributes": - var attrs []*proto.Attribute - for k, v := range value.Interface().(map[string]string) { - // Copy k,v so we can take - // pointers to the new - // temporaries - k_, v_ := k, v - attrs = append(attrs, &proto.Attribute{ - Key: &k_, - Value: &v_, - }) - } - t.FieldByName(name).Set(reflect.ValueOf(attrs)) - } - } - } - - return &e, nil -} - -func pbEventsToEvents(pbEvents []*proto.Event) []Event { - var events []Event - - for _, event := range pbEvents { - e := Event{ - State: event.GetState(), - Service: event.GetService(), - Host: event.GetHost(), - Description: event.GetDescription(), - Ttl: event.GetTtl(), - Time: event.GetTime(), - Tags: event.GetTags(), - } - if event.MetricF != nil { - e.Metric = event.GetMetricF() - } else if event.MetricD != nil { - e.Metric = event.GetMetricD() - } else { - e.Metric = event.GetMetricSint64() - } - if event.Attributes != nil { - e.Attributes = make(map[string]string, len(event.GetAttributes())) - for _, attr := range event.GetAttributes() { - e.Attributes[attr.GetKey()] = attr.GetValue() - } - } - - events = append(events, e) - } - - return events -} - -// Send sends an event to Riemann -func (c *Client) Send(event *Event) error { - return c.SendMulti([]*Event{event}) -} - -// SendMulti sends multiple events to Riemann -func (c *Client) SendMulti(events []*Event) error { - message := &proto.Msg{} - - for _, event := range events { - e, err := eventToPbEvent(event) - if err != nil { - return err - } - - message.Events = append(message.Events, e) - } - - c.Lock() - defer c.Unlock() - - if c.timeout > 0 { - err := c.connection.SetDeadline(time.Now().Add(c.timeout)) - if err != nil { - return err - } - } - - _, err := c.net.Send(message, c.connection) - if err != nil { - return err - } - - return nil -} - -// Query returns a list of events matched by query -func (c *Client) Query(q string) ([]Event, error) { - switch c.net.(type) { - case *udp: - return nil, errors.New("Querying over UDP is not supported") - } - query := &proto.Query{} - query.String_ = pb.String(q) - message := &proto.Msg{} - message.Query = query - c.Lock() - defer c.Unlock() - response, err := c.net.Send(message, c.connection) - if err != nil { - return nil, err - } - return pbEventsToEvents(response.GetEvents()), nil -} - -// Close closes the connection to Riemann -func (c *Client) Close() error { - c.Lock() - defer c.Unlock() - return c.connection.Close() -} diff --git a/vendor/github.com/amir/raidman/raidman_test.go b/vendor/github.com/amir/raidman/raidman_test.go deleted file mode 100644 index 0bf146eb1..000000000 --- a/vendor/github.com/amir/raidman/raidman_test.go +++ /dev/null @@ -1,286 +0,0 @@ -package raidman - -import ( - "fmt" - "os" - "reflect" - "testing" -) - -func TestTCP(t *testing.T) { - c, err := Dial("tcp", "localhost:5555") - if err != nil { - t.Fatal(err.Error()) - } - var event = &Event{ - State: "success", - Host: "raidman", - Service: "tcp", - Metric: 42, - Ttl: 1, - Tags: []string{"tcp", "test", "raidman"}, - Attributes: map[string]string{"type": "test"}, - } - - err = c.Send(event) - if err != nil { - t.Error(err.Error()) - } - - events, err := c.Query("tagged \"test\"") - if err != nil { - t.Error(err.Error()) - } - - if len(events) < 1 { - t.Error("Submitted event not found") - } - - testAttributeExists := false - for _, event := range events { - if val, ok := event.Attributes["type"]; ok && val == "test" { - testAttributeExists = true - } - } - - if !testAttributeExists { - t.Error("Attribute \"type\" is missing") - } - - c.Close() -} - -func TestMultiTCP(t *testing.T) { - c, err := Dial("tcp", "localhost:5555") - if err != nil { - t.Fatal(err.Error()) - } - - err = c.SendMulti([]*Event{ - &Event{ - State: "success", - Host: "raidman", - Service: "tcp-multi-1", - Metric: 42, - Ttl: 1, - Tags: []string{"tcp", "test", "raidman", "multi"}, - Attributes: map[string]string{"type": "test"}, - }, - &Event{ - State: "success", - Host: "raidman", - Service: "tcp-multi-2", - Metric: 42, - Ttl: 1, - Tags: []string{"tcp", "test", "raidman", "multi"}, - Attributes: map[string]string{"type": "test"}, - }, - }) - if err != nil { - t.Error(err.Error()) - } - - events, err := c.Query("tagged \"test\" and tagged \"multi\"") - if err != nil { - t.Error(err.Error()) - } - - if len(events) != 2 { - t.Error("Submitted event not found") - } - - c.Close() -} - -func TestMetricIsInt64(t *testing.T) { - c, err := Dial("tcp", "localhost:5555") - if err != nil { - t.Fatal(err.Error()) - } - - var int64metric int64 = 9223372036854775807 - - var event = &Event{ - State: "success", - Host: "raidman", - Service: "tcp", - Metric: int64metric, - Ttl: 1, - Tags: []string{"tcp", "test", "raidman"}, - Attributes: map[string]string{"type": "test"}, - } - - err = c.Send(event) - if err != nil { - t.Error(err.Error()) - } -} - -func TestUDP(t *testing.T) { - c, err := Dial("udp", "localhost:5555") - if err != nil { - t.Fatal(err.Error()) - } - var event = &Event{ - State: "warning", - Host: "raidman", - Service: "udp", - Metric: 3.4, - Ttl: 10.7, - } - - err = c.Send(event) - if err != nil { - t.Error(err.Error()) - } - c.Close() -} - -func TestTCPWithoutHost(t *testing.T) { - c, err := Dial("tcp", "localhost:5555") - if err != nil { - t.Fatal(err.Error()) - } - defer c.Close() - - var event = &Event{ - State: "success", - Service: "tcp-host-not-set", - Ttl: 5, - } - - err = c.Send(event) - if err != nil { - t.Error(err.Error()) - } - - events, err := c.Query("service = \"tcp-host-not-set\"") - if err != nil { - t.Error(err.Error()) - } - - if len(events) < 1 { - t.Error("Submitted event not found") - } - - for _, e := range events { - if e.Host == "" { - t.Error("Default host name is not set") - } - } -} - -func TestIsZero(t *testing.T) { - event := &Event{ - Time: 1, - } - elem := reflect.ValueOf(event).Elem() - eventType := elem.Type() - for i := 0; i < elem.NumField(); i++ { - field := elem.Field(i) - name := eventType.Field(i).Name - if name == "Time" { - if isZero(field) { - t.Error("Time should not be zero") - } - } else { - if !isZero(field) { - t.Errorf("%s should be zero", name) - } - } - } -} - -func TestDialer(t *testing.T) { - proxyAddr := "localhost:9999" - os.Setenv("RIEMANN_PROXY", "socks5://"+proxyAddr) - defer os.Unsetenv("RIEMANN_PROXY") - dialer, err := newDialer() - if err != nil { - t.Error(err.Error()) - } - val := reflect.Indirect(reflect.ValueOf(dialer)) - // this is a horrible hack but proxy.Dialer exports nothing. - addr := fmt.Sprintf("%s", val.FieldByName("addr")) - if addr != proxyAddr { - t.Errorf("RIEMANN_PROXY is set and is %s but dialer's proxy is %s", proxyAddr, addr) - } -} - -func BenchmarkTCP(b *testing.B) { - c, err := Dial("tcp", "localhost:5555") - - var event = &Event{ - State: "good", - Host: "raidman", - Service: "benchmark", - } - - if err == nil { - for i := 0; i < b.N; i++ { - c.Send(event) - } - } - c.Close() -} - -func BenchmarkUDP(b *testing.B) { - c, err := Dial("udp", "localhost:5555") - - var event = &Event{ - State: "good", - Host: "raidman", - Service: "benchmark", - } - - if err == nil { - for i := 0; i < b.N; i++ { - c.Send(event) - } - } - c.Close() -} - -func BenchmarkConcurrentTCP(b *testing.B) { - c, err := Dial("tcp", "localhost:5555") - - var event = &Event{ - Host: "raidman", - Service: "tcp_concurrent", - Tags: []string{"concurrent", "tcp", "benchmark"}, - } - - ch := make(chan int, b.N) - for i := 0; i < b.N; i++ { - go func(metric int) { - event.Metric = metric - err = c.Send(event) - ch <- i - }(i) - } - <-ch - - c.Close() -} - -func BenchmarkConcurrentUDP(b *testing.B) { - c, err := Dial("udp", "localhost:5555") - - var event = &Event{ - Host: "raidman", - Service: "udp_concurrent", - Tags: []string{"concurrent", "udp", "benchmark"}, - } - - ch := make(chan int, b.N) - for i := 0; i < b.N; i++ { - go func(metric int) { - event.Metric = metric - err = c.Send(event) - ch <- i - }(i) - } - <-ch - - c.Close() -} diff --git a/vendor/github.com/cactus/go-statsd-client/.travis.yml b/vendor/github.com/cactus/go-statsd-client/.travis.yml deleted file mode 100644 index c6419e6d2..000000000 --- a/vendor/github.com/cactus/go-statsd-client/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go -sudo: false -script: go test -v -cpu=1,2 ./... -go: - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - 1.8 - - 1.9 diff --git a/vendor/github.com/cactus/go-statsd-client/CHANGELOG.md b/vendor/github.com/cactus/go-statsd-client/CHANGELOG.md deleted file mode 100644 index e148762d7..000000000 --- a/vendor/github.com/cactus/go-statsd-client/CHANGELOG.md +++ /dev/null @@ -1,49 +0,0 @@ -Changelog -========= - -## head -* Fix leak on sender create with unresolvable destination (GH-34). - -## v3.1.0 2016-05-30 -* `NewClientWithSender(Sender, string) (Statter, error)` method added to - enable building a Client from a prefix and an already created Sender. -* Add stat recording sender in submodule statsdtest (GH-32). -* Add an example helper stat validation function. -* Change the way scope joins are done (GH-26). -* Reorder some structs to avoid middle padding. - -## 3.0.3 2016-02-18 -* make sampler function tunable (GH-24) - -## 3.0.2 2016-01-13 -* reduce memory allocations -* improve performance of buffered clients - -## 3.0.1 2016-01-01 -* documentation typo fixes -* fix possible race condition with `buffered_sender` send/close. - -## 3.0.0 2015-12-04 -* add substatter support - -## 2.0.2 2015-10-16 -* remove trailing newline in buffered sends to avoid etsy statsd log messages -* minor internal code reorganization for clarity (no api changes) - -## 2.0.1 2015-07-12 -* Add Set and SetInt funcs to support Sets -* Properly flush BufferedSender on close (bugfix) -* Add TimingDuration with support for sub-millisecond timing -* fewer allocations, better performance of BufferedClient - -## 2.0.0 2015-03-19 -* BufferedClient - send multiple stats at once -* clean up godocs -* clean up interfaces -- BREAKING CHANGE: for users who previously defined - types as *Client instead of the Statter interface type. - -## 1.0.1 2015-03-19 -* BufferedClient - send multiple stats at once - -## 1.0.0 2015-02-04 -* tag a version as fix for GH-8 diff --git a/vendor/github.com/cactus/go-statsd-client/LICENSE.md b/vendor/github.com/cactus/go-statsd-client/LICENSE.md deleted file mode 100644 index 56bee4f27..000000000 --- a/vendor/github.com/cactus/go-statsd-client/LICENSE.md +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2012-2016 Eli Janssen - -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/cactus/go-statsd-client/README.md b/vendor/github.com/cactus/go-statsd-client/README.md deleted file mode 100644 index f3064612e..000000000 --- a/vendor/github.com/cactus/go-statsd-client/README.md +++ /dev/null @@ -1,68 +0,0 @@ -go-statsd-client -================ - -[![Build Status](https://travis-ci.org/cactus/go-statsd-client.png?branch=master)](https://travis-ci.org/cactus/go-statsd-client) -[![GoDoc](https://godoc.org/github.com/cactus/go-statsd-client/statsd?status.png)](https://godoc.org/github.com/cactus/go-statsd-client/statsd) -[![Go Report Card](https://goreportcard.com/badge/cactus/go-statsd-client)](https://goreportcard.com/report/cactus/go-statsd-client) - - -## About - -A [StatsD][1] client for Go. - -## Docs - -Viewable online at [godoc.org][2]. - -## Example - -``` go -import ( - "log" - - "github.com/cactus/go-statsd-client/statsd" -) - -func main() { - // first create a client - // The basic client sends one stat per packet (for compatibility). - client, err := statsd.NewClient("127.0.0.1:8125", "test-client") - - // A buffered client, which sends multiple stats in one packet, is - // recommended when your server supports it (better performance). - // client, err := statsd.NewBufferedClient("127.0.0.1:8125", "test-client", 300*time.Millisecond, 0) - - // handle any errors - if err != nil { - log.Fatal(err) - } - // make sure to clean up - defer client.Close() - - // Send a stat - client.Inc("stat1", 42, 1.0) -} -``` - -See [docs][2] for more info. There is also some simple example code in the -`test-client` directory. - -## Contributors - -See [here][4]. - -## Alternative Implementations - -See the [statsd wiki][5] for some additional client implementations -(scroll down to the Go section). - -## License - -Released under the [MIT license][3]. See `LICENSE.md` file for details. - - -[1]: https://github.com/etsy/statsd -[2]: http://godoc.org/github.com/cactus/go-statsd-client/statsd -[3]: http://www.opensource.org/licenses/mit-license.php -[4]: https://github.com/cactus/go-statsd-client/graphs/contributors -[5]: https://github.com/etsy/statsd/wiki#client-implementations diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/bench_buffered_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/bench_buffered_test.go deleted file mode 100644 index aef26d7ca..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/bench_buffered_test.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "testing" - "time" -) - -func BenchmarkBufferedClientInc(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewBufferedClient(l.LocalAddr().String(), "test", 1*time.Second, 0) - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.Inc("benchinc", 1, 1) - } - }) -} - -func BenchmarkBufferedClientIncSample(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewBufferedClient(l.LocalAddr().String(), "test", 1*time.Second, 0) - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.Inc("benchinc", 1, 0.3) - } - }) -} - -func BenchmarkBufferedClientSetInt(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewBufferedClient(l.LocalAddr().String(), "test", 1*time.Second, 0) - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.SetInt("setint", 1, 1) - } - }) -} - -func BenchmarkBufferedClientSetIntSample(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewBufferedClient(l.LocalAddr().String(), "test", 1*time.Second, 0) - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.SetInt("setint", 1, 0.3) - } - }) -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/bench_client_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/bench_client_test.go deleted file mode 100644 index 186fae381..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/bench_client_test.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "testing" -) - -func BenchmarkClientInc(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewClient(l.LocalAddr().String(), "test") - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.Inc("benchinc", 1, 1) - } - }) -} - -func BenchmarkClientIncSample(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewClient(l.LocalAddr().String(), "test") - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.Inc("benchinc", 1, 0.3) - } - }) -} - -func BenchmarkClientSetInt(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewClient(l.LocalAddr().String(), "test") - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.SetInt("setint", 1, 1) - } - }) -} - -func BenchmarkClientSetIntSample(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - c, err := NewClient(l.LocalAddr().String(), "test") - if err != nil { - b.Fatal(err) - } - defer c.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - c.SetInt("setint", 1, 0.3) - } - }) -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/bench_sender_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/bench_sender_test.go deleted file mode 100644 index 5c07b9969..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/bench_sender_test.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "bytes" - "testing" - "time" -) - -func BenchmarkSenderSmall(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - s, err := NewSimpleSender(l.LocalAddr().String()) - if err != nil { - b.Fatal(err) - } - defer s.Close() - - data := []byte("test.gauge:1|g\n") - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - s.Send(data) - } - }) -} - -func BenchmarkSenderLarge(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - s, err := NewSimpleSender(l.LocalAddr().String()) - if err != nil { - b.Fatal(err) - } - defer s.Close() - - data := bytes.Repeat([]byte("test.gauge:1|g\n"), 50) - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - s.Send(data) - } - }) -} - -func BenchmarkBufferedSenderSmall(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - s, err := NewBufferedSender(l.LocalAddr().String(), 300*time.Millisecond, 1432) - if err != nil { - b.Fatal(err) - } - defer s.Close() - - data := []byte("test.gauge:1|g\n") - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - s.Send(data) - } - }) -} -func BenchmarkBufferedSenderLarge(b *testing.B) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - b.Fatal(err) - } - defer l.Close() - s, err := NewBufferedSender(l.LocalAddr().String(), 300*time.Millisecond, 1432) - if err != nil { - b.Fatal(err) - } - defer s.Close() - - data := bytes.Repeat([]byte("test.gauge:1|g\n"), 50) - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - //i := 0; i < b.N; i++ { - s.Send(data) - } - }) -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/buffer_pool.go b/vendor/github.com/cactus/go-statsd-client/statsd/buffer_pool.go deleted file mode 100644 index 2ffa05376..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/buffer_pool.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "bytes" - "sync" -) - -type bufferPool struct { - *sync.Pool -} - -func newBufferPool() *bufferPool { - return &bufferPool{ - &sync.Pool{New: func() interface{} { - return bytes.NewBuffer(make([]byte, 0, 1700)) - }}, - } -} - -func (bp *bufferPool) Get() *bytes.Buffer { - return (bp.Pool.Get()).(*bytes.Buffer) -} - -func (bp *bufferPool) Put(b *bytes.Buffer) { - b.Truncate(0) - bp.Pool.Put(b) -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/client.go b/vendor/github.com/cactus/go-statsd-client/statsd/client.go deleted file mode 100644 index 67c803b82..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/client.go +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "fmt" - "math/rand" - "strconv" - "strings" - "time" -) - -var bufPool = newBufferPool() - -// The StatSender interface wraps all the statsd metric methods -type StatSender interface { - Inc(string, int64, float32) error - Dec(string, int64, float32) error - Gauge(string, int64, float32) error - GaugeDelta(string, int64, float32) error - Timing(string, int64, float32) error - TimingDuration(string, time.Duration, float32) error - Set(string, string, float32) error - SetInt(string, int64, float32) error - Raw(string, string, float32) error -} - -// The Statter interface defines the behavior of a stat client -type Statter interface { - StatSender - NewSubStatter(string) SubStatter - SetPrefix(string) - Close() error -} - -// The SubStatter interface defines the behavior of a stat child/subclient -type SubStatter interface { - StatSender - SetSamplerFunc(SamplerFunc) - NewSubStatter(string) SubStatter -} - -// The SamplerFunc type defines a function that can serve -// as a Client sampler function. -type SamplerFunc func(float32) bool - -// DefaultSampler is the default rate sampler function -func DefaultSampler(rate float32) bool { - if rate < 1 { - if rand.Float32() < rate { - return true - } - return false - } - return true -} - -// A Client is a statsd client. -type Client struct { - // prefix for statsd name - prefix string - // packet sender - sender Sender - // sampler method - sampler SamplerFunc -} - -// Close closes the connection and cleans up. -func (s *Client) Close() error { - if s == nil { - return nil - } - - err := s.sender.Close() - return err -} - -// Inc increments a statsd count type. -// stat is a string name for the metric. -// value is the integer value -// rate is the sample rate (0.0 to 1.0) -func (s *Client) Inc(stat string, value int64, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - return s.submit(stat, "", value, "|c", rate) -} - -// Dec decrements a statsd count type. -// stat is a string name for the metric. -// value is the integer value. -// rate is the sample rate (0.0 to 1.0). -func (s *Client) Dec(stat string, value int64, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - return s.submit(stat, "", -value, "|c", rate) -} - -// Gauge submits/updates a statsd gauge type. -// stat is a string name for the metric. -// value is the integer value. -// rate is the sample rate (0.0 to 1.0). -func (s *Client) Gauge(stat string, value int64, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - return s.submit(stat, "", value, "|g", rate) -} - -// GaugeDelta submits a delta to a statsd gauge. -// stat is the string name for the metric. -// value is the (positive or negative) change. -// rate is the sample rate (0.0 to 1.0). -func (s *Client) GaugeDelta(stat string, value int64, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - // if negative, the submit formatter will prefix with a - already - // so only special case the positive value - if value >= 0 { - return s.submit(stat, "+", value, "|g", rate) - } - return s.submit(stat, "", value, "|g", rate) -} - -// Timing submits a statsd timing type. -// stat is a string name for the metric. -// delta is the time duration value in milliseconds -// rate is the sample rate (0.0 to 1.0). -func (s *Client) Timing(stat string, delta int64, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - return s.submit(stat, "", delta, "|ms", rate) -} - -// TimingDuration submits a statsd timing type. -// stat is a string name for the metric. -// delta is the timing value as time.Duration -// rate is the sample rate (0.0 to 1.0). -func (s *Client) TimingDuration(stat string, delta time.Duration, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - ms := float64(delta) / float64(time.Millisecond) - return s.submit(stat, "", ms, "|ms", rate) -} - -// Set submits a stats set type -// stat is a string name for the metric. -// value is the string value -// rate is the sample rate (0.0 to 1.0). -func (s *Client) Set(stat string, value string, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - return s.submit(stat, "", value, "|s", rate) -} - -// SetInt submits a number as a stats set type. -// stat is a string name for the metric. -// value is the integer value -// rate is the sample rate (0.0 to 1.0). -func (s *Client) SetInt(stat string, value int64, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - return s.submit(stat, "", value, "|s", rate) -} - -// Raw submits a preformatted value. -// stat is the string name for the metric. -// value is a preformatted "raw" value string. -// rate is the sample rate (0.0 to 1.0). -func (s *Client) Raw(stat string, value string, rate float32) error { - if !s.includeStat(rate) { - return nil - } - - return s.submit(stat, "", value, "", rate) -} - -// SetSamplerFunc sets a sampler function to something other than the default -// sampler is a function that determines whether the metric is -// to be accepted, or discarded. -// An example use case is for submitted pre-sampled metrics. -func (s *Client) SetSamplerFunc(sampler SamplerFunc) { - s.sampler = sampler -} - -// submit an already sampled raw stat -func (s *Client) submit(stat, vprefix string, value interface{}, suffix string, rate float32) error { - data := bufPool.Get() - defer bufPool.Put(data) - - if s.prefix != "" { - data.WriteString(s.prefix) - data.WriteString(".") - } - - data.WriteString(stat) - data.WriteString(":") - - if vprefix != "" { - data.WriteString(vprefix) - } - - // sadly, no way to jam this back into the bytes.Buffer without - // doing a few allocations... avoiding those is the whole point here... - // so from here on out just use it as a raw []byte - b := data.Bytes() - - switch v := value.(type) { - case string: - b = append(b, v...) - case int64: - b = strconv.AppendInt(b, v, 10) - case float64: - b = strconv.AppendFloat(b, v, 'f', -1, 64) - default: - return fmt.Errorf("No matching type format") - } - - if suffix != "" { - b = append(b, suffix...) - } - - if rate < 1 { - b = append(b, "|@"...) - b = strconv.AppendFloat(b, float64(rate), 'f', 6, 32) - } - - _, err := s.sender.Send(b) - return err -} - -// check for nil client, and perform sampling calculation -func (s *Client) includeStat(rate float32) bool { - if s == nil { - return false - } - - // test for nil in case someone builds their own - // client without calling new (result is nil sampler) - if s.sampler != nil { - return s.sampler(rate) - } - return DefaultSampler(rate) -} - -// SetPrefix sets/updates the statsd client prefix. -// Note: Does not change the prefix of any SubStatters. -func (s *Client) SetPrefix(prefix string) { - if s == nil { - return - } - - s.prefix = prefix -} - -// NewSubStatter returns a SubStatter with appended prefix -func (s *Client) NewSubStatter(prefix string) SubStatter { - var c *Client - if s != nil { - c = &Client{ - prefix: joinPathComp(s.prefix, prefix), - sender: s.sender, - sampler: s.sampler, - } - } - return c -} - -// NewClient returns a pointer to a new Client, and an error. -// -// addr is a string of the format "hostname:port", and must be parsable by -// net.ResolveUDPAddr. -// -// prefix is the statsd client prefix. Can be "" if no prefix is desired. -func NewClient(addr, prefix string) (Statter, error) { - sender, err := NewSimpleSender(addr) - if err != nil { - return nil, err - } - - return &Client{prefix: prefix, sender: sender}, nil -} - -// NewClientWithSender returns a pointer to a new Client and an error. -// -// sender is an instance of a statsd.Sender interface and may not be nil -// -// prefix is the stastd client prefix. Can be "" if no prefix is desired. -func NewClientWithSender(sender Sender, prefix string) (Statter, error) { - if sender == nil { - return nil, fmt.Errorf("Client sender may not be nil") - } - - return &Client{prefix: prefix, sender: sender}, nil -} - -// joinPathComp is a helper that ensures we combine path components with a dot -// when it's appropriate to do so; prefix is the existing prefix and suffix is -// the new component being added. -// -// It returns the joined prefix. -func joinPathComp(prefix, suffix string) string { - suffix = strings.TrimLeft(suffix, ".") - if prefix != "" && suffix != "" { - return prefix + "." + suffix - } - return prefix + suffix -} - -// Dial is a compatibility alias for NewClient -var Dial = NewClient - -// New is a compatibility alias for NewClient -var New = NewClient diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/client_buffered.go b/vendor/github.com/cactus/go-statsd-client/statsd/client_buffered.go deleted file mode 100644 index 960db3dc9..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/client_buffered.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import "time" - -// NewBufferedClient returns a new BufferedClient -// -// addr is a string of the format "hostname:port", and must be parsable by -// net.ResolveUDPAddr. -// -// prefix is the statsd client prefix. Can be "" if no prefix is desired. -// -// flushInterval is a time.Duration, and specifies the maximum interval for -// packet sending. Note that if you send lots of metrics, you will send more -// often. This is just a maximal threshold. -// -// If flushInterval is 0ms, defaults to 300ms. -// -// flushBytes specifies the maximum udp packet size you wish to send. If adding -// a metric would result in a larger packet than flushBytes, the packet will -// first be send, then the new data will be added to the next packet. -// -// If flushBytes is 0, defaults to 1432 bytes, which is considered safe -// for local traffic. If sending over the public internet, 512 bytes is -// the recommended value. -func NewBufferedClient(addr, prefix string, flushInterval time.Duration, flushBytes int) (Statter, error) { - if flushBytes <= 0 { - // https://github.com/etsy/statsd/blob/master/docs/metric_types.md#multi-metric-packets - flushBytes = 1432 - } - if flushInterval <= time.Duration(0) { - flushInterval = 300 * time.Millisecond - } - sender, err := NewBufferedSender(addr, flushInterval, flushBytes) - if err != nil { - return nil, err - } - - client := &Client{ - prefix: prefix, - sender: sender, - } - - return client, nil -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/client_buffered_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/client_buffered_test.go deleted file mode 100644 index bcf364747..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/client_buffered_test.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "bytes" - "fmt" - "log" - "reflect" - "strings" - "testing" - "time" -) - -func TestBufferedClientFlushSize(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - - for _, tt := range statsdPacketTests { - // set flush length to the size of the expected output packet - // so we can ensure a flush happens right away. - // set flush time sufficiently high so that it never matters for this - // test - c, err := NewBufferedClient(l.LocalAddr().String(), tt.Prefix, 10*time.Second, len(tt.Expected)+1) - if err != nil { - c.Close() - t.Fatal(err) - } - method := reflect.ValueOf(c).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - c.Close() - t.Fatal(errInter.(error)) - } - - data := make([]byte, len(tt.Expected)+16) - _, _, err = l.ReadFrom(data) - if err != nil { - c.Close() - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00\n") - if bytes.Equal(data, []byte(tt.Expected)) != true { - t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected) - } - c.Close() - } -} - -func TestBufferedClientFlushTime(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - - for _, tt := range statsdPacketTests { - // set flush length to the size of the expected output packet - // so we can ensure a flush happens right away. - // set flush time sufficiently high so that it never matters for this - // test - c, err := NewBufferedClient(l.LocalAddr().String(), tt.Prefix, 1*time.Microsecond, 1024) - if err != nil { - c.Close() - t.Fatal(err) - } - method := reflect.ValueOf(c).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - c.Close() - t.Fatal(errInter.(error)) - } - - time.Sleep(1 * time.Millisecond) - - data := make([]byte, len(tt.Expected)+16) - _, _, err = l.ReadFrom(data) - if err != nil { - c.Close() - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00\n") - if bytes.Equal(data, []byte(tt.Expected)) != true { - t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected) - } - c.Close() - } -} - -func TestBufferedClientBigPacket(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - - c, err := NewBufferedClient(l.LocalAddr().String(), "test", 10*time.Millisecond, 1024) - if err != nil { - t.Fatal(err) - } - defer c.Close() - - for _, tt := range statsdPacketTests { - if tt.Prefix != "test" { - continue - } - method := reflect.ValueOf(c).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - } - - expected := "" - for _, tt := range statsdPacketTests { - if tt.Prefix != "test" { - continue - } - expected = expected + tt.Expected + "\n" - } - - expected = strings.TrimSuffix(expected, "\n") - - time.Sleep(12 * time.Millisecond) - data := make([]byte, 1024) - _, _, err = l.ReadFrom(data) - if err != nil { - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00") - if bytes.Equal(data, []byte(expected)) != true { - t.Fatalf("got '%s' expected '%s'", data, expected) - } -} - -func TestFlushOnClose(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - - c, err := NewBufferedClient(l.LocalAddr().String(), "test", 1*time.Second, 1024) - if err != nil { - t.Fatal(err) - } - - c.Inc("count", int64(1), 1.0) - c.Close() - - expected := "test.count:1|c" - - data := make([]byte, 1024) - _, _, err = l.ReadFrom(data) - if err != nil { - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00") - if bytes.Equal(data, []byte(expected)) != true { - fmt.Println(data) - fmt.Println([]byte(expected)) - t.Fatalf("got '%s' expected '%s'", data, expected) - } -} - -func ExampleClient_buffered() { - // first create a client - client, err := NewBufferedClient("127.0.0.1:8125", "test-client", 10*time.Millisecond, 0) - // handle any errors - if err != nil { - log.Fatal(err) - } - // make sure to clean up - defer client.Close() - - // Send a stat - err = client.Inc("stat1", 42, 1.0) - // handle any errors - if err != nil { - log.Printf("Error sending metric: %+v", err) - } -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/client_noop.go b/vendor/github.com/cactus/go-statsd-client/statsd/client_noop.go deleted file mode 100644 index 1bdde0882..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/client_noop.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import "time" - -// A NoopClient is a client that does nothing. -type NoopClient struct{} - -// Close closes the connection and cleans up. -func (s *NoopClient) Close() error { - return nil -} - -// Inc increments a statsd count type. -// stat is a string name for the metric. -// value is the integer value -// rate is the sample rate (0.0 to 1.0) -func (s *NoopClient) Inc(stat string, value int64, rate float32) error { - return nil -} - -// Dec decrements a statsd count type. -// stat is a string name for the metric. -// value is the integer value. -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) Dec(stat string, value int64, rate float32) error { - return nil -} - -// Gauge submits/Updates a statsd gauge type. -// stat is a string name for the metric. -// value is the integer value. -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) Gauge(stat string, value int64, rate float32) error { - return nil -} - -// GaugeDelta submits a delta to a statsd gauge. -// stat is the string name for the metric. -// value is the (positive or negative) change. -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) GaugeDelta(stat string, value int64, rate float32) error { - return nil -} - -// Timing submits a statsd timing type. -// stat is a string name for the metric. -// delta is the time duration value in milliseconds -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) Timing(stat string, delta int64, rate float32) error { - return nil -} - -// TimingDuration submits a statsd timing type. -// stat is a string name for the metric. -// delta is the timing value as time.Duration -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) TimingDuration(stat string, delta time.Duration, rate float32) error { - return nil -} - -// Set submits a stats set type. -// stat is a string name for the metric. -// value is the string value -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) Set(stat string, value string, rate float32) error { - return nil -} - -// SetInt submits a number as a stats set type. -// convenience method for Set with number. -// stat is a string name for the metric. -// value is the integer value -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) SetInt(stat string, value int64, rate float32) error { - return nil -} - -// Raw formats the statsd event data, handles sampling, prepares it, -// and sends it to the server. -// stat is the string name for the metric. -// value is the preformatted "raw" value string. -// rate is the sample rate (0.0 to 1.0). -func (s *NoopClient) Raw(stat string, value string, rate float32) error { - return nil -} - -// SetPrefix sets/updates the statsd client prefix -func (s *NoopClient) SetPrefix(prefix string) {} - -// NewSubStatter returns a SubStatter with appended prefix -func (s *NoopClient) NewSubStatter(prefix string) SubStatter { - return &NoopClient{} -} - -// SetSamplerFunc sets the sampler function -func (s *NoopClient) SetSamplerFunc(sampler SamplerFunc) {} - -// NewNoopClient returns a pointer to a new NoopClient, and an error (always -// nil, just supplied to support api convention). -// Use variadic arguments to support identical format as NewClient, or a more -// conventional no argument form. -func NewNoopClient(a ...interface{}) (Statter, error) { - return &NoopClient{}, nil -} - -// NewNoop is a compatibility alias for NewNoopClient -var NewNoop = NewNoopClient diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/client_substatter_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/client_substatter_test.go deleted file mode 100644 index 81919f3d8..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/client_substatter_test.go +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "bytes" - "log" - "reflect" - "strings" - "testing" - "time" -) - -var statsdSubStatterPacketTests = []struct { - Prefix string - SubPrefix string - Method string - Stat string - Value interface{} - Rate float32 - Expected string -}{ - {"test", "sub", "Gauge", "gauge", int64(1), 1.0, "test.sub.gauge:1|g"}, - {"test", "sub", "Inc", "count", int64(1), 0.999999, "test.sub.count:1|c|@0.999999"}, - {"test", "sub", "Inc", "count", int64(1), 1.0, "test.sub.count:1|c"}, - {"test", "sub", "Dec", "count", int64(1), 1.0, "test.sub.count:-1|c"}, - {"test", "sub", "Timing", "timing", int64(1), 1.0, "test.sub.timing:1|ms"}, - {"test", "sub", "TimingDuration", "timing", 1500 * time.Microsecond, 1.0, "test.sub.timing:1.5|ms"}, - {"test", "sub", "TimingDuration", "timing", 3 * time.Microsecond, 1.0, "test.sub.timing:0.003|ms"}, - {"test", "sub", "Set", "strset", "pickle", 1.0, "test.sub.strset:pickle|s"}, - {"test", "sub", "SetInt", "intset", int64(1), 1.0, "test.sub.intset:1|s"}, - {"test", "sub", "GaugeDelta", "gauge", int64(1), 1.0, "test.sub.gauge:+1|g"}, - {"test", "sub", "GaugeDelta", "gauge", int64(-1), 1.0, "test.sub.gauge:-1|g"}, - // empty sub prefix -- note: not used in subsub tests - {"test", "", "Inc", "count", int64(1), 1.0, "test.count:1|c"}, - // empty base prefix - {"", "sub", "Inc", "count", int64(1), 1.0, "sub.count:1|c"}, -} - -func TestSubStatterClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdSubStatterPacketTests { - c, err := NewClient(l.LocalAddr().String(), tt.Prefix) - if err != nil { - t.Fatal(err) - } - s := c.NewSubStatter(tt.SubPrefix) - method := reflect.ValueOf(s).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - _, _, err = l.ReadFrom(data) - if err != nil { - c.Close() - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00") - if bytes.Equal(data, []byte(tt.Expected)) != true { - c.Close() - t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected) - } - c.Close() - } -} - -func TestMultSubStatterClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdSubStatterPacketTests { - // ignore empty sub test for this, as there is nothing to regex sub - if tt.SubPrefix == "" { - continue - } - c, err := NewClient(l.LocalAddr().String(), tt.Prefix) - if err != nil { - t.Fatal(err) - } - s1 := c.NewSubStatter("sub1") - s2 := c.NewSubStatter("sub2") - - responses := [][]byte{} - for _, s := range []SubStatter{s1, s2} { - method := reflect.ValueOf(s).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - _, _, err = l.ReadFrom(data) - if err != nil { - c.Close() - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00") - responses = append(responses, data) - } - - expected := strings.Replace(tt.Expected, "sub.", "sub1.", -1) - if bytes.Equal(responses[0], []byte(expected)) != true { - c.Close() - t.Fatalf("%s got '%s' expected '%s'", - tt.Method, responses[0], tt.Expected) - } - - expected = strings.Replace(tt.Expected, "sub.", "sub2.", -1) - if bytes.Equal(responses[1], []byte(expected)) != true { - c.Close() - t.Fatalf("%s got '%s' expected '%s'", - tt.Method, responses[1], tt.Expected) - } - c.Close() - } -} - -func TestSubSubStatterClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdSubStatterPacketTests { - // ignore empty sub test for this, as there is nothing to regex sub - if tt.SubPrefix == "" { - continue - } - c, err := NewClient(l.LocalAddr().String(), tt.Prefix) - if err != nil { - t.Fatal(err) - } - s := c.NewSubStatter(tt.SubPrefix).NewSubStatter("sub2") - - method := reflect.ValueOf(s).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - _, _, err = l.ReadFrom(data) - if err != nil { - c.Close() - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00") - expected := strings.Replace(tt.Expected, "sub.", "sub.sub2.", -1) - if bytes.Equal(data, []byte(expected)) != true { - c.Close() - t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected) - } - c.Close() - } -} - -func TestSubStatterClosedClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdSubStatterPacketTests { - c, err := NewClient(l.LocalAddr().String(), tt.Prefix) - if err != nil { - t.Fatal(err) - } - c.Close() - s := c.NewSubStatter(tt.SubPrefix) - method := reflect.ValueOf(s).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter == nil { - t.Fatal("Expected error but got none") - } - } -} - -func TestNilSubStatterClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - - for _, tt := range statsdSubStatterPacketTests { - var c *Client - s := c.NewSubStatter(tt.SubPrefix) - - method := reflect.ValueOf(s).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - n, _, err := l.ReadFrom(data) - // this is expected to error, since there should - // be no udp data sent, so the read will time out - if err == nil || n != 0 { - c.Close() - t.Fatal(err) - } - c.Close() - } -} - -func TestNoopSubStatterClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdSubStatterPacketTests { - c, err := NewNoopClient(l.LocalAddr().String(), tt.Prefix) - if err != nil { - t.Fatal(err) - } - s := c.NewSubStatter(tt.SubPrefix) - method := reflect.ValueOf(s).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - n, _, err := l.ReadFrom(data) - // this is expected to error, since there should - // be no udp data sent, so the read will time out - if err == nil || n != 0 { - c.Close() - t.Fatal(err) - } - c.Close() - } -} - -func ExampleClient_substatter() { - // first create a client - client, err := NewClient("127.0.0.1:8125", "test-client") - // handle any errors - if err != nil { - log.Fatal(err) - } - // make sure to clean up - defer client.Close() - - // create a substatter - subclient := client.NewSubStatter("sub") - // send a stat - err = subclient.Inc("stat1", 42, 1.0) - // handle any errors - if err != nil { - log.Printf("Error sending metric: %+v", err) - } -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/client_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/client_test.go deleted file mode 100644 index 98355c538..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/client_test.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "bytes" - "log" - "net" - "reflect" - "testing" - "time" -) - -var statsdPacketTests = []struct { - Prefix string - Method string - Stat string - Value interface{} - Rate float32 - Expected string -}{ - {"test", "Gauge", "gauge", int64(1), 1.0, "test.gauge:1|g"}, - {"test", "Inc", "count", int64(1), 0.999999, "test.count:1|c|@0.999999"}, - {"test", "Inc", "count", int64(1), 1.0, "test.count:1|c"}, - {"test", "Dec", "count", int64(1), 1.0, "test.count:-1|c"}, - {"test", "Timing", "timing", int64(1), 1.0, "test.timing:1|ms"}, - {"test", "TimingDuration", "timing", 1500 * time.Microsecond, 1.0, "test.timing:1.5|ms"}, - {"test", "TimingDuration", "timing", 3 * time.Microsecond, 1.0, "test.timing:0.003|ms"}, - {"test", "Set", "strset", "pickle", 1.0, "test.strset:pickle|s"}, - {"test", "SetInt", "intset", int64(1), 1.0, "test.intset:1|s"}, - {"test", "GaugeDelta", "gauge", int64(1), 1.0, "test.gauge:+1|g"}, - {"test", "GaugeDelta", "gauge", int64(-1), 1.0, "test.gauge:-1|g"}, - - {"", "Gauge", "gauge", int64(1), 1.0, "gauge:1|g"}, - {"", "Inc", "count", int64(1), 0.999999, "count:1|c|@0.999999"}, - {"", "Inc", "count", int64(1), 1.0, "count:1|c"}, - {"", "Dec", "count", int64(1), 1.0, "count:-1|c"}, - {"", "Timing", "timing", int64(1), 1.0, "timing:1|ms"}, - {"", "TimingDuration", "timing", 1500 * time.Microsecond, 1.0, "timing:1.5|ms"}, - {"", "Set", "strset", "pickle", 1.0, "strset:pickle|s"}, - {"", "SetInt", "intset", int64(1), 1.0, "intset:1|s"}, - {"", "GaugeDelta", "gauge", int64(1), 1.0, "gauge:+1|g"}, - {"", "GaugeDelta", "gauge", int64(-1), 1.0, "gauge:-1|g"}, -} - -func TestClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdPacketTests { - c, err := NewClient(l.LocalAddr().String(), tt.Prefix) - if err != nil { - t.Fatal(err) - } - method := reflect.ValueOf(c).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - _, _, err = l.ReadFrom(data) - if err != nil { - c.Close() - t.Fatal(err) - } - - data = bytes.TrimRight(data, "\x00") - if bytes.Equal(data, []byte(tt.Expected)) != true { - c.Close() - t.Fatalf("%s got '%s' expected '%s'", tt.Method, data, tt.Expected) - } - c.Close() - } -} - -func TestNilClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdPacketTests { - var c *Client - - method := reflect.ValueOf(c).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - n, _, err := l.ReadFrom(data) - // this is expected to error, since there should - // be no udp data sent, so the read will time out - if err == nil || n != 0 { - c.Close() - t.Fatal(err) - } - c.Close() - } -} - -func TestNoopClient(t *testing.T) { - l, err := newUDPListener("127.0.0.1:0") - if err != nil { - t.Fatal(err) - } - defer l.Close() - for _, tt := range statsdPacketTests { - c, err := NewNoopClient(l.LocalAddr().String(), tt.Prefix) - if err != nil { - t.Fatal(err) - } - method := reflect.ValueOf(c).MethodByName(tt.Method) - e := method.Call([]reflect.Value{ - reflect.ValueOf(tt.Stat), - reflect.ValueOf(tt.Value), - reflect.ValueOf(tt.Rate)})[0] - errInter := e.Interface() - if errInter != nil { - t.Fatal(errInter.(error)) - } - - data := make([]byte, 128) - n, _, err := l.ReadFrom(data) - // this is expected to error, since there should - // be no udp data sent, so the read will time out - if err == nil || n != 0 { - c.Close() - t.Fatal(err) - } - c.Close() - } -} - -func newUDPListener(addr string) (*net.UDPConn, error) { - l, err := net.ListenPacket("udp", addr) - if err != nil { - return nil, err - } - l.SetDeadline(time.Now().Add(100 * time.Millisecond)) - l.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) - l.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) - return l.(*net.UDPConn), nil -} - -func ExampleClient() { - // first create a client - client, err := NewClient("127.0.0.1:8125", "test-client") - // handle any errors - if err != nil { - log.Fatal(err) - } - // make sure to clean up - defer client.Close() - - // Send a stat - err = client.Inc("stat1", 42, 1.0) - // handle any errors - if err != nil { - log.Printf("Error sending metric: %+v", err) - } -} - -func ExampleClient_noop() { - // use interface so we can sub noop client if needed - var client Statter - var err error - - // first try to create a real client - client, err = NewClient("not-resolvable:8125", "test-client") - // Let us say real client creation fails, but you don't care enough about - // stats that you don't want your program to run. Just log an error and - // make a NoopClient instead - if err != nil { - log.Println("Remote endpoint did not resolve. Disabling stats", err) - client, err = NewNoopClient() - } - // make sure to clean up - defer client.Close() - - // Send a stat - err = client.Inc("stat1", 42, 1.0) - // handle any errors - if err != nil { - log.Printf("Error sending metric: %+v", err) - } -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/doc.go b/vendor/github.com/cactus/go-statsd-client/statsd/doc.go deleted file mode 100644 index e9e0e577c..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/doc.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -/* -Package statsd provides a StatsD client implementation that is safe for -concurrent use by multiple goroutines and for efficiency can be created and -reused. - -Example usage: - - // first create a client - client, err := statsd.NewClient("127.0.0.1:8125", "test-client") - // handle any errors - if err != nil { - log.Fatal(err) - } - // make sure to clean up - defer client.Close() - - // Send a stat - err = client.Inc("stat1", 42, 1.0) - // handle any errors - if err != nil { - log.Printf("Error sending metric: %+v", err) - } - -*/ -package statsd diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/sender.go b/vendor/github.com/cactus/go-statsd-client/statsd/sender.go deleted file mode 100644 index d4f4cb599..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/sender.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "errors" - "net" -) - -// The Sender interface wraps a Send and Close -type Sender interface { - Send(data []byte) (int, error) - Close() error -} - -// SimpleSender provides a socket send interface. -type SimpleSender struct { - // underlying connection - c net.PacketConn - // resolved udp address - ra *net.UDPAddr -} - -// Send sends the data to the server endpoint. -func (s *SimpleSender) Send(data []byte) (int, error) { - // no need for locking here, as the underlying fdNet - // already serialized writes - n, err := s.c.(*net.UDPConn).WriteToUDP(data, s.ra) - if err != nil { - return 0, err - } - if n == 0 { - return n, errors.New("Wrote no bytes") - } - return n, nil -} - -// Close closes the SimpleSender -func (s *SimpleSender) Close() error { - err := s.c.Close() - return err -} - -// NewSimpleSender returns a new SimpleSender for sending to the supplied -// addresss. -// -// addr is a string of the format "hostname:port", and must be parsable by -// net.ResolveUDPAddr. -func NewSimpleSender(addr string) (Sender, error) { - c, err := net.ListenPacket("udp", ":0") - if err != nil { - return nil, err - } - - ra, err := net.ResolveUDPAddr("udp", addr) - if err != nil { - c.Close() - return nil, err - } - - sender := &SimpleSender{ - c: c, - ra: ra, - } - - return sender, nil -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/sender_buffered.go b/vendor/github.com/cactus/go-statsd-client/statsd/sender_buffered.go deleted file mode 100644 index b2e386e1c..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/sender_buffered.go +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "bytes" - "fmt" - "sync" - "time" -) - -var senderPool = newBufferPool() - -// BufferedSender provides a buffered statsd udp, sending multiple -// metrics, where possible. -type BufferedSender struct { - sender Sender - flushBytes int - flushInterval time.Duration - // buffers - bufmx sync.Mutex - buffer *bytes.Buffer - bufs chan *bytes.Buffer - // lifecycle - runmx sync.RWMutex - shutdown chan chan error - running bool -} - -// Send bytes. -func (s *BufferedSender) Send(data []byte) (int, error) { - s.runmx.RLock() - if !s.running { - s.runmx.RUnlock() - return 0, fmt.Errorf("BufferedSender is not running") - } - - s.withBufferLock(func() { - blen := s.buffer.Len() - if blen > 0 && blen+len(data)+1 >= s.flushBytes { - s.swapnqueue() - } - - s.buffer.Write(data) - s.buffer.WriteByte('\n') - - if s.buffer.Len() >= s.flushBytes { - s.swapnqueue() - } - }) - s.runmx.RUnlock() - return len(data), nil -} - -// Close Buffered Sender -func (s *BufferedSender) Close() error { - // since we are running, write lock during cleanup - s.runmx.Lock() - defer s.runmx.Unlock() - if !s.running { - return nil - } - - errChan := make(chan error) - s.running = false - s.shutdown <- errChan - return <-errChan -} - -// Start Buffered Sender -// Begins ticker and read loop -func (s *BufferedSender) Start() { - // write lock to start running - s.runmx.Lock() - defer s.runmx.Unlock() - if s.running { - return - } - - s.running = true - s.bufs = make(chan *bytes.Buffer, 32) - go s.run() -} - -func (s *BufferedSender) withBufferLock(fn func()) { - s.bufmx.Lock() - fn() - s.bufmx.Unlock() -} - -func (s *BufferedSender) swapnqueue() { - if s.buffer.Len() == 0 { - return - } - ob := s.buffer - nb := senderPool.Get() - s.buffer = nb - s.bufs <- ob -} - -func (s *BufferedSender) run() { - ticker := time.NewTicker(s.flushInterval) - defer ticker.Stop() - - doneChan := make(chan bool) - go func() { - for buf := range s.bufs { - s.flush(buf) - senderPool.Put(buf) - } - doneChan <- true - }() - - for { - select { - case <-ticker.C: - s.withBufferLock(func() { - s.swapnqueue() - }) - case errChan := <-s.shutdown: - s.withBufferLock(func() { - s.swapnqueue() - }) - close(s.bufs) - <-doneChan - errChan <- s.sender.Close() - return - } - } -} - -// send to remove endpoint and truncate buffer -func (s *BufferedSender) flush(b *bytes.Buffer) (int, error) { - bb := b.Bytes() - bbl := len(bb) - if bb[bbl-1] == '\n' { - bb = bb[:bbl-1] - } - //n, err := s.sender.Send(bytes.TrimSuffix(b.Bytes(), []byte("\n"))) - n, err := s.sender.Send(bb) - b.Truncate(0) // clear the buffer - return n, err -} - -// NewBufferedSender returns a new BufferedSender -// -// addr is a string of the format "hostname:port", and must be parsable by -// net.ResolveUDPAddr. -// -// flushInterval is a time.Duration, and specifies the maximum interval for -// packet sending. Note that if you send lots of metrics, you will send more -// often. This is just a maximal threshold. -// -// flushBytes specifies the maximum udp packet size you wish to send. If adding -// a metric would result in a larger packet than flushBytes, the packet will -// first be send, then the new data will be added to the next packet. -func NewBufferedSender(addr string, flushInterval time.Duration, flushBytes int) (Sender, error) { - simpleSender, err := NewSimpleSender(addr) - if err != nil { - return nil, err - } - - sender := &BufferedSender{ - flushBytes: flushBytes, - flushInterval: flushInterval, - sender: simpleSender, - buffer: senderPool.Get(), - shutdown: make(chan chan error), - } - - sender.Start() - return sender, nil -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/sender_buffered_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/sender_buffered_test.go deleted file mode 100644 index 023223d16..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/sender_buffered_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "bytes" - "testing" - "time" -) - -type mockSender struct { - closeCallCount int -} - -func (m *mockSender) Send(data []byte) (int, error) { - return 0, nil -} - -func (m *mockSender) Close() error { - m.closeCallCount++ - return nil -} - -func TestClose(t *testing.T) { - mockSender := &mockSender{} - sender := &BufferedSender{ - flushBytes: 512, - flushInterval: 1 * time.Second, - sender: mockSender, - buffer: bytes.NewBuffer(make([]byte, 0, 512)), - shutdown: make(chan chan error), - } - - sender.Close() - if mockSender.closeCallCount != 0 { - t.Fatalf("expected close to have been called zero times, but got %d", mockSender.closeCallCount) - } - - sender.Start() - if !sender.running { - t.Fatal("sender failed to start") - } - - sender.Close() - if mockSender.closeCallCount != 1 { - t.Fatalf("expected close to have been called once, but got %d", mockSender.closeCallCount) - } -} - -func TestCloseConcurrent(t *testing.T) { - mockSender := &mockSender{} - sender := &BufferedSender{ - flushBytes: 512, - flushInterval: 1 * time.Second, - sender: mockSender, - buffer: bytes.NewBuffer(make([]byte, 0, 512)), - shutdown: make(chan chan error), - } - sender.Start() - - const N = 10 - c := make(chan struct{}, N) - for i := 0; i < N; i++ { - go func() { - sender.Close() - c <- struct{}{} - }() - } - - for i := 0; i < N; i++ { - <-c - } - - if mockSender.closeCallCount != 1 { - t.Errorf("expected close to have been called once, but got %d", mockSender.closeCallCount) - } -} - -func TestCloseDuringSendConcurrent(t *testing.T) { - mockSender := &mockSender{} - sender := &BufferedSender{ - flushBytes: 512, - flushInterval: 1 * time.Second, - sender: mockSender, - buffer: bytes.NewBuffer(make([]byte, 0, 512)), - shutdown: make(chan chan error), - } - sender.Start() - - const N = 10 - c := make(chan struct{}, N) - for i := 0; i < N; i++ { - go func() { - for { - _, err := sender.Send([]byte("stat:1|c")) - if err != nil { - c <- struct{}{} - return - } - } - }() - } - - // senders should error out now - // we should not receive any panics - sender.Close() - for i := 0; i < N; i++ { - <-c - } - - if mockSender.closeCallCount != 1 { - t.Errorf("expected close to have been called once, but got %d", mockSender.closeCallCount) - } -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/recorder.go b/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/recorder.go deleted file mode 100644 index 48846f5cf..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/recorder.go +++ /dev/null @@ -1,81 +0,0 @@ -package statsdtest - -import ( - "errors" - "sync" -) - -// RecordingSender implements statsd.Sender but parses individual Stats into a -// buffer that can be later inspected instead of sending to some server. It -// should constructed with NewRecordingSender(). -type RecordingSender struct { - m sync.Mutex - buffer Stats - closed bool -} - -// NewRecordingSender creates a new RecordingSender for use by a statsd.Client. -func NewRecordingSender() *RecordingSender { - rs := &RecordingSender{} - rs.buffer = make(Stats, 0) - return rs -} - -// GetSent returns the stats that have been sent. Locks and copies the current -// state of the sent Stats. -// -// The entire buffer of Stat objects (including Stat.Raw is copied). -func (rs *RecordingSender) GetSent() Stats { - rs.m.Lock() - defer rs.m.Unlock() - - results := make(Stats, len(rs.buffer)) - for i, e := range rs.buffer { - results[i] = e - results[i].Raw = make([]byte, len(e.Raw)) - for j, b := range e.Raw { - results[i].Raw[j] = b - } - } - - return results -} - -// ClearSent locks the sender and clears any Stats that have been recorded. -func (rs *RecordingSender) ClearSent() { - rs.m.Lock() - defer rs.m.Unlock() - - rs.buffer = rs.buffer[:0] -} - -// Send parses the provided []byte into stat objects and then appends these to -// the buffer of sent stats. Buffer operations are synchronized so it is safe -// to call this from multiple goroutines (though contenion will impact -// performance so don't use this during a benchmark). Send treats '\n' as a -// delimiter between multiple sats in the same []byte. -// -// Calling after the Sender has been closed will return an error (and not -// mutate the buffer). -func (rs *RecordingSender) Send(data []byte) (int, error) { - sent := ParseStats(data) - - rs.m.Lock() - defer rs.m.Unlock() - if rs.closed { - return 0, errors.New("writing to a closed sender") - } - - rs.buffer = append(rs.buffer, sent...) - return len(data), nil -} - -// Close marks this sender as closed. Subsequent attempts to Send stats will -// result in an error. -func (rs *RecordingSender) Close() error { - rs.m.Lock() - defer rs.m.Unlock() - - rs.closed = true - return nil -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/recorder_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/recorder_test.go deleted file mode 100644 index 834492e9d..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/recorder_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package statsdtest - -import ( - "fmt" - "reflect" - "strconv" - "testing" - "time" - - "github.com/cactus/go-statsd-client/statsd" -) - -func TestRecordingSenderIsSender(t *testing.T) { - // This ensures that if the Sender interface changes in the future we'll get - // compile time failures should the RecordingSender not be updated to meet - // the new definition. This keeps changes from inadvertently breaking tests - // of folks that use go-statsd-client. - var _ statsd.Sender = NewRecordingSender() -} - -func TestRecordingSender(t *testing.T) { - start := time.Now() - rs := new(RecordingSender) - statter, err := statsd.NewClientWithSender(rs, "test") - if err != nil { - t.Errorf("failed to construct client") - return - } - - statter.Inc("stat", 4444, 1.0) - statter.Dec("stat", 5555, 1.0) - statter.Set("set-stat", "some string", 1.0) - - d := time.Since(start) - statter.TimingDuration("timing", d, 1.0) - - sent := rs.GetSent() - if len(sent) != 4 { - // just dive out because everything else relies on ordering - t.Fatalf("Did not capture all stats sent; got: %s", sent) - } - - ms := float64(d) / float64(time.Millisecond) - // somewhat fragile in that it assums float rendering within client *shrug* - msStr := string(strconv.AppendFloat([]byte(""), ms, 'f', -1, 64)) - - expected := Stats{ - {[]byte("test.stat:4444|c"), "test.stat", "4444", "c", "", true}, - {[]byte("test.stat:-5555|c"), "test.stat", "-5555", "c", "", true}, - {[]byte("test.set-stat:some string|s"), "test.set-stat", "some string", "s", "", true}, - {[]byte(fmt.Sprintf("test.timing:%s|ms", msStr)), "test.timing", msStr, "ms", "", true}, - } - - if !reflect.DeepEqual(sent, expected) { - t.Errorf("got: %s, want: %s", sent, expected) - } -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/stat.go b/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/stat.go deleted file mode 100644 index a05cef3ba..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/stat.go +++ /dev/null @@ -1,140 +0,0 @@ -package statsdtest - -import ( - "bytes" - "fmt" - "strings" -) - -// Stat contains the raw and extracted stat information from a stat that was -// sent by the RecordingSender. Raw will always have the content that was -// consumed for this specific stat and Parsed will be set if no errors were hit -// pulling information out of it. -type Stat struct { - Raw []byte - Stat string - Value string - Tag string - Rate string - Parsed bool -} - -// String fulfils the stringer interface -func (s *Stat) String() string { - return fmt.Sprintf("%s %s %s", s.Stat, s.Value, s.Rate) -} - -// ParseStats takes a sequence of bytes destined for a Statsd server and parses -// it out into one or more Stat structs. Each struct includes both the raw -// bytes (copied, so the src []byte may be reused if desired) as well as each -// component it was able to parse out. If parsing was incomplete Stat.Parsed -// will be set to false but no error is returned / kept. -func ParseStats(src []byte) Stats { - d := make([]byte, len(src)) - for i, b := range src { - d[i] = b - } - // standard protocol indicates one stat per line - entries := bytes.Split(d, []byte{'\n'}) - - result := make(Stats, len(entries)) - - for i, e := range entries { - result[i] = Stat{Raw: e} - ss := &result[i] - - // : deliniates the stat name from the stat data - marker := bytes.IndexByte(e, ':') - if marker == -1 { - continue - } - ss.Stat = string(e[0:marker]) - - // stat data folows ':' with the form {value}|{type tag}[|@{sample rate}] - e = e[marker+1:] - marker = bytes.IndexByte(e, '|') - if marker == -1 { - continue - } - - ss.Value = string(e[:marker]) - - e = e[marker+1:] - marker = bytes.IndexByte(e, '|') - if marker == -1 { - // no sample rate - ss.Tag = string(e) - } else { - ss.Tag = string(e[:marker]) - e = e[marker+1:] - if len(e) == 0 || e[0] != '@' { - // sample rate should be prefixed with '@'; bail otherwise - continue - } - ss.Rate = string(e[1:]) - } - - ss.Parsed = true - } - - return result -} - -// Stats is a slice of Stat -type Stats []Stat - -// Unparsed returns any stats that were unable to be completely parsed. -func (s Stats) Unparsed() Stats { - var r Stats - for _, e := range s { - if !e.Parsed { - r = append(r, e) - } - } - - return r -} - -// CollectNamed returns all data sent for a given stat name. -func (s Stats) CollectNamed(statName string) Stats { - return s.Collect(func(e Stat) bool { - return e.Stat == statName - }) -} - -// Collect gathers all stats that make some predicate true. -func (s Stats) Collect(pred func(Stat) bool) Stats { - var r Stats - for _, e := range s { - if pred(e) { - r = append(r, e) - } - } - return r -} - -// Values returns the values associated with this Stats object. -func (s Stats) Values() []string { - if len(s) == 0 { - return nil - } - - r := make([]string, len(s)) - for i, e := range s { - r[i] = e.Value - } - return r -} - -// String fulfils the stringer interface -func (s Stats) String() string { - if len(s) == 0 { - return "" - } - - r := make([]string, len(s)) - for i, e := range s { - r[i] = e.String() - } - return strings.Join(r, "\n") -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/stat_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/stat_test.go deleted file mode 100644 index 33fe499e9..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/statsdtest/stat_test.go +++ /dev/null @@ -1,154 +0,0 @@ -package statsdtest - -import ( - "bytes" - "reflect" - "testing" -) - -type parsingTestCase struct { - name string - sent [][]byte - expected Stats -} - -var ( - badStatNameOnly = []byte("foo.bar.baz:") - bsnoStat = Stat{ - Raw: badStatNameOnly, - Stat: "foo.bar.baz", - Parsed: false, - } - - gaugeWithoutRate = []byte("foo.bar.baz:1.000|g") - gworStat = Stat{ - Raw: gaugeWithoutRate, - Stat: "foo.bar.baz", - Value: "1.000", - Tag: "g", - Parsed: true, - } - - counterWithRate = []byte("foo.bar.baz:1.000|c|@0.75") - cwrStat = Stat{ - Raw: counterWithRate, - Stat: "foo.bar.baz", - Value: "1.000", - Tag: "c", - Rate: "0.75", - Parsed: true, - } - - stringStat = []byte(":some string value|s") - sStat = Stat{ - Raw: stringStat, - Stat: "", - Value: "some string value", - Tag: "s", - Parsed: true, - } - - badValue = []byte("asoentuh") - bvStat = Stat{Raw: badValue} - - testCases = []parsingTestCase{ - {name: "no stat data", - sent: [][]byte{badStatNameOnly}, - expected: Stats{bsnoStat}}, - {name: "trivial case", - sent: [][]byte{gaugeWithoutRate}, - expected: Stats{gworStat}}, - {name: "multiple simple", - sent: [][]byte{gaugeWithoutRate, counterWithRate}, - expected: Stats{gworStat, cwrStat}}, - {name: "mixed good and bad", - sent: [][]byte{badValue, badValue, stringStat, badValue, counterWithRate, badValue}, - expected: Stats{bvStat, bvStat, sStat, bvStat, cwrStat, bvStat}}, - } -) - -func TestParseBytes(t *testing.T) { - for _, tc := range testCases { - got := ParseStats(bytes.Join(tc.sent, []byte("\n"))) - want := tc.expected - if !reflect.DeepEqual(got, want) { - t.Errorf("%s: got: %+v, want: %+v", tc.name, got, want) - } - } -} - -func TestStatsUnparsed(t *testing.T) { - start := Stats{bsnoStat, gworStat, bsnoStat, bsnoStat, cwrStat} - got := start.Unparsed() - want := Stats{bsnoStat, bsnoStat, bsnoStat} - if !reflect.DeepEqual(got, want) { - t.Errorf("got: %+v, want: %+v", got, want) - } -} - -func TestStatsCollectNamed(t *testing.T) { - type test struct { - name string - start Stats - want Stats - matchOn string - } - - cases := []test{ - {"No matches", - Stats{bsnoStat, cwrStat}, - nil, - "foo"}, - {"One match", - Stats{bsnoStat, Stat{Stat: "foo"}, cwrStat}, - Stats{Stat{Stat: "foo"}}, - "foo"}, - {"Two matches", - Stats{bsnoStat, Stat{Stat: "foo"}, cwrStat}, - Stats{bsnoStat, cwrStat}, - "foo.bar.baz"}, - } - - for _, c := range cases { - got := c.start.CollectNamed(c.matchOn) - if !reflect.DeepEqual(got, c.want) { - t.Errorf("%s: got: %+v, want: %+v", c.name, got, c.want) - } - } -} - -func TestStatsCollect(t *testing.T) { - type test struct { - name string - start Stats - want Stats - pred func(Stat) bool - } - - cases := []test{ - {"Not called", - Stats{}, - nil, - func(_ Stat) bool { t.Errorf("should not be called"); return true }}, - {"Matches value = 1.000", - Stats{bsnoStat, gworStat, cwrStat, sStat, bsnoStat}, - Stats{gworStat, cwrStat}, - func(s Stat) bool { return s.Value == "1.000" }}, - } - - for _, c := range cases { - got := c.start.Collect(c.pred) - if !reflect.DeepEqual(got, c.want) { - t.Errorf("%s: got: %+v, want: %+v", c.name, got, c.want) - } - } -} - -func TestStatsValues(t *testing.T) { - start := Stats{bsnoStat, sStat, gworStat} - got := start.Values() - want := []string{bsnoStat.Value, sStat.Value, gworStat.Value} - if !reflect.DeepEqual(got, want) { - t.Errorf("got: %+v, want: %+v", got, want) - } -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/validator.go b/vendor/github.com/cactus/go-statsd-client/statsd/validator.go deleted file mode 100644 index a022510dd..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/validator.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import ( - "fmt" - "regexp" -) - -// The ValidatorFunc type defines a function that can serve -// as a stat name validation function. -type ValidatorFunc func(string) error - -var safeName = regexp.MustCompile(`^[a-zA-Z0-9\-_.]+$`) - -// CheckName may be used to validate whether a stat name contains invalid -// characters. If invalid characters are found, the function will return an -// error. -func CheckName(stat string) error { - if !safeName.MatchString(stat) { - return fmt.Errorf("invalid stat name: %s", stat) - } - return nil -} diff --git a/vendor/github.com/cactus/go-statsd-client/statsd/validator_test.go b/vendor/github.com/cactus/go-statsd-client/statsd/validator_test.go deleted file mode 100644 index feb7b9bfb..000000000 --- a/vendor/github.com/cactus/go-statsd-client/statsd/validator_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package statsd - -import "testing" - -var validatorTests = []struct { - Stat string - Valid bool -}{ - {"test.one", true}, - {"test#two", false}, - {"test|three", false}, - {"test@four", false}, -} - -func TestValidator(t *testing.T) { - var err error - for _, tt := range validatorTests { - err = CheckName(tt.Stat) - switch { - case err != nil && tt.Valid: - t.Fatal(err) - case err == nil && !tt.Valid: - t.Fatalf("validation should have failed for %s", tt.Stat) - } - } -} diff --git a/vendor/github.com/cactus/go-statsd-client/test-client/main.go b/vendor/github.com/cactus/go-statsd-client/test-client/main.go deleted file mode 100644 index f172926ad..000000000 --- a/vendor/github.com/cactus/go-statsd-client/test-client/main.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2012-2016 Eli Janssen -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package main - -import ( - "fmt" - "log" - "os" - "time" - - "github.com/cactus/go-statsd-client/statsd" - flags "github.com/jessevdk/go-flags" -) - -func main() { - - // command line flags - var opts struct { - HostPort string `long:"host" default:"127.0.0.1:8125" description:"host:port of statsd server"` - Prefix string `long:"prefix" default:"test-client" description:"Statsd prefix"` - StatType string `long:"type" default:"count" description:"stat type to send. Can be one of: timing, count, guage"` - StatValue int64 `long:"value" default:"1" description:"Value to send"` - Name string `short:"n" long:"name" default:"counter" description:"stat name"` - Rate float32 `short:"r" long:"rate" default:"1.0" description:"sample rate"` - Volume int `short:"c" long:"count" default:"1000" description:"Number of stats to send. Volume."` - Nil bool `long:"nil" description:"Use nil client"` - Buffered bool `long:"buffered" description:"Use a buffered client"` - Duration time.Duration `short:"d" long:"duration" default:"10s" description:"How long to spread the volume across. For each second of duration, volume/seconds events will be sent."` - } - - // parse said flags - _, err := flags.Parse(&opts) - if err != nil { - if e, ok := err.(*flags.Error); ok { - if e.Type == flags.ErrHelp { - os.Exit(0) - } - } - fmt.Printf("Error: %+v\n", err) - os.Exit(1) - } - - if opts.Nil && opts.Buffered { - fmt.Printf("Specifying both nil and buffered together is invalid\n") - os.Exit(1) - } - - if opts.Name == "" || statsd.CheckName(opts.Name) != nil { - fmt.Printf("Stat name contains invalid characters\n") - os.Exit(1) - } - - if statsd.CheckName(opts.Prefix) != nil { - fmt.Printf("Stat prefix contains invalid characters\n") - os.Exit(1) - } - - var client statsd.Statter - if !opts.Nil { - if !opts.Buffered { - client, err = statsd.NewClient(opts.HostPort, opts.Prefix) - } else { - client, err = statsd.NewBufferedClient(opts.HostPort, opts.Prefix, opts.Duration/time.Duration(4), 0) - } - if err != nil { - log.Fatal(err) - } - defer client.Close() - } - - var stat func(stat string, value int64, rate float32) error - switch opts.StatType { - case "count": - stat = func(stat string, value int64, rate float32) error { - return client.Inc(stat, value, rate) - } - case "gauge": - stat = func(stat string, value int64, rate float32) error { - return client.Gauge(stat, value, rate) - } - case "timing": - stat = func(stat string, value int64, rate float32) error { - return client.Timing(stat, value, rate) - } - default: - log.Fatal("Unsupported state type") - } - - pertick := opts.Volume / int(opts.Duration.Seconds()) / 10 - // add some extra time, because the first tick takes a while - ender := time.After(opts.Duration + 100*time.Millisecond) - c := time.Tick(time.Second / 10) - count := 0 - for { - select { - case <-c: - for x := 0; x < pertick; x++ { - err := stat(opts.Name, opts.StatValue, opts.Rate) - if err != nil { - log.Printf("Got Error: %+v\n", err) - break - } - count++ - } - case <-ender: - log.Printf("%d events called\n", count) - os.Exit(0) - return - } - } -} diff --git a/vendor/github.com/dghubble/go-twitter/.gitignore b/vendor/github.com/dghubble/go-twitter/.gitignore deleted file mode 100644 index 454b79914..000000000 --- a/vendor/github.com/dghubble/go-twitter/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/coverage -/bin \ No newline at end of file diff --git a/vendor/github.com/dghubble/go-twitter/.travis.yml b/vendor/github.com/dghubble/go-twitter/.travis.yml deleted file mode 100644 index bdcd0b629..000000000 --- a/vendor/github.com/dghubble/go-twitter/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: go -go: - - 1.6 - - 1.7 - - 1.8 - - tip -install: - - go get github.com/golang/lint/golint - - go get -v -t ./twitter -script: - - ./test diff --git a/vendor/github.com/dghubble/go-twitter/README.md b/vendor/github.com/dghubble/go-twitter/README.md deleted file mode 100644 index e6f375441..000000000 --- a/vendor/github.com/dghubble/go-twitter/README.md +++ /dev/null @@ -1,270 +0,0 @@ - - -# go-twitter [![Build Status](https://travis-ci.org/dghubble/go-twitter.png)](https://travis-ci.org/dghubble/go-twitter) [![GoDoc](https://godoc.org/github.com/dghubble/go-twitter?status.png)](https://godoc.org/github.com/dghubble/go-twitter) - - -go-twitter is a Go client library for the [Twitter API](https://dev.twitter.com/rest/public). Check the [usage](#usage) section or try the [examples](/examples) to see how to access the Twitter API. - -### Features - -* Twitter REST API: - * Accounts - * Direct Messages - * Favorites - * Friends - * Friendships - * Followers - * Search - * Statuses - * Timelines - * Users -* Twitter Streaming API - * Public Streams - * User Streams - * Site Streams - * Firehose Streams - -## Install - - go get github.com/dghubble/go-twitter/twitter - -## Documentation - -Read [GoDoc](https://godoc.org/github.com/dghubble/go-twitter/twitter) - -## Usage - -### REST API - -The `twitter` package provides a `Client` for accessing the Twitter API. Here are some example requests. - -```go -config := oauth1.NewConfig("consumerKey", "consumerSecret") -token := oauth1.NewToken("accessToken", "accessSecret") -httpClient := config.Client(oauth1.NoContext, token) - -// Twitter client -client := twitter.NewClient(httpClient) - -// Home Timeline -tweets, resp, err := client.Timelines.HomeTimeline(&twitter.HomeTimelineParams{ - Count: 20, -}) - -// Send a Tweet -tweet, resp, err := client.Statuses.Update("just setting up my twttr", nil) - -// Status Show -tweet, resp, err := client.Statuses.Show(585613041028431872, nil) - -// Search Tweets -search, resp, err := client.Search.Tweets(&twitter.SearchTweetParams{ - Query: "gopher", -}) - -// User Show -user, resp, err := client.Users.Show(&twitter.UserShowParams{ - ScreenName: "dghubble", -}) - -// Followers -followers, resp, err := client.Followers.List(&twitter.FollowerListParams{}) -``` - -Authentication is handled by the `http.Client` passed to `NewClient` to handle user auth (OAuth1) or application auth (OAuth2). See the [Authentication](#authentication) section. - -Required parameters are passed as positional arguments. Optional parameters are passed typed params structs (or nil). - -## Streaming API - -The Twitter Public, User, Site, and Firehose Streaming APIs can be accessed through the `Client` `StreamService` which provides methods `Filter`, `Sample`, `User`, `Site`, and `Firehose`. - -Create a `Client` with an authenticated `http.Client`. All stream endpoints require a user auth context so choose an OAuth1 `http.Client`. - - client := twitter.NewClient(httpClient) - -Next, request a managed `Stream` be started. - -#### Filter - -Filter Streams return Tweets that match one or more filtering predicates such as `Track`, `Follow`, and `Locations`. - -```go -params := &twitter.StreamFilterParams{ - Track: []string{"kitten"}, - StallWarnings: twitter.Bool(true), -} -stream, err := client.Streams.Filter(params) -``` - -#### User - -User Streams provide messages specific to the authenticate User and possibly those they follow. - -```go -params := &twitter.StreamUserParams{ - With: "followings", - StallWarnings: twitter.Bool(true), -} -stream, err := client.Streams.User(params) -``` - -*Note* To see Direct Message events, your consumer application must ask Users for read/write/DM access to their account. - -#### Sample - -Sample Streams return a small sample of public Tweets. - -```go -params := &twitter.StreamSampleParams{ - StallWarnings: twitter.Bool(true), -} -stream, err := client.Streams.Sample(params) -``` - -#### Site, Firehose - -Site and Firehose Streams require your application to have special permissions, but their API works the same way. - -### Receiving Messages - -Each `Stream` maintains the connection to the Twitter Streaming API endpoint, receives messages, and sends them on the `Stream.Messages` channel. - -Go channels support range iterations which allow you to read the messages which are of type `interface{}`. - -```go -for message := range stream.Messages { - fmt.Println(message) -} -``` - -If you run this in your main goroutine, it will receive messages forever unless the stream stops. To continue execution, receive messages using a separate goroutine. - -### Demux - -Receiving messages of type `interface{}` isn't very nice, it means you'll have to type switch and probably filter out message types you don't care about. - -For this, try a `Demux`, like `SwitchDemux`, which receives messages and type switches them to call functions with typed messages. - -For example, say you're only interested in Tweets and Direct Messages. - -```go -demux := twitter.NewSwitchDemux() -demux.Tweet = func(tweet *twitter.Tweet) { - fmt.Println(tweet.Text) -} -demux.DM = func(dm *twitter.DirectMessage) { - fmt.Println(dm.SenderID) -} -``` - -Pass the `Demux` each message or give it the entire `Stream.Message` channel. - -```go -for message := range stream.Messages { - demux.Handle(message) -} -// or pass the channel -demux.HandleChan(stream.Messages) -``` - -### Stopping - -The `Stream` will stop itself if the stream disconnects and retrying produces unrecoverable errors. When this occurs, `Stream` will close the `stream.Messages` channel, so execution will break out of any message *for range* loops. - -When you are finished receiving from a `Stream`, call `Stop()` which closes the connection, channels, and stops the goroutine **before** returning. This ensures resources are properly cleaned up. - -### Pitfalls - -**Bad**: In this example, `Stop()` is unlikely to be reached. Control stays in the message loop unless the `Stream` becomes disconnected and cannot retry. - -```go -// program does not terminate :( -stream, _ := client.Streams.Sample(params) -for message := range stream.Messages { - demux.Handle(message) -} -stream.Stop() -``` - -**Bad**: Here, messages are received on a non-main goroutine, but then `Stop()` is called immediately. The `Stream` is stopped and the program exits. - -```go -// got no messages :( -stream, _ := client.Streams.Sample(params) -go demux.HandleChan(stream.Messages) -stream.Stop() -``` - -**Good**: For main package scripts, one option is to receive messages in a goroutine and wait for CTRL-C to be pressed, then explicitly stop the `Stream`. - -```go -stream, err := client.Streams.Sample(params) -go demux.HandleChan(stream.Messages) - -// Wait for SIGINT and SIGTERM (HIT CTRL-C) -ch := make(chan os.Signal) -signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) -log.Println(<-ch) - -stream.Stop() -``` - -## Authentication - -The API client accepts an any `http.Client` capable of making user auth (OAuth1) or application auth (OAuth2) authorized requests. See the [dghubble/oauth1](https://github.com/dghubble/oauth1) and [golang/oauth2](https://github.com/golang/oauth2/) packages which can provide such agnostic clients. - -Passing an `http.Client` directly grants you control over the underlying transport, avoids dependencies on particular OAuth1 or OAuth2 packages, and keeps client APIs separate from authentication protocols. - -See the [google/go-github](https://github.com/google/go-github) client which takes the same approach. - -For example, make requests as a consumer application on behalf of a user who has granted access, with OAuth1. - -```go -// OAuth1 -import ( - "github.com/dghubble/go-twitter/twitter" - "github.com/dghubble/oauth1" -) - -config := oauth1.NewConfig("consumerKey", "consumerSecret") -token := oauth1.NewToken("accessToken", "accessSecret") -// http.Client will automatically authorize Requests -httpClient := config.Client(oauth1.NoContext, token) - -// Twitter client -client := twitter.NewClient(httpClient) -``` - -If no user auth context is needed, make requests as your application with application auth. - -```go -// OAuth2 -import ( - "github.com/dghubble/go-twitter/twitter" - "golang.org/x/oauth2" -) - -config := &oauth2.Config{} -token := &oauth2.Token{AccessToken: accessToken} -// http.Client will automatically authorize Requests -httpClient := config.Client(oauth2.NoContext, token) - -// Twitter client -client := twitter.NewClient(httpClient) -``` - -To implement Login with Twitter for web or mobile, see the gologin [package](https://github.com/dghubble/gologin) and [examples](https://github.com/dghubble/gologin/tree/master/examples/twitter). - -## Roadmap - -* Support gzipped streams -* Auto-stop streams in the event of long stalls - -## Contributing - -See the [Contributing Guide](https://gist.github.com/dghubble/be682c123727f70bcfe7). - -## License - -[MIT License](LICENSE) diff --git a/vendor/github.com/dghubble/go-twitter/examples/README.md b/vendor/github.com/dghubble/go-twitter/examples/README.md deleted file mode 100644 index 1e291e22b..000000000 --- a/vendor/github.com/dghubble/go-twitter/examples/README.md +++ /dev/null @@ -1,42 +0,0 @@ - -# Examples - -Get the dependencies and examples - - cd examples - go get . - -## User Auth (OAuth1) - -A user access token (OAuth1) grants a consumer application access to a user's Twitter resources. - -Setup an OAuth1 `http.Client` with the consumer key and secret and oauth token and secret. - - export TWITTER_CONSUMER_KEY=xxx - export TWITTER_CONSUMER_SECRET=xxx - export TWITTER_ACCESS_TOKEN=xxx - export TWITTER_ACCESS_SECRET=xxx - -To make requests as an application, on behalf of a user, create a `twitter` `Client` to get the home timeline, mention timeline, and more (example will **not** post Tweets). - - go run user-auth.go - -## App Auth (OAuth2) - -An application access token (OAuth2) allows an application to make Twitter API requests for public content, with rate limits counting against the app itself. App auth requests can be made to API endpoints which do not require a user context. - -Setup an OAuth2 `http.Client` with the Twitter application access token. - - export TWITTER_APP_ACCESS_TOKEN=xxx - -To make requests as an application, create a `twitter` `Client` and get public Tweets or timelines or other public content. - - go run app-auth.go - -## Streaming API - -A user access token (OAuth1) is required for Streaming API requests. See above. - - go run streaming.go - -Hit CTRL-C to stop streaming. Uncomment different examples in code to try different streams. \ No newline at end of file diff --git a/vendor/github.com/dghubble/go-twitter/examples/app-auth.go b/vendor/github.com/dghubble/go-twitter/examples/app-auth.go deleted file mode 100644 index a9223f11a..000000000 --- a/vendor/github.com/dghubble/go-twitter/examples/app-auth.go +++ /dev/null @@ -1,71 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "log" - "os" - - "github.com/coreos/pkg/flagutil" - "github.com/dghubble/go-twitter/twitter" - "golang.org/x/oauth2" -) - -func main() { - flags := flag.NewFlagSet("app-auth", flag.ExitOnError) - accessToken := flags.String("app-access-token", "", "Twitter Application Access Token") - flags.Parse(os.Args[1:]) - flagutil.SetFlagsFromEnv(flags, "TWITTER") - - if *accessToken == "" { - log.Fatal("Application Access Token required") - } - - config := &oauth2.Config{} - token := &oauth2.Token{AccessToken: *accessToken} - // OAuth2 http.Client will automatically authorize Requests - httpClient := config.Client(oauth2.NoContext, token) - - // Twitter client - client := twitter.NewClient(httpClient) - - // user show - userShowParams := &twitter.UserShowParams{ScreenName: "golang"} - user, _, _ := client.Users.Show(userShowParams) - fmt.Printf("USERS SHOW:\n%+v\n", user) - - // users lookup - userLookupParams := &twitter.UserLookupParams{ScreenName: []string{"golang", "gophercon"}} - users, _, _ := client.Users.Lookup(userLookupParams) - fmt.Printf("USERS LOOKUP:\n%+v\n", users) - - // status show - statusShowParams := &twitter.StatusShowParams{} - tweet, _, _ := client.Statuses.Show(584077528026849280, statusShowParams) - fmt.Printf("STATUSES SHOW:\n%+v\n", tweet) - - // statuses lookup - statusLookupParams := &twitter.StatusLookupParams{ID: []int64{20}, TweetMode: "extended"} - tweets, _, _ := client.Statuses.Lookup([]int64{573893817000140800}, statusLookupParams) - fmt.Printf("STATUSES LOOKUP:\n%+v\n", tweets) - - // oEmbed status - statusOembedParams := &twitter.StatusOEmbedParams{ID: 691076766878691329, MaxWidth: 500} - oembed, _, _ := client.Statuses.OEmbed(statusOembedParams) - fmt.Printf("OEMBED TWEET:\n%+v\n", oembed) - - // user timeline - userTimelineParams := &twitter.UserTimelineParams{ScreenName: "golang", Count: 2} - tweets, _, _ = client.Timelines.UserTimeline(userTimelineParams) - fmt.Printf("USER TIMELINE:\n%+v\n", tweets) - - // search tweets - searchTweetParams := &twitter.SearchTweetParams{ - Query: "happy birthday", - TweetMode: "extended", - Count: 3, - } - search, _, _ := client.Search.Tweets(searchTweetParams) - fmt.Printf("SEARCH TWEETS:\n%+v\n", search) - fmt.Printf("SEARCH METADATA:\n%+v\n", search.Metadata) -} diff --git a/vendor/github.com/dghubble/go-twitter/examples/streaming.go b/vendor/github.com/dghubble/go-twitter/examples/streaming.go deleted file mode 100644 index d37585e7b..000000000 --- a/vendor/github.com/dghubble/go-twitter/examples/streaming.go +++ /dev/null @@ -1,91 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "log" - "os" - "os/signal" - "syscall" - - "github.com/coreos/pkg/flagutil" - "github.com/dghubble/go-twitter/twitter" - "github.com/dghubble/oauth1" -) - -func main() { - flags := flag.NewFlagSet("user-auth", flag.ExitOnError) - consumerKey := flags.String("consumer-key", "", "Twitter Consumer Key") - consumerSecret := flags.String("consumer-secret", "", "Twitter Consumer Secret") - accessToken := flags.String("access-token", "", "Twitter Access Token") - accessSecret := flags.String("access-secret", "", "Twitter Access Secret") - flags.Parse(os.Args[1:]) - flagutil.SetFlagsFromEnv(flags, "TWITTER") - - if *consumerKey == "" || *consumerSecret == "" || *accessToken == "" || *accessSecret == "" { - log.Fatal("Consumer key/secret and Access token/secret required") - } - - config := oauth1.NewConfig(*consumerKey, *consumerSecret) - token := oauth1.NewToken(*accessToken, *accessSecret) - // OAuth1 http.Client will automatically authorize Requests - httpClient := config.Client(oauth1.NoContext, token) - - // Twitter Client - client := twitter.NewClient(httpClient) - - // Convenience Demux demultiplexed stream messages - demux := twitter.NewSwitchDemux() - demux.Tweet = func(tweet *twitter.Tweet) { - fmt.Println(tweet.Text) - } - demux.DM = func(dm *twitter.DirectMessage) { - fmt.Println(dm.SenderID) - } - demux.Event = func(event *twitter.Event) { - fmt.Printf("%#v\n", event) - } - - fmt.Println("Starting Stream...") - - // FILTER - filterParams := &twitter.StreamFilterParams{ - Track: []string{"cat"}, - StallWarnings: twitter.Bool(true), - } - stream, err := client.Streams.Filter(filterParams) - if err != nil { - log.Fatal(err) - } - - // USER (quick test: auth'd user likes a tweet -> event) - // userParams := &twitter.StreamUserParams{ - // StallWarnings: twitter.Bool(true), - // With: "followings", - // Language: []string{"en"}, - // } - // stream, err := client.Streams.User(userParams) - // if err != nil { - // log.Fatal(err) - // } - - // SAMPLE - // sampleParams := &twitter.StreamSampleParams{ - // StallWarnings: twitter.Bool(true), - // } - // stream, err := client.Streams.Sample(sampleParams) - // if err != nil { - // log.Fatal(err) - // } - - // Receive messages until stopped or stream quits - go demux.HandleChan(stream.Messages) - - // Wait for SIGINT and SIGTERM (HIT CTRL-C) - ch := make(chan os.Signal) - signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) - log.Println(<-ch) - - fmt.Println("Stopping Stream...") - stream.Stop() -} diff --git a/vendor/github.com/dghubble/go-twitter/examples/user-auth.go b/vendor/github.com/dghubble/go-twitter/examples/user-auth.go deleted file mode 100644 index e04e37d20..000000000 --- a/vendor/github.com/dghubble/go-twitter/examples/user-auth.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "log" - "os" - - "github.com/coreos/pkg/flagutil" - "github.com/dghubble/go-twitter/twitter" - "github.com/dghubble/oauth1" -) - -func main() { - flags := flag.NewFlagSet("user-auth", flag.ExitOnError) - consumerKey := flags.String("consumer-key", "", "Twitter Consumer Key") - consumerSecret := flags.String("consumer-secret", "", "Twitter Consumer Secret") - accessToken := flags.String("access-token", "", "Twitter Access Token") - accessSecret := flags.String("access-secret", "", "Twitter Access Secret") - flags.Parse(os.Args[1:]) - flagutil.SetFlagsFromEnv(flags, "TWITTER") - - if *consumerKey == "" || *consumerSecret == "" || *accessToken == "" || *accessSecret == "" { - log.Fatal("Consumer key/secret and Access token/secret required") - } - - config := oauth1.NewConfig(*consumerKey, *consumerSecret) - token := oauth1.NewToken(*accessToken, *accessSecret) - // OAuth1 http.Client will automatically authorize Requests - httpClient := config.Client(oauth1.NoContext, token) - - // Twitter client - client := twitter.NewClient(httpClient) - - // Verify Credentials - verifyParams := &twitter.AccountVerifyParams{ - SkipStatus: twitter.Bool(true), - IncludeEmail: twitter.Bool(true), - } - user, _, _ := client.Accounts.VerifyCredentials(verifyParams) - fmt.Printf("User's ACCOUNT:\n%+v\n", user) - - // Home Timeline - homeTimelineParams := &twitter.HomeTimelineParams{ - Count: 2, - TweetMode: "extended", - } - tweets, _, _ := client.Timelines.HomeTimeline(homeTimelineParams) - fmt.Printf("User's HOME TIMELINE:\n%+v\n", tweets) - - // Mention Timeline - mentionTimelineParams := &twitter.MentionTimelineParams{ - Count: 2, - TweetMode: "extended", - } - tweets, _, _ = client.Timelines.MentionTimeline(mentionTimelineParams) - fmt.Printf("User's MENTION TIMELINE:\n%+v\n", tweets) - - // Retweets of Me Timeline - retweetTimelineParams := &twitter.RetweetsOfMeTimelineParams{ - Count: 2, - TweetMode: "extended", - } - tweets, _, _ = client.Timelines.RetweetsOfMeTimeline(retweetTimelineParams) - fmt.Printf("User's 'RETWEETS OF ME' TIMELINE:\n%+v\n", tweets) - - // Update (POST!) Tweet (uncomment to run) - // tweet, _, _ := client.Statuses.Update("just setting up my twttr", nil) - // fmt.Printf("Posted Tweet\n%v\n", tweet) -} diff --git a/vendor/github.com/dghubble/go-twitter/test b/vendor/github.com/dghubble/go-twitter/test deleted file mode 100755 index 6bc268742..000000000 --- a/vendor/github.com/dghubble/go-twitter/test +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -e - -PKGS=$(go list ./... | grep -v /examples) -FORMATTABLE="$(ls -d */)" -LINTABLE=$(go list ./...) - -go test $PKGS -cover -go vet $PKGS - -echo "Checking gofmt..." -fmtRes=$(gofmt -l $FORMATTABLE) -if [ -n "${fmtRes}" ]; then - echo -e "gofmt checking failed:\n${fmtRes}" - exit 2 -fi - -echo "Checking golint..." -lintRes=$(echo $LINTABLE | xargs -n 1 golint) -if [ -n "${lintRes}" ]; then - echo -e "golint checking failed:\n${lintRes}" - exit 2 -fi \ No newline at end of file diff --git a/vendor/github.com/dghubble/go-twitter/twitter/accounts.go b/vendor/github.com/dghubble/go-twitter/twitter/accounts.go deleted file mode 100644 index b5e6ef75a..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/accounts.go +++ /dev/null @@ -1,37 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// AccountService provides a method for account credential verification. -type AccountService struct { - sling *sling.Sling -} - -// newAccountService returns a new AccountService. -func newAccountService(sling *sling.Sling) *AccountService { - return &AccountService{ - sling: sling.Path("account/"), - } -} - -// AccountVerifyParams are the params for AccountService.VerifyCredentials. -type AccountVerifyParams struct { - IncludeEntities *bool `url:"include_entities,omitempty"` - SkipStatus *bool `url:"skip_status,omitempty"` - IncludeEmail *bool `url:"include_email,omitempty"` -} - -// VerifyCredentials returns the authorized user if credentials are valid and -// returns an error otherwise. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/get/account/verify_credentials -func (s *AccountService) VerifyCredentials(params *AccountVerifyParams) (*User, *http.Response, error) { - user := new(User) - apiError := new(APIError) - resp, err := s.sling.New().Get("verify_credentials.json").QueryStruct(params).Receive(user, apiError) - return user, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/accounts_test.go b/vendor/github.com/dghubble/go-twitter/twitter/accounts_test.go deleted file mode 100644 index a98680f97..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/accounts_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestAccountService_VerifyCredentials(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/account/verify_credentials.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"include_entities": "false", "include_email": "true"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"name": "Dalton Hubble", "id": 623265148}`) - }) - - client := NewClient(httpClient) - user, _, err := client.Accounts.VerifyCredentials(&AccountVerifyParams{IncludeEntities: Bool(false), IncludeEmail: Bool(true)}) - expected := &User{Name: "Dalton Hubble", ID: 623265148} - assert.Nil(t, err) - assert.Equal(t, expected, user) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/backoffs.go b/vendor/github.com/dghubble/go-twitter/twitter/backoffs.go deleted file mode 100644 index d3a5321c6..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/backoffs.go +++ /dev/null @@ -1,25 +0,0 @@ -package twitter - -import ( - "time" - - "github.com/cenkalti/backoff" -) - -func newExponentialBackOff() *backoff.ExponentialBackOff { - b := backoff.NewExponentialBackOff() - b.InitialInterval = 5 * time.Second - b.Multiplier = 2.0 - b.MaxInterval = 320 * time.Second - b.Reset() - return b -} - -func newAggressiveExponentialBackOff() *backoff.ExponentialBackOff { - b := backoff.NewExponentialBackOff() - b.InitialInterval = 1 * time.Minute - b.Multiplier = 2.0 - b.MaxInterval = 16 * time.Minute - b.Reset() - return b -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/backoffs_test.go b/vendor/github.com/dghubble/go-twitter/twitter/backoffs_test.go deleted file mode 100644 index 49bfd0306..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/backoffs_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package twitter - -import ( - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestNewExponentialBackOff(t *testing.T) { - b := newExponentialBackOff() - assert.Equal(t, 5*time.Second, b.InitialInterval) - assert.Equal(t, 2.0, b.Multiplier) - assert.Equal(t, 320*time.Second, b.MaxInterval) -} - -func TestNewAggressiveExponentialBackOff(t *testing.T) { - b := newAggressiveExponentialBackOff() - assert.Equal(t, 1*time.Minute, b.InitialInterval) - assert.Equal(t, 2.0, b.Multiplier) - assert.Equal(t, 16*time.Minute, b.MaxInterval) -} - -// BackoffRecorder is an implementation of backoff.BackOff that records -// calls to NextBackOff and Reset for later inspection in tests. -type BackOffRecorder struct { - Count int -} - -func (b *BackOffRecorder) NextBackOff() time.Duration { - b.Count++ - return 1 * time.Nanosecond -} - -func (b *BackOffRecorder) Reset() { - b.Count = 0 -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/demux.go b/vendor/github.com/dghubble/go-twitter/twitter/demux.go deleted file mode 100644 index 29e21f2f1..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/demux.go +++ /dev/null @@ -1,88 +0,0 @@ -package twitter - -// A Demux receives interface{} messages individually or from a channel and -// sends those messages to one or more outputs determined by the -// implementation. -type Demux interface { - Handle(message interface{}) - HandleChan(messages <-chan interface{}) -} - -// SwitchDemux receives messages and uses a type switch to send each typed -// message to a handler function. -type SwitchDemux struct { - All func(message interface{}) - Tweet func(tweet *Tweet) - DM func(dm *DirectMessage) - StatusDeletion func(deletion *StatusDeletion) - LocationDeletion func(LocationDeletion *LocationDeletion) - StreamLimit func(limit *StreamLimit) - StatusWithheld func(statusWithheld *StatusWithheld) - UserWithheld func(userWithheld *UserWithheld) - StreamDisconnect func(disconnect *StreamDisconnect) - Warning func(warning *StallWarning) - FriendsList func(friendsList *FriendsList) - Event func(event *Event) - Other func(message interface{}) -} - -// NewSwitchDemux returns a new SwitchMux which has NoOp handler functions. -func NewSwitchDemux() SwitchDemux { - return SwitchDemux{ - All: func(message interface{}) {}, - Tweet: func(tweet *Tweet) {}, - DM: func(dm *DirectMessage) {}, - StatusDeletion: func(deletion *StatusDeletion) {}, - LocationDeletion: func(LocationDeletion *LocationDeletion) {}, - StreamLimit: func(limit *StreamLimit) {}, - StatusWithheld: func(statusWithheld *StatusWithheld) {}, - UserWithheld: func(userWithheld *UserWithheld) {}, - StreamDisconnect: func(disconnect *StreamDisconnect) {}, - Warning: func(warning *StallWarning) {}, - FriendsList: func(friendsList *FriendsList) {}, - Event: func(event *Event) {}, - Other: func(message interface{}) {}, - } -} - -// Handle determines the type of a message and calls the corresponding receiver -// function with the typed message. All messages are passed to the All func. -// Messages with unmatched types are passed to the Other func. -func (d SwitchDemux) Handle(message interface{}) { - d.All(message) - switch msg := message.(type) { - case *Tweet: - d.Tweet(msg) - case *DirectMessage: - d.DM(msg) - case *StatusDeletion: - d.StatusDeletion(msg) - case *LocationDeletion: - d.LocationDeletion(msg) - case *StreamLimit: - d.StreamLimit(msg) - case *StatusWithheld: - d.StatusWithheld(msg) - case *UserWithheld: - d.UserWithheld(msg) - case *StreamDisconnect: - d.StreamDisconnect(msg) - case *StallWarning: - d.Warning(msg) - case *FriendsList: - d.FriendsList(msg) - case *Event: - d.Event(msg) - default: - d.Other(msg) - } -} - -// HandleChan receives messages and calls the corresponding receiver function -// with the typed message. All messages are passed to the All func. Messages -// with unmatched type are passed to the Other func. -func (d SwitchDemux) HandleChan(messages <-chan interface{}) { - for message := range messages { - d.Handle(message) - } -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/demux_test.go b/vendor/github.com/dghubble/go-twitter/twitter/demux_test.go deleted file mode 100644 index ccdce52a9..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/demux_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package twitter - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestDemux_Handle(t *testing.T) { - messages, expectedCounts := exampleMessages() - counts := &counter{} - demux := newCounterDemux(counts) - for _, message := range messages { - demux.Handle(message) - } - assert.Equal(t, expectedCounts, counts) -} - -func TestDemux_HandleChan(t *testing.T) { - messages, expectedCounts := exampleMessages() - counts := &counter{} - demux := newCounterDemux(counts) - ch := make(chan interface{}) - // stream messages into channel - go func() { - for _, msg := range messages { - ch <- msg - } - close(ch) - }() - // handle channel messages until exhausted - demux.HandleChan(ch) - assert.Equal(t, expectedCounts, counts) -} - -// counter counts stream messages by type for testing. -type counter struct { - all int - tweet int - dm int - statusDeletion int - locationDeletion int - streamLimit int - statusWithheld int - userWithheld int - streamDisconnect int - stallWarning int - friendsList int - event int - other int -} - -// newCounterDemux returns a Demux which counts message types. -func newCounterDemux(counter *counter) Demux { - demux := NewSwitchDemux() - demux.All = func(interface{}) { - counter.all++ - } - demux.Tweet = func(*Tweet) { - counter.tweet++ - } - demux.DM = func(*DirectMessage) { - counter.dm++ - } - demux.StatusDeletion = func(*StatusDeletion) { - counter.statusDeletion++ - } - demux.LocationDeletion = func(*LocationDeletion) { - counter.locationDeletion++ - } - demux.StreamLimit = func(*StreamLimit) { - counter.streamLimit++ - } - demux.StatusWithheld = func(*StatusWithheld) { - counter.statusWithheld++ - } - demux.UserWithheld = func(*UserWithheld) { - counter.userWithheld++ - } - demux.StreamDisconnect = func(*StreamDisconnect) { - counter.streamDisconnect++ - } - demux.Warning = func(*StallWarning) { - counter.stallWarning++ - } - demux.FriendsList = func(*FriendsList) { - counter.friendsList++ - } - demux.Event = func(*Event) { - counter.event++ - } - demux.Other = func(interface{}) { - counter.other++ - } - return demux -} - -// examples messages returns a test stream of messages and the expected -// counts of each message type. -func exampleMessages() (messages []interface{}, expectedCounts *counter) { - var ( - tweet = &Tweet{} - dm = &DirectMessage{} - statusDeletion = &StatusDeletion{} - locationDeletion = &LocationDeletion{} - streamLimit = &StreamLimit{} - statusWithheld = &StatusWithheld{} - userWithheld = &UserWithheld{} - streamDisconnect = &StreamDisconnect{} - stallWarning = &StallWarning{} - friendsList = &FriendsList{} - event = &Event{} - otherA = func() {} - otherB = struct{}{} - ) - messages = []interface{}{tweet, dm, statusDeletion, locationDeletion, - streamLimit, statusWithheld, userWithheld, streamDisconnect, - stallWarning, friendsList, event, otherA, otherB} - expectedCounts = &counter{ - all: len(messages), - tweet: 1, - dm: 1, - statusDeletion: 1, - locationDeletion: 1, - streamLimit: 1, - statusWithheld: 1, - userWithheld: 1, - streamDisconnect: 1, - stallWarning: 1, - friendsList: 1, - event: 1, - other: 2, - } - return messages, expectedCounts -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/direct_messages.go b/vendor/github.com/dghubble/go-twitter/twitter/direct_messages.go deleted file mode 100644 index 3d91ec5a0..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/direct_messages.go +++ /dev/null @@ -1,130 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// DirectMessage is a direct message to a single recipient. -type DirectMessage struct { - CreatedAt string `json:"created_at"` - Entities *Entities `json:"entities"` - ID int64 `json:"id"` - IDStr string `json:"id_str"` - Recipient *User `json:"recipient"` - RecipientID int64 `json:"recipient_id"` - RecipientScreenName string `json:"recipient_screen_name"` - Sender *User `json:"sender"` - SenderID int64 `json:"sender_id"` - SenderScreenName string `json:"sender_screen_name"` - Text string `json:"text"` -} - -// DirectMessageService provides methods for accessing Twitter direct message -// API endpoints. -type DirectMessageService struct { - baseSling *sling.Sling - sling *sling.Sling -} - -// newDirectMessageService returns a new DirectMessageService. -func newDirectMessageService(sling *sling.Sling) *DirectMessageService { - return &DirectMessageService{ - baseSling: sling.New(), - sling: sling.Path("direct_messages/"), - } -} - -// directMessageShowParams are the parameters for DirectMessageService.Show -type directMessageShowParams struct { - ID int64 `url:"id,omitempty"` -} - -// Show returns the requested Direct Message. -// Requires a user auth context with DM scope. -// https://dev.twitter.com/rest/reference/get/direct_messages/show -func (s *DirectMessageService) Show(id int64) (*DirectMessage, *http.Response, error) { - params := &directMessageShowParams{ID: id} - dm := new(DirectMessage) - apiError := new(APIError) - resp, err := s.sling.New().Get("show.json").QueryStruct(params).Receive(dm, apiError) - return dm, resp, relevantError(err, *apiError) -} - -// DirectMessageGetParams are the parameters for DirectMessageService.Get -type DirectMessageGetParams struct { - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - Count int `url:"count,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - SkipStatus *bool `url:"skip_status,omitempty"` -} - -// Get returns recent Direct Messages received by the authenticated user. -// Requires a user auth context with DM scope. -// https://dev.twitter.com/rest/reference/get/direct_messages -func (s *DirectMessageService) Get(params *DirectMessageGetParams) ([]DirectMessage, *http.Response, error) { - dms := new([]DirectMessage) - apiError := new(APIError) - resp, err := s.baseSling.New().Get("direct_messages.json").QueryStruct(params).Receive(dms, apiError) - return *dms, resp, relevantError(err, *apiError) -} - -// DirectMessageSentParams are the parameters for DirectMessageService.Sent -type DirectMessageSentParams struct { - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - Count int `url:"count,omitempty"` - Page int `url:"page,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` -} - -// Sent returns recent Direct Messages sent by the authenticated user. -// Requires a user auth context with DM scope. -// https://dev.twitter.com/rest/reference/get/direct_messages/sent -func (s *DirectMessageService) Sent(params *DirectMessageSentParams) ([]DirectMessage, *http.Response, error) { - dms := new([]DirectMessage) - apiError := new(APIError) - resp, err := s.sling.New().Get("sent.json").QueryStruct(params).Receive(dms, apiError) - return *dms, resp, relevantError(err, *apiError) -} - -// DirectMessageNewParams are the parameters for DirectMessageService.New -type DirectMessageNewParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - Text string `url:"text"` -} - -// New sends a new Direct Message to a specified user as the authenticated -// user. -// Requires a user auth context with DM scope. -// https://dev.twitter.com/rest/reference/post/direct_messages/new -func (s *DirectMessageService) New(params *DirectMessageNewParams) (*DirectMessage, *http.Response, error) { - dm := new(DirectMessage) - apiError := new(APIError) - resp, err := s.sling.New().Post("new.json").BodyForm(params).Receive(dm, apiError) - return dm, resp, relevantError(err, *apiError) -} - -// DirectMessageDestroyParams are the parameters for DirectMessageService.Destroy -type DirectMessageDestroyParams struct { - ID int64 `url:"id,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` -} - -// Destroy deletes the Direct Message with the given id and returns it if -// successful. -// Requires a user auth context with DM scope. -// https://dev.twitter.com/rest/reference/post/direct_messages/destroy -func (s *DirectMessageService) Destroy(id int64, params *DirectMessageDestroyParams) (*DirectMessage, *http.Response, error) { - if params == nil { - params = &DirectMessageDestroyParams{} - } - params.ID = id - dm := new(DirectMessage) - apiError := new(APIError) - resp, err := s.sling.New().Post("destroy.json").BodyForm(params).Receive(dm, apiError) - return dm, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/direct_messages_test.go b/vendor/github.com/dghubble/go-twitter/twitter/direct_messages_test.go deleted file mode 100644 index c0ea24238..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/direct_messages_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - testDM = DirectMessage{ - ID: 240136858829479936, - Recipient: &User{ScreenName: "theSeanCook"}, - Sender: &User{ScreenName: "s0c1alm3dia"}, - Text: "hello world", - } - testDMIDStr = "240136858829479936" - testDMJSON = `{"id": 240136858829479936,"recipient": {"screen_name": "theSeanCook"},"sender": {"screen_name": "s0c1alm3dia"},"text": "hello world"}` -) - -func TestDirectMessageService_Show(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/direct_messages/show.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"id": testDMIDStr}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, testDMJSON) - }) - - client := NewClient(httpClient) - dms, _, err := client.DirectMessages.Show(testDM.ID) - assert.Nil(t, err) - assert.Equal(t, &testDM, dms) -} - -func TestDirectMessageService_Get(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/direct_messages.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"since_id": "589147592367431680", "count": "1"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[`+testDMJSON+`]`) - }) - - client := NewClient(httpClient) - params := &DirectMessageGetParams{SinceID: 589147592367431680, Count: 1} - dms, _, err := client.DirectMessages.Get(params) - expected := []DirectMessage{testDM} - assert.Nil(t, err) - assert.Equal(t, expected, dms) -} - -func TestDirectMessageService_Sent(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/direct_messages/sent.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"since_id": "589147592367431680", "count": "1"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[`+testDMJSON+`]`) - }) - - client := NewClient(httpClient) - params := &DirectMessageSentParams{SinceID: 589147592367431680, Count: 1} - dms, _, err := client.DirectMessages.Sent(params) - expected := []DirectMessage{testDM} - assert.Nil(t, err) - assert.Equal(t, expected, dms) -} - -func TestDirectMessageService_New(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/direct_messages/new.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertPostForm(t, map[string]string{"screen_name": "theseancook", "text": "hello world"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, testDMJSON) - }) - - client := NewClient(httpClient) - params := &DirectMessageNewParams{ScreenName: "theseancook", Text: "hello world"} - dm, _, err := client.DirectMessages.New(params) - assert.Nil(t, err) - assert.Equal(t, &testDM, dm) -} - -func TestDirectMessageService_Destroy(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/direct_messages/destroy.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertPostForm(t, map[string]string{"id": testDMIDStr}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, testDMJSON) - }) - - client := NewClient(httpClient) - dm, _, err := client.DirectMessages.Destroy(testDM.ID, nil) - assert.Nil(t, err) - assert.Equal(t, &testDM, dm) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/doc.go b/vendor/github.com/dghubble/go-twitter/twitter/doc.go deleted file mode 100644 index 47136c596..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/doc.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Package twitter provides a Client for the Twitter API. - - -The twitter package provides a Client for accessing the Twitter API. Here are -some example requests. - - // Twitter client - client := twitter.NewClient(httpClient) - // Home Timeline - tweets, resp, err := client.Timelines.HomeTimeline(&HomeTimelineParams{}) - // Send a Tweet - tweet, resp, err := client.Statuses.Update("just setting up my twttr", nil) - // Status Show - tweet, resp, err := client.Statuses.Show(585613041028431872, nil) - // User Show - params := &twitter.UserShowParams{ScreenName: "dghubble"} - user, resp, err := client.Users.Show(params) - // Followers - followers, resp, err := client.Followers.List(&FollowerListParams{}) - -Required parameters are passed as positional arguments. Optional parameters -are passed in a typed params struct (or pass nil). - -Authentication - -By design, the Twitter Client accepts any http.Client so user auth (OAuth1) or -application auth (OAuth2) requests can be made by using the appropriate -authenticated client. Use the https://github.com/dghubble/oauth1 and -https://github.com/golang/oauth2 packages to obtain an http.Client which -transparently authorizes requests. - -For example, make requests as a consumer application on behalf of a user who -has granted access, with OAuth1. - - // OAuth1 - import ( - "github.com/dghubble/go-twitter/twitter" - "github.com/dghubble/oauth1" - ) - - config := oauth1.NewConfig("consumerKey", "consumerSecret") - token := oauth1.NewToken("accessToken", "accessSecret") - // http.Client will automatically authorize Requests - httpClient := config.Client(oauth1.NoContext, token) - - // twitter client - client := twitter.NewClient(httpClient) - -If no user auth context is needed, make requests as your application with -application auth. - - // OAuth2 - import ( - "github.com/dghubble/go-twitter/twitter" - "golang.org/x/oauth2" - ) - - config := &oauth2.Config{} - token := &oauth2.Token{AccessToken: accessToken} - // http.Client will automatically authorize Requests - httpClient := config.Client(oauth2.NoContext, token) - - // twitter client - client := twitter.NewClient(httpClient) - -To implement Login with Twitter, see https://github.com/dghubble/gologin. - -*/ -package twitter diff --git a/vendor/github.com/dghubble/go-twitter/twitter/entities.go b/vendor/github.com/dghubble/go-twitter/twitter/entities.go deleted file mode 100644 index 85b617ab6..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/entities.go +++ /dev/null @@ -1,104 +0,0 @@ -package twitter - -// Entities represent metadata and context info parsed from Twitter components. -// https://dev.twitter.com/overview/api/entities -// TODO: symbols -type Entities struct { - Hashtags []HashtagEntity `json:"hashtags"` - Media []MediaEntity `json:"media"` - Urls []URLEntity `json:"urls"` - UserMentions []MentionEntity `json:"user_mentions"` -} - -// HashtagEntity represents a hashtag which has been parsed from text. -type HashtagEntity struct { - Indices Indices `json:"indices"` - Text string `json:"text"` -} - -// URLEntity represents a URL which has been parsed from text. -type URLEntity struct { - Indices Indices `json:"indices"` - DisplayURL string `json:"display_url"` - ExpandedURL string `json:"expanded_url"` - URL string `json:"url"` -} - -// MediaEntity represents media elements associated with a Tweet. -type MediaEntity struct { - URLEntity - ID int64 `json:"id"` - IDStr string `json:"id_str"` - MediaURL string `json:"media_url"` - MediaURLHttps string `json:"media_url_https"` - SourceStatusID int64 `json:"source_status_id"` - SourceStatusIDStr string `json:"source_status_id_str"` - Type string `json:"type"` - Sizes MediaSizes `json:"sizes"` - VideoInfo VideoInfo `json:"video_info"` -} - -// MentionEntity represents Twitter user mentions parsed from text. -type MentionEntity struct { - Indices Indices `json:"indices"` - ID int64 `json:"id"` - IDStr string `json:"id_str"` - Name string `json:"name"` - ScreenName string `json:"screen_name"` -} - -// UserEntities contain Entities parsed from User url and description fields. -// https://dev.twitter.com/overview/api/entities-in-twitter-objects#users -type UserEntities struct { - URL Entities `json:"url"` - Description Entities `json:"description"` -} - -// ExtendedEntity contains media information. -// https://dev.twitter.com/overview/api/entities-in-twitter-objects#extended_entities -type ExtendedEntity struct { - Media []MediaEntity `json:"media"` -} - -// Indices represent the start and end offsets within text. -type Indices [2]int - -// Start returns the index at which an entity starts, inclusive. -func (i Indices) Start() int { - return i[0] -} - -// End returns the index at which an entity ends, exclusive. -func (i Indices) End() int { - return i[1] -} - -// MediaSizes contain the different size media that are available. -// https://dev.twitter.com/overview/api/entities#obj-sizes -type MediaSizes struct { - Thumb MediaSize `json:"thumb"` - Large MediaSize `json:"large"` - Medium MediaSize `json:"medium"` - Small MediaSize `json:"small"` -} - -// MediaSize describes the height, width, and resizing method used. -type MediaSize struct { - Width int `json:"w"` - Height int `json:"h"` - Resize string `json:"resize"` -} - -// VideoInfo is available on video media objects. -type VideoInfo struct { - AspectRatio [2]int `json:"aspect_ratio"` - DurationMillis int `json:"duration_millis"` - Variants []VideoVariant `json:"variants"` -} - -// VideoVariant describes one of the available video formats. -type VideoVariant struct { - ContentType string `json:"content_type"` - Bitrate int `json:"bitrate"` - URL string `json:"url"` -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/entities_test.go b/vendor/github.com/dghubble/go-twitter/twitter/entities_test.go deleted file mode 100644 index fdfde94ec..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/entities_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package twitter - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestIndices(t *testing.T) { - cases := []struct { - pair Indices - expectedStart int - expectedEnd int - }{ - {Indices{}, 0, 0}, - {Indices{25, 47}, 25, 47}, - } - for _, c := range cases { - assert.Equal(t, c.expectedStart, c.pair.Start()) - assert.Equal(t, c.expectedEnd, c.pair.End()) - } -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/errors.go b/vendor/github.com/dghubble/go-twitter/twitter/errors.go deleted file mode 100644 index 9208a1a6b..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/errors.go +++ /dev/null @@ -1,47 +0,0 @@ -package twitter - -import ( - "fmt" -) - -// APIError represents a Twitter API Error response -// https://dev.twitter.com/overview/api/response-codes -type APIError struct { - Errors []ErrorDetail `json:"errors"` -} - -// ErrorDetail represents an individual item in an APIError. -type ErrorDetail struct { - Message string `json:"message"` - Code int `json:"code"` -} - -func (e APIError) Error() string { - if len(e.Errors) > 0 { - err := e.Errors[0] - return fmt.Sprintf("twitter: %d %v", err.Code, err.Message) - } - return "" -} - -// Empty returns true if empty. Otherwise, at least 1 error message/code is -// present and false is returned. -func (e APIError) Empty() bool { - if len(e.Errors) == 0 { - return true - } - return false -} - -// relevantError returns any non-nil http-related error (creating the request, -// getting the response, decoding) if any. If the decoded apiError is non-zero -// the apiError is returned. Otherwise, no errors occurred, returns nil. -func relevantError(httpError error, apiError APIError) error { - if httpError != nil { - return httpError - } - if apiError.Empty() { - return nil - } - return apiError -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/errors_test.go b/vendor/github.com/dghubble/go-twitter/twitter/errors_test.go deleted file mode 100644 index 806db7559..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/errors_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package twitter - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -var errAPI = APIError{ - Errors: []ErrorDetail{ - ErrorDetail{Message: "Status is a duplicate", Code: 187}, - }, -} -var errHTTP = fmt.Errorf("unknown host") - -func TestAPIError_Error(t *testing.T) { - err := APIError{} - if assert.Error(t, err) { - assert.Equal(t, "", err.Error()) - } - if assert.Error(t, errAPI) { - assert.Equal(t, "twitter: 187 Status is a duplicate", errAPI.Error()) - } -} - -func TestAPIError_Empty(t *testing.T) { - err := APIError{} - assert.True(t, err.Empty()) - assert.False(t, errAPI.Empty()) -} - -func TestRelevantError(t *testing.T) { - cases := []struct { - httpError error - apiError APIError - expected error - }{ - {nil, APIError{}, nil}, - {nil, errAPI, errAPI}, - {errHTTP, APIError{}, errHTTP}, - {errHTTP, errAPI, errHTTP}, - } - for _, c := range cases { - err := relevantError(c.httpError, c.apiError) - assert.Equal(t, c.expected, err) - } -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/favorites.go b/vendor/github.com/dghubble/go-twitter/twitter/favorites.go deleted file mode 100644 index 9cdcf686f..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/favorites.go +++ /dev/null @@ -1,72 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// FavoriteService provides methods for accessing Twitter favorite API endpoints. -// -// Note: the like action was known as favorite before November 3, 2015; the -// historical naming remains in API methods and object properties. -type FavoriteService struct { - sling *sling.Sling -} - -// newFavoriteService returns a new FavoriteService. -func newFavoriteService(sling *sling.Sling) *FavoriteService { - return &FavoriteService{ - sling: sling.Path("favorites/"), - } -} - -// FavoriteListParams are the parameters for FavoriteService.List. -type FavoriteListParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - Count int `url:"count,omitempty"` - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// List returns liked Tweets from the specified user. -// https://dev.twitter.com/rest/reference/get/favorites/list -func (s *FavoriteService) List(params *FavoriteListParams) ([]Tweet, *http.Response, error) { - favorites := new([]Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("list.json").QueryStruct(params).Receive(favorites, apiError) - return *favorites, resp, relevantError(err, *apiError) -} - -// FavoriteCreateParams are the parameters for FavoriteService.Create. -type FavoriteCreateParams struct { - ID int64 `url:"id,omitempty"` -} - -// Create favorites the specified tweet. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/favorites/create -func (s *FavoriteService) Create(params *FavoriteCreateParams) (*Tweet, *http.Response, error) { - tweet := new(Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Post("create.json").QueryStruct(params).Receive(tweet, apiError) - return tweet, resp, relevantError(err, *apiError) -} - -// FavoriteDestroyParams are the parameters for FavoriteService.Destroy. -type FavoriteDestroyParams struct { - ID int64 `url:"id,omitempty"` -} - -// Destroy un-favorites the specified tweet. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/favorites/destroy -func (s *FavoriteService) Destroy(params *FavoriteDestroyParams) (*Tweet, *http.Response, error) { - tweet := new(Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Post("destroy.json").QueryStruct(params).Receive(tweet, apiError) - return tweet, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/favorites_test.go b/vendor/github.com/dghubble/go-twitter/twitter/favorites_test.go deleted file mode 100644 index e546cd642..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/favorites_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestFavoriteService_List(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/favorites/list.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"user_id": "113419064", "since_id": "101492475", "include_entities": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"text": "Gophercon talks!"}, {"text": "Why gophers are so adorable"}]`) - }) - - client := NewClient(httpClient) - tweets, _, err := client.Favorites.List(&FavoriteListParams{UserID: 113419064, SinceID: 101492475, IncludeEntities: Bool(false)}) - expected := []Tweet{Tweet{Text: "Gophercon talks!"}, Tweet{Text: "Why gophers are so adorable"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweets) -} - -func TestFavoriteService_Create(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/favorites/create.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertPostForm(t, map[string]string{"id": "12345"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 581980947630845953, "text": "very informative tweet"}`) - }) - - client := NewClient(httpClient) - params := &FavoriteCreateParams{ID: 12345} - tweet, _, err := client.Favorites.Create(params) - assert.Nil(t, err) - expected := &Tweet{ID: 581980947630845953, Text: "very informative tweet"} - assert.Equal(t, expected, tweet) -} - -func TestFavoriteService_Destroy(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/favorites/destroy.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertPostForm(t, map[string]string{"id": "12345"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 581980947630845953, "text": "very unhappy tweet"}`) - }) - - client := NewClient(httpClient) - params := &FavoriteDestroyParams{ID: 12345} - tweet, _, err := client.Favorites.Destroy(params) - assert.Nil(t, err) - expected := &Tweet{ID: 581980947630845953, Text: "very unhappy tweet"} - assert.Equal(t, expected, tweet) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/followers.go b/vendor/github.com/dghubble/go-twitter/twitter/followers.go deleted file mode 100644 index 19ed4ef60..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/followers.go +++ /dev/null @@ -1,73 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// FollowerIDs is a cursored collection of follower ids. -type FollowerIDs struct { - IDs []int64 `json:"ids"` - NextCursor int64 `json:"next_cursor"` - NextCursorStr string `json:"next_cursor_str"` - PreviousCursor int64 `json:"previous_cursor"` - PreviousCursorStr string `json:"previous_cursor_str"` -} - -// Followers is a cursored collection of followers. -type Followers struct { - Users []User `json:"users"` - NextCursor int64 `json:"next_cursor"` - NextCursorStr string `json:"next_cursor_str"` - PreviousCursor int64 `json:"previous_cursor"` - PreviousCursorStr string `json:"previous_cursor_str"` -} - -// FollowerService provides methods for accessing Twitter followers endpoints. -type FollowerService struct { - sling *sling.Sling -} - -// newFollowerService returns a new FollowerService. -func newFollowerService(sling *sling.Sling) *FollowerService { - return &FollowerService{ - sling: sling.Path("followers/"), - } -} - -// FollowerIDParams are the parameters for FollowerService.Ids -type FollowerIDParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - Cursor int64 `url:"cursor,omitempty"` - Count int `url:"count,omitempty"` -} - -// IDs returns a cursored collection of user ids following the specified user. -// https://dev.twitter.com/rest/reference/get/followers/ids -func (s *FollowerService) IDs(params *FollowerIDParams) (*FollowerIDs, *http.Response, error) { - ids := new(FollowerIDs) - apiError := new(APIError) - resp, err := s.sling.New().Get("ids.json").QueryStruct(params).Receive(ids, apiError) - return ids, resp, relevantError(err, *apiError) -} - -// FollowerListParams are the parameters for FollowerService.List -type FollowerListParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - Cursor int64 `url:"cursor,omitempty"` - Count int `url:"count,omitempty"` - SkipStatus *bool `url:"skip_status,omitempty"` - IncludeUserEntities *bool `url:"include_user_entities,omitempty"` -} - -// List returns a cursored collection of Users following the specified user. -// https://dev.twitter.com/rest/reference/get/followers/list -func (s *FollowerService) List(params *FollowerListParams) (*Followers, *http.Response, error) { - followers := new(Followers) - apiError := new(APIError) - resp, err := s.sling.New().Get("list.json").QueryStruct(params).Receive(followers, apiError) - return followers, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/followers_test.go b/vendor/github.com/dghubble/go-twitter/twitter/followers_test.go deleted file mode 100644 index cab8472be..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/followers_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestFollowerService_Ids(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/followers/ids.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"user_id": "623265148", "count": "5", "cursor": "1516933260114270762"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"ids":[178082406,3318241001,1318020818,191714329,376703838],"next_cursor":1516837838944119498,"next_cursor_str":"1516837838944119498","previous_cursor":-1516924983503961435,"previous_cursor_str":"-1516924983503961435"}`) - }) - expected := &FollowerIDs{ - IDs: []int64{178082406, 3318241001, 1318020818, 191714329, 376703838}, - NextCursor: 1516837838944119498, - NextCursorStr: "1516837838944119498", - PreviousCursor: -1516924983503961435, - PreviousCursorStr: "-1516924983503961435", - } - - client := NewClient(httpClient) - params := &FollowerIDParams{ - UserID: 623265148, - Count: 5, - Cursor: 1516933260114270762, - } - followerIDs, _, err := client.Followers.IDs(params) - assert.Nil(t, err) - assert.Equal(t, expected, followerIDs) -} - -func TestFollowerService_List(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/followers/list.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"screen_name": "dghubble", "count": "5", "cursor": "1516933260114270762", "skip_status": "true", "include_user_entities": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"users": [{"id": 123}], "next_cursor":1516837838944119498,"next_cursor_str":"1516837838944119498","previous_cursor":-1516924983503961435,"previous_cursor_str":"-1516924983503961435"}`) - }) - expected := &Followers{ - Users: []User{User{ID: 123}}, - NextCursor: 1516837838944119498, - NextCursorStr: "1516837838944119498", - PreviousCursor: -1516924983503961435, - PreviousCursorStr: "-1516924983503961435", - } - - client := NewClient(httpClient) - params := &FollowerListParams{ - ScreenName: "dghubble", - Count: 5, - Cursor: 1516933260114270762, - SkipStatus: Bool(true), - IncludeUserEntities: Bool(false), - } - followers, _, err := client.Followers.List(params) - assert.Nil(t, err) - assert.Equal(t, expected, followers) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/friends.go b/vendor/github.com/dghubble/go-twitter/twitter/friends.go deleted file mode 100644 index 32847435c..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/friends.go +++ /dev/null @@ -1,73 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// FriendIDs is a cursored collection of friend ids. -type FriendIDs struct { - IDs []int64 `json:"ids"` - NextCursor int64 `json:"next_cursor"` - NextCursorStr string `json:"next_cursor_str"` - PreviousCursor int64 `json:"previous_cursor"` - PreviousCursorStr string `json:"previous_cursor_str"` -} - -// Friends is a cursored collection of friends. -type Friends struct { - Users []User `json:"users"` - NextCursor int64 `json:"next_cursor"` - NextCursorStr string `json:"next_cursor_str"` - PreviousCursor int64 `json:"previous_cursor"` - PreviousCursorStr string `json:"previous_cursor_str"` -} - -// FriendService provides methods for accessing Twitter friends endpoints. -type FriendService struct { - sling *sling.Sling -} - -// newFriendService returns a new FriendService. -func newFriendService(sling *sling.Sling) *FriendService { - return &FriendService{ - sling: sling.Path("friends/"), - } -} - -// FriendIDParams are the parameters for FriendService.Ids -type FriendIDParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - Cursor int64 `url:"cursor,omitempty"` - Count int `url:"count,omitempty"` -} - -// IDs returns a cursored collection of user ids that the specified user is following. -// https://dev.twitter.com/rest/reference/get/friends/ids -func (s *FriendService) IDs(params *FriendIDParams) (*FriendIDs, *http.Response, error) { - ids := new(FriendIDs) - apiError := new(APIError) - resp, err := s.sling.New().Get("ids.json").QueryStruct(params).Receive(ids, apiError) - return ids, resp, relevantError(err, *apiError) -} - -// FriendListParams are the parameters for FriendService.List -type FriendListParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - Cursor int64 `url:"cursor,omitempty"` - Count int `url:"count,omitempty"` - SkipStatus *bool `url:"skip_status,omitempty"` - IncludeUserEntities *bool `url:"include_user_entities,omitempty"` -} - -// List returns a cursored collection of Users that the specified user is following. -// https://dev.twitter.com/rest/reference/get/friends/list -func (s *FriendService) List(params *FriendListParams) (*Friends, *http.Response, error) { - friends := new(Friends) - apiError := new(APIError) - resp, err := s.sling.New().Get("list.json").QueryStruct(params).Receive(friends, apiError) - return friends, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/friends_test.go b/vendor/github.com/dghubble/go-twitter/twitter/friends_test.go deleted file mode 100644 index cf0c0a714..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/friends_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestFriendService_Ids(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/friends/ids.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"user_id": "623265148", "count": "5", "cursor": "1516933260114270762"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"ids":[178082406,3318241001,1318020818,191714329,376703838],"next_cursor":1516837838944119498,"next_cursor_str":"1516837838944119498","previous_cursor":-1516924983503961435,"previous_cursor_str":"-1516924983503961435"}`) - }) - expected := &FriendIDs{ - IDs: []int64{178082406, 3318241001, 1318020818, 191714329, 376703838}, - NextCursor: 1516837838944119498, - NextCursorStr: "1516837838944119498", - PreviousCursor: -1516924983503961435, - PreviousCursorStr: "-1516924983503961435", - } - - client := NewClient(httpClient) - params := &FriendIDParams{ - UserID: 623265148, - Count: 5, - Cursor: 1516933260114270762, - } - friendIDs, _, err := client.Friends.IDs(params) - assert.Nil(t, err) - assert.Equal(t, expected, friendIDs) -} - -func TestFriendService_List(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/friends/list.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"screen_name": "dghubble", "count": "5", "cursor": "1516933260114270762", "skip_status": "true", "include_user_entities": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"users": [{"id": 123}], "next_cursor":1516837838944119498,"next_cursor_str":"1516837838944119498","previous_cursor":-1516924983503961435,"previous_cursor_str":"-1516924983503961435"}`) - }) - expected := &Friends{ - Users: []User{User{ID: 123}}, - NextCursor: 1516837838944119498, - NextCursorStr: "1516837838944119498", - PreviousCursor: -1516924983503961435, - PreviousCursorStr: "-1516924983503961435", - } - - client := NewClient(httpClient) - params := &FriendListParams{ - ScreenName: "dghubble", - Count: 5, - Cursor: 1516933260114270762, - SkipStatus: Bool(true), - IncludeUserEntities: Bool(false), - } - friends, _, err := client.Friends.List(params) - assert.Nil(t, err) - assert.Equal(t, expected, friends) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/friendships.go b/vendor/github.com/dghubble/go-twitter/twitter/friendships.go deleted file mode 100644 index 51d7278a6..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/friendships.go +++ /dev/null @@ -1,134 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// FriendshipService provides methods for accessing Twitter friendship API -// endpoints. -type FriendshipService struct { - sling *sling.Sling -} - -// newFriendshipService returns a new FriendshipService. -func newFriendshipService(sling *sling.Sling) *FriendshipService { - return &FriendshipService{ - sling: sling.Path("friendships/"), - } -} - -// FriendshipCreateParams are parameters for FriendshipService.Create -type FriendshipCreateParams struct { - ScreenName string `url:"screen_name,omitempty"` - UserID int64 `url:"user_id,omitempty"` - Follow *bool `url:"follow,omitempty"` -} - -// Create creates a friendship to (i.e. follows) the specified user and -// returns the followed user. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/friendships/create -func (s *FriendshipService) Create(params *FriendshipCreateParams) (*User, *http.Response, error) { - user := new(User) - apiError := new(APIError) - resp, err := s.sling.New().Post("create.json").QueryStruct(params).Receive(user, apiError) - return user, resp, relevantError(err, *apiError) -} - -// FriendshipShowParams are paramenters for FriendshipService.Show -type FriendshipShowParams struct { - SourceID int64 `url:"source_id,omitempty"` - SourceScreenName string `url:"source_screen_name,omitempty"` - TargetID int64 `url:"target_id,omitempty"` - TargetScreenName string `url:"target_screen_name,omitempty"` -} - -// Show returns the relationship between two arbitrary users. -// Requires a user auth or an app context. -// https://dev.twitter.com/rest/reference/get/friendships/show -func (s *FriendshipService) Show(params *FriendshipShowParams) (*Relationship, *http.Response, error) { - response := new(RelationshipResponse) - apiError := new(APIError) - resp, err := s.sling.New().Get("show.json").QueryStruct(params).Receive(response, apiError) - return response.Relationship, resp, relevantError(err, *apiError) -} - -// RelationshipResponse contains a relationship. -type RelationshipResponse struct { - Relationship *Relationship `json:"relationship"` -} - -// Relationship represents the relation between a source user and target user. -type Relationship struct { - Source RelationshipSource `json:"source"` - Target RelationshipTarget `json:"target"` -} - -// RelationshipSource represents the source user. -type RelationshipSource struct { - ID int64 `json:"id"` - IDStr string `json:"id_str"` - ScreenName string `json:"screen_name"` - Following bool `json:"following"` - FollowedBy bool `json:"followed_by"` - CanDM bool `json:"can_dm"` - Blocking bool `json:"blocking"` - Muting bool `json:"muting"` - AllReplies bool `json:"all_replies"` - WantRetweets bool `json:"want_retweets"` - MarkedSpam bool `json:"marked_spam"` - NotificationsEnabled bool `json:"notifications_enabled"` -} - -// RelationshipTarget represents the target user. -type RelationshipTarget struct { - ID int64 `json:"id"` - IDStr string `json:"id_str"` - ScreenName string `json:"screen_name"` - Following bool `json:"following"` - FollowedBy bool `json:"followed_by"` -} - -// FriendshipDestroyParams are paramenters for FriendshipService.Destroy -type FriendshipDestroyParams struct { - ScreenName string `url:"screen_name,omitempty"` - UserID int64 `url:"user_id,omitempty"` -} - -// Destroy destroys a friendship to (i.e. unfollows) the specified user and -// returns the unfollowed user. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/friendships/destroy -func (s *FriendshipService) Destroy(params *FriendshipDestroyParams) (*User, *http.Response, error) { - user := new(User) - apiError := new(APIError) - resp, err := s.sling.New().Post("destroy.json").QueryStruct(params).Receive(user, apiError) - return user, resp, relevantError(err, *apiError) -} - -// FriendshipPendingParams are paramenters for FriendshipService.Outgoing -type FriendshipPendingParams struct { - Cursor int64 `url:"cursor,omitempty"` -} - -// Outgoing returns a collection of numeric IDs for every protected user for whom the authenticating -// user has a pending follow request. -// https://dev.twitter.com/rest/reference/get/friendships/outgoing -func (s *FriendshipService) Outgoing(params *FriendshipPendingParams) (*FriendIDs, *http.Response, error) { - ids := new(FriendIDs) - apiError := new(APIError) - resp, err := s.sling.New().Get("outgoing.json").QueryStruct(params).Receive(ids, apiError) - return ids, resp, relevantError(err, *apiError) -} - -// Incoming returns a collection of numeric IDs for every user who has a pending request to -// follow the authenticating user. -// https://dev.twitter.com/rest/reference/get/friendships/incoming -func (s *FriendshipService) Incoming(params *FriendshipPendingParams) (*FriendIDs, *http.Response, error) { - ids := new(FriendIDs) - apiError := new(APIError) - resp, err := s.sling.New().Get("incoming.json").QueryStruct(params).Receive(ids, apiError) - return ids, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/friendships_test.go b/vendor/github.com/dghubble/go-twitter/twitter/friendships_test.go deleted file mode 100644 index 82892bbf3..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/friendships_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestFriendshipService_Create(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/friendships/create.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertPostForm(t, map[string]string{"user_id": "12345"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 12345, "name": "Doug Williams"}`) - }) - - client := NewClient(httpClient) - params := &FriendshipCreateParams{UserID: 12345} - user, _, err := client.Friendships.Create(params) - assert.Nil(t, err) - expected := &User{ID: 12345, Name: "Doug Williams"} - assert.Equal(t, expected, user) -} - -func TestFriendshipService_Show(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/friendships/show.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"source_screen_name": "foo", "target_screen_name": "bar"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{ "relationship": { "source": { "can_dm": false, "muting": true, "id_str": "8649302", "id": 8649302, "screen_name": "foo"}, "target": { "id_str": "12148", "id": 12148, "screen_name": "bar", "following": true, "followed_by": false } } }`) - }) - - client := NewClient(httpClient) - params := &FriendshipShowParams{SourceScreenName: "foo", TargetScreenName: "bar"} - relationship, _, err := client.Friendships.Show(params) - assert.Nil(t, err) - expected := &Relationship{ - Source: RelationshipSource{ID: 8649302, ScreenName: "foo", IDStr: "8649302", CanDM: false, Muting: true, WantRetweets: false}, - Target: RelationshipTarget{ID: 12148, ScreenName: "bar", IDStr: "12148", Following: true, FollowedBy: false}, - } - assert.Equal(t, expected, relationship) -} - -func TestFriendshipService_Destroy(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/friendships/destroy.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertPostForm(t, map[string]string{"user_id": "12345"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 12345, "name": "Doug Williams"}`) - }) - - client := NewClient(httpClient) - params := &FriendshipDestroyParams{UserID: 12345} - user, _, err := client.Friendships.Destroy(params) - assert.Nil(t, err) - expected := &User{ID: 12345, Name: "Doug Williams"} - assert.Equal(t, expected, user) -} - -func TestFriendshipService_Outgoing(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/friendships/outgoing.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"cursor": "1516933260114270762"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"ids":[178082406,3318241001,1318020818,191714329,376703838],"next_cursor":1516837838944119498,"next_cursor_str":"1516837838944119498","previous_cursor":-1516924983503961435,"previous_cursor_str":"-1516924983503961435"}`) - }) - expected := &FriendIDs{ - IDs: []int64{178082406, 3318241001, 1318020818, 191714329, 376703838}, - NextCursor: 1516837838944119498, - NextCursorStr: "1516837838944119498", - PreviousCursor: -1516924983503961435, - PreviousCursorStr: "-1516924983503961435", - } - - client := NewClient(httpClient) - params := &FriendshipPendingParams{ - Cursor: 1516933260114270762, - } - friendIDs, _, err := client.Friendships.Outgoing(params) - assert.Nil(t, err) - assert.Equal(t, expected, friendIDs) -} - -func TestFriendshipService_Incoming(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/friendships/incoming.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"cursor": "1516933260114270762"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"ids":[178082406,3318241001,1318020818,191714329,376703838],"next_cursor":1516837838944119498,"next_cursor_str":"1516837838944119498","previous_cursor":-1516924983503961435,"previous_cursor_str":"-1516924983503961435"}`) - }) - expected := &FriendIDs{ - IDs: []int64{178082406, 3318241001, 1318020818, 191714329, 376703838}, - NextCursor: 1516837838944119498, - NextCursorStr: "1516837838944119498", - PreviousCursor: -1516924983503961435, - PreviousCursorStr: "-1516924983503961435", - } - - client := NewClient(httpClient) - params := &FriendshipPendingParams{ - Cursor: 1516933260114270762, - } - friendIDs, _, err := client.Friendships.Incoming(params) - assert.Nil(t, err) - assert.Equal(t, expected, friendIDs) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/search.go b/vendor/github.com/dghubble/go-twitter/twitter/search.go deleted file mode 100644 index 5bb5071f3..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/search.go +++ /dev/null @@ -1,62 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// Search represents the result of a Tweet search. -type Search struct { - Statuses []Tweet `json:"statuses"` - Metadata *SearchMetadata `json:"search_metadata"` -} - -// SearchMetadata describes a Search result. -type SearchMetadata struct { - Count int `json:"count"` - SinceID int64 `json:"since_id"` - SinceIDStr string `json:"since_id_str"` - MaxID int64 `json:"max_id"` - MaxIDStr string `json:"max_id_str"` - RefreshURL string `json:"refresh_url"` - NextResults string `json:"next_results"` - CompletedIn float64 `json:"completed_in"` - Query string `json:"query"` -} - -// SearchService provides methods for accessing Twitter search API endpoints. -type SearchService struct { - sling *sling.Sling -} - -// newSearchService returns a new SearchService. -func newSearchService(sling *sling.Sling) *SearchService { - return &SearchService{ - sling: sling.Path("search/"), - } -} - -// SearchTweetParams are the parameters for SearchService.Tweets -type SearchTweetParams struct { - Query string `url:"q,omitempty"` - Geocode string `url:"geocode,omitempty"` - Lang string `url:"lang,omitempty"` - Locale string `url:"locale,omitempty"` - ResultType string `url:"result_type,omitempty"` - Count int `url:"count,omitempty"` - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - Until string `url:"until,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Tweets returns a collection of Tweets matching a search query. -// https://dev.twitter.com/rest/reference/get/search/tweets -func (s *SearchService) Tweets(params *SearchTweetParams) (*Search, *http.Response, error) { - search := new(Search) - apiError := new(APIError) - resp, err := s.sling.New().Get("tweets.json").QueryStruct(params).Receive(search, apiError) - return search, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/search_test.go b/vendor/github.com/dghubble/go-twitter/twitter/search_test.go deleted file mode 100644 index 4c6357407..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/search_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestSearchService_Tweets(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/search/tweets.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"q": "happy birthday", "result_type": "popular", "count": "1"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"statuses":[{"id":781760642139250689}],"search_metadata":{"completed_in":0.043,"max_id":781760642139250689,"max_id_str":"781760642139250689","next_results":"?max_id=781760640104828927&q=happy+birthday&count=1&include_entities=1","query":"happy birthday","refresh_url":"?since_id=781760642139250689&q=happy+birthday&include_entities=1","count":1,"since_id":0,"since_id_str":"0"}}`) - }) - - client := NewClient(httpClient) - search, _, err := client.Search.Tweets(&SearchTweetParams{ - Query: "happy birthday", - Count: 1, - ResultType: "popular", - }) - expected := &Search{ - Statuses: []Tweet{ - Tweet{ID: 781760642139250689}, - }, - Metadata: &SearchMetadata{ - Count: 1, - SinceID: 0, - SinceIDStr: "0", - MaxID: 781760642139250689, - MaxIDStr: "781760642139250689", - RefreshURL: "?since_id=781760642139250689&q=happy+birthday&include_entities=1", - NextResults: "?max_id=781760640104828927&q=happy+birthday&count=1&include_entities=1", - CompletedIn: 0.043, - Query: "happy birthday", - }, - } - assert.Nil(t, err) - assert.Equal(t, expected, search) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/statuses.go b/vendor/github.com/dghubble/go-twitter/twitter/statuses.go deleted file mode 100644 index 6a9046bfd..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/statuses.go +++ /dev/null @@ -1,310 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "time" - - "github.com/dghubble/sling" -) - -// Tweet represents a Twitter Tweet, previously called a status. -// https://dev.twitter.com/overview/api/tweets -type Tweet struct { - Coordinates *Coordinates `json:"coordinates"` - CreatedAt string `json:"created_at"` - CurrentUserRetweet *TweetIdentifier `json:"current_user_retweet"` - Entities *Entities `json:"entities"` - FavoriteCount int `json:"favorite_count"` - Favorited bool `json:"favorited"` - FilterLevel string `json:"filter_level"` - ID int64 `json:"id"` - IDStr string `json:"id_str"` - InReplyToScreenName string `json:"in_reply_to_screen_name"` - InReplyToStatusID int64 `json:"in_reply_to_status_id"` - InReplyToStatusIDStr string `json:"in_reply_to_status_id_str"` - InReplyToUserID int64 `json:"in_reply_to_user_id"` - InReplyToUserIDStr string `json:"in_reply_to_user_id_str"` - Lang string `json:"lang"` - PossiblySensitive bool `json:"possibly_sensitive"` - RetweetCount int `json:"retweet_count"` - Retweeted bool `json:"retweeted"` - RetweetedStatus *Tweet `json:"retweeted_status"` - Source string `json:"source"` - Scopes map[string]interface{} `json:"scopes"` - Text string `json:"text"` - FullText string `json:"full_text"` - DisplayTextRange Indices `json:"display_text_range"` - Place *Place `json:"place"` - Truncated bool `json:"truncated"` - User *User `json:"user"` - WithheldCopyright bool `json:"withheld_copyright"` - WithheldInCountries []string `json:"withheld_in_countries"` - WithheldScope string `json:"withheld_scope"` - ExtendedEntities *ExtendedEntity `json:"extended_entities"` - ExtendedTweet *ExtendedTweet `json:"extended_tweet"` - QuotedStatusID int64 `json:"quoted_status_id"` - QuotedStatusIDStr string `json:"quoted_status_id_str"` - QuotedStatus *Tweet `json:"quoted_status"` -} - -// CreatedAtTime is a convenience wrapper that returns the Created_at time, parsed as a time.Time struct -func (t Tweet) CreatedAtTime() (time.Time, error) { - return time.Parse(time.RubyDate, t.CreatedAt) -} - -// ExtendedTweet represents fields embedded in extended Tweets when served in -// compatibility mode (default). -// https://dev.twitter.com/overview/api/upcoming-changes-to-tweets -type ExtendedTweet struct { - FullText string `json:"full_text"` - DisplayTextRange Indices `json:"display_text_range"` - Entities *Entities `json:"entities"` - ExtendedEntities *ExtendedEntity `json:"extended_entities"` -} - -// Place represents a Twitter Place / Location -// https://dev.twitter.com/overview/api/places -type Place struct { - Attributes map[string]string `json:"attributes"` - BoundingBox *BoundingBox `json:"bounding_box"` - Country string `json:"country"` - CountryCode string `json:"country_code"` - FullName string `json:"full_name"` - Geometry *BoundingBox `json:"geometry"` - ID string `json:"id"` - Name string `json:"name"` - PlaceType string `json:"place_type"` - Polylines []string `json:"polylines"` - URL string `json:"url"` -} - -// BoundingBox represents the bounding coordinates (longitude, latitutde) -// defining the bounds of a box containing a Place entity. -type BoundingBox struct { - Coordinates [][][2]float64 `json:"coordinates"` - Type string `json:"type"` -} - -// Coordinates are pairs of longitude and latitude locations. -type Coordinates struct { - Coordinates [2]float64 `json:"coordinates"` - Type string `json:"type"` -} - -// TweetIdentifier represents the id by which a Tweet can be identified. -type TweetIdentifier struct { - ID int64 `json:"id"` - IDStr string `json:"id_str"` -} - -// StatusService provides methods for accessing Twitter status API endpoints. -type StatusService struct { - sling *sling.Sling -} - -// newStatusService returns a new StatusService. -func newStatusService(sling *sling.Sling) *StatusService { - return &StatusService{ - sling: sling.Path("statuses/"), - } -} - -// StatusShowParams are the parameters for StatusService.Show -type StatusShowParams struct { - ID int64 `url:"id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - IncludeMyRetweet *bool `url:"include_my_retweet,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Show returns the requested Tweet. -// https://dev.twitter.com/rest/reference/get/statuses/show/%3Aid -func (s *StatusService) Show(id int64, params *StatusShowParams) (*Tweet, *http.Response, error) { - if params == nil { - params = &StatusShowParams{} - } - params.ID = id - tweet := new(Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("show.json").QueryStruct(params).Receive(tweet, apiError) - return tweet, resp, relevantError(err, *apiError) -} - -// StatusLookupParams are the parameters for StatusService.Lookup -type StatusLookupParams struct { - ID []int64 `url:"id,omitempty,comma"` - TrimUser *bool `url:"trim_user,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - Map *bool `url:"map,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Lookup returns the requested Tweets as a slice. Combines ids from the -// required ids argument and from params.Id. -// https://dev.twitter.com/rest/reference/get/statuses/lookup -func (s *StatusService) Lookup(ids []int64, params *StatusLookupParams) ([]Tweet, *http.Response, error) { - if params == nil { - params = &StatusLookupParams{} - } - params.ID = append(params.ID, ids...) - tweets := new([]Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("lookup.json").QueryStruct(params).Receive(tweets, apiError) - return *tweets, resp, relevantError(err, *apiError) -} - -// StatusUpdateParams are the parameters for StatusService.Update -type StatusUpdateParams struct { - Status string `url:"status,omitempty"` - InReplyToStatusID int64 `url:"in_reply_to_status_id,omitempty"` - PossiblySensitive *bool `url:"possibly_sensitive,omitempty"` - Lat *float64 `url:"lat,omitempty"` - Long *float64 `url:"long,omitempty"` - PlaceID string `url:"place_id,omitempty"` - DisplayCoordinates *bool `url:"display_coordinates,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - MediaIds []int64 `url:"media_ids,omitempty,comma"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Update updates the user's status, also known as Tweeting. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/statuses/update -func (s *StatusService) Update(status string, params *StatusUpdateParams) (*Tweet, *http.Response, error) { - if params == nil { - params = &StatusUpdateParams{} - } - params.Status = status - tweet := new(Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Post("update.json").BodyForm(params).Receive(tweet, apiError) - return tweet, resp, relevantError(err, *apiError) -} - -// StatusRetweetParams are the parameters for StatusService.Retweet -type StatusRetweetParams struct { - ID int64 `url:"id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Retweet retweets the Tweet with the given id and returns the original Tweet -// with embedded retweet details. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/statuses/retweet/%3Aid -func (s *StatusService) Retweet(id int64, params *StatusRetweetParams) (*Tweet, *http.Response, error) { - if params == nil { - params = &StatusRetweetParams{} - } - params.ID = id - tweet := new(Tweet) - apiError := new(APIError) - path := fmt.Sprintf("retweet/%d.json", params.ID) - resp, err := s.sling.New().Post(path).BodyForm(params).Receive(tweet, apiError) - return tweet, resp, relevantError(err, *apiError) -} - -// StatusUnretweetParams are the parameters for StatusService.Unretweet -type StatusUnretweetParams struct { - ID int64 `url:"id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Unretweet unretweets the Tweet with the given id and returns the original Tweet. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/statuses/unretweet/%3Aid -func (s *StatusService) Unretweet(id int64, params *StatusUnretweetParams) (*Tweet, *http.Response, error) { - if params == nil { - params = &StatusUnretweetParams{} - } - params.ID = id - tweet := new(Tweet) - apiError := new(APIError) - path := fmt.Sprintf("unretweet/%d.json", params.ID) - resp, err := s.sling.New().Post(path).BodyForm(params).Receive(tweet, apiError) - return tweet, resp, relevantError(err, *apiError) -} - -// StatusRetweetsParams are the parameters for StatusService.Retweets -type StatusRetweetsParams struct { - ID int64 `url:"id,omitempty"` - Count int `url:"count,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Retweets returns the most recent retweets of the Tweet with the given id. -// https://dev.twitter.com/rest/reference/get/statuses/retweets/%3Aid -func (s *StatusService) Retweets(id int64, params *StatusRetweetsParams) ([]Tweet, *http.Response, error) { - if params == nil { - params = &StatusRetweetsParams{} - } - params.ID = id - tweets := new([]Tweet) - apiError := new(APIError) - path := fmt.Sprintf("retweets/%d.json", params.ID) - resp, err := s.sling.New().Get(path).QueryStruct(params).Receive(tweets, apiError) - return *tweets, resp, relevantError(err, *apiError) -} - -// StatusDestroyParams are the parameters for StatusService.Destroy -type StatusDestroyParams struct { - ID int64 `url:"id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// Destroy deletes the Tweet with the given id and returns it if successful. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/post/statuses/destroy/%3Aid -func (s *StatusService) Destroy(id int64, params *StatusDestroyParams) (*Tweet, *http.Response, error) { - if params == nil { - params = &StatusDestroyParams{} - } - params.ID = id - tweet := new(Tweet) - apiError := new(APIError) - path := fmt.Sprintf("destroy/%d.json", params.ID) - resp, err := s.sling.New().Post(path).BodyForm(params).Receive(tweet, apiError) - return tweet, resp, relevantError(err, *apiError) -} - -// OEmbedTweet represents a Tweet in oEmbed format. -type OEmbedTweet struct { - URL string `json:"url"` - ProviderURL string `json:"provider_url"` - ProviderName string `json:"provider_name"` - AuthorName string `json:"author_name"` - Version string `json:"version"` - AuthorURL string `json:"author_url"` - Type string `json:"type"` - HTML string `json:"html"` - Height int64 `json:"height"` - Width int64 `json:"width"` - CacheAge string `json:"cache_age"` -} - -// StatusOEmbedParams are the parameters for StatusService.OEmbed -type StatusOEmbedParams struct { - ID int64 `url:"id,omitempty"` - URL string `url:"url,omitempty"` - Align string `url:"align,omitempty"` - MaxWidth int64 `url:"maxwidth,omitempty"` - HideMedia *bool `url:"hide_media,omitempty"` - HideThread *bool `url:"hide_media,omitempty"` - OmitScript *bool `url:"hide_media,omitempty"` - WidgetType string `url:"widget_type,omitempty"` - HideTweet *bool `url:"hide_tweet,omitempty"` -} - -// OEmbed returns the requested Tweet in oEmbed format. -// https://dev.twitter.com/rest/reference/get/statuses/oembed -func (s *StatusService) OEmbed(params *StatusOEmbedParams) (*OEmbedTweet, *http.Response, error) { - oEmbedTweet := new(OEmbedTweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("oembed.json").QueryStruct(params).Receive(oEmbedTweet, apiError) - return oEmbedTweet, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/statuses_test.go b/vendor/github.com/dghubble/go-twitter/twitter/statuses_test.go deleted file mode 100644 index 9b583a184..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/statuses_test.go +++ /dev/null @@ -1,275 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestStatusService_Show(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/show.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"id": "589488862814076930", "include_entities": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"user": {"screen_name": "dghubble"}, "text": ".@audreyr use a DONTREADME file if you really want people to read it :P"}`) - }) - - client := NewClient(httpClient) - params := &StatusShowParams{ID: 5441, IncludeEntities: Bool(false)} - tweet, _, err := client.Statuses.Show(589488862814076930, params) - expected := &Tweet{User: &User{ScreenName: "dghubble"}, Text: ".@audreyr use a DONTREADME file if you really want people to read it :P"} - assert.Nil(t, err) - assert.Equal(t, expected, tweet) -} - -func TestStatusService_ShowHandlesNilParams(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/show.json", func(w http.ResponseWriter, r *http.Request) { - assertQuery(t, map[string]string{"id": "589488862814076930"}, r) - }) - client := NewClient(httpClient) - client.Statuses.Show(589488862814076930, nil) -} - -func TestStatusService_Lookup(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/lookup.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"id": "20,573893817000140800", "trim_user": "true"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"id": 20, "text": "just setting up my twttr"}, {"id": 573893817000140800, "text": "Don't get lost #PaxEast2015"}]`) - }) - - client := NewClient(httpClient) - params := &StatusLookupParams{ID: []int64{20}, TrimUser: Bool(true)} - tweets, _, err := client.Statuses.Lookup([]int64{573893817000140800}, params) - expected := []Tweet{Tweet{ID: 20, Text: "just setting up my twttr"}, Tweet{ID: 573893817000140800, Text: "Don't get lost #PaxEast2015"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweets) -} - -func TestStatusService_LookupHandlesNilParams(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - mux.HandleFunc("/1.1/statuses/lookup.json", func(w http.ResponseWriter, r *http.Request) { - assertQuery(t, map[string]string{"id": "20,573893817000140800"}, r) - }) - client := NewClient(httpClient) - client.Statuses.Lookup([]int64{20, 573893817000140800}, nil) -} - -func TestStatusService_Update(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/update.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertQuery(t, map[string]string{}, r) - assertPostForm(t, map[string]string{"status": "very informative tweet", "media_ids": "123456789,987654321", "lat": "37.826706", "long": "-122.42219"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 581980947630845953, "text": "very informative tweet"}`) - }) - - client := NewClient(httpClient) - params := &StatusUpdateParams{MediaIds: []int64{123456789, 987654321}, Lat: Float(37.826706), Long: Float(-122.422190)} - tweet, _, err := client.Statuses.Update("very informative tweet", params) - expected := &Tweet{ID: 581980947630845953, Text: "very informative tweet"} - assert.Nil(t, err) - assert.Equal(t, expected, tweet) -} - -func TestStatusService_UpdateHandlesNilParams(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - mux.HandleFunc("/1.1/statuses/update.json", func(w http.ResponseWriter, r *http.Request) { - assertPostForm(t, map[string]string{"status": "very informative tweet"}, r) - }) - client := NewClient(httpClient) - client.Statuses.Update("very informative tweet", nil) -} - -func TestStatusService_APIError(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - mux.HandleFunc("/1.1/statuses/update.json", func(w http.ResponseWriter, r *http.Request) { - assertPostForm(t, map[string]string{"status": "very informative tweet"}, r) - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(403) - fmt.Fprintf(w, `{"errors": [{"message": "Status is a duplicate", "code": 187}]}`) - }) - - client := NewClient(httpClient) - _, _, err := client.Statuses.Update("very informative tweet", nil) - expected := APIError{ - Errors: []ErrorDetail{ - ErrorDetail{Message: "Status is a duplicate", Code: 187}, - }, - } - if assert.Error(t, err) { - assert.Equal(t, expected, err) - } -} - -func TestStatusService_HTTPError(t *testing.T) { - httpClient, _, server := testServer() - server.Close() - client := NewClient(httpClient) - _, _, err := client.Statuses.Update("very informative tweet", nil) - if err == nil || !strings.Contains(err.Error(), "connection refused") { - t.Errorf("Statuses.Update error expected connection refused, got: \n %+v", err) - } -} - -func TestStatusService_Retweet(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/retweet/20.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertQuery(t, map[string]string{}, r) - assertPostForm(t, map[string]string{"id": "20", "trim_user": "true"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 581980947630202020, "text": "RT @jack: just setting up my twttr", "retweeted_status": {"id": 20, "text": "just setting up my twttr"}}`) - }) - - client := NewClient(httpClient) - params := &StatusRetweetParams{TrimUser: Bool(true)} - tweet, _, err := client.Statuses.Retweet(20, params) - expected := &Tweet{ID: 581980947630202020, Text: "RT @jack: just setting up my twttr", RetweetedStatus: &Tweet{ID: 20, Text: "just setting up my twttr"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweet) -} - -func TestStatusService_RetweetHandlesNilParams(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/retweet/20.json", func(w http.ResponseWriter, r *http.Request) { - assertPostForm(t, map[string]string{"id": "20"}, r) - }) - - client := NewClient(httpClient) - client.Statuses.Retweet(20, nil) -} - -func TestStatusService_Unretweet(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/unretweet/20.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertQuery(t, map[string]string{}, r) - assertPostForm(t, map[string]string{"id": "20", "trim_user": "true"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 581980947630202020, "text":"RT @jack: just setting up my twttr", "retweeted_status": {"id": 20, "text": "just setting up my twttr"}}`) - }) - - client := NewClient(httpClient) - params := &StatusUnretweetParams{TrimUser: Bool(true)} - tweet, _, err := client.Statuses.Unretweet(20, params) - expected := &Tweet{ID: 581980947630202020, Text: "RT @jack: just setting up my twttr", RetweetedStatus: &Tweet{ID: 20, Text: "just setting up my twttr"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweet) -} - -func TestStatusService_Retweets(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/retweets/20.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"id": "20", "count": "2"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"text": "RT @jack: just setting up my twttr"}, {"text": "RT @jack: just setting up my twttr"}]`) - }) - - client := NewClient(httpClient) - params := &StatusRetweetsParams{Count: 2} - retweets, _, err := client.Statuses.Retweets(20, params) - expected := []Tweet{Tweet{Text: "RT @jack: just setting up my twttr"}, Tweet{Text: "RT @jack: just setting up my twttr"}} - assert.Nil(t, err) - assert.Equal(t, expected, retweets) -} - -func TestStatusService_RetweetsHandlesNilParams(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/retweets/20.json", func(w http.ResponseWriter, r *http.Request) { - assertQuery(t, map[string]string{"id": "20"}, r) - }) - - client := NewClient(httpClient) - client.Statuses.Retweets(20, nil) -} - -func TestStatusService_Destroy(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/destroy/40.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertQuery(t, map[string]string{}, r) - assertPostForm(t, map[string]string{"id": "40", "trim_user": "true"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"id": 40, "text": "wishing I had another sammich"}`) - }) - - client := NewClient(httpClient) - params := &StatusDestroyParams{TrimUser: Bool(true)} - tweet, _, err := client.Statuses.Destroy(40, params) - // feed Biz Stone a sammich, he deletes sammich Tweet - expected := &Tweet{ID: 40, Text: "wishing I had another sammich"} - assert.Nil(t, err) - assert.Equal(t, expected, tweet) -} - -func TestStatusService_DestroyHandlesNilParams(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/destroy/40.json", func(w http.ResponseWriter, r *http.Request) { - assertPostForm(t, map[string]string{"id": "40"}, r) - }) - - client := NewClient(httpClient) - client.Statuses.Destroy(40, nil) -} - -func TestStatusService_OEmbed(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/oembed.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"id": "691076766878691329", "maxwidth": "400", "hide_media": "true"}, r) - w.Header().Set("Content-Type", "application/json") - // abbreviated oEmbed response - fmt.Fprintf(w, `{"url": "https://twitter.com/dghubble/statuses/691076766878691329", "width": 400, "html": "
"}`) - }) - - client := NewClient(httpClient) - params := &StatusOEmbedParams{ - ID: 691076766878691329, - MaxWidth: 400, - HideMedia: Bool(true), - } - oembed, _, err := client.Statuses.OEmbed(params) - expected := &OEmbedTweet{ - URL: "https://twitter.com/dghubble/statuses/691076766878691329", - Width: 400, - HTML: "
", - } - assert.Nil(t, err) - assert.Equal(t, expected, oembed) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/stream_messages.go b/vendor/github.com/dghubble/go-twitter/twitter/stream_messages.go deleted file mode 100644 index ad89bad69..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/stream_messages.go +++ /dev/null @@ -1,110 +0,0 @@ -package twitter - -// StatusDeletion indicates that a given Tweet has been deleted. -// https://dev.twitter.com/streaming/overview/messages-types#status_deletion_notices_delete -type StatusDeletion struct { - ID int64 `json:"id"` - IDStr string `json:"id_str"` - UserID int64 `json:"user_id"` - UserIDStr string `json:"user_id_str"` -} - -type statusDeletionNotice struct { - Delete struct { - StatusDeletion *StatusDeletion `json:"status"` - } `json:"delete"` -} - -// LocationDeletion indicates geolocation data must be stripped from a range -// of Tweets. -// https://dev.twitter.com/streaming/overview/messages-types#Location_deletion_notices_scrub_geo -type LocationDeletion struct { - UserID int64 `json:"user_id"` - UserIDStr string `json:"user_id_str"` - UpToStatusID int64 `json:"up_to_status_id"` - UpToStatusIDStr string `json:"up_to_status_id_str"` -} - -type locationDeletionNotice struct { - ScrubGeo *LocationDeletion `json:"scrub_geo"` -} - -// StreamLimit indicates a stream matched more statuses than its rate limit -// allowed. The track number is the number of undelivered matches. -// https://dev.twitter.com/streaming/overview/messages-types#limit_notices -type StreamLimit struct { - Track int64 `json:"track"` -} - -type streamLimitNotice struct { - Limit *StreamLimit `json:"limit"` -} - -// StatusWithheld indicates a Tweet with the given ID, belonging to UserId, -// has been withheld in certain countries. -// https://dev.twitter.com/streaming/overview/messages-types#withheld_content_notices -type StatusWithheld struct { - ID int64 `json:"id"` - UserID int64 `json:"user_id"` - WithheldInCountries []string `json:"withheld_in_countries"` -} - -type statusWithheldNotice struct { - StatusWithheld *StatusWithheld `json:"status_withheld"` -} - -// UserWithheld indicates a User with the given ID has been withheld in -// certain countries. -// https://dev.twitter.com/streaming/overview/messages-types#withheld_content_notices -type UserWithheld struct { - ID int64 `json:"id"` - WithheldInCountries []string `json:"withheld_in_countries"` -} -type userWithheldNotice struct { - UserWithheld *UserWithheld `json:"user_withheld"` -} - -// StreamDisconnect indicates the stream has been shutdown for some reason. -// https://dev.twitter.com/streaming/overview/messages-types#disconnect_messages -type StreamDisconnect struct { - Code int64 `json:"code"` - StreamName string `json:"stream_name"` - Reason string `json:"reason"` -} - -type streamDisconnectNotice struct { - StreamDisconnect *StreamDisconnect `json:"disconnect"` -} - -// StallWarning indicates the client is falling behind in the stream. -// https://dev.twitter.com/streaming/overview/messages-types#stall_warnings -type StallWarning struct { - Code string `json:"code"` - Message string `json:"message"` - PercentFull int `json:"percent_full"` -} - -type stallWarningNotice struct { - StallWarning *StallWarning `json:"warning"` -} - -// FriendsList is a list of some of a user's friends. -// https://dev.twitter.com/streaming/overview/messages-types#friends_list_friends -type FriendsList struct { - Friends []int64 `json:"friends"` -} - -type directMessageNotice struct { - DirectMessage *DirectMessage `json:"direct_message"` -} - -// Event is a non-Tweet notification message (e.g. like, retweet, follow). -// https://dev.twitter.com/streaming/overview/messages-types#Events_event -type Event struct { - Event string `json:"event"` - CreatedAt string `json:"created_at"` - Target *User `json:"target"` - Source *User `json:"source"` - // TODO: add List or deprecate it - TargetObject *Tweet `json:"target_object"` -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/stream_utils.go b/vendor/github.com/dghubble/go-twitter/twitter/stream_utils.go deleted file mode 100644 index 092efa100..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/stream_utils.go +++ /dev/null @@ -1,95 +0,0 @@ -package twitter - -import ( - "bufio" - "bytes" - "io" - "time" -) - -// stopped returns true if the done channel receives, false otherwise. -func stopped(done <-chan struct{}) bool { - select { - case <-done: - return true - default: - return false - } -} - -// sleepOrDone pauses the current goroutine until the done channel receives -// or until at least the duration d has elapsed, whichever comes first. This -// is similar to time.Sleep(d), except it can be interrupted. -func sleepOrDone(d time.Duration, done <-chan struct{}) { - sleep := time.NewTimer(d) - defer sleep.Stop() - select { - case <-sleep.C: - return - case <-done: - return - } -} - -// streamResponseBodyReader is a buffered reader for Twitter stream response -// body. It can scan the arbitrary length of response body unlike bufio.Scanner. -type streamResponseBodyReader struct { - reader *bufio.Reader - buf bytes.Buffer -} - -// newStreamResponseBodyReader returns an instance of streamResponseBodyReader -// for the given Twitter stream response body. -func newStreamResponseBodyReader(body io.Reader) *streamResponseBodyReader { - return &streamResponseBodyReader{reader: bufio.NewReader(body)} -} - -// readNext reads Twitter stream response body and returns the next stream -// content if exists. Returns io.EOF error if we reached the end of the stream -// and there's no more message to read. -func (r *streamResponseBodyReader) readNext() ([]byte, error) { - // Discard all the bytes from buf and continue to use the allocated memory - // space for reading the next message. - r.buf.Truncate(0) - for { - // Twitter stream messages are separated with "\r\n", and a valid - // message may sometimes contain '\n' in the middle. - // bufio.Reader.Read() can accept one byte delimiter only, so we need to - // first break out each line on '\n' and then check whether the line ends - // with "\r\n" to find message boundaries. - // https://dev.twitter.com/streaming/overview/processing - line, err := r.reader.ReadBytes('\n') - // Non-EOF error should be propagated to callers immediately. - if err != nil && err != io.EOF { - return nil, err - } - // EOF error means that we reached the end of the stream body before finding - // delimiter '\n'. If "line" is empty, it means the reader didn't read any - // data from the stream before reaching EOF and there's nothing to append to - // buf. - if err == io.EOF && len(line) == 0 { - // if buf has no data, propagate io.EOF to callers and let them know that - // we've finished processing the stream. - if r.buf.Len() == 0 { - return nil, err - } - // Otherwise, we still have a remaining stream message to return. - break - } - // If the line ends with "\r\n", it's the end of one stream message data. - if bytes.HasSuffix(line, []byte("\r\n")) { - // reader.ReadBytes() returns a slice including the delimiter itself, so - // we need to trim '\n' as well as '\r' from the end of the slice. - r.buf.Write(bytes.TrimRight(line, "\r\n")) - break - } - // Otherwise, the line is not the end of a stream message, so we append - // the line to buf and continue to scan lines. - r.buf.Write(line) - } - - // Get the stream message bytes from buf. Not that Bytes() won't mark the - // returned data as "read", and we need to explicitly call Truncate(0) to - // discard from buf before writing the next stream message to buf. - return r.buf.Bytes(), nil -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/stream_utils_test.go b/vendor/github.com/dghubble/go-twitter/twitter/stream_utils_test.go deleted file mode 100644 index 6884d8af3..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/stream_utils_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package twitter - -import ( - "bufio" - "bytes" - "io" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestStopped(t *testing.T) { - done := make(chan struct{}) - assert.False(t, stopped(done)) - close(done) - assert.True(t, stopped(done)) -} - -func TestSleepOrDone_Sleep(t *testing.T) { - wait := time.Nanosecond * 20 - done := make(chan struct{}) - completed := make(chan struct{}) - go func() { - sleepOrDone(wait, done) - close(completed) - }() - // wait for goroutine SleepOrDone to sleep - assertDone(t, completed, defaultTestTimeout) -} - -func TestSleepOrDone_Done(t *testing.T) { - wait := time.Second * 5 - done := make(chan struct{}) - completed := make(chan struct{}) - go func() { - sleepOrDone(wait, done) - close(completed) - }() - // close done, interrupting SleepOrDone - close(done) - // assert that SleepOrDone exited, closing completed - assertDone(t, completed, defaultTestTimeout) -} - -func TestStreamResponseBodyReader(t *testing.T) { - cases := []struct { - in []byte - want [][]byte - }{ - { - in: []byte("foo\r\nbar\r\n"), - want: [][]byte{ - []byte("foo"), - []byte("bar"), - }, - }, - { - in: []byte("foo\nbar\r\n"), - want: [][]byte{ - []byte("foo\nbar"), - }, - }, - { - in: []byte("foo\r\n\r\n"), - want: [][]byte{ - []byte("foo"), - []byte(""), - }, - }, - { - in: []byte("foo\r\nbar"), - want: [][]byte{ - []byte("foo"), - []byte("bar"), - }, - }, - { - // Message length is more than bufio.MaxScanTokenSize, which can't be - // parsed by bufio.Scanner with default buffer size. - in: []byte(strings.Repeat("X", bufio.MaxScanTokenSize+1) + "\r\n"), - want: [][]byte{ - []byte(strings.Repeat("X", bufio.MaxScanTokenSize+1)), - }, - }, - } - - for _, c := range cases { - body := bytes.NewReader(c.in) - reader := newStreamResponseBodyReader(body) - - for i, want := range c.want { - data, err := reader.readNext() - if err != nil { - t.Errorf("reader(%q).readNext() * %d: err == %q, want nil", c.in, i, err) - } - if !bytes.Equal(data, want) { - t.Errorf("reader(%q).readNext() * %d: data == %q, want %q", c.in, i, data, want) - } - } - - data, err := reader.readNext() - if err != io.EOF { - t.Errorf("reader(%q).readNext() * %d: err == %q, want io.EOF", c.in, len(c.want), err) - } - if len(data) != 0 { - t.Errorf("reader(%q).readNext() * %d: data == %q, want \"\"", c.in, len(c.want), data) - } - } -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/streams.go b/vendor/github.com/dghubble/go-twitter/twitter/streams.go deleted file mode 100644 index 3ff01ee19..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/streams.go +++ /dev/null @@ -1,323 +0,0 @@ -package twitter - -import ( - "encoding/json" - "io" - "net/http" - "sync" - "time" - - "github.com/cenkalti/backoff" - "github.com/dghubble/sling" -) - -const ( - userAgent = "go-twitter v0.1" - publicStream = "https://stream.twitter.com/1.1/" - userStream = "https://userstream.twitter.com/1.1/" - siteStream = "https://sitestream.twitter.com/1.1/" -) - -// StreamService provides methods for accessing the Twitter Streaming API. -type StreamService struct { - client *http.Client - public *sling.Sling - user *sling.Sling - site *sling.Sling -} - -// newStreamService returns a new StreamService. -func newStreamService(client *http.Client, sling *sling.Sling) *StreamService { - sling.Set("User-Agent", userAgent) - return &StreamService{ - client: client, - public: sling.New().Base(publicStream).Path("statuses/"), - user: sling.New().Base(userStream), - site: sling.New().Base(siteStream), - } -} - -// StreamFilterParams are parameters for StreamService.Filter. -type StreamFilterParams struct { - FilterLevel string `url:"filter_level,omitempty"` - Follow []string `url:"follow,omitempty,comma"` - Language []string `url:"language,omitempty,comma"` - Locations []string `url:"locations,omitempty,comma"` - StallWarnings *bool `url:"stall_warnings,omitempty"` - Track []string `url:"track,omitempty,comma"` -} - -// Filter returns messages that match one or more filter predicates. -// https://dev.twitter.com/streaming/reference/post/statuses/filter -func (srv *StreamService) Filter(params *StreamFilterParams) (*Stream, error) { - req, err := srv.public.New().Post("filter.json").QueryStruct(params).Request() - if err != nil { - return nil, err - } - return newStream(srv.client, req), nil -} - -// StreamSampleParams are the parameters for StreamService.Sample. -type StreamSampleParams struct { - StallWarnings *bool `url:"stall_warnings,omitempty"` - Language []string `url:"language,omitempty,comma"` -} - -// Sample returns a small sample of public stream messages. -// https://dev.twitter.com/streaming/reference/get/statuses/sample -func (srv *StreamService) Sample(params *StreamSampleParams) (*Stream, error) { - req, err := srv.public.New().Get("sample.json").QueryStruct(params).Request() - if err != nil { - return nil, err - } - return newStream(srv.client, req), nil -} - -// StreamUserParams are the parameters for StreamService.User. -type StreamUserParams struct { - FilterLevel string `url:"filter_level,omitempty"` - Language []string `url:"language,omitempty,comma"` - Locations []string `url:"locations,omitempty,comma"` - Replies string `url:"replies,omitempty"` - StallWarnings *bool `url:"stall_warnings,omitempty"` - Track []string `url:"track,omitempty,comma"` - With string `url:"with,omitempty"` -} - -// User returns a stream of messages specific to the authenticated User. -// https://dev.twitter.com/streaming/reference/get/user -func (srv *StreamService) User(params *StreamUserParams) (*Stream, error) { - req, err := srv.user.New().Get("user.json").QueryStruct(params).Request() - if err != nil { - return nil, err - } - return newStream(srv.client, req), nil -} - -// StreamSiteParams are the parameters for StreamService.Site. -type StreamSiteParams struct { - FilterLevel string `url:"filter_level,omitempty"` - Follow []string `url:"follow,omitempty,comma"` - Language []string `url:"language,omitempty,comma"` - Replies string `url:"replies,omitempty"` - StallWarnings *bool `url:"stall_warnings,omitempty"` - With string `url:"with,omitempty"` -} - -// Site returns messages for a set of users. -// Requires special permission to access. -// https://dev.twitter.com/streaming/reference/get/site -func (srv *StreamService) Site(params *StreamSiteParams) (*Stream, error) { - req, err := srv.site.New().Get("site.json").QueryStruct(params).Request() - if err != nil { - return nil, err - } - return newStream(srv.client, req), nil -} - -// StreamFirehoseParams are the parameters for StreamService.Firehose. -type StreamFirehoseParams struct { - Count int `url:"count,omitempty"` - FilterLevel string `url:"filter_level,omitempty"` - Language []string `url:"language,omitempty,comma"` - StallWarnings *bool `url:"stall_warnings,omitempty"` -} - -// Firehose returns all public messages and statuses. -// Requires special permission to access. -// https://dev.twitter.com/streaming/reference/get/statuses/firehose -func (srv *StreamService) Firehose(params *StreamFirehoseParams) (*Stream, error) { - req, err := srv.public.New().Get("firehose.json").QueryStruct(params).Request() - if err != nil { - return nil, err - } - return newStream(srv.client, req), nil -} - -// Stream maintains a connection to the Twitter Streaming API, receives -// messages from the streaming response, and sends them on the Messages -// channel from a goroutine. The stream goroutine stops itself if an EOF is -// reached or retry errors occur, also closing the Messages channel. -// -// The client must Stop() the stream when finished receiving, which will -// wait until the stream is properly stopped. -type Stream struct { - client *http.Client - Messages chan interface{} - done chan struct{} - group *sync.WaitGroup - body io.Closer -} - -// newStream creates a Stream and starts a goroutine to retry connecting and -// receive from a stream response. The goroutine may stop due to retry errors -// or be stopped by calling Stop() on the stream. -func newStream(client *http.Client, req *http.Request) *Stream { - s := &Stream{ - client: client, - Messages: make(chan interface{}), - done: make(chan struct{}), - group: &sync.WaitGroup{}, - } - s.group.Add(1) - go s.retry(req, newExponentialBackOff(), newAggressiveExponentialBackOff()) - return s -} - -// Stop signals retry and receiver to stop, closes the Messages channel, and -// blocks until done. -func (s *Stream) Stop() { - close(s.done) - // Scanner does not have a Stop() or take a done channel, so for low volume - // streams Scan() blocks until the next keep-alive. Close the resp.Body to - // escape and stop the stream in a timely fashion. - if s.body != nil { - s.body.Close() - } - // block until the retry goroutine stops - s.group.Wait() -} - -// retry retries making the given http.Request and receiving the response -// according to the Twitter backoff policies. Callers should invoke in a -// goroutine since backoffs sleep between retries. -// https://dev.twitter.com/streaming/overview/connecting -func (s *Stream) retry(req *http.Request, expBackOff backoff.BackOff, aggExpBackOff backoff.BackOff) { - // close Messages channel and decrement the wait group counter - defer close(s.Messages) - defer s.group.Done() - - var wait time.Duration - for !stopped(s.done) { - resp, err := s.client.Do(req) - if err != nil { - // stop retrying for HTTP protocol errors - s.Messages <- err - return - } - // when err is nil, resp contains a non-nil Body which must be closed - defer resp.Body.Close() - s.body = resp.Body - switch resp.StatusCode { - case 200: - // receive stream response Body, handles closing - s.receive(resp.Body) - expBackOff.Reset() - aggExpBackOff.Reset() - case 503: - // exponential backoff - wait = expBackOff.NextBackOff() - case 420, 429: - // aggressive exponential backoff - wait = aggExpBackOff.NextBackOff() - default: - // stop retrying for other response codes - resp.Body.Close() - return - } - // close response before each retry - resp.Body.Close() - if wait == backoff.Stop { - return - } - sleepOrDone(wait, s.done) - } -} - -// receive scans a stream response body, JSON decodes tokens to messages, and -// sends messages to the Messages channel. Receiving continues until an EOF, -// scan error, or the done channel is closed. -func (s *Stream) receive(body io.Reader) { - reader := newStreamResponseBodyReader(body) - for !stopped(s.done) { - data, err := reader.readNext() - if err != nil { - return - } - if len(data) == 0 { - // empty keep-alive - continue - } - select { - // send messages, data, or errors - case s.Messages <- getMessage(data): - continue - // allow client to Stop(), even if not receiving - case <-s.done: - return - } - } -} - -// getMessage unmarshals the token and returns a message struct, if the type -// can be determined. Otherwise, returns the token unmarshalled into a data -// map[string]interface{} or the unmarshal error. -func getMessage(token []byte) interface{} { - var data map[string]interface{} - // unmarshal JSON encoded token into a map for - err := json.Unmarshal(token, &data) - if err != nil { - return err - } - return decodeMessage(token, data) -} - -// decodeMessage determines the message type from known data keys, allocates -// at most one message struct, and JSON decodes the token into the message. -// Returns the message struct or the data map if the message type could not be -// determined. -func decodeMessage(token []byte, data map[string]interface{}) interface{} { - if hasPath(data, "retweet_count") { - tweet := new(Tweet) - json.Unmarshal(token, tweet) - return tweet - } else if hasPath(data, "direct_message") { - notice := new(directMessageNotice) - json.Unmarshal(token, notice) - return notice.DirectMessage - } else if hasPath(data, "delete") { - notice := new(statusDeletionNotice) - json.Unmarshal(token, notice) - return notice.Delete.StatusDeletion - } else if hasPath(data, "scrub_geo") { - notice := new(locationDeletionNotice) - json.Unmarshal(token, notice) - return notice.ScrubGeo - } else if hasPath(data, "limit") { - notice := new(streamLimitNotice) - json.Unmarshal(token, notice) - return notice.Limit - } else if hasPath(data, "status_withheld") { - notice := new(statusWithheldNotice) - json.Unmarshal(token, notice) - return notice.StatusWithheld - } else if hasPath(data, "user_withheld") { - notice := new(userWithheldNotice) - json.Unmarshal(token, notice) - return notice.UserWithheld - } else if hasPath(data, "disconnect") { - notice := new(streamDisconnectNotice) - json.Unmarshal(token, notice) - return notice.StreamDisconnect - } else if hasPath(data, "warning") { - notice := new(stallWarningNotice) - json.Unmarshal(token, notice) - return notice.StallWarning - } else if hasPath(data, "friends") { - friendsList := new(FriendsList) - json.Unmarshal(token, friendsList) - return friendsList - } else if hasPath(data, "event") { - event := new(Event) - json.Unmarshal(token, event) - return event - } - // message type unknown, return the data map[string]interface{} - return data -} - -// hasPath returns true if the map contains the given key, false otherwise. -func hasPath(data map[string]interface{}, key string) bool { - _, ok := data[key] - return ok -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/streams_test.go b/vendor/github.com/dghubble/go-twitter/twitter/streams_test.go deleted file mode 100644 index 633b3eeb2..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/streams_test.go +++ /dev/null @@ -1,393 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "strings" - "sync" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestStream_MessageJSONError(t *testing.T) { - badJSON := []byte(`{`) - msg := getMessage(badJSON) - assert.EqualError(t, msg.(error), "unexpected end of JSON input") -} - -func TestStream_GetMessageTweet(t *testing.T) { - msgJSON := []byte(`{"id": 20, "text": "just setting up my twttr", "retweet_count": "68535"}`) - msg := getMessage(msgJSON) - assert.IsType(t, &Tweet{}, msg) -} - -func TestStream_GetMessageDirectMessage(t *testing.T) { - msgJSON := []byte(`{"direct_message": {"id": 666024290140217347}}`) - msg := getMessage(msgJSON) - assert.IsType(t, &DirectMessage{}, msg) -} - -func TestStream_GetMessageDelete(t *testing.T) { - msgJSON := []byte(`{"delete": { "id": 20}}`) - msg := getMessage(msgJSON) - assert.IsType(t, &StatusDeletion{}, msg) -} - -func TestStream_GetMessageLocationDeletion(t *testing.T) { - msgJSON := []byte(`{"scrub_geo": { "up_to_status_id": 20}}`) - msg := getMessage(msgJSON) - assert.IsType(t, &LocationDeletion{}, msg) -} - -func TestStream_GetMessageStreamLimit(t *testing.T) { - msgJSON := []byte(`{"limit": { "track": 10 }}`) - msg := getMessage(msgJSON) - assert.IsType(t, &StreamLimit{}, msg) -} - -func TestStream_StatusWithheld(t *testing.T) { - msgJSON := []byte(`{"status_withheld": { "id": 20, "user_id": 12, "withheld_in_countries":["USA", "China"] }}`) - msg := getMessage(msgJSON) - assert.IsType(t, &StatusWithheld{}, msg) -} - -func TestStream_UserWithheld(t *testing.T) { - msgJSON := []byte(`{"user_withheld": { "id": 12, "withheld_in_countries":["USA", "China"] }}`) - msg := getMessage(msgJSON) - assert.IsType(t, &UserWithheld{}, msg) -} - -func TestStream_StreamDisconnect(t *testing.T) { - msgJSON := []byte(`{"disconnect": { "code": "420", "stream_name": "streaming stuff", "reason": "too many connections" }}`) - msg := getMessage(msgJSON) - assert.IsType(t, &StreamDisconnect{}, msg) -} - -func TestStream_StallWarning(t *testing.T) { - msgJSON := []byte(`{"warning": { "code": "420", "percent_full": 90, "message": "a lot of messages" }}`) - msg := getMessage(msgJSON) - assert.IsType(t, &StallWarning{}, msg) -} - -func TestStream_FriendsList(t *testing.T) { - msgJSON := []byte(`{"friends": [666024290140217347, 666024290140217349, 666024290140217342]}`) - msg := getMessage(msgJSON) - assert.IsType(t, &FriendsList{}, msg) -} - -func TestStream_Event(t *testing.T) { - msgJSON := []byte(`{"event": "block", "target": {"name": "XKCD Comic", "favourites_count": 2}, "source": {"name": "XKCD Comic2", "favourites_count": 3}, "created_at": "Sat Sep 4 16:10:54 +0000 2010"}`) - msg := getMessage(msgJSON) - assert.IsType(t, &Event{}, msg) -} - -func TestStream_Unknown(t *testing.T) { - msgJSON := []byte(`{"unknown_data": {"new_twitter_type":"unexpected"}}`) - msg := getMessage(msgJSON) - assert.IsType(t, map[string]interface{}{}, msg) -} - -func TestStream_Filter(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/1.1/statuses/filter.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "POST", r) - assertQuery(t, map[string]string{"track": "gophercon,golang"}, r) - switch reqCount { - case 0: - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Transfer-Encoding", "chunked") - fmt.Fprintf(w, - `{"text": "Gophercon talks!"}`+"\r\n"+ - `{"text": "Gophercon super talks!"}`+"\r\n", - ) - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - - counts := &counter{} - demux := newCounterDemux(counts) - client := NewClient(httpClient) - streamFilterParams := &StreamFilterParams{ - Track: []string{"gophercon", "golang"}, - } - stream, err := client.Streams.Filter(streamFilterParams) - // assert that the expected messages are received - assert.NoError(t, err) - defer stream.Stop() - for message := range stream.Messages { - demux.Handle(message) - } - expectedCounts := &counter{all: 2, other: 2} - assert.Equal(t, expectedCounts, counts) -} - -func TestStream_Sample(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/1.1/statuses/sample.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"stall_warnings": "true"}, r) - switch reqCount { - case 0: - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Transfer-Encoding", "chunked") - fmt.Fprintf(w, - `{"text": "Gophercon talks!"}`+"\r\n"+ - `{"text": "Gophercon super talks!"}`+"\r\n", - ) - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - - counts := &counter{} - demux := newCounterDemux(counts) - client := NewClient(httpClient) - streamSampleParams := &StreamSampleParams{ - StallWarnings: Bool(true), - } - stream, err := client.Streams.Sample(streamSampleParams) - // assert that the expected messages are received - assert.NoError(t, err) - defer stream.Stop() - for message := range stream.Messages { - demux.Handle(message) - } - expectedCounts := &counter{all: 2, other: 2} - assert.Equal(t, expectedCounts, counts) -} - -func TestStream_User(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/1.1/user.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"stall_warnings": "true", "with": "followings"}, r) - switch reqCount { - case 0: - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Transfer-Encoding", "chunked") - fmt.Fprintf(w, `{"friends": [666024290140217347, 666024290140217349, 666024290140217342]}`+"\r\n"+"\r\n") - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - - counts := &counter{} - demux := newCounterDemux(counts) - client := NewClient(httpClient) - streamUserParams := &StreamUserParams{ - StallWarnings: Bool(true), - With: "followings", - } - stream, err := client.Streams.User(streamUserParams) - // assert that the expected messages are received - assert.NoError(t, err) - defer stream.Stop() - for message := range stream.Messages { - demux.Handle(message) - } - expectedCounts := &counter{all: 1, friendsList: 1} - assert.Equal(t, expectedCounts, counts) -} - -func TestStream_User_TooManyFriends(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/1.1/user.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"stall_warnings": "true", "with": "followings"}, r) - switch reqCount { - case 0: - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Transfer-Encoding", "chunked") - // The first friend list message is more than bufio.MaxScanTokenSize (65536) bytes - friendsList := "[" + strings.Repeat("1234567890, ", 7000) + "1234567890]" - fmt.Fprintf(w, `{"friends": %s}`+"\r\n"+"\r\n", friendsList) - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - - counts := &counter{} - demux := newCounterDemux(counts) - client := NewClient(httpClient) - streamUserParams := &StreamUserParams{ - StallWarnings: Bool(true), - With: "followings", - } - stream, err := client.Streams.User(streamUserParams) - // assert that the expected messages are received - assert.NoError(t, err) - defer stream.Stop() - for message := range stream.Messages { - demux.Handle(message) - } - expectedCounts := &counter{all: 1, friendsList: 1} - assert.Equal(t, expectedCounts, counts) -} - -func TestStream_Site(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/1.1/site.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"follow": "666024290140217347,666024290140217349"}, r) - switch reqCount { - case 0: - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Transfer-Encoding", "chunked") - fmt.Fprintf(w, - `{"text": "Gophercon talks!"}`+"\r\n"+ - `{"text": "Gophercon super talks!"}`+"\r\n", - ) - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - - counts := &counter{} - demux := newCounterDemux(counts) - client := NewClient(httpClient) - streamSiteParams := &StreamSiteParams{ - Follow: []string{"666024290140217347", "666024290140217349"}, - } - stream, err := client.Streams.Site(streamSiteParams) - // assert that the expected messages are received - assert.NoError(t, err) - defer stream.Stop() - for message := range stream.Messages { - demux.Handle(message) - } - expectedCounts := &counter{all: 2, other: 2} - assert.Equal(t, expectedCounts, counts) -} - -func TestStream_PublicFirehose(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/1.1/statuses/firehose.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"count": "100"}, r) - switch reqCount { - case 0: - w.Header().Set("Content-Type", "application/json") - w.Header().Set("Transfer-Encoding", "chunked") - fmt.Fprintf(w, - `{"text": "Gophercon talks!"}`+"\r\n"+ - `{"text": "Gophercon super talks!"}`+"\r\n", - ) - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - - counts := &counter{} - demux := newCounterDemux(counts) - client := NewClient(httpClient) - streamFirehoseParams := &StreamFirehoseParams{ - Count: 100, - } - stream, err := client.Streams.Firehose(streamFirehoseParams) - // assert that the expected messages are received - assert.NoError(t, err) - defer stream.Stop() - for message := range stream.Messages { - demux.Handle(message) - } - expectedCounts := &counter{all: 2, other: 2} - assert.Equal(t, expectedCounts, counts) -} - -func TestStreamRetry_ExponentialBackoff(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - switch reqCount { - case 0: - http.Error(w, "Service Unavailable", 503) - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - stream := &Stream{ - client: httpClient, - Messages: make(chan interface{}), - done: make(chan struct{}), - group: &sync.WaitGroup{}, - } - stream.group.Add(1) - req, _ := http.NewRequest("GET", "http://example.com/", nil) - expBackoff := &BackOffRecorder{} - // receive messages and throw them away - go NewSwitchDemux().HandleChan(stream.Messages) - stream.retry(req, expBackoff, nil) - defer stream.Stop() - // assert exponential backoff in response to 503 - assert.Equal(t, 1, expBackoff.Count) -} - -func TestStreamRetry_AggressiveBackoff(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - reqCount := 0 - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - switch reqCount { - case 0: - http.Error(w, "Enhance Your Calm", 420) - case 1: - http.Error(w, "Too Many Requests", 429) - default: - // Only allow first request - http.Error(w, "Stream API not available!", 130) - } - reqCount++ - }) - stream := &Stream{ - client: httpClient, - Messages: make(chan interface{}), - done: make(chan struct{}), - group: &sync.WaitGroup{}, - } - stream.group.Add(1) - req, _ := http.NewRequest("GET", "http://example.com/", nil) - aggExpBackoff := &BackOffRecorder{} - // receive messages and throw them away - go NewSwitchDemux().HandleChan(stream.Messages) - stream.retry(req, nil, aggExpBackoff) - defer stream.Stop() - // assert aggressive exponential backoff in response to 420 and 429 - assert.Equal(t, 2, aggExpBackoff.Count) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/timelines.go b/vendor/github.com/dghubble/go-twitter/twitter/timelines.go deleted file mode 100644 index 0fa4e1233..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/timelines.go +++ /dev/null @@ -1,109 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// TimelineService provides methods for accessing Twitter status timeline -// API endpoints. -type TimelineService struct { - sling *sling.Sling -} - -// newTimelineService returns a new TimelineService. -func newTimelineService(sling *sling.Sling) *TimelineService { - return &TimelineService{ - sling: sling.Path("statuses/"), - } -} - -// UserTimelineParams are the parameters for TimelineService.UserTimeline. -type UserTimelineParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - Count int `url:"count,omitempty"` - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - ExcludeReplies *bool `url:"exclude_replies,omitempty"` - IncludeRetweets *bool `url:"include_rts,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// UserTimeline returns recent Tweets from the specified user. -// https://dev.twitter.com/rest/reference/get/statuses/user_timeline -func (s *TimelineService) UserTimeline(params *UserTimelineParams) ([]Tweet, *http.Response, error) { - tweets := new([]Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("user_timeline.json").QueryStruct(params).Receive(tweets, apiError) - return *tweets, resp, relevantError(err, *apiError) -} - -// HomeTimelineParams are the parameters for TimelineService.HomeTimeline. -type HomeTimelineParams struct { - Count int `url:"count,omitempty"` - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - ExcludeReplies *bool `url:"exclude_replies,omitempty"` - ContributorDetails *bool `url:"contributor_details,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// HomeTimeline returns recent Tweets and retweets from the user and those -// users they follow. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/get/statuses/home_timeline -func (s *TimelineService) HomeTimeline(params *HomeTimelineParams) ([]Tweet, *http.Response, error) { - tweets := new([]Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("home_timeline.json").QueryStruct(params).Receive(tweets, apiError) - return *tweets, resp, relevantError(err, *apiError) -} - -// MentionTimelineParams are the parameters for TimelineService.MentionTimeline. -type MentionTimelineParams struct { - Count int `url:"count,omitempty"` - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - ContributorDetails *bool `url:"contributor_details,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// MentionTimeline returns recent Tweet mentions of the authenticated user. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/get/statuses/mentions_timeline -func (s *TimelineService) MentionTimeline(params *MentionTimelineParams) ([]Tweet, *http.Response, error) { - tweets := new([]Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("mentions_timeline.json").QueryStruct(params).Receive(tweets, apiError) - return *tweets, resp, relevantError(err, *apiError) -} - -// RetweetsOfMeTimelineParams are the parameters for -// TimelineService.RetweetsOfMeTimeline. -type RetweetsOfMeTimelineParams struct { - Count int `url:"count,omitempty"` - SinceID int64 `url:"since_id,omitempty"` - MaxID int64 `url:"max_id,omitempty"` - TrimUser *bool `url:"trim_user,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` - IncludeUserEntities *bool `url:"include_user_entities"` - TweetMode string `url:"tweet_mode,omitempty"` -} - -// RetweetsOfMeTimeline returns the most recent Tweets by the authenticated -// user that have been retweeted by others. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/get/statuses/retweets_of_me -func (s *TimelineService) RetweetsOfMeTimeline(params *RetweetsOfMeTimelineParams) ([]Tweet, *http.Response, error) { - tweets := new([]Tweet) - apiError := new(APIError) - resp, err := s.sling.New().Get("retweets_of_me.json").QueryStruct(params).Receive(tweets, apiError) - return *tweets, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/timelines_test.go b/vendor/github.com/dghubble/go-twitter/twitter/timelines_test.go deleted file mode 100644 index 40550c974..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/timelines_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestTimelineService_UserTimeline(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/user_timeline.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"user_id": "113419064", "trim_user": "true", "include_rts": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"text": "Gophercon talks!"}, {"text": "Why gophers are so adorable"}]`) - }) - - client := NewClient(httpClient) - tweets, _, err := client.Timelines.UserTimeline(&UserTimelineParams{UserID: 113419064, TrimUser: Bool(true), IncludeRetweets: Bool(false)}) - expected := []Tweet{Tweet{Text: "Gophercon talks!"}, Tweet{Text: "Why gophers are so adorable"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweets) -} - -func TestTimelineService_HomeTimeline(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/home_timeline.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"since_id": "589147592367431680", "exclude_replies": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"text": "Live on #Periscope"}, {"text": "Clickbait journalism"}, {"text": "Useful announcement"}]`) - }) - - client := NewClient(httpClient) - tweets, _, err := client.Timelines.HomeTimeline(&HomeTimelineParams{SinceID: 589147592367431680, ExcludeReplies: Bool(false)}) - expected := []Tweet{Tweet{Text: "Live on #Periscope"}, Tweet{Text: "Clickbait journalism"}, Tweet{Text: "Useful announcement"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweets) -} - -func TestTimelineService_MentionTimeline(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/mentions_timeline.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"count": "20", "include_entities": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"text": "@dghubble can I get verified?"}, {"text": "@dghubble why are gophers so great?"}]`) - }) - - client := NewClient(httpClient) - tweets, _, err := client.Timelines.MentionTimeline(&MentionTimelineParams{Count: 20, IncludeEntities: Bool(false)}) - expected := []Tweet{Tweet{Text: "@dghubble can I get verified?"}, Tweet{Text: "@dghubble why are gophers so great?"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweets) -} - -func TestTimelineService_RetweetsOfMeTimeline(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/statuses/retweets_of_me.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"trim_user": "false", "include_user_entities": "false"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"text": "RT Twitter UK edition"}, {"text": "RT Triply-replicated Gophers"}]`) - }) - - client := NewClient(httpClient) - tweets, _, err := client.Timelines.RetweetsOfMeTimeline(&RetweetsOfMeTimelineParams{TrimUser: Bool(false), IncludeUserEntities: Bool(false)}) - expected := []Tweet{Tweet{Text: "RT Twitter UK edition"}, Tweet{Text: "RT Triply-replicated Gophers"}} - assert.Nil(t, err) - assert.Equal(t, expected, tweets) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/trends.go b/vendor/github.com/dghubble/go-twitter/twitter/trends.go deleted file mode 100644 index b68a698ce..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/trends.go +++ /dev/null @@ -1,102 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// TrendsService provides methods for accessing Twitter trends API endpoints. -type TrendsService struct { - sling *sling.Sling -} - -// newTrendsService returns a new TrendsService. -func newTrendsService(sling *sling.Sling) *TrendsService { - return &TrendsService{ - sling: sling.Path("trends/"), - } -} - -// PlaceType represents a twitter trends PlaceType. -type PlaceType struct { - Code int `json:"code"` - Name string `json:"name"` -} - -// Location reporesents a twitter Location. -type Location struct { - Country string `json:"country"` - CountryCode string `json:"countryCode"` - Name string `json:"name"` - ParentID int `json:"parentid"` - PlaceType PlaceType `json:"placeType"` - URL string `json:"url"` - WOEID int64 `json:"woeid"` -} - -// Available returns the locations that Twitter has trending topic information for. -// https://dev.twitter.com/rest/reference/get/trends/available -func (s *TrendsService) Available() ([]Location, *http.Response, error) { - locations := new([]Location) - apiError := new(APIError) - resp, err := s.sling.New().Get("available.json").Receive(locations, apiError) - return *locations, resp, relevantError(err, *apiError) -} - -// Trend represents a twitter trend. -type Trend struct { - Name string `json:"name"` - URL string `json:"url"` - PromotedContent string `json:"promoted_content"` - Query string `json:"query"` - TweetVolume int64 `json:"tweet_volume"` -} - -// TrendsList represents a list of twitter trends. -type TrendsList struct { - Trends []Trend `json:"trends"` - AsOf string `json:"as_of"` - CreatedAt string `json:"created_at"` - Locations []TrendsLocation `json:"locations"` -} - -// TrendsLocation represents a twitter trend location. -type TrendsLocation struct { - Name string `json:"name"` - WOEID int64 `json:"woeid"` -} - -// TrendsPlaceParams are the parameters for Trends.Place. -type TrendsPlaceParams struct { - WOEID int64 `url:"id,omitempty"` - Exclude string `url:"exclude,omitempty"` -} - -// Place returns the top 50 trending topics for a specific WOEID. -// https://dev.twitter.com/rest/reference/get/trends/place -func (s *TrendsService) Place(woeid int64, params *TrendsPlaceParams) ([]TrendsList, *http.Response, error) { - if params == nil { - params = &TrendsPlaceParams{} - } - trendsList := new([]TrendsList) - params.WOEID = woeid - apiError := new(APIError) - resp, err := s.sling.New().Get("place.json").QueryStruct(params).Receive(trendsList, apiError) - return *trendsList, resp, relevantError(err, *apiError) -} - -// ClosestParams are the parameters for Trends.Closest. -type ClosestParams struct { - Lat float64 `url:"lat"` - Long float64 `url:"long"` -} - -// Closest returns the locations that Twitter has trending topic information for, closest to a specified location. -// https://dev.twitter.com/rest/reference/get/trends/closest -func (s *TrendsService) Closest(params *ClosestParams) ([]Location, *http.Response, error) { - locations := new([]Location) - apiError := new(APIError) - resp, err := s.sling.New().Get("closest.json").QueryStruct(params).Receive(locations, apiError) - return *locations, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/trends_test.go b/vendor/github.com/dghubble/go-twitter/twitter/trends_test.go deleted file mode 100644 index b8612ad90..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/trends_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestTrendsService_Available(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/trends/available.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"country": "Sweden","countryCode": "SE","name": "Sweden","parentid": 1,"placeType": {"code": 12,"name": "Country"},"url": "http://where.yahooapis.com/v1/place/23424954","woeid": 23424954}]`) - }) - expected := []Location{ - Location{ - Country: "Sweden", - CountryCode: "SE", - Name: "Sweden", - ParentID: 1, - PlaceType: PlaceType{Code: 12, Name: "Country"}, - URL: "http://where.yahooapis.com/v1/place/23424954", - WOEID: 23424954, - }, - } - - client := NewClient(httpClient) - locations, _, err := client.Trends.Available() - assert.Nil(t, err) - assert.Equal(t, expected, locations) -} - -func TestTrendsService_Place(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/trends/place.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"id": "123456"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"trends":[{"name":"#gotwitter"}], "as_of": "2017-02-08T16:18:18Z", "created_at": "2017-02-08T16:10:33Z","locations":[{"name": "Worldwide","woeid": 1}]}]`) - }) - expected := []TrendsList{TrendsList{ - Trends: []Trend{Trend{Name: "#gotwitter"}}, - AsOf: "2017-02-08T16:18:18Z", - CreatedAt: "2017-02-08T16:10:33Z", - Locations: []TrendsLocation{TrendsLocation{Name: "Worldwide", WOEID: 1}}, - }} - - client := NewClient(httpClient) - places, _, err := client.Trends.Place(123456, &TrendsPlaceParams{}) - assert.Nil(t, err) - assert.Equal(t, expected, places) -} - -func TestTrendsService_Closest(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/trends/closest.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"lat": "37.781157", "long": "-122.400612831116"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"country": "Sweden","countryCode": "SE","name": "Sweden","parentid": 1,"placeType": {"code": 12,"name": "Country"},"url": "http://where.yahooapis.com/v1/place/23424954","woeid": 23424954}]`) - }) - expected := []Location{ - Location{ - Country: "Sweden", - CountryCode: "SE", - Name: "Sweden", - ParentID: 1, - PlaceType: PlaceType{Code: 12, Name: "Country"}, - URL: "http://where.yahooapis.com/v1/place/23424954", - WOEID: 23424954, - }, - } - - client := NewClient(httpClient) - locations, _, err := client.Trends.Closest(&ClosestParams{Lat: 37.781157, Long: -122.400612831116}) - assert.Nil(t, err) - assert.Equal(t, expected, locations) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/twitter.go b/vendor/github.com/dghubble/go-twitter/twitter/twitter.go deleted file mode 100644 index 96fbf9fbc..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/twitter.go +++ /dev/null @@ -1,61 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -const twitterAPI = "https://api.twitter.com/1.1/" - -// Client is a Twitter client for making Twitter API requests. -type Client struct { - sling *sling.Sling - // Twitter API Services - Accounts *AccountService - DirectMessages *DirectMessageService - Favorites *FavoriteService - Followers *FollowerService - Friends *FriendService - Friendships *FriendshipService - Search *SearchService - Statuses *StatusService - Streams *StreamService - Timelines *TimelineService - Trends *TrendsService - Users *UserService -} - -// NewClient returns a new Client. -func NewClient(httpClient *http.Client) *Client { - base := sling.New().Client(httpClient).Base(twitterAPI) - return &Client{ - sling: base, - Accounts: newAccountService(base.New()), - DirectMessages: newDirectMessageService(base.New()), - Favorites: newFavoriteService(base.New()), - Followers: newFollowerService(base.New()), - Friends: newFriendService(base.New()), - Friendships: newFriendshipService(base.New()), - Search: newSearchService(base.New()), - Statuses: newStatusService(base.New()), - Streams: newStreamService(httpClient, base.New()), - Timelines: newTimelineService(base.New()), - Trends: newTrendsService(base.New()), - Users: newUserService(base.New()), - } -} - -// Bool returns a new pointer to the given bool value. -func Bool(v bool) *bool { - ptr := new(bool) - *ptr = v - return ptr -} - -// Float returns a new pointer to the given float64 value. -func Float(v float64) *float64 { - ptr := new(float64) - *ptr = v - return ptr -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/twitter_test.go b/vendor/github.com/dghubble/go-twitter/twitter/twitter_test.go deleted file mode 100644 index 4b7ca2964..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/twitter_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package twitter - -import ( - "net/http" - "net/http/httptest" - "net/url" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -var defaultTestTimeout = time.Second * 1 - -// testServer returns an http Client, ServeMux, and Server. The client proxies -// requests to the server and handlers can be registered on the mux to handle -// requests. The caller must close the test server. -func testServer() (*http.Client, *http.ServeMux, *httptest.Server) { - mux := http.NewServeMux() - server := httptest.NewServer(mux) - transport := &RewriteTransport{&http.Transport{ - Proxy: func(req *http.Request) (*url.URL, error) { - return url.Parse(server.URL) - }, - }} - client := &http.Client{Transport: transport} - return client, mux, server -} - -// RewriteTransport rewrites https requests to http to avoid TLS cert issues -// during testing. -type RewriteTransport struct { - Transport http.RoundTripper -} - -// RoundTrip rewrites the request scheme to http and calls through to the -// composed RoundTripper or if it is nil, to the http.DefaultTransport. -func (t *RewriteTransport) RoundTrip(req *http.Request) (*http.Response, error) { - req.URL.Scheme = "http" - if t.Transport == nil { - return http.DefaultTransport.RoundTrip(req) - } - return t.Transport.RoundTrip(req) -} - -func assertMethod(t *testing.T, expectedMethod string, req *http.Request) { - assert.Equal(t, expectedMethod, req.Method) -} - -// assertQuery tests that the Request has the expected url query key/val pairs -func assertQuery(t *testing.T, expected map[string]string, req *http.Request) { - queryValues := req.URL.Query() - expectedValues := url.Values{} - for key, value := range expected { - expectedValues.Add(key, value) - } - assert.Equal(t, expectedValues, queryValues) -} - -// assertPostForm tests that the Request has the expected key values pairs url -// encoded in its Body -func assertPostForm(t *testing.T, expected map[string]string, req *http.Request) { - req.ParseForm() // parses request Body to put url.Values in r.Form/r.PostForm - expectedValues := url.Values{} - for key, value := range expected { - expectedValues.Add(key, value) - } - assert.Equal(t, expectedValues, req.Form) -} - -// assertDone asserts that the empty struct channel is closed before the given -// timeout elapses. -func assertDone(t *testing.T, ch <-chan struct{}, timeout time.Duration) { - select { - case <-ch: - _, more := <-ch - assert.False(t, more) - case <-time.After(timeout): - t.Errorf("expected channel to be closed within timeout %v", timeout) - } -} - -// assertClosed asserts that the channel is closed before the given timeout -// elapses. -func assertClosed(t *testing.T, ch <-chan interface{}, timeout time.Duration) { - select { - case <-ch: - _, more := <-ch - assert.False(t, more) - case <-time.After(timeout): - t.Errorf("expected channel to be closed within timeout %v", timeout) - } -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/users.go b/vendor/github.com/dghubble/go-twitter/twitter/users.go deleted file mode 100644 index 25be5c901..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/users.go +++ /dev/null @@ -1,122 +0,0 @@ -package twitter - -import ( - "net/http" - - "github.com/dghubble/sling" -) - -// User represents a Twitter User. -// https://dev.twitter.com/overview/api/users -type User struct { - ContributorsEnabled bool `json:"contributors_enabled"` - CreatedAt string `json:"created_at"` - DefaultProfile bool `json:"default_profile"` - DefaultProfileImage bool `json:"default_profile_image"` - Description string `json:"description"` - Email string `json:"email"` - Entities *UserEntities `json:"entities"` - FavouritesCount int `json:"favourites_count"` - FollowRequestSent bool `json:"follow_request_sent"` - Following bool `json:"following"` - FollowersCount int `json:"followers_count"` - FriendsCount int `json:"friends_count"` - GeoEnabled bool `json:"geo_enabled"` - ID int64 `json:"id"` - IDStr string `json:"id_str"` - IsTranslator bool `json:"is_translator"` - Lang string `json:"lang"` - ListedCount int `json:"listed_count"` - Location string `json:"location"` - Name string `json:"name"` - Notifications bool `json:"notifications"` - ProfileBackgroundColor string `json:"profile_background_color"` - ProfileBackgroundImageURL string `json:"profile_background_image_url"` - ProfileBackgroundImageURLHttps string `json:"profile_background_image_url_https"` - ProfileBackgroundTile bool `json:"profile_background_tile"` - ProfileBannerURL string `json:"profile_banner_url"` - ProfileImageURL string `json:"profile_image_url"` - ProfileImageURLHttps string `json:"profile_image_url_https"` - ProfileLinkColor string `json:"profile_link_color"` - ProfileSidebarBorderColor string `json:"profile_sidebar_border_color"` - ProfileSidebarFillColor string `json:"profile_sidebar_fill_color"` - ProfileTextColor string `json:"profile_text_color"` - ProfileUseBackgroundImage bool `json:"profile_use_background_image"` - Protected bool `json:"protected"` - ScreenName string `json:"screen_name"` - ShowAllInlineMedia bool `json:"show_all_inline_media"` - Status *Tweet `json:"status"` - StatusesCount int `json:"statuses_count"` - Timezone string `json:"time_zone"` - URL string `json:"url"` - UtcOffset int `json:"utc_offset"` - Verified bool `json:"verified"` - WithheldInCountries []string `json:"withheld_in_countries"` - WithholdScope string `json:"withheld_scope"` -} - -// UserService provides methods for accessing Twitter user API endpoints. -type UserService struct { - sling *sling.Sling -} - -// newUserService returns a new UserService. -func newUserService(sling *sling.Sling) *UserService { - return &UserService{ - sling: sling.Path("users/"), - } -} - -// UserShowParams are the parameters for UserService.Show. -type UserShowParams struct { - UserID int64 `url:"user_id,omitempty"` - ScreenName string `url:"screen_name,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` // whether 'status' should include entities -} - -// Show returns the requested User. -// https://dev.twitter.com/rest/reference/get/users/show -func (s *UserService) Show(params *UserShowParams) (*User, *http.Response, error) { - user := new(User) - apiError := new(APIError) - resp, err := s.sling.New().Get("show.json").QueryStruct(params).Receive(user, apiError) - return user, resp, relevantError(err, *apiError) -} - -// UserLookupParams are the parameters for UserService.Lookup. -type UserLookupParams struct { - UserID []int64 `url:"user_id,omitempty,comma"` - ScreenName []string `url:"screen_name,omitempty,comma"` - IncludeEntities *bool `url:"include_entities,omitempty"` // whether 'status' should include entities -} - -// Lookup returns the requested Users as a slice. -// https://dev.twitter.com/rest/reference/get/users/lookup -func (s *UserService) Lookup(params *UserLookupParams) ([]User, *http.Response, error) { - users := new([]User) - apiError := new(APIError) - resp, err := s.sling.New().Get("lookup.json").QueryStruct(params).Receive(users, apiError) - return *users, resp, relevantError(err, *apiError) -} - -// UserSearchParams are the parameters for UserService.Search. -type UserSearchParams struct { - Query string `url:"q,omitempty"` - Page int `url:"page,omitempty"` // 1-based page number - Count int `url:"count,omitempty"` - IncludeEntities *bool `url:"include_entities,omitempty"` // whether 'status' should include entities -} - -// Search queries public user accounts. -// Requires a user auth context. -// https://dev.twitter.com/rest/reference/get/users/search -func (s *UserService) Search(query string, params *UserSearchParams) ([]User, *http.Response, error) { - if params == nil { - params = &UserSearchParams{} - } - params.Query = query - users := new([]User) - apiError := new(APIError) - resp, err := s.sling.New().Get("search.json").QueryStruct(params).Receive(users, apiError) - return *users, resp, relevantError(err, *apiError) -} diff --git a/vendor/github.com/dghubble/go-twitter/twitter/users_test.go b/vendor/github.com/dghubble/go-twitter/twitter/users_test.go deleted file mode 100644 index 54e6c5f2d..000000000 --- a/vendor/github.com/dghubble/go-twitter/twitter/users_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package twitter - -import ( - "fmt" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestUserService_Show(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/users/show.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"screen_name": "xkcdComic"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `{"name": "XKCD Comic", "favourites_count": 2}`) - }) - - client := NewClient(httpClient) - user, _, err := client.Users.Show(&UserShowParams{ScreenName: "xkcdComic"}) - expected := &User{Name: "XKCD Comic", FavouritesCount: 2} - assert.Nil(t, err) - assert.Equal(t, expected, user) -} - -func TestUserService_LookupWithIds(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/users/lookup.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"user_id": "113419064,623265148"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"screen_name": "golang"}, {"screen_name": "dghubble"}]`) - }) - - client := NewClient(httpClient) - users, _, err := client.Users.Lookup(&UserLookupParams{UserID: []int64{113419064, 623265148}}) - expected := []User{User{ScreenName: "golang"}, User{ScreenName: "dghubble"}} - assert.Nil(t, err) - assert.Equal(t, expected, users) -} - -func TestUserService_LookupWithScreenNames(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/users/lookup.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"screen_name": "foo,bar"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"name": "Foo"}, {"name": "Bar"}]`) - }) - - client := NewClient(httpClient) - users, _, err := client.Users.Lookup(&UserLookupParams{ScreenName: []string{"foo", "bar"}}) - expected := []User{User{Name: "Foo"}, User{Name: "Bar"}} - assert.Nil(t, err) - assert.Equal(t, expected, users) -} - -func TestUserService_Search(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/users/search.json", func(w http.ResponseWriter, r *http.Request) { - assertMethod(t, "GET", r) - assertQuery(t, map[string]string{"count": "11", "q": "news"}, r) - w.Header().Set("Content-Type", "application/json") - fmt.Fprintf(w, `[{"name": "BBC"}, {"name": "BBC Breaking News"}]`) - }) - - client := NewClient(httpClient) - users, _, err := client.Users.Search("news", &UserSearchParams{Query: "override me", Count: 11}) - expected := []User{User{Name: "BBC"}, User{Name: "BBC Breaking News"}} - assert.Nil(t, err) - assert.Equal(t, expected, users) -} - -func TestUserService_SearchHandlesNilParams(t *testing.T) { - httpClient, mux, server := testServer() - defer server.Close() - - mux.HandleFunc("/1.1/users/search.json", func(w http.ResponseWriter, r *http.Request) { - assertQuery(t, map[string]string{"q": "news"}, r) - }) - client := NewClient(httpClient) - client.Users.Search("news", nil) -} diff --git a/vendor/github.com/dghubble/oauth1/.travis.yml b/vendor/github.com/dghubble/oauth1/.travis.yml deleted file mode 100644 index b93afce6d..000000000 --- a/vendor/github.com/dghubble/oauth1/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go -go: - - 1.7 - - 1.8 - - tip -install: - - go get github.com/golang/lint/golint - - go get -v -t . -script: - - ./test diff --git a/vendor/github.com/dghubble/oauth1/CHANGES.md b/vendor/github.com/dghubble/oauth1/CHANGES.md deleted file mode 100644 index 975c61203..000000000 --- a/vendor/github.com/dghubble/oauth1/CHANGES.md +++ /dev/null @@ -1,30 +0,0 @@ -# OAuth1 Changelog - -## v0.4.0 (2016-04-20) - -* Add a Signer field to the Config to allow custom Signer implementations. -* Use the HMACSigner by default. This provides the same signing behavior as in previous versions (HMAC-SHA1). -* Add an RSASigner for "RSA-SHA1" OAuth1 Providers. -* Add missing Authorization Header quotes around OAuth parameter values. Many providers allowed these quotes to be missing. -* Change `Signer` to be a signer interface. -* Remove the old Signer methods `SetAccessTokenAuthHeader`, `SetRequestAuthHeader`, and `SetRequestTokenAuthHeader`. - -## v0.3.0 (2015-09-13) - -* Added `NoContext` which may be used in most cases. -* Allowed Transport Base http.RoundTripper to be set through a ctx. -* Changed `NewClient` to require a context.Context. -* Changed `Config.Client` to require a context.Context. - -## v.0.2.0 (2015-08-30) - -* Improved OAuth 1 spec compliance and test coverage. -* Added `func StaticTokenSource(*Token) TokenSource` -* Added `ParseAuthorizationCallback` function. Removed `Config.HandleAuthorizationCallback` method. -* Changed `Config` method signatures to allow an interface to be defined for the OAuth1 authorization flow. Gives users of this package (and downstream packages) the freedom to use other implementations if they wish. -* Removed `RequestToken` in favor of passing token and secret value strings. -* Removed `ReuseTokenSource` struct, it was effectively a static source. Replaced by `StaticTokenSource`. - -## v0.1.0 (2015-04-26) - -* Initial OAuth1 support for obtaining authorization and making authorized requests. \ No newline at end of file diff --git a/vendor/github.com/dghubble/oauth1/LICENSE b/vendor/github.com/dghubble/oauth1/LICENSE deleted file mode 100644 index 2718840d9..000000000 --- a/vendor/github.com/dghubble/oauth1/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Dalton Hubble - -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. \ No newline at end of file diff --git a/vendor/github.com/dghubble/oauth1/README.md b/vendor/github.com/dghubble/oauth1/README.md deleted file mode 100644 index b7867ff05..000000000 --- a/vendor/github.com/dghubble/oauth1/README.md +++ /dev/null @@ -1,125 +0,0 @@ - -# OAuth1 [![Build Status](https://travis-ci.org/dghubble/oauth1.png)](https://travis-ci.org/dghubble/oauth1) [![GoDoc](http://godoc.org/github.com/dghubble/oauth1?status.png)](http://godoc.org/github.com/dghubble/oauth1) - - -OAauth1 is a Go implementation of the [OAuth 1 spec](https://tools.ietf.org/html/rfc5849). - -It allows end-users to authorize a client (consumer) to access protected resources on his/her behalf and to make signed and authorized requests. - -Package `oauth1` takes design cues from [golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2), to provide an analogous API and an `http.Client` with a Transport which signs/authorizes requests. - -## Install - - go get github.com/dghubble/oauth1 - -## Docs - -Read [GoDoc](https://godoc.org/github.com/dghubble/oauth1) - -## Usage - -Package `oauth1` implements the OAuth1 authorization flow and provides an `http.Client` which can sign and authorize OAuth1 requests. - -To implement "Login with X", use the [gologin](https://github.com/dghubble/gologin) packages which provide login handlers for OAuth1 and OAuth2 providers. - -To call the Twitter, Digits, or Tumblr OAuth1 APIs, use the higher level Go API clients. - -* [Twitter](https://github.com/dghubble/go-twitter) -* [Digits](https://github.com/dghubble/go-digits) -* [Tumblr](https://github.com/benfb/go-tumblr) - -### Authorization Flow - -Perform the OAuth 1 authorization flow to ask a user to grant an application access to his/her resources via an access token. - -```go -import ( - "github.com/dghubble/oauth1" - "github.com/dghubble/oauth1/twitter"" -) -... - -config := oauth1.Config{ - ConsumerKey: "consumerKey", - ConsumerSecret: "consumerSecret", - CallbackURL: "http://mysite.com/oauth/twitter/callback", - Endpoint: twitter.AuthorizeEndpoint, -} -``` - -1. When a user performs an action (e.g. "Login with X" button calls "/login" route) get an OAuth1 request token (temporary credentials). - - ```go - requestToken, requestSecret, err = config.RequestToken() - // handle err - ``` - -2. Obtain authorization from the user by redirecting them to the OAuth1 provider's authorization URL to grant the application access. - - ```go - authorizationURL, err := config.AuthorizationURL(requestToken) - // handle err - http.Redirect(w, req, authorizationURL.String(), http.StatusFound) - ``` - - Receive the callback from the OAuth1 provider in a handler. - - ```go - requestToken, verifier, err := oauth1.ParseAuthorizationCallback(req) - // handle err - ``` - -3. Acquire the access token (token credentials) which can later be used to make requests on behalf of the user. - - ```go - accessToken, accessSecret, err := config.AccessToken(requestToken, requestSecret, verifier) - // handle error - token := oauth1.NewToken(accessToken, accessSecret) - ``` - -Check the [examples](examples) to see this authorization flow in action from the command line, with Twitter PIN-based login and Tumblr login. - -### Authorized Requests - -Use an access `Token` to make authorized requests on behalf of a user. - -```go -import ( - "github.com/dghubble/oauth1" -) - -func main() { - config := oauth1.NewConfig("consumerKey", "consumerSecret") - token := oauth1.NewToken("token", "tokenSecret") - - // httpClient will automatically authorize http.Request's - httpClient := config.Client(oauth1.NoContext, token) - - // example Twitter API request - path := "https://api.twitter.com/1.1/statuses/home_timeline.json?count=2" - resp, _ := httpClient.Get(path) - defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) - fmt.Printf("Raw Response Body:\n%v\n", string(body)) -} -``` - -Check the [examples](examples) to see Twitter and Tumblr requests in action. - -### Concepts - -An `Endpoint` groups an OAuth provider's token and authorization URL endpoints.Endpoints for common providers are provided in subpackages. - -A `Config` stores a consumer application's consumer key and secret, the registered callback URL, and the `Endpoint` to which the consumer is registered. It provides OAuth1 authorization flow methods. - -An OAuth1 `Token` is an access token which can be used to make signed requests on behalf of a user. See [Authorized Requests](#Authorized Requests) for details. - -If you've used the [golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2) package for OAuth2 before, this organization should be familiar. - -## Contributing - -See the [Contributing Guide](https://gist.github.com/dghubble/be682c123727f70bcfe7). - -## License - -[MIT License](LICENSE) diff --git a/vendor/github.com/dghubble/oauth1/auther.go b/vendor/github.com/dghubble/oauth1/auther.go deleted file mode 100644 index 2de98d00c..000000000 --- a/vendor/github.com/dghubble/oauth1/auther.go +++ /dev/null @@ -1,265 +0,0 @@ -package oauth1 - -import ( - "bytes" - "crypto/rand" - "encoding/base64" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "sort" - "strconv" - "strings" - "time" -) - -const ( - authorizationHeaderParam = "Authorization" - authorizationPrefix = "OAuth " // trailing space is intentional - oauthConsumerKeyParam = "oauth_consumer_key" - oauthNonceParam = "oauth_nonce" - oauthSignatureParam = "oauth_signature" - oauthSignatureMethodParam = "oauth_signature_method" - oauthTimestampParam = "oauth_timestamp" - oauthTokenParam = "oauth_token" - oauthVersionParam = "oauth_version" - oauthCallbackParam = "oauth_callback" - oauthVerifierParam = "oauth_verifier" - defaultOauthVersion = "1.0" - contentType = "Content-Type" - formContentType = "application/x-www-form-urlencoded" -) - -// clock provides a interface for current time providers. A Clock can be used -// in place of calling time.Now() directly. -type clock interface { - Now() time.Time -} - -// A noncer provides random nonce strings. -type noncer interface { - Nonce() string -} - -// auther adds an "OAuth" Authorization header field to requests. -type auther struct { - config *Config - clock clock - noncer noncer -} - -func newAuther(config *Config) *auther { - return &auther{ - config: config, - } -} - -// setRequestTokenAuthHeader adds the OAuth1 header for the request token -// request (temporary credential) according to RFC 5849 2.1. -func (a *auther) setRequestTokenAuthHeader(req *http.Request) error { - oauthParams := a.commonOAuthParams() - oauthParams[oauthCallbackParam] = a.config.CallbackURL - params, err := collectParameters(req, oauthParams) - if err != nil { - return err - } - signatureBase := signatureBase(req, params) - signature, err := a.signer().Sign("", signatureBase) - if err != nil { - return err - } - oauthParams[oauthSignatureParam] = signature - req.Header.Set(authorizationHeaderParam, authHeaderValue(oauthParams)) - return nil -} - -// setAccessTokenAuthHeader sets the OAuth1 header for the access token request -// (token credential) according to RFC 5849 2.3. -func (a *auther) setAccessTokenAuthHeader(req *http.Request, requestToken, requestSecret, verifier string) error { - oauthParams := a.commonOAuthParams() - oauthParams[oauthTokenParam] = requestToken - oauthParams[oauthVerifierParam] = verifier - params, err := collectParameters(req, oauthParams) - if err != nil { - return err - } - signatureBase := signatureBase(req, params) - signature, err := a.signer().Sign(requestSecret, signatureBase) - if err != nil { - return err - } - oauthParams[oauthSignatureParam] = signature - req.Header.Set(authorizationHeaderParam, authHeaderValue(oauthParams)) - return nil -} - -// setRequestAuthHeader sets the OAuth1 header for making authenticated -// requests with an AccessToken (token credential) according to RFC 5849 3.1. -func (a *auther) setRequestAuthHeader(req *http.Request, accessToken *Token) error { - oauthParams := a.commonOAuthParams() - oauthParams[oauthTokenParam] = accessToken.Token - params, err := collectParameters(req, oauthParams) - if err != nil { - return err - } - signatureBase := signatureBase(req, params) - signature, err := a.signer().Sign(accessToken.TokenSecret, signatureBase) - if err != nil { - return err - } - oauthParams[oauthSignatureParam] = signature - req.Header.Set(authorizationHeaderParam, authHeaderValue(oauthParams)) - return nil -} - -// commonOAuthParams returns a map of the common OAuth1 protocol parameters, -// excluding the oauth_signature parameter. -func (a *auther) commonOAuthParams() map[string]string { - return map[string]string{ - oauthConsumerKeyParam: a.config.ConsumerKey, - oauthSignatureMethodParam: a.signer().Name(), - oauthTimestampParam: strconv.FormatInt(a.epoch(), 10), - oauthNonceParam: a.nonce(), - oauthVersionParam: defaultOauthVersion, - } -} - -// Returns a base64 encoded random 32 byte string. -func (a *auther) nonce() string { - if a.noncer != nil { - return a.noncer.Nonce() - } - b := make([]byte, 32) - rand.Read(b) - return base64.StdEncoding.EncodeToString(b) -} - -// Returns the Unix epoch seconds. -func (a *auther) epoch() int64 { - if a.clock != nil { - return a.clock.Now().Unix() - } - return time.Now().Unix() -} - -// Returns the Config's Signer or the default Signer. -func (a *auther) signer() Signer { - if a.config.Signer != nil { - return a.config.Signer - } - return &HMACSigner{ConsumerSecret: a.config.ConsumerSecret} -} - -// authHeaderValue formats OAuth parameters according to RFC 5849 3.5.1. OAuth -// params are percent encoded, sorted by key (for testability), and joined by -// "=" into pairs. Pairs are joined with a ", " comma separator into a header -// string. -// The given OAuth params should include the "oauth_signature" key. -func authHeaderValue(oauthParams map[string]string) string { - pairs := sortParameters(encodeParameters(oauthParams), `%s="%s"`) - return authorizationPrefix + strings.Join(pairs, ", ") -} - -// encodeParameters percent encodes parameter keys and values according to -// RFC5849 3.6 and RFC3986 2.1 and returns a new map. -func encodeParameters(params map[string]string) map[string]string { - encoded := map[string]string{} - for key, value := range params { - encoded[PercentEncode(key)] = PercentEncode(value) - } - return encoded -} - -// sortParameters sorts parameters by key and returns a slice of key/value -// pairs formatted with the given format string (e.g. "%s=%s"). -func sortParameters(params map[string]string, format string) []string { - // sort by key - keys := make([]string, len(params)) - i := 0 - for key := range params { - keys[i] = key - i++ - } - sort.Strings(keys) - // parameter join - pairs := make([]string, len(params)) - for i, key := range keys { - pairs[i] = fmt.Sprintf(format, key, params[key]) - } - return pairs -} - -// collectParameters collects request parameters from the request query, OAuth -// parameters (which should exclude oauth_signature), and the request body -// provided the body is single part, form encoded, and the form content type -// header is set. The returned map of collected parameter keys and values -// follow RFC 5849 3.4.1.3, except duplicate parameters are not supported. -func collectParameters(req *http.Request, oauthParams map[string]string) (map[string]string, error) { - // add oauth, query, and body parameters into params - params := map[string]string{} - for key, value := range req.URL.Query() { - // most backends do not accept duplicate query keys - params[key] = value[0] - } - if req.Body != nil && req.Header.Get(contentType) == formContentType { - // reads data to a []byte, draining req.Body - b, err := ioutil.ReadAll(req.Body) - if err != nil { - return nil, err - } - values, err := url.ParseQuery(string(b)) - if err != nil { - return nil, err - } - for key, value := range values { - // not supporting params with duplicate keys - params[key] = value[0] - } - // reinitialize Body with ReadCloser over the []byte - req.Body = ioutil.NopCloser(bytes.NewReader(b)) - } - for key, value := range oauthParams { - params[key] = value - } - return params, nil -} - -// signatureBase combines the uppercase request method, percent encoded base -// string URI, and normalizes the request parameters int a parameter string. -// Returns the OAuth1 signature base string according to RFC5849 3.4.1. -func signatureBase(req *http.Request, params map[string]string) string { - method := strings.ToUpper(req.Method) - baseURL := baseURI(req) - parameterString := normalizedParameterString(params) - // signature base string constructed accoding to 3.4.1.1 - baseParts := []string{method, PercentEncode(baseURL), PercentEncode(parameterString)} - return strings.Join(baseParts, "&") -} - -// baseURI returns the base string URI of a request according to RFC 5849 -// 3.4.1.2. The scheme and host are lowercased, the port is dropped if it -// is 80 or 443, and the path minus query parameters is included. -func baseURI(req *http.Request) string { - scheme := strings.ToLower(req.URL.Scheme) - host := strings.ToLower(req.URL.Host) - if hostPort := strings.Split(host, ":"); len(hostPort) == 2 && (hostPort[1] == "80" || hostPort[1] == "443") { - host = hostPort[0] - } - // TODO: use req.URL.EscapedPath() once Go 1.5 is more generally adopted - // For now, hacky workaround accomplishes the same internal escaping mode - // escape(u.Path, encodePath) for proper compliance with the OAuth1 spec. - path := req.URL.Path - if path != "" { - path = strings.Split(req.URL.RequestURI(), "?")[0] - } - return fmt.Sprintf("%v://%v%v", scheme, host, path) -} - -// parameterString normalizes collected OAuth parameters (which should exclude -// oauth_signature) into a parameter string as defined in RFC 5894 3.4.1.3.2. -// The parameters are encoded, sorted by key, keys and values joined with "&", -// and pairs joined with "=" (e.g. foo=bar&q=gopher). -func normalizedParameterString(params map[string]string) string { - return strings.Join(sortParameters(encodeParameters(params), "%s=%s"), "&") -} diff --git a/vendor/github.com/dghubble/oauth1/auther_test.go b/vendor/github.com/dghubble/oauth1/auther_test.go deleted file mode 100644 index 4cd28a0a8..000000000 --- a/vendor/github.com/dghubble/oauth1/auther_test.go +++ /dev/null @@ -1,244 +0,0 @@ -package oauth1 - -import ( - "net/http" - "net/url" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestCommonOAuthParams(t *testing.T) { - config := &Config{ConsumerKey: "some_consumer_key"} - auther := &auther{config, &fixedClock{time.Unix(50037133, 0)}, &fixedNoncer{"some_nonce"}} - expectedParams := map[string]string{ - "oauth_consumer_key": "some_consumer_key", - "oauth_signature_method": "HMAC-SHA1", - "oauth_timestamp": "50037133", - "oauth_nonce": "some_nonce", - "oauth_version": "1.0", - } - assert.Equal(t, expectedParams, auther.commonOAuthParams()) -} - -func TestNonce(t *testing.T) { - auther := &auther{} - nonce := auther.nonce() - // assert that 32 bytes (256 bites) become 44 bytes since a base64 byte - // zeros the 2 high bits. 3 bytes convert to 4 base64 bytes, 40 base64 bytes - // represent the first 30 of 32 bytes, = padding adds another 4 byte group. - // base64 bytes = 4 * floor(bytes/3) + 4 - assert.Equal(t, 44, len([]byte(nonce))) -} - -func TestEpoch(t *testing.T) { - a := &auther{} - // assert that a real time is used by default - assert.InEpsilon(t, time.Now().Unix(), a.epoch(), 1) - // assert that the fixed clock can be used for testing - a = &auther{clock: &fixedClock{time.Unix(50037133, 0)}} - assert.Equal(t, int64(50037133), a.epoch()) -} - -func TestSigner_Default(t *testing.T) { - config := &Config{ConsumerSecret: "consumer_secret"} - a := newAuther(config) - // echo -n "hello world" | openssl dgst -sha1 -hmac "consumer_secret&token_secret" -binary | base64 - expectedSignature := "BE0uILOruKfSXd4UzYlLJDfOq08=" - // assert that the default signer produces the expected HMAC-SHA1 digest - method := a.signer().Name() - digest, err := a.signer().Sign("token_secret", "hello world") - assert.Nil(t, err) - assert.Equal(t, "HMAC-SHA1", method) - assert.Equal(t, expectedSignature, digest) -} - -type identitySigner struct{} - -func (s *identitySigner) Name() string { - return "identity" -} - -func (s *identitySigner) Sign(tokenSecret, message string) (string, error) { - return message, nil -} - -func TestSigner_Custom(t *testing.T) { - config := &Config{ - ConsumerSecret: "consumer_secret", - Signer: &identitySigner{}, - } - a := newAuther(config) - // assert that the custom signer is used - method := a.signer().Name() - digest, err := a.signer().Sign("secret", "hello world") - assert.Nil(t, err) - assert.Equal(t, "identity", method) - assert.Equal(t, "hello world", digest) -} - -func TestAuthHeaderValue(t *testing.T) { - cases := []struct { - params map[string]string - authHeader string - }{ - {map[string]string{}, "OAuth "}, - {map[string]string{"a": "b"}, `OAuth a="b"`}, - {map[string]string{"a": "b", "c": "d", "e": "f", "1": "2"}, `OAuth 1="2", a="b", c="d", e="f"`}, - {map[string]string{"/= +doencode": "/= +doencode"}, `OAuth %2F%3D%20%2Bdoencode="%2F%3D%20%2Bdoencode"`}, - {map[string]string{"-._~dontencode": "-._~dontencode"}, `OAuth -._~dontencode="-._~dontencode"`}, - } - for _, c := range cases { - assert.Equal(t, c.authHeader, authHeaderValue(c.params)) - } -} - -func TestEncodeParameters(t *testing.T) { - input := map[string]string{ - "a": "Dogs, Cats & Mice", - "☃": "snowman", - "ル": "ル", - } - expected := map[string]string{ - "a": "Dogs%2C%20Cats%20%26%20Mice", - "%E2%98%83": "snowman", - "%E3%83%AB": "%E3%83%AB", - } - assert.Equal(t, expected, encodeParameters(input)) -} - -func TestSortParameters(t *testing.T) { - input := map[string]string{ - ".": "ape", - "5.6": "bat", - "rsa": "cat", - "%20": "dog", - "%E3%83%AB": "eel", - "dup": "fox", - //"dup": "fix", // duplicate keys not supported - } - expected := []string{ - "%20=dog", - "%E3%83%AB=eel", - ".=ape", - "5.6=bat", - "dup=fox", - "rsa=cat", - } - assert.Equal(t, expected, sortParameters(input, "%s=%s")) -} - -func TestCollectParameters(t *testing.T) { - // example from RFC 5849 3.4.1.3.1 - oauthParams := map[string]string{ - "oauth_token": "kkk9d7dh3k39sjv7", - "oauth_consumer_key": "9djdj82h48djs9d2", - "oauth_signature_method": "HMAC-SHA1", - "oauth_timestamp": "137131201", - "oauth_nonce": "7d8f3e4a", - } - values := url.Values{} - values.Add("c2", "") - values.Add("plus", "2 q") // duplicate keys not supported, a3 -> plus - req, err := http.NewRequest("POST", "/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b", strings.NewReader(values.Encode())) - assert.Nil(t, err) - req.Header.Set(contentType, formContentType) - params, err := collectParameters(req, oauthParams) - // assert parameters were collected from oauthParams, the query, and form body - expected := map[string]string{ - "b5": "=%3D", - "a3": "a", - "c@": "", - "a2": "r b", - "oauth_token": "kkk9d7dh3k39sjv7", - "oauth_consumer_key": "9djdj82h48djs9d2", - "oauth_signature_method": "HMAC-SHA1", - "oauth_timestamp": "137131201", - "oauth_nonce": "7d8f3e4a", - "c2": "", - "plus": "2 q", - } - assert.Nil(t, err) - assert.Equal(t, expected, params) - // RFC 5849 3.4.1.3.1 requires a {"a3"="2 q"} be form encoded to "a3=2+q" in - // the application/x-www-form-urlencoded body. The parameter "2+q" should be - // read as "2 q" and percent encoded to "2%20q". - // In Go, data is form encoded by calling Encode on url.Values{} (URL - // encoding) and decoded with url.ParseQuery to url.Values. So the encoding - // of "2 q" to "2+q" and decoding back to "2 q" is handled and then params - // are percent encoded. - // http://golang.org/src/net/http/client.go#L496 - // http://golang.org/src/net/http/request.go#L837 -} - -func TestSignatureBase(t *testing.T) { - reqA, err := http.NewRequest("get", "HTTPS://HELLO.IO?q=test", nil) - assert.Nil(t, err) - reqB, err := http.NewRequest("POST", "http://hello.io:8080", nil) - assert.Nil(t, err) - cases := []struct { - req *http.Request - params map[string]string - signatureBase string - }{ - {reqA, map[string]string{"a": "b", "c": "d"}, "GET&https%3A%2F%2Fhello.io&a%3Db%26c%3Dd"}, - {reqB, map[string]string{"a": "b"}, "POST&http%3A%2F%2Fhello.io%3A8080&a%3Db"}, - } - // assert that method is uppercased, base uri rules applied, queries added, joined by & - for _, c := range cases { - base := signatureBase(c.req, c.params) - assert.Equal(t, c.signatureBase, base) - } -} - -func TestBaseURI(t *testing.T) { - reqA, err := http.NewRequest("GET", "HTTP://EXAMPLE.COM:80/r%20v/X?id=123", nil) - assert.Nil(t, err) - reqB, err := http.NewRequest("POST", "https://www.example.net:8080/?q=1", nil) - assert.Nil(t, err) - reqC, err := http.NewRequest("POST", "https://example.com:443", nil) - cases := []struct { - req *http.Request - baseURI string - }{ - {reqA, "http://example.com/r%20v/X"}, - {reqB, "https://www.example.net:8080/"}, - {reqC, "https://example.com"}, - } - for _, c := range cases { - baseURI := baseURI(c.req) - assert.Equal(t, c.baseURI, baseURI) - } -} - -func TestNormalizedParameterString(t *testing.T) { - simple := map[string]string{ - "a": "b & c", - "☃": "snowman", - } - rfcExample := map[string]string{ - "b5": "=%3D", - "a3": "a", - "c@": "", - "a2": "r b", - "oauth_token": "kkk9d7dh3k39sjv7", - "oauth_consumer_key": "9djdj82h48djs9d2", - "oauth_signature_method": "HMAC-SHA1", - "oauth_timestamp": "137131201", - "oauth_nonce": "7d8f3e4a", - "c2": "", - "plus": "2 q", - } - cases := []struct { - params map[string]string - parameterStr string - }{ - {simple, "%E2%98%83=snowman&a=b%20%26%20c"}, - {rfcExample, "a2=r%20b&a3=a&b5=%3D%253D&c%40=&c2=&oauth_consumer_key=9djdj82h48djs9d2&oauth_nonce=7d8f3e4a&oauth_signature_method=HMAC-SHA1&oauth_timestamp=137131201&oauth_token=kkk9d7dh3k39sjv7&plus=2%20q"}, - } - for _, c := range cases { - assert.Equal(t, c.parameterStr, normalizedParameterString(c.params)) - } -} diff --git a/vendor/github.com/dghubble/oauth1/config.go b/vendor/github.com/dghubble/oauth1/config.go deleted file mode 100644 index df18e86bd..000000000 --- a/vendor/github.com/dghubble/oauth1/config.go +++ /dev/null @@ -1,172 +0,0 @@ -package oauth1 - -import ( - "errors" - "fmt" - "io/ioutil" - "net/http" - "net/url" - - "golang.org/x/net/context" -) - -const ( - oauthTokenSecretParam = "oauth_token_secret" - oauthCallbackConfirmedParam = "oauth_callback_confirmed" -) - -// Config represents an OAuth1 consumer's (client's) key and secret, the -// callback URL, and the provider Endpoint to which the consumer corresponds. -type Config struct { - // Consumer Key (Client Identifier) - ConsumerKey string - // Consumer Secret (Client Shared-Secret) - ConsumerSecret string - // Callback URL - CallbackURL string - // Provider Endpoint specifying OAuth1 endpoint URLs - Endpoint Endpoint - // OAuth1 Signer (defaults to HMAC-SHA1) - Signer Signer -} - -// NewConfig returns a new Config with the given consumer key and secret. -func NewConfig(consumerKey, consumerSecret string) *Config { - return &Config{ - ConsumerKey: consumerKey, - ConsumerSecret: consumerSecret, - } -} - -// Client returns an HTTP client which uses the provided ctx and access Token. -func (c *Config) Client(ctx context.Context, t *Token) *http.Client { - return NewClient(ctx, c, t) -} - -// NewClient returns a new http Client which signs requests via OAuth1. -func NewClient(ctx context.Context, config *Config, token *Token) *http.Client { - transport := &Transport{ - Base: contextTransport(ctx), - source: StaticTokenSource(token), - auther: newAuther(config), - } - return &http.Client{Transport: transport} -} - -// RequestToken obtains a Request token and secret (temporary credential) by -// POSTing a request (with oauth_callback in the auth header) to the Endpoint -// RequestTokenURL. The response body form is validated to ensure -// oauth_callback_confirmed is true. Returns the request token and secret -// (temporary credentials). -// See RFC 5849 2.1 Temporary Credentials. -func (c *Config) RequestToken() (requestToken, requestSecret string, err error) { - req, err := http.NewRequest("POST", c.Endpoint.RequestTokenURL, nil) - if err != nil { - return "", "", err - } - err = newAuther(c).setRequestTokenAuthHeader(req) - if err != nil { - return "", "", err - } - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", "", err - } - // when err is nil, resp contains a non-nil resp.Body which must be closed - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { - return "", "", fmt.Errorf("oauth1: Server returned status %d", resp.StatusCode) - } - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "", "", err - } - // ParseQuery to decode URL-encoded application/x-www-form-urlencoded body - values, err := url.ParseQuery(string(body)) - if err != nil { - return "", "", err - } - requestToken = values.Get(oauthTokenParam) - requestSecret = values.Get(oauthTokenSecretParam) - if requestToken == "" || requestSecret == "" { - return "", "", errors.New("oauth1: Response missing oauth_token or oauth_token_secret") - } - if values.Get(oauthCallbackConfirmedParam) != "true" { - return "", "", errors.New("oauth1: oauth_callback_confirmed was not true") - } - return requestToken, requestSecret, nil -} - -// AuthorizationURL accepts a request token and returns the *url.URL to the -// Endpoint's authorization page that asks the user (resource owner) for to -// authorize the consumer to act on his/her/its behalf. -// See RFC 5849 2.2 Resource Owner Authorization. -func (c *Config) AuthorizationURL(requestToken string) (*url.URL, error) { - authorizationURL, err := url.Parse(c.Endpoint.AuthorizeURL) - if err != nil { - return nil, err - } - values := authorizationURL.Query() - values.Add(oauthTokenParam, requestToken) - authorizationURL.RawQuery = values.Encode() - return authorizationURL, nil -} - -// ParseAuthorizationCallback parses an OAuth1 authorization callback request -// from a provider server. The oauth_token and oauth_verifier parameters are -// parsed to return the request token from earlier in the flow and the -// verifier string. -// See RFC 5849 2.2 Resource Owner Authorization. -func ParseAuthorizationCallback(req *http.Request) (requestToken, verifier string, err error) { - // parse the raw query from the URL into req.Form - err = req.ParseForm() - if err != nil { - return "", "", err - } - requestToken = req.Form.Get(oauthTokenParam) - verifier = req.Form.Get(oauthVerifierParam) - if requestToken == "" || verifier == "" { - return "", "", errors.New("oauth1: Request missing oauth_token or oauth_verifier") - } - return requestToken, verifier, nil -} - -// AccessToken obtains an access token (token credential) by POSTing a -// request (with oauth_token and oauth_verifier in the auth header) to the -// Endpoint AccessTokenURL. Returns the access token and secret (token -// credentials). -// See RFC 5849 2.3 Token Credentials. -func (c *Config) AccessToken(requestToken, requestSecret, verifier string) (accessToken, accessSecret string, err error) { - req, err := http.NewRequest("POST", c.Endpoint.AccessTokenURL, nil) - if err != nil { - return "", "", err - } - err = newAuther(c).setAccessTokenAuthHeader(req, requestToken, requestSecret, verifier) - if err != nil { - return "", "", err - } - resp, err := http.DefaultClient.Do(req) - if err != nil { - return "", "", err - } - // when err is nil, resp contains a non-nil resp.Body which must be closed - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { - return "", "", fmt.Errorf("oauth1: Server returned status %d", resp.StatusCode) - } - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return "", "", err - } - // ParseQuery to decode URL-encoded application/x-www-form-urlencoded body - values, err := url.ParseQuery(string(body)) - if err != nil { - return "", "", err - } - accessToken = values.Get(oauthTokenParam) - accessSecret = values.Get(oauthTokenSecretParam) - if accessToken == "" || accessSecret == "" { - return "", "", errors.New("oauth1: Response missing oauth_token or oauth_token_secret") - } - return accessToken, accessSecret, nil -} diff --git a/vendor/github.com/dghubble/oauth1/config_test.go b/vendor/github.com/dghubble/oauth1/config_test.go deleted file mode 100644 index fcb4525a0..000000000 --- a/vendor/github.com/dghubble/oauth1/config_test.go +++ /dev/null @@ -1,346 +0,0 @@ -package oauth1 - -import ( - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -const expectedVerifier = "some_verifier" - -func TestNewConfig(t *testing.T) { - expectedConsumerKey := "consumer_key" - expectedConsumerSecret := "consumer_secret" - config := NewConfig(expectedConsumerKey, expectedConsumerSecret) - assert.Equal(t, expectedConsumerKey, config.ConsumerKey) - assert.Equal(t, expectedConsumerSecret, config.ConsumerSecret) -} - -func TestNewClient(t *testing.T) { - expectedToken := "access_token" - expectedConsumerKey := "consumer_key" - config := NewConfig(expectedConsumerKey, "consumer_secret") - token := NewToken(expectedToken, "access_secret") - client := config.Client(NoContext, token) - - server := newMockServer(func(w http.ResponseWriter, req *http.Request) { - assert.Equal(t, "GET", req.Method) - params := parseOAuthParamsOrFail(t, req.Header.Get(authorizationHeaderParam)) - assert.Equal(t, expectedToken, params[oauthTokenParam]) - assert.Equal(t, expectedConsumerKey, params[oauthConsumerKeyParam]) - }) - defer server.Close() - client.Get(server.URL) -} - -func TestNewClient_DefaultTransport(t *testing.T) { - client := NewClient(NoContext, NewConfig("t", "s"), NewToken("t", "s")) - // assert that the client uses the DefaultTransport - transport, ok := client.Transport.(*Transport) - assert.True(t, ok) - assert.Equal(t, http.DefaultTransport, transport.base()) -} - -func TestNewClient_ContextClientTransport(t *testing.T) { - baseTransport := &http.Transport{} - baseClient := &http.Client{Transport: baseTransport} - ctx := context.WithValue(NoContext, HTTPClient, baseClient) - client := NewClient(ctx, NewConfig("t", "s"), NewToken("t", "s")) - // assert that the client uses the ctx client's Transport as its base RoundTripper - transport, ok := client.Transport.(*Transport) - assert.True(t, ok) - assert.Equal(t, baseTransport, transport.base()) -} - -// newRequestTokenServer returns a new httptest.Server for an OAuth1 provider -// request token endpoint. -func newRequestTokenServer(t *testing.T, data url.Values) *httptest.Server { - return newMockServer(func(w http.ResponseWriter, req *http.Request) { - assert.Equal(t, "POST", req.Method) - assert.NotEmpty(t, req.Header.Get("Authorization")) - w.Header().Set(contentType, formContentType) - w.Write([]byte(data.Encode())) - }) -} - -// newAccessTokenServer returns a new httptest.Server for an OAuth1 provider -// access token endpoint. -func newAccessTokenServer(t *testing.T, data url.Values) *httptest.Server { - return newMockServer(func(w http.ResponseWriter, req *http.Request) { - assert.Equal(t, "POST", req.Method) - assert.NotEmpty(t, req.Header.Get("Authorization")) - params := parseOAuthParamsOrFail(t, req.Header.Get(authorizationHeaderParam)) - assert.Equal(t, expectedVerifier, params[oauthVerifierParam]) - w.Header().Set(contentType, formContentType) - w.Write([]byte(data.Encode())) - }) -} - -// newUnparseableBodyServer returns a new httptest.Server which writes -// responses with bodies that error when parsed by url.ParseQuery. -func newUnparseableBodyServer() *httptest.Server { - return newMockServer(func(w http.ResponseWriter, req *http.Request) { - w.Header().Set(contentType, formContentType) - // url.ParseQuery will error, https://golang.org/src/net/url/url_test.go#L1107 - w.Write([]byte("%gh&%ij")) - }) -} - -func TestConfigRequestToken(t *testing.T) { - expectedToken := "reqest_token" - expectedSecret := "request_secret" - data := url.Values{} - data.Add("oauth_token", expectedToken) - data.Add("oauth_token_secret", expectedSecret) - data.Add("oauth_callback_confirmed", "true") - server := newRequestTokenServer(t, data) - defer server.Close() - - config := &Config{ - Endpoint: Endpoint{ - RequestTokenURL: server.URL, - }, - } - requestToken, requestSecret, err := config.RequestToken() - assert.Nil(t, err) - assert.Equal(t, expectedToken, requestToken) - assert.Equal(t, expectedSecret, requestSecret) -} - -func TestConfigRequestToken_InvalidRequestTokenURL(t *testing.T) { - config := &Config{ - Endpoint: Endpoint{ - RequestTokenURL: "http://wrong.com/oauth/request_token", - }, - } - requestToken, requestSecret, err := config.RequestToken() - assert.NotNil(t, err) - assert.Equal(t, "", requestToken) - assert.Equal(t, "", requestSecret) -} - -func TestConfigRequestToken_CallbackNotConfirmed(t *testing.T) { - const expectedToken = "reqest_token" - const expectedSecret = "request_secret" - data := url.Values{} - data.Add("oauth_token", expectedToken) - data.Add("oauth_token_secret", expectedSecret) - data.Add("oauth_callback_confirmed", "false") - server := newRequestTokenServer(t, data) - defer server.Close() - - config := &Config{ - Endpoint: Endpoint{ - RequestTokenURL: server.URL, - }, - } - requestToken, requestSecret, err := config.RequestToken() - if assert.Error(t, err) { - assert.Equal(t, "oauth1: oauth_callback_confirmed was not true", err.Error()) - } - assert.Equal(t, "", requestToken) - assert.Equal(t, "", requestSecret) -} - -func TestConfigRequestToken_CannotParseBody(t *testing.T) { - server := newUnparseableBodyServer() - defer server.Close() - - config := &Config{ - Endpoint: Endpoint{ - RequestTokenURL: server.URL, - }, - } - requestToken, requestSecret, err := config.RequestToken() - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "invalid URL escape") - } - assert.Equal(t, "", requestToken) - assert.Equal(t, "", requestSecret) -} - -func TestConfigRequestToken_MissingTokenOrSecret(t *testing.T) { - data := url.Values{} - data.Add("oauth_token", "any_token") - data.Add("oauth_callback_confirmed", "true") - server := newRequestTokenServer(t, data) - defer server.Close() - - config := &Config{ - Endpoint: Endpoint{ - RequestTokenURL: server.URL, - }, - } - requestToken, requestSecret, err := config.RequestToken() - if assert.Error(t, err) { - assert.Equal(t, "oauth1: Response missing oauth_token or oauth_token_secret", err.Error()) - } - assert.Equal(t, "", requestToken) - assert.Equal(t, "", requestSecret) -} - -func TestAuthorizationURL(t *testing.T) { - expectedURL := "https://api.example.com/oauth/authorize?oauth_token=a%2Frequest_token" - config := &Config{ - Endpoint: Endpoint{ - AuthorizeURL: "https://api.example.com/oauth/authorize", - }, - } - url, err := config.AuthorizationURL("a/request_token") - assert.Nil(t, err) - if assert.NotNil(t, url) { - assert.Equal(t, expectedURL, url.String()) - } -} - -func TestAuthorizationURL_CannotParseAuthorizeURL(t *testing.T) { - config := &Config{ - Endpoint: Endpoint{ - AuthorizeURL: "%gh&%ij", - }, - } - url, err := config.AuthorizationURL("any_request_token") - assert.Nil(t, url) - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "parse") - assert.Contains(t, err.Error(), "invalid URL") - } -} - -func TestConfigAccessToken(t *testing.T) { - expectedToken := "access_token" - expectedSecret := "access_secret" - data := url.Values{} - data.Add("oauth_token", expectedToken) - data.Add("oauth_token_secret", expectedSecret) - server := newAccessTokenServer(t, data) - defer server.Close() - - config := &Config{ - Endpoint: Endpoint{ - AccessTokenURL: server.URL, - }, - } - accessToken, accessSecret, err := config.AccessToken("request_token", "request_secret", expectedVerifier) - assert.Nil(t, err) - assert.Equal(t, expectedToken, accessToken) - assert.Equal(t, expectedSecret, accessSecret) -} - -func TestConfigAccessToken_InvalidAccessTokenURL(t *testing.T) { - config := &Config{ - Endpoint: Endpoint{ - AccessTokenURL: "http://wrong.com/oauth/access_token", - }, - } - accessToken, accessSecret, err := config.AccessToken("any_token", "any_secret", "any_verifier") - assert.NotNil(t, err) - assert.Equal(t, "", accessToken) - assert.Equal(t, "", accessSecret) -} - -func TestConfigAccessToken_CannotParseBody(t *testing.T) { - server := newUnparseableBodyServer() - defer server.Close() - - config := &Config{ - Endpoint: Endpoint{ - AccessTokenURL: server.URL, - }, - } - accessToken, accessSecret, err := config.AccessToken("any_token", "any_secret", "any_verifier") - if assert.Error(t, err) { - assert.Contains(t, err.Error(), "invalid URL escape") - } - assert.Equal(t, "", accessToken) - assert.Equal(t, "", accessSecret) -} - -func TestConfigAccessToken_MissingTokenOrSecret(t *testing.T) { - data := url.Values{} - data.Add("oauth_token", "any_token") - server := newAccessTokenServer(t, data) - defer server.Close() - - config := &Config{ - Endpoint: Endpoint{ - AccessTokenURL: server.URL, - }, - } - accessToken, accessSecret, err := config.AccessToken("request_token", "request_secret", expectedVerifier) - if assert.Error(t, err) { - assert.Equal(t, "oauth1: Response missing oauth_token or oauth_token_secret", err.Error()) - } - assert.Equal(t, "", accessToken) - assert.Equal(t, "", accessSecret) -} - -func TestParseAuthorizationCallback_GET(t *testing.T) { - expectedToken := "token" - expectedVerifier := "verifier" - server := newMockServer(func(w http.ResponseWriter, req *http.Request) { - assert.Equal(t, "GET", req.Method) - // logic under test - requestToken, verifier, err := ParseAuthorizationCallback(req) - assert.Nil(t, err) - assert.Equal(t, expectedToken, requestToken) - assert.Equal(t, expectedVerifier, verifier) - }) - defer server.Close() - - // OAuth1 provider calls callback url - url, err := url.Parse(server.URL) - assert.Nil(t, err) - query := url.Query() - query.Add("oauth_token", expectedToken) - query.Add("oauth_verifier", expectedVerifier) - url.RawQuery = query.Encode() - http.Get(url.String()) -} - -func TestParseAuthorizationCallback_POST(t *testing.T) { - expectedToken := "token" - expectedVerifier := "verifier" - server := newMockServer(func(w http.ResponseWriter, req *http.Request) { - assert.Equal(t, "POST", req.Method) - // logic under test - requestToken, verifier, err := ParseAuthorizationCallback(req) - assert.Nil(t, err) - assert.Equal(t, expectedToken, requestToken) - assert.Equal(t, expectedVerifier, verifier) - }) - defer server.Close() - - // OAuth1 provider calls callback url - form := url.Values{} - form.Add("oauth_token", expectedToken) - form.Add("oauth_verifier", expectedVerifier) - http.PostForm(server.URL, form) -} - -func TestParseAuthorizationCallback_MissingTokenOrVerifier(t *testing.T) { - server := newMockServer(func(w http.ResponseWriter, req *http.Request) { - assert.Equal(t, "GET", req.Method) - // logic under test - requestToken, verifier, err := ParseAuthorizationCallback(req) - if assert.Error(t, err) { - assert.Equal(t, "oauth1: Request missing oauth_token or oauth_verifier", err.Error()) - } - assert.Equal(t, "", requestToken) - assert.Equal(t, "", verifier) - }) - defer server.Close() - - // OAuth1 provider calls callback url - url, err := url.Parse(server.URL) - assert.Nil(t, err) - query := url.Query() - query.Add("oauth_token", "any_token") - query.Add("oauth_verifier", "") // missing oauth_verifier - url.RawQuery = query.Encode() - http.Get(url.String()) -} diff --git a/vendor/github.com/dghubble/oauth1/context.go b/vendor/github.com/dghubble/oauth1/context.go deleted file mode 100644 index c4dbc26f3..000000000 --- a/vendor/github.com/dghubble/oauth1/context.go +++ /dev/null @@ -1,24 +0,0 @@ -package oauth1 - -import ( - "net/http" - - "golang.org/x/net/context" -) - -type contextKey struct{} - -// HTTPClient is the context key to associate an *http.Client value with -// a context. -var HTTPClient contextKey - -// NoContext is the default context to use in most cases. -var NoContext = context.TODO() - -// contextTransport gets the Transport from the context client or nil. -func contextTransport(ctx context.Context) http.RoundTripper { - if client, ok := ctx.Value(HTTPClient).(*http.Client); ok { - return client.Transport - } - return nil -} diff --git a/vendor/github.com/dghubble/oauth1/context_test.go b/vendor/github.com/dghubble/oauth1/context_test.go deleted file mode 100644 index e81453b3b..000000000 --- a/vendor/github.com/dghubble/oauth1/context_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package oauth1 - -import ( - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestContextTransport(t *testing.T) { - client := &http.Client{ - Transport: http.DefaultTransport, - } - ctx := context.WithValue(NoContext, HTTPClient, client) - assert.Equal(t, http.DefaultTransport, contextTransport(ctx)) -} - -func TestContextTransport_NoContextClient(t *testing.T) { - assert.Nil(t, contextTransport(NoContext)) -} diff --git a/vendor/github.com/dghubble/oauth1/doc.go b/vendor/github.com/dghubble/oauth1/doc.go deleted file mode 100644 index ef303dbc5..000000000 --- a/vendor/github.com/dghubble/oauth1/doc.go +++ /dev/null @@ -1,97 +0,0 @@ -/* -Package oauth1 is a Go implementation of the OAuth1 spec RFC 5849. - -It allows end-users to authorize a client (consumer) to access protected -resources on their behalf (e.g. login) and allows clients to make signed and -authorized requests on behalf of a user (e.g. API calls). - -It takes design cues from golang.org/x/oauth2, providing an http.Client which -handles request signing and authorization. - -Usage - -Package oauth1 implements the OAuth1 authorization flow and provides an -http.Client which can sign and authorize OAuth1 requests. - -To implement "Login with X", use the https://github.com/dghubble/gologin -packages which provide login handlers for OAuth1 and OAuth2 providers. - -To call the Twitter, Digits, or Tumblr OAuth1 APIs, use the higher level Go API -clients. - -* https://github.com/dghubble/go-twitter -* https://github.com/dghubble/go-digits -* https://github.com/benfb/go-tumblr - -Authorization Flow - -Perform the OAuth 1 authorization flow to ask a user to grant an application -access to his/her resources via an access token. - - import ( - "github.com/dghubble/oauth1" - "github.com/dghubble/oauth1/twitter"" - ) - ... - - config := oauth1.Config{ - ConsumerKey: "consumerKey", - ConsumerSecret: "consumerSecret", - CallbackURL: "http://mysite.com/oauth/twitter/callback", - Endpoint: twitter.AuthorizeEndpoint, - } - -1. When a user performs an action (e.g. "Login with X" button calls "/login" -route) get an OAuth1 request token (temporary credentials). - - requestToken, requestSecret, err = config.RequestToken() - // handle err - -2. Obtain authorization from the user by redirecting them to the OAuth1 -provider's authorization URL to grant the application access. - - authorizationURL, err := config.AuthorizationURL(requestToken) - // handle err - http.Redirect(w, req, authorizationURL.String(), htt.StatusFound) - -Receive the callback from the OAuth1 provider in a handler. - - requestToken, verifier, err := oauth1.ParseAuthorizationCallback(req) - // handle err - -3. Acquire the access token (token credentials) which can later be used -to make requests on behalf of the user. - - accessToken, accessSecret, err := config.AccessToken(requestToken, requestSecret, verifier) - // handle error - token := oauth1.NewToken(accessToken, accessSecret) - -Check the examples to see this authorization flow in action from the command -line, with Twitter PIN-based login and Tumblr login. - -Authorized Requests - -Use an access Token to make authorized requests on behalf of a user. - - import ( - "github.com/dghubble/oauth1" - ) - - func main() { - config := oauth1.NewConfig("consumerKey", "consumerSecret") - token := oauth1.NewToken("token", "tokenSecret") - - // httpClient will automatically authorize http.Request's - httpClient := config.Client(token) - - // example Twitter API request - path := "https://api.twitter.com/1.1/statuses/home_timeline.json?count=2" - resp, _ := httpClient.Get(path) - defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) - fmt.Printf("Raw Response Body:\n%v\n", string(body)) - } - -Check the examples to see Twitter and Tumblr requests in action. -*/ -package oauth1 diff --git a/vendor/github.com/dghubble/oauth1/dropbox/dropbox.go b/vendor/github.com/dghubble/oauth1/dropbox/dropbox.go deleted file mode 100644 index 7902cb91f..000000000 --- a/vendor/github.com/dghubble/oauth1/dropbox/dropbox.go +++ /dev/null @@ -1,13 +0,0 @@ -// Package dropbox provides constants for using OAuth1 to access Dropbox. -package dropbox - -import ( - "github.com/dghubble/oauth1" -) - -// Endpoint is Dropbox's OAuth 1 endpoint. -var Endpoint = oauth1.Endpoint{ - RequestTokenURL: "https://api.dropbox.com/1/oauth/request_token", - AuthorizeURL: "https://api.dropbox.com/1/oauth/authorize", - AccessTokenURL: "https://api.dropbox.com/1/oauth/access_token", -} diff --git a/vendor/github.com/dghubble/oauth1/encode.go b/vendor/github.com/dghubble/oauth1/encode.go deleted file mode 100644 index 9c078346e..000000000 --- a/vendor/github.com/dghubble/oauth1/encode.go +++ /dev/null @@ -1,36 +0,0 @@ -package oauth1 - -import ( - "bytes" - "fmt" -) - -// PercentEncode percent encodes a string according to RFC 3986 2.1. -func PercentEncode(input string) string { - var buf bytes.Buffer - for _, b := range []byte(input) { - // if in unreserved set - if shouldEscape(b) { - buf.Write([]byte(fmt.Sprintf("%%%02X", b))) - } else { - // do not escape, write byte as-is - buf.WriteByte(b) - } - } - return buf.String() -} - -// shouldEscape returns false if the byte is an unreserved character that -// should not be escaped and true otherwise, according to RFC 3986 2.1. -func shouldEscape(c byte) bool { - // RFC3986 2.3 unreserved characters - if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' { - return false - } - switch c { - case '-', '.', '_', '~': - return false - } - // all other bytes must be escaped - return true -} diff --git a/vendor/github.com/dghubble/oauth1/encode_test.go b/vendor/github.com/dghubble/oauth1/encode_test.go deleted file mode 100644 index 6b310fc03..000000000 --- a/vendor/github.com/dghubble/oauth1/encode_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package oauth1 - -import ( - "testing" -) - -func TestPercentEncode(t *testing.T) { - cases := []struct { - input string - expected string - }{ - {" ", "%20"}, - {"%", "%25"}, - {"&", "%26"}, - {"-._", "-._"}, - {" /=+", "%20%2F%3D%2B"}, - {"Ladies + Gentlemen", "Ladies%20%2B%20Gentlemen"}, - {"An encoded string!", "An%20encoded%20string%21"}, - {"Dogs, Cats & Mice", "Dogs%2C%20Cats%20%26%20Mice"}, - {"☃", "%E2%98%83"}, - } - for _, c := range cases { - if output := PercentEncode(c.input); output != c.expected { - t.Errorf("expected %s, got %s", c.expected, output) - } - } -} diff --git a/vendor/github.com/dghubble/oauth1/endpoint.go b/vendor/github.com/dghubble/oauth1/endpoint.go deleted file mode 100644 index cb3f66775..000000000 --- a/vendor/github.com/dghubble/oauth1/endpoint.go +++ /dev/null @@ -1,12 +0,0 @@ -package oauth1 - -// Endpoint represents an OAuth1 provider's (server's) request token, -// owner authorization, and access token request URLs. -type Endpoint struct { - // Request URL (Temporary Credential Request URI) - RequestTokenURL string - // Authorize URL (Resource Owner Authorization URI) - AuthorizeURL string - // Access Token URL (Token Request URI) - AccessTokenURL string -} diff --git a/vendor/github.com/dghubble/oauth1/examples/README.md b/vendor/github.com/dghubble/oauth1/examples/README.md deleted file mode 100644 index 47fb9c446..000000000 --- a/vendor/github.com/dghubble/oauth1/examples/README.md +++ /dev/null @@ -1,48 +0,0 @@ - -# OAuth1 Examples - -## Twitter - -### Authorization Flow (PIN-based) - -An application can obtain a Twitter access `Token` for a user by requesting the user grant access via [3-legged](https://dev.twitter.com/oauth/3-legged) or [PIN-based](https://dev.twitter.com/oauth/pin-based) OAuth 1. Here is a command line example showing PIN-based authorization. - - export TWITTER_CONSUMER_KEY=xxx - export TWITTER_CONSUMER_SECRET=xxx - go run twitter-login.go - -The OAuth 1 flow can be used to implement Login with Twitter. Upon receiving an access token in a callback handler on your server, issue a user some form of unforgeable session identifier (i.e. cookie, token). Note that web backends should use a real `CallbackURL`, "oob" is for PIN-based agents such as the command line. - -### Authorized Requests - -Use the access `Token` to make requests on behalf of a Twitter user. - - export TWITTER_CONSUMER_KEY=xxx - export TWITTER_CONSUMER_SECRET=xxx - export TWITTER_ACCESS_TOKEN=xxx - export TWITTER_ACCESS_SECRET=xxx - go run twitter-request.go - - -## Tumblr - -### Authorization Flow - -An application can obtain a Tumblr access `Token` to act on behalf of a user. Here is a command line example which requests permission. - - export TUMBLR_CONSUMER_KEY=xxx - export TUMBLR_CONSUMER_SECRET=xxx - go run tumblr-login.go - -### Authorized Requests - -Use the access `Token` to make requests on behalf of a Tumblr user. - - export TUMBLR_CONSUMER_KEY=xxx - export TUMBLR_CONSUMER_SECRET=xxx - export TUMBLR_ACCESS_TOKEN=xxx - export TUMBLR_ACCESS_SECRET=xxx - go run tumblr-request.go - -Note that only some Tumblr endpoints require OAuth1 signed requests, other endpoints require a special consumer key query parameter or no authorization. - diff --git a/vendor/github.com/dghubble/oauth1/examples/tumblr-login.go b/vendor/github.com/dghubble/oauth1/examples/tumblr-login.go deleted file mode 100644 index 3b81f7716..000000000 --- a/vendor/github.com/dghubble/oauth1/examples/tumblr-login.go +++ /dev/null @@ -1,68 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - - "github.com/dghubble/oauth1" - "github.com/dghubble/oauth1/tumblr" -) - -var config oauth1.Config - -// main performs the Tumblr OAuth1 user flow from the command line -func main() { - // read credentials from environment variables - consumerKey := os.Getenv("TUMBLR_CONSUMER_KEY") - consumerSecret := os.Getenv("TUMBLR_CONSUMER_SECRET") - if consumerKey == "" || consumerSecret == "" { - log.Fatal("Required environment variable missing.") - } - - config = oauth1.Config{ - ConsumerKey: consumerKey, - ConsumerSecret: consumerSecret, - // Tumblr does not support oob, uses consumer registered callback - CallbackURL: "", - Endpoint: tumblr.Endpoint, - } - - requestToken, requestSecret, err := login() - if err != nil { - log.Fatalf("Request Token Phase: %s", err.Error()) - } - accessToken, err := receivePIN(requestToken, requestSecret) - if err != nil { - log.Fatalf("Access Token Phase: %s", err.Error()) - } - - fmt.Println("Consumer was granted an access token to act on behalf of a user.") - fmt.Printf("token: %s\nsecret: %s\n", accessToken.Token, accessToken.TokenSecret) -} - -func login() (requestToken, requestSecret string, err error) { - requestToken, requestSecret, err = config.RequestToken() - if err != nil { - return "", "", err - } - authorizationURL, err := config.AuthorizationURL(requestToken) - if err != nil { - return "", "", err - } - fmt.Printf("Open this URL in your browser:\n%s\n", authorizationURL.String()) - return requestToken, requestSecret, err -} - -func receivePIN(requestToken, requestSecret string) (*oauth1.Token, error) { - fmt.Printf("Choose whether to grant the application access.\nPaste " + - "the oauth_verifier parameter (excluding trailing #_=_) from the " + - "address bar: ") - var verifier string - _, err := fmt.Scanf("%s", &verifier) - accessToken, accessSecret, err := config.AccessToken(requestToken, requestSecret, verifier) - if err != nil { - return nil, err - } - return oauth1.NewToken(accessToken, accessSecret), err -} diff --git a/vendor/github.com/dghubble/oauth1/examples/tumblr-request.go b/vendor/github.com/dghubble/oauth1/examples/tumblr-request.go deleted file mode 100644 index 588dd4134..000000000 --- a/vendor/github.com/dghubble/oauth1/examples/tumblr-request.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "os" - - "github.com/dghubble/oauth1" -) - -// Tumblr access token (token credential) requests on behalf of a user -func main() { - // read credentials from environment variables - consumerKey := os.Getenv("TUMBLR_CONSUMER_KEY") - consumerSecret := os.Getenv("TUMBLR_CONSUMER_SECRET") - accessToken := os.Getenv("TUMBLR_ACCESS_TOKEN") - accessSecret := os.Getenv("TUMBLR_ACCESS_SECRET") - if consumerKey == "" || consumerSecret == "" || accessToken == "" || accessSecret == "" { - panic("Missing required environment variable") - } - - config := oauth1.NewConfig(consumerKey, consumerSecret) - token := oauth1.NewToken(accessToken, accessSecret) - - // httpClient will automatically authorize http.Request's - httpClient := config.Client(oauth1.NoContext, token) - - // get information about the current authenticated user - path := "https://api.tumblr.com/v2/user/info" - resp, _ := httpClient.Get(path) - defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) - fmt.Printf("Raw Response Body:\n%v\n", string(body)) - - // note: Tumblr requires OAuth signed requests for particular endpoints, - // others just need a consumer key query parameter (its janky). -} diff --git a/vendor/github.com/dghubble/oauth1/examples/twitter-login.go b/vendor/github.com/dghubble/oauth1/examples/twitter-login.go deleted file mode 100644 index 3ef4c3a1e..000000000 --- a/vendor/github.com/dghubble/oauth1/examples/twitter-login.go +++ /dev/null @@ -1,75 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - - "github.com/dghubble/oauth1" - twauth "github.com/dghubble/oauth1/twitter" -) - -const outOfBand = "oob" - -var config oauth1.Config - -// main performs Twitter PIN-based 3-legged OAuth 1 from the command line -func main() { - // read credentials from environment variables - consumerKey := os.Getenv("TWITTER_CONSUMER_KEY") - consumerSecret := os.Getenv("TWITTER_CONSUMER_SECRET") - if consumerKey == "" || consumerSecret == "" { - log.Fatal("Required environment variable missing.") - } - - config = oauth1.Config{ - ConsumerKey: consumerKey, - ConsumerSecret: consumerSecret, - CallbackURL: outOfBand, - Endpoint: twauth.AuthorizeEndpoint, - } - - requestToken, err := login() - if err != nil { - log.Fatalf("Request Token Phase: %s", err.Error()) - } - accessToken, err := receivePIN(requestToken) - if err != nil { - log.Fatalf("Access Token Phase: %s", err.Error()) - } - - fmt.Println("Consumer was granted an access token to act on behalf of a user.") - fmt.Printf("token: %s\nsecret: %s\n", accessToken.Token, accessToken.TokenSecret) -} - -func login() (requestToken string, err error) { - requestToken, _, err = config.RequestToken() - if err != nil { - return "", err - } - authorizationURL, err := config.AuthorizationURL(requestToken) - if err != nil { - return "", err - } - fmt.Printf("Open this URL in your browser:\n%s\n", authorizationURL.String()) - return requestToken, err -} - -func receivePIN(requestToken string) (*oauth1.Token, error) { - fmt.Printf("Paste your PIN here: ") - var verifier string - _, err := fmt.Scanf("%s", &verifier) - if err != nil { - return nil, err - } - // Twitter ignores the oauth_signature on the access token request. The user - // to which the request (temporary) token corresponds is already known on the - // server. The request for a request token earlier was validated signed by - // the consumer. Consumer applications can avoid keeping request token state - // between authorization granting and callback handling. - accessToken, accessSecret, err := config.AccessToken(requestToken, "secret does not matter", verifier) - if err != nil { - return nil, err - } - return oauth1.NewToken(accessToken, accessSecret), err -} diff --git a/vendor/github.com/dghubble/oauth1/examples/twitter-request.go b/vendor/github.com/dghubble/oauth1/examples/twitter-request.go deleted file mode 100644 index fba66b7cd..000000000 --- a/vendor/github.com/dghubble/oauth1/examples/twitter-request.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "os" - - "github.com/dghubble/go-twitter/twitter" - "github.com/dghubble/oauth1" -) - -// Twitter user-auth requests with an Access Token (token credential) -func main() { - // read credentials from environment variables - consumerKey := os.Getenv("TWITTER_CONSUMER_KEY") - consumerSecret := os.Getenv("TWITTER_CONSUMER_SECRET") - accessToken := os.Getenv("TWITTER_ACCESS_TOKEN") - accessSecret := os.Getenv("TWITTER_ACCESS_SECRET") - if consumerKey == "" || consumerSecret == "" || accessToken == "" || accessSecret == "" { - panic("Missing required environment variable") - } - - config := oauth1.NewConfig(consumerKey, consumerSecret) - token := oauth1.NewToken(accessToken, accessSecret) - - // httpClient will automatically authorize http.Request's - httpClient := config.Client(oauth1.NoContext, token) - - path := "https://api.twitter.com/1.1/statuses/home_timeline.json?count=2" - resp, _ := httpClient.Get(path) - defer resp.Body.Close() - body, _ := ioutil.ReadAll(resp.Body) - fmt.Printf("Raw Response Body:\n%v\n", string(body)) - - // Nicer: Pass OAuth1 client to go-twitter API - api := twitter.NewClient(httpClient) - tweets, _, _ := api.Timelines.HomeTimeline(nil) - fmt.Printf("User's HOME TIMELINE:\n%+v\n", tweets) -} diff --git a/vendor/github.com/dghubble/oauth1/reference_test.go b/vendor/github.com/dghubble/oauth1/reference_test.go deleted file mode 100644 index 3fbfc1288..000000000 --- a/vendor/github.com/dghubble/oauth1/reference_test.go +++ /dev/null @@ -1,202 +0,0 @@ -package oauth1 - -import ( - "fmt" - "net/http" - "net/url" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -const ( - expectedVersion = "1.0" - expectedSignatureMethod = "HMAC-SHA1" -) - -func TestTwitterRequestTokenAuthHeader(t *testing.T) { - // example from https://dev.twitter.com/web/sign-in/implementing - var unixTimestamp int64 = 1318467427 - expectedConsumerKey := "cChZNFj6T5R0TigYB9yd1w" - expectedCallback := "http%3A%2F%2Flocalhost%2Fsign-in-with-twitter%2F" - expectedSignature := "F1Li3tvehgcraF8DMJ7OyxO4w9Y%3D" - expectedTimestamp := "1318467427" - expectedNonce := "ea9ec8429b68d6b77cd5600adbbb0456" - config := &Config{ - ConsumerKey: expectedConsumerKey, - ConsumerSecret: "L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg", - CallbackURL: "http://localhost/sign-in-with-twitter/", - Endpoint: Endpoint{ - RequestTokenURL: "https://api.twitter.com/oauth/request_token", - AuthorizeURL: "https://api.twitter.com/oauth/authorize", - AccessTokenURL: "https://api.twitter.com/oauth/access_token", - }, - } - - auther := &auther{config, &fixedClock{time.Unix(unixTimestamp, 0)}, &fixedNoncer{expectedNonce}} - req, err := http.NewRequest("POST", config.Endpoint.RequestTokenURL, nil) - assert.Nil(t, err) - err = auther.setRequestTokenAuthHeader(req) - // assert the request for a request token is signed and has an oauth_callback - assert.Nil(t, err) - params := parseOAuthParamsOrFail(t, req.Header.Get(authorizationHeaderParam)) - assert.Equal(t, expectedCallback, params[oauthCallbackParam]) - assert.Equal(t, expectedSignature, params[oauthSignatureParam]) - // additional OAuth parameters - assert.Equal(t, expectedConsumerKey, params[oauthConsumerKeyParam]) - assert.Equal(t, expectedNonce, params[oauthNonceParam]) - assert.Equal(t, expectedTimestamp, params[oauthTimestampParam]) - assert.Equal(t, expectedVersion, params[oauthVersionParam]) - assert.Equal(t, expectedSignatureMethod, params[oauthSignatureMethodParam]) -} - -func TestTwitterAccessTokenAuthHeader(t *testing.T) { - // example from https://dev.twitter.com/web/sign-in/implementing - var unixTimestamp int64 = 1318467427 - expectedConsumerKey := "cChZNFj6T5R0TigYB9yd1w" - expectedRequestToken := "NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0" - requestTokenSecret := "veNRnAWe6inFuo8o2u8SLLZLjolYDmDP7SzL0YfYI" - expectedVerifier := "uw7NjWHT6OJ1MpJOXsHfNxoAhPKpgI8BlYDhxEjIBY" - expectedSignature := "39cipBtIOHEEnybAR4sATQTpl2I%3D" - expectedTimestamp := "1318467427" - expectedNonce := "a9900fe68e2573b27a37f10fbad6a755" - config := &Config{ - ConsumerKey: expectedConsumerKey, - ConsumerSecret: "L8qq9PZyRg6ieKGEKhZolGC0vJWLw8iEJ88DRdyOg", - Endpoint: Endpoint{ - RequestTokenURL: "https://api.twitter.com/oauth/request_token", - AuthorizeURL: "https://api.twitter.com/oauth/authorize", - AccessTokenURL: "https://api.twitter.com/oauth/access_token", - }, - } - - auther := &auther{config, &fixedClock{time.Unix(unixTimestamp, 0)}, &fixedNoncer{expectedNonce}} - req, err := http.NewRequest("POST", config.Endpoint.AccessTokenURL, nil) - assert.Nil(t, err) - err = auther.setAccessTokenAuthHeader(req, expectedRequestToken, requestTokenSecret, expectedVerifier) - // assert the request for an access token is signed and has an oauth_token and verifier - assert.Nil(t, err) - params := parseOAuthParamsOrFail(t, req.Header.Get(authorizationHeaderParam)) - assert.Equal(t, expectedRequestToken, params[oauthTokenParam]) - assert.Equal(t, expectedVerifier, params[oauthVerifierParam]) - assert.Equal(t, expectedSignature, params[oauthSignatureParam]) - // additional OAuth parameters - assert.Equal(t, expectedConsumerKey, params[oauthConsumerKeyParam]) - assert.Equal(t, expectedNonce, params[oauthNonceParam]) - assert.Equal(t, expectedTimestamp, params[oauthTimestampParam]) - assert.Equal(t, expectedVersion, params[oauthVersionParam]) - assert.Equal(t, expectedSignatureMethod, params[oauthSignatureMethodParam]) -} - -// example from https://dev.twitter.com/oauth/overview/authorizing-requests, -// https://dev.twitter.com/oauth/overview/creating-signatures, and -// https://dev.twitter.com/oauth/application-only -var unixTimestampOfRequest int64 = 1318622958 -var expectedTwitterConsumerKey = "xvz1evFS4wEEPTGEFPHBog" -var expectedTwitterOAuthToken = "370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb" -var expectedNonce = "kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg" -var twitterConfig = &Config{ - ConsumerKey: expectedTwitterConsumerKey, - ConsumerSecret: "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw", - Endpoint: Endpoint{ - RequestTokenURL: "https://api.twitter.com/oauth/request_token", - AuthorizeURL: "https://api.twitter.com/oauth/authorize", - AccessTokenURL: "https://api.twitter.com/oauth/access_token", - }, -} - -func TestTwitterParameterString(t *testing.T) { - auther := &auther{twitterConfig, &fixedClock{time.Unix(unixTimestampOfRequest, 0)}, &fixedNoncer{expectedNonce}} - values := url.Values{} - values.Add("status", "Hello Ladies + Gentlemen, a signed OAuth request!") - // note: the reference example is old and uses api v1 in the URL - req, err := http.NewRequest("post", "https://api.twitter.com/1/statuses/update.json?include_entities=true", strings.NewReader(values.Encode())) - assert.Nil(t, err) - req.Header.Set(contentType, formContentType) - oauthParams := auther.commonOAuthParams() - oauthParams[oauthTokenParam] = expectedTwitterOAuthToken - params, err := collectParameters(req, oauthParams) - // assert that the parameter string matches the reference - expectedParameterString := "include_entities=true&oauth_consumer_key=xvz1evFS4wEEPTGEFPHBog&oauth_nonce=kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1318622958&oauth_token=370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb&oauth_version=1.0&status=Hello%20Ladies%20%2B%20Gentlemen%2C%20a%20signed%20OAuth%20request%21" - assert.Nil(t, err) - assert.Equal(t, expectedParameterString, normalizedParameterString(params)) -} - -func TestTwitterSignatureBase(t *testing.T) { - auther := &auther{twitterConfig, &fixedClock{time.Unix(unixTimestampOfRequest, 0)}, &fixedNoncer{expectedNonce}} - values := url.Values{} - values.Add("status", "Hello Ladies + Gentlemen, a signed OAuth request!") - // note: the reference example is old and uses api v1 in the URL - req, err := http.NewRequest("post", "https://api.twitter.com/1/statuses/update.json?include_entities=true", strings.NewReader(values.Encode())) - assert.Nil(t, err) - req.Header.Set(contentType, formContentType) - oauthParams := auther.commonOAuthParams() - oauthParams[oauthTokenParam] = expectedTwitterOAuthToken - params, err := collectParameters(req, oauthParams) - signatureBase := signatureBase(req, params) - // assert that the signature base string matches the reference - // checks that method is uppercased, url is encoded, parameter string is added, all joined by & - expectedSignatureBase := "POST&https%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&include_entities%3Dtrue%26oauth_consumer_key%3Dxvz1evFS4wEEPTGEFPHBog%26oauth_nonce%3DkYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1318622958%26oauth_token%3D370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb%26oauth_version%3D1.0%26status%3DHello%2520Ladies%2520%252B%2520Gentlemen%252C%2520a%2520signed%2520OAuth%2520request%2521" - assert.Nil(t, err) - assert.Equal(t, expectedSignatureBase, signatureBase) -} - -func TestTwitterRequestAuthHeader(t *testing.T) { - oauthTokenSecret := "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE" - expectedSignature := PercentEncode("tnnArxj06cWHq44gCs1OSKk/jLY=") - expectedTimestamp := "1318622958" - - auther := &auther{twitterConfig, &fixedClock{time.Unix(unixTimestampOfRequest, 0)}, &fixedNoncer{expectedNonce}} - values := url.Values{} - values.Add("status", "Hello Ladies + Gentlemen, a signed OAuth request!") - - accessToken := &Token{expectedTwitterOAuthToken, oauthTokenSecret} - req, err := http.NewRequest("POST", "https://api.twitter.com/1/statuses/update.json?include_entities=true", strings.NewReader(values.Encode())) - assert.Nil(t, err) - req.Header.Set(contentType, formContentType) - err = auther.setRequestAuthHeader(req, accessToken) - // assert that request is signed and has an access token token - assert.Nil(t, err) - params := parseOAuthParamsOrFail(t, req.Header.Get(authorizationHeaderParam)) - assert.Equal(t, expectedTwitterOAuthToken, params[oauthTokenParam]) - assert.Equal(t, expectedSignature, params[oauthSignatureParam]) - // additional OAuth parameters - assert.Equal(t, expectedTwitterConsumerKey, params[oauthConsumerKeyParam]) - assert.Equal(t, expectedNonce, params[oauthNonceParam]) - assert.Equal(t, expectedSignatureMethod, params[oauthSignatureMethodParam]) - assert.Equal(t, expectedTimestamp, params[oauthTimestampParam]) - assert.Equal(t, expectedVersion, params[oauthVersionParam]) -} - -func parseOAuthParamsOrFail(t *testing.T, authHeader string) map[string]string { - if !strings.HasPrefix(authHeader, authorizationPrefix) { - assert.Fail(t, fmt.Sprintf("Expected Authorization header to start with \"%s\", got \"%s\"", authorizationPrefix, authHeader[:len(authorizationPrefix)+1])) - } - params := map[string]string{} - for _, pairStr := range strings.Split(authHeader[len(authorizationPrefix):], ", ") { - pair := strings.Split(pairStr, "=") - if len(pair) != 2 { - assert.Fail(t, "Error parsing OAuth parameter %s", pairStr) - } - params[pair[0]] = strings.Replace(pair[1], "\"", "", -1) - } - return params -} - -type fixedClock struct { - now time.Time -} - -func (c *fixedClock) Now() time.Time { - return c.now -} - -type fixedNoncer struct { - nonce string -} - -func (n *fixedNoncer) Nonce() string { - return n.nonce -} diff --git a/vendor/github.com/dghubble/oauth1/signer.go b/vendor/github.com/dghubble/oauth1/signer.go deleted file mode 100644 index 341c85929..000000000 --- a/vendor/github.com/dghubble/oauth1/signer.go +++ /dev/null @@ -1,62 +0,0 @@ -package oauth1 - -import ( - "crypto" - "crypto/hmac" - "crypto/rand" - "crypto/rsa" - "crypto/sha1" - "encoding/base64" - "strings" -) - -// A Signer signs messages to create signed OAuth1 Requests. -type Signer interface { - // Name returns the name of the signing method. - Name() string - // Sign signs the message using the given secret key. - Sign(key string, message string) (string, error) -} - -// HMACSigner signs messages with an HMAC SHA1 digest, using the concatenated -// consumer secret and token secret as the key. -type HMACSigner struct { - ConsumerSecret string -} - -// Name returns the HMAC-SHA1 method. -func (s *HMACSigner) Name() string { - return "HMAC-SHA1" -} - -// Sign creates a concatenated consumer and token secret key and calculates -// the HMAC digest of the message. Returns the base64 encoded digest bytes. -func (s *HMACSigner) Sign(tokenSecret, message string) (string, error) { - signingKey := strings.Join([]string{s.ConsumerSecret, tokenSecret}, "&") - mac := hmac.New(sha1.New, []byte(signingKey)) - mac.Write([]byte(message)) - signatureBytes := mac.Sum(nil) - return base64.StdEncoding.EncodeToString(signatureBytes), nil -} - -// RSASigner RSA PKCS1-v1_5 signs SHA1 digests of messages using the given -// RSA private key. -type RSASigner struct { - PrivateKey *rsa.PrivateKey -} - -// Name returns the RSA-SHA1 method. -func (s *RSASigner) Name() string { - return "RSA-SHA1" -} - -// Sign uses RSA PKCS1-v1_5 to sign a SHA1 digest of the given message. The -// tokenSecret is not used with this signing scheme. -func (s *RSASigner) Sign(tokenSecret, message string) (string, error) { - digest := sha1.Sum([]byte(message)) - signature, err := rsa.SignPKCS1v15(rand.Reader, s.PrivateKey, crypto.SHA1, digest[:]) - if err != nil { - return "", err - } - return base64.StdEncoding.EncodeToString(signature), nil -} diff --git a/vendor/github.com/dghubble/oauth1/test b/vendor/github.com/dghubble/oauth1/test deleted file mode 100755 index b37bf4d6b..000000000 --- a/vendor/github.com/dghubble/oauth1/test +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -set -e - -PKGS=$(go list ./... | grep -v /examples) -FORMATTABLE="$(find . -maxdepth 1 -type d)" -LINTABLE=$(go list ./...) - -go test $PKGS -cover -go vet $PKGS - -echo "Checking gofmt..." -fmtRes=$(gofmt -l $FORMATTABLE) -if [ -n "${fmtRes}" ]; then - echo -e "gofmt checking failed:\n${fmtRes}" - exit 2 -fi - -echo "Checking golint..." -lintRes=$(echo $LINTABLE | xargs -n 1 golint) -if [ -n "${lintRes}" ]; then - echo -e "golint checking failed:\n${lintRes}" - exit 2 -fi diff --git a/vendor/github.com/dghubble/oauth1/token.go b/vendor/github.com/dghubble/oauth1/token.go deleted file mode 100644 index d010d2fcc..000000000 --- a/vendor/github.com/dghubble/oauth1/token.go +++ /dev/null @@ -1,43 +0,0 @@ -package oauth1 - -import ( - "errors" -) - -// A TokenSource can return a Token. -type TokenSource interface { - Token() (*Token, error) -} - -// Token is an AccessToken (token credential) which allows a consumer (client) -// to access resources from an OAuth1 provider server. -type Token struct { - Token string - TokenSecret string -} - -// NewToken returns a new Token with the given token and token secret. -func NewToken(token, tokenSecret string) *Token { - return &Token{ - Token: token, - TokenSecret: tokenSecret, - } -} - -// StaticTokenSource returns a TokenSource which always returns the same Token. -// This is appropriate for tokens which do not have a time expiration. -func StaticTokenSource(token *Token) TokenSource { - return staticTokenSource{token} -} - -// staticTokenSource is a TokenSource that always returns the same Token. -type staticTokenSource struct { - token *Token -} - -func (s staticTokenSource) Token() (*Token, error) { - if s.token == nil { - return nil, errors.New("oauth1: Token is nil") - } - return s.token, nil -} diff --git a/vendor/github.com/dghubble/oauth1/token_test.go b/vendor/github.com/dghubble/oauth1/token_test.go deleted file mode 100644 index 140dc4517..000000000 --- a/vendor/github.com/dghubble/oauth1/token_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package oauth1 - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNewToken(t *testing.T) { - expectedToken := "token" - expectedSecret := "secret" - tk := NewToken(expectedToken, expectedSecret) - assert.Equal(t, expectedToken, tk.Token) - assert.Equal(t, expectedSecret, tk.TokenSecret) -} - -func TestStaticTokenSource(t *testing.T) { - ts := StaticTokenSource(NewToken("t", "s")) - tk, err := ts.Token() - assert.Nil(t, err) - assert.Equal(t, "t", tk.Token) -} - -func TestStaticTokenSourceEmpty(t *testing.T) { - ts := StaticTokenSource(nil) - tk, err := ts.Token() - assert.Nil(t, tk) - if assert.Error(t, err) { - assert.Equal(t, "oauth1: Token is nil", err.Error()) - } -} diff --git a/vendor/github.com/dghubble/oauth1/transport.go b/vendor/github.com/dghubble/oauth1/transport.go deleted file mode 100644 index c1af9937e..000000000 --- a/vendor/github.com/dghubble/oauth1/transport.go +++ /dev/null @@ -1,65 +0,0 @@ -package oauth1 - -import ( - "fmt" - "net/http" -) - -// Transport is an http.RoundTripper which makes OAuth1 HTTP requests. It -// wraps a base RoundTripper and adds an Authorization header using the -// token from a TokenSource. -// -// Transport is a low-level component, most users should use Config to create -// an http.Client instead. -type Transport struct { - // Base is the base RoundTripper used to make HTTP requests. If nil, then - // http.DefaultTransport is used - Base http.RoundTripper - // source supplies the token to use when signing a request - source TokenSource - // auther adds OAuth1 Authorization headers to requests - auther *auther -} - -// RoundTrip authorizes the request with a signed OAuth1 Authorization header -// using the auther and TokenSource. -func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { - if t.source == nil { - return nil, fmt.Errorf("oauth1: Transport's source is nil") - } - accessToken, err := t.source.Token() - if err != nil { - return nil, err - } - if t.auther == nil { - return nil, fmt.Errorf("oauth1: Transport's auther is nil") - } - // RoundTripper should not modify the given request, clone it - req2 := cloneRequest(req) - err = t.auther.setRequestAuthHeader(req2, accessToken) - if err != nil { - return nil, err - } - return t.base().RoundTrip(req2) -} - -func (t *Transport) base() http.RoundTripper { - if t.Base != nil { - return t.Base - } - return http.DefaultTransport -} - -// cloneRequest returns a clone of the given *http.Request with a shallow -// copy of struct fields and a deep copy of the Header map. -func cloneRequest(req *http.Request) *http.Request { - // shallow copy the struct - r2 := new(http.Request) - *r2 = *req - // deep copy Header so setting a header on the clone does not affect original - r2.Header = make(http.Header, len(req.Header)) - for k, s := range req.Header { - r2.Header[k] = append([]string(nil), s...) - } - return r2 -} diff --git a/vendor/github.com/dghubble/oauth1/transport_test.go b/vendor/github.com/dghubble/oauth1/transport_test.go deleted file mode 100644 index 4a6fef5f7..000000000 --- a/vendor/github.com/dghubble/oauth1/transport_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package oauth1 - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestTransport(t *testing.T) { - const ( - expectedToken = "access_token" - expectedConsumerKey = "consumer_key" - expectedNonce = "some_nonce" - expectedSignatureMethod = "HMAC-SHA1" - expectedTimestamp = "123456789" - ) - server := newMockServer(func(w http.ResponseWriter, req *http.Request) { - params := parseOAuthParamsOrFail(t, req.Header.Get("Authorization")) - assert.Equal(t, expectedToken, params[oauthTokenParam]) - assert.Equal(t, expectedConsumerKey, params[oauthConsumerKeyParam]) - assert.Equal(t, expectedNonce, params[oauthNonceParam]) - assert.Equal(t, expectedSignatureMethod, params[oauthSignatureMethodParam]) - assert.Equal(t, expectedTimestamp, params[oauthTimestampParam]) - assert.Equal(t, defaultOauthVersion, params[oauthVersionParam]) - // oauth_signature will vary, httptest.Server uses a random port - }) - defer server.Close() - - config := &Config{ - ConsumerKey: expectedConsumerKey, - ConsumerSecret: "consumer_secret", - } - auther := &auther{ - config: config, - clock: &fixedClock{time.Unix(123456789, 0)}, - noncer: &fixedNoncer{expectedNonce}, - } - tr := &Transport{ - source: StaticTokenSource(NewToken(expectedToken, "some_secret")), - auther: auther, - } - client := &http.Client{Transport: tr} - - req, err := http.NewRequest("GET", server.URL, nil) - assert.Nil(t, err) - _, err = client.Do(req) - assert.Nil(t, err) -} - -func TestTransport_defaultBaseTransport(t *testing.T) { - tr := &Transport{ - Base: nil, - } - assert.Equal(t, http.DefaultTransport, tr.base()) -} - -func TestTransport_customBaseTransport(t *testing.T) { - expected := &http.Transport{} - tr := &Transport{ - Base: expected, - } - assert.Equal(t, expected, tr.base()) -} - -func TestTransport_nilSource(t *testing.T) { - tr := &Transport{ - source: nil, - auther: &auther{ - config: &Config{}, - clock: &fixedClock{time.Unix(123456789, 0)}, - noncer: &fixedNoncer{"any_nonce"}, - }, - } - client := &http.Client{Transport: tr} - resp, err := client.Get("http://example.com") - assert.Nil(t, resp) - if assert.Error(t, err) { - assert.Equal(t, "Get http://example.com: oauth1: Transport's source is nil", err.Error()) - } -} - -func TestTransport_emptySource(t *testing.T) { - tr := &Transport{ - source: StaticTokenSource(nil), - auther: &auther{ - config: &Config{}, - clock: &fixedClock{time.Unix(123456789, 0)}, - noncer: &fixedNoncer{"any_nonce"}, - }, - } - client := &http.Client{Transport: tr} - resp, err := client.Get("http://example.com") - assert.Nil(t, resp) - if assert.Error(t, err) { - assert.Equal(t, "Get http://example.com: oauth1: Token is nil", err.Error()) - } -} - -func TestTransport_nilAuther(t *testing.T) { - tr := &Transport{ - source: StaticTokenSource(&Token{}), - auther: nil, - } - client := &http.Client{Transport: tr} - resp, err := client.Get("http://example.com") - assert.Nil(t, resp) - if assert.Error(t, err) { - assert.Equal(t, "Get http://example.com: oauth1: Transport's auther is nil", err.Error()) - } -} - -func newMockServer(handler func(w http.ResponseWriter, r *http.Request)) *httptest.Server { - return httptest.NewServer(http.HandlerFunc(handler)) -} diff --git a/vendor/github.com/dghubble/oauth1/tumblr/tumblr.go b/vendor/github.com/dghubble/oauth1/tumblr/tumblr.go deleted file mode 100644 index 5c020ca75..000000000 --- a/vendor/github.com/dghubble/oauth1/tumblr/tumblr.go +++ /dev/null @@ -1,13 +0,0 @@ -// Package tumblr provides constants for using OAuth 1 to access Tumblr. -package tumblr - -import ( - "github.com/dghubble/oauth1" -) - -// Endpoint is Tumblr's OAuth 1a endpoint. -var Endpoint = oauth1.Endpoint{ - RequestTokenURL: "http://www.tumblr.com/oauth/request_token", - AuthorizeURL: "http://www.tumblr.com/oauth/authorize", - AccessTokenURL: "http://www.tumblr.com/oauth/access_token", -} diff --git a/vendor/github.com/dghubble/oauth1/twitter/twitter.go b/vendor/github.com/dghubble/oauth1/twitter/twitter.go deleted file mode 100644 index ffb0ea61f..000000000 --- a/vendor/github.com/dghubble/oauth1/twitter/twitter.go +++ /dev/null @@ -1,25 +0,0 @@ -// Package twitter provides constants for using OAuth1 to access Twitter. -package twitter - -import ( - "github.com/dghubble/oauth1" -) - -// AuthenticateEndpoint is Twitter's OAuth 1 endpoint which uses the -// oauth/authenticate AuthorizeURL redirect. Logged in users who have granted -// access are immediately authenticated and redirected to the callback URL. -var AuthenticateEndpoint = oauth1.Endpoint{ - RequestTokenURL: "https://api.twitter.com/oauth/request_token", - AuthorizeURL: "https://api.twitter.com/oauth/authenticate", - AccessTokenURL: "https://api.twitter.com/oauth/access_token", -} - -// AuthorizeEndpoint is Twitter's OAuth 1 endpoint which uses the -// oauth/authorize AuthorizeURL redirect. Note that this requires users who -// have granted access previously, to re-grant access at AuthorizeURL. -// Prefer AuthenticateEndpoint over AuthorizeEndpoint if you are unsure. -var AuthorizeEndpoint = oauth1.Endpoint{ - RequestTokenURL: "https://api.twitter.com/oauth/request_token", - AuthorizeURL: "https://api.twitter.com/oauth/authorize", - AccessTokenURL: "https://api.twitter.com/oauth/access_token", -} diff --git a/vendor/github.com/dghubble/oauth1/xing/xing.go b/vendor/github.com/dghubble/oauth1/xing/xing.go deleted file mode 100644 index be47c5f0e..000000000 --- a/vendor/github.com/dghubble/oauth1/xing/xing.go +++ /dev/null @@ -1,13 +0,0 @@ -// Package xing provides constants for using OAuth1 to access Xing. -package xing - -import ( - "github.com/dghubble/oauth1" -) - -// Endpoint is Xing's OAuth 1 endpoint. -var Endpoint = oauth1.Endpoint{ - RequestTokenURL: "https://api.xing.com/v1/request_token", - AuthorizeURL: "https://api.xing.com/v1/authorize", - AccessTokenURL: "https://api.xing.com/v1/access_token", -} diff --git a/vendor/github.com/dgrijalva/jwt-go/.gitignore b/vendor/github.com/dgrijalva/jwt-go/.gitignore deleted file mode 100644 index 80bed650e..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -bin - - diff --git a/vendor/github.com/dgrijalva/jwt-go/.travis.yml b/vendor/github.com/dgrijalva/jwt-go/.travis.yml deleted file mode 100644 index 1027f56cd..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -script: - - go vet ./... - - go test -v ./... - -go: - - 1.3 - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - tip diff --git a/vendor/github.com/dgrijalva/jwt-go/LICENSE b/vendor/github.com/dgrijalva/jwt-go/LICENSE deleted file mode 100644 index df83a9c2f..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/LICENSE +++ /dev/null @@ -1,8 +0,0 @@ -Copyright (c) 2012 Dave Grijalva - -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/dgrijalva/jwt-go/MIGRATION_GUIDE.md b/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md deleted file mode 100644 index 7fc1f793c..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md +++ /dev/null @@ -1,97 +0,0 @@ -## Migration Guide from v2 -> v3 - -Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code. - -### `Token.Claims` is now an interface type - -The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`. - -`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property. - -The old example for parsing a token looked like this.. - -```go - if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { - fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) - } -``` - -is now directly mapped to... - -```go - if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil { - claims := token.Claims.(jwt.MapClaims) - fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) - } -``` - -`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type. - -```go - type MyCustomClaims struct { - User string - *StandardClaims - } - - if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil { - claims := token.Claims.(*MyCustomClaims) - fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt) - } -``` - -### `ParseFromRequest` has been moved - -To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`. - -`Extractors` do the work of picking the token string out of a request. The interface is simple and composable. - -This simple parsing example: - -```go - if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil { - fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"]) - } -``` - -is directly mapped to: - -```go - if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil { - claims := token.Claims.(jwt.MapClaims) - fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"]) - } -``` - -There are several concrete `Extractor` types provided for your convenience: - -* `HeaderExtractor` will search a list of headers until one contains content. -* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content. -* `MultiExtractor` will try a list of `Extractors` in order until one returns content. -* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token. -* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument -* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header - - -### RSA signing methods no longer accept `[]byte` keys - -Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse. - -To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types. - -```go - func keyLookupFunc(*Token) (interface{}, error) { - // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - - // Look up key - key, err := lookupPublicKey(token.Header["kid"]) - if err != nil { - return nil, err - } - - // Unpack key from PEM encoded PKCS8 - return jwt.ParseRSAPublicKeyFromPEM(key) - } -``` diff --git a/vendor/github.com/dgrijalva/jwt-go/README.md b/vendor/github.com/dgrijalva/jwt-go/README.md deleted file mode 100644 index 25aec486c..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/README.md +++ /dev/null @@ -1,85 +0,0 @@ -A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) - -[![Build Status](https://travis-ci.org/dgrijalva/jwt-go.svg?branch=master)](https://travis-ci.org/dgrijalva/jwt-go) - -**BREAKING CHANGES:*** Version 3.0.0 is here. It includes _a lot_ of changes including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. - -**NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. - - -## What the heck is a JWT? - -JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. - -In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way. - -The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. - -The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own. - -## What's in the box? - -This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. - -## Examples - -See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage: - -* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac) -* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac) -* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples) - -## Extensions - -This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`. - -Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go - -## Compliance - -This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences: - -* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. - -## Project Status & Versioning - -This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). - -This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases). - -While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v2`. It will do the right thing WRT semantic versioning. - -## Usage Tips - -### Signing vs Encryption - -A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: - -* The author of the token was in the possession of the signing secret -* The data has not been modified since it was signed - -It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library. - -### Choosing a Signing Method - -There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. - -Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. - -Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. - -### JWT and OAuth - -It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. - -Without going too far down the rabbit hole, here's a description of the interaction of these technologies: - -* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. -* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. -* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. - -## More - -Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go). - -The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. diff --git a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md b/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md deleted file mode 100644 index b605b4509..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md +++ /dev/null @@ -1,105 +0,0 @@ -## `jwt-go` Version History - -#### 3.0.0 - -* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code - * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. - * `ParseFromRequest` has been moved to `request` subpackage and usage has changed - * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. -* Other Additions and Changes - * Added `Claims` interface type to allow users to decode the claims into a custom type - * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. - * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage - * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` - * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. - * Added several new, more specific, validation errors to error type bitmask - * Moved examples from README to executable example files - * Signing method registry is now thread safe - * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) - -#### 2.7.0 - -This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. - -* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying -* Error text for expired tokens includes how long it's been expired -* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` -* Documentation updates - -#### 2.6.0 - -* Exposed inner error within ValidationError -* Fixed validation errors when using UseJSONNumber flag -* Added several unit tests - -#### 2.5.0 - -* Added support for signing method none. You shouldn't use this. The API tries to make this clear. -* Updated/fixed some documentation -* Added more helpful error message when trying to parse tokens that begin with `BEARER ` - -#### 2.4.0 - -* Added new type, Parser, to allow for configuration of various parsing parameters - * You can now specify a list of valid signing methods. Anything outside this set will be rejected. - * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON -* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) -* Fixed some bugs with ECDSA parsing - -#### 2.3.0 - -* Added support for ECDSA signing methods -* Added support for RSA PSS signing methods (requires go v1.4) - -#### 2.2.0 - -* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. - -#### 2.1.0 - -Backwards compatible API change that was missed in 2.0.0. - -* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` - -#### 2.0.0 - -There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. - -The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. - -It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. - -* **Compatibility Breaking Changes** - * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` - * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` - * `KeyFunc` now returns `interface{}` instead of `[]byte` - * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key - * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key -* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodHS256` - * Added public package global `SigningMethodHS384` - * Added public package global `SigningMethodHS512` -* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodRS256` - * Added public package global `SigningMethodRS384` - * Added public package global `SigningMethodRS512` -* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. -* Refactored the RSA implementation to be easier to read -* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` - -#### 1.0.2 - -* Fixed bug in parsing public keys from certificates -* Added more tests around the parsing of keys for RS256 -* Code refactoring in RS256 implementation. No functional changes - -#### 1.0.1 - -* Fixed panic if RS256 signing method was passed an invalid key - -#### 1.0.0 - -* First versioned release -* API stabilized -* Supports creating, signing, parsing, and validating JWT tokens -* Supports RS256 and HS256 signing methods \ No newline at end of file diff --git a/vendor/github.com/dgrijalva/jwt-go/claims.go b/vendor/github.com/dgrijalva/jwt-go/claims.go deleted file mode 100644 index f0228f02e..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/claims.go +++ /dev/null @@ -1,134 +0,0 @@ -package jwt - -import ( - "crypto/subtle" - "fmt" - "time" -) - -// For a type to be a Claims object, it must just have a Valid method that determines -// if the token is invalid for any supported reason -type Claims interface { - Valid() error -} - -// Structured version of Claims Section, as referenced at -// https://tools.ietf.org/html/rfc7519#section-4.1 -// See examples for how to use this with your own claim types -type StandardClaims struct { - Audience string `json:"aud,omitempty"` - ExpiresAt int64 `json:"exp,omitempty"` - Id string `json:"jti,omitempty"` - IssuedAt int64 `json:"iat,omitempty"` - Issuer string `json:"iss,omitempty"` - NotBefore int64 `json:"nbf,omitempty"` - Subject string `json:"sub,omitempty"` -} - -// Validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c StandardClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if c.VerifyExpiresAt(now, false) == false { - delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) - vErr.Inner = fmt.Errorf("token is expired by %v", delta) - vErr.Errors |= ValidationErrorExpired - } - - if c.VerifyIssuedAt(now, false) == false { - vErr.Inner = fmt.Errorf("Token used before issued") - vErr.Errors |= ValidationErrorIssuedAt - } - - if c.VerifyNotBefore(now, false) == false { - vErr.Inner = fmt.Errorf("token is not valid yet") - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} - -// Compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud(c.Audience, cmp, req) -} - -// Compares the exp claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { - return verifyExp(c.ExpiresAt, cmp, req) -} - -// Compares the iat claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { - return verifyIat(c.IssuedAt, cmp, req) -} - -// Compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - -// Compares the nbf claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { - return verifyNbf(c.NotBefore, cmp, req) -} - -// ----- helpers - -func verifyAud(aud string, cmp string, required bool) bool { - if aud == "" { - return !required - } - if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 { - return true - } else { - return false - } -} - -func verifyExp(exp int64, now int64, required bool) bool { - if exp == 0 { - return !required - } - return now <= exp -} - -func verifyIat(iat int64, now int64, required bool) bool { - if iat == 0 { - return !required - } - return now >= iat -} - -func verifyIss(iss string, cmp string, required bool) bool { - if iss == "" { - return !required - } - if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 { - return true - } else { - return false - } -} - -func verifyNbf(nbf int64, now int64, required bool) bool { - if nbf == 0 { - return !required - } - return now >= nbf -} diff --git a/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/README.md b/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/README.md deleted file mode 100644 index c05150e33..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/README.md +++ /dev/null @@ -1,13 +0,0 @@ -`jwt` command-line tool -======================= - -This is a simple tool to sign, verify and show JSON Web Tokens from -the command line. - -The following will create and sign a token, then verify it and output the original claims: - - echo {\"foo\":\"bar\"} | ./jwt -key ../../test/sample_key -alg RS256 -sign - | ./jwt -key ../../test/sample_key.pub -alg RS256 -verify - - -To simply display a token, use: - - echo $JWT | ./jwt -show - diff --git a/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/app.go b/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/app.go deleted file mode 100644 index 727182a98..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/app.go +++ /dev/null @@ -1,282 +0,0 @@ -// A useful example app. You can use this to debug your tokens on the command line. -// This is also a great place to look at how you might use this library. -// -// Example usage: -// The following will create and sign a token, then verify it and output the original claims. -// echo {\"foo\":\"bar\"} | bin/jwt -key test/sample_key -alg RS256 -sign - | bin/jwt -key test/sample_key.pub -verify - -package main - -import ( - "encoding/json" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "regexp" - "strings" - - jwt "github.com/dgrijalva/jwt-go" -) - -var ( - // Options - flagAlg = flag.String("alg", "", "signing algorithm identifier") - flagKey = flag.String("key", "", "path to key file or '-' to read from stdin") - flagCompact = flag.Bool("compact", false, "output compact JSON") - flagDebug = flag.Bool("debug", false, "print out all kinds of debug data") - flagClaims = make(ArgList) - flagHead = make(ArgList) - - // Modes - exactly one of these is required - flagSign = flag.String("sign", "", "path to claims object to sign, '-' to read from stdin, or '+' to use only -claim args") - flagVerify = flag.String("verify", "", "path to JWT token to verify or '-' to read from stdin") - flagShow = flag.String("show", "", "path to JWT file or '-' to read from stdin") -) - -func main() { - // Plug in Var flags - flag.Var(flagClaims, "claim", "add additional claims. may be used more than once") - flag.Var(flagHead, "header", "add additional header params. may be used more than once") - - // Usage message if you ask for -help or if you mess up inputs. - flag.Usage = func() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) - fmt.Fprintf(os.Stderr, " One of the following flags is required: sign, verify\n") - flag.PrintDefaults() - } - - // Parse command line options - flag.Parse() - - // Do the thing. If something goes wrong, print error to stderr - // and exit with a non-zero status code - if err := start(); err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } -} - -// Figure out which thing to do and then do that -func start() error { - if *flagSign != "" { - return signToken() - } else if *flagVerify != "" { - return verifyToken() - } else if *flagShow != "" { - return showToken() - } else { - flag.Usage() - return fmt.Errorf("None of the required flags are present. What do you want me to do?") - } -} - -// Helper func: Read input from specified file or stdin -func loadData(p string) ([]byte, error) { - if p == "" { - return nil, fmt.Errorf("No path specified") - } - - var rdr io.Reader - if p == "-" { - rdr = os.Stdin - } else if p == "+" { - return []byte("{}"), nil - } else { - if f, err := os.Open(p); err == nil { - rdr = f - defer f.Close() - } else { - return nil, err - } - } - return ioutil.ReadAll(rdr) -} - -// Print a json object in accordance with the prophecy (or the command line options) -func printJSON(j interface{}) error { - var out []byte - var err error - - if *flagCompact == false { - out, err = json.MarshalIndent(j, "", " ") - } else { - out, err = json.Marshal(j) - } - - if err == nil { - fmt.Println(string(out)) - } - - return err -} - -// Verify a token and output the claims. This is a great example -// of how to verify and view a token. -func verifyToken() error { - // get the token - tokData, err := loadData(*flagVerify) - if err != nil { - return fmt.Errorf("Couldn't read token: %v", err) - } - - // trim possible whitespace from token - tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{}) - if *flagDebug { - fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData)) - } - - // Parse the token. Load the key from command line option - token, err := jwt.Parse(string(tokData), func(t *jwt.Token) (interface{}, error) { - data, err := loadData(*flagKey) - if err != nil { - return nil, err - } - if isEs() { - return jwt.ParseECPublicKeyFromPEM(data) - } else if isRs() { - return jwt.ParseRSAPublicKeyFromPEM(data) - } - return data, nil - }) - - // Print some debug data - if *flagDebug && token != nil { - fmt.Fprintf(os.Stderr, "Header:\n%v\n", token.Header) - fmt.Fprintf(os.Stderr, "Claims:\n%v\n", token.Claims) - } - - // Print an error if we can't parse for some reason - if err != nil { - return fmt.Errorf("Couldn't parse token: %v", err) - } - - // Is token invalid? - if !token.Valid { - return fmt.Errorf("Token is invalid") - } - - // Print the token details - if err := printJSON(token.Claims); err != nil { - return fmt.Errorf("Failed to output claims: %v", err) - } - - return nil -} - -// Create, sign, and output a token. This is a great, simple example of -// how to use this library to create and sign a token. -func signToken() error { - // get the token data from command line arguments - tokData, err := loadData(*flagSign) - if err != nil { - return fmt.Errorf("Couldn't read token: %v", err) - } else if *flagDebug { - fmt.Fprintf(os.Stderr, "Token: %v bytes", len(tokData)) - } - - // parse the JSON of the claims - var claims jwt.MapClaims - if err := json.Unmarshal(tokData, &claims); err != nil { - return fmt.Errorf("Couldn't parse claims JSON: %v", err) - } - - // add command line claims - if len(flagClaims) > 0 { - for k, v := range flagClaims { - claims[k] = v - } - } - - // get the key - var key interface{} - key, err = loadData(*flagKey) - if err != nil { - return fmt.Errorf("Couldn't read key: %v", err) - } - - // get the signing alg - alg := jwt.GetSigningMethod(*flagAlg) - if alg == nil { - return fmt.Errorf("Couldn't find signing method: %v", *flagAlg) - } - - // create a new token - token := jwt.NewWithClaims(alg, claims) - - // add command line headers - if len(flagHead) > 0 { - for k, v := range flagHead { - token.Header[k] = v - } - } - - if isEs() { - if k, ok := key.([]byte); !ok { - return fmt.Errorf("Couldn't convert key data to key") - } else { - key, err = jwt.ParseECPrivateKeyFromPEM(k) - if err != nil { - return err - } - } - } else if isRs() { - if k, ok := key.([]byte); !ok { - return fmt.Errorf("Couldn't convert key data to key") - } else { - key, err = jwt.ParseRSAPrivateKeyFromPEM(k) - if err != nil { - return err - } - } - } - - if out, err := token.SignedString(key); err == nil { - fmt.Println(out) - } else { - return fmt.Errorf("Error signing token: %v", err) - } - - return nil -} - -// showToken pretty-prints the token on the command line. -func showToken() error { - // get the token - tokData, err := loadData(*flagShow) - if err != nil { - return fmt.Errorf("Couldn't read token: %v", err) - } - - // trim possible whitespace from token - tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{}) - if *flagDebug { - fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData)) - } - - token, err := jwt.Parse(string(tokData), nil) - if token == nil { - return fmt.Errorf("malformed token: %v", err) - } - - // Print the token details - fmt.Println("Header:") - if err := printJSON(token.Header); err != nil { - return fmt.Errorf("Failed to output header: %v", err) - } - - fmt.Println("Claims:") - if err := printJSON(token.Claims); err != nil { - return fmt.Errorf("Failed to output claims: %v", err) - } - - return nil -} - -func isEs() bool { - return strings.HasPrefix(*flagAlg, "ES") -} - -func isRs() bool { - return strings.HasPrefix(*flagAlg, "RS") -} diff --git a/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/args.go b/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/args.go deleted file mode 100644 index a5bba5b10..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/cmd/jwt/args.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "strings" -) - -type ArgList map[string]string - -func (l ArgList) String() string { - data, _ := json.Marshal(l) - return string(data) -} - -func (l ArgList) Set(arg string) error { - parts := strings.SplitN(arg, "=", 2) - if len(parts) != 2 { - return fmt.Errorf("Invalid argument '%v'. Must use format 'key=value'. %v", arg, parts) - } - l[parts[0]] = parts[1] - return nil -} diff --git a/vendor/github.com/dgrijalva/jwt-go/doc.go b/vendor/github.com/dgrijalva/jwt-go/doc.go deleted file mode 100644 index a86dc1a3b..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html -// -// See README.md for more info. -package jwt diff --git a/vendor/github.com/dgrijalva/jwt-go/ecdsa.go b/vendor/github.com/dgrijalva/jwt-go/ecdsa.go deleted file mode 100644 index 2f59a2223..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/ecdsa.go +++ /dev/null @@ -1,147 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/ecdsa" - "crypto/rand" - "errors" - "math/big" -) - -var ( - // Sadly this is missing from crypto/ecdsa compared to crypto/rsa - ErrECDSAVerification = errors.New("crypto/ecdsa: verification error") -) - -// Implements the ECDSA family of signing methods signing methods -type SigningMethodECDSA struct { - Name string - Hash crypto.Hash - KeySize int - CurveBits int -} - -// Specific instances for EC256 and company -var ( - SigningMethodES256 *SigningMethodECDSA - SigningMethodES384 *SigningMethodECDSA - SigningMethodES512 *SigningMethodECDSA -) - -func init() { - // ES256 - SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256} - RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod { - return SigningMethodES256 - }) - - // ES384 - SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384} - RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod { - return SigningMethodES384 - }) - - // ES512 - SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521} - RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod { - return SigningMethodES512 - }) -} - -func (m *SigningMethodECDSA) Alg() string { - return m.Name -} - -// Implements the Verify method from SigningMethod -// For this verify method, key must be an ecdsa.PublicKey struct -func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - // Get the key - var ecdsaKey *ecdsa.PublicKey - switch k := key.(type) { - case *ecdsa.PublicKey: - ecdsaKey = k - default: - return ErrInvalidKeyType - } - - if len(sig) != 2*m.KeySize { - return ErrECDSAVerification - } - - r := big.NewInt(0).SetBytes(sig[:m.KeySize]) - s := big.NewInt(0).SetBytes(sig[m.KeySize:]) - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Verify the signature - if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true { - return nil - } else { - return ErrECDSAVerification - } -} - -// Implements the Sign method from SigningMethod -// For this signing method, key must be an ecdsa.PrivateKey struct -func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { - // Get the key - var ecdsaKey *ecdsa.PrivateKey - switch k := key.(type) { - case *ecdsa.PrivateKey: - ecdsaKey = k - default: - return "", ErrInvalidKeyType - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return r, s - if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { - curveBits := ecdsaKey.Curve.Params().BitSize - - if m.CurveBits != curveBits { - return "", ErrInvalidKey - } - - keyBytes := curveBits / 8 - if curveBits%8 > 0 { - keyBytes += 1 - } - - // We serialize the outpus (r and s) into big-endian byte arrays and pad - // them with zeros on the left to make sure the sizes work out. Both arrays - // must be keyBytes long, and the output must be 2*keyBytes long. - rBytes := r.Bytes() - rBytesPadded := make([]byte, keyBytes) - copy(rBytesPadded[keyBytes-len(rBytes):], rBytes) - - sBytes := s.Bytes() - sBytesPadded := make([]byte, keyBytes) - copy(sBytesPadded[keyBytes-len(sBytes):], sBytes) - - out := append(rBytesPadded, sBytesPadded...) - - return EncodeSegment(out), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go b/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go deleted file mode 100644 index 753047b1e..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/ecdsa_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package jwt_test - -import ( - "crypto/ecdsa" - "io/ioutil" - "strings" - "testing" - - "github.com/dgrijalva/jwt-go" -) - -var ecdsaTestData = []struct { - name string - keys map[string]string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "Basic ES256", - map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"}, - "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJmb28iOiJiYXIifQ.feG39E-bn8HXAKhzDZq7yEAPWYDhZlwTn3sePJnU9VrGMmwdXAIEyoOnrjreYlVM_Z4N13eK9-TmMTWyfKJtHQ", - "ES256", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic ES384", - map[string]string{"private": "test/ec384-private.pem", "public": "test/ec384-public.pem"}, - "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzM4NCJ9.eyJmb28iOiJiYXIifQ.ngAfKMbJUh0WWubSIYe5GMsA-aHNKwFbJk_wq3lq23aPp8H2anb1rRILIzVR0gUf4a8WzDtrzmiikuPWyCS6CN4-PwdgTk-5nehC7JXqlaBZU05p3toM3nWCwm_LXcld", - "ES384", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic ES512", - map[string]string{"private": "test/ec512-private.pem", "public": "test/ec512-public.pem"}, - "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzUxMiJ9.eyJmb28iOiJiYXIifQ.AAU0TvGQOcdg2OvrwY73NHKgfk26UDekh9Prz-L_iWuTBIBqOFCWwwLsRiHB1JOddfKAls5do1W0jR_F30JpVd-6AJeTjGKA4C1A1H6gIKwRY0o_tFDIydZCl_lMBMeG5VNFAjO86-WCSKwc3hqaGkq1MugPRq_qrF9AVbuEB4JPLyL5", - "ES512", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "basic ES256 invalid: foo => bar", - map[string]string{"private": "test/ec256-private.pem", "public": "test/ec256-public.pem"}, - "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.MEQCIHoSJnmGlPaVQDqacx_2XlXEhhqtWceVopjomc2PJLtdAiAUTeGPoNYxZw0z8mgOnnIcjoxRuNDVZvybRZF3wR1l8W", - "ES256", - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestECDSAVerify(t *testing.T) { - for _, data := range ecdsaTestData { - var err error - - key, _ := ioutil.ReadFile(data.keys["public"]) - - var ecdsaKey *ecdsa.PublicKey - if ecdsaKey, err = jwt.ParseECPublicKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse ECDSA public key: %v", err) - } - - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err = method.Verify(strings.Join(parts[0:2], "."), parts[2], ecdsaKey) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestECDSASign(t *testing.T) { - for _, data := range ecdsaTestData { - var err error - key, _ := ioutil.ReadFile(data.keys["private"]) - - var ecdsaKey *ecdsa.PrivateKey - if ecdsaKey, err = jwt.ParseECPrivateKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse ECDSA private key: %v", err) - } - - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), ecdsaKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig == parts[2] { - t.Errorf("[%v] Identical signatures\nbefore:\n%v\nafter:\n%v", data.name, parts[2], sig) - } - } - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/ecdsa_utils.go b/vendor/github.com/dgrijalva/jwt-go/ecdsa_utils.go deleted file mode 100644 index d19624b72..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/ecdsa_utils.go +++ /dev/null @@ -1,67 +0,0 @@ -package jwt - -import ( - "crypto/ecdsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrNotECPublicKey = errors.New("Key is not a valid ECDSA public key") - ErrNotECPrivateKey = errors.New("Key is not a valid ECDSA private key") -) - -// Parse PEM encoded Elliptic Curve Private Key Structure -func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil { - return nil, err - } - - var pkey *ecdsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { - return nil, ErrNotECPrivateKey - } - - return pkey, nil -} - -// Parse PEM encoded PKCS1 or PKCS8 public key -func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - if cert, err := x509.ParseCertificate(block.Bytes); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - var pkey *ecdsa.PublicKey - var ok bool - if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok { - return nil, ErrNotECPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/dgrijalva/jwt-go/errors.go b/vendor/github.com/dgrijalva/jwt-go/errors.go deleted file mode 100644 index 1c93024aa..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/errors.go +++ /dev/null @@ -1,59 +0,0 @@ -package jwt - -import ( - "errors" -) - -// Error constants -var ( - ErrInvalidKey = errors.New("key is invalid") - ErrInvalidKeyType = errors.New("key is of invalid type") - ErrHashUnavailable = errors.New("the requested hash function is unavailable") -) - -// The errors that might occur when parsing and validating a token -const ( - ValidationErrorMalformed uint32 = 1 << iota // Token is malformed - ValidationErrorUnverifiable // Token could not be verified because of signing problems - ValidationErrorSignatureInvalid // Signature validation failed - - // Standard Claim validation errors - ValidationErrorAudience // AUD validation failed - ValidationErrorExpired // EXP validation failed - ValidationErrorIssuedAt // IAT validation failed - ValidationErrorIssuer // ISS validation failed - ValidationErrorNotValidYet // NBF validation failed - ValidationErrorId // JTI validation failed - ValidationErrorClaimsInvalid // Generic claims validation error -) - -// Helper for constructing a ValidationError with a string error message -func NewValidationError(errorText string, errorFlags uint32) *ValidationError { - return &ValidationError{ - text: errorText, - Errors: errorFlags, - } -} - -// The error from Parse if token is not valid -type ValidationError struct { - Inner error // stores the error returned by external dependencies, i.e.: KeyFunc - Errors uint32 // bitfield. see ValidationError... constants - text string // errors that do not have a valid error just have text -} - -// Validation error is an error type -func (e ValidationError) Error() string { - if e.Inner != nil { - return e.Inner.Error() - } else if e.text != "" { - return e.text - } else { - return "token is invalid" - } -} - -// No errors -func (e *ValidationError) valid() bool { - return e.Errors == 0 -} diff --git a/vendor/github.com/dgrijalva/jwt-go/example_test.go b/vendor/github.com/dgrijalva/jwt-go/example_test.go deleted file mode 100644 index ae8b788a0..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/example_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package jwt_test - -import ( - "fmt" - "github.com/dgrijalva/jwt-go" - "time" -) - -// Example (atypical) using the StandardClaims type by itself to parse a token. -// The StandardClaims type is designed to be embedded into your custom types -// to provide standard validation features. You can use it alone, but there's -// no way to retrieve other fields after parsing. -// See the CustomClaimsType example for intended usage. -func ExampleNewWithClaims_standardClaims() { - mySigningKey := []byte("AllYourBase") - - // Create the Claims - claims := &jwt.StandardClaims{ - ExpiresAt: 15000, - Issuer: "test", - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - ss, err := token.SignedString(mySigningKey) - fmt.Printf("%v %v", ss, err) - //Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.QsODzZu3lUZMVdhbO76u3Jv02iYCvEHcYVUI1kOWEU0 -} - -// Example creating a token using a custom claims type. The StandardClaim is embedded -// in the custom type to allow for easy encoding, parsing and validation of standard claims. -func ExampleNewWithClaims_customClaimsType() { - mySigningKey := []byte("AllYourBase") - - type MyCustomClaims struct { - Foo string `json:"foo"` - jwt.StandardClaims - } - - // Create the Claims - claims := MyCustomClaims{ - "bar", - jwt.StandardClaims{ - ExpiresAt: 15000, - Issuer: "test", - }, - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - ss, err := token.SignedString(mySigningKey) - fmt.Printf("%v %v", ss, err) - //Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c -} - -// Example creating a token using a custom claims type. The StandardClaim is embedded -// in the custom type to allow for easy encoding, parsing and validation of standard claims. -func ExampleParseWithClaims_customClaimsType() { - tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c" - - type MyCustomClaims struct { - Foo string `json:"foo"` - jwt.StandardClaims - } - - // sample token is expired. override time so it parses as valid - at(time.Unix(0, 0), func() { - token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) { - return []byte("AllYourBase"), nil - }) - - if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid { - fmt.Printf("%v %v", claims.Foo, claims.StandardClaims.ExpiresAt) - } else { - fmt.Println(err) - } - }) - - // Output: bar 15000 -} - -// Override time value for tests. Restore default value after. -func at(t time.Time, f func()) { - jwt.TimeFunc = func() time.Time { - return t - } - f() - jwt.TimeFunc = time.Now -} - -// An example of parsing the error types using bitfield checks -func ExampleParse_errorChecking() { - // Token from another example. This token is expired - var tokenString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJleHAiOjE1MDAwLCJpc3MiOiJ0ZXN0In0.HE7fK0xOQwFEr4WDgRWj4teRPZ6i3GLwD5YCm6Pwu_c" - - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - return []byte("AllYourBase"), nil - }) - - if token.Valid { - fmt.Println("You look nice today") - } else if ve, ok := err.(*jwt.ValidationError); ok { - if ve.Errors&jwt.ValidationErrorMalformed != 0 { - fmt.Println("That's not even a token") - } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 { - // Token is either expired or not active yet - fmt.Println("Timing is everything") - } else { - fmt.Println("Couldn't handle this token:", err) - } - } else { - fmt.Println("Couldn't handle this token:", err) - } - - // Output: Timing is everything -} diff --git a/vendor/github.com/dgrijalva/jwt-go/hmac.go b/vendor/github.com/dgrijalva/jwt-go/hmac.go deleted file mode 100644 index c22991925..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/hmac.go +++ /dev/null @@ -1,94 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/hmac" - "errors" -) - -// Implements the HMAC-SHA family of signing methods signing methods -type SigningMethodHMAC struct { - Name string - Hash crypto.Hash -} - -// Specific instances for HS256 and company -var ( - SigningMethodHS256 *SigningMethodHMAC - SigningMethodHS384 *SigningMethodHMAC - SigningMethodHS512 *SigningMethodHMAC - ErrSignatureInvalid = errors.New("signature is invalid") -) - -func init() { - // HS256 - SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} - RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { - return SigningMethodHS256 - }) - - // HS384 - SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} - RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { - return SigningMethodHS384 - }) - - // HS512 - SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} - RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { - return SigningMethodHS512 - }) -} - -func (m *SigningMethodHMAC) Alg() string { - return m.Name -} - -// Verify the signature of HSXXX tokens. Returns nil if the signature is valid. -func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { - // Verify the key is the right type - keyBytes, ok := key.([]byte) - if !ok { - return ErrInvalidKeyType - } - - // Decode signature, for comparison - sig, err := DecodeSegment(signature) - if err != nil { - return err - } - - // Can we use the specified hashing method? - if !m.Hash.Available() { - return ErrHashUnavailable - } - - // This signing method is symmetric, so we validate the signature - // by reproducing the signature from the signing string and key, then - // comparing that against the provided signature. - hasher := hmac.New(m.Hash.New, keyBytes) - hasher.Write([]byte(signingString)) - if !hmac.Equal(sig, hasher.Sum(nil)) { - return ErrSignatureInvalid - } - - // No validation errors. Signature is good. - return nil -} - -// Implements the Sign method from SigningMethod for this signing method. -// Key must be []byte -func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { - if keyBytes, ok := key.([]byte); ok { - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := hmac.New(m.Hash.New, keyBytes) - hasher.Write([]byte(signingString)) - - return EncodeSegment(hasher.Sum(nil)), nil - } - - return "", ErrInvalidKey -} diff --git a/vendor/github.com/dgrijalva/jwt-go/hmac_example_test.go b/vendor/github.com/dgrijalva/jwt-go/hmac_example_test.go deleted file mode 100644 index 002783147..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/hmac_example_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package jwt_test - -import ( - "fmt" - "github.com/dgrijalva/jwt-go" - "io/ioutil" - "time" -) - -// For HMAC signing method, the key can be any []byte. It is recommended to generate -// a key using crypto/rand or something equivalent. You need the same key for signing -// and validating. -var hmacSampleSecret []byte - -func init() { - // Load sample key data - if keyData, e := ioutil.ReadFile("test/hmacTestKey"); e == nil { - hmacSampleSecret = keyData - } else { - panic(e) - } -} - -// Example creating, signing, and encoding a JWT token using the HMAC signing method -func ExampleNew_hmac() { - // Create a new token object, specifying signing method and the claims - // you would like it to contain. - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ - "foo": "bar", - "nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(), - }) - - // Sign and get the complete encoded token as a string using the secret - tokenString, err := token.SignedString(hmacSampleSecret) - - fmt.Println(tokenString, err) - // Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJuYmYiOjE0NDQ0Nzg0MDB9.u1riaD1rW97opCoAuRCTy4w58Br-Zk-bh7vLiRIsrpU -} - -// Example parsing and validating a token using the HMAC signing method -func ExampleParse_hmac() { - // sample token string taken from the New example - tokenString := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIiLCJuYmYiOjE0NDQ0Nzg0MDB9.u1riaD1rW97opCoAuRCTy4w58Br-Zk-bh7vLiRIsrpU" - - // Parse takes the token string and a function for looking up the key. The latter is especially - // useful if you use multiple keys for your application. The standard is to use 'kid' in the - // head of the token to identify which key to use, but the parsed token (head and claims) is provided - // to the callback, providing flexibility. - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - - // hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key") - return hmacSampleSecret, nil - }) - - if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { - fmt.Println(claims["foo"], claims["nbf"]) - } else { - fmt.Println(err) - } - - // Output: bar 1.4444784e+09 -} diff --git a/vendor/github.com/dgrijalva/jwt-go/hmac_test.go b/vendor/github.com/dgrijalva/jwt-go/hmac_test.go deleted file mode 100644 index c7e114f4f..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/hmac_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package jwt_test - -import ( - "github.com/dgrijalva/jwt-go" - "io/ioutil" - "strings" - "testing" -) - -var hmacTestData = []struct { - name string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "web sample", - "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk", - "HS256", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - true, - }, - { - "HS384", - "eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJleHAiOjEuMzAwODE5MzhlKzA5LCJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZSwiaXNzIjoiam9lIn0.KWZEuOD5lbBxZ34g7F-SlVLAQ_r5KApWNWlZIIMyQVz5Zs58a7XdNzj5_0EcNoOy", - "HS384", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - true, - }, - { - "HS512", - "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEuMzAwODE5MzhlKzA5LCJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZSwiaXNzIjoiam9lIn0.CN7YijRX6Aw1n2jyI2Id1w90ja-DEMYiWixhYCyHnrZ1VfJRaFQz1bEbjjA5Fn4CLYaUG432dEYmSbS4Saokmw", - "HS512", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - true, - }, - { - "web sample: invalid", - "eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXo", - "HS256", - map[string]interface{}{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": true}, - false, - }, -} - -// Sample data from http://tools.ietf.org/html/draft-jones-json-web-signature-04#appendix-A.1 -var hmacTestKey, _ = ioutil.ReadFile("test/hmacTestKey") - -func TestHMACVerify(t *testing.T) { - for _, data := range hmacTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], hmacTestKey) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestHMACSign(t *testing.T) { - for _, data := range hmacTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), hmacTestKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2]) - } - } - } -} - -func BenchmarkHS256Signing(b *testing.B) { - benchmarkSigning(b, jwt.SigningMethodHS256, hmacTestKey) -} - -func BenchmarkHS384Signing(b *testing.B) { - benchmarkSigning(b, jwt.SigningMethodHS384, hmacTestKey) -} - -func BenchmarkHS512Signing(b *testing.B) { - benchmarkSigning(b, jwt.SigningMethodHS512, hmacTestKey) -} diff --git a/vendor/github.com/dgrijalva/jwt-go/http_example_test.go b/vendor/github.com/dgrijalva/jwt-go/http_example_test.go deleted file mode 100644 index 82e9c50a4..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/http_example_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package jwt_test - -// Example HTTP auth using asymmetric crypto/RSA keys -// This is based on a (now outdated) example at https://gist.github.com/cryptix/45c33ecf0ae54828e63b - -import ( - "bytes" - "crypto/rsa" - "fmt" - "github.com/dgrijalva/jwt-go" - "github.com/dgrijalva/jwt-go/request" - "io" - "io/ioutil" - "log" - "net" - "net/http" - "net/url" - "strings" - "time" -) - -// location of the files used for signing and verification -const ( - privKeyPath = "test/sample_key" // openssl genrsa -out app.rsa keysize - pubKeyPath = "test/sample_key.pub" // openssl rsa -in app.rsa -pubout > app.rsa.pub -) - -var ( - verifyKey *rsa.PublicKey - signKey *rsa.PrivateKey - serverPort int - // storing sample username/password pairs - // don't do this on a real server - users = map[string]string{ - "test": "known", - } -) - -// read the key files before starting http handlers -func init() { - signBytes, err := ioutil.ReadFile(privKeyPath) - fatal(err) - - signKey, err = jwt.ParseRSAPrivateKeyFromPEM(signBytes) - fatal(err) - - verifyBytes, err := ioutil.ReadFile(pubKeyPath) - fatal(err) - - verifyKey, err = jwt.ParseRSAPublicKeyFromPEM(verifyBytes) - fatal(err) - - http.HandleFunc("/authenticate", authHandler) - http.HandleFunc("/restricted", restrictedHandler) - - // Setup listener - listener, err := net.ListenTCP("tcp", &net.TCPAddr{}) - serverPort = listener.Addr().(*net.TCPAddr).Port - - log.Println("Listening...") - go func() { - fatal(http.Serve(listener, nil)) - }() -} - -var start func() - -func fatal(err error) { - if err != nil { - log.Fatal(err) - } -} - -// Define some custom types were going to use within our tokens -type CustomerInfo struct { - Name string - Kind string -} - -type CustomClaimsExample struct { - *jwt.StandardClaims - TokenType string - CustomerInfo -} - -func Example_getTokenViaHTTP() { - // See func authHandler for an example auth handler that produces a token - res, err := http.PostForm(fmt.Sprintf("http://localhost:%v/authenticate", serverPort), url.Values{ - "user": {"test"}, - "pass": {"known"}, - }) - if err != nil { - fatal(err) - } - - if res.StatusCode != 200 { - fmt.Println("Unexpected status code", res.StatusCode) - } - - // Read the token out of the response body - buf := new(bytes.Buffer) - io.Copy(buf, res.Body) - res.Body.Close() - tokenString := strings.TrimSpace(buf.String()) - - // Parse the token - token, err := jwt.ParseWithClaims(tokenString, &CustomClaimsExample{}, func(token *jwt.Token) (interface{}, error) { - // since we only use the one private key to sign the tokens, - // we also only use its public counter part to verify - return verifyKey, nil - }) - fatal(err) - - claims := token.Claims.(*CustomClaimsExample) - fmt.Println(claims.CustomerInfo.Name) - - //Output: test -} - -func Example_useTokenViaHTTP() { - - // Make a sample token - // In a real world situation, this token will have been acquired from - // some other API call (see Example_getTokenViaHTTP) - token, err := createToken("foo") - fatal(err) - - // Make request. See func restrictedHandler for example request processor - req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost:%v/restricted", serverPort), nil) - fatal(err) - req.Header.Set("Authorization", fmt.Sprintf("Bearer %v", token)) - res, err := http.DefaultClient.Do(req) - fatal(err) - - // Read the response body - buf := new(bytes.Buffer) - io.Copy(buf, res.Body) - res.Body.Close() - fmt.Println(buf.String()) - - // Output: Welcome, foo -} - -func createToken(user string) (string, error) { - // create a signer for rsa 256 - t := jwt.New(jwt.GetSigningMethod("RS256")) - - // set our claims - t.Claims = &CustomClaimsExample{ - &jwt.StandardClaims{ - // set the expire time - // see http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-20#section-4.1.4 - ExpiresAt: time.Now().Add(time.Minute * 1).Unix(), - }, - "level1", - CustomerInfo{user, "human"}, - } - - // Creat token string - return t.SignedString(signKey) -} - -// reads the form values, checks them and creates the token -func authHandler(w http.ResponseWriter, r *http.Request) { - // make sure its post - if r.Method != "POST" { - w.WriteHeader(http.StatusBadRequest) - fmt.Fprintln(w, "No POST", r.Method) - return - } - - user := r.FormValue("user") - pass := r.FormValue("pass") - - log.Printf("Authenticate: user[%s] pass[%s]\n", user, pass) - - // check values - if user != "test" || pass != "known" { - w.WriteHeader(http.StatusForbidden) - fmt.Fprintln(w, "Wrong info") - return - } - - tokenString, err := createToken(user) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintln(w, "Sorry, error while Signing Token!") - log.Printf("Token Signing error: %v\n", err) - return - } - - w.Header().Set("Content-Type", "application/jwt") - w.WriteHeader(http.StatusOK) - fmt.Fprintln(w, tokenString) -} - -// only accessible with a valid token -func restrictedHandler(w http.ResponseWriter, r *http.Request) { - // Get token from request - token, err := request.ParseFromRequestWithClaims(r, request.OAuth2Extractor, &CustomClaimsExample{}, func(token *jwt.Token) (interface{}, error) { - // since we only use the one private key to sign the tokens, - // we also only use its public counter part to verify - return verifyKey, nil - }) - - // If the token is missing or invalid, return error - if err != nil { - w.WriteHeader(http.StatusUnauthorized) - fmt.Fprintln(w, "Invalid token:", err) - return - } - - // Token is valid - fmt.Fprintln(w, "Welcome,", token.Claims.(*CustomClaimsExample).Name) - return -} diff --git a/vendor/github.com/dgrijalva/jwt-go/map_claims.go b/vendor/github.com/dgrijalva/jwt-go/map_claims.go deleted file mode 100644 index 291213c46..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/map_claims.go +++ /dev/null @@ -1,94 +0,0 @@ -package jwt - -import ( - "encoding/json" - "errors" - // "fmt" -) - -// Claims type that uses the map[string]interface{} for JSON decoding -// This is the default claims type if you don't supply one -type MapClaims map[string]interface{} - -// Compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyAudience(cmp string, req bool) bool { - aud, _ := m["aud"].(string) - return verifyAud(aud, cmp, req) -} - -// Compares the exp claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { - switch exp := m["exp"].(type) { - case float64: - return verifyExp(int64(exp), cmp, req) - case json.Number: - v, _ := exp.Int64() - return verifyExp(v, cmp, req) - } - return req == false -} - -// Compares the iat claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { - switch iat := m["iat"].(type) { - case float64: - return verifyIat(int64(iat), cmp, req) - case json.Number: - v, _ := iat.Int64() - return verifyIat(v, cmp, req) - } - return req == false -} - -// Compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { - iss, _ := m["iss"].(string) - return verifyIss(iss, cmp, req) -} - -// Compares the nbf claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { - switch nbf := m["nbf"].(type) { - case float64: - return verifyNbf(int64(nbf), cmp, req) - case json.Number: - v, _ := nbf.Int64() - return verifyNbf(v, cmp, req) - } - return req == false -} - -// Validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (m MapClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - if m.VerifyExpiresAt(now, false) == false { - vErr.Inner = errors.New("Token is expired") - vErr.Errors |= ValidationErrorExpired - } - - if m.VerifyIssuedAt(now, false) == false { - vErr.Inner = errors.New("Token used before issued") - vErr.Errors |= ValidationErrorIssuedAt - } - - if m.VerifyNotBefore(now, false) == false { - vErr.Inner = errors.New("Token is not valid yet") - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} diff --git a/vendor/github.com/dgrijalva/jwt-go/none.go b/vendor/github.com/dgrijalva/jwt-go/none.go deleted file mode 100644 index f04d189d0..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/none.go +++ /dev/null @@ -1,52 +0,0 @@ -package jwt - -// Implements the none signing method. This is required by the spec -// but you probably should never use it. -var SigningMethodNone *signingMethodNone - -const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed" - -var NoneSignatureTypeDisallowedError error - -type signingMethodNone struct{} -type unsafeNoneMagicConstant string - -func init() { - SigningMethodNone = &signingMethodNone{} - NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) - - RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { - return SigningMethodNone - }) -} - -func (m *signingMethodNone) Alg() string { - return "none" -} - -// Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) { - // Key must be UnsafeAllowNoneSignatureType to prevent accidentally - // accepting 'none' signing method - if _, ok := key.(unsafeNoneMagicConstant); !ok { - return NoneSignatureTypeDisallowedError - } - // If signing method is none, signature must be an empty string - if signature != "" { - return NewValidationError( - "'none' signing method with non-empty signature", - ValidationErrorSignatureInvalid, - ) - } - - // Accept 'none' signing method. - return nil -} - -// Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) { - if _, ok := key.(unsafeNoneMagicConstant); ok { - return "", nil - } - return "", NoneSignatureTypeDisallowedError -} diff --git a/vendor/github.com/dgrijalva/jwt-go/none_test.go b/vendor/github.com/dgrijalva/jwt-go/none_test.go deleted file mode 100644 index 29a69efef..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/none_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package jwt_test - -import ( - "github.com/dgrijalva/jwt-go" - "strings" - "testing" -) - -var noneTestData = []struct { - name string - tokenString string - alg string - key interface{} - claims map[string]interface{} - valid bool -}{ - { - "Basic", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.", - "none", - jwt.UnsafeAllowNoneSignatureType, - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic - no key", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.", - "none", - nil, - map[string]interface{}{"foo": "bar"}, - false, - }, - { - "Signed", - "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.W-jEzRfBigtCWsinvVVuldiuilzVdU5ty0MvpLaSaqK9PlAWWlDQ1VIQ_qSKzwL5IXaZkvZFJXT3yL3n7OUVu7zCNJzdwznbC8Z-b0z2lYvcklJYi2VOFRcGbJtXUqgjk2oGsiqUMUMOLP70TTefkpsgqDxbRh9CDUfpOJgW-dU7cmgaoswe3wjUAUi6B6G2YEaiuXC0XScQYSYVKIzgKXJV8Zw-7AN_DBUI4GkTpsvQ9fVVjZM9csQiEXhYekyrKu1nu_POpQonGd8yqkIyXPECNmmqH5jH4sFiF67XhD7_JpkvLziBpI-uh86evBUadmHhb9Otqw3uV3NTaXLzJw", - "none", - jwt.UnsafeAllowNoneSignatureType, - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestNoneVerify(t *testing.T) { - for _, data := range noneTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], data.key) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestNoneSign(t *testing.T) { - for _, data := range noneTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), data.key) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2]) - } - } - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/parser.go b/vendor/github.com/dgrijalva/jwt-go/parser.go deleted file mode 100644 index 7bf1c4ea0..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/parser.go +++ /dev/null @@ -1,131 +0,0 @@ -package jwt - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" -) - -type Parser struct { - ValidMethods []string // If populated, only these methods will be considered valid - UseJSONNumber bool // Use JSON Number format in JSON decoder - SkipClaimsValidation bool // Skip claims validation during token parsing -} - -// Parse, validate, and return a token. -// keyFunc will receive the parsed token and should return the key for validating. -// If everything is kosher, err will be nil -func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { - return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) -} - -func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { - parts := strings.Split(tokenString, ".") - if len(parts) != 3 { - return nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) - } - - var err error - token := &Token{Raw: tokenString} - - // parse Header - var headerBytes []byte - if headerBytes, err = DecodeSegment(parts[0]); err != nil { - if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { - return token, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) - } - return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - if err = json.Unmarshal(headerBytes, &token.Header); err != nil { - return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // parse Claims - var claimBytes []byte - token.Claims = claims - - if claimBytes, err = DecodeSegment(parts[1]); err != nil { - return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) - if p.UseJSONNumber { - dec.UseNumber() - } - // JSON Decode. Special case for map type to avoid weird pointer behavior - if c, ok := token.Claims.(MapClaims); ok { - err = dec.Decode(&c) - } else { - err = dec.Decode(&claims) - } - // Handle decode error - if err != nil { - return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // Lookup signature method - if method, ok := token.Header["alg"].(string); ok { - if token.Method = GetSigningMethod(method); token.Method == nil { - return token, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) - } - } else { - return token, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) - } - - // Verify signing method is in the required set - if p.ValidMethods != nil { - var signingMethodValid = false - var alg = token.Method.Alg() - for _, m := range p.ValidMethods { - if m == alg { - signingMethodValid = true - break - } - } - if !signingMethodValid { - // signing method is not in the listed set - return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) - } - } - - // Lookup key - var key interface{} - if keyFunc == nil { - // keyFunc was not provided. short circuiting validation - return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) - } - if key, err = keyFunc(token); err != nil { - // keyFunc returned an error - return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} - } - - vErr := &ValidationError{} - - // Validate Claims - if !p.SkipClaimsValidation { - if err := token.Claims.Valid(); err != nil { - - // If the Claims Valid returned an error, check if it is a validation error, - // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set - if e, ok := err.(*ValidationError); !ok { - vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} - } else { - vErr = e - } - } - } - - // Perform validation - token.Signature = parts[2] - if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { - vErr.Inner = err - vErr.Errors |= ValidationErrorSignatureInvalid - } - - if vErr.valid() { - token.Valid = true - return token, nil - } - - return token, vErr -} diff --git a/vendor/github.com/dgrijalva/jwt-go/parser_test.go b/vendor/github.com/dgrijalva/jwt-go/parser_test.go deleted file mode 100644 index f8ad6f908..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/parser_test.go +++ /dev/null @@ -1,261 +0,0 @@ -package jwt_test - -import ( - "crypto/rsa" - "encoding/json" - "fmt" - "reflect" - "testing" - "time" - - "github.com/dgrijalva/jwt-go" - "github.com/dgrijalva/jwt-go/test" -) - -var keyFuncError error = fmt.Errorf("error loading key") - -var ( - jwtTestDefaultKey *rsa.PublicKey - defaultKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return jwtTestDefaultKey, nil } - emptyKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, nil } - errorKeyFunc jwt.Keyfunc = func(t *jwt.Token) (interface{}, error) { return nil, keyFuncError } - nilKeyFunc jwt.Keyfunc = nil -) - -func init() { - jwtTestDefaultKey = test.LoadRSAPublicKeyFromDisk("test/sample_key.pub") -} - -var jwtTestData = []struct { - name string - tokenString string - keyfunc jwt.Keyfunc - claims jwt.Claims - valid bool - errors uint32 - parser *jwt.Parser -}{ - { - "basic", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - true, - 0, - nil, - }, - { - "basic expired", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "exp": float64(time.Now().Unix() - 100)}, - false, - jwt.ValidationErrorExpired, - nil, - }, - { - "basic nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": float64(time.Now().Unix() + 100)}, - false, - jwt.ValidationErrorNotValidYet, - nil, - }, - { - "expired and nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": float64(time.Now().Unix() + 100), "exp": float64(time.Now().Unix() - 100)}, - false, - jwt.ValidationErrorNotValidYet | jwt.ValidationErrorExpired, - nil, - }, - { - "basic invalid", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorSignatureInvalid, - nil, - }, - { - "basic nokeyfunc", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - nilKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorUnverifiable, - nil, - }, - { - "basic nokey", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - emptyKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorSignatureInvalid, - nil, - }, - { - "basic errorkey", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - errorKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorUnverifiable, - nil, - }, - { - "invalid signing method", - "", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - false, - jwt.ValidationErrorSignatureInvalid, - &jwt.Parser{ValidMethods: []string{"HS256"}}, - }, - { - "valid signing method", - "", - defaultKeyFunc, - jwt.MapClaims{"foo": "bar"}, - true, - 0, - &jwt.Parser{ValidMethods: []string{"RS256", "HS256"}}, - }, - { - "JSON Number", - "", - defaultKeyFunc, - jwt.MapClaims{"foo": json.Number("123.4")}, - true, - 0, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "Standard Claims", - "", - defaultKeyFunc, - &jwt.StandardClaims{ - ExpiresAt: time.Now().Add(time.Second * 10).Unix(), - }, - true, - 0, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "JSON Number - basic expired", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "exp": json.Number(fmt.Sprintf("%v", time.Now().Unix()-100))}, - false, - jwt.ValidationErrorExpired, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "JSON Number - basic nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": json.Number(fmt.Sprintf("%v", time.Now().Unix()+100))}, - false, - jwt.ValidationErrorNotValidYet, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "JSON Number - expired and nbf", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": json.Number(fmt.Sprintf("%v", time.Now().Unix()+100)), "exp": json.Number(fmt.Sprintf("%v", time.Now().Unix()-100))}, - false, - jwt.ValidationErrorNotValidYet | jwt.ValidationErrorExpired, - &jwt.Parser{UseJSONNumber: true}, - }, - { - "SkipClaimsValidation during token parsing", - "", // autogen - defaultKeyFunc, - jwt.MapClaims{"foo": "bar", "nbf": json.Number(fmt.Sprintf("%v", time.Now().Unix()+100))}, - true, - 0, - &jwt.Parser{UseJSONNumber: true, SkipClaimsValidation: true}, - }, -} - -func TestParser_Parse(t *testing.T) { - privateKey := test.LoadRSAPrivateKeyFromDisk("test/sample_key") - - // Iterate over test data set and run tests - for _, data := range jwtTestData { - // If the token string is blank, use helper function to generate string - if data.tokenString == "" { - data.tokenString = test.MakeSampleToken(data.claims, privateKey) - } - - // Parse the token - var token *jwt.Token - var err error - var parser = data.parser - if parser == nil { - parser = new(jwt.Parser) - } - // Figure out correct claims type - switch data.claims.(type) { - case jwt.MapClaims: - token, err = parser.ParseWithClaims(data.tokenString, jwt.MapClaims{}, data.keyfunc) - case *jwt.StandardClaims: - token, err = parser.ParseWithClaims(data.tokenString, &jwt.StandardClaims{}, data.keyfunc) - } - - // Verify result matches expectation - if !reflect.DeepEqual(data.claims, token.Claims) { - t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims) - } - - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying token: %T:%v", data.name, err, err) - } - - if !data.valid && err == nil { - t.Errorf("[%v] Invalid token passed validation", data.name) - } - - if (err == nil && !token.Valid) || (err != nil && token.Valid) { - t.Errorf("[%v] Inconsistent behavior between returned error and token.Valid", data.name) - } - - if data.errors != 0 { - if err == nil { - t.Errorf("[%v] Expecting error. Didn't get one.", data.name) - } else { - - ve := err.(*jwt.ValidationError) - // compare the bitfield part of the error - if e := ve.Errors; e != data.errors { - t.Errorf("[%v] Errors don't match expectation. %v != %v", data.name, e, data.errors) - } - - if err.Error() == keyFuncError.Error() && ve.Inner != keyFuncError { - t.Errorf("[%v] Inner error does not match expectation. %v != %v", data.name, ve.Inner, keyFuncError) - } - } - } - if data.valid && token.Signature == "" { - t.Errorf("[%v] Signature is left unpopulated after parsing", data.name) - } - } -} - -// Helper method for benchmarking various methods -func benchmarkSigning(b *testing.B, method jwt.SigningMethod, key interface{}) { - t := jwt.New(method) - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if _, err := t.SignedString(key); err != nil { - b.Fatal(err) - } - } - }) - -} diff --git a/vendor/github.com/dgrijalva/jwt-go/request/doc.go b/vendor/github.com/dgrijalva/jwt-go/request/doc.go deleted file mode 100644 index c01069c98..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/request/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Utility package for extracting JWT tokens from -// HTTP requests. -// -// The main function is ParseFromRequest and it's WithClaims variant. -// See examples for how to use the various Extractor implementations -// or roll your own. -package request diff --git a/vendor/github.com/dgrijalva/jwt-go/request/extractor.go b/vendor/github.com/dgrijalva/jwt-go/request/extractor.go deleted file mode 100644 index 14414fe2f..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/request/extractor.go +++ /dev/null @@ -1,81 +0,0 @@ -package request - -import ( - "errors" - "net/http" -) - -// Errors -var ( - ErrNoTokenInRequest = errors.New("no token present in request") -) - -// Interface for extracting a token from an HTTP request. -// The ExtractToken method should return a token string or an error. -// If no token is present, you must return ErrNoTokenInRequest. -type Extractor interface { - ExtractToken(*http.Request) (string, error) -} - -// Extractor for finding a token in a header. Looks at each specified -// header in order until there's a match -type HeaderExtractor []string - -func (e HeaderExtractor) ExtractToken(req *http.Request) (string, error) { - // loop over header names and return the first one that contains data - for _, header := range e { - if ah := req.Header.Get(header); ah != "" { - return ah, nil - } - } - return "", ErrNoTokenInRequest -} - -// Extract token from request arguments. This includes a POSTed form or -// GET URL arguments. Argument names are tried in order until there's a match. -// This extractor calls `ParseMultipartForm` on the request -type ArgumentExtractor []string - -func (e ArgumentExtractor) ExtractToken(req *http.Request) (string, error) { - // Make sure form is parsed - req.ParseMultipartForm(10e6) - - // loop over arg names and return the first one that contains data - for _, arg := range e { - if ah := req.Form.Get(arg); ah != "" { - return ah, nil - } - } - - return "", ErrNoTokenInRequest -} - -// Tries Extractors in order until one returns a token string or an error occurs -type MultiExtractor []Extractor - -func (e MultiExtractor) ExtractToken(req *http.Request) (string, error) { - // loop over header names and return the first one that contains data - for _, extractor := range e { - if tok, err := extractor.ExtractToken(req); tok != "" { - return tok, nil - } else if err != ErrNoTokenInRequest { - return "", err - } - } - return "", ErrNoTokenInRequest -} - -// Wrap an Extractor in this to post-process the value before it's handed off. -// See AuthorizationHeaderExtractor for an example -type PostExtractionFilter struct { - Extractor - Filter func(string) (string, error) -} - -func (e *PostExtractionFilter) ExtractToken(req *http.Request) (string, error) { - if tok, err := e.Extractor.ExtractToken(req); tok != "" { - return e.Filter(tok) - } else { - return "", err - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/request/extractor_example_test.go b/vendor/github.com/dgrijalva/jwt-go/request/extractor_example_test.go deleted file mode 100644 index a994ffe58..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/request/extractor_example_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package request - -import ( - "fmt" - "net/url" -) - -const ( - exampleTokenA = "A" -) - -func ExampleHeaderExtractor() { - req := makeExampleRequest("GET", "/", map[string]string{"Token": exampleTokenA}, nil) - tokenString, err := HeaderExtractor{"Token"}.ExtractToken(req) - if err == nil { - fmt.Println(tokenString) - } else { - fmt.Println(err) - } - //Output: A -} - -func ExampleArgumentExtractor() { - req := makeExampleRequest("GET", "/", nil, url.Values{"token": {extractorTestTokenA}}) - tokenString, err := ArgumentExtractor{"token"}.ExtractToken(req) - if err == nil { - fmt.Println(tokenString) - } else { - fmt.Println(err) - } - //Output: A -} diff --git a/vendor/github.com/dgrijalva/jwt-go/request/extractor_test.go b/vendor/github.com/dgrijalva/jwt-go/request/extractor_test.go deleted file mode 100644 index e3bbb0a3e..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/request/extractor_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package request - -import ( - "fmt" - "net/http" - "net/url" - "testing" -) - -var extractorTestTokenA = "A" -var extractorTestTokenB = "B" - -var extractorTestData = []struct { - name string - extractor Extractor - headers map[string]string - query url.Values - token string - err error -}{ - { - name: "simple header", - extractor: HeaderExtractor{"Foo"}, - headers: map[string]string{"Foo": extractorTestTokenA}, - query: nil, - token: extractorTestTokenA, - err: nil, - }, - { - name: "simple argument", - extractor: ArgumentExtractor{"token"}, - headers: map[string]string{}, - query: url.Values{"token": {extractorTestTokenA}}, - token: extractorTestTokenA, - err: nil, - }, - { - name: "multiple extractors", - extractor: MultiExtractor{ - HeaderExtractor{"Foo"}, - ArgumentExtractor{"token"}, - }, - headers: map[string]string{"Foo": extractorTestTokenA}, - query: url.Values{"token": {extractorTestTokenB}}, - token: extractorTestTokenA, - err: nil, - }, - { - name: "simple miss", - extractor: HeaderExtractor{"This-Header-Is-Not-Set"}, - headers: map[string]string{"Foo": extractorTestTokenA}, - query: nil, - token: "", - err: ErrNoTokenInRequest, - }, - { - name: "filter", - extractor: AuthorizationHeaderExtractor, - headers: map[string]string{"Authorization": "Bearer " + extractorTestTokenA}, - query: nil, - token: extractorTestTokenA, - err: nil, - }, -} - -func TestExtractor(t *testing.T) { - // Bearer token request - for _, data := range extractorTestData { - // Make request from test struct - r := makeExampleRequest("GET", "/", data.headers, data.query) - - // Test extractor - token, err := data.extractor.ExtractToken(r) - if token != data.token { - t.Errorf("[%v] Expected token '%v'. Got '%v'", data.name, data.token, token) - continue - } - if err != data.err { - t.Errorf("[%v] Expected error '%v'. Got '%v'", data.name, data.err, err) - continue - } - } -} - -func makeExampleRequest(method, path string, headers map[string]string, urlArgs url.Values) *http.Request { - r, _ := http.NewRequest(method, fmt.Sprintf("%v?%v", path, urlArgs.Encode()), nil) - for k, v := range headers { - r.Header.Set(k, v) - } - return r -} diff --git a/vendor/github.com/dgrijalva/jwt-go/request/oauth2.go b/vendor/github.com/dgrijalva/jwt-go/request/oauth2.go deleted file mode 100644 index 5948694a5..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/request/oauth2.go +++ /dev/null @@ -1,28 +0,0 @@ -package request - -import ( - "strings" -) - -// Strips 'Bearer ' prefix from bearer token string -func stripBearerPrefixFromTokenString(tok string) (string, error) { - // Should be a bearer token - if len(tok) > 6 && strings.ToUpper(tok[0:7]) == "BEARER " { - return tok[7:], nil - } - return tok, nil -} - -// Extract bearer token from Authorization header -// Uses PostExtractionFilter to strip "Bearer " prefix from header -var AuthorizationHeaderExtractor = &PostExtractionFilter{ - HeaderExtractor{"Authorization"}, - stripBearerPrefixFromTokenString, -} - -// Extractor for OAuth2 access tokens. Looks in 'Authorization' -// header then 'access_token' argument for a token. -var OAuth2Extractor = &MultiExtractor{ - AuthorizationHeaderExtractor, - ArgumentExtractor{"access_token"}, -} diff --git a/vendor/github.com/dgrijalva/jwt-go/request/request.go b/vendor/github.com/dgrijalva/jwt-go/request/request.go deleted file mode 100644 index 1807b3965..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/request/request.go +++ /dev/null @@ -1,24 +0,0 @@ -package request - -import ( - "github.com/dgrijalva/jwt-go" - "net/http" -) - -// Extract and parse a JWT token from an HTTP request. -// This behaves the same as Parse, but accepts a request and an extractor -// instead of a token string. The Extractor interface allows you to define -// the logic for extracting a token. Several useful implementations are provided. -func ParseFromRequest(req *http.Request, extractor Extractor, keyFunc jwt.Keyfunc) (token *jwt.Token, err error) { - return ParseFromRequestWithClaims(req, extractor, jwt.MapClaims{}, keyFunc) -} - -// ParseFromRequest but with custom Claims type -func ParseFromRequestWithClaims(req *http.Request, extractor Extractor, claims jwt.Claims, keyFunc jwt.Keyfunc) (token *jwt.Token, err error) { - // Extract token from request - if tokStr, err := extractor.ExtractToken(req); err == nil { - return jwt.ParseWithClaims(tokStr, claims, keyFunc) - } else { - return nil, err - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/request/request_test.go b/vendor/github.com/dgrijalva/jwt-go/request/request_test.go deleted file mode 100644 index b4365cd86..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/request/request_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package request - -import ( - "fmt" - "github.com/dgrijalva/jwt-go" - "github.com/dgrijalva/jwt-go/test" - "net/http" - "net/url" - "reflect" - "strings" - "testing" -) - -var requestTestData = []struct { - name string - claims jwt.MapClaims - extractor Extractor - headers map[string]string - query url.Values - valid bool -}{ - { - "authorization bearer token", - jwt.MapClaims{"foo": "bar"}, - AuthorizationHeaderExtractor, - map[string]string{"Authorization": "Bearer %v"}, - url.Values{}, - true, - }, - { - "oauth bearer token - header", - jwt.MapClaims{"foo": "bar"}, - OAuth2Extractor, - map[string]string{"Authorization": "Bearer %v"}, - url.Values{}, - true, - }, - { - "oauth bearer token - url", - jwt.MapClaims{"foo": "bar"}, - OAuth2Extractor, - map[string]string{}, - url.Values{"access_token": {"%v"}}, - true, - }, - { - "url token", - jwt.MapClaims{"foo": "bar"}, - ArgumentExtractor{"token"}, - map[string]string{}, - url.Values{"token": {"%v"}}, - true, - }, -} - -func TestParseRequest(t *testing.T) { - // load keys from disk - privateKey := test.LoadRSAPrivateKeyFromDisk("../test/sample_key") - publicKey := test.LoadRSAPublicKeyFromDisk("../test/sample_key.pub") - keyfunc := func(*jwt.Token) (interface{}, error) { - return publicKey, nil - } - - // Bearer token request - for _, data := range requestTestData { - // Make token from claims - tokenString := test.MakeSampleToken(data.claims, privateKey) - - // Make query string - for k, vv := range data.query { - for i, v := range vv { - if strings.Contains(v, "%v") { - data.query[k][i] = fmt.Sprintf(v, tokenString) - } - } - } - - // Make request from test struct - r, _ := http.NewRequest("GET", fmt.Sprintf("/?%v", data.query.Encode()), nil) - for k, v := range data.headers { - if strings.Contains(v, "%v") { - r.Header.Set(k, fmt.Sprintf(v, tokenString)) - } else { - r.Header.Set(k, tokenString) - } - } - token, err := ParseFromRequestWithClaims(r, data.extractor, jwt.MapClaims{}, keyfunc) - - if token == nil { - t.Errorf("[%v] Token was not found: %v", data.name, err) - continue - } - if !reflect.DeepEqual(data.claims, token.Claims) { - t.Errorf("[%v] Claims mismatch. Expecting: %v Got: %v", data.name, data.claims, token.Claims) - } - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying token: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid token passed validation", data.name) - } - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa.go b/vendor/github.com/dgrijalva/jwt-go/rsa.go deleted file mode 100644 index 0ae0b1984..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/rsa.go +++ /dev/null @@ -1,100 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" -) - -// Implements the RSA family of signing methods signing methods -type SigningMethodRSA struct { - Name string - Hash crypto.Hash -} - -// Specific instances for RS256 and company -var ( - SigningMethodRS256 *SigningMethodRSA - SigningMethodRS384 *SigningMethodRSA - SigningMethodRS512 *SigningMethodRSA -) - -func init() { - // RS256 - SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256} - RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod { - return SigningMethodRS256 - }) - - // RS384 - SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384} - RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod { - return SigningMethodRS384 - }) - - // RS512 - SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512} - RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod { - return SigningMethodRS512 - }) -} - -func (m *SigningMethodRSA) Alg() string { - return m.Name -} - -// Implements the Verify method from SigningMethod -// For this signing method, must be an rsa.PublicKey structure. -func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - var rsaKey *rsa.PublicKey - var ok bool - - if rsaKey, ok = key.(*rsa.PublicKey); !ok { - return ErrInvalidKeyType - } - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Verify the signature - return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig) -} - -// Implements the Sign method from SigningMethod -// For this signing method, must be an rsa.PrivateKey structure. -func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { - var rsaKey *rsa.PrivateKey - var ok bool - - // Validate type of key - if rsaKey, ok = key.(*rsa.PrivateKey); !ok { - return "", ErrInvalidKey - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return the encoded bytes - if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { - return EncodeSegment(sigBytes), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_pss.go b/vendor/github.com/dgrijalva/jwt-go/rsa_pss.go deleted file mode 100644 index 10ee9db8a..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/rsa_pss.go +++ /dev/null @@ -1,126 +0,0 @@ -// +build go1.4 - -package jwt - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" -) - -// Implements the RSAPSS family of signing methods signing methods -type SigningMethodRSAPSS struct { - *SigningMethodRSA - Options *rsa.PSSOptions -} - -// Specific instances for RS/PS and company -var ( - SigningMethodPS256 *SigningMethodRSAPSS - SigningMethodPS384 *SigningMethodRSAPSS - SigningMethodPS512 *SigningMethodRSAPSS -) - -func init() { - // PS256 - SigningMethodPS256 = &SigningMethodRSAPSS{ - &SigningMethodRSA{ - Name: "PS256", - Hash: crypto.SHA256, - }, - &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - Hash: crypto.SHA256, - }, - } - RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { - return SigningMethodPS256 - }) - - // PS384 - SigningMethodPS384 = &SigningMethodRSAPSS{ - &SigningMethodRSA{ - Name: "PS384", - Hash: crypto.SHA384, - }, - &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - Hash: crypto.SHA384, - }, - } - RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { - return SigningMethodPS384 - }) - - // PS512 - SigningMethodPS512 = &SigningMethodRSAPSS{ - &SigningMethodRSA{ - Name: "PS512", - Hash: crypto.SHA512, - }, - &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - Hash: crypto.SHA512, - }, - } - RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { - return SigningMethodPS512 - }) -} - -// Implements the Verify method from SigningMethod -// For this verify method, key must be an rsa.PublicKey struct -func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - var rsaKey *rsa.PublicKey - switch k := key.(type) { - case *rsa.PublicKey: - rsaKey = k - default: - return ErrInvalidKey - } - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options) -} - -// Implements the Sign method from SigningMethod -// For this signing method, key must be an rsa.PrivateKey struct -func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { - var rsaKey *rsa.PrivateKey - - switch k := key.(type) { - case *rsa.PrivateKey: - rsaKey = k - default: - return "", ErrInvalidKeyType - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return the encoded bytes - if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { - return EncodeSegment(sigBytes), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go b/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go deleted file mode 100644 index 9045aaf34..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/rsa_pss_test.go +++ /dev/null @@ -1,96 +0,0 @@ -// +build go1.4 - -package jwt_test - -import ( - "crypto/rsa" - "io/ioutil" - "strings" - "testing" - - "github.com/dgrijalva/jwt-go" -) - -var rsaPSSTestData = []struct { - name string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "Basic PS256", - "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9w", - "PS256", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic PS384", - "eyJhbGciOiJQUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.w7-qqgj97gK4fJsq_DCqdYQiylJjzWONvD0qWWWhqEOFk2P1eDULPnqHRnjgTXoO4HAw4YIWCsZPet7nR3Xxq4ZhMqvKW8b7KlfRTb9cH8zqFvzMmybQ4jv2hKc3bXYqVow3AoR7hN_CWXI3Dv6Kd2X5xhtxRHI6IL39oTVDUQ74LACe-9t4c3QRPuj6Pq1H4FAT2E2kW_0KOc6EQhCLWEhm2Z2__OZskDC8AiPpP8Kv4k2vB7l0IKQu8Pr4RcNBlqJdq8dA5D3hk5TLxP8V5nG1Ib80MOMMqoS3FQvSLyolFX-R_jZ3-zfq6Ebsqr0yEb0AH2CfsECF7935Pa0FKQ", - "PS384", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic PS512", - "eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.GX1HWGzFaJevuSLavqqFYaW8_TpvcjQ8KfC5fXiSDzSiT9UD9nB_ikSmDNyDILNdtjZLSvVKfXxZJqCfefxAtiozEDDdJthZ-F0uO4SPFHlGiXszvKeodh7BuTWRI2wL9-ZO4mFa8nq3GMeQAfo9cx11i7nfN8n2YNQ9SHGovG7_T_AvaMZB_jT6jkDHpwGR9mz7x1sycckEo6teLdHRnH_ZdlHlxqknmyTu8Odr5Xh0sJFOL8BepWbbvIIn-P161rRHHiDWFv6nhlHwZnVzjx7HQrWSGb6-s2cdLie9QL_8XaMcUpjLkfOMKkDOfHo6AvpL7Jbwi83Z2ZTHjJWB-A", - "PS512", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "basic PS256 invalid: foo => bar", - "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.PPG4xyDVY8ffp4CcxofNmsTDXsrVG2npdQuibLhJbv4ClyPTUtR5giNSvuxo03kB6I8VXVr0Y9X7UxhJVEoJOmULAwRWaUsDnIewQa101cVhMa6iR8X37kfFoiZ6NkS-c7henVkkQWu2HtotkEtQvN5hFlk8IevXXPmvZlhQhwzB1sGzGYnoi1zOfuL98d3BIjUjtlwii5w6gYG2AEEzp7HnHCsb3jIwUPdq86Oe6hIFjtBwduIK90ca4UqzARpcfwxHwVLMpatKask00AgGVI0ysdk0BLMjmLutquD03XbThHScC2C2_Pp4cHWgMzvbgLU2RYYZcZRKr46QeNgz9W", - "PS256", - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestRSAPSSVerify(t *testing.T) { - var err error - - key, _ := ioutil.ReadFile("test/sample_key.pub") - var rsaPSSKey *rsa.PublicKey - if rsaPSSKey, err = jwt.ParseRSAPublicKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse RSA public key: %v", err) - } - - for _, data := range rsaPSSTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], rsaPSSKey) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestRSAPSSSign(t *testing.T) { - var err error - - key, _ := ioutil.ReadFile("test/sample_key") - var rsaPSSKey *rsa.PrivateKey - if rsaPSSKey, err = jwt.ParseRSAPrivateKeyFromPEM(key); err != nil { - t.Errorf("Unable to parse RSA private key: %v", err) - } - - for _, data := range rsaPSSTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), rsaPSSKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig == parts[2] { - t.Errorf("[%v] Signatures shouldn't match\nnew:\n%v\noriginal:\n%v", data.name, sig, parts[2]) - } - } - } -} diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_test.go b/vendor/github.com/dgrijalva/jwt-go/rsa_test.go deleted file mode 100644 index 2e0f78536..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/rsa_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package jwt_test - -import ( - "github.com/dgrijalva/jwt-go" - "io/ioutil" - "strings" - "testing" -) - -var rsaTestData = []struct { - name string - tokenString string - alg string - claims map[string]interface{} - valid bool -}{ - { - "Basic RS256", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.FhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - "RS256", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic RS384", - "eyJhbGciOiJSUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.W-jEzRfBigtCWsinvVVuldiuilzVdU5ty0MvpLaSaqK9PlAWWlDQ1VIQ_qSKzwL5IXaZkvZFJXT3yL3n7OUVu7zCNJzdwznbC8Z-b0z2lYvcklJYi2VOFRcGbJtXUqgjk2oGsiqUMUMOLP70TTefkpsgqDxbRh9CDUfpOJgW-dU7cmgaoswe3wjUAUi6B6G2YEaiuXC0XScQYSYVKIzgKXJV8Zw-7AN_DBUI4GkTpsvQ9fVVjZM9csQiEXhYekyrKu1nu_POpQonGd8yqkIyXPECNmmqH5jH4sFiF67XhD7_JpkvLziBpI-uh86evBUadmHhb9Otqw3uV3NTaXLzJw", - "RS384", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "Basic RS512", - "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.zBlLlmRrUxx4SJPUbV37Q1joRcI9EW13grnKduK3wtYKmDXbgDpF1cZ6B-2Jsm5RB8REmMiLpGms-EjXhgnyh2TSHE-9W2gA_jvshegLWtwRVDX40ODSkTb7OVuaWgiy9y7llvcknFBTIg-FnVPVpXMmeV_pvwQyhaz1SSwSPrDyxEmksz1hq7YONXhXPpGaNbMMeDTNP_1oj8DZaqTIL9TwV8_1wb2Odt_Fy58Ke2RVFijsOLdnyEAjt2n9Mxihu9i3PhNBkkxa2GbnXBfq3kzvZ_xxGGopLdHhJjcGWXO-NiwI9_tiu14NRv4L2xC0ItD9Yz68v2ZIZEp_DuzwRQ", - "RS512", - map[string]interface{}{"foo": "bar"}, - true, - }, - { - "basic invalid: foo => bar", - "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIifQ.EhkiHkoESI_cG3NPigFrxEk9Z60_oXrOT2vGm9Pn6RDgYNovYORQmmA0zs1AoAOf09ly2Nx2YAg6ABqAYga1AcMFkJljwxTT5fYphTuqpWdy4BELeSYJx5Ty2gmr8e7RonuUztrdD5WfPqLKMm1Ozp_T6zALpRmwTIW0QPnaBXaQD90FplAg46Iy1UlDKr-Eupy0i5SLch5Q-p2ZpaL_5fnTIUDlxC3pWhJTyx_71qDI-mAA_5lE_VdroOeflG56sSmDxopPEG3bFlSu1eowyBfxtu0_CuVd-M42RU75Zc4Gsj6uV77MBtbMrf4_7M_NUTSgoIF3fRqxrj0NzihIBg", - "RS256", - map[string]interface{}{"foo": "bar"}, - false, - }, -} - -func TestRSAVerify(t *testing.T) { - keyData, _ := ioutil.ReadFile("test/sample_key.pub") - key, _ := jwt.ParseRSAPublicKeyFromPEM(keyData) - - for _, data := range rsaTestData { - parts := strings.Split(data.tokenString, ".") - - method := jwt.GetSigningMethod(data.alg) - err := method.Verify(strings.Join(parts[0:2], "."), parts[2], key) - if data.valid && err != nil { - t.Errorf("[%v] Error while verifying key: %v", data.name, err) - } - if !data.valid && err == nil { - t.Errorf("[%v] Invalid key passed validation", data.name) - } - } -} - -func TestRSASign(t *testing.T) { - keyData, _ := ioutil.ReadFile("test/sample_key") - key, _ := jwt.ParseRSAPrivateKeyFromPEM(keyData) - - for _, data := range rsaTestData { - if data.valid { - parts := strings.Split(data.tokenString, ".") - method := jwt.GetSigningMethod(data.alg) - sig, err := method.Sign(strings.Join(parts[0:2], "."), key) - if err != nil { - t.Errorf("[%v] Error signing token: %v", data.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", data.name, sig, parts[2]) - } - } - } -} - -func TestRSAVerifyWithPreParsedPrivateKey(t *testing.T) { - key, _ := ioutil.ReadFile("test/sample_key.pub") - parsedKey, err := jwt.ParseRSAPublicKeyFromPEM(key) - if err != nil { - t.Fatal(err) - } - testData := rsaTestData[0] - parts := strings.Split(testData.tokenString, ".") - err = jwt.SigningMethodRS256.Verify(strings.Join(parts[0:2], "."), parts[2], parsedKey) - if err != nil { - t.Errorf("[%v] Error while verifying key: %v", testData.name, err) - } -} - -func TestRSAWithPreParsedPrivateKey(t *testing.T) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - t.Fatal(err) - } - testData := rsaTestData[0] - parts := strings.Split(testData.tokenString, ".") - sig, err := jwt.SigningMethodRS256.Sign(strings.Join(parts[0:2], "."), parsedKey) - if err != nil { - t.Errorf("[%v] Error signing token: %v", testData.name, err) - } - if sig != parts[2] { - t.Errorf("[%v] Incorrect signature.\nwas:\n%v\nexpecting:\n%v", testData.name, sig, parts[2]) - } -} - -func TestRSAKeyParsing(t *testing.T) { - key, _ := ioutil.ReadFile("test/sample_key") - pubKey, _ := ioutil.ReadFile("test/sample_key.pub") - badKey := []byte("All your base are belong to key") - - // Test parsePrivateKey - if _, e := jwt.ParseRSAPrivateKeyFromPEM(key); e != nil { - t.Errorf("Failed to parse valid private key: %v", e) - } - - if k, e := jwt.ParseRSAPrivateKeyFromPEM(pubKey); e == nil { - t.Errorf("Parsed public key as valid private key: %v", k) - } - - if k, e := jwt.ParseRSAPrivateKeyFromPEM(badKey); e == nil { - t.Errorf("Parsed invalid key as valid private key: %v", k) - } - - // Test parsePublicKey - if _, e := jwt.ParseRSAPublicKeyFromPEM(pubKey); e != nil { - t.Errorf("Failed to parse valid public key: %v", e) - } - - if k, e := jwt.ParseRSAPublicKeyFromPEM(key); e == nil { - t.Errorf("Parsed private key as valid public key: %v", k) - } - - if k, e := jwt.ParseRSAPublicKeyFromPEM(badKey); e == nil { - t.Errorf("Parsed invalid key as valid private key: %v", k) - } - -} - -func BenchmarkRS256Signing(b *testing.B) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - b.Fatal(err) - } - - benchmarkSigning(b, jwt.SigningMethodRS256, parsedKey) -} - -func BenchmarkRS384Signing(b *testing.B) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - b.Fatal(err) - } - - benchmarkSigning(b, jwt.SigningMethodRS384, parsedKey) -} - -func BenchmarkRS512Signing(b *testing.B) { - key, _ := ioutil.ReadFile("test/sample_key") - parsedKey, err := jwt.ParseRSAPrivateKeyFromPEM(key) - if err != nil { - b.Fatal(err) - } - - benchmarkSigning(b, jwt.SigningMethodRS512, parsedKey) -} diff --git a/vendor/github.com/dgrijalva/jwt-go/rsa_utils.go b/vendor/github.com/dgrijalva/jwt-go/rsa_utils.go deleted file mode 100644 index 213a90dbb..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/rsa_utils.go +++ /dev/null @@ -1,69 +0,0 @@ -package jwt - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key") - ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key") - ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key") -) - -// Parse PEM encoded PKCS1 or PKCS8 private key -func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - } - - var pkey *rsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, ErrNotRSAPrivateKey - } - - return pkey, nil -} - -// Parse PEM encoded PKCS1 or PKCS8 public key -func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - if cert, err := x509.ParseCertificate(block.Bytes); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - var pkey *rsa.PublicKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { - return nil, ErrNotRSAPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/dgrijalva/jwt-go/signing_method.go b/vendor/github.com/dgrijalva/jwt-go/signing_method.go deleted file mode 100644 index ed1f212b2..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/signing_method.go +++ /dev/null @@ -1,35 +0,0 @@ -package jwt - -import ( - "sync" -) - -var signingMethods = map[string]func() SigningMethod{} -var signingMethodLock = new(sync.RWMutex) - -// Implement SigningMethod to add new methods for signing or verifying tokens. -type SigningMethod interface { - Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid - Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error - Alg() string // returns the alg identifier for this method (example: 'HS256') -} - -// Register the "alg" name and a factory function for signing method. -// This is typically done during init() in the method's implementation -func RegisterSigningMethod(alg string, f func() SigningMethod) { - signingMethodLock.Lock() - defer signingMethodLock.Unlock() - - signingMethods[alg] = f -} - -// Get a signing method from an "alg" string -func GetSigningMethod(alg string) (method SigningMethod) { - signingMethodLock.RLock() - defer signingMethodLock.RUnlock() - - if methodF, ok := signingMethods[alg]; ok { - method = methodF() - } - return -} diff --git a/vendor/github.com/dgrijalva/jwt-go/test/helpers.go b/vendor/github.com/dgrijalva/jwt-go/test/helpers.go deleted file mode 100644 index f84c3ef63..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/test/helpers.go +++ /dev/null @@ -1,42 +0,0 @@ -package test - -import ( - "crypto/rsa" - "github.com/dgrijalva/jwt-go" - "io/ioutil" -) - -func LoadRSAPrivateKeyFromDisk(location string) *rsa.PrivateKey { - keyData, e := ioutil.ReadFile(location) - if e != nil { - panic(e.Error()) - } - key, e := jwt.ParseRSAPrivateKeyFromPEM(keyData) - if e != nil { - panic(e.Error()) - } - return key -} - -func LoadRSAPublicKeyFromDisk(location string) *rsa.PublicKey { - keyData, e := ioutil.ReadFile(location) - if e != nil { - panic(e.Error()) - } - key, e := jwt.ParseRSAPublicKeyFromPEM(keyData) - if e != nil { - panic(e.Error()) - } - return key -} - -func MakeSampleToken(c jwt.Claims, key interface{}) string { - token := jwt.NewWithClaims(jwt.SigningMethodRS256, c) - s, e := token.SignedString(key) - - if e != nil { - panic(e.Error()) - } - - return s -} diff --git a/vendor/github.com/dgrijalva/jwt-go/test/hmacTestKey b/vendor/github.com/dgrijalva/jwt-go/test/hmacTestKey deleted file mode 100644 index 435b8ddb3..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/test/hmacTestKey +++ /dev/null @@ -1 +0,0 @@ -#5K+~ew{Z(T(P.ZGwb="=.!r.O͚gЀ \ No newline at end of file diff --git a/vendor/github.com/dgrijalva/jwt-go/test/sample_key b/vendor/github.com/dgrijalva/jwt-go/test/sample_key deleted file mode 100644 index abdbade31..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/test/sample_key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEA4f5wg5l2hKsTeNem/V41fGnJm6gOdrj8ym3rFkEU/wT8RDtn -SgFEZOQpHEgQ7JL38xUfU0Y3g6aYw9QT0hJ7mCpz9Er5qLaMXJwZxzHzAahlfA0i -cqabvJOMvQtzD6uQv6wPEyZtDTWiQi9AXwBpHssPnpYGIn20ZZuNlX2BrClciHhC -PUIIZOQn/MmqTD31jSyjoQoV7MhhMTATKJx2XrHhR+1DcKJzQBSTAGnpYVaqpsAR -ap+nwRipr3nUTuxyGohBTSmjJ2usSeQXHI3bODIRe1AuTyHceAbewn8b462yEWKA -Rdpd9AjQW5SIVPfdsz5B6GlYQ5LdYKtznTuy7wIDAQABAoIBAQCwia1k7+2oZ2d3 -n6agCAbqIE1QXfCmh41ZqJHbOY3oRQG3X1wpcGH4Gk+O+zDVTV2JszdcOt7E5dAy -MaomETAhRxB7hlIOnEN7WKm+dGNrKRvV0wDU5ReFMRHg31/Lnu8c+5BvGjZX+ky9 -POIhFFYJqwCRlopGSUIxmVj5rSgtzk3iWOQXr+ah1bjEXvlxDOWkHN6YfpV5ThdE -KdBIPGEVqa63r9n2h+qazKrtiRqJqGnOrHzOECYbRFYhexsNFz7YT02xdfSHn7gM -IvabDDP/Qp0PjE1jdouiMaFHYnLBbgvlnZW9yuVf/rpXTUq/njxIXMmvmEyyvSDn -FcFikB8pAoGBAPF77hK4m3/rdGT7X8a/gwvZ2R121aBcdPwEaUhvj/36dx596zvY -mEOjrWfZhF083/nYWE2kVquj2wjs+otCLfifEEgXcVPTnEOPO9Zg3uNSL0nNQghj -FuD3iGLTUBCtM66oTe0jLSslHe8gLGEQqyMzHOzYxNqibxcOZIe8Qt0NAoGBAO+U -I5+XWjWEgDmvyC3TrOSf/KCGjtu0TSv30ipv27bDLMrpvPmD/5lpptTFwcxvVhCs -2b+chCjlghFSWFbBULBrfci2FtliClOVMYrlNBdUSJhf3aYSG2Doe6Bgt1n2CpNn -/iu37Y3NfemZBJA7hNl4dYe+f+uzM87cdQ214+jrAoGAXA0XxX8ll2+ToOLJsaNT -OvNB9h9Uc5qK5X5w+7G7O998BN2PC/MWp8H+2fVqpXgNENpNXttkRm1hk1dych86 -EunfdPuqsX+as44oCyJGFHVBnWpm33eWQw9YqANRI+pCJzP08I5WK3osnPiwshd+ -hR54yjgfYhBFNI7B95PmEQkCgYBzFSz7h1+s34Ycr8SvxsOBWxymG5zaCsUbPsL0 -4aCgLScCHb9J+E86aVbbVFdglYa5Id7DPTL61ixhl7WZjujspeXZGSbmq0Kcnckb -mDgqkLECiOJW2NHP/j0McAkDLL4tysF8TLDO8gvuvzNC+WQ6drO2ThrypLVZQ+ry -eBIPmwKBgEZxhqa0gVvHQG/7Od69KWj4eJP28kq13RhKay8JOoN0vPmspXJo1HY3 -CKuHRG+AP579dncdUnOMvfXOtkdM4vk0+hWASBQzM9xzVcztCa+koAugjVaLS9A+ -9uQoqEeVNTckxx0S2bYevRy7hGQmUJTyQm3j1zEUR5jpdbL83Fbq ------END RSA PRIVATE KEY----- diff --git a/vendor/github.com/dgrijalva/jwt-go/test/sample_key.pub b/vendor/github.com/dgrijalva/jwt-go/test/sample_key.pub deleted file mode 100644 index 03dc982ac..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/test/sample_key.pub +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4f5wg5l2hKsTeNem/V41 -fGnJm6gOdrj8ym3rFkEU/wT8RDtnSgFEZOQpHEgQ7JL38xUfU0Y3g6aYw9QT0hJ7 -mCpz9Er5qLaMXJwZxzHzAahlfA0icqabvJOMvQtzD6uQv6wPEyZtDTWiQi9AXwBp -HssPnpYGIn20ZZuNlX2BrClciHhCPUIIZOQn/MmqTD31jSyjoQoV7MhhMTATKJx2 -XrHhR+1DcKJzQBSTAGnpYVaqpsARap+nwRipr3nUTuxyGohBTSmjJ2usSeQXHI3b -ODIRe1AuTyHceAbewn8b462yEWKARdpd9AjQW5SIVPfdsz5B6GlYQ5LdYKtznTuy -7wIDAQAB ------END PUBLIC KEY----- diff --git a/vendor/github.com/dgrijalva/jwt-go/token.go b/vendor/github.com/dgrijalva/jwt-go/token.go deleted file mode 100644 index d637e0867..000000000 --- a/vendor/github.com/dgrijalva/jwt-go/token.go +++ /dev/null @@ -1,108 +0,0 @@ -package jwt - -import ( - "encoding/base64" - "encoding/json" - "strings" - "time" -) - -// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). -// You can override it to use another time value. This is useful for testing or if your -// server uses a different time zone than your tokens. -var TimeFunc = time.Now - -// Parse methods use this callback function to supply -// the key for verification. The function receives the parsed, -// but unverified Token. This allows you to use properties in the -// Header of the token (such as `kid`) to identify which key to use. -type Keyfunc func(*Token) (interface{}, error) - -// A JWT Token. Different fields will be used depending on whether you're -// creating or parsing/verifying a token. -type Token struct { - Raw string // The raw token. Populated when you Parse a token - Method SigningMethod // The signing method used or to be used - Header map[string]interface{} // The first segment of the token - Claims Claims // The second segment of the token - Signature string // The third segment of the token. Populated when you Parse a token - Valid bool // Is the token valid? Populated when you Parse/Verify a token -} - -// Create a new Token. Takes a signing method -func New(method SigningMethod) *Token { - return NewWithClaims(method, MapClaims{}) -} - -func NewWithClaims(method SigningMethod, claims Claims) *Token { - return &Token{ - Header: map[string]interface{}{ - "typ": "JWT", - "alg": method.Alg(), - }, - Claims: claims, - Method: method, - } -} - -// Get the complete, signed token -func (t *Token) SignedString(key interface{}) (string, error) { - var sig, sstr string - var err error - if sstr, err = t.SigningString(); err != nil { - return "", err - } - if sig, err = t.Method.Sign(sstr, key); err != nil { - return "", err - } - return strings.Join([]string{sstr, sig}, "."), nil -} - -// Generate the signing string. This is the -// most expensive part of the whole deal. Unless you -// need this for something special, just go straight for -// the SignedString. -func (t *Token) SigningString() (string, error) { - var err error - parts := make([]string, 2) - for i, _ := range parts { - var jsonValue []byte - if i == 0 { - if jsonValue, err = json.Marshal(t.Header); err != nil { - return "", err - } - } else { - if jsonValue, err = json.Marshal(t.Claims); err != nil { - return "", err - } - } - - parts[i] = EncodeSegment(jsonValue) - } - return strings.Join(parts, "."), nil -} - -// Parse, validate, and return a token. -// keyFunc will receive the parsed token and should return the key for validating. -// If everything is kosher, err will be nil -func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { - return new(Parser).Parse(tokenString, keyFunc) -} - -func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { - return new(Parser).ParseWithClaims(tokenString, claims, keyFunc) -} - -// Encode JWT specific base64url encoding with padding stripped -func EncodeSegment(seg []byte) string { - return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=") -} - -// Decode JWT specific base64url encoding with padding stripped -func DecodeSegment(seg string) ([]byte, error) { - if l := len(seg) % 4; l > 0 { - seg += strings.Repeat("=", 4-l) - } - - return base64.URLEncoding.DecodeString(seg) -} diff --git a/vendor/github.com/docker/cli/.dockerignore b/vendor/github.com/docker/cli/.dockerignore deleted file mode 100644 index b0e1ba591..000000000 --- a/vendor/github.com/docker/cli/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -.git -build \ No newline at end of file diff --git a/vendor/github.com/docker/cli/.github/CODEOWNERS b/vendor/github.com/docker/cli/.github/CODEOWNERS deleted file mode 100644 index a14fab44c..000000000 --- a/vendor/github.com/docker/cli/.github/CODEOWNERS +++ /dev/null @@ -1,9 +0,0 @@ -# Github code owners -# See https://github.com/blog/2392-introducing-code-owners - -cli/command/stack/** @dnephin @vdemeester -cli/compose/** @dnephin @vdemeester -contrib/completion/bash/** @albers -contrib/completion/zsh/** @sdurrheimer -docs/** @mstanleyjones @vdemeester @thaJeztah -scripts/** @dnephin diff --git a/vendor/github.com/docker/cli/.github/ISSUE_TEMPLATE.md b/vendor/github.com/docker/cli/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index f4c202880..000000000 --- a/vendor/github.com/docker/cli/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,64 +0,0 @@ - - -**Description** - - - -**Steps to reproduce the issue:** -1. -2. -3. - -**Describe the results you received:** - - -**Describe the results you expected:** - - -**Additional information you deem important (e.g. issue happens only occasionally):** - -**Output of `docker version`:** - -``` -(paste your output here) -``` - -**Output of `docker info`:** - -``` -(paste your output here) -``` - -**Additional environment details (AWS, VirtualBox, physical, etc.):** diff --git a/vendor/github.com/docker/cli/.github/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/docker/cli/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 4e48d5f88..000000000 --- a/vendor/github.com/docker/cli/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,30 +0,0 @@ - - -**- What I did** - -**- How I did it** - -**- How to verify it** - -**- Description for the changelog** - - - -**- A picture of a cute animal (not mandatory but encouraged)** - diff --git a/vendor/github.com/docker/cli/.gitignore b/vendor/github.com/docker/cli/.gitignore deleted file mode 100644 index fa99439ac..000000000 --- a/vendor/github.com/docker/cli/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -.DS_Store -/build/ -cli/winresources/rsrc_386.syso -cli/winresources/rsrc_amd64.syso -/man/man1/ -/man/man5/ -/man/man8/ -/docs/yaml/gen/ -coverage.txt -profile.out diff --git a/vendor/github.com/docker/cli/CONTRIBUTING.md b/vendor/github.com/docker/cli/CONTRIBUTING.md deleted file mode 100644 index 245d3a3ab..000000000 --- a/vendor/github.com/docker/cli/CONTRIBUTING.md +++ /dev/null @@ -1,365 +0,0 @@ -# Contributing to Docker - -Want to hack on Docker? Awesome! We have a contributor's guide that explains -[setting up a Docker development environment and the contribution -process](https://docs.docker.com/opensource/project/who-written-for/). - -This page contains information about reporting issues as well as some tips and -guidelines useful to experienced open source contributors. Finally, make sure -you read our [community guidelines](#docker-community-guidelines) before you -start participating. - -## Topics - -* [Reporting Security Issues](#reporting-security-issues) -* [Design and Cleanup Proposals](#design-and-cleanup-proposals) -* [Reporting Issues](#reporting-other-issues) -* [Quick Contribution Tips and Guidelines](#quick-contribution-tips-and-guidelines) -* [Community Guidelines](#docker-community-guidelines) - -## Reporting security issues - -The Docker maintainers take security seriously. If you discover a security -issue, please bring it to their attention right away! - -Please **DO NOT** file a public issue, instead send your report privately to -[security@docker.com](mailto:security@docker.com). - -Security reports are greatly appreciated and we will publicly thank you for it. -We also like to send gifts—if you're into Docker schwag, make sure to let -us know. We currently do not offer a paid security bounty program, but are not -ruling it out in the future. - - -## Reporting other issues - -A great way to contribute to the project is to send a detailed report when you -encounter an issue. We always appreciate a well-written, thorough bug report, -and will thank you for it! - -Check that [our issue database](https://github.com/docker/cli/issues) -doesn't already include that problem or suggestion before submitting an issue. -If you find a match, you can use the "subscribe" button to get notified on -updates. Do *not* leave random "+1" or "I have this too" comments, as they -only clutter the discussion, and don't help resolving it. However, if you -have ways to reproduce the issue or have additional information that may help -resolving the issue, please leave a comment. - -When reporting issues, always include: - -* The output of `docker version`. -* The output of `docker info`. - -Also include the steps required to reproduce the problem if possible and -applicable. This information will help us review and fix your issue faster. -When sending lengthy log-files, consider posting them as a gist (https://gist.github.com). -Don't forget to remove sensitive data from your logfiles before posting (you can -replace those parts with "REDACTED"). - -## Quick contribution tips and guidelines - -This section gives the experienced contributor some tips and guidelines. - -### Pull requests are always welcome - -Not sure if that typo is worth a pull request? Found a bug and know how to fix -it? Do it! We will appreciate it. Any significant improvement should be -documented as [a GitHub issue](https://github.com/docker/cli/issues) before -anybody starts working on it. - -We are always thrilled to receive pull requests. We do our best to process them -quickly. If your pull request is not accepted on the first try, -don't get discouraged! Our contributor's guide explains [the review process we -use for simple changes](https://docs.docker.com/opensource/workflow/make-a-contribution/). - -### Talking to other Docker users and contributors - - - - - - - - - - - - - - - - - - - - -
Forums - A public forum for users to discuss questions and explore current design patterns and - best practices about Docker and related projects in the Docker Ecosystem. To participate, - just log in with your Docker Hub account on https://forums.docker.com. -
Community Slack - The Docker Community has a dedicated Slack chat to discuss features and issues. You can sign-up with this link. -
Twitter - You can follow Docker's Twitter feed - to get updates on our products. You can also tweet us questions or just - share blogs or stories. -
Stack Overflow - Stack Overflow has over 17000 Docker questions listed. We regularly - monitor Docker questions - and so do many other knowledgeable Docker users. -
- - -### Conventions - -Fork the repository and make changes on your fork in a feature branch: - -- If it's a bug fix branch, name it XXXX-something where XXXX is the number of - the issue. -- If it's a feature branch, create an enhancement issue to announce - your intentions, and name it XXXX-something where XXXX is the number of the - issue. - -Submit unit tests for your changes. Go has a great test framework built in; use -it! Take a look at existing tests for inspiration. [Run the full test -suite](README.md) on your branch before -submitting a pull request. - -Update the documentation when creating or modifying features. Test your -documentation changes for clarity, concision, and correctness, as well as a -clean documentation build. See our contributors guide for [our style -guide](https://docs.docker.com/opensource/doc-style) and instructions on [building -the documentation](https://docs.docker.com/opensource/project/test-and-docs/#build-and-test-the-documentation). - -Write clean code. Universally formatted code promotes ease of writing, reading, -and maintenance. Always run `gofmt -s -w file.go` on each changed file before -committing your changes. Most editors have plug-ins that do this automatically. - -Pull request descriptions should be as clear as possible and include a reference -to all the issues that they address. - -Commit messages must start with a capitalized and short summary (max. 50 chars) -written in the imperative, followed by an optional, more detailed explanatory -text which is separated from the summary by an empty line. - -Code review comments may be added to your pull request. Discuss, then make the -suggested modifications and push additional commits to your feature branch. Post -a comment after pushing. New commits show up in the pull request automatically, -but the reviewers are notified only when you comment. - -Pull requests must be cleanly rebased on top of master without multiple branches -mixed into the PR. - -**Git tip**: If your PR no longer merges cleanly, use `rebase master` in your -feature branch to update your pull request rather than `merge master`. - -Before you make a pull request, squash your commits into logical units of work -using `git rebase -i` and `git push -f`. A logical unit of work is a consistent -set of patches that should be reviewed together: for example, upgrading the -version of a vendored dependency and taking advantage of its now available new -feature constitute two separate units of work. Implementing a new function and -calling it in another file constitute a single logical unit of work. The very -high majority of submissions should have a single commit, so if in doubt: squash -down to one. - -After every commit, make sure the test suite passes. Include documentation -changes in the same pull request so that a revert would remove all traces of -the feature or fix. - -Include an issue reference like `Closes #XXXX` or `Fixes #XXXX` in the pull request -description that close an issue. Including references automatically closes the issue -on a merge. - -Please do not add yourself to the `AUTHORS` file, as it is regenerated regularly -from the Git history. - -Please see the [Coding Style](#coding-style) for further guidelines. - -### Merge approval - -Docker maintainers use LGTM (Looks Good To Me) in comments on the code review to -indicate acceptance. - -A change requires LGTMs from an absolute majority of the maintainers of each -component affected. For example, if a change affects `docs/` and `registry/`, it -needs an absolute majority from the maintainers of `docs/` AND, separately, an -absolute majority of the maintainers of `registry/`. - -For more details, see the [MAINTAINERS](MAINTAINERS) page. - -### 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`. - -### How can I become a maintainer? - -The procedures for adding new maintainers are explained in the -global [MAINTAINERS](https://github.com/docker/opensource/blob/master/MAINTAINERS) -file in the [https://github.com/docker/opensource/](https://github.com/docker/opensource/) -repository. - -Don't forget: being a maintainer is a time investment. Make sure you -will have time to make yourself available. You don't have to be a -maintainer to make a difference on the project! - -## Docker community guidelines - -We want to keep the Docker community awesome, growing and collaborative. We need -your help to keep it that way. To help with this we've come up with some general -guidelines for the community as a whole: - -* Be nice: Be courteous, respectful and polite to fellow community members: - no regional, racial, gender, or other abuse will be tolerated. We like - nice people way better than mean ones! - -* Encourage diversity and participation: Make everyone in our community feel - welcome, regardless of their background and the extent of their - contributions, and do everything possible to encourage participation in - our community. - -* Keep it legal: Basically, don't get us in trouble. Share only content that - you own, do not share private or sensitive information, and don't break - the law. - -* Stay on topic: Make sure that you are posting to the correct channel and - avoid off-topic discussions. Remember when you update an issue or respond - to an email you are potentially sending to a large number of people. Please - consider this before you update. Also remember that nobody likes spam. - -* Don't send email to the maintainers: There's no need to send email to the - maintainers to ask them to investigate an issue or to take a look at a - pull request. Instead of sending an email, GitHub mentions should be - used to ping maintainers to review a pull request, a proposal or an - issue. - -### Guideline violations — 3 strikes method - -The point of this section is not to find opportunities to punish people, but we -do need a fair way to deal with people who are making our community suck. - -1. First occurrence: We'll give you a friendly, but public reminder that the - behavior is inappropriate according to our guidelines. - -2. Second occurrence: We will send you a private message with a warning that - any additional violations will result in removal from the community. - -3. Third occurrence: Depending on the violation, we may need to delete or ban - your account. - -**Notes:** - -* Obvious spammers are banned on first occurrence. If we don't do this, we'll - have spam all over the place. - -* Violations are forgiven after 6 months of good behavior, and we won't hold a - grudge. - -* People who commit minor infractions will get some education, rather than - hammering them in the 3 strikes process. - -* The rules apply equally to everyone in the community, no matter how much - you've contributed. - -* Extreme violations of a threatening, abusive, destructive or illegal nature - will be addressed immediately and are not subject to 3 strikes or forgiveness. - -* Contact abuse@docker.com to report abuse or appeal violations. In the case of - appeals, we know that mistakes happen, and we'll work with you to come up with a - fair solution if there has been a misunderstanding. - -## Coding Style - -Unless explicitly stated, we follow all coding guidelines from the Go -community. While some of these standards may seem arbitrary, they somehow seem -to result in a solid, consistent codebase. - -It is possible that the code base does not currently comply with these -guidelines. We are not looking for a massive PR that fixes this, since that -goes against the spirit of the guidelines. All new contributions should make a -best effort to clean up and make the code base better than they left it. -Obviously, apply your best judgement. Remember, the goal here is to make the -code base easier for humans to navigate and understand. Always keep that in -mind when nudging others to comply. - -The rules: - -1. All code should be formatted with `gofmt -s`. -2. All code should pass the default levels of - [`golint`](https://github.com/golang/lint). -3. All code should follow the guidelines covered in [Effective - Go](http://golang.org/doc/effective_go.html) and [Go Code Review - Comments](https://github.com/golang/go/wiki/CodeReviewComments). -4. Comment the code. Tell us the why, the history and the context. -5. Document _all_ declarations and methods, even private ones. Declare - expectations, caveats and anything else that may be important. If a type - gets exported, having the comments already there will ensure it's ready. -6. Variable name length should be proportional to its context and no longer. - `noCommaALongVariableNameLikeThisIsNotMoreClearWhenASimpleCommentWouldDo`. - In practice, short methods will have short variable names and globals will - have longer names. -7. No underscores in package names. If you need a compound name, step back, - and re-examine why you need a compound name. If you still think you need a - compound name, lose the underscore. -8. No utils or helpers packages. If a function is not general enough to - warrant its own package, it has not been written generally enough to be a - part of a util package. Just leave it unexported and well-documented. -9. All tests should run with `go test` and outside tooling should not be - required. No, we don't need another unit testing framework. Assertion - packages are acceptable if they provide _real_ incremental value. -10. Even though we call these "rules" above, they are actually just - guidelines. Since you've read all the rules, you now know that. - -If you are having trouble getting into the mood of idiomatic Go, we recommend -reading through [Effective Go](https://golang.org/doc/effective_go.html). The -[Go Blog](https://blog.golang.org) is also a great resource. Drinking the -kool-aid is a lot easier than going thirsty. \ No newline at end of file diff --git a/vendor/github.com/docker/cli/Jenkinsfile b/vendor/github.com/docker/cli/Jenkinsfile deleted file mode 100644 index c5fd50559..000000000 --- a/vendor/github.com/docker/cli/Jenkinsfile +++ /dev/null @@ -1,12 +0,0 @@ -wrappedNode(label: 'linux && x86_64', cleanWorkspace: true) { - timeout(time: 60, unit: 'MINUTES') { - stage "Git Checkout" - checkout scm - - stage "Run end-to-end test suite" - sh "docker version" - sh "E2E_UNIQUE_ID=clie2e${BUILD_NUMBER} \ - IMAGE_TAG=clie2e${BUILD_NUMBER} \ - make -f docker.Makefile test-e2e" - } -} diff --git a/vendor/github.com/docker/cli/MAINTAINERS b/vendor/github.com/docker/cli/MAINTAINERS deleted file mode 100644 index 2ebec81eb..000000000 --- a/vendor/github.com/docker/cli/MAINTAINERS +++ /dev/null @@ -1,177 +0,0 @@ -# Docker maintainers file -# -# This file describes who runs the docker/docker 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"] - - # The Core maintainers are the ghostbusters of the project: when there's a problem others - # can't solve, they show up and fix it with bizarre devices and weaponry. - # They have final say on technical implementation and coding style. - # They are ultimately responsible for quality in all its forms: usability polish, - # bugfixes, performance, stability, etc. When ownership can cleanly be passed to - # a subsystem, they are responsible for doing so and holding the - # subsystem maintainers accountable. If ownership is unclear, they are the de facto owners. - - # For each release (including minor releases), a "release captain" is assigned from the - # pool of core maintainers. Rotation is encouraged across all maintainers, to ensure - # the release process is clear and up-to-date. - - people = [ - "aaronlehmann", - "albers", - "aluzzardi", - "anusha", - "cpuguy83", - "crosbymichael", - "dnephin", - "ehazlett", - "johnstep", - "justincormack", - "mavenugo", - "mlaventure", - "stevvooe", - "tibor", - "tonistiigi", - "vdemeester", - "vieux", - ] - - [Org."Docs maintainers"] - - # TODO Describe the docs maintainers role. - - people = [ - "misty", - "thajeztah" - ] - - [Org.Curators] - - # The curators help ensure that incoming issues and pull requests are properly triaged and - # that our various contribution and reviewing processes are respected. With their knowledge of - # the repository activity, they can also guide contributors to relevant material or - # discussions. - # - # They are neither code nor docs reviewers, so they are never expected to merge. They can - # however: - # - close an issue or pull request when it's an exact duplicate - # - close an issue or pull request when it's inappropriate or off-topic - - people = [ - "ehazlett", - "programmerq", - "thajeztah" - ] - -[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.aaronlehmann] - Name = "Aaron Lehmann" - Email = "aaron.lehmann@docker.com" - GitHub = "aaronlehmann" - - [people.albers] - Name = "Harald Albers" - Email = "github@albersweb.de" - GitHub = "albers" - - [people.aluzzardi] - Name = "Andrea Luzzardi" - Email = "al@docker.com" - GitHub = "aluzzardi" - - [people.anusha] - Name = "Anusha Ragunathan" - Email = "anusha@docker.com" - GitHub = "anusha-ragunathan" - - [people.cpuguy83] - Name = "Brian Goff" - Email = "cpuguy83@gmail.com" - Github = "cpuguy83" - - [people.crosbymichael] - Name = "Michael Crosby" - Email = "crosbymichael@gmail.com" - GitHub = "crosbymichael" - - [people.dnephin] - Name = "Daniel Nephin" - Email = "dnephin@gmail.com" - GitHub = "dnephin" - - [people.ehazlett] - Name = "Evan Hazlett" - Email = "ejhazlett@gmail.com" - GitHub = "ehazlett" - - [people.johnstep] - Name = "John Stephens" - Email = "johnstep@docker.com" - GitHub = "johnstep" - - [people.justincormack] - Name = "Justin Cormack" - Email = "justin.cormack@docker.com" - GitHub = "justincormack" - - [people.misty] - Name = "Misty Stanley-Jones" - Email = "misty@docker.com" - GitHub = "mstanleyjones" - - [people.mlaventure] - Name = "Kenfe-Mickaël Laventure" - Email = "mickael.laventure@docker.com" - GitHub = "mlaventure" - - [people.shykes] - Name = "Solomon Hykes" - Email = "solomon@docker.com" - GitHub = "shykes" - - [people.stevvooe] - Name = "Stephen Day" - Email = "stephen.day@docker.com" - GitHub = "stevvooe" - - [people.thajeztah] - Name = "Sebastiaan van Stijn" - Email = "github@gone.nl" - GitHub = "thaJeztah" - - [people.tibor] - Name = "Tibor Vass" - Email = "tibor@docker.com" - GitHub = "tiborvass" - - [people.tonistiigi] - Name = "Tõnis Tiigi" - Email = "tonis@docker.com" - GitHub = "tonistiigi" - - [people.vdemeester] - Name = "Vincent Demeester" - Email = "vincent@sbr.pm" - GitHub = "vdemeester" - - [people.vieux] - Name = "Victor Vieux" - Email = "vieux@docker.com" - GitHub = "vieux" - diff --git a/vendor/github.com/docker/cli/Makefile b/vendor/github.com/docker/cli/Makefile deleted file mode 100644 index f6e73e067..000000000 --- a/vendor/github.com/docker/cli/Makefile +++ /dev/null @@ -1,77 +0,0 @@ -# -# github.com/docker/cli -# -all: binary - - -_:=$(shell ./scripts/warn-outside-container $(MAKECMDGOALS)) - -.PHONY: clean -clean: ## remove build artifacts - rm -rf ./build/* cli/winresources/rsrc_* ./man/man[1-9] docs/yaml/gen - -.PHONY: test-unit -test-unit: ## run unit test - ./scripts/test/unit $(shell go list ./... | grep -vE '/vendor/|/e2e/') - -.PHONY: test -test: test-unit ## run tests - -.PHONY: test-coverage -test-coverage: ## run test coverage - ./scripts/test/unit-with-coverage $(shell go list ./... | grep -vE '/vendor/|/e2e/') - -.PHONY: lint -lint: ## run all the lint tools - gometalinter --config gometalinter.json ./... - -.PHONY: binary -binary: ## build executable for Linux - @echo "WARNING: binary creates a Linux executable. Use cross for macOS or Windows." - ./scripts/build/binary - -.PHONY: cross -cross: ## build executable for macOS and Windows - ./scripts/build/cross - -.PHONY: dynbinary -dynbinary: ## build dynamically linked binary - ./scripts/build/dynbinary - -.PHONY: watch -watch: ## monitor file changes and run go test - ./scripts/test/watch - -vendor: vendor.conf ## check that vendor matches vendor.conf - vndr 2> /dev/null - scripts/validate/check-git-diff vendor - -.PHONY: manpages -manpages: ## generate man pages from go source and markdown - scripts/docs/generate-man.sh - -.PHONY: yamldocs -yamldocs: ## generate documentation YAML files consumed by docs repo - scripts/docs/generate-yaml.sh - -.PHONY: shellcheck -shellcheck: ## run shellcheck validation - scripts/validate/shellcheck - -.PHONY: help -help: ## print this help - @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) - - -cli/compose/schema/bindata.go: cli/compose/schema/data/*.json - go generate github.com/docker/cli/cli/compose/schema - -compose-jsonschema: cli/compose/schema/bindata.go - scripts/validate/check-git-diff cli/compose/schema/bindata.go - -.PHONY: ci-validate -ci-validate: - time make -B vendor - time make -B compose-jsonschema - time make manpages - time make yamldocs diff --git a/vendor/github.com/docker/cli/NOTICE b/vendor/github.com/docker/cli/NOTICE deleted file mode 100644 index 0c74e15b0..000000000 --- a/vendor/github.com/docker/cli/NOTICE +++ /dev/null @@ -1,19 +0,0 @@ -Docker -Copyright 2012-2017 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/cli/README.md b/vendor/github.com/docker/cli/README.md deleted file mode 100644 index 496d13f23..000000000 --- a/vendor/github.com/docker/cli/README.md +++ /dev/null @@ -1,69 +0,0 @@ -[![build status](https://circleci.com/gh/docker/cli.svg?style=shield)](https://circleci.com/gh/docker/cli/tree/master) - -docker/cli -========== - -This repository is the home of the cli used in the Docker CE and -Docker EE products. - -Development -=========== - -`docker/cli` is developed using Docker. - -Build a linux binary: - -``` -$ make -f docker.Makefile binary -``` - -Build binaries for all supported platforms: - -``` -$ make -f docker.Makefile cross -``` - -Run all linting: - -``` -$ make -f docker.Makefile lint -``` - -List all the available targets: - -``` -$ make help -``` - -### In-container development environment - -Start an interactive development environment: - -``` -$ make -f docker.Makefile shell -``` - -In the development environment you can run many tasks, including build binaries: - -``` -$ make binary -``` - -Legal -===== -*Brought to you courtesy of our legal counsel. For more context, -please see the [NOTICE](https://github.com/docker/cli/blob/master/NOTICE) document in this repo.* - -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 - -Licensing -========= -docker/cli is licensed under the Apache License, Version 2.0. See -[LICENSE](https://github.com/docker/docker/blob/master/LICENSE) for the full -license text. diff --git a/vendor/github.com/docker/cli/TESTING.md b/vendor/github.com/docker/cli/TESTING.md deleted file mode 100644 index 63bba1d3d..000000000 --- a/vendor/github.com/docker/cli/TESTING.md +++ /dev/null @@ -1,87 +0,0 @@ -# Testing - -The following guidelines summarize the testing policy for docker/cli. - -## Unit Test Suite - -All code changes should have unit test coverage. - -Error cases should be tested with unit tests. - -Bug fixes should be covered by new unit tests or additional assertions in -existing unit tests. - -### Details - -The unit test suite follows the standard Go testing convention. Tests are -located in the package directory in `_test.go` files. - -Unit tests should be named using the convention: - -``` -Test -``` - -[Table tests](https://github.com/golang/go/wiki/TableDrivenTests) should be used -where appropriate, but may not be appropriate in all cases. - -Assertions should be made using -[testify/assert](https://godoc.org/github.com/stretchr/testify/assert) and test -requirements should be verified using -[testify/require](https://godoc.org/github.com/stretchr/testify/require). - -Fakes, and testing utilities can be found in -[internal/test](https://godoc.org/github.com/docker/cli/internal/test) and -[gotestyourself](https://godoc.org/github.com/gotestyourself/gotestyourself). - -## End-to-End Test Suite - -The end-to-end test suite tests a cli binary against a real API backend. - -### Guidelines - -Each feature (subcommand) should have a single end-to-end test for -the success case. The test should include all (or most) flags/options supported -by that feature. - -In some rare cases a couple additional end-to-end tests may be written for a -sufficiently complex and critical feature (ex: `container run`, `service -create`, `service update`, and `docker build` may have ~3-5 cases each). - -In some rare cases a sufficiently critical error paths may have a single -end-to-end test case. - -In all other cases the behaviour should be covered by unit tests. - -If a code change adds a new flag, that flag should be added to the existing -"success case" end-to-end test. - -If a code change fixes a bug, that bug fix should be covered either by adding -assertions to the existing end-to-end test, or with one or more unit test. - -### Details - -The end-to-end test suite is located in -[./e2e](https://github.com/docker/cli/tree/master/e2e). Each directory in `e2e` -corresponds to a directory in `cli/command` and contains the tests for that -subcommand. Files in each directory should be named `_test.go` where -command is the basename of the command (ex: the test for `docker stack deploy` -is found in `e2e/stack/deploy_test.go`). - -Tests should be named using the convention: - -``` -Test[] -``` - -where the test case name is only required when there are multiple test cases for -a single command. - -End-to-end test should run the `docker` binary using -[gotestyourself/icmd](https://godoc.org/github.com/gotestyourself/gotestyourself/icmd) -and make assertions about the exit code, stdout, stderr, and local file system. - -Any Docker image or registry operations should use `registry:5000/` -to communicate with the local instance of the Docker registry. To load -additional fixture images to the registry see -[scripts/test/e2e/run](https://github.com/docker/cli/blob/master/scripts/test/e2e/run). diff --git a/vendor/github.com/docker/cli/VERSION b/vendor/github.com/docker/cli/VERSION deleted file mode 100644 index a38a5dd06..000000000 --- a/vendor/github.com/docker/cli/VERSION +++ /dev/null @@ -1 +0,0 @@ -17.10.0-dev diff --git a/vendor/github.com/docker/cli/circle.yml b/vendor/github.com/docker/cli/circle.yml deleted file mode 100644 index 53fcac738..000000000 --- a/vendor/github.com/docker/cli/circle.yml +++ /dev/null @@ -1,116 +0,0 @@ -version: 2 - -jobs: - - lint: - working_directory: /work - docker: [{image: 'docker:17.06-git'}] - steps: - - checkout - - setup_remote_docker: - reusable: true - exclusive: false - - run: - command: docker version - - run: - name: "Lint" - command: | - dockerfile=dockerfiles/Dockerfile.lint - echo "COPY . ." >> $dockerfile - docker build -f $dockerfile --tag cli-linter:$CIRCLE_BUILD_NUM . - docker run --rm cli-linter:$CIRCLE_BUILD_NUM - - cross: - working_directory: /work - docker: [{image: 'docker:17.06-git'}] - parallelism: 3 - steps: - - checkout - - setup_remote_docker: - reusable: true - exclusive: false - - run: - name: "Cross" - command: | - dockerfile=dockerfiles/Dockerfile.cross - echo "COPY . ." >> $dockerfile - docker build -f $dockerfile --tag cli-builder:$CIRCLE_BUILD_NUM . - name=cross-$CIRCLE_BUILD_NUM-$CIRCLE_NODE_INDEX - docker run \ - -e CROSS_GROUP=$CIRCLE_NODE_INDEX \ - --name $name cli-builder:$CIRCLE_BUILD_NUM \ - make cross - docker cp \ - $name:/go/src/github.com/docker/cli/build \ - /work/build - - store_artifacts: - path: /work/build - - test: - working_directory: /work - docker: [{image: 'docker:17.06-git'}] - steps: - - checkout - - setup_remote_docker: - reusable: true - exclusive: false - - run: - name: "Unit Test with Coverage" - command: | - dockerfile=dockerfiles/Dockerfile.dev - echo "COPY . ." >> $dockerfile - docker build -f $dockerfile --tag cli-builder:$CIRCLE_BUILD_NUM . - docker run --name \ - test-$CIRCLE_BUILD_NUM cli-builder:$CIRCLE_BUILD_NUM \ - make test-coverage - - - run: - name: "Upload to Codecov" - command: | - docker cp \ - test-$CIRCLE_BUILD_NUM:/go/src/github.com/docker/cli/coverage.txt \ - coverage.txt - apk add -U bash curl - curl -s https://codecov.io/bash | bash || \ - echo 'Codecov failed to upload' - - validate: - working_directory: /work - docker: [{image: 'docker:17.06-git'}] - steps: - - checkout - - setup_remote_docker: - reusable: true - exclusive: false - - run: - name: "Validate Vendor, Docs, and Code Generation" - command: | - dockerfile=dockerfiles/Dockerfile.dev - echo "COPY . ." >> $dockerfile - rm -f .dockerignore # include .git - docker build -f $dockerfile --tag cli-builder-with-git:$CIRCLE_BUILD_NUM . - docker run --rm cli-builder-with-git:$CIRCLE_BUILD_NUM \ - make ci-validate - shellcheck: - working_directory: /work - docker: [{image: 'docker:17.06-git'}] - steps: - - checkout - - setup_remote_docker - - run: - name: "Run shellcheck" - command: | - dockerfile=dockerfiles/Dockerfile.shellcheck - echo "COPY . ." >> $dockerfile - docker build -f $dockerfile --tag cli-validator:$CIRCLE_BUILD_NUM . - docker run --rm cli-validator:$CIRCLE_BUILD_NUM \ - make shellcheck -workflows: - version: 2 - ci: - jobs: - - lint - - cross - - test - - validate - - shellcheck diff --git a/vendor/github.com/docker/cli/cli/cobra.go b/vendor/github.com/docker/cli/cli/cobra.go deleted file mode 100644 index 114f1b7d6..000000000 --- a/vendor/github.com/docker/cli/cli/cobra.go +++ /dev/null @@ -1,150 +0,0 @@ -package cli - -import ( - "fmt" - "strings" - - "github.com/docker/docker/pkg/term" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -// SetupRootCommand sets default usage, help, and error handling for the -// root command. -func SetupRootCommand(rootCmd *cobra.Command) { - cobra.AddTemplateFunc("hasSubCommands", hasSubCommands) - cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands) - cobra.AddTemplateFunc("operationSubCommands", operationSubCommands) - cobra.AddTemplateFunc("managementSubCommands", managementSubCommands) - cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages) - - rootCmd.SetUsageTemplate(usageTemplate) - rootCmd.SetHelpTemplate(helpTemplate) - rootCmd.SetFlagErrorFunc(FlagErrorFunc) - rootCmd.SetHelpCommand(helpCommand) - - rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage") - rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help") -} - -// FlagErrorFunc prints an error message which matches the format of the -// docker/cli/cli error messages -func FlagErrorFunc(cmd *cobra.Command, err error) error { - if err == nil { - return nil - } - - usage := "" - if cmd.HasSubCommands() { - usage = "\n\n" + cmd.UsageString() - } - return StatusError{ - Status: fmt.Sprintf("%s\nSee '%s --help'.%s", err, cmd.CommandPath(), usage), - StatusCode: 125, - } -} - -var helpCommand = &cobra.Command{ - Use: "help [command]", - Short: "Help about the command", - PersistentPreRun: func(cmd *cobra.Command, args []string) {}, - PersistentPostRun: func(cmd *cobra.Command, args []string) {}, - RunE: func(c *cobra.Command, args []string) error { - cmd, args, e := c.Root().Find(args) - if cmd == nil || e != nil || len(args) > 0 { - return errors.Errorf("unknown help topic: %v", strings.Join(args, " ")) - } - - helpFunc := cmd.HelpFunc() - helpFunc(cmd, args) - return nil - }, -} - -func hasSubCommands(cmd *cobra.Command) bool { - return len(operationSubCommands(cmd)) > 0 -} - -func hasManagementSubCommands(cmd *cobra.Command) bool { - return len(managementSubCommands(cmd)) > 0 -} - -func operationSubCommands(cmd *cobra.Command) []*cobra.Command { - cmds := []*cobra.Command{} - for _, sub := range cmd.Commands() { - if sub.IsAvailableCommand() && !sub.HasSubCommands() { - cmds = append(cmds, sub) - } - } - return cmds -} - -func wrappedFlagUsages(cmd *cobra.Command) string { - width := 80 - if ws, err := term.GetWinsize(0); err == nil { - width = int(ws.Width) - } - return cmd.Flags().FlagUsagesWrapped(width - 1) -} - -func managementSubCommands(cmd *cobra.Command) []*cobra.Command { - cmds := []*cobra.Command{} - for _, sub := range cmd.Commands() { - if sub.IsAvailableCommand() && sub.HasSubCommands() { - cmds = append(cmds, sub) - } - } - return cmds -} - -var usageTemplate = `Usage: - -{{- if not .HasSubCommands}} {{.UseLine}}{{end}} -{{- if .HasSubCommands}} {{ .CommandPath}} COMMAND{{end}} - -{{ .Short | trim }} - -{{- if gt .Aliases 0}} - -Aliases: - {{.NameAndAliases}} - -{{- end}} -{{- if .HasExample}} - -Examples: -{{ .Example }} - -{{- end}} -{{- if .HasFlags}} - -Options: -{{ wrappedFlagUsages . | trimRightSpace}} - -{{- end}} -{{- if hasManagementSubCommands . }} - -Management Commands: - -{{- range managementSubCommands . }} - {{rpad .Name .NamePadding }} {{.Short}} -{{- end}} - -{{- end}} -{{- if hasSubCommands .}} - -Commands: - -{{- range operationSubCommands . }} - {{rpad .Name .NamePadding }} {{.Short}} -{{- end}} -{{- end}} - -{{- if .HasSubCommands }} - -Run '{{.CommandPath}} COMMAND --help' for more information on a command. -{{- end}} -` - -var helpTemplate = ` -{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}}` diff --git a/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile.go b/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile.go deleted file mode 100644 index 07e2c8b08..000000000 --- a/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile.go +++ /dev/null @@ -1,70 +0,0 @@ -package bundlefile - -import ( - "encoding/json" - "io" - - "github.com/pkg/errors" -) - -// Bundlefile stores the contents of a bundlefile -type Bundlefile struct { - Version string - Services map[string]Service -} - -// Service is a service from a bundlefile -type Service struct { - Image string - Command []string `json:",omitempty"` - Args []string `json:",omitempty"` - Env []string `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Ports []Port `json:",omitempty"` - WorkingDir *string `json:",omitempty"` - User *string `json:",omitempty"` - Networks []string `json:",omitempty"` -} - -// Port is a port as defined in a bundlefile -type Port struct { - Protocol string - Port uint32 -} - -// LoadFile loads a bundlefile from a path to the file -func LoadFile(reader io.Reader) (*Bundlefile, error) { - bundlefile := &Bundlefile{} - - decoder := json.NewDecoder(reader) - if err := decoder.Decode(bundlefile); err != nil { - switch jsonErr := err.(type) { - case *json.SyntaxError: - return nil, errors.Errorf( - "JSON syntax error at byte %v: %s", - jsonErr.Offset, - jsonErr.Error()) - case *json.UnmarshalTypeError: - return nil, errors.Errorf( - "Unexpected type at byte %v. Expected %s but received %s.", - jsonErr.Offset, - jsonErr.Type, - jsonErr.Value) - } - return nil, err - } - - return bundlefile, nil -} - -// Print writes the contents of the bundlefile to the output writer -// as human readable json -func Print(out io.Writer, bundle *Bundlefile) error { - bytes, err := json.MarshalIndent(*bundle, "", " ") - if err != nil { - return err - } - - _, err = out.Write(bytes) - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile_test.go b/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile_test.go deleted file mode 100644 index bd059c4dc..000000000 --- a/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package bundlefile - -import ( - "bytes" - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestLoadFileV01Success(t *testing.T) { - reader := strings.NewReader(`{ - "Version": "0.1", - "Services": { - "redis": { - "Image": "redis@sha256:4b24131101fa0117bcaa18ac37055fffd9176aa1a240392bb8ea85e0be50f2ce", - "Networks": ["default"] - }, - "web": { - "Image": "dockercloud/hello-world@sha256:fe79a2cfbd17eefc344fb8419420808df95a1e22d93b7f621a7399fd1e9dca1d", - "Networks": ["default"], - "User": "web" - } - } - }`) - - bundle, err := LoadFile(reader) - assert.NoError(t, err) - assert.Equal(t, "0.1", bundle.Version) - assert.Len(t, bundle.Services, 2) -} - -func TestLoadFileSyntaxError(t *testing.T) { - reader := strings.NewReader(`{ - "Version": "0.1", - "Services": unquoted string - }`) - - _, err := LoadFile(reader) - assert.EqualError(t, err, "JSON syntax error at byte 37: invalid character 'u' looking for beginning of value") -} - -func TestLoadFileTypeError(t *testing.T) { - reader := strings.NewReader(`{ - "Version": "0.1", - "Services": { - "web": { - "Image": "redis", - "Networks": "none" - } - } - }`) - - _, err := LoadFile(reader) - assert.EqualError(t, err, "Unexpected type at byte 94. Expected []string but received string.") -} - -func TestPrint(t *testing.T) { - var buffer bytes.Buffer - bundle := &Bundlefile{ - Version: "0.1", - Services: map[string]Service{ - "web": { - Image: "image", - Command: []string{"echo", "something"}, - }, - }, - } - assert.NoError(t, Print(&buffer, bundle)) - output := buffer.String() - assert.Contains(t, output, "\"Image\": \"image\"") - assert.Contains(t, output, - `"Command": [ - "echo", - "something" - ]`) -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/client_test.go b/vendor/github.com/docker/cli/cli/command/checkpoint/client_test.go deleted file mode 100644 index ca9171961..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/client_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package checkpoint - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - checkpointCreateFunc func(container string, options types.CheckpointCreateOptions) error - checkpointDeleteFunc func(container string, options types.CheckpointDeleteOptions) error - checkpointListFunc func(container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) -} - -func (cli *fakeClient) CheckpointCreate(ctx context.Context, container string, options types.CheckpointCreateOptions) error { - if cli.checkpointCreateFunc != nil { - return cli.checkpointCreateFunc(container, options) - } - return nil -} - -func (cli *fakeClient) CheckpointDelete(ctx context.Context, container string, options types.CheckpointDeleteOptions) error { - if cli.checkpointDeleteFunc != nil { - return cli.checkpointDeleteFunc(container, options) - } - return nil -} - -func (cli *fakeClient) CheckpointList(ctx context.Context, container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) { - if cli.checkpointListFunc != nil { - return cli.checkpointListFunc(container, options) - } - return []types.Checkpoint{}, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/cmd.go b/vendor/github.com/docker/cli/cli/command/checkpoint/cmd.go deleted file mode 100644 index 30e9ce364..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/cmd.go +++ /dev/null @@ -1,24 +0,0 @@ -package checkpoint - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewCheckpointCommand returns the `checkpoint` subcommand (only in experimental) -func NewCheckpointCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "checkpoint", - Short: "Manage checkpoints", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"experimental": "", "version": "1.25"}, - } - cmd.AddCommand( - newCreateCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/create.go b/vendor/github.com/docker/cli/cli/command/checkpoint/create.go deleted file mode 100644 index 974b44ab8..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/create.go +++ /dev/null @@ -1,58 +0,0 @@ -package checkpoint - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -type createOptions struct { - container string - checkpoint string - checkpointDir string - leaveRunning bool -} - -func newCreateCommand(dockerCli command.Cli) *cobra.Command { - var opts createOptions - - cmd := &cobra.Command{ - Use: "create [OPTIONS] CONTAINER CHECKPOINT", - Short: "Create a checkpoint from a running container", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - opts.checkpoint = args[1] - return runCreate(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVar(&opts.leaveRunning, "leave-running", false, "Leave the container running after checkpoint") - flags.StringVarP(&opts.checkpointDir, "checkpoint-dir", "", "", "Use a custom checkpoint storage directory") - - return cmd -} - -func runCreate(dockerCli command.Cli, opts createOptions) error { - client := dockerCli.Client() - - checkpointOpts := types.CheckpointCreateOptions{ - CheckpointID: opts.checkpoint, - CheckpointDir: opts.checkpointDir, - Exit: !opts.leaveRunning, - } - - err := client.CheckpointCreate(context.Background(), opts.container, checkpointOpts) - if err != nil { - return err - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", opts.checkpoint) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/create_test.go b/vendor/github.com/docker/cli/cli/command/checkpoint/create_test.go deleted file mode 100644 index 19bd3920c..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/create_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package checkpoint - -import ( - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestCheckpointCreateErrors(t *testing.T) { - testCases := []struct { - args []string - checkpointCreateFunc func(container string, options types.CheckpointCreateOptions) error - expectedError string - }{ - { - args: []string{"too-few-arguments"}, - expectedError: "requires exactly 2 arguments", - }, - { - args: []string{"too", "many", "arguments"}, - expectedError: "requires exactly 2 arguments", - }, - { - args: []string{"foo", "bar"}, - checkpointCreateFunc: func(container string, options types.CheckpointCreateOptions) error { - return errors.Errorf("error creating checkpoint for container foo") - }, - expectedError: "error creating checkpoint for container foo", - }, - } - - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - checkpointCreateFunc: tc.checkpointCreateFunc, - }) - cmd := newCreateCommand(cli) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestCheckpointCreateWithOptions(t *testing.T) { - var containerID, checkpointID, checkpointDir string - var exit bool - cli := test.NewFakeCli(&fakeClient{ - checkpointCreateFunc: func(container string, options types.CheckpointCreateOptions) error { - containerID = container - checkpointID = options.CheckpointID - checkpointDir = options.CheckpointDir - exit = options.Exit - return nil - }, - }) - cmd := newCreateCommand(cli) - checkpoint := "checkpoint-bar" - cmd.SetArgs([]string{"container-foo", checkpoint}) - cmd.Flags().Set("leave-running", "true") - cmd.Flags().Set("checkpoint-dir", "/dir/foo") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "container-foo", containerID) - assert.Equal(t, checkpoint, checkpointID) - assert.Equal(t, "/dir/foo", checkpointDir) - assert.Equal(t, false, exit) - assert.Equal(t, checkpoint, strings.TrimSpace(cli.OutBuffer().String())) -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/list.go b/vendor/github.com/docker/cli/cli/command/checkpoint/list.go deleted file mode 100644 index 758aa6993..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/list.go +++ /dev/null @@ -1,54 +0,0 @@ -package checkpoint - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -type listOptions struct { - checkpointDir string -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - var opts listOptions - - cmd := &cobra.Command{ - Use: "ls [OPTIONS] CONTAINER", - Aliases: []string{"list"}, - Short: "List checkpoints for a container", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, args[0], opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.checkpointDir, "checkpoint-dir", "", "", "Use a custom checkpoint storage directory") - - return cmd - -} - -func runList(dockerCli command.Cli, container string, opts listOptions) error { - client := dockerCli.Client() - - listOpts := types.CheckpointListOptions{ - CheckpointDir: opts.checkpointDir, - } - - checkpoints, err := client.CheckpointList(context.Background(), container, listOpts) - if err != nil { - return err - } - - cpCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewCheckpointFormat(formatter.TableFormatKey), - } - return formatter.CheckpointWrite(cpCtx, checkpoints) -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/list_test.go b/vendor/github.com/docker/cli/cli/command/checkpoint/list_test.go deleted file mode 100644 index 373460d3b..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/list_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package checkpoint - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestCheckpointListErrors(t *testing.T) { - testCases := []struct { - args []string - checkpointListFunc func(container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) - expectedError string - }{ - { - args: []string{}, - expectedError: "requires exactly 1 argument", - }, - { - args: []string{"too", "many", "arguments"}, - expectedError: "requires exactly 1 argument", - }, - { - args: []string{"foo"}, - checkpointListFunc: func(container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) { - return []types.Checkpoint{}, errors.Errorf("error getting checkpoints for container foo") - }, - expectedError: "error getting checkpoints for container foo", - }, - } - - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - checkpointListFunc: tc.checkpointListFunc, - }) - cmd := newListCommand(cli) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestCheckpointListWithOptions(t *testing.T) { - var containerID, checkpointDir string - cli := test.NewFakeCli(&fakeClient{ - checkpointListFunc: func(container string, options types.CheckpointListOptions) ([]types.Checkpoint, error) { - containerID = container - checkpointDir = options.CheckpointDir - return []types.Checkpoint{ - {Name: "checkpoint-foo"}, - }, nil - }, - }) - cmd := newListCommand(cli) - cmd.SetArgs([]string{"container-foo"}) - cmd.Flags().Set("checkpoint-dir", "/dir/foo") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "container-foo", containerID) - assert.Equal(t, "/dir/foo", checkpointDir) - golden.Assert(t, cli.OutBuffer().String(), "checkpoint-list-with-options.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/remove.go b/vendor/github.com/docker/cli/cli/command/checkpoint/remove.go deleted file mode 100644 index 298adbaef..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/remove.go +++ /dev/null @@ -1,44 +0,0 @@ -package checkpoint - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -type removeOptions struct { - checkpointDir string -} - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - var opts removeOptions - - cmd := &cobra.Command{ - Use: "rm [OPTIONS] CONTAINER CHECKPOINT", - Aliases: []string{"remove"}, - Short: "Remove a checkpoint", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, args[0], args[1], opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.checkpointDir, "checkpoint-dir", "", "", "Use a custom checkpoint storage directory") - - return cmd -} - -func runRemove(dockerCli command.Cli, container string, checkpoint string, opts removeOptions) error { - client := dockerCli.Client() - - removeOpts := types.CheckpointDeleteOptions{ - CheckpointID: checkpoint, - CheckpointDir: opts.checkpointDir, - } - - return client.CheckpointDelete(context.Background(), container, removeOpts) -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/remove_test.go b/vendor/github.com/docker/cli/cli/command/checkpoint/remove_test.go deleted file mode 100644 index 6100d75e4..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/remove_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package checkpoint - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestCheckpointRemoveErrors(t *testing.T) { - testCases := []struct { - args []string - checkpointDeleteFunc func(container string, options types.CheckpointDeleteOptions) error - expectedError string - }{ - { - args: []string{"too-few-arguments"}, - expectedError: "requires exactly 2 arguments", - }, - { - args: []string{"too", "many", "arguments"}, - expectedError: "requires exactly 2 arguments", - }, - { - args: []string{"foo", "bar"}, - checkpointDeleteFunc: func(container string, options types.CheckpointDeleteOptions) error { - return errors.Errorf("error deleting checkpoint") - }, - expectedError: "error deleting checkpoint", - }, - } - - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - checkpointDeleteFunc: tc.checkpointDeleteFunc, - }) - cmd := newRemoveCommand(cli) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestCheckpointRemoveWithOptions(t *testing.T) { - var containerID, checkpointID, checkpointDir string - cli := test.NewFakeCli(&fakeClient{ - checkpointDeleteFunc: func(container string, options types.CheckpointDeleteOptions) error { - containerID = container - checkpointID = options.CheckpointID - checkpointDir = options.CheckpointDir - return nil - }, - }) - cmd := newRemoveCommand(cli) - cmd.SetArgs([]string{"container-foo", "checkpoint-bar"}) - cmd.Flags().Set("checkpoint-dir", "/dir/foo") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "container-foo", containerID) - assert.Equal(t, "checkpoint-bar", checkpointID) - assert.Equal(t, "/dir/foo", checkpointDir) -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/testdata/checkpoint-list-with-options.golden b/vendor/github.com/docker/cli/cli/command/checkpoint/testdata/checkpoint-list-with-options.golden deleted file mode 100644 index f53f016ae..000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/testdata/checkpoint-list-with-options.golden +++ /dev/null @@ -1,2 +0,0 @@ -CHECKPOINT NAME -checkpoint-foo diff --git a/vendor/github.com/docker/cli/cli/command/cli.go b/vendor/github.com/docker/cli/cli/command/cli.go deleted file mode 100644 index 4ac881f2d..000000000 --- a/vendor/github.com/docker/cli/cli/command/cli.go +++ /dev/null @@ -1,240 +0,0 @@ -package command - -import ( - "io" - "net" - "net/http" - "os" - "runtime" - "time" - - "github.com/docker/cli/cli" - cliconfig "github.com/docker/cli/cli/config" - "github.com/docker/cli/cli/config/configfile" - cliflags "github.com/docker/cli/cli/flags" - dopts "github.com/docker/cli/opts" - "github.com/docker/docker/api" - "github.com/docker/docker/client" - "github.com/docker/go-connections/sockets" - "github.com/docker/go-connections/tlsconfig" - "github.com/docker/notary/passphrase" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -// Streams is an interface which exposes the standard input and output streams -type Streams interface { - In() *InStream - Out() *OutStream - Err() io.Writer -} - -// Cli represents the docker command line client. -type Cli interface { - Client() client.APIClient - Out() *OutStream - Err() io.Writer - In() *InStream - SetIn(in *InStream) - ConfigFile() *configfile.ConfigFile - ServerInfo() ServerInfo -} - -// DockerCli is an instance the docker command line client. -// Instances of the client can be returned from NewDockerCli. -type DockerCli struct { - configFile *configfile.ConfigFile - in *InStream - out *OutStream - err io.Writer - client client.APIClient - defaultVersion string - server ServerInfo -} - -// DefaultVersion returns api.defaultVersion or DOCKER_API_VERSION if specified. -func (cli *DockerCli) DefaultVersion() string { - return cli.defaultVersion -} - -// Client returns the APIClient -func (cli *DockerCli) Client() client.APIClient { - return cli.client -} - -// Out returns the writer used for stdout -func (cli *DockerCli) Out() *OutStream { - return cli.out -} - -// Err returns the writer used for stderr -func (cli *DockerCli) Err() io.Writer { - return cli.err -} - -// SetIn sets the reader used for stdin -func (cli *DockerCli) SetIn(in *InStream) { - cli.in = in -} - -// In returns the reader used for stdin -func (cli *DockerCli) In() *InStream { - return cli.in -} - -// ShowHelp shows the command help. -func ShowHelp(err io.Writer) func(*cobra.Command, []string) error { - return func(cmd *cobra.Command, args []string) error { - cmd.SetOutput(err) - cmd.HelpFunc()(cmd, args) - return nil - } -} - -// ConfigFile returns the ConfigFile -func (cli *DockerCli) ConfigFile() *configfile.ConfigFile { - return cli.configFile -} - -// ServerInfo returns the server version details for the host this client is -// connected to -func (cli *DockerCli) ServerInfo() ServerInfo { - return cli.server -} - -// Initialize the dockerCli runs initialization that must happen after command -// line flags are parsed. -func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions) error { - cli.configFile = cliconfig.LoadDefaultConfigFile(cli.err) - - var err error - cli.client, err = NewAPIClientFromFlags(opts.Common, cli.configFile) - if tlsconfig.IsErrEncryptedKey(err) { - var ( - passwd string - giveup bool - ) - passRetriever := passphrase.PromptRetrieverWithInOut(cli.In(), cli.Out(), nil) - - for attempts := 0; tlsconfig.IsErrEncryptedKey(err); attempts++ { - // some code and comments borrowed from notary/trustmanager/keystore.go - passwd, giveup, err = passRetriever("private", "encrypted TLS private", false, attempts) - // Check if the passphrase retriever got an error or if it is telling us to give up - if giveup || err != nil { - return errors.Wrap(err, "private key is encrypted, but could not get passphrase") - } - - opts.Common.TLSOptions.Passphrase = passwd - cli.client, err = NewAPIClientFromFlags(opts.Common, cli.configFile) - } - } - - if err != nil { - return err - } - - cli.defaultVersion = cli.client.ClientVersion() - - if ping, err := cli.client.Ping(context.Background()); err == nil { - cli.server = ServerInfo{ - HasExperimental: ping.Experimental, - OSType: ping.OSType, - } - - cli.client.NegotiateAPIVersionPing(ping) - } else { - // Default to true if we fail to connect to daemon - cli.server = ServerInfo{HasExperimental: true} - } - - return nil -} - -// ServerInfo stores details about the supported features and platform of the -// server -type ServerInfo struct { - HasExperimental bool - OSType string -} - -// NewDockerCli returns a DockerCli instance with IO output and error streams set by in, out and err. -func NewDockerCli(in io.ReadCloser, out, err io.Writer) *DockerCli { - return &DockerCli{in: NewInStream(in), out: NewOutStream(out), err: err} -} - -// NewAPIClientFromFlags creates a new APIClient from command line flags -func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.ConfigFile) (client.APIClient, error) { - host, err := getServerHost(opts.Hosts, opts.TLSOptions) - if err != nil { - return &client.Client{}, err - } - - customHeaders := configFile.HTTPHeaders - if customHeaders == nil { - customHeaders = map[string]string{} - } - customHeaders["User-Agent"] = UserAgent() - - verStr := api.DefaultVersion - if tmpStr := os.Getenv("DOCKER_API_VERSION"); tmpStr != "" { - verStr = tmpStr - } - - httpClient, err := newHTTPClient(host, opts.TLSOptions) - if err != nil { - return &client.Client{}, err - } - - return client.NewClient(host, verStr, httpClient, customHeaders) -} - -func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (host string, err error) { - switch len(hosts) { - case 0: - host = os.Getenv("DOCKER_HOST") - case 1: - host = hosts[0] - default: - return "", errors.New("Please specify only one -H") - } - - host, err = dopts.ParseHost(tlsOptions != nil, host) - return -} - -func newHTTPClient(host string, tlsOptions *tlsconfig.Options) (*http.Client, error) { - if tlsOptions == nil { - // let the api client configure the default transport. - return nil, nil - } - opts := *tlsOptions - opts.ExclusiveRootPools = true - config, err := tlsconfig.Client(opts) - if err != nil { - return nil, err - } - tr := &http.Transport{ - TLSClientConfig: config, - DialContext: (&net.Dialer{ - KeepAlive: 30 * time.Second, - Timeout: 30 * time.Second, - }).DialContext, - } - proto, addr, _, err := client.ParseHost(host) - if err != nil { - return nil, err - } - - sockets.ConfigureTransport(tr, proto, addr) - - return &http.Client{ - Transport: tr, - CheckRedirect: client.CheckRedirect, - }, nil -} - -// UserAgent returns the user agent string used for making API requests -func UserAgent() string { - return "Docker-Client/" + cli.Version + " (" + runtime.GOOS + ")" -} diff --git a/vendor/github.com/docker/cli/cli/command/cli_test.go b/vendor/github.com/docker/cli/cli/command/cli_test.go deleted file mode 100644 index ca73a05e3..000000000 --- a/vendor/github.com/docker/cli/cli/command/cli_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package command - -import ( - "os" - "testing" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/cli/flags" - "github.com/docker/docker/api" - "github.com/docker/docker/client" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewAPIClientFromFlags(t *testing.T) { - host := "unix://path" - opts := &flags.CommonOptions{Hosts: []string{host}} - configFile := &configfile.ConfigFile{ - HTTPHeaders: map[string]string{ - "My-Header": "Custom-Value", - }, - } - apiclient, err := NewAPIClientFromFlags(opts, configFile) - require.NoError(t, err) - assert.Equal(t, host, apiclient.DaemonHost()) - - expectedHeaders := map[string]string{ - "My-Header": "Custom-Value", - "User-Agent": UserAgent(), - } - assert.Equal(t, expectedHeaders, apiclient.(*client.Client).CustomHTTPHeaders()) - assert.Equal(t, api.DefaultVersion, apiclient.ClientVersion()) -} - -func TestNewAPIClientFromFlagsWithAPIVersionFromEnv(t *testing.T) { - customVersion := "v3.3.3" - defer patchEnvVariable(t, "DOCKER_API_VERSION", customVersion)() - - opts := &flags.CommonOptions{} - configFile := &configfile.ConfigFile{} - apiclient, err := NewAPIClientFromFlags(opts, configFile) - require.NoError(t, err) - assert.Equal(t, customVersion, apiclient.ClientVersion()) -} - -// TODO: move to gotestyourself -func patchEnvVariable(t *testing.T, key, value string) func() { - oldValue, ok := os.LookupEnv(key) - require.NoError(t, os.Setenv(key, value)) - return func() { - if !ok { - require.NoError(t, os.Unsetenv(key)) - return - } - require.NoError(t, os.Setenv(key, oldValue)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/commands/commands.go b/vendor/github.com/docker/cli/cli/command/commands/commands.go deleted file mode 100644 index c6fc8d6ac..000000000 --- a/vendor/github.com/docker/cli/cli/command/commands/commands.go +++ /dev/null @@ -1,125 +0,0 @@ -package commands - -import ( - "os" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/checkpoint" - "github.com/docker/cli/cli/command/config" - "github.com/docker/cli/cli/command/container" - "github.com/docker/cli/cli/command/image" - "github.com/docker/cli/cli/command/network" - "github.com/docker/cli/cli/command/node" - "github.com/docker/cli/cli/command/plugin" - "github.com/docker/cli/cli/command/registry" - "github.com/docker/cli/cli/command/secret" - "github.com/docker/cli/cli/command/service" - "github.com/docker/cli/cli/command/stack" - "github.com/docker/cli/cli/command/swarm" - "github.com/docker/cli/cli/command/system" - "github.com/docker/cli/cli/command/volume" - "github.com/spf13/cobra" -) - -// AddCommands adds all the commands from cli/command to the root command -func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) { - cmd.AddCommand( - // checkpoint - checkpoint.NewCheckpointCommand(dockerCli), - - // config - config.NewConfigCommand(dockerCli), - - // container - container.NewContainerCommand(dockerCli), - container.NewRunCommand(dockerCli), - - // image - image.NewImageCommand(dockerCli), - image.NewBuildCommand(dockerCli), - - // node - node.NewNodeCommand(dockerCli), - - // network - network.NewNetworkCommand(dockerCli), - - // plugin - plugin.NewPluginCommand(dockerCli), - - // registry - registry.NewLoginCommand(dockerCli), - registry.NewLogoutCommand(dockerCli), - registry.NewSearchCommand(dockerCli), - - // secret - secret.NewSecretCommand(dockerCli), - - // service - service.NewServiceCommand(dockerCli), - - // system - system.NewSystemCommand(dockerCli), - system.NewVersionCommand(dockerCli), - - // stack - stack.NewStackCommand(dockerCli), - stack.NewTopLevelDeployCommand(dockerCli), - - // swarm - swarm.NewSwarmCommand(dockerCli), - - // volume - volume.NewVolumeCommand(dockerCli), - - // legacy commands may be hidden - hide(system.NewEventsCommand(dockerCli)), - hide(system.NewInfoCommand(dockerCli)), - hide(system.NewInspectCommand(dockerCli)), - hide(container.NewAttachCommand(dockerCli)), - hide(container.NewCommitCommand(dockerCli)), - hide(container.NewCopyCommand(dockerCli)), - hide(container.NewCreateCommand(dockerCli)), - hide(container.NewDiffCommand(dockerCli)), - hide(container.NewExecCommand(dockerCli)), - hide(container.NewExportCommand(dockerCli)), - hide(container.NewKillCommand(dockerCli)), - hide(container.NewLogsCommand(dockerCli)), - hide(container.NewPauseCommand(dockerCli)), - hide(container.NewPortCommand(dockerCli)), - hide(container.NewPsCommand(dockerCli)), - hide(container.NewRenameCommand(dockerCli)), - hide(container.NewRestartCommand(dockerCli)), - hide(container.NewRmCommand(dockerCli)), - hide(container.NewStartCommand(dockerCli)), - hide(container.NewStatsCommand(dockerCli)), - hide(container.NewStopCommand(dockerCli)), - hide(container.NewTopCommand(dockerCli)), - hide(container.NewUnpauseCommand(dockerCli)), - hide(container.NewUpdateCommand(dockerCli)), - hide(container.NewWaitCommand(dockerCli)), - hide(image.NewHistoryCommand(dockerCli)), - hide(image.NewImagesCommand(dockerCli)), - hide(image.NewImportCommand(dockerCli)), - hide(image.NewLoadCommand(dockerCli)), - hide(image.NewPullCommand(dockerCli)), - hide(image.NewPushCommand(dockerCli)), - hide(image.NewRemoveCommand(dockerCli)), - hide(image.NewSaveCommand(dockerCli)), - hide(image.NewTagCommand(dockerCli)), - ) - -} - -func hide(cmd *cobra.Command) *cobra.Command { - // If the environment variable with name "DOCKER_HIDE_LEGACY_COMMANDS" is not empty, - // these legacy commands (such as `docker ps`, `docker exec`, etc) - // will not be shown in output console. - if os.Getenv("DOCKER_HIDE_LEGACY_COMMANDS") == "" { - return cmd - } - cmdCopy := *cmd - cmdCopy.Hidden = true - cmdCopy.Aliases = []string{} - return &cmdCopy -} diff --git a/vendor/github.com/docker/cli/cli/command/config/client_test.go b/vendor/github.com/docker/cli/cli/command/config/client_test.go deleted file mode 100644 index fdb132184..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/client_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package config - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - configCreateFunc func(swarm.ConfigSpec) (types.ConfigCreateResponse, error) - configInspectFunc func(string) (swarm.Config, []byte, error) - configListFunc func(types.ConfigListOptions) ([]swarm.Config, error) - configRemoveFunc func(string) error -} - -func (c *fakeClient) ConfigCreate(ctx context.Context, spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) { - if c.configCreateFunc != nil { - return c.configCreateFunc(spec) - } - return types.ConfigCreateResponse{}, nil -} - -func (c *fakeClient) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) { - if c.configInspectFunc != nil { - return c.configInspectFunc(id) - } - return swarm.Config{}, nil, nil -} - -func (c *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) { - if c.configListFunc != nil { - return c.configListFunc(options) - } - return []swarm.Config{}, nil -} - -func (c *fakeClient) ConfigRemove(ctx context.Context, name string) error { - if c.configRemoveFunc != nil { - return c.configRemoveFunc(name) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/config/cmd.go b/vendor/github.com/docker/cli/cli/command/config/cmd.go deleted file mode 100644 index 1f762596c..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/cmd.go +++ /dev/null @@ -1,27 +0,0 @@ -package config - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewConfigCommand returns a cobra command for `config` subcommands -// nolint: interfacer -func NewConfigCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "config", - Short: "Manage Docker configs", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.30"}, - } - cmd.AddCommand( - newConfigListCommand(dockerCli), - newConfigCreateCommand(dockerCli), - newConfigInspectCommand(dockerCli), - newConfigRemoveCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/config/create.go b/vendor/github.com/docker/cli/cli/command/config/create.go deleted file mode 100644 index 437137c16..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/create.go +++ /dev/null @@ -1,79 +0,0 @@ -package config - -import ( - "fmt" - "io" - "io/ioutil" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/system" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type createOptions struct { - name string - file string - labels opts.ListOpts -} - -func newConfigCreateCommand(dockerCli command.Cli) *cobra.Command { - createOpts := createOptions{ - labels: opts.NewListOpts(opts.ValidateEnv), - } - - cmd := &cobra.Command{ - Use: "create [OPTIONS] CONFIG file|-", - Short: "Create a configuration file from a file or STDIN as content", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - createOpts.name = args[0] - createOpts.file = args[1] - return runConfigCreate(dockerCli, createOpts) - }, - } - flags := cmd.Flags() - flags.VarP(&createOpts.labels, "label", "l", "Config labels") - - return cmd -} - -func runConfigCreate(dockerCli command.Cli, options createOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var in io.Reader = dockerCli.In() - if options.file != "-" { - file, err := system.OpenSequential(options.file) - if err != nil { - return err - } - in = file - defer file.Close() - } - - configData, err := ioutil.ReadAll(in) - if err != nil { - return errors.Errorf("Error reading content from %q: %v", options.file, err) - } - - spec := swarm.ConfigSpec{ - Annotations: swarm.Annotations{ - Name: options.name, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - }, - Data: configData, - } - - r, err := client.ConfigCreate(ctx, spec) - if err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), r.ID) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/config/create_test.go b/vendor/github.com/docker/cli/cli/command/config/create_test.go deleted file mode 100644 index 7bde47e69..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/create_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package config - -import ( - "io/ioutil" - "path/filepath" - "reflect" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -const configDataFile = "config-create-with-name.golden" - -func TestConfigCreateErrors(t *testing.T) { - testCases := []struct { - args []string - configCreateFunc func(swarm.ConfigSpec) (types.ConfigCreateResponse, error) - expectedError string - }{ - { - args: []string{"too_few"}, - expectedError: "requires exactly 2 arguments", - }, - {args: []string{"too", "many", "arguments"}, - expectedError: "requires exactly 2 arguments", - }, - { - args: []string{"name", filepath.Join("testdata", configDataFile)}, - configCreateFunc: func(configSpec swarm.ConfigSpec) (types.ConfigCreateResponse, error) { - return types.ConfigCreateResponse{}, errors.Errorf("error creating config") - }, - expectedError: "error creating config", - }, - } - for _, tc := range testCases { - cmd := newConfigCreateCommand( - test.NewFakeCli(&fakeClient{ - configCreateFunc: tc.configCreateFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestConfigCreateWithName(t *testing.T) { - name := "foo" - var actual []byte - cli := test.NewFakeCli(&fakeClient{ - configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) { - if spec.Name != name { - return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name) - } - - actual = spec.Data - - return types.ConfigCreateResponse{ - ID: "ID-" + spec.Name, - }, nil - }, - }) - - cmd := newConfigCreateCommand(cli) - cmd.SetArgs([]string{name, filepath.Join("testdata", configDataFile)}) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, string(actual), configDataFile) - assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String())) -} - -func TestConfigCreateWithLabels(t *testing.T) { - expectedLabels := map[string]string{ - "lbl1": "Label-foo", - "lbl2": "Label-bar", - } - name := "foo" - - cli := test.NewFakeCli(&fakeClient{ - configCreateFunc: func(spec swarm.ConfigSpec) (types.ConfigCreateResponse, error) { - if spec.Name != name { - return types.ConfigCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name) - } - - if !reflect.DeepEqual(spec.Labels, expectedLabels) { - return types.ConfigCreateResponse{}, errors.Errorf("expected labels %v, got %v", expectedLabels, spec.Labels) - } - - return types.ConfigCreateResponse{ - ID: "ID-" + spec.Name, - }, nil - }, - }) - - cmd := newConfigCreateCommand(cli) - cmd.SetArgs([]string{name, filepath.Join("testdata", configDataFile)}) - cmd.Flags().Set("label", "lbl1=Label-foo") - cmd.Flags().Set("label", "lbl2=Label-bar") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String())) -} diff --git a/vendor/github.com/docker/cli/cli/command/config/inspect.go b/vendor/github.com/docker/cli/cli/command/config/inspect.go deleted file mode 100644 index d7a3422a7..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/inspect.go +++ /dev/null @@ -1,66 +0,0 @@ -package config - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - names []string - format string - pretty bool -} - -func newConfigInspectCommand(dockerCli command.Cli) *cobra.Command { - opts := inspectOptions{} - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] CONFIG [CONFIG...]", - Short: "Display detailed information on one or more configuration files", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.names = args - return runConfigInspect(dockerCli, opts) - }, - } - - cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - cmd.Flags().BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runConfigInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(id string) (interface{}, []byte, error) { - return client.ConfigInspectWithRaw(ctx, id) - } - f := opts.format - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return fmt.Errorf("Cannot supply extra formatting options to the pretty template") - } - - configCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewConfigFormat(f, false), - } - - if err := formatter.ConfigInspectWrite(configCtx, opts.names, getRef); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil - -} diff --git a/vendor/github.com/docker/cli/cli/command/config/inspect_test.go b/vendor/github.com/docker/cli/cli/command/config/inspect_test.go deleted file mode 100644 index 5ff280fd2..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/inspect_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package config - -import ( - "fmt" - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestConfigInspectErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - configInspectFunc func(configID string) (swarm.Config, []byte, error) - expectedError string - }{ - { - expectedError: "requires at least 1 argument", - }, - { - args: []string{"foo"}, - configInspectFunc: func(configID string) (swarm.Config, []byte, error) { - return swarm.Config{}, nil, errors.Errorf("error while inspecting the config") - }, - expectedError: "error while inspecting the config", - }, - { - args: []string{"foo"}, - flags: map[string]string{ - "format": "{{invalid format}}", - }, - expectedError: "Template parsing error", - }, - { - args: []string{"foo", "bar"}, - configInspectFunc: func(configID string) (swarm.Config, []byte, error) { - if configID == "foo" { - return *Config(ConfigName("foo")), nil, nil - } - return swarm.Config{}, nil, errors.Errorf("error while inspecting the config") - }, - expectedError: "error while inspecting the config", - }, - } - for _, tc := range testCases { - cmd := newConfigInspectCommand( - test.NewFakeCli(&fakeClient{ - configInspectFunc: tc.configInspectFunc, - }), - ) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestConfigInspectWithoutFormat(t *testing.T) { - testCases := []struct { - name string - args []string - configInspectFunc func(configID string) (swarm.Config, []byte, error) - }{ - { - name: "single-config", - args: []string{"foo"}, - configInspectFunc: func(name string) (swarm.Config, []byte, error) { - if name != "foo" { - return swarm.Config{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name) - } - return *Config(ConfigID("ID-foo"), ConfigName("foo")), nil, nil - }, - }, - { - name: "multiple-configs-with-labels", - args: []string{"foo", "bar"}, - configInspectFunc: func(name string) (swarm.Config, []byte, error) { - return *Config(ConfigID("ID-"+name), ConfigName(name), ConfigLabels(map[string]string{ - "label1": "label-foo", - })), nil, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{configInspectFunc: tc.configInspectFunc}) - cmd := newConfigInspectCommand(cli) - cmd.SetArgs(tc.args) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-without-format.%s.golden", tc.name)) - } -} - -func TestConfigInspectWithFormat(t *testing.T) { - configInspectFunc := func(name string) (swarm.Config, []byte, error) { - return *Config(ConfigName("foo"), ConfigLabels(map[string]string{ - "label1": "label-foo", - })), nil, nil - } - testCases := []struct { - name string - format string - args []string - configInspectFunc func(name string) (swarm.Config, []byte, error) - }{ - { - name: "simple-template", - format: "{{.Spec.Name}}", - args: []string{"foo"}, - configInspectFunc: configInspectFunc, - }, - { - name: "json-template", - format: "{{json .Spec.Labels}}", - args: []string{"foo"}, - configInspectFunc: configInspectFunc, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - configInspectFunc: tc.configInspectFunc, - }) - cmd := newConfigInspectCommand(cli) - cmd.SetArgs(tc.args) - cmd.Flags().Set("format", tc.format) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-with-format.%s.golden", tc.name)) - } -} - -func TestConfigInspectPretty(t *testing.T) { - testCases := []struct { - name string - configInspectFunc func(string) (swarm.Config, []byte, error) - }{ - { - name: "simple", - configInspectFunc: func(id string) (swarm.Config, []byte, error) { - return *Config( - ConfigLabels(map[string]string{ - "lbl1": "value1", - }), - ConfigID("configID"), - ConfigName("configName"), - ConfigCreatedAt(time.Time{}), - ConfigUpdatedAt(time.Time{}), - ConfigData([]byte("payload here")), - ), []byte{}, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - configInspectFunc: tc.configInspectFunc, - }) - cmd := newConfigInspectCommand(cli) - - cmd.SetArgs([]string{"configID"}) - cmd.Flags().Set("pretty", "true") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("config-inspect-pretty.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/config/ls.go b/vendor/github.com/docker/cli/cli/command/config/ls.go deleted file mode 100644 index f01e3b915..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/ls.go +++ /dev/null @@ -1,63 +0,0 @@ -package config - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newConfigListCommand(dockerCli command.Cli) *cobra.Command { - listOpts := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List configs", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runConfigList(dockerCli, listOpts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&listOpts.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVarP(&listOpts.format, "format", "", "", "Pretty-print configs using a Go template") - flags.VarP(&listOpts.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runConfigList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - configs, err := client.ConfigList(ctx, types.ConfigListOptions{Filters: options.filter.Value()}) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().ConfigFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().ConfigFormat - } else { - format = formatter.TableFormatKey - } - } - - configCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewConfigFormat(format, options.quiet), - } - return formatter.ConfigWrite(configCtx, configs) -} diff --git a/vendor/github.com/docker/cli/cli/command/config/ls_test.go b/vendor/github.com/docker/cli/cli/command/config/ls_test.go deleted file mode 100644 index ac351cc72..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/ls_test.go +++ /dev/null @@ -1,153 +0,0 @@ -package config - -import ( - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestConfigListErrors(t *testing.T) { - testCases := []struct { - args []string - configListFunc func(types.ConfigListOptions) ([]swarm.Config, error) - expectedError string - }{ - { - args: []string{"foo"}, - expectedError: "accepts no argument", - }, - { - configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) { - return []swarm.Config{}, errors.Errorf("error listing configs") - }, - expectedError: "error listing configs", - }, - } - for _, tc := range testCases { - cmd := newConfigListCommand( - test.NewFakeCli(&fakeClient{ - configListFunc: tc.configListFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestConfigList(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) { - return []swarm.Config{ - *Config(ConfigID("ID-foo"), - ConfigName("foo"), - ConfigVersion(swarm.Version{Index: 10}), - ConfigCreatedAt(time.Now().Add(-2*time.Hour)), - ConfigUpdatedAt(time.Now().Add(-1*time.Hour)), - ), - *Config(ConfigID("ID-bar"), - ConfigName("bar"), - ConfigVersion(swarm.Version{Index: 11}), - ConfigCreatedAt(time.Now().Add(-2*time.Hour)), - ConfigUpdatedAt(time.Now().Add(-1*time.Hour)), - ), - }, nil - }, - }) - cmd := newConfigListCommand(cli) - cmd.SetOutput(cli.OutBuffer()) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "config-list.golden") -} - -func TestConfigListWithQuietOption(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) { - return []swarm.Config{ - *Config(ConfigID("ID-foo"), ConfigName("foo")), - *Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{ - "label": "label-bar", - })), - }, nil - }, - }) - cmd := newConfigListCommand(cli) - cmd.Flags().Set("quiet", "true") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "config-list-with-quiet-option.golden") -} - -func TestConfigListWithConfigFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) { - return []swarm.Config{ - *Config(ConfigID("ID-foo"), ConfigName("foo")), - *Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{ - "label": "label-bar", - })), - }, nil - }, - }) - cli.SetConfigFile(&configfile.ConfigFile{ - ConfigFormat: "{{ .Name }} {{ .Labels }}", - }) - cmd := newConfigListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "config-list-with-config-format.golden") -} - -func TestConfigListWithFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) { - return []swarm.Config{ - *Config(ConfigID("ID-foo"), ConfigName("foo")), - *Config(ConfigID("ID-bar"), ConfigName("bar"), ConfigLabels(map[string]string{ - "label": "label-bar", - })), - }, nil - }, - }) - cmd := newConfigListCommand(cli) - cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "config-list-with-format.golden") -} - -func TestConfigListWithFilter(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - configListFunc: func(options types.ConfigListOptions) ([]swarm.Config, error) { - assert.Equal(t, "foo", options.Filters.Get("name")[0]) - assert.Equal(t, "lbl1=Label-bar", options.Filters.Get("label")[0]) - return []swarm.Config{ - *Config(ConfigID("ID-foo"), - ConfigName("foo"), - ConfigVersion(swarm.Version{Index: 10}), - ConfigCreatedAt(time.Now().Add(-2*time.Hour)), - ConfigUpdatedAt(time.Now().Add(-1*time.Hour)), - ), - *Config(ConfigID("ID-bar"), - ConfigName("bar"), - ConfigVersion(swarm.Version{Index: 11}), - ConfigCreatedAt(time.Now().Add(-2*time.Hour)), - ConfigUpdatedAt(time.Now().Add(-1*time.Hour)), - ), - }, nil - }, - }) - cmd := newConfigListCommand(cli) - cmd.Flags().Set("filter", "name=foo") - cmd.Flags().Set("filter", "label=lbl1=Label-bar") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "config-list-with-filter.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/config/remove.go b/vendor/github.com/docker/cli/cli/command/config/remove.go deleted file mode 100644 index 5512986d9..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/remove.go +++ /dev/null @@ -1,53 +0,0 @@ -package config - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type removeOptions struct { - names []string -} - -func newConfigRemoveCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "rm CONFIG [CONFIG...]", - Aliases: []string{"remove"}, - Short: "Remove one or more configuration files", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts := removeOptions{ - names: args, - } - return runConfigRemove(dockerCli, opts) - }, - } -} - -func runConfigRemove(dockerCli command.Cli, opts removeOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - - for _, name := range opts.names { - if err := client.ConfigRemove(ctx, name); err != nil { - errs = append(errs, err.Error()) - continue - } - - fmt.Fprintln(dockerCli.Out(), name) - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/config/remove_test.go b/vendor/github.com/docker/cli/cli/command/config/remove_test.go deleted file mode 100644 index f7142a256..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/remove_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package config - -import ( - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestConfigRemoveErrors(t *testing.T) { - testCases := []struct { - args []string - configRemoveFunc func(string) error - expectedError string - }{ - { - args: []string{}, - expectedError: "requires at least 1 argument.", - }, - { - args: []string{"foo"}, - configRemoveFunc: func(name string) error { - return errors.Errorf("error removing config") - }, - expectedError: "error removing config", - }, - } - for _, tc := range testCases { - cmd := newConfigRemoveCommand( - test.NewFakeCli(&fakeClient{ - configRemoveFunc: tc.configRemoveFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestConfigRemoveWithName(t *testing.T) { - names := []string{"foo", "bar"} - var removedConfigs []string - cli := test.NewFakeCli(&fakeClient{ - configRemoveFunc: func(name string) error { - removedConfigs = append(removedConfigs, name) - return nil - }, - }) - cmd := newConfigRemoveCommand(cli) - cmd.SetArgs(names) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, names, strings.Split(strings.TrimSpace(cli.OutBuffer().String()), "\n")) - assert.Equal(t, names, removedConfigs) -} - -func TestConfigRemoveContinueAfterError(t *testing.T) { - names := []string{"foo", "bar"} - var removedConfigs []string - - cli := test.NewFakeCli(&fakeClient{ - configRemoveFunc: func(name string) error { - removedConfigs = append(removedConfigs, name) - if name == "foo" { - return errors.Errorf("error removing config: %s", name) - } - return nil - }, - }) - - cmd := newConfigRemoveCommand(cli) - cmd.SetArgs(names) - cmd.SetOutput(ioutil.Discard) - assert.EqualError(t, cmd.Execute(), "error removing config: foo") - assert.Equal(t, names, removedConfigs) -} diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-create-with-name.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-create-with-name.golden deleted file mode 100644 index 7b28bb3f3..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-create-with-name.golden +++ /dev/null @@ -1 +0,0 @@ -config_foo_bar diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-pretty.simple.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-pretty.simple.golden deleted file mode 100644 index 60b5c7fa4..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-pretty.simple.golden +++ /dev/null @@ -1,8 +0,0 @@ -ID: configID -Name: configName -Labels: - - lbl1=value1 -Created at: 0001-01-01 00:00:00 +0000 utc -Updated at: 0001-01-01 00:00:00 +0000 utc -Data: -payload here diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-with-format.json-template.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-with-format.json-template.golden deleted file mode 100644 index aab678f85..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-with-format.json-template.golden +++ /dev/null @@ -1 +0,0 @@ -{"label1":"label-foo"} diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-with-format.simple-template.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-with-format.simple-template.golden deleted file mode 100644 index 257cc5642..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-with-format.simple-template.golden +++ /dev/null @@ -1 +0,0 @@ -foo diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-without-format.multiple-configs-with-labels.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-without-format.multiple-configs-with-labels.golden deleted file mode 100644 index b01a400c5..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-without-format.multiple-configs-with-labels.golden +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "ID": "ID-foo", - "Version": {}, - "CreatedAt": "0001-01-01T00:00:00Z", - "UpdatedAt": "0001-01-01T00:00:00Z", - "Spec": { - "Name": "foo", - "Labels": { - "label1": "label-foo" - } - } - }, - { - "ID": "ID-bar", - "Version": {}, - "CreatedAt": "0001-01-01T00:00:00Z", - "UpdatedAt": "0001-01-01T00:00:00Z", - "Spec": { - "Name": "bar", - "Labels": { - "label1": "label-foo" - } - } - } -] diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-without-format.single-config.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-without-format.single-config.golden deleted file mode 100644 index c4f41c106..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-inspect-without-format.single-config.golden +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "ID": "ID-foo", - "Version": {}, - "CreatedAt": "0001-01-01T00:00:00Z", - "UpdatedAt": "0001-01-01T00:00:00Z", - "Spec": { - "Name": "foo", - "Labels": null - } - } -] diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-config-format.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-config-format.golden deleted file mode 100644 index 11c39229b..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-config-format.golden +++ /dev/null @@ -1,2 +0,0 @@ -foo -bar label=label-bar diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-filter.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-filter.golden deleted file mode 100644 index 29983de8e..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-filter.golden +++ /dev/null @@ -1,3 +0,0 @@ -ID NAME CREATED UPDATED -ID-foo foo 2 hours ago About an hour ago -ID-bar bar 2 hours ago About an hour ago diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-format.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-format.golden deleted file mode 100644 index 11c39229b..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-format.golden +++ /dev/null @@ -1,2 +0,0 @@ -foo -bar label=label-bar diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-quiet-option.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-quiet-option.golden deleted file mode 100644 index 83fb6e897..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list-with-quiet-option.golden +++ /dev/null @@ -1,2 +0,0 @@ -ID-foo -ID-bar diff --git a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list.golden b/vendor/github.com/docker/cli/cli/command/config/testdata/config-list.golden deleted file mode 100644 index 29983de8e..000000000 --- a/vendor/github.com/docker/cli/cli/command/config/testdata/config-list.golden +++ /dev/null @@ -1,3 +0,0 @@ -ID NAME CREATED UPDATED -ID-foo foo 2 hours ago About an hour ago -ID-bar bar 2 hours ago About an hour ago diff --git a/vendor/github.com/docker/cli/cli/command/container/attach.go b/vendor/github.com/docker/cli/cli/command/container/attach.go deleted file mode 100644 index 6e4628d95..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/attach.go +++ /dev/null @@ -1,175 +0,0 @@ -package container - -import ( - "io" - "net/http/httputil" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/signal" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type attachOptions struct { - noStdin bool - proxy bool - detachKeys string - - container string -} - -func inspectContainerAndCheckState(ctx context.Context, cli client.APIClient, args string) (*types.ContainerJSON, error) { - c, err := cli.ContainerInspect(ctx, args) - if err != nil { - return nil, err - } - if !c.State.Running { - return nil, errors.New("You cannot attach to a stopped container, start it first") - } - if c.State.Paused { - return nil, errors.New("You cannot attach to a paused container, unpause it first") - } - if c.State.Restarting { - return nil, errors.New("You cannot attach to a restarting container, wait until it is running") - } - - return &c, nil -} - -// NewAttachCommand creates a new cobra.Command for `docker attach` -func NewAttachCommand(dockerCli command.Cli) *cobra.Command { - var opts attachOptions - - cmd := &cobra.Command{ - Use: "attach [OPTIONS] CONTAINER", - Short: "Attach local standard input, output, and error streams to a running container", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - return runAttach(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.BoolVar(&opts.noStdin, "no-stdin", false, "Do not attach STDIN") - flags.BoolVar(&opts.proxy, "sig-proxy", true, "Proxy all received signals to the process") - flags.StringVar(&opts.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container") - return cmd -} - -func runAttach(dockerCli command.Cli, opts *attachOptions) error { - ctx := context.Background() - client := dockerCli.Client() - - c, err := inspectContainerAndCheckState(ctx, client, opts.container) - if err != nil { - return err - } - - if err := dockerCli.In().CheckTty(!opts.noStdin, c.Config.Tty); err != nil { - return err - } - - if opts.detachKeys != "" { - dockerCli.ConfigFile().DetachKeys = opts.detachKeys - } - - options := types.ContainerAttachOptions{ - Stream: true, - Stdin: !opts.noStdin && c.Config.OpenStdin, - Stdout: true, - Stderr: true, - DetachKeys: dockerCli.ConfigFile().DetachKeys, - } - - var in io.ReadCloser - if options.Stdin { - in = dockerCli.In() - } - - if opts.proxy && !c.Config.Tty { - sigc := ForwardAllSignals(ctx, dockerCli, opts.container) - defer signal.StopCatch(sigc) - } - - resp, errAttach := client.ContainerAttach(ctx, opts.container, options) - if errAttach != nil && errAttach != httputil.ErrPersistEOF { - // ContainerAttach returns an ErrPersistEOF (connection closed) - // means server met an error and put it in Hijacked connection - // keep the error and read detailed error message from hijacked connection later - return errAttach - } - defer resp.Close() - - // If use docker attach command to attach to a stop container, it will return - // "You cannot attach to a stopped container" error, it's ok, but when - // attach to a running container, it(docker attach) use inspect to check - // the container's state, if it pass the state check on the client side, - // and then the container is stopped, docker attach command still attach to - // the container and not exit. - // - // Recheck the container's state to avoid attach block. - _, err = inspectContainerAndCheckState(ctx, client, opts.container) - if err != nil { - return err - } - - if c.Config.Tty && dockerCli.Out().IsTerminal() { - resizeTTY(ctx, dockerCli, opts.container) - } - - streamer := hijackedIOStreamer{ - streams: dockerCli, - inputStream: in, - outputStream: dockerCli.Out(), - errorStream: dockerCli.Err(), - resp: resp, - tty: c.Config.Tty, - detachKeys: options.DetachKeys, - } - - if err := streamer.stream(ctx); err != nil { - return err - } - - if errAttach != nil { - return errAttach - } - return getExitStatus(ctx, dockerCli.Client(), opts.container) -} - -func resizeTTY(ctx context.Context, dockerCli command.Cli, containerID string) { - height, width := dockerCli.Out().GetTtySize() - // To handle the case where a user repeatedly attaches/detaches without resizing their - // terminal, the only way to get the shell prompt to display for attaches 2+ is to artificially - // resize it, then go back to normal. Without this, every attach after the first will - // require the user to manually resize or hit enter. - resizeTtyTo(ctx, dockerCli.Client(), containerID, height+1, width+1, false) - - // After the above resizing occurs, the call to MonitorTtySize below will handle resetting back - // to the actual size. - if err := MonitorTtySize(ctx, dockerCli, containerID, false); err != nil { - logrus.Debugf("Error monitoring TTY size: %s", err) - } -} - -func getExitStatus(ctx context.Context, apiclient client.ContainerAPIClient, containerID string) error { - container, err := apiclient.ContainerInspect(ctx, containerID) - if err != nil { - // If we can't connect, then the daemon probably died. - if !client.IsErrConnectionFailed(err) { - return err - } - return cli.StatusError{StatusCode: -1} - } - status := container.State.ExitCode - if status != 0 { - return cli.StatusError{StatusCode: status} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/attach_test.go b/vendor/github.com/docker/cli/cli/command/container/attach_test.go deleted file mode 100644 index 1ca775c6d..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/attach_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package container - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/cli" - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestNewAttachCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - containerInspectFunc func(img string) (types.ContainerJSON, error) - }{ - { - name: "client-error", - args: []string{"5cb5bb5e4a3b"}, - expectedError: "something went wrong", - containerInspectFunc: func(containerID string) (types.ContainerJSON, error) { - return types.ContainerJSON{}, errors.Errorf("something went wrong") - }, - }, - { - name: "client-stopped", - args: []string{"5cb5bb5e4a3b"}, - expectedError: "You cannot attach to a stopped container", - containerInspectFunc: func(containerID string) (types.ContainerJSON, error) { - c := types.ContainerJSON{} - c.ContainerJSONBase = &types.ContainerJSONBase{} - c.ContainerJSONBase.State = &types.ContainerState{Running: false} - return c, nil - }, - }, - { - name: "client-paused", - args: []string{"5cb5bb5e4a3b"}, - expectedError: "You cannot attach to a paused container", - containerInspectFunc: func(containerID string) (types.ContainerJSON, error) { - c := types.ContainerJSON{} - c.ContainerJSONBase = &types.ContainerJSONBase{} - c.ContainerJSONBase.State = &types.ContainerState{ - Running: true, - Paused: true, - } - return c, nil - }, - }, - { - name: "client-restarting", - args: []string{"5cb5bb5e4a3b"}, - expectedError: "You cannot attach to a restarting container", - containerInspectFunc: func(containerID string) (types.ContainerJSON, error) { - c := types.ContainerJSON{} - c.ContainerJSONBase = &types.ContainerJSONBase{} - c.ContainerJSONBase.State = &types.ContainerState{ - Running: true, - Paused: false, - Restarting: true, - } - return c, nil - }, - }, - } - for _, tc := range testCases { - cmd := NewAttachCommand(test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestGetExitStatus(t *testing.T) { - containerID := "the exec id" - expecatedErr := errors.New("unexpected error") - - testcases := []struct { - inspectError error - exitCode int - expectedError error - }{ - { - inspectError: nil, - exitCode: 0, - }, - { - inspectError: expecatedErr, - expectedError: expecatedErr, - }, - { - exitCode: 15, - expectedError: cli.StatusError{StatusCode: 15}, - }, - } - - for _, testcase := range testcases { - client := &fakeClient{ - inspectFunc: func(id string) (types.ContainerJSON, error) { - assert.Equal(t, containerID, id) - return types.ContainerJSON{ - ContainerJSONBase: &types.ContainerJSONBase{ - State: &types.ContainerState{ExitCode: testcase.exitCode}, - }, - }, testcase.inspectError - }, - } - err := getExitStatus(context.Background(), client, containerID) - assert.Equal(t, testcase.expectedError, err) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/container/client_test.go b/vendor/github.com/docker/cli/cli/command/container/client_test.go deleted file mode 100644 index 875fee704..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/client_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package container - -import ( - "io" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - inspectFunc func(string) (types.ContainerJSON, error) - execInspectFunc func(execID string) (types.ContainerExecInspect, error) - execCreateFunc func(container string, config types.ExecConfig) (types.IDResponse, error) - createContainerFunc func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error) - imageCreateFunc func(parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) - infoFunc func() (types.Info, error) -} - -func (f *fakeClient) ContainerInspect(_ context.Context, containerID string) (types.ContainerJSON, error) { - if f.inspectFunc != nil { - return f.inspectFunc(containerID) - } - return types.ContainerJSON{}, nil -} - -func (f *fakeClient) ContainerExecCreate(_ context.Context, container string, config types.ExecConfig) (types.IDResponse, error) { - if f.execCreateFunc != nil { - return f.execCreateFunc(container, config) - } - return types.IDResponse{}, nil -} - -func (f *fakeClient) ContainerExecInspect(_ context.Context, execID string) (types.ContainerExecInspect, error) { - if f.execInspectFunc != nil { - return f.execInspectFunc(execID) - } - return types.ContainerExecInspect{}, nil -} - -func (f *fakeClient) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error { - return nil -} - -func (f *fakeClient) ContainerCreate( - _ context.Context, - config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - containerName string, -) (container.ContainerCreateCreatedBody, error) { - if f.createContainerFunc != nil { - return f.createContainerFunc(config, hostConfig, networkingConfig, containerName) - } - return container.ContainerCreateCreatedBody{}, nil -} - -func (f *fakeClient) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) { - if f.imageCreateFunc != nil { - return f.imageCreateFunc(parentReference, options) - } - return nil, nil -} - -func (f *fakeClient) Info(_ context.Context) (types.Info, error) { - if f.infoFunc != nil { - return f.infoFunc() - } - return types.Info{}, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/cmd.go b/vendor/github.com/docker/cli/cli/command/container/cmd.go deleted file mode 100644 index 82500be02..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/cmd.go +++ /dev/null @@ -1,46 +0,0 @@ -package container - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewContainerCommand returns a cobra command for `container` subcommands -// nolint: interfacer -func NewContainerCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "container", - Short: "Manage containers", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - } - cmd.AddCommand( - NewAttachCommand(dockerCli), - NewCommitCommand(dockerCli), - NewCopyCommand(dockerCli), - NewCreateCommand(dockerCli), - NewDiffCommand(dockerCli), - NewExecCommand(dockerCli), - NewExportCommand(dockerCli), - NewKillCommand(dockerCli), - NewLogsCommand(dockerCli), - NewPauseCommand(dockerCli), - NewPortCommand(dockerCli), - NewRenameCommand(dockerCli), - NewRestartCommand(dockerCli), - NewRmCommand(dockerCli), - NewRunCommand(dockerCli), - NewStartCommand(dockerCli), - NewStatsCommand(dockerCli), - NewStopCommand(dockerCli), - NewTopCommand(dockerCli), - NewUnpauseCommand(dockerCli), - NewUpdateCommand(dockerCli), - NewWaitCommand(dockerCli), - newListCommand(dockerCli), - newInspectCommand(dockerCli), - NewPruneCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/container/commit.go b/vendor/github.com/docker/cli/cli/command/container/commit.go deleted file mode 100644 index 689918e08..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/commit.go +++ /dev/null @@ -1,75 +0,0 @@ -package container - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type commitOptions struct { - container string - reference string - - pause bool - comment string - author string - changes opts.ListOpts -} - -// NewCommitCommand creates a new cobra.Command for `docker commit` -func NewCommitCommand(dockerCli *command.DockerCli) *cobra.Command { - var options commitOptions - - cmd := &cobra.Command{ - Use: "commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]", - Short: "Create a new image from a container's changes", - Args: cli.RequiresRangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - options.container = args[0] - if len(args) > 1 { - options.reference = args[1] - } - return runCommit(dockerCli, &options) - }, - } - - flags := cmd.Flags() - flags.SetInterspersed(false) - - flags.BoolVarP(&options.pause, "pause", "p", true, "Pause container during commit") - flags.StringVarP(&options.comment, "message", "m", "", "Commit message") - flags.StringVarP(&options.author, "author", "a", "", "Author (e.g., \"John Hannibal Smith \")") - - options.changes = opts.NewListOpts(nil) - flags.VarP(&options.changes, "change", "c", "Apply Dockerfile instruction to the created image") - - return cmd -} - -func runCommit(dockerCli *command.DockerCli, options *commitOptions) error { - ctx := context.Background() - - name := options.container - reference := options.reference - - commitOptions := types.ContainerCommitOptions{ - Reference: reference, - Comment: options.comment, - Author: options.author, - Changes: options.changes.GetAll(), - Pause: options.pause, - } - - response, err := dockerCli.Client().ContainerCommit(ctx, name, commitOptions) - if err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), response.ID) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/cp.go b/vendor/github.com/docker/cli/cli/command/container/cp.go deleted file mode 100644 index 17a403013..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/cp.go +++ /dev/null @@ -1,305 +0,0 @@ -package container - -import ( - "io" - "os" - "path/filepath" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/system" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type copyOptions struct { - source string - destination string - followLink bool - copyUIDGID bool -} - -type copyDirection int - -const ( - fromContainer copyDirection = (1 << iota) - toContainer - acrossContainers = fromContainer | toContainer -) - -type cpConfig struct { - followLink bool -} - -// NewCopyCommand creates a new `docker cp` command -func NewCopyCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts copyOptions - - cmd := &cobra.Command{ - Use: `cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- - docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH`, - Short: "Copy files/folders between a container and the local filesystem", - Long: strings.Join([]string{ - "Copy files/folders between a container and the local filesystem\n", - "\nUse '-' as the source to read a tar archive from stdin\n", - "and extract it to a directory destination in a container.\n", - "Use '-' as the destination to stream a tar archive of a\n", - "container source to stdout.", - }, ""), - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - if args[0] == "" { - return errors.New("source can not be empty") - } - if args[1] == "" { - return errors.New("destination can not be empty") - } - opts.source = args[0] - opts.destination = args[1] - return runCopy(dockerCli, opts) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&opts.followLink, "follow-link", "L", false, "Always follow symbol link in SRC_PATH") - flags.BoolVarP(&opts.copyUIDGID, "archive", "a", false, "Archive mode (copy all uid/gid information)") - - return cmd -} - -func runCopy(dockerCli *command.DockerCli, opts copyOptions) error { - srcContainer, srcPath := splitCpArg(opts.source) - dstContainer, dstPath := splitCpArg(opts.destination) - - var direction copyDirection - if srcContainer != "" { - direction |= fromContainer - } - if dstContainer != "" { - direction |= toContainer - } - - cpParam := &cpConfig{ - followLink: opts.followLink, - } - - ctx := context.Background() - - switch direction { - case fromContainer: - return copyFromContainer(ctx, dockerCli, srcContainer, srcPath, dstPath, cpParam) - case toContainer: - return copyToContainer(ctx, dockerCli, srcPath, dstContainer, dstPath, cpParam, opts.copyUIDGID) - case acrossContainers: - // Copying between containers isn't supported. - return errors.New("copying between containers is not supported") - default: - // User didn't specify any container. - return errors.New("must specify at least one container source") - } -} - -func statContainerPath(ctx context.Context, dockerCli *command.DockerCli, containerName, path string) (types.ContainerPathStat, error) { - return dockerCli.Client().ContainerStatPath(ctx, containerName, path) -} - -func resolveLocalPath(localPath string) (absPath string, err error) { - if absPath, err = filepath.Abs(localPath); err != nil { - return - } - - return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil -} - -func copyFromContainer(ctx context.Context, dockerCli *command.DockerCli, srcContainer, srcPath, dstPath string, cpParam *cpConfig) (err error) { - if dstPath != "-" { - // Get an absolute destination path. - dstPath, err = resolveLocalPath(dstPath) - if err != nil { - return err - } - } - - // if client requests to follow symbol link, then must decide target file to be copied - var rebaseName string - if cpParam.followLink { - srcStat, err := statContainerPath(ctx, dockerCli, srcContainer, srcPath) - - // If the destination is a symbolic link, we should follow it. - if err == nil && srcStat.Mode&os.ModeSymlink != 0 { - linkTarget := srcStat.LinkTarget - if !system.IsAbs(linkTarget) { - // Join with the parent directory. - srcParent, _ := archive.SplitPathDirEntry(srcPath) - linkTarget = filepath.Join(srcParent, linkTarget) - } - - linkTarget, rebaseName = archive.GetRebaseName(srcPath, linkTarget) - srcPath = linkTarget - } - - } - - content, stat, err := dockerCli.Client().CopyFromContainer(ctx, srcContainer, srcPath) - if err != nil { - return err - } - defer content.Close() - - if dstPath == "-" { - // Send the response to STDOUT. - _, err = io.Copy(os.Stdout, content) - - return err - } - - // Prepare source copy info. - srcInfo := archive.CopyInfo{ - Path: srcPath, - Exists: true, - IsDir: stat.Mode.IsDir(), - RebaseName: rebaseName, - } - - preArchive := content - if len(srcInfo.RebaseName) != 0 { - _, srcBase := archive.SplitPathDirEntry(srcInfo.Path) - preArchive = archive.RebaseArchiveEntries(content, srcBase, srcInfo.RebaseName) - } - // See comments in the implementation of `archive.CopyTo` for exactly what - // goes into deciding how and whether the source archive needs to be - // altered for the correct copy behavior. - return archive.CopyTo(preArchive, srcInfo, dstPath) -} - -func copyToContainer(ctx context.Context, dockerCli *command.DockerCli, srcPath, dstContainer, dstPath string, cpParam *cpConfig, copyUIDGID bool) (err error) { - if srcPath != "-" { - // Get an absolute source path. - srcPath, err = resolveLocalPath(srcPath) - if err != nil { - return err - } - } - - // In order to get the copy behavior right, we need to know information - // about both the source and destination. The API is a simple tar - // archive/extract API but we can use the stat info header about the - // destination to be more informed about exactly what the destination is. - - // Prepare destination copy info by stat-ing the container path. - dstInfo := archive.CopyInfo{Path: dstPath} - dstStat, err := statContainerPath(ctx, dockerCli, dstContainer, dstPath) - - // If the destination is a symbolic link, we should evaluate it. - if err == nil && dstStat.Mode&os.ModeSymlink != 0 { - linkTarget := dstStat.LinkTarget - if !system.IsAbs(linkTarget) { - // Join with the parent directory. - dstParent, _ := archive.SplitPathDirEntry(dstPath) - linkTarget = filepath.Join(dstParent, linkTarget) - } - - dstInfo.Path = linkTarget - dstStat, err = statContainerPath(ctx, dockerCli, dstContainer, linkTarget) - } - - // Ignore any error and assume that the parent directory of the destination - // path exists, in which case the copy may still succeed. If there is any - // type of conflict (e.g., non-directory overwriting an existing directory - // or vice versa) the extraction will fail. If the destination simply did - // not exist, but the parent directory does, the extraction will still - // succeed. - if err == nil { - dstInfo.Exists, dstInfo.IsDir = true, dstStat.Mode.IsDir() - } - - var ( - content io.Reader - resolvedDstPath string - ) - - if srcPath == "-" { - // Use STDIN. - content = os.Stdin - resolvedDstPath = dstInfo.Path - if !dstInfo.IsDir { - return errors.Errorf("destination \"%s:%s\" must be a directory", dstContainer, dstPath) - } - } else { - // Prepare source copy info. - srcInfo, err := archive.CopyInfoSourcePath(srcPath, cpParam.followLink) - if err != nil { - return err - } - - srcArchive, err := archive.TarResource(srcInfo) - if err != nil { - return err - } - defer srcArchive.Close() - - // With the stat info about the local source as well as the - // destination, we have enough information to know whether we need to - // alter the archive that we upload so that when the server extracts - // it to the specified directory in the container we get the desired - // copy behavior. - - // See comments in the implementation of `archive.PrepareArchiveCopy` - // for exactly what goes into deciding how and whether the source - // archive needs to be altered for the correct copy behavior when it is - // extracted. This function also infers from the source and destination - // info which directory to extract to, which may be the parent of the - // destination that the user specified. - dstDir, preparedArchive, err := archive.PrepareArchiveCopy(srcArchive, srcInfo, dstInfo) - if err != nil { - return err - } - defer preparedArchive.Close() - - resolvedDstPath = dstDir - content = preparedArchive - } - - options := types.CopyToContainerOptions{ - AllowOverwriteDirWithFile: false, - CopyUIDGID: copyUIDGID, - } - - return dockerCli.Client().CopyToContainer(ctx, dstContainer, resolvedDstPath, content, options) -} - -// We use `:` as a delimiter between CONTAINER and PATH, but `:` could also be -// in a valid LOCALPATH, like `file:name.txt`. We can resolve this ambiguity by -// requiring a LOCALPATH with a `:` to be made explicit with a relative or -// absolute path: -// `/path/to/file:name.txt` or `./file:name.txt` -// -// This is apparently how `scp` handles this as well: -// http://www.cyberciti.biz/faq/rsync-scp-file-name-with-colon-punctuation-in-it/ -// -// We can't simply check for a filepath separator because container names may -// have a separator, e.g., "host0/cname1" if container is in a Docker cluster, -// so we have to check for a `/` or `.` prefix. Also, in the case of a Windows -// client, a `:` could be part of an absolute Windows path, in which case it -// is immediately proceeded by a backslash. -func splitCpArg(arg string) (container, path string) { - if system.IsAbs(arg) { - // Explicit local absolute path, e.g., `C:\foo` or `/foo`. - return "", arg - } - - parts := strings.SplitN(arg, ":", 2) - - if len(parts) == 1 || strings.HasPrefix(parts[0], ".") { - // Either there's no `:` in the arg - // OR it's an explicit local relative path like `./file:name.txt`. - return "", arg - } - - return parts[0], parts[1] -} diff --git a/vendor/github.com/docker/cli/cli/command/container/create.go b/vendor/github.com/docker/cli/cli/command/container/create.go deleted file mode 100644 index e87e3fb28..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/create.go +++ /dev/null @@ -1,225 +0,0 @@ -package container - -import ( - "fmt" - "io" - "os" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - apiclient "github.com/docker/docker/client" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/registry" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -type createOptions struct { - name string -} - -// NewCreateCommand creates a new cobra.Command for `docker create` -func NewCreateCommand(dockerCli command.Cli) *cobra.Command { - var opts createOptions - var copts *containerOptions - - cmd := &cobra.Command{ - Use: "create [OPTIONS] IMAGE [COMMAND] [ARG...]", - Short: "Create a new container", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - copts.Image = args[0] - if len(args) > 1 { - copts.Args = args[1:] - } - return runCreate(dockerCli, cmd.Flags(), &opts, copts) - }, - } - - flags := cmd.Flags() - flags.SetInterspersed(false) - - flags.StringVar(&opts.name, "name", "", "Assign a name to the container") - - // Add an explicit help that doesn't have a `-h` to prevent the conflict - // with hostname - flags.Bool("help", false, "Print usage") - - command.AddTrustVerificationFlags(flags) - copts = addFlags(flags) - return cmd -} - -func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *createOptions, copts *containerOptions) error { - containerConfig, err := parse(flags, copts) - if err != nil { - reportError(dockerCli.Err(), "create", err.Error(), true) - return cli.StatusError{StatusCode: 125} - } - response, err := createContainer(context.Background(), dockerCli, containerConfig, opts.name) - if err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), response.ID) - return nil -} - -func pullImage(ctx context.Context, dockerCli command.Cli, image string, out io.Writer) error { - ref, err := reference.ParseNormalizedNamed(image) - if err != nil { - return err - } - - // Resolve the Repository name from fqn to RepositoryInfo - repoInfo, err := registry.ParseRepositoryInfo(ref) - if err != nil { - return err - } - - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return err - } - - options := types.ImageCreateOptions{ - RegistryAuth: encodedAuth, - } - - responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options) - if err != nil { - return err - } - defer responseBody.Close() - - return jsonmessage.DisplayJSONMessagesStream( - responseBody, - out, - dockerCli.Out().FD(), - dockerCli.Out().IsTerminal(), - nil) -} - -type cidFile struct { - path string - file *os.File - written bool -} - -func (cid *cidFile) Close() error { - if cid.file == nil { - return nil - } - cid.file.Close() - - if cid.written { - return nil - } - if err := os.Remove(cid.path); err != nil { - return errors.Errorf("failed to remove the CID file '%s': %s \n", cid.path, err) - } - - return nil -} - -func (cid *cidFile) Write(id string) error { - if cid.file == nil { - return nil - } - if _, err := cid.file.Write([]byte(id)); err != nil { - return errors.Errorf("Failed to write the container ID to the file: %s", err) - } - cid.written = true - return nil -} - -func newCIDFile(path string) (*cidFile, error) { - if path == "" { - return &cidFile{}, nil - } - if _, err := os.Stat(path); err == nil { - return nil, errors.Errorf("Container ID file found, make sure the other container isn't running or delete %s", path) - } - - f, err := os.Create(path) - if err != nil { - return nil, errors.Errorf("Failed to create the container ID file: %s", err) - } - - return &cidFile{path: path, file: f}, nil -} - -func createContainer(ctx context.Context, dockerCli command.Cli, containerConfig *containerConfig, name string) (*container.ContainerCreateCreatedBody, error) { - config := containerConfig.Config - hostConfig := containerConfig.HostConfig - networkingConfig := containerConfig.NetworkingConfig - stderr := dockerCli.Err() - - var ( - trustedRef reference.Canonical - namedRef reference.Named - ) - - containerIDFile, err := newCIDFile(hostConfig.ContainerIDFile) - if err != nil { - return nil, err - } - defer containerIDFile.Close() - - ref, err := reference.ParseAnyReference(config.Image) - if err != nil { - return nil, err - } - if named, ok := ref.(reference.Named); ok { - namedRef = reference.TagNameOnly(named) - - if taggedRef, ok := namedRef.(reference.NamedTagged); ok && command.IsTrusted() { - var err error - trustedRef, err = image.TrustedReference(ctx, dockerCli, taggedRef, nil) - if err != nil { - return nil, err - } - config.Image = reference.FamiliarString(trustedRef) - } - } - - //create the container - response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name) - - //if image not found try to pull it - if err != nil { - if apiclient.IsErrImageNotFound(err) && namedRef != nil { - fmt.Fprintf(stderr, "Unable to find image '%s' locally\n", reference.FamiliarString(namedRef)) - - // we don't want to write to stdout anything apart from container.ID - if err := pullImage(ctx, dockerCli, config.Image, stderr); err != nil { - return nil, err - } - if taggedRef, ok := namedRef.(reference.NamedTagged); ok && trustedRef != nil { - if err := image.TagTrusted(ctx, dockerCli, trustedRef, taggedRef); err != nil { - return nil, err - } - } - // Retry - var retryErr error - response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name) - if retryErr != nil { - return nil, retryErr - } - } else { - return nil, err - } - } - - for _, warning := range response.Warnings { - fmt.Fprintf(stderr, "WARNING: %s\n", warning) - } - err = containerIDFile.Write(response.ID) - return &response, err -} diff --git a/vendor/github.com/docker/cli/cli/command/container/create_test.go b/vendor/github.com/docker/cli/cli/command/container/create_test.go deleted file mode 100644 index 21354e093..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/create_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package container - -import ( - "context" - "io" - "io/ioutil" - "os" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" - "github.com/gotestyourself/gotestyourself/fs" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestCIDFileNoOPWithNoFilename(t *testing.T) { - file, err := newCIDFile("") - require.NoError(t, err) - assert.Equal(t, &cidFile{}, file) - - assert.NoError(t, file.Write("id")) - assert.NoError(t, file.Close()) -} - -func TestNewCIDFileWhenFileAlreadyExists(t *testing.T) { - tempfile := fs.NewFile(t, "test-cid-file") - defer tempfile.Remove() - - _, err := newCIDFile(tempfile.Path()) - testutil.ErrorContains(t, err, "Container ID file found") -} - -func TestCIDFileCloseWithNoWrite(t *testing.T) { - tempdir := fs.NewDir(t, "test-cid-file") - defer tempdir.Remove() - - path := tempdir.Join("cidfile") - file, err := newCIDFile(path) - require.NoError(t, err) - assert.Equal(t, file.path, path) - - assert.NoError(t, file.Close()) - _, err = os.Stat(path) - assert.True(t, os.IsNotExist(err)) -} - -func TestCIDFileCloseWithWrite(t *testing.T) { - tempdir := fs.NewDir(t, "test-cid-file") - defer tempdir.Remove() - - path := tempdir.Join("cidfile") - file, err := newCIDFile(path) - require.NoError(t, err) - - content := "id" - assert.NoError(t, file.Write(content)) - - actual, err := ioutil.ReadFile(path) - require.NoError(t, err) - assert.Equal(t, content, string(actual)) - - assert.NoError(t, file.Close()) - _, err = os.Stat(path) - require.NoError(t, err) -} - -func TestCreateContainerPullsImageIfMissing(t *testing.T) { - imageName := "does-not-exist-locally" - responseCounter := 0 - containerID := "abcdef" - - client := &fakeClient{ - createContainerFunc: func( - config *container.Config, - hostConfig *container.HostConfig, - networkingConfig *network.NetworkingConfig, - containerName string, - ) (container.ContainerCreateCreatedBody, error) { - defer func() { responseCounter++ }() - switch responseCounter { - case 0: - return container.ContainerCreateCreatedBody{}, fakeNotFound{} - case 1: - return container.ContainerCreateCreatedBody{ID: containerID}, nil - default: - return container.ContainerCreateCreatedBody{}, errors.New("unexpected") - } - }, - imageCreateFunc: func(parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) { - return ioutil.NopCloser(strings.NewReader("")), nil - }, - infoFunc: func() (types.Info, error) { - return types.Info{IndexServerAddress: "http://indexserver"}, nil - }, - } - cli := test.NewFakeCli(client) - config := &containerConfig{ - Config: &container.Config{ - Image: imageName, - }, - HostConfig: &container.HostConfig{}, - } - body, err := createContainer(context.Background(), cli, config, "name") - require.NoError(t, err) - expected := container.ContainerCreateCreatedBody{ID: containerID} - assert.Equal(t, expected, *body) - stderr := cli.ErrBuffer().String() - assert.Contains(t, stderr, "Unable to find image 'does-not-exist-locally:latest' locally") -} - -type fakeNotFound struct{} - -func (f fakeNotFound) NotFound() bool { return true } -func (f fakeNotFound) Error() string { return "error fake not found" } diff --git a/vendor/github.com/docker/cli/cli/command/container/diff.go b/vendor/github.com/docker/cli/cli/command/container/diff.go deleted file mode 100644 index 5f646aa96..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/diff.go +++ /dev/null @@ -1,46 +0,0 @@ -package container - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type diffOptions struct { - container string -} - -// NewDiffCommand creates a new cobra.Command for `docker diff` -func NewDiffCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts diffOptions - - return &cobra.Command{ - Use: "diff CONTAINER", - Short: "Inspect changes to files or directories on a container's filesystem", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - return runDiff(dockerCli, &opts) - }, - } -} - -func runDiff(dockerCli *command.DockerCli, opts *diffOptions) error { - if opts.container == "" { - return errors.New("Container name cannot be empty") - } - ctx := context.Background() - - changes, err := dockerCli.Client().ContainerDiff(ctx, opts.container) - if err != nil { - return err - } - diffCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewDiffFormat("{{.Type}} {{.Path}}"), - } - return formatter.DiffWrite(diffCtx, changes) -} diff --git a/vendor/github.com/docker/cli/cli/command/container/exec.go b/vendor/github.com/docker/cli/cli/command/container/exec.go deleted file mode 100644 index f6860db57..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/exec.go +++ /dev/null @@ -1,203 +0,0 @@ -package container - -import ( - "fmt" - "io" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - apiclient "github.com/docker/docker/client" - "github.com/docker/docker/pkg/promise" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type execOptions struct { - detachKeys string - interactive bool - tty bool - detach bool - user string - privileged bool - env opts.ListOpts - container string - command []string -} - -func newExecOptions() execOptions { - return execOptions{env: opts.NewListOpts(opts.ValidateEnv)} -} - -// NewExecCommand creates a new cobra.Command for `docker exec` -func NewExecCommand(dockerCli command.Cli) *cobra.Command { - options := newExecOptions() - - cmd := &cobra.Command{ - Use: "exec [OPTIONS] CONTAINER COMMAND [ARG...]", - Short: "Run a command in a running container", - Args: cli.RequiresMinArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - options.container = args[0] - options.command = args[1:] - return runExec(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.SetInterspersed(false) - - flags.StringVarP(&options.detachKeys, "detach-keys", "", "", "Override the key sequence for detaching a container") - flags.BoolVarP(&options.interactive, "interactive", "i", false, "Keep STDIN open even if not attached") - flags.BoolVarP(&options.tty, "tty", "t", false, "Allocate a pseudo-TTY") - flags.BoolVarP(&options.detach, "detach", "d", false, "Detached mode: run command in the background") - flags.StringVarP(&options.user, "user", "u", "", "Username or UID (format: [:])") - flags.BoolVarP(&options.privileged, "privileged", "", false, "Give extended privileges to the command") - flags.VarP(&options.env, "env", "e", "Set environment variables") - flags.SetAnnotation("env", "version", []string{"1.25"}) - - return cmd -} - -func runExec(dockerCli command.Cli, options execOptions) error { - execConfig := parseExec(options, dockerCli.ConfigFile()) - ctx := context.Background() - client := dockerCli.Client() - - // We need to check the tty _before_ we do the ContainerExecCreate, because - // otherwise if we error out we will leak execIDs on the server (and - // there's no easy way to clean those up). But also in order to make "not - // exist" errors take precedence we do a dummy inspect first. - if _, err := client.ContainerInspect(ctx, options.container); err != nil { - return err - } - if !execConfig.Detach { - if err := dockerCli.In().CheckTty(execConfig.AttachStdin, execConfig.Tty); err != nil { - return err - } - } - - response, err := client.ContainerExecCreate(ctx, options.container, *execConfig) - if err != nil { - return err - } - - execID := response.ID - if execID == "" { - return errors.New("exec ID empty") - } - - if execConfig.Detach { - execStartCheck := types.ExecStartCheck{ - Detach: execConfig.Detach, - Tty: execConfig.Tty, - } - return client.ContainerExecStart(ctx, execID, execStartCheck) - } - return interactiveExec(ctx, dockerCli, execConfig, execID) -} - -func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *types.ExecConfig, execID string) error { - // Interactive exec requested. - var ( - out, stderr io.Writer - in io.ReadCloser - errCh chan error - ) - - if execConfig.AttachStdin { - in = dockerCli.In() - } - if execConfig.AttachStdout { - out = dockerCli.Out() - } - if execConfig.AttachStderr { - if execConfig.Tty { - stderr = dockerCli.Out() - } else { - stderr = dockerCli.Err() - } - } - - client := dockerCli.Client() - resp, err := client.ContainerExecAttach(ctx, execID, *execConfig) - if err != nil { - return err - } - defer resp.Close() - errCh = promise.Go(func() error { - streamer := hijackedIOStreamer{ - streams: dockerCli, - inputStream: in, - outputStream: out, - errorStream: stderr, - resp: resp, - tty: execConfig.Tty, - detachKeys: execConfig.DetachKeys, - } - - return streamer.stream(ctx) - }) - - if execConfig.Tty && dockerCli.In().IsTerminal() { - if err := MonitorTtySize(ctx, dockerCli, execID, true); err != nil { - fmt.Fprintln(dockerCli.Err(), "Error monitoring TTY size:", err) - } - } - - if err := <-errCh; err != nil { - logrus.Debugf("Error hijack: %s", err) - return err - } - - return getExecExitStatus(ctx, client, execID) -} - -func getExecExitStatus(ctx context.Context, client apiclient.ContainerAPIClient, execID string) error { - resp, err := client.ContainerExecInspect(ctx, execID) - if err != nil { - // If we can't connect, then the daemon probably died. - if !apiclient.IsErrConnectionFailed(err) { - return err - } - return cli.StatusError{StatusCode: -1} - } - status := resp.ExitCode - if status != 0 { - return cli.StatusError{StatusCode: status} - } - return nil -} - -// parseExec parses the specified args for the specified command and generates -// an ExecConfig from it. -func parseExec(opts execOptions, configFile *configfile.ConfigFile) *types.ExecConfig { - execConfig := &types.ExecConfig{ - User: opts.user, - Privileged: opts.privileged, - Tty: opts.tty, - Cmd: opts.command, - Detach: opts.detach, - Env: opts.env.GetAll(), - } - - // If -d is not set, attach to everything by default - if !opts.detach { - execConfig.AttachStdout = true - execConfig.AttachStderr = true - if opts.interactive { - execConfig.AttachStdin = true - } - } - - if opts.detachKeys != "" { - execConfig.DetachKeys = opts.detachKeys - } else { - execConfig.DetachKeys = configFile.DetachKeys - } - return execConfig -} diff --git a/vendor/github.com/docker/cli/cli/command/container/exec_test.go b/vendor/github.com/docker/cli/cli/command/container/exec_test.go deleted file mode 100644 index 492e3a558..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/exec_test.go +++ /dev/null @@ -1,227 +0,0 @@ -package container - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func withDefaultOpts(options execOptions) execOptions { - options.env = opts.NewListOpts(opts.ValidateEnv) - if len(options.command) == 0 { - options.command = []string{"command"} - } - return options -} - -func TestParseExec(t *testing.T) { - testcases := []struct { - options execOptions - configFile configfile.ConfigFile - expected types.ExecConfig - }{ - { - expected: types.ExecConfig{ - Cmd: []string{"command"}, - AttachStdout: true, - AttachStderr: true, - }, - options: withDefaultOpts(execOptions{}), - }, - { - expected: types.ExecConfig{ - Cmd: []string{"command1", "command2"}, - AttachStdout: true, - AttachStderr: true, - }, - options: withDefaultOpts(execOptions{ - command: []string{"command1", "command2"}, - }), - }, - { - options: withDefaultOpts(execOptions{ - interactive: true, - tty: true, - user: "uid", - }), - expected: types.ExecConfig{ - User: "uid", - AttachStdin: true, - AttachStdout: true, - AttachStderr: true, - Tty: true, - Cmd: []string{"command"}, - }, - }, - { - options: withDefaultOpts(execOptions{detach: true}), - expected: types.ExecConfig{ - Detach: true, - Cmd: []string{"command"}, - }, - }, - { - options: withDefaultOpts(execOptions{ - tty: true, - interactive: true, - detach: true, - }), - expected: types.ExecConfig{ - Detach: true, - Tty: true, - Cmd: []string{"command"}, - }, - }, - { - options: withDefaultOpts(execOptions{detach: true}), - configFile: configfile.ConfigFile{DetachKeys: "de"}, - expected: types.ExecConfig{ - Cmd: []string{"command"}, - DetachKeys: "de", - Detach: true, - }, - }, - { - options: withDefaultOpts(execOptions{ - detach: true, - detachKeys: "ab", - }), - configFile: configfile.ConfigFile{DetachKeys: "de"}, - expected: types.ExecConfig{ - Cmd: []string{"command"}, - DetachKeys: "ab", - Detach: true, - }, - }, - } - - for _, testcase := range testcases { - execConfig := parseExec(testcase.options, &testcase.configFile) - assert.Equal(t, testcase.expected, *execConfig) - } -} - -func TestRunExec(t *testing.T) { - var testcases = []struct { - doc string - options execOptions - client fakeClient - expectedError string - expectedOut string - expectedErr string - }{ - { - doc: "successful detach", - options: withDefaultOpts(execOptions{ - container: "thecontainer", - detach: true, - }), - client: fakeClient{execCreateFunc: execCreateWithID}, - }, - { - doc: "inspect error", - options: newExecOptions(), - client: fakeClient{ - inspectFunc: func(string) (types.ContainerJSON, error) { - return types.ContainerJSON{}, errors.New("failed inspect") - }, - }, - expectedError: "failed inspect", - }, - { - doc: "missing exec ID", - options: newExecOptions(), - expectedError: "exec ID empty", - }, - } - - for _, testcase := range testcases { - t.Run(testcase.doc, func(t *testing.T) { - cli := test.NewFakeCli(&testcase.client) - - err := runExec(cli, testcase.options) - if testcase.expectedError != "" { - testutil.ErrorContains(t, err, testcase.expectedError) - } else { - if !assert.NoError(t, err) { - return - } - } - assert.Equal(t, testcase.expectedOut, cli.OutBuffer().String()) - assert.Equal(t, testcase.expectedErr, cli.ErrBuffer().String()) - }) - } -} - -func execCreateWithID(_ string, _ types.ExecConfig) (types.IDResponse, error) { - return types.IDResponse{ID: "execid"}, nil -} - -func TestGetExecExitStatus(t *testing.T) { - execID := "the exec id" - expecatedErr := errors.New("unexpected error") - - testcases := []struct { - inspectError error - exitCode int - expectedError error - }{ - { - inspectError: nil, - exitCode: 0, - }, - { - inspectError: expecatedErr, - expectedError: expecatedErr, - }, - { - exitCode: 15, - expectedError: cli.StatusError{StatusCode: 15}, - }, - } - - for _, testcase := range testcases { - client := &fakeClient{ - execInspectFunc: func(id string) (types.ContainerExecInspect, error) { - assert.Equal(t, execID, id) - return types.ContainerExecInspect{ExitCode: testcase.exitCode}, testcase.inspectError - }, - } - err := getExecExitStatus(context.Background(), client, execID) - assert.Equal(t, testcase.expectedError, err) - } -} - -func TestNewExecCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - containerInspectFunc func(img string) (types.ContainerJSON, error) - }{ - { - name: "client-error", - args: []string{"5cb5bb5e4a3b", "-t", "-i", "bash"}, - expectedError: "something went wrong", - containerInspectFunc: func(containerID string) (types.ContainerJSON, error) { - return types.ContainerJSON{}, errors.Errorf("something went wrong") - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{inspectFunc: tc.containerInspectFunc}) - cmd := NewExecCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/container/export.go b/vendor/github.com/docker/cli/cli/command/container/export.go deleted file mode 100644 index 700f55762..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/export.go +++ /dev/null @@ -1,58 +0,0 @@ -package container - -import ( - "io" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type exportOptions struct { - container string - output string -} - -// NewExportCommand creates a new `docker export` command -func NewExportCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts exportOptions - - cmd := &cobra.Command{ - Use: "export [OPTIONS] CONTAINER", - Short: "Export a container's filesystem as a tar archive", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - return runExport(dockerCli, opts) - }, - } - - flags := cmd.Flags() - - flags.StringVarP(&opts.output, "output", "o", "", "Write to a file, instead of STDOUT") - - return cmd -} - -func runExport(dockerCli *command.DockerCli, opts exportOptions) error { - if opts.output == "" && dockerCli.Out().IsTerminal() { - return errors.New("cowardly refusing to save to a terminal. Use the -o flag or redirect") - } - - clnt := dockerCli.Client() - - responseBody, err := clnt.ContainerExport(context.Background(), opts.container) - if err != nil { - return err - } - defer responseBody.Close() - - if opts.output == "" { - _, err := io.Copy(dockerCli.Out(), responseBody) - return err - } - - return command.CopyToFile(opts.output, responseBody) -} diff --git a/vendor/github.com/docker/cli/cli/command/container/hijack.go b/vendor/github.com/docker/cli/cli/command/container/hijack.go deleted file mode 100644 index 3653f1f9b..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/hijack.go +++ /dev/null @@ -1,207 +0,0 @@ -package container - -import ( - "fmt" - "io" - "runtime" - "sync" - - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/docker/pkg/term" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" -) - -// The default escape key sequence: ctrl-p, ctrl-q -// TODO: This could be moved to `pkg/term`. -var defaultEscapeKeys = []byte{16, 17} - -// A hijackedIOStreamer handles copying input to and output from streams to the -// connection. -type hijackedIOStreamer struct { - streams command.Streams - inputStream io.ReadCloser - outputStream io.Writer - errorStream io.Writer - - resp types.HijackedResponse - - tty bool - detachKeys string -} - -// stream handles setting up the IO and then begins streaming stdin/stdout -// to/from the hijacked connection, blocking until it is either done reading -// output, the user inputs the detach key sequence when in TTY mode, or when -// the given context is cancelled. -func (h *hijackedIOStreamer) stream(ctx context.Context) error { - restoreInput, err := h.setupInput() - if err != nil { - return fmt.Errorf("unable to setup input stream: %s", err) - } - - defer restoreInput() - - outputDone := h.beginOutputStream(restoreInput) - inputDone, detached := h.beginInputStream(restoreInput) - - select { - case err := <-outputDone: - return err - case <-inputDone: - // Input stream has closed. - if h.outputStream != nil || h.errorStream != nil { - // Wait for output to complete streaming. - select { - case err := <-outputDone: - return err - case <-ctx.Done(): - return ctx.Err() - } - } - return nil - case err := <-detached: - // Got a detach key sequence. - return err - case <-ctx.Done(): - return ctx.Err() - } -} - -func (h *hijackedIOStreamer) setupInput() (restore func(), err error) { - if h.inputStream == nil || !h.tty { - // No need to setup input TTY. - // The restore func is a nop. - return func() {}, nil - } - - if err := setRawTerminal(h.streams); err != nil { - return nil, fmt.Errorf("unable to set IO streams as raw terminal: %s", err) - } - - // Use sync.Once so we may call restore multiple times but ensure we - // only restore the terminal once. - var restoreOnce sync.Once - restore = func() { - restoreOnce.Do(func() { - restoreTerminal(h.streams, h.inputStream) - }) - } - - // Wrap the input to detect detach escape sequence. - // Use default escape keys if an invalid sequence is given. - escapeKeys := defaultEscapeKeys - if h.detachKeys != "" { - customEscapeKeys, err := term.ToBytes(h.detachKeys) - if err != nil { - logrus.Warnf("invalid detach escape keys, using default: %s", err) - } else { - escapeKeys = customEscapeKeys - } - } - - h.inputStream = ioutils.NewReadCloserWrapper(term.NewEscapeProxy(h.inputStream, escapeKeys), h.inputStream.Close) - - return restore, nil -} - -func (h *hijackedIOStreamer) beginOutputStream(restoreInput func()) <-chan error { - if h.outputStream == nil && h.errorStream == nil { - // There is no need to copy output. - return nil - } - - outputDone := make(chan error) - go func() { - var err error - - // When TTY is ON, use regular copy - if h.outputStream != nil && h.tty { - _, err = io.Copy(h.outputStream, h.resp.Reader) - // We should restore the terminal as soon as possible - // once the connection ends so any following print - // messages will be in normal type. - restoreInput() - } else { - _, err = stdcopy.StdCopy(h.outputStream, h.errorStream, h.resp.Reader) - } - - logrus.Debug("[hijack] End of stdout") - - if err != nil { - logrus.Debugf("Error receiveStdout: %s", err) - } - - outputDone <- err - }() - - return outputDone -} - -func (h *hijackedIOStreamer) beginInputStream(restoreInput func()) (doneC <-chan struct{}, detachedC <-chan error) { - inputDone := make(chan struct{}) - detached := make(chan error) - - go func() { - if h.inputStream != nil { - _, err := io.Copy(h.resp.Conn, h.inputStream) - // We should restore the terminal as soon as possible - // once the connection ends so any following print - // messages will be in normal type. - restoreInput() - - logrus.Debug("[hijack] End of stdin") - - if _, ok := err.(term.EscapeError); ok { - detached <- err - return - } - - if err != nil { - // This error will also occur on the receive - // side (from stdout) where it will be - // propagated back to the caller. - logrus.Debugf("Error sendStdin: %s", err) - } - } - - if err := h.resp.CloseWrite(); err != nil { - logrus.Debugf("Couldn't send EOF: %s", err) - } - - close(inputDone) - }() - - return inputDone, detached -} - -func setRawTerminal(streams command.Streams) error { - if err := streams.In().SetRawTerminal(); err != nil { - return err - } - return streams.Out().SetRawTerminal() -} - -func restoreTerminal(streams command.Streams, in io.Closer) error { - streams.In().RestoreTerminal() - streams.Out().RestoreTerminal() - // WARNING: DO NOT REMOVE THE OS CHECKS !!! - // For some reason this Close call blocks on darwin.. - // As the client exits right after, simply discard the close - // until we find a better solution. - // - // This can also cause the client on Windows to get stuck in Win32 CloseHandle() - // in some cases. See https://github.com/docker/docker/issues/28267#issuecomment-288237442 - // Tracked internally at Microsoft by VSO #11352156. In the - // Windows case, you hit this if you are using the native/v2 console, - // not the "legacy" console, and you start the client in a new window. eg - // `start docker run --rm -it microsoft/nanoserver cmd /s /c echo foobar` - // will hang. Remove start, and it won't repro. - if in != nil && runtime.GOOS != "darwin" && runtime.GOOS != "windows" { - return in.Close() - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/inspect.go b/vendor/github.com/docker/cli/cli/command/container/inspect.go deleted file mode 100644 index 7e0e71034..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/inspect.go +++ /dev/null @@ -1,46 +0,0 @@ -package container - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - format string - size bool - refs []string -} - -// newInspectCommand creates a new cobra.Command for `docker container inspect` -func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] CONTAINER [CONTAINER...]", - Short: "Display detailed information on one or more containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.refs = args - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes") - - return cmd -} - -func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - getRefFunc := func(ref string) (interface{}, []byte, error) { - return client.ContainerInspectWithRaw(ctx, ref, opts.size) - } - return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRefFunc) -} diff --git a/vendor/github.com/docker/cli/cli/command/container/kill.go b/vendor/github.com/docker/cli/cli/command/container/kill.go deleted file mode 100644 index 650f9577a..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/kill.go +++ /dev/null @@ -1,56 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type killOptions struct { - signal string - - containers []string -} - -// NewKillCommand creates a new cobra.Command for `docker kill` -func NewKillCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts killOptions - - cmd := &cobra.Command{ - Use: "kill [OPTIONS] CONTAINER [CONTAINER...]", - Short: "Kill one or more running containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - return runKill(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.signal, "signal", "s", "KILL", "Signal to send to the container") - return cmd -} - -func runKill(dockerCli *command.DockerCli, opts *killOptions) error { - var errs []string - ctx := context.Background() - errChan := parallelOperation(ctx, opts.containers, func(ctx context.Context, container string) error { - return dockerCli.Client().ContainerKill(ctx, container, opts.signal) - }) - for _, name := range opts.containers { - if err := <-errChan; err != nil { - errs = append(errs, err.Error()) - } else { - fmt.Fprintln(dockerCli.Out(), name) - } - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/list.go b/vendor/github.com/docker/cli/cli/command/container/list.go deleted file mode 100644 index ec1ad69e1..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/list.go +++ /dev/null @@ -1,140 +0,0 @@ -package container - -import ( - "io/ioutil" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/cli/templates" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type psOptions struct { - quiet bool - size bool - all bool - noTrunc bool - nLatest bool - last int - format string - filter opts.FilterOpt -} - -// NewPsCommand creates a new cobra.Command for `docker ps` -func NewPsCommand(dockerCli *command.DockerCli) *cobra.Command { - options := psOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ps [OPTIONS]", - Short: "List containers", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runPs(dockerCli, &options) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display numeric IDs") - flags.BoolVarP(&options.size, "size", "s", false, "Display total file sizes") - flags.BoolVarP(&options.all, "all", "a", false, "Show all containers (default shows just running)") - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") - flags.BoolVarP(&options.nLatest, "latest", "l", false, "Show the latest created container (includes all states)") - flags.IntVarP(&options.last, "last", "n", -1, "Show n last created containers (includes all states)") - flags.StringVarP(&options.format, "format", "", "", "Pretty-print containers using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func newListCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := *NewPsCommand(dockerCli) - cmd.Aliases = []string{"ps", "list"} - cmd.Use = "ls [OPTIONS]" - return &cmd -} - -// listOptionsProcessor is used to set any container list options which may only -// be embedded in the format template. -// This is passed directly into tmpl.Execute in order to allow the preprocessor -// to set any list options that were not provided by flags (e.g. `.Size`). -// It is using a `map[string]bool` so that unknown fields passed into the -// template format do not cause errors. These errors will get picked up when -// running through the actual template processor. -type listOptionsProcessor map[string]bool - -// Size sets the size of the map when called by a template execution. -func (o listOptionsProcessor) Size() bool { - o["size"] = true - return true -} - -// Label is needed here as it allows the correct pre-processing -// because Label() is a method with arguments -func (o listOptionsProcessor) Label(name string) string { - return "" -} - -func buildContainerListOptions(opts *psOptions) (*types.ContainerListOptions, error) { - options := &types.ContainerListOptions{ - All: opts.all, - Limit: opts.last, - Size: opts.size, - Filters: opts.filter.Value(), - } - - if opts.nLatest && opts.last == -1 { - options.Limit = 1 - } - - tmpl, err := templates.Parse(opts.format) - - if err != nil { - return nil, err - } - - optionsProcessor := listOptionsProcessor{} - // This shouldn't error out but swallowing the error makes it harder - // to track down if preProcessor issues come up. Ref #24696 - if err := tmpl.Execute(ioutil.Discard, optionsProcessor); err != nil { - return nil, err - } - // At the moment all we need is to capture .Size for preprocessor - options.Size = opts.size || optionsProcessor["size"] - - return options, nil -} - -func runPs(dockerCli *command.DockerCli, options *psOptions) error { - ctx := context.Background() - - listOptions, err := buildContainerListOptions(options) - if err != nil { - return err - } - - containers, err := dockerCli.Client().ContainerList(ctx, *listOptions) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().PsFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().PsFormat - } else { - format = formatter.TableFormatKey - } - } - - containerCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewContainerFormat(format, options.quiet, listOptions.Size), - Trunc: !options.noTrunc, - } - return formatter.ContainerWrite(containerCtx, containers) -} diff --git a/vendor/github.com/docker/cli/cli/command/container/logs.go b/vendor/github.com/docker/cli/cli/command/container/logs.go deleted file mode 100644 index 209e74942..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/logs.go +++ /dev/null @@ -1,76 +0,0 @@ -package container - -import ( - "io" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stdcopy" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type logsOptions struct { - follow bool - since string - timestamps bool - details bool - tail string - - container string -} - -// NewLogsCommand creates a new cobra.Command for `docker logs` -func NewLogsCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts logsOptions - - cmd := &cobra.Command{ - Use: "logs [OPTIONS] CONTAINER", - Short: "Fetch the logs of a container", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - return runLogs(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output") - flags.StringVar(&opts.since, "since", "", "Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)") - flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps") - flags.BoolVar(&opts.details, "details", false, "Show extra details provided to logs") - flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs") - return cmd -} - -func runLogs(dockerCli *command.DockerCli, opts *logsOptions) error { - ctx := context.Background() - - options := types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Since: opts.since, - Timestamps: opts.timestamps, - Follow: opts.follow, - Tail: opts.tail, - Details: opts.details, - } - responseBody, err := dockerCli.Client().ContainerLogs(ctx, opts.container, options) - if err != nil { - return err - } - defer responseBody.Close() - - c, err := dockerCli.Client().ContainerInspect(ctx, opts.container) - if err != nil { - return err - } - - if c.Config.Tty { - _, err = io.Copy(dockerCli.Out(), responseBody) - } else { - _, err = stdcopy.StdCopy(dockerCli.Out(), dockerCli.Err(), responseBody) - } - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/container/opts.go b/vendor/github.com/docker/cli/cli/command/container/opts.go deleted file mode 100644 index 017a43657..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/opts.go +++ /dev/null @@ -1,836 +0,0 @@ -package container - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "path" - "regexp" - "strconv" - "strings" - "time" - - "github.com/docker/cli/cli/compose/loader" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/container" - networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/strslice" - "github.com/docker/docker/pkg/signal" - "github.com/docker/go-connections/nat" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/pflag" -) - -var ( - deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`) -) - -// containerOptions is a data object with all the options for creating a container -type containerOptions struct { - attach opts.ListOpts - volumes opts.ListOpts - tmpfs opts.ListOpts - mounts opts.MountOpt - blkioWeightDevice opts.WeightdeviceOpt - deviceReadBps opts.ThrottledeviceOpt - deviceWriteBps opts.ThrottledeviceOpt - links opts.ListOpts - aliases opts.ListOpts - linkLocalIPs opts.ListOpts - deviceReadIOps opts.ThrottledeviceOpt - deviceWriteIOps opts.ThrottledeviceOpt - env opts.ListOpts - labels opts.ListOpts - deviceCgroupRules opts.ListOpts - devices opts.ListOpts - ulimits *opts.UlimitOpt - sysctls *opts.MapOpts - publish opts.ListOpts - expose opts.ListOpts - dns opts.ListOpts - dnsSearch opts.ListOpts - dnsOptions opts.ListOpts - extraHosts opts.ListOpts - volumesFrom opts.ListOpts - envFile opts.ListOpts - capAdd opts.ListOpts - capDrop opts.ListOpts - groupAdd opts.ListOpts - securityOpt opts.ListOpts - storageOpt opts.ListOpts - labelsFile opts.ListOpts - loggingOpts opts.ListOpts - privileged bool - pidMode string - utsMode string - usernsMode string - publishAll bool - stdin bool - tty bool - oomKillDisable bool - oomScoreAdj int - containerIDFile string - entrypoint string - hostname string - memory opts.MemBytes - memoryReservation opts.MemBytes - memorySwap opts.MemSwapBytes - kernelMemory opts.MemBytes - user string - workingDir string - cpuCount int64 - cpuShares int64 - cpuPercent int64 - cpuPeriod int64 - cpuRealtimePeriod int64 - cpuRealtimeRuntime int64 - cpuQuota int64 - cpus opts.NanoCPUs - cpusetCpus string - cpusetMems string - blkioWeight uint16 - ioMaxBandwidth opts.MemBytes - ioMaxIOps uint64 - swappiness int64 - netMode string - macAddress string - ipv4Address string - ipv6Address string - ipcMode string - pidsLimit int64 - restartPolicy string - readonlyRootfs bool - loggingDriver string - cgroupParent string - volumeDriver string - stopSignal string - stopTimeout int - isolation string - shmSize opts.MemBytes - noHealthcheck bool - healthCmd string - healthInterval time.Duration - healthTimeout time.Duration - healthStartPeriod time.Duration - healthRetries int - runtime string - autoRemove bool - init bool - - Image string - Args []string -} - -// addFlags adds all command line flags that will be used by parse to the FlagSet -func addFlags(flags *pflag.FlagSet) *containerOptions { - copts := &containerOptions{ - aliases: opts.NewListOpts(nil), - attach: opts.NewListOpts(validateAttach), - blkioWeightDevice: opts.NewWeightdeviceOpt(opts.ValidateWeightDevice), - capAdd: opts.NewListOpts(nil), - capDrop: opts.NewListOpts(nil), - dns: opts.NewListOpts(opts.ValidateIPAddress), - dnsOptions: opts.NewListOpts(nil), - dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch), - deviceCgroupRules: opts.NewListOpts(validateDeviceCgroupRule), - deviceReadBps: opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice), - deviceReadIOps: opts.NewThrottledeviceOpt(opts.ValidateThrottleIOpsDevice), - deviceWriteBps: opts.NewThrottledeviceOpt(opts.ValidateThrottleBpsDevice), - deviceWriteIOps: opts.NewThrottledeviceOpt(opts.ValidateThrottleIOpsDevice), - devices: opts.NewListOpts(validateDevice), - env: opts.NewListOpts(opts.ValidateEnv), - envFile: opts.NewListOpts(nil), - expose: opts.NewListOpts(nil), - extraHosts: opts.NewListOpts(opts.ValidateExtraHost), - groupAdd: opts.NewListOpts(nil), - labels: opts.NewListOpts(opts.ValidateEnv), - labelsFile: opts.NewListOpts(nil), - linkLocalIPs: opts.NewListOpts(nil), - links: opts.NewListOpts(opts.ValidateLink), - loggingOpts: opts.NewListOpts(nil), - publish: opts.NewListOpts(nil), - securityOpt: opts.NewListOpts(nil), - storageOpt: opts.NewListOpts(nil), - sysctls: opts.NewMapOpts(nil, opts.ValidateSysctl), - tmpfs: opts.NewListOpts(nil), - ulimits: opts.NewUlimitOpt(nil), - volumes: opts.NewListOpts(nil), - volumesFrom: opts.NewListOpts(nil), - } - - // General purpose flags - flags.VarP(&copts.attach, "attach", "a", "Attach to STDIN, STDOUT or STDERR") - flags.Var(&copts.deviceCgroupRules, "device-cgroup-rule", "Add a rule to the cgroup allowed devices list") - flags.Var(&copts.devices, "device", "Add a host device to the container") - flags.VarP(&copts.env, "env", "e", "Set environment variables") - flags.Var(&copts.envFile, "env-file", "Read in a file of environment variables") - flags.StringVar(&copts.entrypoint, "entrypoint", "", "Overwrite the default ENTRYPOINT of the image") - flags.Var(&copts.groupAdd, "group-add", "Add additional groups to join") - flags.StringVarP(&copts.hostname, "hostname", "h", "", "Container host name") - flags.BoolVarP(&copts.stdin, "interactive", "i", false, "Keep STDIN open even if not attached") - flags.VarP(&copts.labels, "label", "l", "Set meta data on a container") - flags.Var(&copts.labelsFile, "label-file", "Read in a line delimited file of labels") - flags.BoolVar(&copts.readonlyRootfs, "read-only", false, "Mount the container's root filesystem as read only") - flags.StringVar(&copts.restartPolicy, "restart", "no", "Restart policy to apply when a container exits") - flags.StringVar(&copts.stopSignal, "stop-signal", signal.DefaultStopSignal, "Signal to stop a container") - flags.IntVar(&copts.stopTimeout, "stop-timeout", 0, "Timeout (in seconds) to stop a container") - flags.SetAnnotation("stop-timeout", "version", []string{"1.25"}) - flags.Var(copts.sysctls, "sysctl", "Sysctl options") - flags.BoolVarP(&copts.tty, "tty", "t", false, "Allocate a pseudo-TTY") - flags.Var(copts.ulimits, "ulimit", "Ulimit options") - flags.StringVarP(&copts.user, "user", "u", "", "Username or UID (format: [:])") - flags.StringVarP(&copts.workingDir, "workdir", "w", "", "Working directory inside the container") - flags.BoolVar(&copts.autoRemove, "rm", false, "Automatically remove the container when it exits") - - // Security - flags.Var(&copts.capAdd, "cap-add", "Add Linux capabilities") - flags.Var(&copts.capDrop, "cap-drop", "Drop Linux capabilities") - flags.BoolVar(&copts.privileged, "privileged", false, "Give extended privileges to this container") - flags.Var(&copts.securityOpt, "security-opt", "Security Options") - flags.StringVar(&copts.usernsMode, "userns", "", "User namespace to use") - - // Network and port publishing flag - flags.Var(&copts.extraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)") - flags.Var(&copts.dns, "dns", "Set custom DNS servers") - // We allow for both "--dns-opt" and "--dns-option", although the latter is the recommended way. - // This is to be consistent with service create/update - flags.Var(&copts.dnsOptions, "dns-opt", "Set DNS options") - flags.Var(&copts.dnsOptions, "dns-option", "Set DNS options") - flags.MarkHidden("dns-opt") - flags.Var(&copts.dnsSearch, "dns-search", "Set custom DNS search domains") - flags.Var(&copts.expose, "expose", "Expose a port or a range of ports") - flags.StringVar(&copts.ipv4Address, "ip", "", "IPv4 address (e.g., 172.30.100.104)") - flags.StringVar(&copts.ipv6Address, "ip6", "", "IPv6 address (e.g., 2001:db8::33)") - flags.Var(&copts.links, "link", "Add link to another container") - flags.Var(&copts.linkLocalIPs, "link-local-ip", "Container IPv4/IPv6 link-local addresses") - flags.StringVar(&copts.macAddress, "mac-address", "", "Container MAC address (e.g., 92:d0:c6:0a:29:33)") - flags.VarP(&copts.publish, "publish", "p", "Publish a container's port(s) to the host") - flags.BoolVarP(&copts.publishAll, "publish-all", "P", false, "Publish all exposed ports to random ports") - // We allow for both "--net" and "--network", although the latter is the recommended way. - flags.StringVar(&copts.netMode, "net", "default", "Connect a container to a network") - flags.StringVar(&copts.netMode, "network", "default", "Connect a container to a network") - flags.MarkHidden("net") - // We allow for both "--net-alias" and "--network-alias", although the latter is the recommended way. - flags.Var(&copts.aliases, "net-alias", "Add network-scoped alias for the container") - flags.Var(&copts.aliases, "network-alias", "Add network-scoped alias for the container") - flags.MarkHidden("net-alias") - - // Logging and storage - flags.StringVar(&copts.loggingDriver, "log-driver", "", "Logging driver for the container") - flags.StringVar(&copts.volumeDriver, "volume-driver", "", "Optional volume driver for the container") - flags.Var(&copts.loggingOpts, "log-opt", "Log driver options") - flags.Var(&copts.storageOpt, "storage-opt", "Storage driver options for the container") - flags.Var(&copts.tmpfs, "tmpfs", "Mount a tmpfs directory") - flags.Var(&copts.volumesFrom, "volumes-from", "Mount volumes from the specified container(s)") - flags.VarP(&copts.volumes, "volume", "v", "Bind mount a volume") - flags.Var(&copts.mounts, "mount", "Attach a filesystem mount to the container") - - // Health-checking - flags.StringVar(&copts.healthCmd, "health-cmd", "", "Command to run to check health") - flags.DurationVar(&copts.healthInterval, "health-interval", 0, "Time between running the check (ms|s|m|h) (default 0s)") - flags.IntVar(&copts.healthRetries, "health-retries", 0, "Consecutive failures needed to report unhealthy") - flags.DurationVar(&copts.healthTimeout, "health-timeout", 0, "Maximum time to allow one check to run (ms|s|m|h) (default 0s)") - flags.DurationVar(&copts.healthStartPeriod, "health-start-period", 0, "Start period for the container to initialize before starting health-retries countdown (ms|s|m|h) (default 0s)") - flags.SetAnnotation("health-start-period", "version", []string{"1.29"}) - flags.BoolVar(&copts.noHealthcheck, "no-healthcheck", false, "Disable any container-specified HEALTHCHECK") - - // Resource management - flags.Uint16Var(&copts.blkioWeight, "blkio-weight", 0, "Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)") - flags.Var(&copts.blkioWeightDevice, "blkio-weight-device", "Block IO weight (relative device weight)") - flags.StringVar(&copts.containerIDFile, "cidfile", "", "Write the container ID to the file") - flags.StringVar(&copts.cpusetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)") - flags.StringVar(&copts.cpusetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)") - flags.Int64Var(&copts.cpuCount, "cpu-count", 0, "CPU count (Windows only)") - flags.SetAnnotation("cpu-count", "ostype", []string{"windows"}) - flags.Int64Var(&copts.cpuPercent, "cpu-percent", 0, "CPU percent (Windows only)") - flags.SetAnnotation("cpu-percent", "ostype", []string{"windows"}) - flags.Int64Var(&copts.cpuPeriod, "cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period") - flags.Int64Var(&copts.cpuQuota, "cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota") - flags.Int64Var(&copts.cpuRealtimePeriod, "cpu-rt-period", 0, "Limit CPU real-time period in microseconds") - flags.SetAnnotation("cpu-rt-period", "version", []string{"1.25"}) - flags.Int64Var(&copts.cpuRealtimeRuntime, "cpu-rt-runtime", 0, "Limit CPU real-time runtime in microseconds") - flags.SetAnnotation("cpu-rt-runtime", "version", []string{"1.25"}) - flags.Int64VarP(&copts.cpuShares, "cpu-shares", "c", 0, "CPU shares (relative weight)") - flags.Var(&copts.cpus, "cpus", "Number of CPUs") - flags.SetAnnotation("cpus", "version", []string{"1.25"}) - flags.Var(&copts.deviceReadBps, "device-read-bps", "Limit read rate (bytes per second) from a device") - flags.Var(&copts.deviceReadIOps, "device-read-iops", "Limit read rate (IO per second) from a device") - flags.Var(&copts.deviceWriteBps, "device-write-bps", "Limit write rate (bytes per second) to a device") - flags.Var(&copts.deviceWriteIOps, "device-write-iops", "Limit write rate (IO per second) to a device") - flags.Var(&copts.ioMaxBandwidth, "io-maxbandwidth", "Maximum IO bandwidth limit for the system drive (Windows only)") - flags.SetAnnotation("io-maxbandwidth", "ostype", []string{"windows"}) - flags.Uint64Var(&copts.ioMaxIOps, "io-maxiops", 0, "Maximum IOps limit for the system drive (Windows only)") - flags.SetAnnotation("io-maxiops", "ostype", []string{"windows"}) - flags.Var(&copts.kernelMemory, "kernel-memory", "Kernel memory limit") - flags.VarP(&copts.memory, "memory", "m", "Memory limit") - flags.Var(&copts.memoryReservation, "memory-reservation", "Memory soft limit") - flags.Var(&copts.memorySwap, "memory-swap", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") - flags.Int64Var(&copts.swappiness, "memory-swappiness", -1, "Tune container memory swappiness (0 to 100)") - flags.BoolVar(&copts.oomKillDisable, "oom-kill-disable", false, "Disable OOM Killer") - flags.IntVar(&copts.oomScoreAdj, "oom-score-adj", 0, "Tune host's OOM preferences (-1000 to 1000)") - flags.Int64Var(&copts.pidsLimit, "pids-limit", 0, "Tune container pids limit (set -1 for unlimited)") - - // Low-level execution (cgroups, namespaces, ...) - flags.StringVar(&copts.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container") - flags.StringVar(&copts.ipcMode, "ipc", "", "IPC mode to use") - flags.StringVar(&copts.isolation, "isolation", "", "Container isolation technology") - flags.StringVar(&copts.pidMode, "pid", "", "PID namespace to use") - flags.Var(&copts.shmSize, "shm-size", "Size of /dev/shm") - flags.StringVar(&copts.utsMode, "uts", "", "UTS namespace to use") - flags.StringVar(&copts.runtime, "runtime", "", "Runtime to use for this container") - - flags.BoolVar(&copts.init, "init", false, "Run an init inside the container that forwards signals and reaps processes") - flags.SetAnnotation("init", "version", []string{"1.25"}) - return copts -} - -type containerConfig struct { - Config *container.Config - HostConfig *container.HostConfig - NetworkingConfig *networktypes.NetworkingConfig -} - -// parse parses the args for the specified command and generates a Config, -// a HostConfig and returns them with the specified command. -// If the specified args are not valid, it will return an error. -// nolint: gocyclo -func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, error) { - var ( - attachStdin = copts.attach.Get("stdin") - attachStdout = copts.attach.Get("stdout") - attachStderr = copts.attach.Get("stderr") - ) - - // Validate the input mac address - if copts.macAddress != "" { - if _, err := opts.ValidateMACAddress(copts.macAddress); err != nil { - return nil, errors.Errorf("%s is not a valid mac address", copts.macAddress) - } - } - if copts.stdin { - attachStdin = true - } - // If -a is not set, attach to stdout and stderr - if copts.attach.Len() == 0 { - attachStdout = true - attachStderr = true - } - - var err error - - swappiness := copts.swappiness - if swappiness != -1 && (swappiness < 0 || swappiness > 100) { - return nil, errors.Errorf("invalid value: %d. Valid memory swappiness range is 0-100", swappiness) - } - - mounts := copts.mounts.Value() - if len(mounts) > 0 && copts.volumeDriver != "" { - logrus.Warn("`--volume-driver` is ignored for volumes specified via `--mount`. Use `--mount type=volume,volume-driver=...` instead.") - } - var binds []string - volumes := copts.volumes.GetMap() - // add any bind targets to the list of container volumes - for bind := range copts.volumes.GetMap() { - parsed, _ := loader.ParseVolume(bind) - if parsed.Source != "" { - // after creating the bind mount we want to delete it from the copts.volumes values because - // we do not want bind mounts being committed to image configs - binds = append(binds, bind) - // We should delete from the map (`volumes`) here, as deleting from copts.volumes will not work if - // there are duplicates entries. - delete(volumes, bind) - } - } - - // Can't evaluate options passed into --tmpfs until we actually mount - tmpfs := make(map[string]string) - for _, t := range copts.tmpfs.GetAll() { - if arr := strings.SplitN(t, ":", 2); len(arr) > 1 { - tmpfs[arr[0]] = arr[1] - } else { - tmpfs[arr[0]] = "" - } - } - - var ( - runCmd strslice.StrSlice - entrypoint strslice.StrSlice - ) - - if len(copts.Args) > 0 { - runCmd = strslice.StrSlice(copts.Args) - } - - if copts.entrypoint != "" { - entrypoint = strslice.StrSlice{copts.entrypoint} - } else if flags.Changed("entrypoint") { - // if `--entrypoint=` is parsed then Entrypoint is reset - entrypoint = []string{""} - } - - ports, portBindings, err := nat.ParsePortSpecs(copts.publish.GetAll()) - if err != nil { - return nil, err - } - - // Merge in exposed ports to the map of published ports - for _, e := range copts.expose.GetAll() { - if strings.Contains(e, ":") { - return nil, errors.Errorf("invalid port format for --expose: %s", e) - } - //support two formats for expose, original format /[] or /[] - proto, port := nat.SplitProtoPort(e) - //parse the start and end port and create a sequence of ports to expose - //if expose a port, the start and end port are the same - start, end, err := nat.ParsePortRange(port) - if err != nil { - return nil, errors.Errorf("invalid range format for --expose: %s, error: %s", e, err) - } - for i := start; i <= end; i++ { - p, err := nat.NewPort(proto, strconv.FormatUint(i, 10)) - if err != nil { - return nil, err - } - if _, exists := ports[p]; !exists { - ports[p] = struct{}{} - } - } - } - - // parse device mappings - deviceMappings := []container.DeviceMapping{} - for _, device := range copts.devices.GetAll() { - deviceMapping, err := parseDevice(device) - if err != nil { - return nil, err - } - deviceMappings = append(deviceMappings, deviceMapping) - } - - // collect all the environment variables for the container - envVariables, err := opts.ReadKVStrings(copts.envFile.GetAll(), copts.env.GetAll()) - if err != nil { - return nil, err - } - - // collect all the labels for the container - labels, err := opts.ReadKVStrings(copts.labelsFile.GetAll(), copts.labels.GetAll()) - if err != nil { - return nil, err - } - - pidMode := container.PidMode(copts.pidMode) - if !pidMode.Valid() { - return nil, errors.Errorf("--pid: invalid PID mode") - } - - utsMode := container.UTSMode(copts.utsMode) - if !utsMode.Valid() { - return nil, errors.Errorf("--uts: invalid UTS mode") - } - - usernsMode := container.UsernsMode(copts.usernsMode) - if !usernsMode.Valid() { - return nil, errors.Errorf("--userns: invalid USER mode") - } - - restartPolicy, err := opts.ParseRestartPolicy(copts.restartPolicy) - if err != nil { - return nil, err - } - - loggingOpts, err := parseLoggingOpts(copts.loggingDriver, copts.loggingOpts.GetAll()) - if err != nil { - return nil, err - } - - securityOpts, err := parseSecurityOpts(copts.securityOpt.GetAll()) - if err != nil { - return nil, err - } - - storageOpts, err := parseStorageOpts(copts.storageOpt.GetAll()) - if err != nil { - return nil, err - } - - // Healthcheck - var healthConfig *container.HealthConfig - haveHealthSettings := copts.healthCmd != "" || - copts.healthInterval != 0 || - copts.healthTimeout != 0 || - copts.healthStartPeriod != 0 || - copts.healthRetries != 0 - if copts.noHealthcheck { - if haveHealthSettings { - return nil, errors.Errorf("--no-healthcheck conflicts with --health-* options") - } - test := strslice.StrSlice{"NONE"} - healthConfig = &container.HealthConfig{Test: test} - } else if haveHealthSettings { - var probe strslice.StrSlice - if copts.healthCmd != "" { - args := []string{"CMD-SHELL", copts.healthCmd} - probe = strslice.StrSlice(args) - } - if copts.healthInterval < 0 { - return nil, errors.Errorf("--health-interval cannot be negative") - } - if copts.healthTimeout < 0 { - return nil, errors.Errorf("--health-timeout cannot be negative") - } - if copts.healthRetries < 0 { - return nil, errors.Errorf("--health-retries cannot be negative") - } - if copts.healthStartPeriod < 0 { - return nil, fmt.Errorf("--health-start-period cannot be negative") - } - - healthConfig = &container.HealthConfig{ - Test: probe, - Interval: copts.healthInterval, - Timeout: copts.healthTimeout, - StartPeriod: copts.healthStartPeriod, - Retries: copts.healthRetries, - } - } - - resources := container.Resources{ - CgroupParent: copts.cgroupParent, - Memory: copts.memory.Value(), - MemoryReservation: copts.memoryReservation.Value(), - MemorySwap: copts.memorySwap.Value(), - MemorySwappiness: &copts.swappiness, - KernelMemory: copts.kernelMemory.Value(), - OomKillDisable: &copts.oomKillDisable, - NanoCPUs: copts.cpus.Value(), - CPUCount: copts.cpuCount, - CPUPercent: copts.cpuPercent, - CPUShares: copts.cpuShares, - CPUPeriod: copts.cpuPeriod, - CpusetCpus: copts.cpusetCpus, - CpusetMems: copts.cpusetMems, - CPUQuota: copts.cpuQuota, - CPURealtimePeriod: copts.cpuRealtimePeriod, - CPURealtimeRuntime: copts.cpuRealtimeRuntime, - PidsLimit: copts.pidsLimit, - BlkioWeight: copts.blkioWeight, - BlkioWeightDevice: copts.blkioWeightDevice.GetList(), - BlkioDeviceReadBps: copts.deviceReadBps.GetList(), - BlkioDeviceWriteBps: copts.deviceWriteBps.GetList(), - BlkioDeviceReadIOps: copts.deviceReadIOps.GetList(), - BlkioDeviceWriteIOps: copts.deviceWriteIOps.GetList(), - IOMaximumIOps: copts.ioMaxIOps, - IOMaximumBandwidth: uint64(copts.ioMaxBandwidth), - Ulimits: copts.ulimits.GetList(), - DeviceCgroupRules: copts.deviceCgroupRules.GetAll(), - Devices: deviceMappings, - } - - config := &container.Config{ - Hostname: copts.hostname, - ExposedPorts: ports, - User: copts.user, - Tty: copts.tty, - // TODO: deprecated, it comes from -n, --networking - // it's still needed internally to set the network to disabled - // if e.g. bridge is none in daemon opts, and in inspect - NetworkDisabled: false, - OpenStdin: copts.stdin, - AttachStdin: attachStdin, - AttachStdout: attachStdout, - AttachStderr: attachStderr, - Env: envVariables, - Cmd: runCmd, - Image: copts.Image, - Volumes: volumes, - MacAddress: copts.macAddress, - Entrypoint: entrypoint, - WorkingDir: copts.workingDir, - Labels: opts.ConvertKVStringsToMap(labels), - Healthcheck: healthConfig, - } - if flags.Changed("stop-signal") { - config.StopSignal = copts.stopSignal - } - if flags.Changed("stop-timeout") { - config.StopTimeout = &copts.stopTimeout - } - - hostConfig := &container.HostConfig{ - Binds: binds, - ContainerIDFile: copts.containerIDFile, - OomScoreAdj: copts.oomScoreAdj, - AutoRemove: copts.autoRemove, - Privileged: copts.privileged, - PortBindings: portBindings, - Links: copts.links.GetAll(), - PublishAllPorts: copts.publishAll, - // Make sure the dns fields are never nil. - // New containers don't ever have those fields nil, - // but pre created containers can still have those nil values. - // See https://github.com/docker/docker/pull/17779 - // for a more detailed explanation on why we don't want that. - DNS: copts.dns.GetAllOrEmpty(), - DNSSearch: copts.dnsSearch.GetAllOrEmpty(), - DNSOptions: copts.dnsOptions.GetAllOrEmpty(), - ExtraHosts: copts.extraHosts.GetAll(), - VolumesFrom: copts.volumesFrom.GetAll(), - NetworkMode: container.NetworkMode(copts.netMode), - IpcMode: container.IpcMode(copts.ipcMode), - PidMode: pidMode, - UTSMode: utsMode, - UsernsMode: usernsMode, - CapAdd: strslice.StrSlice(copts.capAdd.GetAll()), - CapDrop: strslice.StrSlice(copts.capDrop.GetAll()), - GroupAdd: copts.groupAdd.GetAll(), - RestartPolicy: restartPolicy, - SecurityOpt: securityOpts, - StorageOpt: storageOpts, - ReadonlyRootfs: copts.readonlyRootfs, - LogConfig: container.LogConfig{Type: copts.loggingDriver, Config: loggingOpts}, - VolumeDriver: copts.volumeDriver, - Isolation: container.Isolation(copts.isolation), - ShmSize: copts.shmSize.Value(), - Resources: resources, - Tmpfs: tmpfs, - Sysctls: copts.sysctls.GetAll(), - Runtime: copts.runtime, - Mounts: mounts, - } - - if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() { - return nil, errors.Errorf("Conflicting options: --restart and --rm") - } - - // only set this value if the user provided the flag, else it should default to nil - if flags.Changed("init") { - hostConfig.Init = &copts.init - } - - // When allocating stdin in attached mode, close stdin at client disconnect - if config.OpenStdin && config.AttachStdin { - config.StdinOnce = true - } - - networkingConfig := &networktypes.NetworkingConfig{ - EndpointsConfig: make(map[string]*networktypes.EndpointSettings), - } - - if copts.ipv4Address != "" || copts.ipv6Address != "" || copts.linkLocalIPs.Len() > 0 { - epConfig := &networktypes.EndpointSettings{} - networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig - - epConfig.IPAMConfig = &networktypes.EndpointIPAMConfig{ - IPv4Address: copts.ipv4Address, - IPv6Address: copts.ipv6Address, - } - - if copts.linkLocalIPs.Len() > 0 { - epConfig.IPAMConfig.LinkLocalIPs = make([]string, copts.linkLocalIPs.Len()) - copy(epConfig.IPAMConfig.LinkLocalIPs, copts.linkLocalIPs.GetAll()) - } - } - - if hostConfig.NetworkMode.IsUserDefined() && len(hostConfig.Links) > 0 { - epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] - if epConfig == nil { - epConfig = &networktypes.EndpointSettings{} - } - epConfig.Links = make([]string, len(hostConfig.Links)) - copy(epConfig.Links, hostConfig.Links) - networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig - } - - if copts.aliases.Len() > 0 { - epConfig := networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] - if epConfig == nil { - epConfig = &networktypes.EndpointSettings{} - } - epConfig.Aliases = make([]string, copts.aliases.Len()) - copy(epConfig.Aliases, copts.aliases.GetAll()) - networkingConfig.EndpointsConfig[string(hostConfig.NetworkMode)] = epConfig - } - - return &containerConfig{ - Config: config, - HostConfig: hostConfig, - NetworkingConfig: networkingConfig, - }, nil -} - -func parseLoggingOpts(loggingDriver string, loggingOpts []string) (map[string]string, error) { - loggingOptsMap := opts.ConvertKVStringsToMap(loggingOpts) - if loggingDriver == "none" && len(loggingOpts) > 0 { - return map[string]string{}, errors.Errorf("invalid logging opts for driver %s", loggingDriver) - } - return loggingOptsMap, nil -} - -// takes a local seccomp daemon, reads the file contents for sending to the daemon -func parseSecurityOpts(securityOpts []string) ([]string, error) { - for key, opt := range securityOpts { - con := strings.SplitN(opt, "=", 2) - if len(con) == 1 && con[0] != "no-new-privileges" { - if strings.Contains(opt, ":") { - con = strings.SplitN(opt, ":", 2) - } else { - return securityOpts, errors.Errorf("Invalid --security-opt: %q", opt) - } - } - if con[0] == "seccomp" && con[1] != "unconfined" { - f, err := ioutil.ReadFile(con[1]) - if err != nil { - return securityOpts, errors.Errorf("opening seccomp profile (%s) failed: %v", con[1], err) - } - b := bytes.NewBuffer(nil) - if err := json.Compact(b, f); err != nil { - return securityOpts, errors.Errorf("compacting json for seccomp profile (%s) failed: %v", con[1], err) - } - securityOpts[key] = fmt.Sprintf("seccomp=%s", b.Bytes()) - } - } - - return securityOpts, nil -} - -// parses storage options per container into a map -func parseStorageOpts(storageOpts []string) (map[string]string, error) { - m := make(map[string]string) - for _, option := range storageOpts { - if strings.Contains(option, "=") { - opt := strings.SplitN(option, "=", 2) - m[opt[0]] = opt[1] - } else { - return nil, errors.Errorf("invalid storage option") - } - } - return m, nil -} - -// parseDevice parses a device mapping string to a container.DeviceMapping struct -func parseDevice(device string) (container.DeviceMapping, error) { - src := "" - dst := "" - permissions := "rwm" - arr := strings.Split(device, ":") - switch len(arr) { - case 3: - permissions = arr[2] - fallthrough - case 2: - if validDeviceMode(arr[1]) { - permissions = arr[1] - } else { - dst = arr[1] - } - fallthrough - case 1: - src = arr[0] - default: - return container.DeviceMapping{}, errors.Errorf("invalid device specification: %s", device) - } - - if dst == "" { - dst = src - } - - deviceMapping := container.DeviceMapping{ - PathOnHost: src, - PathInContainer: dst, - CgroupPermissions: permissions, - } - return deviceMapping, nil -} - -// validateDeviceCgroupRule validates a device cgroup rule string format -// It will make sure 'val' is in the form: -// 'type major:minor mode' -func validateDeviceCgroupRule(val string) (string, error) { - if deviceCgroupRuleRegexp.MatchString(val) { - return val, nil - } - - return val, errors.Errorf("invalid device cgroup format '%s'", val) -} - -// validDeviceMode checks if the mode for device is valid or not. -// Valid mode is a composition of r (read), w (write), and m (mknod). -func validDeviceMode(mode string) bool { - var legalDeviceMode = map[rune]bool{ - 'r': true, - 'w': true, - 'm': true, - } - if mode == "" { - return false - } - for _, c := range mode { - if !legalDeviceMode[c] { - return false - } - legalDeviceMode[c] = false - } - return true -} - -// validateDevice validates a path for devices -// It will make sure 'val' is in the form: -// [host-dir:]container-path[:mode] -// It also validates the device mode. -func validateDevice(val string) (string, error) { - return validatePath(val, validDeviceMode) -} - -func validatePath(val string, validator func(string) bool) (string, error) { - var containerPath string - var mode string - - if strings.Count(val, ":") > 2 { - return val, errors.Errorf("bad format for path: %s", val) - } - - split := strings.SplitN(val, ":", 3) - if split[0] == "" { - return val, errors.Errorf("bad format for path: %s", val) - } - switch len(split) { - case 1: - containerPath = split[0] - val = path.Clean(containerPath) - case 2: - if isValid := validator(split[1]); isValid { - containerPath = split[0] - mode = split[1] - val = fmt.Sprintf("%s:%s", path.Clean(containerPath), mode) - } else { - containerPath = split[1] - val = fmt.Sprintf("%s:%s", split[0], path.Clean(containerPath)) - } - case 3: - containerPath = split[1] - mode = split[2] - if isValid := validator(split[2]); !isValid { - return val, errors.Errorf("bad mode specified: %s", mode) - } - val = fmt.Sprintf("%s:%s:%s", split[0], containerPath, mode) - } - - if !path.IsAbs(containerPath) { - return val, errors.Errorf("%s is not an absolute path", containerPath) - } - return val, nil -} - -// validateAttach validates that the specified string is a valid attach option. -func validateAttach(val string) (string, error) { - s := strings.ToLower(val) - for _, str := range []string{"stdin", "stdout", "stderr"} { - if s == str { - return s, nil - } - } - return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR") -} diff --git a/vendor/github.com/docker/cli/cli/command/container/opts_test.go b/vendor/github.com/docker/cli/cli/command/container/opts_test.go deleted file mode 100644 index 08c1d07da..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/opts_test.go +++ /dev/null @@ -1,633 +0,0 @@ -package container - -import ( - "fmt" - "io/ioutil" - "os" - "runtime" - "strings" - "testing" - "time" - - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types/container" - networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/go-connections/nat" - "github.com/pkg/errors" - "github.com/spf13/pflag" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestValidateAttach(t *testing.T) { - valid := []string{ - "stdin", - "stdout", - "stderr", - "STDIN", - "STDOUT", - "STDERR", - } - if _, err := validateAttach("invalid"); err == nil { - t.Fatal("Expected error with [valid streams are STDIN, STDOUT and STDERR], got nothing") - } - - for _, attach := range valid { - value, err := validateAttach(attach) - if err != nil { - t.Fatal(err) - } - if value != strings.ToLower(attach) { - t.Fatalf("Expected [%v], got [%v]", attach, value) - } - } -} - -func parseRun(args []string) (*container.Config, *container.HostConfig, *networktypes.NetworkingConfig, error) { - flags := pflag.NewFlagSet("run", pflag.ContinueOnError) - flags.SetOutput(ioutil.Discard) - flags.Usage = nil - copts := addFlags(flags) - if err := flags.Parse(args); err != nil { - return nil, nil, nil, err - } - // TODO: fix tests to accept ContainerConfig - containerConfig, err := parse(flags, copts) - if err != nil { - return nil, nil, nil, err - } - return containerConfig.Config, containerConfig.HostConfig, containerConfig.NetworkingConfig, err -} - -func parseMustError(t *testing.T, args string) { - _, _, _, err := parseRun(strings.Split(args+" ubuntu bash", " ")) - assert.Error(t, err, args) -} - -func mustParse(t *testing.T, args string) (*container.Config, *container.HostConfig) { - config, hostConfig, _, err := parseRun(append(strings.Split(args, " "), "ubuntu", "bash")) - assert.NoError(t, err) - return config, hostConfig -} - -func TestParseRunLinks(t *testing.T) { - if _, hostConfig := mustParse(t, "--link a:b"); len(hostConfig.Links) == 0 || hostConfig.Links[0] != "a:b" { - t.Fatalf("Error parsing links. Expected []string{\"a:b\"}, received: %v", hostConfig.Links) - } - if _, hostConfig := mustParse(t, "--link a:b --link c:d"); len(hostConfig.Links) < 2 || hostConfig.Links[0] != "a:b" || hostConfig.Links[1] != "c:d" { - t.Fatalf("Error parsing links. Expected []string{\"a:b\", \"c:d\"}, received: %v", hostConfig.Links) - } - if _, hostConfig := mustParse(t, ""); len(hostConfig.Links) != 0 { - t.Fatalf("Error parsing links. No link expected, received: %v", hostConfig.Links) - } -} - -func TestParseRunAttach(t *testing.T) { - if config, _ := mustParse(t, "-a stdin"); !config.AttachStdin || config.AttachStdout || config.AttachStderr { - t.Fatalf("Error parsing attach flags. Expect only Stdin enabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) - } - if config, _ := mustParse(t, "-a stdin -a stdout"); !config.AttachStdin || !config.AttachStdout || config.AttachStderr { - t.Fatalf("Error parsing attach flags. Expect only Stdin and Stdout enabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) - } - if config, _ := mustParse(t, "-a stdin -a stdout -a stderr"); !config.AttachStdin || !config.AttachStdout || !config.AttachStderr { - t.Fatalf("Error parsing attach flags. Expect all attach enabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) - } - if config, _ := mustParse(t, ""); config.AttachStdin || !config.AttachStdout || !config.AttachStderr { - t.Fatalf("Error parsing attach flags. Expect Stdin disabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) - } - if config, _ := mustParse(t, "-i"); !config.AttachStdin || !config.AttachStdout || !config.AttachStderr { - t.Fatalf("Error parsing attach flags. Expect Stdin enabled. Received: in: %v, out: %v, err: %v", config.AttachStdin, config.AttachStdout, config.AttachStderr) - } -} - -func TestParseRunWithInvalidArgs(t *testing.T) { - parseMustError(t, "-a") - parseMustError(t, "-a invalid") - parseMustError(t, "-a invalid -a stdout") - parseMustError(t, "-a stdout -a stderr -d") - parseMustError(t, "-a stdin -d") - parseMustError(t, "-a stdout -d") - parseMustError(t, "-a stderr -d") - parseMustError(t, "-d --rm") -} - -// nolint: gocyclo -func TestParseWithVolumes(t *testing.T) { - - // A single volume - arr, tryit := setupPlatformVolume([]string{`/tmp`}, []string{`c:\tmp`}) - if config, hostConfig := mustParse(t, tryit); hostConfig.Binds != nil { - t.Fatalf("Error parsing volume flags, %q should not mount-bind anything. Received %v", tryit, hostConfig.Binds) - } else if _, exists := config.Volumes[arr[0]]; !exists { - t.Fatalf("Error parsing volume flags, %q is missing from volumes. Received %v", tryit, config.Volumes) - } - - // Two volumes - arr, tryit = setupPlatformVolume([]string{`/tmp`, `/var`}, []string{`c:\tmp`, `c:\var`}) - if config, hostConfig := mustParse(t, tryit); hostConfig.Binds != nil { - t.Fatalf("Error parsing volume flags, %q should not mount-bind anything. Received %v", tryit, hostConfig.Binds) - } else if _, exists := config.Volumes[arr[0]]; !exists { - t.Fatalf("Error parsing volume flags, %s is missing from volumes. Received %v", arr[0], config.Volumes) - } else if _, exists := config.Volumes[arr[1]]; !exists { - t.Fatalf("Error parsing volume flags, %s is missing from volumes. Received %v", arr[1], config.Volumes) - } - - // A single bind mount - arr, tryit = setupPlatformVolume([]string{`/hostTmp:/containerTmp`}, []string{os.Getenv("TEMP") + `:c:\containerTmp`}) - if config, hostConfig := mustParse(t, tryit); hostConfig.Binds == nil || hostConfig.Binds[0] != arr[0] { - t.Fatalf("Error parsing volume flags, %q should mount-bind the path before the colon into the path after the colon. Received %v %v", arr[0], hostConfig.Binds, config.Volumes) - } - - // Two bind mounts. - arr, tryit = setupPlatformVolume([]string{`/hostTmp:/containerTmp`, `/hostVar:/containerVar`}, []string{os.Getenv("ProgramData") + `:c:\ContainerPD`, os.Getenv("TEMP") + `:c:\containerTmp`}) - if _, hostConfig := mustParse(t, tryit); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], arr[0], arr[1]) != nil { - t.Fatalf("Error parsing volume flags, `%s and %s` did not mount-bind correctly. Received %v", arr[0], arr[1], hostConfig.Binds) - } - - // Two bind mounts, first read-only, second read-write. - // TODO Windows: The Windows version uses read-write as that's the only mode it supports. Can change this post TP4 - arr, tryit = setupPlatformVolume( - []string{`/hostTmp:/containerTmp:ro`, `/hostVar:/containerVar:rw`}, - []string{os.Getenv("TEMP") + `:c:\containerTmp:rw`, os.Getenv("ProgramData") + `:c:\ContainerPD:rw`}) - if _, hostConfig := mustParse(t, tryit); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], arr[0], arr[1]) != nil { - t.Fatalf("Error parsing volume flags, `%s and %s` did not mount-bind correctly. Received %v", arr[0], arr[1], hostConfig.Binds) - } - - // Similar to previous test but with alternate modes which are only supported by Linux - if runtime.GOOS != "windows" { - arr, tryit = setupPlatformVolume([]string{`/hostTmp:/containerTmp:ro,Z`, `/hostVar:/containerVar:rw,Z`}, []string{}) - if _, hostConfig := mustParse(t, tryit); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], arr[0], arr[1]) != nil { - t.Fatalf("Error parsing volume flags, `%s and %s` did not mount-bind correctly. Received %v", arr[0], arr[1], hostConfig.Binds) - } - - arr, tryit = setupPlatformVolume([]string{`/hostTmp:/containerTmp:Z`, `/hostVar:/containerVar:z`}, []string{}) - if _, hostConfig := mustParse(t, tryit); hostConfig.Binds == nil || compareRandomizedStrings(hostConfig.Binds[0], hostConfig.Binds[1], arr[0], arr[1]) != nil { - t.Fatalf("Error parsing volume flags, `%s and %s` did not mount-bind correctly. Received %v", arr[0], arr[1], hostConfig.Binds) - } - } - - // One bind mount and one volume - arr, tryit = setupPlatformVolume([]string{`/hostTmp:/containerTmp`, `/containerVar`}, []string{os.Getenv("TEMP") + `:c:\containerTmp`, `c:\containerTmp`}) - if config, hostConfig := mustParse(t, tryit); hostConfig.Binds == nil || len(hostConfig.Binds) > 1 || hostConfig.Binds[0] != arr[0] { - t.Fatalf("Error parsing volume flags, %s and %s should only one and only one bind mount %s. Received %s", arr[0], arr[1], arr[0], hostConfig.Binds) - } else if _, exists := config.Volumes[arr[1]]; !exists { - t.Fatalf("Error parsing volume flags %s and %s. %s is missing from volumes. Received %v", arr[0], arr[1], arr[1], config.Volumes) - } - - // Root to non-c: drive letter (Windows specific) - if runtime.GOOS == "windows" { - arr, tryit = setupPlatformVolume([]string{}, []string{os.Getenv("SystemDrive") + `\:d:`}) - if config, hostConfig := mustParse(t, tryit); hostConfig.Binds == nil || len(hostConfig.Binds) > 1 || hostConfig.Binds[0] != arr[0] || len(config.Volumes) != 0 { - t.Fatalf("Error parsing %s. Should have a single bind mount and no volumes", arr[0]) - } - } - -} - -// setupPlatformVolume takes two arrays of volume specs - a Unix style -// spec and a Windows style spec. Depending on the platform being unit tested, -// it returns one of them, along with a volume string that would be passed -// on the docker CLI (e.g. -v /bar -v /foo). -func setupPlatformVolume(u []string, w []string) ([]string, string) { - var a []string - if runtime.GOOS == "windows" { - a = w - } else { - a = u - } - s := "" - for _, v := range a { - s = s + "-v " + v + " " - } - return a, s -} - -// check if (a == c && b == d) || (a == d && b == c) -// because maps are randomized -func compareRandomizedStrings(a, b, c, d string) error { - if a == c && b == d { - return nil - } - if a == d && b == c { - return nil - } - return errors.Errorf("strings don't match") -} - -// Simple parse with MacAddress validation -func TestParseWithMacAddress(t *testing.T) { - invalidMacAddress := "--mac-address=invalidMacAddress" - validMacAddress := "--mac-address=92:d0:c6:0a:29:33" - if _, _, _, err := parseRun([]string{invalidMacAddress, "img", "cmd"}); err != nil && err.Error() != "invalidMacAddress is not a valid mac address" { - t.Fatalf("Expected an error with %v mac-address, got %v", invalidMacAddress, err) - } - if config, _ := mustParse(t, validMacAddress); config.MacAddress != "92:d0:c6:0a:29:33" { - t.Fatalf("Expected the config to have '92:d0:c6:0a:29:33' as MacAddress, got '%v'", config.MacAddress) - } -} - -func TestParseWithMemory(t *testing.T) { - invalidMemory := "--memory=invalid" - _, _, _, err := parseRun([]string{invalidMemory, "img", "cmd"}) - testutil.ErrorContains(t, err, invalidMemory) - - _, hostconfig := mustParse(t, "--memory=1G") - assert.Equal(t, int64(1073741824), hostconfig.Memory) -} - -func TestParseWithMemorySwap(t *testing.T) { - invalidMemory := "--memory-swap=invalid" - - _, _, _, err := parseRun([]string{invalidMemory, "img", "cmd"}) - testutil.ErrorContains(t, err, invalidMemory) - - _, hostconfig := mustParse(t, "--memory-swap=1G") - assert.Equal(t, int64(1073741824), hostconfig.MemorySwap) - - _, hostconfig = mustParse(t, "--memory-swap=-1") - assert.Equal(t, int64(-1), hostconfig.MemorySwap) -} - -func TestParseHostname(t *testing.T) { - validHostnames := map[string]string{ - "hostname": "hostname", - "host-name": "host-name", - "hostname123": "hostname123", - "123hostname": "123hostname", - "hostname-of-63-bytes-long-should-be-valid-and-without-any-error": "hostname-of-63-bytes-long-should-be-valid-and-without-any-error", - } - hostnameWithDomain := "--hostname=hostname.domainname" - hostnameWithDomainTld := "--hostname=hostname.domainname.tld" - for hostname, expectedHostname := range validHostnames { - if config, _ := mustParse(t, fmt.Sprintf("--hostname=%s", hostname)); config.Hostname != expectedHostname { - t.Fatalf("Expected the config to have 'hostname' as hostname, got '%v'", config.Hostname) - } - } - if config, _ := mustParse(t, hostnameWithDomain); config.Hostname != "hostname.domainname" && config.Domainname != "" { - t.Fatalf("Expected the config to have 'hostname' as hostname.domainname, got '%v'", config.Hostname) - } - if config, _ := mustParse(t, hostnameWithDomainTld); config.Hostname != "hostname.domainname.tld" && config.Domainname != "" { - t.Fatalf("Expected the config to have 'hostname' as hostname.domainname.tld, got '%v'", config.Hostname) - } -} - -func TestParseWithExpose(t *testing.T) { - invalids := map[string]string{ - ":": "invalid port format for --expose: :", - "8080:9090": "invalid port format for --expose: 8080:9090", - "/tcp": "invalid range format for --expose: /tcp, error: Empty string specified for ports.", - "/udp": "invalid range format for --expose: /udp, error: Empty string specified for ports.", - "NaN/tcp": `invalid range format for --expose: NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`, - "NaN-NaN/tcp": `invalid range format for --expose: NaN-NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`, - "8080-NaN/tcp": `invalid range format for --expose: 8080-NaN/tcp, error: strconv.ParseUint: parsing "NaN": invalid syntax`, - "1234567890-8080/tcp": `invalid range format for --expose: 1234567890-8080/tcp, error: strconv.ParseUint: parsing "1234567890": value out of range`, - } - valids := map[string][]nat.Port{ - "8080/tcp": {"8080/tcp"}, - "8080/udp": {"8080/udp"}, - "8080/ncp": {"8080/ncp"}, - "8080-8080/udp": {"8080/udp"}, - "8080-8082/tcp": {"8080/tcp", "8081/tcp", "8082/tcp"}, - } - for expose, expectedError := range invalids { - if _, _, _, err := parseRun([]string{fmt.Sprintf("--expose=%v", expose), "img", "cmd"}); err == nil || err.Error() != expectedError { - t.Fatalf("Expected error '%v' with '--expose=%v', got '%v'", expectedError, expose, err) - } - } - for expose, exposedPorts := range valids { - config, _, _, err := parseRun([]string{fmt.Sprintf("--expose=%v", expose), "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if len(config.ExposedPorts) != len(exposedPorts) { - t.Fatalf("Expected %v exposed port, got %v", len(exposedPorts), len(config.ExposedPorts)) - } - for _, port := range exposedPorts { - if _, ok := config.ExposedPorts[port]; !ok { - t.Fatalf("Expected %v, got %v", exposedPorts, config.ExposedPorts) - } - } - } - // Merge with actual published port - config, _, _, err := parseRun([]string{"--publish=80", "--expose=80-81/tcp", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if len(config.ExposedPorts) != 2 { - t.Fatalf("Expected 2 exposed ports, got %v", config.ExposedPorts) - } - ports := []nat.Port{"80/tcp", "81/tcp"} - for _, port := range ports { - if _, ok := config.ExposedPorts[port]; !ok { - t.Fatalf("Expected %v, got %v", ports, config.ExposedPorts) - } - } -} - -func TestParseDevice(t *testing.T) { - valids := map[string]container.DeviceMapping{ - "/dev/snd": { - PathOnHost: "/dev/snd", - PathInContainer: "/dev/snd", - CgroupPermissions: "rwm", - }, - "/dev/snd:rw": { - PathOnHost: "/dev/snd", - PathInContainer: "/dev/snd", - CgroupPermissions: "rw", - }, - "/dev/snd:/something": { - PathOnHost: "/dev/snd", - PathInContainer: "/something", - CgroupPermissions: "rwm", - }, - "/dev/snd:/something:rw": { - PathOnHost: "/dev/snd", - PathInContainer: "/something", - CgroupPermissions: "rw", - }, - } - for device, deviceMapping := range valids { - _, hostconfig, _, err := parseRun([]string{fmt.Sprintf("--device=%v", device), "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if len(hostconfig.Devices) != 1 { - t.Fatalf("Expected 1 devices, got %v", hostconfig.Devices) - } - if hostconfig.Devices[0] != deviceMapping { - t.Fatalf("Expected %v, got %v", deviceMapping, hostconfig.Devices) - } - } - -} - -func TestParseModes(t *testing.T) { - // pid ko - _, _, _, err := parseRun([]string{"--pid=container:", "img", "cmd"}) - testutil.ErrorContains(t, err, "--pid: invalid PID mode") - - // pid ok - _, hostconfig, _, err := parseRun([]string{"--pid=host", "img", "cmd"}) - require.NoError(t, err) - if !hostconfig.PidMode.Valid() { - t.Fatalf("Expected a valid PidMode, got %v", hostconfig.PidMode) - } - - // uts ko - _, _, _, err = parseRun([]string{"--uts=container:", "img", "cmd"}) - testutil.ErrorContains(t, err, "--uts: invalid UTS mode") - - // uts ok - _, hostconfig, _, err = parseRun([]string{"--uts=host", "img", "cmd"}) - require.NoError(t, err) - if !hostconfig.UTSMode.Valid() { - t.Fatalf("Expected a valid UTSMode, got %v", hostconfig.UTSMode) - } - - // shm-size ko - expectedErr := `invalid argument "a128m" for --shm-size=a128m: invalid size: 'a128m'` - _, _, _, err = parseRun([]string{"--shm-size=a128m", "img", "cmd"}) - testutil.ErrorContains(t, err, expectedErr) - - // shm-size ok - _, hostconfig, _, err = parseRun([]string{"--shm-size=128m", "img", "cmd"}) - require.NoError(t, err) - if hostconfig.ShmSize != 134217728 { - t.Fatalf("Expected a valid ShmSize, got %d", hostconfig.ShmSize) - } -} - -func TestParseRestartPolicy(t *testing.T) { - invalids := map[string]string{ - "always:2:3": "invalid restart policy format", - "on-failure:invalid": "maximum retry count must be an integer", - } - valids := map[string]container.RestartPolicy{ - "": {}, - "always": { - Name: "always", - MaximumRetryCount: 0, - }, - "on-failure:1": { - Name: "on-failure", - MaximumRetryCount: 1, - }, - } - for restart, expectedError := range invalids { - if _, _, _, err := parseRun([]string{fmt.Sprintf("--restart=%s", restart), "img", "cmd"}); err == nil || err.Error() != expectedError { - t.Fatalf("Expected an error with message '%v' for %v, got %v", expectedError, restart, err) - } - } - for restart, expected := range valids { - _, hostconfig, _, err := parseRun([]string{fmt.Sprintf("--restart=%v", restart), "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if hostconfig.RestartPolicy != expected { - t.Fatalf("Expected %v, got %v", expected, hostconfig.RestartPolicy) - } - } -} - -func TestParseRestartPolicyAutoRemove(t *testing.T) { - expected := "Conflicting options: --restart and --rm" - _, _, _, err := parseRun([]string{"--rm", "--restart=always", "img", "cmd"}) - if err == nil || err.Error() != expected { - t.Fatalf("Expected error %v, but got none", expected) - } -} - -func TestParseHealth(t *testing.T) { - checkOk := func(args ...string) *container.HealthConfig { - config, _, _, err := parseRun(args) - if err != nil { - t.Fatalf("%#v: %v", args, err) - } - return config.Healthcheck - } - checkError := func(expected string, args ...string) { - config, _, _, err := parseRun(args) - if err == nil { - t.Fatalf("Expected error, but got %#v", config) - } - if err.Error() != expected { - t.Fatalf("Expected %#v, got %#v", expected, err) - } - } - health := checkOk("--no-healthcheck", "img", "cmd") - if health == nil || len(health.Test) != 1 || health.Test[0] != "NONE" { - t.Fatalf("--no-healthcheck failed: %#v", health) - } - - health = checkOk("--health-cmd=/check.sh -q", "img", "cmd") - if len(health.Test) != 2 || health.Test[0] != "CMD-SHELL" || health.Test[1] != "/check.sh -q" { - t.Fatalf("--health-cmd: got %#v", health.Test) - } - if health.Timeout != 0 { - t.Fatalf("--health-cmd: timeout = %s", health.Timeout) - } - - checkError("--no-healthcheck conflicts with --health-* options", - "--no-healthcheck", "--health-cmd=/check.sh -q", "img", "cmd") - - health = checkOk("--health-timeout=2s", "--health-retries=3", "--health-interval=4.5s", "--health-start-period=5s", "img", "cmd") - if health.Timeout != 2*time.Second || health.Retries != 3 || health.Interval != 4500*time.Millisecond || health.StartPeriod != 5*time.Second { - t.Fatalf("--health-*: got %#v", health) - } -} - -func TestParseLoggingOpts(t *testing.T) { - // logging opts ko - if _, _, _, err := parseRun([]string{"--log-driver=none", "--log-opt=anything", "img", "cmd"}); err == nil || err.Error() != "invalid logging opts for driver none" { - t.Fatalf("Expected an error with message 'invalid logging opts for driver none', got %v", err) - } - // logging opts ok - _, hostconfig, _, err := parseRun([]string{"--log-driver=syslog", "--log-opt=something", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if hostconfig.LogConfig.Type != "syslog" || len(hostconfig.LogConfig.Config) != 1 { - t.Fatalf("Expected a 'syslog' LogConfig with one config, got %v", hostconfig.RestartPolicy) - } -} - -func TestParseEnvfileVariables(t *testing.T) { - e := "open nonexistent: no such file or directory" - if runtime.GOOS == "windows" { - e = "open nonexistent: The system cannot find the file specified." - } - // env ko - if _, _, _, err := parseRun([]string{"--env-file=nonexistent", "img", "cmd"}); err == nil || err.Error() != e { - t.Fatalf("Expected an error with message '%s', got %v", e, err) - } - // env ok - config, _, _, err := parseRun([]string{"--env-file=testdata/valid.env", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if len(config.Env) != 1 || config.Env[0] != "ENV1=value1" { - t.Fatalf("Expected a config with [ENV1=value1], got %v", config.Env) - } - config, _, _, err = parseRun([]string{"--env-file=testdata/valid.env", "--env=ENV2=value2", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if len(config.Env) != 2 || config.Env[0] != "ENV1=value1" || config.Env[1] != "ENV2=value2" { - t.Fatalf("Expected a config with [ENV1=value1 ENV2=value2], got %v", config.Env) - } -} - -func TestParseEnvfileVariablesWithBOMUnicode(t *testing.T) { - // UTF8 with BOM - config, _, _, err := parseRun([]string{"--env-file=testdata/utf8.env", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - env := []string{"FOO=BAR", "HELLO=" + string([]byte{0xe6, 0x82, 0xa8, 0xe5, 0xa5, 0xbd}), "BAR=FOO"} - if len(config.Env) != len(env) { - t.Fatalf("Expected a config with %d env variables, got %v: %v", len(env), len(config.Env), config.Env) - } - for i, v := range env { - if config.Env[i] != v { - t.Fatalf("Expected a config with [%s], got %v", v, []byte(config.Env[i])) - } - } - - // UTF16 with BOM - e := "contains invalid utf8 bytes at line" - if _, _, _, err := parseRun([]string{"--env-file=testdata/utf16.env", "img", "cmd"}); err == nil || !strings.Contains(err.Error(), e) { - t.Fatalf("Expected an error with message '%s', got %v", e, err) - } - // UTF16BE with BOM - if _, _, _, err := parseRun([]string{"--env-file=testdata/utf16be.env", "img", "cmd"}); err == nil || !strings.Contains(err.Error(), e) { - t.Fatalf("Expected an error with message '%s', got %v", e, err) - } -} - -func TestParseLabelfileVariables(t *testing.T) { - e := "open nonexistent: no such file or directory" - if runtime.GOOS == "windows" { - e = "open nonexistent: The system cannot find the file specified." - } - // label ko - if _, _, _, err := parseRun([]string{"--label-file=nonexistent", "img", "cmd"}); err == nil || err.Error() != e { - t.Fatalf("Expected an error with message '%s', got %v", e, err) - } - // label ok - config, _, _, err := parseRun([]string{"--label-file=testdata/valid.label", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if len(config.Labels) != 1 || config.Labels["LABEL1"] != "value1" { - t.Fatalf("Expected a config with [LABEL1:value1], got %v", config.Labels) - } - config, _, _, err = parseRun([]string{"--label-file=testdata/valid.label", "--label=LABEL2=value2", "img", "cmd"}) - if err != nil { - t.Fatal(err) - } - if len(config.Labels) != 2 || config.Labels["LABEL1"] != "value1" || config.Labels["LABEL2"] != "value2" { - t.Fatalf("Expected a config with [LABEL1:value1 LABEL2:value2], got %v", config.Labels) - } -} - -func TestParseEntryPoint(t *testing.T) { - config, _, _, err := parseRun([]string{"--entrypoint=anything", "cmd", "img"}) - if err != nil { - t.Fatal(err) - } - if len(config.Entrypoint) != 1 && config.Entrypoint[0] != "anything" { - t.Fatalf("Expected entrypoint 'anything', got %v", config.Entrypoint) - } -} - -func TestValidateDevice(t *testing.T) { - valid := []string{ - "/home", - "/home:/home", - "/home:/something/else", - "/with space", - "/home:/with space", - "relative:/absolute-path", - "hostPath:/containerPath:r", - "/hostPath:/containerPath:rw", - "/hostPath:/containerPath:mrw", - } - invalid := map[string]string{ - "": "bad format for path: ", - "./": "./ is not an absolute path", - "../": "../ is not an absolute path", - "/:../": "../ is not an absolute path", - "/:path": "path is not an absolute path", - ":": "bad format for path: :", - "/tmp:": " is not an absolute path", - ":test": "bad format for path: :test", - ":/test": "bad format for path: :/test", - "tmp:": " is not an absolute path", - ":test:": "bad format for path: :test:", - "::": "bad format for path: ::", - ":::": "bad format for path: :::", - "/tmp:::": "bad format for path: /tmp:::", - ":/tmp::": "bad format for path: :/tmp::", - "path:ro": "ro is not an absolute path", - "path:rr": "rr is not an absolute path", - "a:/b:ro": "bad mode specified: ro", - "a:/b:rr": "bad mode specified: rr", - } - - for _, path := range valid { - if _, err := validateDevice(path); err != nil { - t.Fatalf("ValidateDevice(`%q`) should succeed: error %q", path, err) - } - } - - for path, expectedError := range invalid { - if _, err := validateDevice(path); err == nil { - t.Fatalf("ValidateDevice(`%q`) should have failed validation", path) - } else { - if err.Error() != expectedError { - t.Fatalf("ValidateDevice(`%q`) error should contain %q, got %q", path, expectedError, err.Error()) - } - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/container/pause.go b/vendor/github.com/docker/cli/cli/command/container/pause.go deleted file mode 100644 index 9dc404d78..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/pause.go +++ /dev/null @@ -1,49 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type pauseOptions struct { - containers []string -} - -// NewPauseCommand creates a new cobra.Command for `docker pause` -func NewPauseCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts pauseOptions - - return &cobra.Command{ - Use: "pause CONTAINER [CONTAINER...]", - Short: "Pause all processes within one or more containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - return runPause(dockerCli, &opts) - }, - } -} - -func runPause(dockerCli *command.DockerCli, opts *pauseOptions) error { - ctx := context.Background() - - var errs []string - errChan := parallelOperation(ctx, opts.containers, dockerCli.Client().ContainerPause) - for _, container := range opts.containers { - if err := <-errChan; err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintln(dockerCli.Out(), container) - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/port.go b/vendor/github.com/docker/cli/cli/command/container/port.go deleted file mode 100644 index 13a1ae423..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/port.go +++ /dev/null @@ -1,78 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/go-connections/nat" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type portOptions struct { - container string - - port string -} - -// NewPortCommand creates a new cobra.Command for `docker port` -func NewPortCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts portOptions - - cmd := &cobra.Command{ - Use: "port CONTAINER [PRIVATE_PORT[/PROTO]]", - Short: "List port mappings or a specific mapping for the container", - Args: cli.RequiresRangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - if len(args) > 1 { - opts.port = args[1] - } - return runPort(dockerCli, &opts) - }, - } - return cmd -} - -func runPort(dockerCli *command.DockerCli, opts *portOptions) error { - ctx := context.Background() - - c, err := dockerCli.Client().ContainerInspect(ctx, opts.container) - if err != nil { - return err - } - - if opts.port != "" { - port := opts.port - proto := "tcp" - parts := strings.SplitN(port, "/", 2) - - if len(parts) == 2 && len(parts[1]) != 0 { - port = parts[0] - proto = parts[1] - } - natPort := port + "/" + proto - newP, err := nat.NewPort(proto, port) - if err != nil { - return err - } - if frontends, exists := c.NetworkSettings.Ports[newP]; exists && frontends != nil { - for _, frontend := range frontends { - fmt.Fprintf(dockerCli.Out(), "%s:%s\n", frontend.HostIP, frontend.HostPort) - } - return nil - } - return errors.Errorf("Error: No public port '%s' published for %s", natPort, opts.container) - } - - for from, frontends := range c.NetworkSettings.Ports { - for _, frontend := range frontends { - fmt.Fprintf(dockerCli.Out(), "%s -> %s:%s\n", from, frontend.HostIP, frontend.HostPort) - } - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/prune.go b/vendor/github.com/docker/cli/cli/command/container/prune.go deleted file mode 100644 index 38ac64729..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/prune.go +++ /dev/null @@ -1,78 +0,0 @@ -package container - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - units "github.com/docker/go-units" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type pruneOptions struct { - force bool - filter opts.FilterOpt -} - -// NewPruneCommand returns a new cobra prune command for containers -func NewPruneCommand(dockerCli command.Cli) *cobra.Command { - options := pruneOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "prune [OPTIONS]", - Short: "Remove all stopped containers", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - spaceReclaimed, output, err := runPrune(dockerCli, options) - if err != nil { - return err - } - if output != "" { - fmt.Fprintln(dockerCli.Out(), output) - } - fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) - return nil - }, - Tags: map[string]string{"version": "1.25"}, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") - flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'until=')") - - return cmd -} - -const warning = `WARNING! This will remove all stopped containers. -Are you sure you want to continue?` - -func runPrune(dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint64, output string, err error) { - pruneFilters := command.PruneFilters(dockerCli, options.filter.Value()) - - if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) { - return - } - - report, err := dockerCli.Client().ContainersPrune(context.Background(), pruneFilters) - if err != nil { - return - } - - if len(report.ContainersDeleted) > 0 { - output = "Deleted Containers:\n" - for _, id := range report.ContainersDeleted { - output += id + "\n" - } - spaceReclaimed = report.SpaceReclaimed - } - - return -} - -// RunPrune calls the Container Prune API -// This returns the amount of space reclaimed and a detailed output string -func RunPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return runPrune(dockerCli, pruneOptions{force: true, filter: filter}) -} diff --git a/vendor/github.com/docker/cli/cli/command/container/ps_test.go b/vendor/github.com/docker/cli/cli/command/container/ps_test.go deleted file mode 100644 index d5a51d92e..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/ps_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package container - -import ( - "testing" - - "github.com/docker/cli/opts" - "github.com/stretchr/testify/assert" -) - -func TestBuildContainerListOptions(t *testing.T) { - filters := opts.NewFilterOpt() - assert.NoError(t, filters.Set("foo=bar")) - assert.NoError(t, filters.Set("baz=foo")) - - contexts := []struct { - psOpts *psOptions - expectedAll bool - expectedSize bool - expectedLimit int - expectedFilters map[string]string - }{ - { - psOpts: &psOptions{ - all: true, - size: true, - last: 5, - filter: filters, - }, - expectedAll: true, - expectedSize: true, - expectedLimit: 5, - expectedFilters: map[string]string{ - "foo": "bar", - "baz": "foo", - }, - }, - { - psOpts: &psOptions{ - all: true, - size: true, - last: -1, - nLatest: true, - }, - expectedAll: true, - expectedSize: true, - expectedLimit: 1, - expectedFilters: make(map[string]string), - }, - { - psOpts: &psOptions{ - all: true, - size: false, - last: 5, - filter: filters, - // With .Size, size should be true - format: "{{.Size}}", - }, - expectedAll: true, - expectedSize: true, - expectedLimit: 5, - expectedFilters: map[string]string{ - "foo": "bar", - "baz": "foo", - }, - }, - { - psOpts: &psOptions{ - all: true, - size: false, - last: 5, - filter: filters, - // With .Size, size should be true - format: "{{.Size}} {{.CreatedAt}} {{.Networks}}", - }, - expectedAll: true, - expectedSize: true, - expectedLimit: 5, - expectedFilters: map[string]string{ - "foo": "bar", - "baz": "foo", - }, - }, - { - psOpts: &psOptions{ - all: true, - size: false, - last: 5, - filter: filters, - // Without .Size, size should be false - format: "{{.CreatedAt}} {{.Networks}}", - }, - expectedAll: true, - expectedSize: false, - expectedLimit: 5, - expectedFilters: map[string]string{ - "foo": "bar", - "baz": "foo", - }, - }, - } - - for _, c := range contexts { - options, err := buildContainerListOptions(c.psOpts) - assert.NoError(t, err) - - assert.Equal(t, c.expectedAll, options.All) - assert.Equal(t, c.expectedSize, options.Size) - assert.Equal(t, c.expectedLimit, options.Limit) - assert.Equal(t, len(c.expectedFilters), options.Filters.Len()) - - for k, v := range c.expectedFilters { - f := options.Filters - if !f.ExactMatch(k, v) { - t.Fatalf("Expected filter with key %s to be %s but got %s", k, v, f.Get(k)) - } - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/container/rename.go b/vendor/github.com/docker/cli/cli/command/container/rename.go deleted file mode 100644 index ad60bda3b..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/rename.go +++ /dev/null @@ -1,51 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type renameOptions struct { - oldName string - newName string -} - -// NewRenameCommand creates a new cobra.Command for `docker rename` -func NewRenameCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts renameOptions - - cmd := &cobra.Command{ - Use: "rename CONTAINER NEW_NAME", - Short: "Rename a container", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - opts.oldName = args[0] - opts.newName = args[1] - return runRename(dockerCli, &opts) - }, - } - return cmd -} - -func runRename(dockerCli *command.DockerCli, opts *renameOptions) error { - ctx := context.Background() - - oldName := strings.TrimSpace(opts.oldName) - newName := strings.TrimSpace(opts.newName) - - if oldName == "" || newName == "" { - return errors.New("Error: Neither old nor new names may be empty") - } - - if err := dockerCli.Client().ContainerRename(ctx, oldName, newName); err != nil { - fmt.Fprintln(dockerCli.Err(), err) - return errors.Errorf("Error: failed to rename container named %s", oldName) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/restart.go b/vendor/github.com/docker/cli/cli/command/container/restart.go deleted file mode 100644 index 6e1360366..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/restart.go +++ /dev/null @@ -1,62 +0,0 @@ -package container - -import ( - "fmt" - "strings" - "time" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type restartOptions struct { - nSeconds int - nSecondsChanged bool - - containers []string -} - -// NewRestartCommand creates a new cobra.Command for `docker restart` -func NewRestartCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts restartOptions - - cmd := &cobra.Command{ - Use: "restart [OPTIONS] CONTAINER [CONTAINER...]", - Short: "Restart one or more containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - opts.nSecondsChanged = cmd.Flags().Changed("time") - return runRestart(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.IntVarP(&opts.nSeconds, "time", "t", 10, "Seconds to wait for stop before killing the container") - return cmd -} - -func runRestart(dockerCli *command.DockerCli, opts *restartOptions) error { - ctx := context.Background() - var errs []string - var timeout *time.Duration - if opts.nSecondsChanged { - timeoutValue := time.Duration(opts.nSeconds) * time.Second - timeout = &timeoutValue - } - - for _, name := range opts.containers { - if err := dockerCli.Client().ContainerRestart(ctx, name, timeout); err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintln(dockerCli.Out(), name) - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/rm.go b/vendor/github.com/docker/cli/cli/command/container/rm.go deleted file mode 100644 index a7106acce..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/rm.go +++ /dev/null @@ -1,73 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type rmOptions struct { - rmVolumes bool - rmLink bool - force bool - - containers []string -} - -// NewRmCommand creates a new cobra.Command for `docker rm` -func NewRmCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts rmOptions - - cmd := &cobra.Command{ - Use: "rm [OPTIONS] CONTAINER [CONTAINER...]", - Short: "Remove one or more containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - return runRm(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.rmVolumes, "volumes", "v", false, "Remove the volumes associated with the container") - flags.BoolVarP(&opts.rmLink, "link", "l", false, "Remove the specified link") - flags.BoolVarP(&opts.force, "force", "f", false, "Force the removal of a running container (uses SIGKILL)") - return cmd -} - -func runRm(dockerCli *command.DockerCli, opts *rmOptions) error { - ctx := context.Background() - - var errs []string - options := types.ContainerRemoveOptions{ - RemoveVolumes: opts.rmVolumes, - RemoveLinks: opts.rmLink, - Force: opts.force, - } - - errChan := parallelOperation(ctx, opts.containers, func(ctx context.Context, container string) error { - container = strings.Trim(container, "/") - if container == "" { - return errors.New("Container name cannot be empty") - } - return dockerCli.Client().ContainerRemove(ctx, container, options) - }) - - for _, name := range opts.containers { - if err := <-errChan; err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintln(dockerCli.Out(), name) - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/run.go b/vendor/github.com/docker/cli/cli/command/container/run.go deleted file mode 100644 index 7ebea722d..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/run.go +++ /dev/null @@ -1,338 +0,0 @@ -package container - -import ( - "fmt" - "io" - "net/http/httputil" - "os" - "regexp" - "runtime" - "strings" - "syscall" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/pkg/term" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -type runOptions struct { - detach bool - sigProxy bool - name string - detachKeys string -} - -// NewRunCommand create a new `docker run` command -func NewRunCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts runOptions - var copts *containerOptions - - cmd := &cobra.Command{ - Use: "run [OPTIONS] IMAGE [COMMAND] [ARG...]", - Short: "Run a command in a new container", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - copts.Image = args[0] - if len(args) > 1 { - copts.Args = args[1:] - } - return runRun(dockerCli, cmd.Flags(), &opts, copts) - }, - } - - flags := cmd.Flags() - flags.SetInterspersed(false) - - // These are flags not stored in Config/HostConfig - flags.BoolVarP(&opts.detach, "detach", "d", false, "Run container in background and print container ID") - flags.BoolVar(&opts.sigProxy, "sig-proxy", true, "Proxy received signals to the process") - flags.StringVar(&opts.name, "name", "", "Assign a name to the container") - flags.StringVar(&opts.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container") - - // Add an explicit help that doesn't have a `-h` to prevent the conflict - // with hostname - flags.Bool("help", false, "Print usage") - - command.AddTrustVerificationFlags(flags) - copts = addFlags(flags) - return cmd -} - -func warnOnOomKillDisable(hostConfig container.HostConfig, stderr io.Writer) { - if hostConfig.OomKillDisable != nil && *hostConfig.OomKillDisable && hostConfig.Memory == 0 { - fmt.Fprintln(stderr, "WARNING: Disabling the OOM killer on containers without setting a '-m/--memory' limit may be dangerous.") - } -} - -// check the DNS settings passed via --dns against localhost regexp to warn if -// they are trying to set a DNS to a localhost address -func warnOnLocalhostDNS(hostConfig container.HostConfig, stderr io.Writer) { - for _, dnsIP := range hostConfig.DNS { - if isLocalhost(dnsIP) { - fmt.Fprintf(stderr, "WARNING: Localhost DNS setting (--dns=%s) may fail in containers.\n", dnsIP) - return - } - } -} - -// IPLocalhost is a regex pattern for IPv4 or IPv6 loopback range. -const ipLocalhost = `((127\.([0-9]{1,3}\.){2}[0-9]{1,3})|(::1)$)` - -var localhostIPRegexp = regexp.MustCompile(ipLocalhost) - -// IsLocalhost returns true if ip matches the localhost IP regular expression. -// Used for determining if nameserver settings are being passed which are -// localhost addresses -func isLocalhost(ip string) bool { - return localhostIPRegexp.MatchString(ip) -} - -func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, ropts *runOptions, copts *containerOptions) error { - proxyConfig := dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), copts.env.GetAll()) - newEnv := []string{} - for k, v := range proxyConfig { - if v == nil { - newEnv = append(newEnv, k) - } else { - newEnv = append(newEnv, fmt.Sprintf("%s=%s", k, *v)) - } - } - copts.env = *opts.NewListOptsRef(&newEnv, nil) - containerConfig, err := parse(flags, copts) - // just in case the parse does not exit - if err != nil { - reportError(dockerCli.Err(), "run", err.Error(), true) - return cli.StatusError{StatusCode: 125} - } - return runContainer(dockerCli, ropts, copts, containerConfig) -} - -// nolint: gocyclo -func runContainer(dockerCli *command.DockerCli, opts *runOptions, copts *containerOptions, containerConfig *containerConfig) error { - config := containerConfig.Config - hostConfig := containerConfig.HostConfig - stdout, stderr := dockerCli.Out(), dockerCli.Err() - client := dockerCli.Client() - - // TODO: pass this as an argument - cmdPath := "run" - - warnOnOomKillDisable(*hostConfig, stderr) - warnOnLocalhostDNS(*hostConfig, stderr) - - config.ArgsEscaped = false - - if !opts.detach { - if err := dockerCli.In().CheckTty(config.AttachStdin, config.Tty); err != nil { - return err - } - } else { - if copts.attach.Len() != 0 { - return errors.New("Conflicting options: -a and -d") - } - - config.AttachStdin = false - config.AttachStdout = false - config.AttachStderr = false - config.StdinOnce = false - } - - // Disable sigProxy when in TTY mode - if config.Tty { - opts.sigProxy = false - } - - // Telling the Windows daemon the initial size of the tty during start makes - // a far better user experience rather than relying on subsequent resizes - // to cause things to catch up. - if runtime.GOOS == "windows" { - hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = dockerCli.Out().GetTtySize() - } - - ctx, cancelFun := context.WithCancel(context.Background()) - - createResponse, err := createContainer(ctx, dockerCli, containerConfig, opts.name) - if err != nil { - reportError(stderr, cmdPath, err.Error(), true) - return runStartContainerErr(err) - } - if opts.sigProxy { - sigc := ForwardAllSignals(ctx, dockerCli, createResponse.ID) - defer signal.StopCatch(sigc) - } - - var ( - waitDisplayID chan struct{} - errCh chan error - ) - if !config.AttachStdout && !config.AttachStderr { - // Make this asynchronous to allow the client to write to stdin before having to read the ID - waitDisplayID = make(chan struct{}) - go func() { - defer close(waitDisplayID) - fmt.Fprintln(stdout, createResponse.ID) - }() - } - attach := config.AttachStdin || config.AttachStdout || config.AttachStderr - if attach { - if opts.detachKeys != "" { - dockerCli.ConfigFile().DetachKeys = opts.detachKeys - } - - close, err := attachContainer(ctx, dockerCli, &errCh, config, createResponse.ID) - - if err != nil { - return err - } - defer close() - } - - statusChan := waitExitOrRemoved(ctx, dockerCli, createResponse.ID, copts.autoRemove) - - //start the container - if err := client.ContainerStart(ctx, createResponse.ID, types.ContainerStartOptions{}); err != nil { - // If we have hijackedIOStreamer, we should notify - // hijackedIOStreamer we are going to exit and wait - // to avoid the terminal are not restored. - if attach { - cancelFun() - <-errCh - } - - reportError(stderr, cmdPath, err.Error(), false) - if copts.autoRemove { - // wait container to be removed - <-statusChan - } - return runStartContainerErr(err) - } - - if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && dockerCli.Out().IsTerminal() { - if err := MonitorTtySize(ctx, dockerCli, createResponse.ID, false); err != nil { - fmt.Fprintln(stderr, "Error monitoring TTY size:", err) - } - } - - if errCh != nil { - if err := <-errCh; err != nil { - if _, ok := err.(term.EscapeError); ok { - // The user entered the detach escape sequence. - return nil - } - - logrus.Debugf("Error hijack: %s", err) - return err - } - } - - // Detached mode: wait for the id to be displayed and return. - if !config.AttachStdout && !config.AttachStderr { - // Detached mode - <-waitDisplayID - return nil - } - - status := <-statusChan - if status != 0 { - return cli.StatusError{StatusCode: status} - } - return nil -} - -func attachContainer( - ctx context.Context, - dockerCli command.Cli, - errCh *chan error, - config *container.Config, - containerID string, -) (func(), error) { - stdout, stderr := dockerCli.Out(), dockerCli.Err() - var ( - out, cerr io.Writer - in io.ReadCloser - ) - if config.AttachStdin { - in = dockerCli.In() - } - if config.AttachStdout { - out = stdout - } - if config.AttachStderr { - if config.Tty { - cerr = stdout - } else { - cerr = stderr - } - } - - options := types.ContainerAttachOptions{ - Stream: true, - Stdin: config.AttachStdin, - Stdout: config.AttachStdout, - Stderr: config.AttachStderr, - DetachKeys: dockerCli.ConfigFile().DetachKeys, - } - - resp, errAttach := dockerCli.Client().ContainerAttach(ctx, containerID, options) - if errAttach != nil && errAttach != httputil.ErrPersistEOF { - // ContainerAttach returns an ErrPersistEOF (connection closed) - // means server met an error and put it in Hijacked connection - // keep the error and read detailed error message from hijacked connection later - return nil, errAttach - } - - *errCh = promise.Go(func() error { - streamer := hijackedIOStreamer{ - streams: dockerCli, - inputStream: in, - outputStream: out, - errorStream: cerr, - resp: resp, - tty: config.Tty, - detachKeys: options.DetachKeys, - } - - if errHijack := streamer.stream(ctx); errHijack != nil { - return errHijack - } - return errAttach - }) - return resp.Close, nil -} - -// reportError is a utility method that prints a user-friendly message -// containing the error that occurred during parsing and a suggestion to get help -func reportError(stderr io.Writer, name string, str string, withHelp bool) { - str = strings.TrimSuffix(str, ".") + "." - if withHelp { - str += "\nSee '" + os.Args[0] + " " + name + " --help'." - } - fmt.Fprintf(stderr, "%s: %s\n", os.Args[0], str) -} - -// if container start fails with 'not found'/'no such' error, return 127 -// if container start fails with 'permission denied' error, return 126 -// return 125 for generic docker daemon failures -func runStartContainerErr(err error) error { - trimmedErr := strings.TrimPrefix(err.Error(), "Error response from daemon: ") - statusError := cli.StatusError{StatusCode: 125} - if strings.Contains(trimmedErr, "executable file not found") || - strings.Contains(trimmedErr, "no such file or directory") || - strings.Contains(trimmedErr, "system cannot find the file specified") { - statusError = cli.StatusError{StatusCode: 127} - } else if strings.Contains(trimmedErr, syscall.EACCES.Error()) { - statusError = cli.StatusError{StatusCode: 126} - } - - return statusError -} diff --git a/vendor/github.com/docker/cli/cli/command/container/start.go b/vendor/github.com/docker/cli/cli/command/container/start.go deleted file mode 100644 index 6cd475111..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/start.go +++ /dev/null @@ -1,195 +0,0 @@ -package container - -import ( - "fmt" - "io" - "net/http/httputil" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/promise" - "github.com/docker/docker/pkg/signal" - "github.com/docker/docker/pkg/term" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type startOptions struct { - attach bool - openStdin bool - detachKeys string - checkpoint string - checkpointDir string - - containers []string -} - -// NewStartCommand creates a new cobra.Command for `docker start` -func NewStartCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts startOptions - - cmd := &cobra.Command{ - Use: "start [OPTIONS] CONTAINER [CONTAINER...]", - Short: "Start one or more stopped containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - return runStart(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.attach, "attach", "a", false, "Attach STDOUT/STDERR and forward signals") - flags.BoolVarP(&opts.openStdin, "interactive", "i", false, "Attach container's STDIN") - flags.StringVar(&opts.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container") - - flags.StringVar(&opts.checkpoint, "checkpoint", "", "Restore from this checkpoint") - flags.SetAnnotation("checkpoint", "experimental", nil) - flags.StringVar(&opts.checkpointDir, "checkpoint-dir", "", "Use a custom checkpoint storage directory") - flags.SetAnnotation("checkpoint-dir", "experimental", nil) - return cmd -} - -// nolint: gocyclo -func runStart(dockerCli *command.DockerCli, opts *startOptions) error { - ctx, cancelFun := context.WithCancel(context.Background()) - - if opts.attach || opts.openStdin { - // We're going to attach to a container. - // 1. Ensure we only have one container. - if len(opts.containers) > 1 { - return errors.New("you cannot start and attach multiple containers at once") - } - - // 2. Attach to the container. - container := opts.containers[0] - c, err := dockerCli.Client().ContainerInspect(ctx, container) - if err != nil { - return err - } - - // We always use c.ID instead of container to maintain consistency during `docker start` - if !c.Config.Tty { - sigc := ForwardAllSignals(ctx, dockerCli, c.ID) - defer signal.StopCatch(sigc) - } - - if opts.detachKeys != "" { - dockerCli.ConfigFile().DetachKeys = opts.detachKeys - } - - options := types.ContainerAttachOptions{ - Stream: true, - Stdin: opts.openStdin && c.Config.OpenStdin, - Stdout: true, - Stderr: true, - DetachKeys: dockerCli.ConfigFile().DetachKeys, - } - - var in io.ReadCloser - - if options.Stdin { - in = dockerCli.In() - } - - resp, errAttach := dockerCli.Client().ContainerAttach(ctx, c.ID, options) - if errAttach != nil && errAttach != httputil.ErrPersistEOF { - // ContainerAttach return an ErrPersistEOF (connection closed) - // means server met an error and already put it in Hijacked connection, - // we would keep the error and read the detailed error message from hijacked connection - return errAttach - } - defer resp.Close() - cErr := promise.Go(func() error { - streamer := hijackedIOStreamer{ - streams: dockerCli, - inputStream: in, - outputStream: dockerCli.Out(), - errorStream: dockerCli.Err(), - resp: resp, - tty: c.Config.Tty, - detachKeys: options.DetachKeys, - } - - errHijack := streamer.stream(ctx) - if errHijack == nil { - return errAttach - } - return errHijack - }) - - // 3. We should open a channel for receiving status code of the container - // no matter it's detached, removed on daemon side(--rm) or exit normally. - statusChan := waitExitOrRemoved(ctx, dockerCli, c.ID, c.HostConfig.AutoRemove) - startOptions := types.ContainerStartOptions{ - CheckpointID: opts.checkpoint, - CheckpointDir: opts.checkpointDir, - } - - // 4. Start the container. - if err := dockerCli.Client().ContainerStart(ctx, c.ID, startOptions); err != nil { - cancelFun() - <-cErr - if c.HostConfig.AutoRemove { - // wait container to be removed - <-statusChan - } - return err - } - - // 5. Wait for attachment to break. - if c.Config.Tty && dockerCli.Out().IsTerminal() { - if err := MonitorTtySize(ctx, dockerCli, c.ID, false); err != nil { - fmt.Fprintln(dockerCli.Err(), "Error monitoring TTY size:", err) - } - } - if attachErr := <-cErr; attachErr != nil { - if _, ok := err.(term.EscapeError); ok { - // The user entered the detach escape sequence. - return nil - } - return attachErr - } - - if status := <-statusChan; status != 0 { - return cli.StatusError{StatusCode: status} - } - } else if opts.checkpoint != "" { - if len(opts.containers) > 1 { - return errors.New("you cannot restore multiple containers at once") - } - container := opts.containers[0] - startOptions := types.ContainerStartOptions{ - CheckpointID: opts.checkpoint, - CheckpointDir: opts.checkpointDir, - } - return dockerCli.Client().ContainerStart(ctx, container, startOptions) - - } else { - // We're not going to attach to anything. - // Start as many containers as we want. - return startContainersWithoutAttachments(ctx, dockerCli, opts.containers) - } - - return nil -} - -func startContainersWithoutAttachments(ctx context.Context, dockerCli *command.DockerCli, containers []string) error { - var failedContainers []string - for _, container := range containers { - if err := dockerCli.Client().ContainerStart(ctx, container, types.ContainerStartOptions{}); err != nil { - fmt.Fprintln(dockerCli.Err(), err) - failedContainers = append(failedContainers, container) - continue - } - fmt.Fprintln(dockerCli.Out(), container) - } - - if len(failedContainers) > 0 { - return errors.Errorf("Error: failed to start containers: %s", strings.Join(failedContainers, ", ")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/stats.go b/vendor/github.com/docker/cli/cli/command/container/stats.go deleted file mode 100644 index 50495f00c..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/stats.go +++ /dev/null @@ -1,243 +0,0 @@ -package container - -import ( - "fmt" - "io" - "strings" - "sync" - "time" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type statsOptions struct { - all bool - noStream bool - format string - containers []string -} - -// NewStatsCommand creates a new cobra.Command for `docker stats` -func NewStatsCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts statsOptions - - cmd := &cobra.Command{ - Use: "stats [OPTIONS] [CONTAINER...]", - Short: "Display a live stream of container(s) resource usage statistics", - Args: cli.RequiresMinArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - return runStats(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.all, "all", "a", false, "Show all containers (default shows just running)") - flags.BoolVar(&opts.noStream, "no-stream", false, "Disable streaming stats and only pull the first result") - flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template") - return cmd -} - -// runStats displays a live stream of resource usage statistics for one or more containers. -// This shows real-time information on CPU usage, memory usage, and network I/O. -// nolint: gocyclo -func runStats(dockerCli *command.DockerCli, opts *statsOptions) error { - showAll := len(opts.containers) == 0 - closeChan := make(chan error) - - ctx := context.Background() - - // monitorContainerEvents watches for container creation and removal (only - // used when calling `docker stats` without arguments). - monitorContainerEvents := func(started chan<- struct{}, c chan events.Message) { - f := filters.NewArgs() - f.Add("type", "container") - options := types.EventsOptions{ - Filters: f, - } - - eventq, errq := dockerCli.Client().Events(ctx, options) - - // Whether we successfully subscribed to eventq or not, we can now - // unblock the main goroutine. - close(started) - - for { - select { - case event := <-eventq: - c <- event - case err := <-errq: - closeChan <- err - return - } - } - } - - // Get the daemonOSType if not set already - if daemonOSType == "" { - svctx := context.Background() - sv, err := dockerCli.Client().ServerVersion(svctx) - if err != nil { - return err - } - daemonOSType = sv.Os - } - - // waitFirst is a WaitGroup to wait first stat data's reach for each container - waitFirst := &sync.WaitGroup{} - - cStats := stats{} - // getContainerList simulates creation event for all previously existing - // containers (only used when calling `docker stats` without arguments). - getContainerList := func() { - options := types.ContainerListOptions{ - All: opts.all, - } - cs, err := dockerCli.Client().ContainerList(ctx, options) - if err != nil { - closeChan <- err - } - for _, container := range cs { - s := formatter.NewContainerStats(container.ID[:12]) - if cStats.add(s) { - waitFirst.Add(1) - go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst) - } - } - } - - if showAll { - // If no names were specified, start a long running goroutine which - // monitors container events. We make sure we're subscribed before - // retrieving the list of running containers to avoid a race where we - // would "miss" a creation. - started := make(chan struct{}) - eh := command.InitEventHandler() - eh.Handle("create", func(e events.Message) { - if opts.all { - s := formatter.NewContainerStats(e.ID[:12]) - if cStats.add(s) { - waitFirst.Add(1) - go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst) - } - } - }) - - eh.Handle("start", func(e events.Message) { - s := formatter.NewContainerStats(e.ID[:12]) - if cStats.add(s) { - waitFirst.Add(1) - go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst) - } - }) - - eh.Handle("die", func(e events.Message) { - if !opts.all { - cStats.remove(e.ID[:12]) - } - }) - - eventChan := make(chan events.Message) - go eh.Watch(eventChan) - go monitorContainerEvents(started, eventChan) - defer close(eventChan) - <-started - - // Start a short-lived goroutine to retrieve the initial list of - // containers. - getContainerList() - } else { - // Artificially send creation events for the containers we were asked to - // monitor (same code path than we use when monitoring all containers). - for _, name := range opts.containers { - s := formatter.NewContainerStats(name) - if cStats.add(s) { - waitFirst.Add(1) - go collect(ctx, s, dockerCli.Client(), !opts.noStream, waitFirst) - } - } - - // We don't expect any asynchronous errors: closeChan can be closed. - close(closeChan) - - // Do a quick pause to detect any error with the provided list of - // container names. - time.Sleep(1500 * time.Millisecond) - var errs []string - cStats.mu.Lock() - for _, c := range cStats.cs { - if err := c.GetError(); err != nil { - errs = append(errs, err.Error()) - } - } - cStats.mu.Unlock() - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - } - - // before print to screen, make sure each container get at least one valid stat data - waitFirst.Wait() - format := opts.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().StatsFormat) > 0 { - format = dockerCli.ConfigFile().StatsFormat - } else { - format = formatter.TableFormatKey - } - } - statsCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewStatsFormat(format, daemonOSType), - } - cleanScreen := func() { - if !opts.noStream { - fmt.Fprint(dockerCli.Out(), "\033[2J") - fmt.Fprint(dockerCli.Out(), "\033[H") - } - } - - var err error - for range time.Tick(500 * time.Millisecond) { - cleanScreen() - ccstats := []formatter.StatsEntry{} - cStats.mu.Lock() - for _, c := range cStats.cs { - ccstats = append(ccstats, c.GetStatistics()) - } - cStats.mu.Unlock() - if err = formatter.ContainerStatsWrite(statsCtx, ccstats, daemonOSType); err != nil { - break - } - if len(cStats.cs) == 0 && !showAll { - break - } - if opts.noStream { - break - } - select { - case err, ok := <-closeChan: - if ok { - if err != nil { - // this is suppressing "unexpected EOF" in the cli when the - // daemon restarts so it shutdowns cleanly - if err == io.ErrUnexpectedEOF { - return nil - } - return err - } - } - default: - // just skip - } - } - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/container/stats_helpers.go b/vendor/github.com/docker/cli/cli/command/container/stats_helpers.go deleted file mode 100644 index 5f5a05cf7..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/stats_helpers.go +++ /dev/null @@ -1,238 +0,0 @@ -package container - -import ( - "encoding/json" - "io" - "strings" - "sync" - "time" - - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" -) - -type stats struct { - mu sync.Mutex - cs []*formatter.ContainerStats -} - -// daemonOSType is set once we have at least one stat for a container -// from the daemon. It is used to ensure we print the right header based -// on the daemon platform. -var daemonOSType string - -func (s *stats) add(cs *formatter.ContainerStats) bool { - s.mu.Lock() - defer s.mu.Unlock() - if _, exists := s.isKnownContainer(cs.Container); !exists { - s.cs = append(s.cs, cs) - return true - } - return false -} - -func (s *stats) remove(id string) { - s.mu.Lock() - if i, exists := s.isKnownContainer(id); exists { - s.cs = append(s.cs[:i], s.cs[i+1:]...) - } - s.mu.Unlock() -} - -func (s *stats) isKnownContainer(cid string) (int, bool) { - for i, c := range s.cs { - if c.Container == cid { - return i, true - } - } - return -1, false -} - -func collect(ctx context.Context, s *formatter.ContainerStats, cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) { - logrus.Debugf("collecting stats for %s", s.Container) - var ( - getFirst bool - previousCPU uint64 - previousSystem uint64 - u = make(chan error, 1) - ) - - defer func() { - // if error happens and we get nothing of stats, release wait group whatever - if !getFirst { - getFirst = true - waitFirst.Done() - } - }() - - response, err := cli.ContainerStats(ctx, s.Container, streamStats) - if err != nil { - s.SetError(err) - return - } - defer response.Body.Close() - - dec := json.NewDecoder(response.Body) - go func() { - for { - var ( - v *types.StatsJSON - memPercent, cpuPercent float64 - blkRead, blkWrite uint64 // Only used on Linux - mem, memLimit float64 - pidsStatsCurrent uint64 - ) - - if err := dec.Decode(&v); err != nil { - dec = json.NewDecoder(io.MultiReader(dec.Buffered(), response.Body)) - u <- err - if err == io.EOF { - break - } - time.Sleep(100 * time.Millisecond) - continue - } - - daemonOSType = response.OSType - - if daemonOSType != "windows" { - previousCPU = v.PreCPUStats.CPUUsage.TotalUsage - previousSystem = v.PreCPUStats.SystemUsage - cpuPercent = calculateCPUPercentUnix(previousCPU, previousSystem, v) - blkRead, blkWrite = calculateBlockIO(v.BlkioStats) - mem = calculateMemUsageUnixNoCache(v.MemoryStats) - memLimit = float64(v.MemoryStats.Limit) - memPercent = calculateMemPercentUnixNoCache(memLimit, mem) - pidsStatsCurrent = v.PidsStats.Current - } else { - cpuPercent = calculateCPUPercentWindows(v) - blkRead = v.StorageStats.ReadSizeBytes - blkWrite = v.StorageStats.WriteSizeBytes - mem = float64(v.MemoryStats.PrivateWorkingSet) - } - netRx, netTx := calculateNetwork(v.Networks) - s.SetStatistics(formatter.StatsEntry{ - Name: v.Name, - ID: v.ID, - CPUPercentage: cpuPercent, - Memory: mem, - MemoryPercentage: memPercent, - MemoryLimit: memLimit, - NetworkRx: netRx, - NetworkTx: netTx, - BlockRead: float64(blkRead), - BlockWrite: float64(blkWrite), - PidsCurrent: pidsStatsCurrent, - }) - u <- nil - if !streamStats { - return - } - } - }() - for { - select { - case <-time.After(2 * time.Second): - // zero out the values if we have not received an update within - // the specified duration. - s.SetErrorAndReset(errors.New("timeout waiting for stats")) - // if this is the first stat you get, release WaitGroup - if !getFirst { - getFirst = true - waitFirst.Done() - } - case err := <-u: - s.SetError(err) - if err == io.EOF { - break - } - if err != nil { - continue - } - // if this is the first stat you get, release WaitGroup - if !getFirst { - getFirst = true - waitFirst.Done() - } - } - if !streamStats { - return - } - } -} - -func calculateCPUPercentUnix(previousCPU, previousSystem uint64, v *types.StatsJSON) float64 { - var ( - cpuPercent = 0.0 - // calculate the change for the cpu usage of the container in between readings - cpuDelta = float64(v.CPUStats.CPUUsage.TotalUsage) - float64(previousCPU) - // calculate the change for the entire system between readings - systemDelta = float64(v.CPUStats.SystemUsage) - float64(previousSystem) - onlineCPUs = float64(v.CPUStats.OnlineCPUs) - ) - - if onlineCPUs == 0.0 { - onlineCPUs = float64(len(v.CPUStats.CPUUsage.PercpuUsage)) - } - if systemDelta > 0.0 && cpuDelta > 0.0 { - cpuPercent = (cpuDelta / systemDelta) * onlineCPUs * 100.0 - } - return cpuPercent -} - -func calculateCPUPercentWindows(v *types.StatsJSON) float64 { - // Max number of 100ns intervals between the previous time read and now - possIntervals := uint64(v.Read.Sub(v.PreRead).Nanoseconds()) // Start with number of ns intervals - possIntervals /= 100 // Convert to number of 100ns intervals - possIntervals *= uint64(v.NumProcs) // Multiple by the number of processors - - // Intervals used - intervalsUsed := v.CPUStats.CPUUsage.TotalUsage - v.PreCPUStats.CPUUsage.TotalUsage - - // Percentage avoiding divide-by-zero - if possIntervals > 0 { - return float64(intervalsUsed) / float64(possIntervals) * 100.0 - } - return 0.00 -} - -func calculateBlockIO(blkio types.BlkioStats) (blkRead uint64, blkWrite uint64) { - for _, bioEntry := range blkio.IoServiceBytesRecursive { - switch strings.ToLower(bioEntry.Op) { - case "read": - blkRead = blkRead + bioEntry.Value - case "write": - blkWrite = blkWrite + bioEntry.Value - } - } - return -} - -func calculateNetwork(network map[string]types.NetworkStats) (float64, float64) { - var rx, tx float64 - - for _, v := range network { - rx += float64(v.RxBytes) - tx += float64(v.TxBytes) - } - return rx, tx -} - -// calculateMemUsageUnixNoCache calculate memory usage of the container. -// Page cache is intentionally excluded to avoid misinterpretation of the output. -func calculateMemUsageUnixNoCache(mem types.MemoryStats) float64 { - return float64(mem.Usage - mem.Stats["cache"]) -} - -func calculateMemPercentUnixNoCache(limit float64, usedNoCache float64) float64 { - // MemoryStats.Limit will never be 0 unless the container is not running and we haven't - // got any data from cgroup - if limit != 0 { - return usedNoCache / limit * 100.0 - } - return 0 -} diff --git a/vendor/github.com/docker/cli/cli/command/container/stats_helpers_test.go b/vendor/github.com/docker/cli/cli/command/container/stats_helpers_test.go deleted file mode 100644 index 0425a3ba1..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/stats_helpers_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package container - -import ( - "testing" - - "github.com/docker/docker/api/types" - "github.com/stretchr/testify/assert" -) - -func TestCalculateMemUsageUnixNoCache(t *testing.T) { - // Given - stats := types.MemoryStats{Usage: 500, Stats: map[string]uint64{"cache": 400}} - - // When - result := calculateMemUsageUnixNoCache(stats) - - // Then - assert.InDelta(t, 100.0, result, 1e-6) -} - -func TestCalculateMemPercentUnixNoCache(t *testing.T) { - // Given - someLimit := float64(100.0) - noLimit := float64(0.0) - used := float64(70.0) - - // When and Then - t.Run("Limit is set", func(t *testing.T) { - result := calculateMemPercentUnixNoCache(someLimit, used) - assert.InDelta(t, 70.0, result, 1e-6) - }) - t.Run("No limit, no cgroup data", func(t *testing.T) { - result := calculateMemPercentUnixNoCache(noLimit, used) - assert.InDelta(t, 0.0, result, 1e-6) - }) -} diff --git a/vendor/github.com/docker/cli/cli/command/container/stats_unit_test.go b/vendor/github.com/docker/cli/cli/command/container/stats_unit_test.go deleted file mode 100644 index 21e650e28..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/stats_unit_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package container - -import ( - "testing" - - "github.com/docker/docker/api/types" -) - -func TestCalculateBlockIO(t *testing.T) { - blkio := types.BlkioStats{ - IoServiceBytesRecursive: []types.BlkioStatEntry{ - {Major: 8, Minor: 0, Op: "read", Value: 1234}, - {Major: 8, Minor: 1, Op: "read", Value: 4567}, - {Major: 8, Minor: 0, Op: "write", Value: 123}, - {Major: 8, Minor: 1, Op: "write", Value: 456}, - }, - } - blkRead, blkWrite := calculateBlockIO(blkio) - if blkRead != 5801 { - t.Fatalf("blkRead = %d, want 5801", blkRead) - } - if blkWrite != 579 { - t.Fatalf("blkWrite = %d, want 579", blkWrite) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/container/stop.go b/vendor/github.com/docker/cli/cli/command/container/stop.go deleted file mode 100644 index 59d6d0b70..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/stop.go +++ /dev/null @@ -1,67 +0,0 @@ -package container - -import ( - "fmt" - "strings" - "time" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type stopOptions struct { - time int - timeChanged bool - - containers []string -} - -// NewStopCommand creates a new cobra.Command for `docker stop` -func NewStopCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts stopOptions - - cmd := &cobra.Command{ - Use: "stop [OPTIONS] CONTAINER [CONTAINER...]", - Short: "Stop one or more running containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - opts.timeChanged = cmd.Flags().Changed("time") - return runStop(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.IntVarP(&opts.time, "time", "t", 10, "Seconds to wait for stop before killing it") - return cmd -} - -func runStop(dockerCli *command.DockerCli, opts *stopOptions) error { - ctx := context.Background() - - var timeout *time.Duration - if opts.timeChanged { - timeoutValue := time.Duration(opts.time) * time.Second - timeout = &timeoutValue - } - - var errs []string - - errChan := parallelOperation(ctx, opts.containers, func(ctx context.Context, id string) error { - return dockerCli.Client().ContainerStop(ctx, id, timeout) - }) - for _, container := range opts.containers { - if err := <-errChan; err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintln(dockerCli.Out(), container) - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/testdata/utf16.env b/vendor/github.com/docker/cli/cli/command/container/testdata/utf16.env deleted file mode 100755 index 3a73358ff..000000000 Binary files a/vendor/github.com/docker/cli/cli/command/container/testdata/utf16.env and /dev/null differ diff --git a/vendor/github.com/docker/cli/cli/command/container/testdata/utf16be.env b/vendor/github.com/docker/cli/cli/command/container/testdata/utf16be.env deleted file mode 100755 index e523da7af..000000000 Binary files a/vendor/github.com/docker/cli/cli/command/container/testdata/utf16be.env and /dev/null differ diff --git a/vendor/github.com/docker/cli/cli/command/container/testdata/utf8.env b/vendor/github.com/docker/cli/cli/command/container/testdata/utf8.env deleted file mode 100755 index 1ce45055b..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/testdata/utf8.env +++ /dev/null @@ -1,3 +0,0 @@ -FOO=BAR -HELLO=您好 -BAR=FOO \ No newline at end of file diff --git a/vendor/github.com/docker/cli/cli/command/container/testdata/valid.env b/vendor/github.com/docker/cli/cli/command/container/testdata/valid.env deleted file mode 100644 index 3afbdc81c..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/testdata/valid.env +++ /dev/null @@ -1 +0,0 @@ -ENV1=value1 diff --git a/vendor/github.com/docker/cli/cli/command/container/testdata/valid.label b/vendor/github.com/docker/cli/cli/command/container/testdata/valid.label deleted file mode 100644 index b4208bdf8..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/testdata/valid.label +++ /dev/null @@ -1 +0,0 @@ -LABEL1=value1 diff --git a/vendor/github.com/docker/cli/cli/command/container/top.go b/vendor/github.com/docker/cli/cli/command/container/top.go deleted file mode 100644 index 428ee27ff..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/top.go +++ /dev/null @@ -1,57 +0,0 @@ -package container - -import ( - "fmt" - "strings" - "text/tabwriter" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type topOptions struct { - container string - - args []string -} - -// NewTopCommand creates a new cobra.Command for `docker top` -func NewTopCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts topOptions - - cmd := &cobra.Command{ - Use: "top CONTAINER [ps OPTIONS]", - Short: "Display the running processes of a container", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - opts.args = args[1:] - return runTop(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.SetInterspersed(false) - - return cmd -} - -func runTop(dockerCli *command.DockerCli, opts *topOptions) error { - ctx := context.Background() - - procList, err := dockerCli.Client().ContainerTop(ctx, opts.container, opts.args) - if err != nil { - return err - } - - w := tabwriter.NewWriter(dockerCli.Out(), 20, 1, 3, ' ', 0) - fmt.Fprintln(w, strings.Join(procList.Titles, "\t")) - - for _, proc := range procList.Processes { - fmt.Fprintln(w, strings.Join(proc, "\t")) - } - w.Flush() - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/tty.go b/vendor/github.com/docker/cli/cli/command/container/tty.go deleted file mode 100644 index a02377836..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/tty.go +++ /dev/null @@ -1,103 +0,0 @@ -package container - -import ( - "fmt" - "os" - gosignal "os/signal" - "runtime" - "time" - - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/signal" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" -) - -// resizeTtyTo resizes tty to specific height and width -func resizeTtyTo(ctx context.Context, client client.ContainerAPIClient, id string, height, width uint, isExec bool) { - if height == 0 && width == 0 { - return - } - - options := types.ResizeOptions{ - Height: height, - Width: width, - } - - var err error - if isExec { - err = client.ContainerExecResize(ctx, id, options) - } else { - err = client.ContainerResize(ctx, id, options) - } - - if err != nil { - logrus.Debugf("Error resize: %s", err) - } -} - -// MonitorTtySize updates the container tty size when the terminal tty changes size -func MonitorTtySize(ctx context.Context, cli command.Cli, id string, isExec bool) error { - resizeTty := func() { - height, width := cli.Out().GetTtySize() - resizeTtyTo(ctx, cli.Client(), id, height, width, isExec) - } - - resizeTty() - - if runtime.GOOS == "windows" { - go func() { - prevH, prevW := cli.Out().GetTtySize() - for { - time.Sleep(time.Millisecond * 250) - h, w := cli.Out().GetTtySize() - - if prevW != w || prevH != h { - resizeTty() - } - prevH = h - prevW = w - } - }() - } else { - sigchan := make(chan os.Signal, 1) - gosignal.Notify(sigchan, signal.SIGWINCH) - go func() { - for range sigchan { - resizeTty() - } - }() - } - return nil -} - -// ForwardAllSignals forwards signals to the container -func ForwardAllSignals(ctx context.Context, cli command.Cli, cid string) chan os.Signal { - sigc := make(chan os.Signal, 128) - signal.CatchAll(sigc) - go func() { - for s := range sigc { - if s == signal.SIGCHLD || s == signal.SIGPIPE { - continue - } - var sig string - for sigStr, sigN := range signal.SignalMap { - if sigN == s { - sig = sigStr - break - } - } - if sig == "" { - fmt.Fprintf(cli.Err(), "Unsupported signal: %v. Discarding.\n", s) - continue - } - - if err := cli.Client().ContainerKill(ctx, cid, sig); err != nil { - logrus.Debugf("Error sending signal: %s", err) - } - } - }() - return sigc -} diff --git a/vendor/github.com/docker/cli/cli/command/container/unpause.go b/vendor/github.com/docker/cli/cli/command/container/unpause.go deleted file mode 100644 index b6d5e231b..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/unpause.go +++ /dev/null @@ -1,50 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type unpauseOptions struct { - containers []string -} - -// NewUnpauseCommand creates a new cobra.Command for `docker unpause` -func NewUnpauseCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts unpauseOptions - - cmd := &cobra.Command{ - Use: "unpause CONTAINER [CONTAINER...]", - Short: "Unpause all processes within one or more containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - return runUnpause(dockerCli, &opts) - }, - } - return cmd -} - -func runUnpause(dockerCli *command.DockerCli, opts *unpauseOptions) error { - ctx := context.Background() - - var errs []string - errChan := parallelOperation(ctx, opts.containers, dockerCli.Client().ContainerUnpause) - for _, container := range opts.containers { - if err := <-errChan; err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintln(dockerCli.Out(), container) - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/update.go b/vendor/github.com/docker/cli/cli/command/container/update.go deleted file mode 100644 index 9cb74aeb7..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/update.go +++ /dev/null @@ -1,133 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - containertypes "github.com/docker/docker/api/types/container" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type updateOptions struct { - blkioWeight uint16 - cpuPeriod int64 - cpuQuota int64 - cpuRealtimePeriod int64 - cpuRealtimeRuntime int64 - cpusetCpus string - cpusetMems string - cpuShares int64 - memory opts.MemBytes - memoryReservation opts.MemBytes - memorySwap opts.MemSwapBytes - kernelMemory opts.MemBytes - restartPolicy string - cpus opts.NanoCPUs - - nFlag int - - containers []string -} - -// NewUpdateCommand creates a new cobra.Command for `docker update` -func NewUpdateCommand(dockerCli *command.DockerCli) *cobra.Command { - var options updateOptions - - cmd := &cobra.Command{ - Use: "update [OPTIONS] CONTAINER [CONTAINER...]", - Short: "Update configuration of one or more containers", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.containers = args - options.nFlag = cmd.Flags().NFlag() - return runUpdate(dockerCli, &options) - }, - } - - flags := cmd.Flags() - flags.Uint16Var(&options.blkioWeight, "blkio-weight", 0, "Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)") - flags.Int64Var(&options.cpuPeriod, "cpu-period", 0, "Limit CPU CFS (Completely Fair Scheduler) period") - flags.Int64Var(&options.cpuQuota, "cpu-quota", 0, "Limit CPU CFS (Completely Fair Scheduler) quota") - flags.Int64Var(&options.cpuRealtimePeriod, "cpu-rt-period", 0, "Limit the CPU real-time period in microseconds") - flags.SetAnnotation("cpu-rt-period", "version", []string{"1.25"}) - flags.Int64Var(&options.cpuRealtimeRuntime, "cpu-rt-runtime", 0, "Limit the CPU real-time runtime in microseconds") - flags.SetAnnotation("cpu-rt-runtime", "version", []string{"1.25"}) - flags.StringVar(&options.cpusetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)") - flags.StringVar(&options.cpusetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)") - flags.Int64VarP(&options.cpuShares, "cpu-shares", "c", 0, "CPU shares (relative weight)") - flags.VarP(&options.memory, "memory", "m", "Memory limit") - flags.Var(&options.memoryReservation, "memory-reservation", "Memory soft limit") - flags.Var(&options.memorySwap, "memory-swap", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") - flags.Var(&options.kernelMemory, "kernel-memory", "Kernel memory limit") - flags.StringVar(&options.restartPolicy, "restart", "", "Restart policy to apply when a container exits") - - flags.Var(&options.cpus, "cpus", "Number of CPUs") - flags.SetAnnotation("cpus", "version", []string{"1.29"}) - - return cmd -} - -func runUpdate(dockerCli *command.DockerCli, options *updateOptions) error { - var err error - - if options.nFlag == 0 { - return errors.New("you must provide one or more flags when using this command") - } - - var restartPolicy containertypes.RestartPolicy - if options.restartPolicy != "" { - restartPolicy, err = opts.ParseRestartPolicy(options.restartPolicy) - if err != nil { - return err - } - } - - resources := containertypes.Resources{ - BlkioWeight: options.blkioWeight, - CpusetCpus: options.cpusetCpus, - CpusetMems: options.cpusetMems, - CPUShares: options.cpuShares, - Memory: options.memory.Value(), - MemoryReservation: options.memoryReservation.Value(), - MemorySwap: options.memorySwap.Value(), - KernelMemory: options.kernelMemory.Value(), - CPUPeriod: options.cpuPeriod, - CPUQuota: options.cpuQuota, - CPURealtimePeriod: options.cpuRealtimePeriod, - CPURealtimeRuntime: options.cpuRealtimeRuntime, - NanoCPUs: options.cpus.Value(), - } - - updateConfig := containertypes.UpdateConfig{ - Resources: resources, - RestartPolicy: restartPolicy, - } - - ctx := context.Background() - - var ( - warns []string - errs []string - ) - for _, container := range options.containers { - r, err := dockerCli.Client().ContainerUpdate(ctx, container, updateConfig) - if err != nil { - errs = append(errs, err.Error()) - } else { - fmt.Fprintln(dockerCli.Out(), container) - } - warns = append(warns, r.Warnings...) - } - if len(warns) > 0 { - fmt.Fprintln(dockerCli.Out(), strings.Join(warns, "\n")) - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/container/utils.go b/vendor/github.com/docker/cli/cli/command/container/utils.go deleted file mode 100644 index 024e6ed6d..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/utils.go +++ /dev/null @@ -1,157 +0,0 @@ -package container - -import ( - "strconv" - - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/events" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/versions" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" -) - -func waitExitOrRemoved(ctx context.Context, dockerCli *command.DockerCli, containerID string, waitRemove bool) <-chan int { - if len(containerID) == 0 { - // containerID can never be empty - panic("Internal Error: waitExitOrRemoved needs a containerID as parameter") - } - - // Older versions used the Events API, and even older versions did not - // support server-side removal. This legacyWaitExitOrRemoved method - // preserves that old behavior and any issues it may have. - if versions.LessThan(dockerCli.Client().ClientVersion(), "1.30") { - return legacyWaitExitOrRemoved(ctx, dockerCli, containerID, waitRemove) - } - - condition := container.WaitConditionNextExit - if waitRemove { - condition = container.WaitConditionRemoved - } - - resultC, errC := dockerCli.Client().ContainerWait(ctx, containerID, condition) - - statusC := make(chan int) - go func() { - select { - case result := <-resultC: - statusC <- int(result.StatusCode) - case err := <-errC: - logrus.Errorf("error waiting for container: %v", err) - statusC <- 125 - } - }() - - return statusC -} - -func legacyWaitExitOrRemoved(ctx context.Context, dockerCli *command.DockerCli, containerID string, waitRemove bool) <-chan int { - var removeErr error - statusChan := make(chan int) - exitCode := 125 - - // Get events via Events API - f := filters.NewArgs() - f.Add("type", "container") - f.Add("container", containerID) - options := types.EventsOptions{ - Filters: f, - } - eventCtx, cancel := context.WithCancel(ctx) - eventq, errq := dockerCli.Client().Events(eventCtx, options) - - eventProcessor := func(e events.Message) bool { - stopProcessing := false - switch e.Status { - case "die": - if v, ok := e.Actor.Attributes["exitCode"]; ok { - code, cerr := strconv.Atoi(v) - if cerr != nil { - logrus.Errorf("failed to convert exitcode '%q' to int: %v", v, cerr) - } else { - exitCode = code - } - } - if !waitRemove { - stopProcessing = true - } else { - // If we are talking to an older daemon, `AutoRemove` is not supported. - // We need to fall back to the old behavior, which is client-side removal - if versions.LessThan(dockerCli.Client().ClientVersion(), "1.25") { - go func() { - removeErr = dockerCli.Client().ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{RemoveVolumes: true}) - if removeErr != nil { - logrus.Errorf("error removing container: %v", removeErr) - cancel() // cancel the event Q - } - }() - } - } - case "detach": - exitCode = 0 - stopProcessing = true - case "destroy": - stopProcessing = true - } - return stopProcessing - } - - go func() { - defer func() { - statusChan <- exitCode // must always send an exit code or the caller will block - cancel() - }() - - for { - select { - case <-eventCtx.Done(): - if removeErr != nil { - return - } - case evt := <-eventq: - if eventProcessor(evt) { - return - } - case err := <-errq: - logrus.Errorf("error getting events from daemon: %v", err) - return - } - } - }() - - return statusChan -} - -func parallelOperation(ctx context.Context, containers []string, op func(ctx context.Context, container string) error) chan error { - if len(containers) == 0 { - return nil - } - const defaultParallel int = 50 - sem := make(chan struct{}, defaultParallel) - errChan := make(chan error) - - // make sure result is printed in correct order - output := map[string]chan error{} - for _, c := range containers { - output[c] = make(chan error, 1) - } - go func() { - for _, c := range containers { - err := <-output[c] - errChan <- err - } - }() - - go func() { - for _, c := range containers { - sem <- struct{}{} // Wait for active queue sem to drain. - go func(container string) { - output[container] <- op(ctx, container) - <-sem - }(c) - } - }() - return errChan -} diff --git a/vendor/github.com/docker/cli/cli/command/container/wait.go b/vendor/github.com/docker/cli/cli/command/container/wait.go deleted file mode 100644 index f582469c3..000000000 --- a/vendor/github.com/docker/cli/cli/command/container/wait.go +++ /dev/null @@ -1,53 +0,0 @@ -package container - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type waitOptions struct { - containers []string -} - -// NewWaitCommand creates a new cobra.Command for `docker wait` -func NewWaitCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts waitOptions - - cmd := &cobra.Command{ - Use: "wait CONTAINER [CONTAINER...]", - Short: "Block until one or more containers stop, then print their exit codes", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.containers = args - return runWait(dockerCli, &opts) - }, - } - - return cmd -} - -func runWait(dockerCli *command.DockerCli, opts *waitOptions) error { - ctx := context.Background() - - var errs []string - for _, container := range opts.containers { - resultC, errC := dockerCli.Client().ContainerWait(ctx, container, "") - - select { - case result := <-resultC: - fmt.Fprintf(dockerCli.Out(), "%d\n", result.StatusCode) - case err := <-errC: - errs = append(errs, err.Error()) - } - } - if len(errs) > 0 { - return errors.New(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/events_utils.go b/vendor/github.com/docker/cli/cli/command/events_utils.go deleted file mode 100644 index 16d76892a..000000000 --- a/vendor/github.com/docker/cli/cli/command/events_utils.go +++ /dev/null @@ -1,47 +0,0 @@ -package command - -import ( - "sync" - - eventtypes "github.com/docker/docker/api/types/events" - "github.com/sirupsen/logrus" -) - -// EventHandler is abstract interface for user to customize -// own handle functions of each type of events -type EventHandler interface { - Handle(action string, h func(eventtypes.Message)) - Watch(c <-chan eventtypes.Message) -} - -// InitEventHandler initializes and returns an EventHandler -func InitEventHandler() EventHandler { - return &eventHandler{handlers: make(map[string]func(eventtypes.Message))} -} - -type eventHandler struct { - handlers map[string]func(eventtypes.Message) - mu sync.Mutex -} - -func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) { - w.mu.Lock() - w.handlers[action] = h - w.mu.Unlock() -} - -// Watch ranges over the passed in event chan and processes the events based on the -// handlers created for a given action. -// To stop watching, close the event chan. -func (w *eventHandler) Watch(c <-chan eventtypes.Message) { - for e := range c { - w.mu.Lock() - h, exists := w.handlers[e.Action] - w.mu.Unlock() - if !exists { - continue - } - logrus.Debugf("event handler: received event: %v", e) - go h(e) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/checkpoint.go b/vendor/github.com/docker/cli/cli/command/formatter/checkpoint.go deleted file mode 100644 index 041fcafb7..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/checkpoint.go +++ /dev/null @@ -1,52 +0,0 @@ -package formatter - -import "github.com/docker/docker/api/types" - -const ( - defaultCheckpointFormat = "table {{.Name}}" - - checkpointNameHeader = "CHECKPOINT NAME" -) - -// NewCheckpointFormat returns a format for use with a checkpoint Context -func NewCheckpointFormat(source string) Format { - switch source { - case TableFormatKey: - return defaultCheckpointFormat - } - return Format(source) -} - -// CheckpointWrite writes formatted checkpoints using the Context -func CheckpointWrite(ctx Context, checkpoints []types.Checkpoint) error { - render := func(format func(subContext subContext) error) error { - for _, checkpoint := range checkpoints { - if err := format(&checkpointContext{c: checkpoint}); err != nil { - return err - } - } - return nil - } - return ctx.Write(newCheckpointContext(), render) -} - -type checkpointContext struct { - HeaderContext - c types.Checkpoint -} - -func newCheckpointContext() *checkpointContext { - cpCtx := checkpointContext{} - cpCtx.header = volumeHeaderContext{ - "Name": checkpointNameHeader, - } - return &cpCtx -} - -func (c *checkpointContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *checkpointContext) Name() string { - return c.c.Name -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/checkpoint_test.go b/vendor/github.com/docker/cli/cli/command/formatter/checkpoint_test.go deleted file mode 100644 index e88c4d013..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/checkpoint_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package formatter - -import ( - "bytes" - "testing" - - "github.com/docker/docker/api/types" - "github.com/stretchr/testify/assert" -) - -func TestCheckpointContextFormatWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - { - Context{Format: NewCheckpointFormat(defaultCheckpointFormat)}, - `CHECKPOINT NAME -checkpoint-1 -checkpoint-2 -checkpoint-3 -`, - }, - { - Context{Format: NewCheckpointFormat("{{.Name}}")}, - `checkpoint-1 -checkpoint-2 -checkpoint-3 -`, - }, - { - Context{Format: NewCheckpointFormat("{{.Name}}:")}, - `checkpoint-1: -checkpoint-2: -checkpoint-3: -`, - }, - } - - checkpoints := []types.Checkpoint{ - {"checkpoint-1"}, - {"checkpoint-2"}, - {"checkpoint-3"}, - } - for _, testcase := range cases { - out := bytes.NewBufferString("") - testcase.context.Output = out - err := CheckpointWrite(testcase.context, checkpoints) - if err != nil { - assert.Error(t, err, testcase.expected) - } else { - assert.Equal(t, out.String(), testcase.expected) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/config.go b/vendor/github.com/docker/cli/cli/command/formatter/config.go deleted file mode 100644 index 72203f35f..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/config.go +++ /dev/null @@ -1,171 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - "time" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/docker/docker/api/types/swarm" - units "github.com/docker/go-units" -) - -const ( - defaultConfigTableFormat = "table {{.ID}}\t{{.Name}}\t{{.CreatedAt}}\t{{.UpdatedAt}}" - configIDHeader = "ID" - configCreatedHeader = "CREATED" - configUpdatedHeader = "UPDATED" - configInspectPrettyTemplate Format = `ID: {{.ID}} -Name: {{.Name}} -{{- if .Labels }} -Labels: -{{- range $k, $v := .Labels }} - - {{ $k }}{{if $v }}={{ $v }}{{ end }} -{{- end }}{{ end }} -Created at: {{.CreatedAt}} -Updated at: {{.UpdatedAt}} -Data: -{{.Data}}` -) - -// NewConfigFormat returns a Format for rendering using a config Context -func NewConfigFormat(source string, quiet bool) Format { - switch source { - case PrettyFormatKey: - return configInspectPrettyTemplate - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - return defaultConfigTableFormat - } - return Format(source) -} - -// ConfigWrite writes the context -func ConfigWrite(ctx Context, configs []swarm.Config) error { - render := func(format func(subContext subContext) error) error { - for _, config := range configs { - configCtx := &configContext{c: config} - if err := format(configCtx); err != nil { - return err - } - } - return nil - } - return ctx.Write(newConfigContext(), render) -} - -func newConfigContext() *configContext { - cCtx := &configContext{} - - cCtx.header = map[string]string{ - "ID": configIDHeader, - "Name": nameHeader, - "CreatedAt": configCreatedHeader, - "UpdatedAt": configUpdatedHeader, - "Labels": labelsHeader, - } - return cCtx -} - -type configContext struct { - HeaderContext - c swarm.Config -} - -func (c *configContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *configContext) ID() string { - return c.c.ID -} - -func (c *configContext) Name() string { - return c.c.Spec.Annotations.Name -} - -func (c *configContext) CreatedAt() string { - return units.HumanDuration(time.Now().UTC().Sub(c.c.Meta.CreatedAt)) + " ago" -} - -func (c *configContext) UpdatedAt() string { - return units.HumanDuration(time.Now().UTC().Sub(c.c.Meta.UpdatedAt)) + " ago" -} - -func (c *configContext) Labels() string { - mapLabels := c.c.Spec.Annotations.Labels - if mapLabels == nil { - return "" - } - var joinLabels []string - for k, v := range mapLabels { - joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v)) - } - return strings.Join(joinLabels, ",") -} - -func (c *configContext) Label(name string) string { - if c.c.Spec.Annotations.Labels == nil { - return "" - } - return c.c.Spec.Annotations.Labels[name] -} - -// ConfigInspectWrite renders the context for a list of configs -func ConfigInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) error { - if ctx.Format != configInspectPrettyTemplate { - return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef) - } - render := func(format func(subContext subContext) error) error { - for _, ref := range refs { - configI, _, err := getRef(ref) - if err != nil { - return err - } - config, ok := configI.(swarm.Config) - if !ok { - return fmt.Errorf("got wrong object to inspect :%v", ok) - } - if err := format(&configInspectContext{Config: config}); err != nil { - return err - } - } - return nil - } - return ctx.Write(&configInspectContext{}, render) -} - -type configInspectContext struct { - swarm.Config - subContext -} - -func (ctx *configInspectContext) ID() string { - return ctx.Config.ID -} - -func (ctx *configInspectContext) Name() string { - return ctx.Config.Spec.Name -} - -func (ctx *configInspectContext) Labels() map[string]string { - return ctx.Config.Spec.Labels -} - -func (ctx *configInspectContext) CreatedAt() string { - return command.PrettyPrint(ctx.Config.CreatedAt) -} - -func (ctx *configInspectContext) UpdatedAt() string { - return command.PrettyPrint(ctx.Config.UpdatedAt) -} - -func (ctx *configInspectContext) Data() string { - if ctx.Config.Spec.Data == nil { - return "" - } - return string(ctx.Config.Spec.Data) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/config_test.go b/vendor/github.com/docker/cli/cli/command/formatter/config_test.go deleted file mode 100644 index 227f454ff..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/config_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package formatter - -import ( - "bytes" - "testing" - "time" - - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" -) - -func TestConfigContextFormatWrite(t *testing.T) { - // Check default output format (verbose and non-verbose mode) for table headers - cases := []struct { - context Context - expected string - }{ - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - {Context{Format: NewConfigFormat("table", false)}, - `ID NAME CREATED UPDATED -1 passwords Less than a second ago Less than a second ago -2 id_rsa Less than a second ago Less than a second ago -`}, - {Context{Format: NewConfigFormat("table {{.Name}}", true)}, - `NAME -passwords -id_rsa -`}, - {Context{Format: NewConfigFormat("{{.ID}}-{{.Name}}", false)}, - `1-passwords -2-id_rsa -`}, - } - - configs := []swarm.Config{ - {ID: "1", - Meta: swarm.Meta{CreatedAt: time.Now(), UpdatedAt: time.Now()}, - Spec: swarm.ConfigSpec{Annotations: swarm.Annotations{Name: "passwords"}}}, - {ID: "2", - Meta: swarm.Meta{CreatedAt: time.Now(), UpdatedAt: time.Now()}, - Spec: swarm.ConfigSpec{Annotations: swarm.Annotations{Name: "id_rsa"}}}, - } - for _, testcase := range cases { - out := bytes.NewBufferString("") - testcase.context.Output = out - if err := ConfigWrite(testcase.context, configs); err != nil { - assert.Error(t, err, testcase.expected) - } else { - assert.Equal(t, out.String(), testcase.expected) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/container.go b/vendor/github.com/docker/cli/cli/command/formatter/container.go deleted file mode 100644 index 5ee1309d2..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/container.go +++ /dev/null @@ -1,345 +0,0 @@ -package formatter - -import ( - "fmt" - "sort" - "strconv" - "strings" - "time" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - "github.com/docker/go-units" -) - -const ( - defaultContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}}\t{{.Status}}\t{{.Ports}}\t{{.Names}}" - - containerIDHeader = "CONTAINER ID" - namesHeader = "NAMES" - commandHeader = "COMMAND" - runningForHeader = "CREATED" - statusHeader = "STATUS" - portsHeader = "PORTS" - mountsHeader = "MOUNTS" - localVolumes = "LOCAL VOLUMES" - networksHeader = "NETWORKS" -) - -// NewContainerFormat returns a Format for rendering using a Context -func NewContainerFormat(source string, quiet bool, size bool) Format { - switch source { - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - format := defaultContainerTableFormat - if size { - format += `\t{{.Size}}` - } - return Format(format) - case RawFormatKey: - if quiet { - return `container_id: {{.ID}}` - } - format := `container_id: {{.ID}} -image: {{.Image}} -command: {{.Command}} -created_at: {{.CreatedAt}} -status: {{- pad .Status 1 0}} -names: {{.Names}} -labels: {{- pad .Labels 1 0}} -ports: {{- pad .Ports 1 0}} -` - if size { - format += `size: {{.Size}}\n` - } - return Format(format) - } - return Format(source) -} - -// ContainerWrite renders the context for a list of containers -func ContainerWrite(ctx Context, containers []types.Container) error { - render := func(format func(subContext subContext) error) error { - for _, container := range containers { - err := format(&containerContext{trunc: ctx.Trunc, c: container}) - if err != nil { - return err - } - } - return nil - } - return ctx.Write(newContainerContext(), render) -} - -type containerHeaderContext map[string]string - -func (c containerHeaderContext) Label(name string) string { - n := strings.Split(name, ".") - r := strings.NewReplacer("-", " ", "_", " ") - h := r.Replace(n[len(n)-1]) - - return h -} - -type containerContext struct { - HeaderContext - trunc bool - c types.Container -} - -func newContainerContext() *containerContext { - containerCtx := containerContext{} - containerCtx.header = containerHeaderContext{ - "ID": containerIDHeader, - "Names": namesHeader, - "Image": imageHeader, - "Command": commandHeader, - "CreatedAt": createdAtHeader, - "RunningFor": runningForHeader, - "Ports": portsHeader, - "Status": statusHeader, - "Size": sizeHeader, - "Labels": labelsHeader, - "Mounts": mountsHeader, - "LocalVolumes": localVolumes, - "Networks": networksHeader, - } - return &containerCtx -} - -func (c *containerContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *containerContext) ID() string { - if c.trunc { - return stringid.TruncateID(c.c.ID) - } - return c.c.ID -} - -func (c *containerContext) Names() string { - names := stripNamePrefix(c.c.Names) - if c.trunc { - for _, name := range names { - if len(strings.Split(name, "/")) == 1 { - names = []string{name} - break - } - } - } - return strings.Join(names, ",") -} - -func (c *containerContext) Image() string { - if c.c.Image == "" { - return "" - } - if c.trunc { - if trunc := stringid.TruncateID(c.c.ImageID); trunc == stringid.TruncateID(c.c.Image) { - return trunc - } - // truncate digest if no-trunc option was not selected - ref, err := reference.ParseNormalizedNamed(c.c.Image) - if err == nil { - if nt, ok := ref.(reference.NamedTagged); ok { - // case for when a tag is provided - if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil { - return reference.FamiliarString(namedTagged) - } - } else { - // case for when a tag is not provided - named := reference.TrimNamed(ref) - return reference.FamiliarString(named) - } - } - } - - return c.c.Image -} - -func (c *containerContext) Command() string { - command := c.c.Command - if c.trunc { - command = stringutils.Ellipsis(command, 20) - } - return strconv.Quote(command) -} - -func (c *containerContext) CreatedAt() string { - return time.Unix(c.c.Created, 0).String() -} - -func (c *containerContext) RunningFor() string { - createdAt := time.Unix(c.c.Created, 0) - return units.HumanDuration(time.Now().UTC().Sub(createdAt)) + " ago" -} - -func (c *containerContext) Ports() string { - return DisplayablePorts(c.c.Ports) -} - -func (c *containerContext) Status() string { - return c.c.Status -} - -func (c *containerContext) Size() string { - srw := units.HumanSizeWithPrecision(float64(c.c.SizeRw), 3) - sv := units.HumanSizeWithPrecision(float64(c.c.SizeRootFs), 3) - - sf := srw - if c.c.SizeRootFs > 0 { - sf = fmt.Sprintf("%s (virtual %s)", srw, sv) - } - return sf -} - -func (c *containerContext) Labels() string { - if c.c.Labels == nil { - return "" - } - - var joinLabels []string - for k, v := range c.c.Labels { - joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v)) - } - return strings.Join(joinLabels, ",") -} - -func (c *containerContext) Label(name string) string { - if c.c.Labels == nil { - return "" - } - return c.c.Labels[name] -} - -func (c *containerContext) Mounts() string { - var name string - var mounts []string - for _, m := range c.c.Mounts { - if m.Name == "" { - name = m.Source - } else { - name = m.Name - } - if c.trunc { - name = stringutils.Ellipsis(name, 15) - } - mounts = append(mounts, name) - } - return strings.Join(mounts, ",") -} - -func (c *containerContext) LocalVolumes() string { - count := 0 - for _, m := range c.c.Mounts { - if m.Driver == "local" { - count++ - } - } - - return fmt.Sprintf("%d", count) -} - -func (c *containerContext) Networks() string { - if c.c.NetworkSettings == nil { - return "" - } - - networks := []string{} - for k := range c.c.NetworkSettings.Networks { - networks = append(networks, k) - } - - return strings.Join(networks, ",") -} - -// DisplayablePorts returns formatted string representing open ports of container -// e.g. "0.0.0.0:80->9090/tcp, 9988/tcp" -// it's used by command 'docker ps' -func DisplayablePorts(ports []types.Port) string { - type portGroup struct { - first uint16 - last uint16 - } - groupMap := make(map[string]*portGroup) - var result []string - var hostMappings []string - var groupMapKeys []string - sort.Sort(byPortInfo(ports)) - for _, port := range ports { - current := port.PrivatePort - portKey := port.Type - if port.IP != "" { - if port.PublicPort != current { - hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type)) - continue - } - portKey = fmt.Sprintf("%s/%s", port.IP, port.Type) - } - group := groupMap[portKey] - - if group == nil { - groupMap[portKey] = &portGroup{first: current, last: current} - // record order that groupMap keys are created - groupMapKeys = append(groupMapKeys, portKey) - continue - } - if current == (group.last + 1) { - group.last = current - continue - } - - result = append(result, formGroup(portKey, group.first, group.last)) - groupMap[portKey] = &portGroup{first: current, last: current} - } - for _, portKey := range groupMapKeys { - g := groupMap[portKey] - result = append(result, formGroup(portKey, g.first, g.last)) - } - result = append(result, hostMappings...) - return strings.Join(result, ", ") -} - -func formGroup(key string, start, last uint16) string { - parts := strings.Split(key, "/") - groupType := parts[0] - var ip string - if len(parts) > 1 { - ip = parts[0] - groupType = parts[1] - } - group := strconv.Itoa(int(start)) - if start != last { - group = fmt.Sprintf("%s-%d", group, last) - } - if ip != "" { - group = fmt.Sprintf("%s:%s->%s", ip, group, group) - } - return fmt.Sprintf("%s/%s", group, groupType) -} - -// byPortInfo is a temporary type used to sort types.Port by its fields -type byPortInfo []types.Port - -func (r byPortInfo) Len() int { return len(r) } -func (r byPortInfo) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byPortInfo) Less(i, j int) bool { - if r[i].PrivatePort != r[j].PrivatePort { - return r[i].PrivatePort < r[j].PrivatePort - } - - if r[i].IP != r[j].IP { - return r[i].IP < r[j].IP - } - - if r[i].PublicPort != r[j].PublicPort { - return r[i].PublicPort < r[j].PublicPort - } - - return r[i].Type < r[j].Type -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/container_test.go b/vendor/github.com/docker/cli/cli/command/formatter/container_test.go deleted file mode 100644 index 02f75bd0a..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/container_test.go +++ /dev/null @@ -1,655 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestContainerPsContext(t *testing.T) { - containerID := stringid.GenerateRandomID() - unix := time.Now().Add(-65 * time.Second).Unix() - - var ctx containerContext - cases := []struct { - container types.Container - trunc bool - expValue string - call func() string - }{ - {types.Container{ID: containerID}, true, stringid.TruncateID(containerID), ctx.ID}, - {types.Container{ID: containerID}, false, containerID, ctx.ID}, - {types.Container{Names: []string{"/foobar_baz"}}, true, "foobar_baz", ctx.Names}, - {types.Container{Image: "ubuntu"}, true, "ubuntu", ctx.Image}, - {types.Container{Image: "verylongimagename"}, true, "verylongimagename", ctx.Image}, - {types.Container{Image: "verylongimagename"}, false, "verylongimagename", ctx.Image}, - {types.Container{ - Image: "a5a665ff33eced1e0803148700880edab4", - ImageID: "a5a665ff33eced1e0803148700880edab4269067ed77e27737a708d0d293fbf5", - }, - true, - "a5a665ff33ec", - ctx.Image, - }, - {types.Container{ - Image: "a5a665ff33eced1e0803148700880edab4", - ImageID: "a5a665ff33eced1e0803148700880edab4269067ed77e27737a708d0d293fbf5", - }, - false, - "a5a665ff33eced1e0803148700880edab4", - ctx.Image, - }, - {types.Container{Image: ""}, true, "", ctx.Image}, - {types.Container{Command: "sh -c 'ls -la'"}, true, `"sh -c 'ls -la'"`, ctx.Command}, - {types.Container{Created: unix}, true, time.Unix(unix, 0).String(), ctx.CreatedAt}, - {types.Container{Ports: []types.Port{{PrivatePort: 8080, PublicPort: 8080, Type: "tcp"}}}, true, "8080/tcp", ctx.Ports}, - {types.Container{Status: "RUNNING"}, true, "RUNNING", ctx.Status}, - {types.Container{SizeRw: 10}, true, "10B", ctx.Size}, - {types.Container{SizeRw: 10, SizeRootFs: 20}, true, "10B (virtual 20B)", ctx.Size}, - {types.Container{}, true, "", ctx.Labels}, - {types.Container{Labels: map[string]string{"cpu": "6", "storage": "ssd"}}, true, "cpu=6,storage=ssd", ctx.Labels}, - {types.Container{Created: unix}, true, "About a minute ago", ctx.RunningFor}, - {types.Container{ - Mounts: []types.MountPoint{ - { - Name: "this-is-a-long-volume-name-and-will-be-truncated-if-trunc-is-set", - Driver: "local", - Source: "/a/path", - }, - }, - }, true, "this-is-a-lo...", ctx.Mounts}, - {types.Container{ - Mounts: []types.MountPoint{ - { - Driver: "local", - Source: "/a/path", - }, - }, - }, false, "/a/path", ctx.Mounts}, - {types.Container{ - Mounts: []types.MountPoint{ - { - Name: "733908409c91817de8e92b0096373245f329f19a88e2c849f02460e9b3d1c203", - Driver: "local", - Source: "/a/path", - }, - }, - }, false, "733908409c91817de8e92b0096373245f329f19a88e2c849f02460e9b3d1c203", ctx.Mounts}, - } - - for _, c := range cases { - ctx = containerContext{c: c.container, trunc: c.trunc} - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } - - c1 := types.Container{Labels: map[string]string{"com.docker.swarm.swarm-id": "33", "com.docker.swarm.node_name": "ubuntu"}} - ctx = containerContext{c: c1, trunc: true} - - sid := ctx.Label("com.docker.swarm.swarm-id") - node := ctx.Label("com.docker.swarm.node_name") - if sid != "33" { - t.Fatalf("Expected 33, was %s\n", sid) - } - - if node != "ubuntu" { - t.Fatalf("Expected ubuntu, was %s\n", node) - } - - c2 := types.Container{} - ctx = containerContext{c: c2, trunc: true} - - label := ctx.Label("anything.really") - if label != "" { - t.Fatalf("Expected an empty string, was %s", label) - } -} - -func TestContainerContextWrite(t *testing.T) { - unixTime := time.Now().AddDate(0, 0, -1).Unix() - expectedTime := time.Unix(unixTime, 0).String() - - cases := []struct { - context Context - expected string - }{ - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table Format - { - Context{Format: NewContainerFormat("table", false, true)}, - `CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE -containerID1 ubuntu "" 24 hours ago foobar_baz 0B -containerID2 ubuntu "" 24 hours ago foobar_bar 0B -`, - }, - { - Context{Format: NewContainerFormat("table", false, false)}, - `CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -containerID1 ubuntu "" 24 hours ago foobar_baz -containerID2 ubuntu "" 24 hours ago foobar_bar -`, - }, - { - Context{Format: NewContainerFormat("table {{.Image}}", false, false)}, - "IMAGE\nubuntu\nubuntu\n", - }, - { - Context{Format: NewContainerFormat("table {{.Image}}", false, true)}, - "IMAGE\nubuntu\nubuntu\n", - }, - { - Context{Format: NewContainerFormat("table {{.Image}}", true, false)}, - "IMAGE\nubuntu\nubuntu\n", - }, - { - Context{Format: NewContainerFormat("table", true, false)}, - "containerID1\ncontainerID2\n", - }, - // Raw Format - { - Context{Format: NewContainerFormat("raw", false, false)}, - fmt.Sprintf(`container_id: containerID1 -image: ubuntu -command: "" -created_at: %s -status: -names: foobar_baz -labels: -ports: - -container_id: containerID2 -image: ubuntu -command: "" -created_at: %s -status: -names: foobar_bar -labels: -ports: - -`, expectedTime, expectedTime), - }, - { - Context{Format: NewContainerFormat("raw", false, true)}, - fmt.Sprintf(`container_id: containerID1 -image: ubuntu -command: "" -created_at: %s -status: -names: foobar_baz -labels: -ports: -size: 0B - -container_id: containerID2 -image: ubuntu -command: "" -created_at: %s -status: -names: foobar_bar -labels: -ports: -size: 0B - -`, expectedTime, expectedTime), - }, - { - Context{Format: NewContainerFormat("raw", true, false)}, - "container_id: containerID1\ncontainer_id: containerID2\n", - }, - // Custom Format - { - Context{Format: "{{.Image}}"}, - "ubuntu\nubuntu\n", - }, - { - Context{Format: NewContainerFormat("{{.Image}}", false, true)}, - "ubuntu\nubuntu\n", - }, - // Special headers for customized table format - { - Context{Format: NewContainerFormat(`table {{truncate .ID 5}}\t{{json .Image}} {{.RunningFor}}/{{title .Status}}/{{pad .Ports 2 2}}.{{upper .Names}} {{lower .Status}}`, false, true)}, - string(golden.Get(t, "container-context-write-special-headers.golden")), - }, - } - - for _, testcase := range cases { - containers := []types.Container{ - {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unixTime}, - {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unixTime}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := ContainerWrite(testcase.context, containers) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestContainerContextWriteWithNoContainers(t *testing.T) { - out := bytes.NewBufferString("") - containers := []types.Container{} - - contexts := []struct { - context Context - expected string - }{ - { - Context{ - Format: "{{.Image}}", - Output: out, - }, - "", - }, - { - Context{ - Format: "table {{.Image}}", - Output: out, - }, - "IMAGE\n", - }, - { - Context{ - Format: NewContainerFormat("{{.Image}}", false, true), - Output: out, - }, - "", - }, - { - Context{ - Format: NewContainerFormat("table {{.Image}}", false, true), - Output: out, - }, - "IMAGE\n", - }, - { - Context{ - Format: "table {{.Image}}\t{{.Size}}", - Output: out, - }, - "IMAGE SIZE\n", - }, - { - Context{ - Format: NewContainerFormat("table {{.Image}}\t{{.Size}}", false, true), - Output: out, - }, - "IMAGE SIZE\n", - }, - } - - for _, context := range contexts { - ContainerWrite(context.context, containers) - assert.Equal(t, context.expected, out.String()) - // Clean buffer - out.Reset() - } -} - -func TestContainerContextWriteJSON(t *testing.T) { - unix := time.Now().Add(-65 * time.Second).Unix() - containers := []types.Container{ - {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu", Created: unix}, - {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu", Created: unix}, - } - expectedCreated := time.Unix(unix, 0).String() - expectedJSONs := []map[string]interface{}{ - { - "Command": "\"\"", - "CreatedAt": expectedCreated, - "ID": "containerID1", - "Image": "ubuntu", - "Labels": "", - "LocalVolumes": "0", - "Mounts": "", - "Names": "foobar_baz", - "Networks": "", - "Ports": "", - "RunningFor": "About a minute ago", - "Size": "0B", - "Status": "", - }, - { - "Command": "\"\"", - "CreatedAt": expectedCreated, - "ID": "containerID2", - "Image": "ubuntu", - "Labels": "", - "LocalVolumes": "0", - "Mounts": "", - "Names": "foobar_bar", - "Networks": "", - "Ports": "", - "RunningFor": "About a minute ago", - "Size": "0B", - "Status": "", - }, - } - out := bytes.NewBufferString("") - err := ContainerWrite(Context{Format: "{{json .}}", Output: out}, containers) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var m map[string]interface{} - err := json.Unmarshal([]byte(line), &m) - require.NoError(t, err, msg) - assert.Equal(t, expectedJSONs[i], m, msg) - } -} - -func TestContainerContextWriteJSONField(t *testing.T) { - containers := []types.Container{ - {ID: "containerID1", Names: []string{"/foobar_baz"}, Image: "ubuntu"}, - {ID: "containerID2", Names: []string{"/foobar_bar"}, Image: "ubuntu"}, - } - out := bytes.NewBufferString("") - err := ContainerWrite(Context{Format: "{{json .ID}}", Output: out}, containers) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var s string - err := json.Unmarshal([]byte(line), &s) - require.NoError(t, err, msg) - assert.Equal(t, containers[i].ID, s, msg) - } -} - -func TestContainerBackCompat(t *testing.T) { - containers := []types.Container{{ID: "brewhaha"}} - cases := []string{ - "ID", - "Names", - "Image", - "Command", - "CreatedAt", - "RunningFor", - "Ports", - "Status", - "Size", - "Labels", - "Mounts", - } - buf := bytes.NewBuffer(nil) - for _, c := range cases { - ctx := Context{Format: Format(fmt.Sprintf("{{ .%s }}", c)), Output: buf} - if err := ContainerWrite(ctx, containers); err != nil { - t.Logf("could not render template for field '%s': %v", c, err) - t.Fail() - } - buf.Reset() - } -} - -type ports struct { - ports []types.Port - expected string -} - -// nolint: lll -func TestDisplayablePorts(t *testing.T) { - cases := []ports{ - { - []types.Port{ - { - PrivatePort: 9988, - Type: "tcp", - }, - }, - "9988/tcp"}, - { - []types.Port{ - { - PrivatePort: 9988, - Type: "udp", - }, - }, - "9988/udp", - }, - { - []types.Port{ - { - IP: "0.0.0.0", - PrivatePort: 9988, - Type: "tcp", - }, - }, - "0.0.0.0:0->9988/tcp", - }, - { - []types.Port{ - { - PrivatePort: 9988, - PublicPort: 8899, - Type: "tcp", - }, - }, - "9988/tcp", - }, - { - []types.Port{ - { - IP: "4.3.2.1", - PrivatePort: 9988, - PublicPort: 8899, - Type: "tcp", - }, - }, - "4.3.2.1:8899->9988/tcp", - }, - { - []types.Port{ - { - IP: "4.3.2.1", - PrivatePort: 9988, - PublicPort: 9988, - Type: "tcp", - }, - }, - "4.3.2.1:9988->9988/tcp", - }, - { - []types.Port{ - { - PrivatePort: 9988, - Type: "udp", - }, { - PrivatePort: 9988, - Type: "udp", - }, - }, - "9988/udp, 9988/udp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PublicPort: 9998, - PrivatePort: 9998, - Type: "udp", - }, { - IP: "1.2.3.4", - PublicPort: 9999, - PrivatePort: 9999, - Type: "udp", - }, - }, - "1.2.3.4:9998-9999->9998-9999/udp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PublicPort: 8887, - PrivatePort: 9998, - Type: "udp", - }, { - IP: "1.2.3.4", - PublicPort: 8888, - PrivatePort: 9999, - Type: "udp", - }, - }, - "1.2.3.4:8887->9998/udp, 1.2.3.4:8888->9999/udp", - }, - { - []types.Port{ - { - PrivatePort: 9998, - Type: "udp", - }, { - PrivatePort: 9999, - Type: "udp", - }, - }, - "9998-9999/udp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PrivatePort: 6677, - PublicPort: 7766, - Type: "tcp", - }, { - PrivatePort: 9988, - PublicPort: 8899, - Type: "udp", - }, - }, - "9988/udp, 1.2.3.4:7766->6677/tcp", - }, - { - []types.Port{ - { - IP: "1.2.3.4", - PrivatePort: 9988, - PublicPort: 8899, - Type: "udp", - }, { - IP: "1.2.3.4", - PrivatePort: 9988, - PublicPort: 8899, - Type: "tcp", - }, { - IP: "4.3.2.1", - PrivatePort: 2233, - PublicPort: 3322, - Type: "tcp", - }, - }, - "4.3.2.1:3322->2233/tcp, 1.2.3.4:8899->9988/tcp, 1.2.3.4:8899->9988/udp", - }, - { - []types.Port{ - { - PrivatePort: 9988, - PublicPort: 8899, - Type: "udp", - }, { - IP: "1.2.3.4", - PrivatePort: 6677, - PublicPort: 7766, - Type: "tcp", - }, { - IP: "4.3.2.1", - PrivatePort: 2233, - PublicPort: 3322, - Type: "tcp", - }, - }, - "9988/udp, 4.3.2.1:3322->2233/tcp, 1.2.3.4:7766->6677/tcp", - }, - { - []types.Port{ - { - PrivatePort: 80, - Type: "tcp", - }, { - PrivatePort: 1024, - Type: "tcp", - }, { - PrivatePort: 80, - Type: "udp", - }, { - PrivatePort: 1024, - Type: "udp", - }, { - IP: "1.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "tcp", - }, { - IP: "1.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "udp", - }, { - IP: "1.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "tcp", - }, { - IP: "1.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "udp", - }, { - IP: "2.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "tcp", - }, { - IP: "2.1.1.1", - PublicPort: 80, - PrivatePort: 1024, - Type: "udp", - }, { - IP: "2.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "tcp", - }, { - IP: "2.1.1.1", - PublicPort: 1024, - PrivatePort: 80, - Type: "udp", - }, - }, - "80/tcp, 80/udp, 1024/tcp, 1024/udp, 1.1.1.1:1024->80/tcp, 1.1.1.1:1024->80/udp, 2.1.1.1:1024->80/tcp, 2.1.1.1:1024->80/udp, 1.1.1.1:80->1024/tcp, 1.1.1.1:80->1024/udp, 2.1.1.1:80->1024/tcp, 2.1.1.1:80->1024/udp", - }, - } - - for _, port := range cases { - actual := DisplayablePorts(port.ports) - assert.Equal(t, port.expected, actual) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/custom.go b/vendor/github.com/docker/cli/cli/command/formatter/custom.go deleted file mode 100644 index 73487f63e..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/custom.go +++ /dev/null @@ -1,35 +0,0 @@ -package formatter - -const ( - imageHeader = "IMAGE" - createdSinceHeader = "CREATED" - createdAtHeader = "CREATED AT" - sizeHeader = "SIZE" - labelsHeader = "LABELS" - nameHeader = "NAME" - driverHeader = "DRIVER" - scopeHeader = "SCOPE" -) - -type subContext interface { - FullHeader() interface{} -} - -// HeaderContext provides the subContext interface for managing headers -type HeaderContext struct { - header interface{} -} - -// FullHeader returns the header as an interface -func (c *HeaderContext) FullHeader() interface{} { - return c.header -} - -func stripNamePrefix(ss []string) []string { - sss := make([]string, len(ss)) - for i, s := range ss { - sss[i] = s[1:] - } - - return sss -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/custom_test.go b/vendor/github.com/docker/cli/cli/command/formatter/custom_test.go deleted file mode 100644 index a9f6ccdac..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/custom_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package formatter - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/assert" -) - -func compareMultipleValues(t *testing.T, value, expected string) { - // comma-separated values means probably a map input, which won't - // be guaranteed to have the same order as our expected value - // We'll create maps and use reflect.DeepEquals to check instead: - entriesMap := make(map[string]string) - expMap := make(map[string]string) - entries := strings.Split(value, ",") - expectedEntries := strings.Split(expected, ",") - for _, entry := range entries { - keyval := strings.Split(entry, "=") - entriesMap[keyval[0]] = keyval[1] - } - for _, expected := range expectedEntries { - keyval := strings.Split(expected, "=") - expMap[keyval[0]] = keyval[1] - } - assert.Equal(t, expMap, entriesMap) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/diff.go b/vendor/github.com/docker/cli/cli/command/formatter/diff.go deleted file mode 100644 index 9b4681934..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/diff.go +++ /dev/null @@ -1,72 +0,0 @@ -package formatter - -import ( - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/archive" -) - -const ( - defaultDiffTableFormat = "table {{.Type}}\t{{.Path}}" - - changeTypeHeader = "CHANGE TYPE" - pathHeader = "PATH" -) - -// NewDiffFormat returns a format for use with a diff Context -func NewDiffFormat(source string) Format { - switch source { - case TableFormatKey: - return defaultDiffTableFormat - } - return Format(source) -} - -// DiffWrite writes formatted diff using the Context -func DiffWrite(ctx Context, changes []container.ContainerChangeResponseItem) error { - - render := func(format func(subContext subContext) error) error { - for _, change := range changes { - if err := format(&diffContext{c: change}); err != nil { - return err - } - } - return nil - } - return ctx.Write(newDiffContext(), render) -} - -type diffContext struct { - HeaderContext - c container.ContainerChangeResponseItem -} - -func newDiffContext() *diffContext { - diffCtx := diffContext{} - diffCtx.header = map[string]string{ - "Type": changeTypeHeader, - "Path": pathHeader, - } - return &diffCtx -} - -func (d *diffContext) MarshalJSON() ([]byte, error) { - return marshalJSON(d) -} - -func (d *diffContext) Type() string { - var kind string - switch d.c.Kind { - case archive.ChangeModify: - kind = "C" - case archive.ChangeAdd: - kind = "A" - case archive.ChangeDelete: - kind = "D" - } - return kind - -} - -func (d *diffContext) Path() string { - return d.c.Path -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/diff_test.go b/vendor/github.com/docker/cli/cli/command/formatter/diff_test.go deleted file mode 100644 index 1aa7b5305..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/diff_test.go +++ /dev/null @@ -1,59 +0,0 @@ -package formatter - -import ( - "bytes" - "testing" - - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/archive" - "github.com/stretchr/testify/assert" -) - -func TestDiffContextFormatWrite(t *testing.T) { - // Check default output format (verbose and non-verbose mode) for table headers - cases := []struct { - context Context - expected string - }{ - { - Context{Format: NewDiffFormat("table")}, - `CHANGE TYPE PATH -C /var/log/app.log -A /usr/app/app.js -D /usr/app/old_app.js -`, - }, - { - Context{Format: NewDiffFormat("table {{.Path}}")}, - `PATH -/var/log/app.log -/usr/app/app.js -/usr/app/old_app.js -`, - }, - { - Context{Format: NewDiffFormat("{{.Type}}: {{.Path}}")}, - `C: /var/log/app.log -A: /usr/app/app.js -D: /usr/app/old_app.js -`, - }, - } - - diffs := []container.ContainerChangeResponseItem{ - {archive.ChangeModify, "/var/log/app.log"}, - {archive.ChangeAdd, "/usr/app/app.js"}, - {archive.ChangeDelete, "/usr/app/old_app.js"}, - } - - for _, testcase := range cases { - out := bytes.NewBufferString("") - testcase.context.Output = out - err := DiffWrite(testcase.context, diffs) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/disk_usage.go b/vendor/github.com/docker/cli/cli/command/formatter/disk_usage.go deleted file mode 100644 index 5681f296c..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/disk_usage.go +++ /dev/null @@ -1,399 +0,0 @@ -package formatter - -import ( - "bytes" - "fmt" - "strings" - "text/template" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - units "github.com/docker/go-units" -) - -const ( - defaultDiskUsageImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}} ago\t{{.VirtualSize}}\t{{.SharedSize}}\t{{.UniqueSize}}\t{{.Containers}}" - defaultDiskUsageContainerTableFormat = "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.LocalVolumes}}\t{{.Size}}\t{{.RunningFor}} ago\t{{.Status}}\t{{.Names}}" - defaultDiskUsageVolumeTableFormat = "table {{.Name}}\t{{.Links}}\t{{.Size}}" - defaultDiskUsageTableFormat = "table {{.Type}}\t{{.TotalCount}}\t{{.Active}}\t{{.Size}}\t{{.Reclaimable}}" - - typeHeader = "TYPE" - totalHeader = "TOTAL" - activeHeader = "ACTIVE" - reclaimableHeader = "RECLAIMABLE" - containersHeader = "CONTAINERS" - sharedSizeHeader = "SHARED SIZE" - uniqueSizeHeader = "UNIQUE SiZE" -) - -// DiskUsageContext contains disk usage specific information required by the formatter, encapsulate a Context struct. -type DiskUsageContext struct { - Context - Verbose bool - LayersSize int64 - Images []*types.ImageSummary - Containers []*types.Container - Volumes []*types.Volume - BuilderSize int64 -} - -func (ctx *DiskUsageContext) startSubsection(format string) (*template.Template, error) { - ctx.buffer = bytes.NewBufferString("") - ctx.header = "" - ctx.Format = Format(format) - ctx.preFormat() - - return ctx.parseFormat() -} - -// -// NewDiskUsageFormat returns a format for rendering an DiskUsageContext -func NewDiskUsageFormat(source string) Format { - switch source { - case TableFormatKey: - format := defaultDiskUsageTableFormat - return Format(format) - case RawFormatKey: - format := `type: {{.Type}} -total: {{.TotalCount}} -active: {{.Active}} -size: {{.Size}} -reclaimable: {{.Reclaimable}} -` - return Format(format) - } - return Format(source) -} - -func (ctx *DiskUsageContext) Write() (err error) { - if ctx.Verbose { - return ctx.verboseWrite() - } - ctx.buffer = bytes.NewBufferString("") - ctx.preFormat() - - tmpl, err := ctx.parseFormat() - if err != nil { - return err - } - - err = ctx.contextFormat(tmpl, &diskUsageImagesContext{ - totalSize: ctx.LayersSize, - images: ctx.Images, - }) - if err != nil { - return err - } - err = ctx.contextFormat(tmpl, &diskUsageContainersContext{ - containers: ctx.Containers, - }) - if err != nil { - return err - } - - err = ctx.contextFormat(tmpl, &diskUsageVolumesContext{ - volumes: ctx.Volumes, - }) - if err != nil { - return err - } - - err = ctx.contextFormat(tmpl, &diskUsageBuilderContext{ - builderSize: ctx.BuilderSize, - }) - if err != nil { - return err - } - - diskUsageContainersCtx := diskUsageContainersContext{containers: []*types.Container{}} - diskUsageContainersCtx.header = map[string]string{ - "Type": typeHeader, - "TotalCount": totalHeader, - "Active": activeHeader, - "Size": sizeHeader, - "Reclaimable": reclaimableHeader, - } - ctx.postFormat(tmpl, &diskUsageContainersCtx) - - return err -} - -func (ctx *DiskUsageContext) verboseWrite() (err error) { - // First images - tmpl, err := ctx.startSubsection(defaultDiskUsageImageTableFormat) - if err != nil { - return - } - - ctx.Output.Write([]byte("Images space usage:\n\n")) - for _, i := range ctx.Images { - repo := "" - tag := "" - if len(i.RepoTags) > 0 && !isDangling(*i) { - // Only show the first tag - ref, err := reference.ParseNormalizedNamed(i.RepoTags[0]) - if err != nil { - continue - } - if nt, ok := ref.(reference.NamedTagged); ok { - repo = reference.FamiliarName(ref) - tag = nt.Tag() - } - } - - err = ctx.contextFormat(tmpl, &imageContext{ - repo: repo, - tag: tag, - trunc: true, - i: *i, - }) - if err != nil { - return - } - } - ctx.postFormat(tmpl, newImageContext()) - - // Now containers - ctx.Output.Write([]byte("\nContainers space usage:\n\n")) - tmpl, err = ctx.startSubsection(defaultDiskUsageContainerTableFormat) - if err != nil { - return - } - for _, c := range ctx.Containers { - // Don't display the virtual size - c.SizeRootFs = 0 - err = ctx.contextFormat(tmpl, &containerContext{ - trunc: true, - c: *c, - }) - if err != nil { - return - } - } - ctx.postFormat(tmpl, newContainerContext()) - - // And volumes - ctx.Output.Write([]byte("\nLocal Volumes space usage:\n\n")) - tmpl, err = ctx.startSubsection(defaultDiskUsageVolumeTableFormat) - if err != nil { - return - } - for _, v := range ctx.Volumes { - err = ctx.contextFormat(tmpl, &volumeContext{ - v: *v, - }) - if err != nil { - return - } - } - ctx.postFormat(tmpl, newVolumeContext()) - - // And build cache - fmt.Fprintf(ctx.Output, "\nBuild cache usage: %s\n\n", units.HumanSize(float64(ctx.BuilderSize))) - return -} - -type diskUsageImagesContext struct { - HeaderContext - totalSize int64 - images []*types.ImageSummary -} - -func (c *diskUsageImagesContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *diskUsageImagesContext) Type() string { - return "Images" -} - -func (c *diskUsageImagesContext) TotalCount() string { - return fmt.Sprintf("%d", len(c.images)) -} - -func (c *diskUsageImagesContext) Active() string { - used := 0 - for _, i := range c.images { - if i.Containers > 0 { - used++ - } - } - - return fmt.Sprintf("%d", used) -} - -func (c *diskUsageImagesContext) Size() string { - return units.HumanSize(float64(c.totalSize)) - -} - -func (c *diskUsageImagesContext) Reclaimable() string { - var used int64 - - for _, i := range c.images { - if i.Containers != 0 { - if i.VirtualSize == -1 || i.SharedSize == -1 { - continue - } - used += i.VirtualSize - i.SharedSize - } - } - - reclaimable := c.totalSize - used - if c.totalSize > 0 { - return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(reclaimable)), (reclaimable*100)/c.totalSize) - } - return units.HumanSize(float64(reclaimable)) -} - -type diskUsageContainersContext struct { - HeaderContext - containers []*types.Container -} - -func (c *diskUsageContainersContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *diskUsageContainersContext) Type() string { - return "Containers" -} - -func (c *diskUsageContainersContext) TotalCount() string { - return fmt.Sprintf("%d", len(c.containers)) -} - -func (c *diskUsageContainersContext) isActive(container types.Container) bool { - return strings.Contains(container.State, "running") || - strings.Contains(container.State, "paused") || - strings.Contains(container.State, "restarting") -} - -func (c *diskUsageContainersContext) Active() string { - used := 0 - for _, container := range c.containers { - if c.isActive(*container) { - used++ - } - } - - return fmt.Sprintf("%d", used) -} - -func (c *diskUsageContainersContext) Size() string { - var size int64 - - for _, container := range c.containers { - size += container.SizeRw - } - - return units.HumanSize(float64(size)) -} - -func (c *diskUsageContainersContext) Reclaimable() string { - var reclaimable int64 - var totalSize int64 - - for _, container := range c.containers { - if !c.isActive(*container) { - reclaimable += container.SizeRw - } - totalSize += container.SizeRw - } - - if totalSize > 0 { - return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(reclaimable)), (reclaimable*100)/totalSize) - } - - return units.HumanSize(float64(reclaimable)) -} - -type diskUsageVolumesContext struct { - HeaderContext - volumes []*types.Volume -} - -func (c *diskUsageVolumesContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *diskUsageVolumesContext) Type() string { - return "Local Volumes" -} - -func (c *diskUsageVolumesContext) TotalCount() string { - return fmt.Sprintf("%d", len(c.volumes)) -} - -func (c *diskUsageVolumesContext) Active() string { - - used := 0 - for _, v := range c.volumes { - if v.UsageData.RefCount > 0 { - used++ - } - } - - return fmt.Sprintf("%d", used) -} - -func (c *diskUsageVolumesContext) Size() string { - var size int64 - - for _, v := range c.volumes { - if v.UsageData.Size != -1 { - size += v.UsageData.Size - } - } - - return units.HumanSize(float64(size)) -} - -func (c *diskUsageVolumesContext) Reclaimable() string { - var reclaimable int64 - var totalSize int64 - - for _, v := range c.volumes { - if v.UsageData.Size != -1 { - if v.UsageData.RefCount == 0 { - reclaimable += v.UsageData.Size - } - totalSize += v.UsageData.Size - } - } - - if totalSize > 0 { - return fmt.Sprintf("%s (%v%%)", units.HumanSize(float64(reclaimable)), (reclaimable*100)/totalSize) - } - - return units.HumanSize(float64(reclaimable)) -} - -type diskUsageBuilderContext struct { - HeaderContext - builderSize int64 -} - -func (c *diskUsageBuilderContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *diskUsageBuilderContext) Type() string { - return "Build Cache" -} - -func (c *diskUsageBuilderContext) TotalCount() string { - return "" -} - -func (c *diskUsageBuilderContext) Active() string { - return "" -} - -func (c *diskUsageBuilderContext) Size() string { - return units.HumanSize(float64(c.builderSize)) -} - -func (c *diskUsageBuilderContext) Reclaimable() string { - return c.Size() -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/disk_usage_test.go b/vendor/github.com/docker/cli/cli/command/formatter/disk_usage_test.go deleted file mode 100644 index 293fe6d82..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/disk_usage_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package formatter - -import ( - "bytes" - "testing" - - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestDiskUsageContextFormatWrite(t *testing.T) { - cases := []struct { - context DiskUsageContext - expected string - }{ - // Check default output format (verbose and non-verbose mode) for table headers - { - DiskUsageContext{ - Context: Context{ - Format: NewDiskUsageFormat("table"), - }, - Verbose: false}, - `TYPE TOTAL ACTIVE SIZE RECLAIMABLE -Images 0 0 0B 0B -Containers 0 0 0B 0B -Local Volumes 0 0 0B 0B -Build Cache 0B 0B -`, - }, - { - DiskUsageContext{Verbose: true}, - `Images space usage: - -REPOSITORY TAG IMAGE ID CREATED ago SIZE SHARED SIZE UNIQUE SiZE CONTAINERS - -Containers space usage: - -CONTAINER ID IMAGE COMMAND LOCAL VOLUMES SIZE CREATED ago STATUS NAMES - -Local Volumes space usage: - -VOLUME NAME LINKS SIZE - -Build cache usage: 0B - -`, - }, - // Errors - { - DiskUsageContext{ - Context: Context{ - Format: "{{InvalidFunction}}", - }, - }, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - DiskUsageContext{ - Context: Context{ - Format: "{{nil}}", - }, - }, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table Format - { - DiskUsageContext{ - Context: Context{ - Format: NewDiskUsageFormat("table"), - }, - }, - `TYPE TOTAL ACTIVE SIZE RECLAIMABLE -Images 0 0 0B 0B -Containers 0 0 0B 0B -Local Volumes 0 0 0B 0B -Build Cache 0B 0B -`, - }, - { - DiskUsageContext{ - Context: Context{ - Format: NewDiskUsageFormat("table {{.Type}}\t{{.Active}}"), - }, - }, - string(golden.Get(t, "disk-usage-context-write-custom.golden")), - }, - // Raw Format - { - DiskUsageContext{ - Context: Context{ - Format: NewDiskUsageFormat("raw"), - }, - }, - string(golden.Get(t, "disk-usage-raw-format.golden")), - }, - } - - for _, testcase := range cases { - out := bytes.NewBufferString("") - testcase.context.Output = out - if err := testcase.context.Write(); err != nil { - assert.Equal(t, testcase.expected, err.Error()) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/formatter.go b/vendor/github.com/docker/cli/cli/command/formatter/formatter.go deleted file mode 100644 index c63e1a490..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/formatter.go +++ /dev/null @@ -1,119 +0,0 @@ -package formatter - -import ( - "bytes" - "io" - "strings" - "text/tabwriter" - "text/template" - - "github.com/docker/cli/templates" - "github.com/pkg/errors" -) - -// Format keys used to specify certain kinds of output formats -const ( - TableFormatKey = "table" - RawFormatKey = "raw" - PrettyFormatKey = "pretty" - - defaultQuietFormat = "{{.ID}}" -) - -// Format is the format string rendered using the Context -type Format string - -// IsTable returns true if the format is a table-type format -func (f Format) IsTable() bool { - return strings.HasPrefix(string(f), TableFormatKey) -} - -// Contains returns true if the format contains the substring -func (f Format) Contains(sub string) bool { - return strings.Contains(string(f), sub) -} - -// Context contains information required by the formatter to print the output as desired. -type Context struct { - // Output is the output stream to which the formatted string is written. - Output io.Writer - // Format is used to choose raw, table or custom format for the output. - Format Format - // Trunc when set to true will truncate the output of certain fields such as Container ID. - Trunc bool - - // internal element - finalFormat string - header interface{} - buffer *bytes.Buffer -} - -func (c *Context) preFormat() { - c.finalFormat = string(c.Format) - - // TODO: handle this in the Format type - if c.Format.IsTable() { - c.finalFormat = c.finalFormat[len(TableFormatKey):] - } - - c.finalFormat = strings.Trim(c.finalFormat, " ") - r := strings.NewReplacer(`\t`, "\t", `\n`, "\n") - c.finalFormat = r.Replace(c.finalFormat) -} - -func (c *Context) parseFormat() (*template.Template, error) { - tmpl, err := templates.Parse(c.finalFormat) - if err != nil { - return tmpl, errors.Errorf("Template parsing error: %v\n", err) - } - return tmpl, err -} - -func (c *Context) postFormat(tmpl *template.Template, subContext subContext) { - if c.Format.IsTable() { - t := tabwriter.NewWriter(c.Output, 20, 1, 3, ' ', 0) - buffer := bytes.NewBufferString("") - tmpl.Funcs(templates.HeaderFunctions).Execute(buffer, subContext.FullHeader()) - buffer.WriteTo(t) - t.Write([]byte("\n")) - c.buffer.WriteTo(t) - t.Flush() - } else { - c.buffer.WriteTo(c.Output) - } -} - -func (c *Context) contextFormat(tmpl *template.Template, subContext subContext) error { - if err := tmpl.Execute(c.buffer, subContext); err != nil { - return errors.Errorf("Template parsing error: %v\n", err) - } - if c.Format.IsTable() && c.header != nil { - c.header = subContext.FullHeader() - } - c.buffer.WriteString("\n") - return nil -} - -// SubFormat is a function type accepted by Write() -type SubFormat func(func(subContext) error) error - -// Write the template to the buffer using this Context -func (c *Context) Write(sub subContext, f SubFormat) error { - c.buffer = bytes.NewBufferString("") - c.preFormat() - - tmpl, err := c.parseFormat() - if err != nil { - return err - } - - subFormat := func(subContext subContext) error { - return c.contextFormat(tmpl, subContext) - } - if err := f(subFormat); err != nil { - return err - } - - c.postFormat(tmpl, sub) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/history.go b/vendor/github.com/docker/cli/cli/command/formatter/history.go deleted file mode 100644 index c01b54159..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/history.go +++ /dev/null @@ -1,110 +0,0 @@ -package formatter - -import ( - "strconv" - "strings" - "time" - - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - units "github.com/docker/go-units" -) - -const ( - defaultHistoryTableFormat = "table {{.ID}}\t{{.CreatedSince}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}" - nonHumanHistoryTableFormat = "table {{.ID}}\t{{.CreatedAt}}\t{{.CreatedBy}}\t{{.Size}}\t{{.Comment}}" - - historyIDHeader = "IMAGE" - createdByHeader = "CREATED BY" - commentHeader = "COMMENT" -) - -// NewHistoryFormat returns a format for rendering an HistoryContext -func NewHistoryFormat(source string, quiet bool, human bool) Format { - switch source { - case TableFormatKey: - switch { - case quiet: - return defaultQuietFormat - case !human: - return nonHumanHistoryTableFormat - default: - return defaultHistoryTableFormat - } - } - - return Format(source) -} - -// HistoryWrite writes the context -func HistoryWrite(ctx Context, human bool, histories []image.HistoryResponseItem) error { - render := func(format func(subContext subContext) error) error { - for _, history := range histories { - historyCtx := &historyContext{trunc: ctx.Trunc, h: history, human: human} - if err := format(historyCtx); err != nil { - return err - } - } - return nil - } - historyCtx := &historyContext{} - historyCtx.header = map[string]string{ - "ID": historyIDHeader, - "CreatedSince": createdSinceHeader, - "CreatedAt": createdAtHeader, - "CreatedBy": createdByHeader, - "Size": sizeHeader, - "Comment": commentHeader, - } - return ctx.Write(historyCtx, render) -} - -type historyContext struct { - HeaderContext - trunc bool - human bool - h image.HistoryResponseItem -} - -func (c *historyContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *historyContext) ID() string { - if c.trunc { - return stringid.TruncateID(c.h.ID) - } - return c.h.ID -} - -func (c *historyContext) CreatedAt() string { - return time.Unix(c.h.Created, 0).Format(time.RFC3339) -} - -func (c *historyContext) CreatedSince() string { - if !c.human { - return c.CreatedAt() - } - created := units.HumanDuration(time.Now().UTC().Sub(time.Unix(c.h.Created, 0))) - return created + " ago" -} - -func (c *historyContext) CreatedBy() string { - createdBy := strings.Replace(c.h.CreatedBy, "\t", " ", -1) - if c.trunc { - return stringutils.Ellipsis(createdBy, 45) - } - return createdBy -} - -func (c *historyContext) Size() string { - if c.human { - return units.HumanSizeWithPrecision(float64(c.h.Size), 3) - } - return strconv.FormatInt(c.h.Size, 10) -} - -func (c *historyContext) Comment() string { - return c.h.Comment -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/history_test.go b/vendor/github.com/docker/cli/cli/command/formatter/history_test.go deleted file mode 100644 index 6b2c55e67..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/history_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package formatter - -import ( - "strconv" - "strings" - "testing" - "time" - - "bytes" - - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" - "github.com/stretchr/testify/assert" -) - -type historyCase struct { - historyCtx historyContext - expValue string - call func() string -} - -func TestHistoryContext_ID(t *testing.T) { - id := stringid.GenerateRandomID() - - var ctx historyContext - cases := []historyCase{ - { - historyContext{ - h: image.HistoryResponseItem{ID: id}, - trunc: false, - }, id, ctx.ID, - }, - { - historyContext{ - h: image.HistoryResponseItem{ID: id}, - trunc: true, - }, stringid.TruncateID(id), ctx.ID, - }, - } - - for _, c := range cases { - ctx = c.historyCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestHistoryContext_CreatedSince(t *testing.T) { - var ctx historyContext - cases := []historyCase{ - { - historyContext{ - h: image.HistoryResponseItem{Created: time.Now().AddDate(0, 0, -7).Unix()}, - trunc: false, - human: true, - }, "7 days ago", ctx.CreatedSince, - }, - { - historyContext{ - h: image.HistoryResponseItem{Created: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC).Unix()}, - trunc: false, - human: false, - }, "2009-11-10T23:00:00Z", ctx.CreatedSince, - }, - } - - for _, c := range cases { - ctx = c.historyCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestHistoryContext_CreatedBy(t *testing.T) { - withTabs := `/bin/sh -c apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 && echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >> /etc/apt/sources.list && apt-get update && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates nginx=${NGINX_VERSION} nginx-module-xslt nginx-module-geoip nginx-module-image-filter nginx-module-perl nginx-module-njs gettext-base && rm -rf /var/lib/apt/lists/*` // nolint: lll - expected := `/bin/sh -c apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 && echo "deb http://nginx.org/packages/mainline/debian/ jessie nginx" >> /etc/apt/sources.list && apt-get update && apt-get install --no-install-recommends --no-install-suggests -y ca-certificates nginx=${NGINX_VERSION} nginx-module-xslt nginx-module-geoip nginx-module-image-filter nginx-module-perl nginx-module-njs gettext-base && rm -rf /var/lib/apt/lists/*` // nolint: lll - - var ctx historyContext - cases := []historyCase{ - { - historyContext{ - h: image.HistoryResponseItem{CreatedBy: withTabs}, - trunc: false, - }, expected, ctx.CreatedBy, - }, - { - historyContext{ - h: image.HistoryResponseItem{CreatedBy: withTabs}, - trunc: true, - }, stringutils.Ellipsis(expected, 45), ctx.CreatedBy, - }, - } - - for _, c := range cases { - ctx = c.historyCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestHistoryContext_Size(t *testing.T) { - size := int64(182964289) - expected := "183MB" - - var ctx historyContext - cases := []historyCase{ - { - historyContext{ - h: image.HistoryResponseItem{Size: size}, - trunc: false, - human: true, - }, expected, ctx.Size, - }, { - historyContext{ - h: image.HistoryResponseItem{Size: size}, - trunc: false, - human: false, - }, strconv.Itoa(182964289), ctx.Size, - }, - } - - for _, c := range cases { - ctx = c.historyCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestHistoryContext_Comment(t *testing.T) { - comment := "Some comment" - - var ctx historyContext - cases := []historyCase{ - { - historyContext{ - h: image.HistoryResponseItem{Comment: comment}, - trunc: false, - }, comment, ctx.Comment, - }, - } - - for _, c := range cases { - ctx = c.historyCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestHistoryContext_Table(t *testing.T) { - out := bytes.NewBufferString("") - unixTime := time.Now().AddDate(0, 0, -1).Unix() - histories := []image.HistoryResponseItem{ - { - ID: "imageID1", - Created: unixTime, - CreatedBy: "/bin/bash ls && npm i && npm run test && karma -c karma.conf.js start && npm start && more commands here && the list goes on", - Size: int64(182964289), - Comment: "Hi", - Tags: []string{"image:tag2"}, - }, - {ID: "imageID2", Created: unixTime, CreatedBy: "/bin/bash echo", Size: int64(182964289), Comment: "Hi", Tags: []string{"image:tag2"}}, - {ID: "imageID3", Created: unixTime, CreatedBy: "/bin/bash ls", Size: int64(182964289), Comment: "Hi", Tags: []string{"image:tag2"}}, - {ID: "imageID4", Created: unixTime, CreatedBy: "/bin/bash grep", Size: int64(182964289), Comment: "Hi", Tags: []string{"image:tag2"}}, - } - // nolint: lll - expectedNoTrunc := `IMAGE CREATED CREATED BY SIZE COMMENT -imageID1 24 hours ago /bin/bash ls && npm i && npm run test && karma -c karma.conf.js start && npm start && more commands here && the list goes on 183MB Hi -imageID2 24 hours ago /bin/bash echo 183MB Hi -imageID3 24 hours ago /bin/bash ls 183MB Hi -imageID4 24 hours ago /bin/bash grep 183MB Hi -` - expectedTrunc := `IMAGE CREATED CREATED BY SIZE COMMENT -imageID1 24 hours ago /bin/bash ls && npm i && npm run test && k... 183MB Hi -imageID2 24 hours ago /bin/bash echo 183MB Hi -imageID3 24 hours ago /bin/bash ls 183MB Hi -imageID4 24 hours ago /bin/bash grep 183MB Hi -` - - contexts := []struct { - context Context - expected string - }{ - {Context{ - Format: NewHistoryFormat("table", false, true), - Trunc: true, - Output: out, - }, - expectedTrunc, - }, - {Context{ - Format: NewHistoryFormat("table", false, true), - Trunc: false, - Output: out, - }, - expectedNoTrunc, - }, - } - - for _, context := range contexts { - HistoryWrite(context.context, true, histories) - assert.Equal(t, context.expected, out.String()) - // Clean buffer - out.Reset() - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/image.go b/vendor/github.com/docker/cli/cli/command/formatter/image.go deleted file mode 100644 index e94785ef0..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/image.go +++ /dev/null @@ -1,272 +0,0 @@ -package formatter - -import ( - "fmt" - "time" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - units "github.com/docker/go-units" -) - -const ( - defaultImageTableFormat = "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}" - defaultImageTableFormatWithDigest = "table {{.Repository}}\t{{.Tag}}\t{{.Digest}}\t{{.ID}}\t{{.CreatedSince}}\t{{.Size}}" - - imageIDHeader = "IMAGE ID" - repositoryHeader = "REPOSITORY" - tagHeader = "TAG" - digestHeader = "DIGEST" -) - -// ImageContext contains image specific information required by the formatter, encapsulate a Context struct. -type ImageContext struct { - Context - Digest bool -} - -func isDangling(image types.ImageSummary) bool { - return len(image.RepoTags) == 1 && image.RepoTags[0] == ":" && len(image.RepoDigests) == 1 && image.RepoDigests[0] == "@" -} - -// NewImageFormat returns a format for rendering an ImageContext -func NewImageFormat(source string, quiet bool, digest bool) Format { - switch source { - case TableFormatKey: - switch { - case quiet: - return defaultQuietFormat - case digest: - return defaultImageTableFormatWithDigest - default: - return defaultImageTableFormat - } - case RawFormatKey: - switch { - case quiet: - return `image_id: {{.ID}}` - case digest: - return `repository: {{ .Repository }} -tag: {{.Tag}} -digest: {{.Digest}} -image_id: {{.ID}} -created_at: {{.CreatedAt}} -virtual_size: {{.Size}} -` - default: - return `repository: {{ .Repository }} -tag: {{.Tag}} -image_id: {{.ID}} -created_at: {{.CreatedAt}} -virtual_size: {{.Size}} -` - } - } - - format := Format(source) - if format.IsTable() && digest && !format.Contains("{{.Digest}}") { - format += "\t{{.Digest}}" - } - return format -} - -// ImageWrite writes the formatter images using the ImageContext -func ImageWrite(ctx ImageContext, images []types.ImageSummary) error { - render := func(format func(subContext subContext) error) error { - return imageFormat(ctx, images, format) - } - return ctx.Write(newImageContext(), render) -} - -// needDigest determines whether the image digest should be ignored or not when writing image context -func needDigest(ctx ImageContext) bool { - return ctx.Digest || ctx.Format.Contains("{{.Digest}}") -} - -func imageFormat(ctx ImageContext, images []types.ImageSummary, format func(subContext subContext) error) error { - for _, image := range images { - formatted := []*imageContext{} - if isDangling(image) { - formatted = append(formatted, &imageContext{ - trunc: ctx.Trunc, - i: image, - repo: "", - tag: "", - digest: "", - }) - } else { - formatted = imageFormatTaggedAndDigest(ctx, image) - } - for _, imageCtx := range formatted { - if err := format(imageCtx); err != nil { - return err - } - } - } - return nil -} - -func imageFormatTaggedAndDigest(ctx ImageContext, image types.ImageSummary) []*imageContext { - repoTags := map[string][]string{} - repoDigests := map[string][]string{} - images := []*imageContext{} - - for _, refString := range image.RepoTags { - ref, err := reference.ParseNormalizedNamed(refString) - if err != nil { - continue - } - if nt, ok := ref.(reference.NamedTagged); ok { - familiarRef := reference.FamiliarName(ref) - repoTags[familiarRef] = append(repoTags[familiarRef], nt.Tag()) - } - } - for _, refString := range image.RepoDigests { - ref, err := reference.ParseNormalizedNamed(refString) - if err != nil { - continue - } - if c, ok := ref.(reference.Canonical); ok { - familiarRef := reference.FamiliarName(ref) - repoDigests[familiarRef] = append(repoDigests[familiarRef], c.Digest().String()) - } - } - - addImage := func(repo, tag, digest string) { - image := &imageContext{ - trunc: ctx.Trunc, - i: image, - repo: repo, - tag: tag, - digest: digest, - } - images = append(images, image) - } - - for repo, tags := range repoTags { - digests := repoDigests[repo] - - // Do not display digests as their own row - delete(repoDigests, repo) - - if !needDigest(ctx) { - // Ignore digest references, just show tag once - digests = nil - } - - for _, tag := range tags { - if len(digests) == 0 { - addImage(repo, tag, "") - continue - } - // Display the digests for each tag - for _, dgst := range digests { - addImage(repo, tag, dgst) - } - - } - } - - // Show rows for remaining digest only references - for repo, digests := range repoDigests { - // If digests are displayed, show row per digest - if ctx.Digest { - for _, dgst := range digests { - addImage(repo, "", dgst) - } - } else { - addImage(repo, "", "") - - } - } - return images -} - -type imageContext struct { - HeaderContext - trunc bool - i types.ImageSummary - repo string - tag string - digest string -} - -func newImageContext() *imageContext { - imageCtx := imageContext{} - imageCtx.header = map[string]string{ - "ID": imageIDHeader, - "Repository": repositoryHeader, - "Tag": tagHeader, - "Digest": digestHeader, - "CreatedSince": createdSinceHeader, - "CreatedAt": createdAtHeader, - "Size": sizeHeader, - "Containers": containersHeader, - "VirtualSize": sizeHeader, - "SharedSize": sharedSizeHeader, - "UniqueSize": uniqueSizeHeader, - } - return &imageCtx -} - -func (c *imageContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *imageContext) ID() string { - if c.trunc { - return stringid.TruncateID(c.i.ID) - } - return c.i.ID -} - -func (c *imageContext) Repository() string { - return c.repo -} - -func (c *imageContext) Tag() string { - return c.tag -} - -func (c *imageContext) Digest() string { - return c.digest -} - -func (c *imageContext) CreatedSince() string { - createdAt := time.Unix(c.i.Created, 0) - return units.HumanDuration(time.Now().UTC().Sub(createdAt)) + " ago" -} - -func (c *imageContext) CreatedAt() string { - return time.Unix(c.i.Created, 0).String() -} - -func (c *imageContext) Size() string { - return units.HumanSizeWithPrecision(float64(c.i.Size), 3) -} - -func (c *imageContext) Containers() string { - if c.i.Containers == -1 { - return "N/A" - } - return fmt.Sprintf("%d", c.i.Containers) -} - -func (c *imageContext) VirtualSize() string { - return units.HumanSize(float64(c.i.VirtualSize)) -} - -func (c *imageContext) SharedSize() string { - if c.i.SharedSize == -1 { - return "N/A" - } - return units.HumanSize(float64(c.i.SharedSize)) -} - -func (c *imageContext) UniqueSize() string { - if c.i.VirtualSize == -1 || c.i.SharedSize == -1 { - return "N/A" - } - return units.HumanSize(float64(c.i.VirtualSize - c.i.SharedSize)) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/image_test.go b/vendor/github.com/docker/cli/cli/command/formatter/image_test.go deleted file mode 100644 index 20b73a52c..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/image_test.go +++ /dev/null @@ -1,355 +0,0 @@ -package formatter - -import ( - "bytes" - "fmt" - "strings" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/stretchr/testify/assert" -) - -func TestImageContext(t *testing.T) { - imageID := stringid.GenerateRandomID() - unix := time.Now().Unix() - - var ctx imageContext - cases := []struct { - imageCtx imageContext - expValue string - call func() string - }{ - {imageContext{ - i: types.ImageSummary{ID: imageID}, - trunc: true, - }, stringid.TruncateID(imageID), ctx.ID}, - {imageContext{ - i: types.ImageSummary{ID: imageID}, - trunc: false, - }, imageID, ctx.ID}, - {imageContext{ - i: types.ImageSummary{Size: 10, VirtualSize: 10}, - trunc: true, - }, "10B", ctx.Size}, - {imageContext{ - i: types.ImageSummary{Created: unix}, - trunc: true, - }, time.Unix(unix, 0).String(), ctx.CreatedAt}, - // FIXME - // {imageContext{ - // i: types.ImageSummary{Created: unix}, - // trunc: true, - // }, units.HumanDuration(time.Unix(unix, 0)), createdSinceHeader, ctx.CreatedSince}, - {imageContext{ - i: types.ImageSummary{}, - repo: "busybox", - }, "busybox", ctx.Repository}, - {imageContext{ - i: types.ImageSummary{}, - tag: "latest", - }, "latest", ctx.Tag}, - {imageContext{ - i: types.ImageSummary{}, - digest: "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", - }, "sha256:d149ab53f8718e987c3a3024bb8aa0e2caadf6c0328f1d9d850b2a2a67f2819a", ctx.Digest}, - { - imageContext{ - i: types.ImageSummary{Containers: 10}, - }, "10", ctx.Containers, - }, - { - imageContext{ - i: types.ImageSummary{VirtualSize: 10000}, - }, "10kB", ctx.VirtualSize, - }, - { - imageContext{ - i: types.ImageSummary{SharedSize: 10000}, - }, "10kB", ctx.SharedSize, - }, - { - imageContext{ - i: types.ImageSummary{SharedSize: 5000, VirtualSize: 20000}, - }, "15kB", ctx.UniqueSize, - }, - } - - for _, c := range cases { - ctx = c.imageCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else { - assert.Equal(t, c.expValue, v) - } - } -} - -func TestImageContextWrite(t *testing.T) { - unixTime := time.Now().AddDate(0, 0, -1).Unix() - expectedTime := time.Unix(unixTime, 0).String() - - cases := []struct { - context ImageContext - expected string - }{ - // Errors - { - ImageContext{ - Context: Context{ - Format: "{{InvalidFunction}}", - }, - }, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - ImageContext{ - Context: Context{ - Format: "{{nil}}", - }, - }, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table Format - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table", false, false), - }, - }, - `REPOSITORY TAG IMAGE ID CREATED SIZE -image tag1 imageID1 24 hours ago 0B -image tag2 imageID2 24 hours ago 0B - imageID3 24 hours ago 0B -`, - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table {{.Repository}}", false, false), - }, - }, - "REPOSITORY\nimage\nimage\n\n", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table {{.Repository}}", false, true), - }, - Digest: true, - }, - `REPOSITORY DIGEST -image sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf -image - -`, - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table {{.Repository}}", true, false), - }, - }, - "REPOSITORY\nimage\nimage\n\n", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table {{.Digest}}", true, false), - }, - }, - "DIGEST\nsha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf\n\n\n", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table", true, false), - }, - }, - "imageID1\nimageID2\nimageID3\n", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table", false, true), - }, - Digest: true, - }, - `REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE -image tag1 sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf imageID1 24 hours ago 0B -image tag2 imageID2 24 hours ago 0B - imageID3 24 hours ago 0B -`, - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table", true, true), - }, - Digest: true, - }, - "imageID1\nimageID2\nimageID3\n", - }, - // Raw Format - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("raw", false, false), - }, - }, - fmt.Sprintf(`repository: image -tag: tag1 -image_id: imageID1 -created_at: %s -virtual_size: 0B - -repository: image -tag: tag2 -image_id: imageID2 -created_at: %s -virtual_size: 0B - -repository: -tag: -image_id: imageID3 -created_at: %s -virtual_size: 0B - -`, expectedTime, expectedTime, expectedTime), - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("raw", false, true), - }, - Digest: true, - }, - fmt.Sprintf(`repository: image -tag: tag1 -digest: sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf -image_id: imageID1 -created_at: %s -virtual_size: 0B - -repository: image -tag: tag2 -digest: -image_id: imageID2 -created_at: %s -virtual_size: 0B - -repository: -tag: -digest: -image_id: imageID3 -created_at: %s -virtual_size: 0B - -`, expectedTime, expectedTime, expectedTime), - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("raw", true, false), - }, - }, - `image_id: imageID1 -image_id: imageID2 -image_id: imageID3 -`, - }, - // Custom Format - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("{{.Repository}}", false, false), - }, - }, - "image\nimage\n\n", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("{{.Repository}}", false, true), - }, - Digest: true, - }, - "image\nimage\n\n", - }, - } - - for _, testcase := range cases { - images := []types.ImageSummary{ - {ID: "imageID1", RepoTags: []string{"image:tag1"}, RepoDigests: []string{"image@sha256:cbbf2f9a99b47fc460d422812b6a5adff7dfee951d8fa2e4a98caa0382cfbdbf"}, Created: unixTime}, - {ID: "imageID2", RepoTags: []string{"image:tag2"}, Created: unixTime}, - {ID: "imageID3", RepoTags: []string{":"}, RepoDigests: []string{"@"}, Created: unixTime}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := ImageWrite(testcase.context, images) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestImageContextWriteWithNoImage(t *testing.T) { - out := bytes.NewBufferString("") - images := []types.ImageSummary{} - - contexts := []struct { - context ImageContext - expected string - }{ - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("{{.Repository}}", false, false), - Output: out, - }, - }, - "", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table {{.Repository}}", false, false), - Output: out, - }, - }, - "REPOSITORY\n", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("{{.Repository}}", false, true), - Output: out, - }, - }, - "", - }, - { - ImageContext{ - Context: Context{ - Format: NewImageFormat("table {{.Repository}}", false, true), - Output: out, - }, - }, - "REPOSITORY DIGEST\n", - }, - } - - for _, context := range contexts { - ImageWrite(context.context, images) - assert.Equal(t, context.expected, out.String()) - // Clean buffer - out.Reset() - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/network.go b/vendor/github.com/docker/cli/cli/command/formatter/network.go deleted file mode 100644 index 4aeebd175..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/network.go +++ /dev/null @@ -1,129 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" -) - -const ( - defaultNetworkTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.Scope}}" - - networkIDHeader = "NETWORK ID" - ipv6Header = "IPV6" - internalHeader = "INTERNAL" -) - -// NewNetworkFormat returns a Format for rendering using a network Context -func NewNetworkFormat(source string, quiet bool) Format { - switch source { - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - return defaultNetworkTableFormat - case RawFormatKey: - if quiet { - return `network_id: {{.ID}}` - } - return `network_id: {{.ID}}\nname: {{.Name}}\ndriver: {{.Driver}}\nscope: {{.Scope}}\n` - } - return Format(source) -} - -// NetworkWrite writes the context -func NetworkWrite(ctx Context, networks []types.NetworkResource) error { - render := func(format func(subContext subContext) error) error { - for _, network := range networks { - networkCtx := &networkContext{trunc: ctx.Trunc, n: network} - if err := format(networkCtx); err != nil { - return err - } - } - return nil - } - networkCtx := networkContext{} - networkCtx.header = networkHeaderContext{ - "ID": networkIDHeader, - "Name": nameHeader, - "Driver": driverHeader, - "Scope": scopeHeader, - "IPv6": ipv6Header, - "Internal": internalHeader, - "Labels": labelsHeader, - "CreatedAt": createdAtHeader, - } - return ctx.Write(&networkCtx, render) -} - -type networkHeaderContext map[string]string - -func (c networkHeaderContext) Label(name string) string { - n := strings.Split(name, ".") - r := strings.NewReplacer("-", " ", "_", " ") - h := r.Replace(n[len(n)-1]) - - return h -} - -type networkContext struct { - HeaderContext - trunc bool - n types.NetworkResource -} - -func (c *networkContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *networkContext) ID() string { - if c.trunc { - return stringid.TruncateID(c.n.ID) - } - return c.n.ID -} - -func (c *networkContext) Name() string { - return c.n.Name -} - -func (c *networkContext) Driver() string { - return c.n.Driver -} - -func (c *networkContext) Scope() string { - return c.n.Scope -} - -func (c *networkContext) IPv6() string { - return fmt.Sprintf("%v", c.n.EnableIPv6) -} - -func (c *networkContext) Internal() string { - return fmt.Sprintf("%v", c.n.Internal) -} - -func (c *networkContext) Labels() string { - if c.n.Labels == nil { - return "" - } - - var joinLabels []string - for k, v := range c.n.Labels { - joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v)) - } - return strings.Join(joinLabels, ",") -} - -func (c *networkContext) Label(name string) string { - if c.n.Labels == nil { - return "" - } - return c.n.Labels[name] -} - -func (c *networkContext) CreatedAt() string { - return c.n.Created.String() -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/network_test.go b/vendor/github.com/docker/cli/cli/command/formatter/network_test.go deleted file mode 100644 index 201838cf7..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/network_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNetworkContext(t *testing.T) { - networkID := stringid.GenerateRandomID() - - var ctx networkContext - cases := []struct { - networkCtx networkContext - expValue string - call func() string - }{ - {networkContext{ - n: types.NetworkResource{ID: networkID}, - trunc: false, - }, networkID, ctx.ID}, - {networkContext{ - n: types.NetworkResource{ID: networkID}, - trunc: true, - }, stringid.TruncateID(networkID), ctx.ID}, - {networkContext{ - n: types.NetworkResource{Name: "network_name"}, - }, "network_name", ctx.Name}, - {networkContext{ - n: types.NetworkResource{Driver: "driver_name"}, - }, "driver_name", ctx.Driver}, - {networkContext{ - n: types.NetworkResource{EnableIPv6: true}, - }, "true", ctx.IPv6}, - {networkContext{ - n: types.NetworkResource{EnableIPv6: false}, - }, "false", ctx.IPv6}, - {networkContext{ - n: types.NetworkResource{Internal: true}, - }, "true", ctx.Internal}, - {networkContext{ - n: types.NetworkResource{Internal: false}, - }, "false", ctx.Internal}, - {networkContext{ - n: types.NetworkResource{}, - }, "", ctx.Labels}, - {networkContext{ - n: types.NetworkResource{Labels: map[string]string{"label1": "value1", "label2": "value2"}}, - }, "label1=value1,label2=value2", ctx.Labels}, - } - - for _, c := range cases { - ctx = c.networkCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestNetworkContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - { - Context{Format: NewNetworkFormat("table", false)}, - `NETWORK ID NAME DRIVER SCOPE -networkID1 foobar_baz foo local -networkID2 foobar_bar bar local -`, - }, - { - Context{Format: NewNetworkFormat("table", true)}, - `networkID1 -networkID2 -`, - }, - { - Context{Format: NewNetworkFormat("table {{.Name}}", false)}, - `NAME -foobar_baz -foobar_bar -`, - }, - { - Context{Format: NewNetworkFormat("table {{.Name}}", true)}, - `NAME -foobar_baz -foobar_bar -`, - }, - // Raw Format - { - Context{Format: NewNetworkFormat("raw", false)}, - `network_id: networkID1 -name: foobar_baz -driver: foo -scope: local - -network_id: networkID2 -name: foobar_bar -driver: bar -scope: local - -`, - }, - { - Context{Format: NewNetworkFormat("raw", true)}, - `network_id: networkID1 -network_id: networkID2 -`, - }, - // Custom Format - { - Context{Format: NewNetworkFormat("{{.Name}}", false)}, - `foobar_baz -foobar_bar -`, - }, - // Custom Format with CreatedAt - { - Context{Format: NewNetworkFormat("{{.Name}} {{.CreatedAt}}", false)}, - `foobar_baz 2016-01-01 00:00:00 +0000 UTC -foobar_bar 2017-01-01 00:00:00 +0000 UTC -`, - }, - } - - timestamp1, _ := time.Parse("2006-01-02", "2016-01-01") - timestamp2, _ := time.Parse("2006-01-02", "2017-01-01") - - for _, testcase := range cases { - networks := []types.NetworkResource{ - {ID: "networkID1", Name: "foobar_baz", Driver: "foo", Scope: "local", Created: timestamp1}, - {ID: "networkID2", Name: "foobar_bar", Driver: "bar", Scope: "local", Created: timestamp2}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := NetworkWrite(testcase.context, networks) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestNetworkContextWriteJSON(t *testing.T) { - networks := []types.NetworkResource{ - {ID: "networkID1", Name: "foobar_baz"}, - {ID: "networkID2", Name: "foobar_bar"}, - } - expectedJSONs := []map[string]interface{}{ - {"Driver": "", "ID": "networkID1", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_baz", "Scope": "", "CreatedAt": "0001-01-01 00:00:00 +0000 UTC"}, - {"Driver": "", "ID": "networkID2", "IPv6": "false", "Internal": "false", "Labels": "", "Name": "foobar_bar", "Scope": "", "CreatedAt": "0001-01-01 00:00:00 +0000 UTC"}, - } - - out := bytes.NewBufferString("") - err := NetworkWrite(Context{Format: "{{json .}}", Output: out}, networks) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var m map[string]interface{} - err := json.Unmarshal([]byte(line), &m) - require.NoError(t, err, msg) - assert.Equal(t, expectedJSONs[i], m, msg) - } -} - -func TestNetworkContextWriteJSONField(t *testing.T) { - networks := []types.NetworkResource{ - {ID: "networkID1", Name: "foobar_baz"}, - {ID: "networkID2", Name: "foobar_bar"}, - } - out := bytes.NewBufferString("") - err := NetworkWrite(Context{Format: "{{json .ID}}", Output: out}, networks) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var s string - err := json.Unmarshal([]byte(line), &s) - require.NoError(t, err, msg) - assert.Equal(t, networks[i].ID, s, msg) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/node.go b/vendor/github.com/docker/cli/cli/command/formatter/node.go deleted file mode 100644 index 09bcd3f9f..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/node.go +++ /dev/null @@ -1,330 +0,0 @@ -package formatter - -import ( - "encoding/base64" - "fmt" - "reflect" - "strings" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - units "github.com/docker/go-units" -) - -const ( - defaultNodeTableFormat = "table {{.ID}} {{if .Self}}*{{else}} {{ end }}\t{{.Hostname}}\t{{.Status}}\t{{.Availability}}\t{{.ManagerStatus}}" - nodeInspectPrettyTemplate Format = `ID: {{.ID}} -{{- if .Name }} -Name: {{.Name}} -{{- end }} -{{- if .Labels }} -Labels: -{{- range $k, $v := .Labels }} - - {{ $k }}{{if $v }}={{ $v }}{{ end }} -{{- end }}{{ end }} -Hostname: {{.Hostname}} -Joined at: {{.CreatedAt}} -Status: - State: {{.StatusState}} - {{- if .HasStatusMessage}} - Message: {{.StatusMessage}} - {{- end}} - Availability: {{.SpecAvailability}} - {{- if .Status.Addr}} - Address: {{.StatusAddr}} - {{- end}} -{{- if .HasManagerStatus}} -Manager Status: - Address: {{.ManagerStatusAddr}} - Raft Status: {{.ManagerStatusReachability}} - {{- if .IsManagerStatusLeader}} - Leader: Yes - {{- else}} - Leader: No - {{- end}} -{{- end}} -Platform: - Operating System: {{.PlatformOS}} - Architecture: {{.PlatformArchitecture}} -Resources: - CPUs: {{.ResourceNanoCPUs}} - Memory: {{.ResourceMemory}} -{{- if .HasEnginePlugins}} -Plugins: -{{- range $k, $v := .EnginePlugins }} - {{ $k }}:{{if $v }} {{ $v }}{{ end }} -{{- end }} -{{- end }} -Engine Version: {{.EngineVersion}} -{{- if .EngineLabels}} -Engine Labels: -{{- range $k, $v := .EngineLabels }} - - {{ $k }}{{if $v }}={{ $v }}{{ end }} -{{- end }}{{- end }} -{{- if .HasTLSInfo}} -TLS Info: - TrustRoot: -{{.TLSInfoTrustRoot}} - Issuer Subject: {{.TLSInfoCertIssuerSubject}} - Issuer Public Key: {{.TLSInfoCertIssuerPublicKey}} -{{- end}}` - nodeIDHeader = "ID" - selfHeader = "" - hostnameHeader = "HOSTNAME" - availabilityHeader = "AVAILABILITY" - managerStatusHeader = "MANAGER STATUS" - tlsStatusHeader = "TLS STATUS" -) - -// NewNodeFormat returns a Format for rendering using a node Context -func NewNodeFormat(source string, quiet bool) Format { - switch source { - case PrettyFormatKey: - return nodeInspectPrettyTemplate - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - return defaultNodeTableFormat - case RawFormatKey: - if quiet { - return `node_id: {{.ID}}` - } - return `node_id: {{.ID}}\nhostname: {{.Hostname}}\nstatus: {{.Status}}\navailability: {{.Availability}}\nmanager_status: {{.ManagerStatus}}\n` - } - return Format(source) -} - -// NodeWrite writes the context -func NodeWrite(ctx Context, nodes []swarm.Node, info types.Info) error { - render := func(format func(subContext subContext) error) error { - for _, node := range nodes { - nodeCtx := &nodeContext{n: node, info: info} - if err := format(nodeCtx); err != nil { - return err - } - } - return nil - } - header := nodeHeaderContext{ - "ID": nodeIDHeader, - "Self": selfHeader, - "Hostname": hostnameHeader, - "Status": statusHeader, - "Availability": availabilityHeader, - "ManagerStatus": managerStatusHeader, - "TLSStatus": tlsStatusHeader, - } - nodeCtx := nodeContext{} - nodeCtx.header = header - return ctx.Write(&nodeCtx, render) -} - -type nodeHeaderContext map[string]string - -type nodeContext struct { - HeaderContext - n swarm.Node - info types.Info -} - -func (c *nodeContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *nodeContext) ID() string { - return c.n.ID -} - -func (c *nodeContext) Self() bool { - return c.n.ID == c.info.Swarm.NodeID -} - -func (c *nodeContext) Hostname() string { - return c.n.Description.Hostname -} - -func (c *nodeContext) Status() string { - return command.PrettyPrint(string(c.n.Status.State)) -} - -func (c *nodeContext) Availability() string { - return command.PrettyPrint(string(c.n.Spec.Availability)) -} - -func (c *nodeContext) ManagerStatus() string { - reachability := "" - if c.n.ManagerStatus != nil { - if c.n.ManagerStatus.Leader { - reachability = "Leader" - } else { - reachability = string(c.n.ManagerStatus.Reachability) - } - } - return command.PrettyPrint(reachability) -} - -func (c *nodeContext) TLSStatus() string { - if c.info.Swarm.Cluster == nil || reflect.DeepEqual(c.info.Swarm.Cluster.TLSInfo, swarm.TLSInfo{}) || reflect.DeepEqual(c.n.Description.TLSInfo, swarm.TLSInfo{}) { - return "Unknown" - } - if reflect.DeepEqual(c.n.Description.TLSInfo, c.info.Swarm.Cluster.TLSInfo) { - return "Ready" - } - return "Needs Rotation" -} - -// NodeInspectWrite renders the context for a list of nodes -func NodeInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) error { - if ctx.Format != nodeInspectPrettyTemplate { - return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef) - } - render := func(format func(subContext subContext) error) error { - for _, ref := range refs { - nodeI, _, err := getRef(ref) - if err != nil { - return err - } - node, ok := nodeI.(swarm.Node) - if !ok { - return fmt.Errorf("got wrong object to inspect :%v", ok) - } - if err := format(&nodeInspectContext{Node: node}); err != nil { - return err - } - } - return nil - } - return ctx.Write(&nodeInspectContext{}, render) -} - -type nodeInspectContext struct { - swarm.Node - subContext -} - -func (ctx *nodeInspectContext) ID() string { - return ctx.Node.ID -} - -func (ctx *nodeInspectContext) Name() string { - return ctx.Node.Spec.Name -} - -func (ctx *nodeInspectContext) Labels() map[string]string { - return ctx.Node.Spec.Labels -} - -func (ctx *nodeInspectContext) Hostname() string { - return ctx.Node.Description.Hostname -} - -func (ctx *nodeInspectContext) CreatedAt() string { - return command.PrettyPrint(ctx.Node.CreatedAt) -} - -func (ctx *nodeInspectContext) StatusState() string { - return command.PrettyPrint(ctx.Node.Status.State) -} - -func (ctx *nodeInspectContext) HasStatusMessage() bool { - return ctx.Node.Status.Message != "" -} - -func (ctx *nodeInspectContext) StatusMessage() string { - return command.PrettyPrint(ctx.Node.Status.Message) -} - -func (ctx *nodeInspectContext) SpecAvailability() string { - return command.PrettyPrint(ctx.Node.Spec.Availability) -} - -func (ctx *nodeInspectContext) HasStatusAddr() bool { - return ctx.Node.Status.Addr != "" -} - -func (ctx *nodeInspectContext) StatusAddr() string { - return ctx.Node.Status.Addr -} - -func (ctx *nodeInspectContext) HasManagerStatus() bool { - return ctx.Node.ManagerStatus != nil -} - -func (ctx *nodeInspectContext) ManagerStatusAddr() string { - return ctx.Node.ManagerStatus.Addr -} - -func (ctx *nodeInspectContext) ManagerStatusReachability() string { - return command.PrettyPrint(ctx.Node.ManagerStatus.Reachability) -} - -func (ctx *nodeInspectContext) IsManagerStatusLeader() bool { - return ctx.Node.ManagerStatus.Leader -} - -func (ctx *nodeInspectContext) PlatformOS() string { - return ctx.Node.Description.Platform.OS -} - -func (ctx *nodeInspectContext) PlatformArchitecture() string { - return ctx.Node.Description.Platform.Architecture -} - -func (ctx *nodeInspectContext) ResourceNanoCPUs() int { - if ctx.Node.Description.Resources.NanoCPUs == 0 { - return int(0) - } - return int(ctx.Node.Description.Resources.NanoCPUs) / 1e9 -} - -func (ctx *nodeInspectContext) ResourceMemory() string { - if ctx.Node.Description.Resources.MemoryBytes == 0 { - return "" - } - return units.BytesSize(float64(ctx.Node.Description.Resources.MemoryBytes)) -} - -func (ctx *nodeInspectContext) HasEnginePlugins() bool { - return len(ctx.Node.Description.Engine.Plugins) > 0 -} - -func (ctx *nodeInspectContext) EnginePlugins() map[string]string { - pluginMap := map[string][]string{} - for _, p := range ctx.Node.Description.Engine.Plugins { - pluginMap[p.Type] = append(pluginMap[p.Type], p.Name) - } - - pluginNamesByType := map[string]string{} - for k, v := range pluginMap { - pluginNamesByType[k] = strings.Join(v, ", ") - } - return pluginNamesByType -} - -func (ctx *nodeInspectContext) EngineLabels() map[string]string { - return ctx.Node.Description.Engine.Labels -} - -func (ctx *nodeInspectContext) EngineVersion() string { - return ctx.Node.Description.Engine.EngineVersion -} - -func (ctx *nodeInspectContext) HasTLSInfo() bool { - tlsInfo := ctx.Node.Description.TLSInfo - return !reflect.DeepEqual(tlsInfo, swarm.TLSInfo{}) -} - -func (ctx *nodeInspectContext) TLSInfoTrustRoot() string { - return ctx.Node.Description.TLSInfo.TrustRoot -} - -func (ctx *nodeInspectContext) TLSInfoCertIssuerPublicKey() string { - return base64.StdEncoding.EncodeToString(ctx.Node.Description.TLSInfo.CertIssuerPublicKey) -} - -func (ctx *nodeInspectContext) TLSInfoCertIssuerSubject() string { - return base64.StdEncoding.EncodeToString(ctx.Node.Description.TLSInfo.CertIssuerSubject) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/node_test.go b/vendor/github.com/docker/cli/cli/command/formatter/node_test.go deleted file mode 100644 index 42fdf5138..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/node_test.go +++ /dev/null @@ -1,346 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/stringid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNodeContext(t *testing.T) { - nodeID := stringid.GenerateRandomID() - - var ctx nodeContext - cases := []struct { - nodeCtx nodeContext - expValue string - call func() string - }{ - {nodeContext{ - n: swarm.Node{ID: nodeID}, - }, nodeID, ctx.ID}, - {nodeContext{ - n: swarm.Node{Description: swarm.NodeDescription{Hostname: "node_hostname"}}, - }, "node_hostname", ctx.Hostname}, - {nodeContext{ - n: swarm.Node{Status: swarm.NodeStatus{State: swarm.NodeState("foo")}}, - }, "Foo", ctx.Status}, - {nodeContext{ - n: swarm.Node{Spec: swarm.NodeSpec{Availability: swarm.NodeAvailability("drain")}}, - }, "Drain", ctx.Availability}, - {nodeContext{ - n: swarm.Node{ManagerStatus: &swarm.ManagerStatus{Leader: true}}, - }, "Leader", ctx.ManagerStatus}, - } - - for _, c := range cases { - ctx = c.nodeCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestNodeContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - clusterInfo swarm.ClusterInfo - }{ - - // Errors - { - context: Context{Format: "{{InvalidFunction}}"}, - expected: `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - { - context: Context{Format: "{{nil}}"}, - expected: `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - // Table format - { - context: Context{Format: NewNodeFormat("table", false)}, - expected: `ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS -nodeID1 foobar_baz Foo Drain Leader -nodeID2 foobar_bar Bar Active Reachable -nodeID3 foobar_boo Boo Active ` + "\n", // (to preserve whitespace) - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - { - context: Context{Format: NewNodeFormat("table", true)}, - expected: `nodeID1 -nodeID2 -nodeID3 -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - { - context: Context{Format: NewNodeFormat("table {{.Hostname}}", false)}, - expected: `HOSTNAME -foobar_baz -foobar_bar -foobar_boo -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - { - context: Context{Format: NewNodeFormat("table {{.Hostname}}", true)}, - expected: `HOSTNAME -foobar_baz -foobar_bar -foobar_boo -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - { - context: Context{Format: NewNodeFormat("table {{.ID}}\t{{.Hostname}}\t{{.TLSStatus}}", false)}, - expected: `ID HOSTNAME TLS STATUS -nodeID1 foobar_baz Needs Rotation -nodeID2 foobar_bar Ready -nodeID3 foobar_boo Unknown -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - { // no cluster TLS status info, TLS status for all nodes is unknown - context: Context{Format: NewNodeFormat("table {{.ID}}\t{{.Hostname}}\t{{.TLSStatus}}", false)}, - expected: `ID HOSTNAME TLS STATUS -nodeID1 foobar_baz Unknown -nodeID2 foobar_bar Unknown -nodeID3 foobar_boo Unknown -`, - clusterInfo: swarm.ClusterInfo{}, - }, - // Raw Format - { - context: Context{Format: NewNodeFormat("raw", false)}, - expected: `node_id: nodeID1 -hostname: foobar_baz -status: Foo -availability: Drain -manager_status: Leader - -node_id: nodeID2 -hostname: foobar_bar -status: Bar -availability: Active -manager_status: Reachable - -node_id: nodeID3 -hostname: foobar_boo -status: Boo -availability: Active -manager_status: ` + "\n\n", // to preserve whitespace - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - { - context: Context{Format: NewNodeFormat("raw", true)}, - expected: `node_id: nodeID1 -node_id: nodeID2 -node_id: nodeID3 -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - // Custom Format - { - context: Context{Format: NewNodeFormat("{{.Hostname}} {{.TLSStatus}}", false)}, - expected: `foobar_baz Needs Rotation -foobar_bar Ready -foobar_boo Unknown -`, - clusterInfo: swarm.ClusterInfo{TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}, - }, - } - - for _, testcase := range cases { - nodes := []swarm.Node{ - { - ID: "nodeID1", - Description: swarm.NodeDescription{ - Hostname: "foobar_baz", - TLSInfo: swarm.TLSInfo{TrustRoot: "no"}, - }, - Status: swarm.NodeStatus{State: swarm.NodeState("foo")}, - Spec: swarm.NodeSpec{Availability: swarm.NodeAvailability("drain")}, - ManagerStatus: &swarm.ManagerStatus{Leader: true}, - }, - { - ID: "nodeID2", - Description: swarm.NodeDescription{ - Hostname: "foobar_bar", - TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}, - }, - Status: swarm.NodeStatus{State: swarm.NodeState("bar")}, - Spec: swarm.NodeSpec{Availability: swarm.NodeAvailability("active")}, - ManagerStatus: &swarm.ManagerStatus{ - Leader: false, - Reachability: swarm.Reachability("Reachable"), - }, - }, - { - ID: "nodeID3", - Description: swarm.NodeDescription{Hostname: "foobar_boo"}, - Status: swarm.NodeStatus{State: swarm.NodeState("boo")}, - Spec: swarm.NodeSpec{Availability: swarm.NodeAvailability("active")}, - }, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := NodeWrite(testcase.context, nodes, types.Info{Swarm: swarm.Info{Cluster: &testcase.clusterInfo}}) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestNodeContextWriteJSON(t *testing.T) { - cases := []struct { - expected []map[string]interface{} - info types.Info - }{ - { - expected: []map[string]interface{}{ - {"Availability": "", "Hostname": "foobar_baz", "ID": "nodeID1", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"}, - {"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"}, - {"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"}, - }, - info: types.Info{}, - }, - { - expected: []map[string]interface{}{ - {"Availability": "", "Hostname": "foobar_baz", "ID": "nodeID1", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Ready"}, - {"Availability": "", "Hostname": "foobar_bar", "ID": "nodeID2", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Needs Rotation"}, - {"Availability": "", "Hostname": "foobar_boo", "ID": "nodeID3", "ManagerStatus": "", "Status": "", "Self": false, "TLSStatus": "Unknown"}, - }, - info: types.Info{ - Swarm: swarm.Info{ - Cluster: &swarm.ClusterInfo{ - TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}, - RootRotationInProgress: true, - }, - }, - }, - }, - } - - for _, testcase := range cases { - nodes := []swarm.Node{ - {ID: "nodeID1", Description: swarm.NodeDescription{Hostname: "foobar_baz", TLSInfo: swarm.TLSInfo{TrustRoot: "hi"}}}, - {ID: "nodeID2", Description: swarm.NodeDescription{Hostname: "foobar_bar", TLSInfo: swarm.TLSInfo{TrustRoot: "no"}}}, - {ID: "nodeID3", Description: swarm.NodeDescription{Hostname: "foobar_boo"}}, - } - out := bytes.NewBufferString("") - err := NodeWrite(Context{Format: "{{json .}}", Output: out}, nodes, testcase.info) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var m map[string]interface{} - err := json.Unmarshal([]byte(line), &m) - require.NoError(t, err, msg) - assert.Equal(t, testcase.expected[i], m, msg) - } - } -} - -func TestNodeContextWriteJSONField(t *testing.T) { - nodes := []swarm.Node{ - {ID: "nodeID1", Description: swarm.NodeDescription{Hostname: "foobar_baz"}}, - {ID: "nodeID2", Description: swarm.NodeDescription{Hostname: "foobar_bar"}}, - } - out := bytes.NewBufferString("") - err := NodeWrite(Context{Format: "{{json .ID}}", Output: out}, nodes, types.Info{}) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var s string - err := json.Unmarshal([]byte(line), &s) - require.NoError(t, err, msg) - assert.Equal(t, nodes[i].ID, s, msg) - } -} - -func TestNodeInspectWriteContext(t *testing.T) { - node := swarm.Node{ - ID: "nodeID1", - Description: swarm.NodeDescription{ - Hostname: "foobar_baz", - TLSInfo: swarm.TLSInfo{ - TrustRoot: "-----BEGIN CERTIFICATE-----\ndata\n-----END CERTIFICATE-----\n", - CertIssuerPublicKey: []byte("pubKey"), - CertIssuerSubject: []byte("subject"), - }, - Platform: swarm.Platform{ - OS: "linux", - Architecture: "amd64", - }, - Resources: swarm.Resources{ - MemoryBytes: 1, - }, - Engine: swarm.EngineDescription{ - EngineVersion: "0.1.1", - }, - }, - Status: swarm.NodeStatus{ - State: swarm.NodeState("ready"), - Addr: "1.1.1.1", - }, - Spec: swarm.NodeSpec{ - Availability: swarm.NodeAvailability("drain"), - Role: swarm.NodeRole("manager"), - }, - } - out := bytes.NewBufferString("") - context := Context{ - Format: NewNodeFormat("pretty", false), - Output: out, - } - err := NodeInspectWrite(context, []string{"nodeID1"}, func(string) (interface{}, []byte, error) { - return node, nil, nil - }) - if err != nil { - t.Fatal(err) - } - expected := `ID: nodeID1 -Hostname: foobar_baz -Joined at: 0001-01-01 00:00:00 +0000 utc -Status: - State: Ready - Availability: Drain - Address: 1.1.1.1 -Platform: - Operating System: linux - Architecture: amd64 -Resources: - CPUs: 0 - Memory: 1B -Engine Version: 0.1.1 -TLS Info: - TrustRoot: ------BEGIN CERTIFICATE----- -data ------END CERTIFICATE----- - - Issuer Subject: c3ViamVjdA== - Issuer Public Key: cHViS2V5 -` - assert.Equal(t, expected, out.String()) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/plugin.go b/vendor/github.com/docker/cli/cli/command/formatter/plugin.go deleted file mode 100644 index 2b71281a5..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/plugin.go +++ /dev/null @@ -1,95 +0,0 @@ -package formatter - -import ( - "strings" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/stringutils" -) - -const ( - defaultPluginTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Description}}\t{{.Enabled}}" - - pluginIDHeader = "ID" - descriptionHeader = "DESCRIPTION" - enabledHeader = "ENABLED" -) - -// NewPluginFormat returns a Format for rendering using a plugin Context -func NewPluginFormat(source string, quiet bool) Format { - switch source { - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - return defaultPluginTableFormat - case RawFormatKey: - if quiet { - return `plugin_id: {{.ID}}` - } - return `plugin_id: {{.ID}}\nname: {{.Name}}\ndescription: {{.Description}}\nenabled: {{.Enabled}}\n` - } - return Format(source) -} - -// PluginWrite writes the context -func PluginWrite(ctx Context, plugins []*types.Plugin) error { - render := func(format func(subContext subContext) error) error { - for _, plugin := range plugins { - pluginCtx := &pluginContext{trunc: ctx.Trunc, p: *plugin} - if err := format(pluginCtx); err != nil { - return err - } - } - return nil - } - pluginCtx := pluginContext{} - pluginCtx.header = map[string]string{ - "ID": pluginIDHeader, - "Name": nameHeader, - "Description": descriptionHeader, - "Enabled": enabledHeader, - "PluginReference": imageHeader, - } - return ctx.Write(&pluginCtx, render) -} - -type pluginContext struct { - HeaderContext - trunc bool - p types.Plugin -} - -func (c *pluginContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *pluginContext) ID() string { - if c.trunc { - return stringid.TruncateID(c.p.ID) - } - return c.p.ID -} - -func (c *pluginContext) Name() string { - return c.p.Name -} - -func (c *pluginContext) Description() string { - desc := strings.Replace(c.p.Config.Description, "\n", "", -1) - desc = strings.Replace(desc, "\r", "", -1) - if c.trunc { - desc = stringutils.Ellipsis(desc, 45) - } - - return desc -} - -func (c *pluginContext) Enabled() bool { - return c.p.Enabled -} - -func (c *pluginContext) PluginReference() string { - return c.p.PluginReference -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/plugin_test.go b/vendor/github.com/docker/cli/cli/command/formatter/plugin_test.go deleted file mode 100644 index 607262dcc..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/plugin_test.go +++ /dev/null @@ -1,182 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "strings" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/stretchr/testify/assert" -) - -func TestPluginContext(t *testing.T) { - pluginID := stringid.GenerateRandomID() - - var ctx pluginContext - cases := []struct { - pluginCtx pluginContext - expValue string - call func() string - }{ - {pluginContext{ - p: types.Plugin{ID: pluginID}, - trunc: false, - }, pluginID, ctx.ID}, - {pluginContext{ - p: types.Plugin{ID: pluginID}, - trunc: true, - }, stringid.TruncateID(pluginID), ctx.ID}, - {pluginContext{ - p: types.Plugin{Name: "plugin_name"}, - }, "plugin_name", ctx.Name}, - {pluginContext{ - p: types.Plugin{Config: types.PluginConfig{Description: "plugin_description"}}, - }, "plugin_description", ctx.Description}, - } - - for _, c := range cases { - ctx = c.pluginCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestPluginContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - { - Context{Format: NewPluginFormat("table", false)}, - `ID NAME DESCRIPTION ENABLED -pluginID1 foobar_baz description 1 true -pluginID2 foobar_bar description 2 false -`, - }, - { - Context{Format: NewPluginFormat("table", true)}, - `pluginID1 -pluginID2 -`, - }, - { - Context{Format: NewPluginFormat("table {{.Name}}", false)}, - `NAME -foobar_baz -foobar_bar -`, - }, - { - Context{Format: NewPluginFormat("table {{.Name}}", true)}, - `NAME -foobar_baz -foobar_bar -`, - }, - // Raw Format - { - Context{Format: NewPluginFormat("raw", false)}, - `plugin_id: pluginID1 -name: foobar_baz -description: description 1 -enabled: true - -plugin_id: pluginID2 -name: foobar_bar -description: description 2 -enabled: false - -`, - }, - { - Context{Format: NewPluginFormat("raw", true)}, - `plugin_id: pluginID1 -plugin_id: pluginID2 -`, - }, - // Custom Format - { - Context{Format: NewPluginFormat("{{.Name}}", false)}, - `foobar_baz -foobar_bar -`, - }, - } - - for _, testcase := range cases { - plugins := []*types.Plugin{ - {ID: "pluginID1", Name: "foobar_baz", Config: types.PluginConfig{Description: "description 1"}, Enabled: true}, - {ID: "pluginID2", Name: "foobar_bar", Config: types.PluginConfig{Description: "description 2"}, Enabled: false}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := PluginWrite(testcase.context, plugins) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestPluginContextWriteJSON(t *testing.T) { - plugins := []*types.Plugin{ - {ID: "pluginID1", Name: "foobar_baz"}, - {ID: "pluginID2", Name: "foobar_bar"}, - } - expectedJSONs := []map[string]interface{}{ - {"Description": "", "Enabled": false, "ID": "pluginID1", "Name": "foobar_baz", "PluginReference": ""}, - {"Description": "", "Enabled": false, "ID": "pluginID2", "Name": "foobar_bar", "PluginReference": ""}, - } - - out := bytes.NewBufferString("") - err := PluginWrite(Context{Format: "{{json .}}", Output: out}, plugins) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - var m map[string]interface{} - if err := json.Unmarshal([]byte(line), &m); err != nil { - t.Fatal(err) - } - assert.Equal(t, expectedJSONs[i], m) - } -} - -func TestPluginContextWriteJSONField(t *testing.T) { - plugins := []*types.Plugin{ - {ID: "pluginID1", Name: "foobar_baz"}, - {ID: "pluginID2", Name: "foobar_bar"}, - } - out := bytes.NewBufferString("") - err := PluginWrite(Context{Format: "{{json .ID}}", Output: out}, plugins) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - var s string - if err := json.Unmarshal([]byte(line), &s); err != nil { - t.Fatal(err) - } - assert.Equal(t, plugins[i].ID, s) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/reflect.go b/vendor/github.com/docker/cli/cli/command/formatter/reflect.go deleted file mode 100644 index fd59404d0..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/reflect.go +++ /dev/null @@ -1,66 +0,0 @@ -package formatter - -import ( - "encoding/json" - "reflect" - "unicode" - - "github.com/pkg/errors" -) - -func marshalJSON(x interface{}) ([]byte, error) { - m, err := marshalMap(x) - if err != nil { - return nil, err - } - return json.Marshal(m) -} - -// marshalMap marshals x to map[string]interface{} -func marshalMap(x interface{}) (map[string]interface{}, error) { - val := reflect.ValueOf(x) - if val.Kind() != reflect.Ptr { - return nil, errors.Errorf("expected a pointer to a struct, got %v", val.Kind()) - } - if val.IsNil() { - return nil, errors.Errorf("expected a pointer to a struct, got nil pointer") - } - valElem := val.Elem() - if valElem.Kind() != reflect.Struct { - return nil, errors.Errorf("expected a pointer to a struct, got a pointer to %v", valElem.Kind()) - } - typ := val.Type() - m := make(map[string]interface{}) - for i := 0; i < val.NumMethod(); i++ { - k, v, err := marshalForMethod(typ.Method(i), val.Method(i)) - if err != nil { - return nil, err - } - if k != "" { - m[k] = v - } - } - return m, nil -} - -var unmarshallableNames = map[string]struct{}{"FullHeader": {}} - -// marshalForMethod returns the map key and the map value for marshalling the method. -// It returns ("", nil, nil) for valid but non-marshallable parameter. (e.g. "unexportedFunc()") -func marshalForMethod(typ reflect.Method, val reflect.Value) (string, interface{}, error) { - if val.Kind() != reflect.Func { - return "", nil, errors.Errorf("expected func, got %v", val.Kind()) - } - name, numIn, numOut := typ.Name, val.Type().NumIn(), val.Type().NumOut() - _, blackListed := unmarshallableNames[name] - // FIXME: In text/template, (numOut == 2) is marshallable, - // if the type of the second param is error. - marshallable := unicode.IsUpper(rune(name[0])) && !blackListed && - numIn == 0 && numOut == 1 - if !marshallable { - return "", nil, nil - } - result := val.Call(make([]reflect.Value, numIn)) - intf := result[0].Interface() - return name, intf, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/reflect_test.go b/vendor/github.com/docker/cli/cli/command/formatter/reflect_test.go deleted file mode 100644 index ffda51b85..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/reflect_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package formatter - -import ( - "reflect" - "testing" -) - -type dummy struct { -} - -func (d *dummy) Func1() string { - return "Func1" -} - -func (d *dummy) func2() string { // nolint: unused - return "func2(should not be marshalled)" -} - -func (d *dummy) Func3() (string, int) { - return "Func3(should not be marshalled)", -42 -} - -func (d *dummy) Func4() int { - return 4 -} - -type dummyType string - -func (d *dummy) Func5() dummyType { - return dummyType("Func5") -} - -func (d *dummy) FullHeader() string { - return "FullHeader(should not be marshalled)" -} - -var dummyExpected = map[string]interface{}{ - "Func1": "Func1", - "Func4": 4, - "Func5": dummyType("Func5"), -} - -func TestMarshalMap(t *testing.T) { - d := dummy{} - m, err := marshalMap(&d) - if err != nil { - t.Fatal(err) - } - if !reflect.DeepEqual(dummyExpected, m) { - t.Fatalf("expected %+v, got %+v", - dummyExpected, m) - } -} - -func TestMarshalMapBad(t *testing.T) { - if _, err := marshalMap(nil); err == nil { - t.Fatal("expected an error (argument is nil)") - } - if _, err := marshalMap(dummy{}); err == nil { - t.Fatal("expected an error (argument is non-pointer)") - } - x := 42 - if _, err := marshalMap(&x); err == nil { - t.Fatal("expected an error (argument is a pointer to non-struct)") - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/search.go b/vendor/github.com/docker/cli/cli/command/formatter/search.go deleted file mode 100644 index c19318a83..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/search.go +++ /dev/null @@ -1,104 +0,0 @@ -package formatter - -import ( - "strconv" - "strings" - - registry "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/pkg/stringutils" -) - -const ( - defaultSearchTableFormat = "table {{.Name}}\t{{.Description}}\t{{.StarCount}}\t{{.IsOfficial}}\t{{.IsAutomated}}" - - starsHeader = "STARS" - officialHeader = "OFFICIAL" - automatedHeader = "AUTOMATED" -) - -// NewSearchFormat returns a Format for rendering using a network Context -func NewSearchFormat(source string) Format { - switch source { - case "": - return defaultSearchTableFormat - case TableFormatKey: - return defaultSearchTableFormat - } - return Format(source) -} - -// SearchWrite writes the context -func SearchWrite(ctx Context, results []registry.SearchResult, auto bool, stars int) error { - render := func(format func(subContext subContext) error) error { - for _, result := range results { - // --automated and -s, --stars are deprecated since Docker 1.12 - if (auto && !result.IsAutomated) || (stars > result.StarCount) { - continue - } - searchCtx := &searchContext{trunc: ctx.Trunc, s: result} - if err := format(searchCtx); err != nil { - return err - } - } - return nil - } - searchCtx := searchContext{} - searchCtx.header = map[string]string{ - "Name": nameHeader, - "Description": descriptionHeader, - "StarCount": starsHeader, - "IsOfficial": officialHeader, - "IsAutomated": automatedHeader, - } - return ctx.Write(&searchCtx, render) -} - -type searchContext struct { - HeaderContext - trunc bool - json bool - s registry.SearchResult -} - -func (c *searchContext) MarshalJSON() ([]byte, error) { - c.json = true - return marshalJSON(c) -} - -func (c *searchContext) Name() string { - return c.s.Name -} - -func (c *searchContext) Description() string { - desc := strings.Replace(c.s.Description, "\n", " ", -1) - desc = strings.Replace(desc, "\r", " ", -1) - if c.trunc { - desc = stringutils.Ellipsis(desc, 45) - } - return desc -} - -func (c *searchContext) StarCount() string { - return strconv.Itoa(c.s.StarCount) -} - -func (c *searchContext) formatBool(value bool) string { - switch { - case value && c.json: - return "true" - case value: - return "[OK]" - case c.json: - return "false" - default: - return "" - } -} - -func (c *searchContext) IsOfficial() string { - return c.formatBool(c.s.IsOfficial) -} - -func (c *searchContext) IsAutomated() string { - return c.formatBool(c.s.IsAutomated) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/search_test.go b/vendor/github.com/docker/cli/cli/command/formatter/search_test.go deleted file mode 100644 index 80273a522..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/search_test.go +++ /dev/null @@ -1,280 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "strings" - "testing" - - registrytypes "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/pkg/stringutils" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestSearchContext(t *testing.T) { - name := "nginx" - starCount := 5000 - - var ctx searchContext - cases := []struct { - searchCtx searchContext - expValue string - call func() string - }{ - {searchContext{ - s: registrytypes.SearchResult{Name: name}, - }, name, ctx.Name}, - {searchContext{ - s: registrytypes.SearchResult{StarCount: starCount}, - }, "5000", ctx.StarCount}, - {searchContext{ - s: registrytypes.SearchResult{IsOfficial: true}, - }, "[OK]", ctx.IsOfficial}, - {searchContext{ - s: registrytypes.SearchResult{IsOfficial: false}, - }, "", ctx.IsOfficial}, - {searchContext{ - s: registrytypes.SearchResult{IsAutomated: true}, - }, "[OK]", ctx.IsAutomated}, - {searchContext{ - s: registrytypes.SearchResult{IsAutomated: false}, - }, "", ctx.IsAutomated}, - } - - for _, c := range cases { - ctx = c.searchCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestSearchContextDescription(t *testing.T) { - shortDescription := "Official build of Nginx." - longDescription := "Automated Nginx reverse proxy for docker containers" - descriptionWReturns := "Automated\nNginx reverse\rproxy\rfor docker\ncontainers" - - var ctx searchContext - cases := []struct { - searchCtx searchContext - expValue string - call func() string - }{ - {searchContext{ - s: registrytypes.SearchResult{Description: shortDescription}, - trunc: true, - }, shortDescription, ctx.Description}, - {searchContext{ - s: registrytypes.SearchResult{Description: shortDescription}, - trunc: false, - }, shortDescription, ctx.Description}, - {searchContext{ - s: registrytypes.SearchResult{Description: longDescription}, - trunc: false, - }, longDescription, ctx.Description}, - {searchContext{ - s: registrytypes.SearchResult{Description: longDescription}, - trunc: true, - }, stringutils.Ellipsis(longDescription, 45), ctx.Description}, - {searchContext{ - s: registrytypes.SearchResult{Description: descriptionWReturns}, - trunc: false, - }, longDescription, ctx.Description}, - {searchContext{ - s: registrytypes.SearchResult{Description: descriptionWReturns}, - trunc: true, - }, stringutils.Ellipsis(longDescription, 45), ctx.Description}, - } - - for _, c := range cases { - ctx = c.searchCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestSearchContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - { - Context{Format: NewSearchFormat("table")}, - string(golden.Get(t, "search-context-write-table.golden")), - }, - { - Context{Format: NewSearchFormat("table {{.Name}}")}, - `NAME -result1 -result2 -`, - }, - // Custom Format - { - Context{Format: NewSearchFormat("{{.Name}}")}, - `result1 -result2 -`, - }, - // Custom Format with CreatedAt - { - Context{Format: NewSearchFormat("{{.Name}} {{.StarCount}}")}, - `result1 5000 -result2 5 -`, - }, - } - - for _, testcase := range cases { - results := []registrytypes.SearchResult{ - {Name: "result1", Description: "Official build", StarCount: 5000, IsOfficial: true, IsAutomated: false}, - {Name: "result2", Description: "Not official", StarCount: 5, IsOfficial: false, IsAutomated: true}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := SearchWrite(testcase.context, results, false, 0) - if err != nil { - assert.Error(t, err, testcase.expected) - } else { - assert.Equal(t, out.String(), testcase.expected) - } - } -} - -func TestSearchContextWriteAutomated(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - - // Table format - { - Context{Format: NewSearchFormat("table")}, - `NAME DESCRIPTION STARS OFFICIAL AUTOMATED -result2 Not official 5 [OK] -`, - }, - { - Context{Format: NewSearchFormat("table {{.Name}}")}, - `NAME -result2 -`, - }, - } - - for _, testcase := range cases { - results := []registrytypes.SearchResult{ - {Name: "result1", Description: "Official build", StarCount: 5000, IsOfficial: true, IsAutomated: false}, - {Name: "result2", Description: "Not official", StarCount: 5, IsOfficial: false, IsAutomated: true}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := SearchWrite(testcase.context, results, true, 0) - if err != nil { - assert.Error(t, err, testcase.expected) - } else { - assert.Equal(t, out.String(), testcase.expected) - } - } -} - -func TestSearchContextWriteStars(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - - // Table format - { - Context{Format: NewSearchFormat("table")}, - string(golden.Get(t, "search-context-write-stars-table.golden")), - }, - { - Context{Format: NewSearchFormat("table {{.Name}}")}, - `NAME -result1 -`, - }, - } - - for _, testcase := range cases { - results := []registrytypes.SearchResult{ - {Name: "result1", Description: "Official build", StarCount: 5000, IsOfficial: true, IsAutomated: false}, - {Name: "result2", Description: "Not official", StarCount: 5, IsOfficial: false, IsAutomated: true}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := SearchWrite(testcase.context, results, false, 6) - if err != nil { - assert.Error(t, err, testcase.expected) - } else { - assert.Equal(t, out.String(), testcase.expected) - } - } -} - -func TestSearchContextWriteJSON(t *testing.T) { - results := []registrytypes.SearchResult{ - {Name: "result1", Description: "Official build", StarCount: 5000, IsOfficial: true, IsAutomated: false}, - {Name: "result2", Description: "Not official", StarCount: 5, IsOfficial: false, IsAutomated: true}, - } - expectedJSONs := []map[string]interface{}{ - {"Name": "result1", "Description": "Official build", "StarCount": "5000", "IsOfficial": "true", "IsAutomated": "false"}, - {"Name": "result2", "Description": "Not official", "StarCount": "5", "IsOfficial": "false", "IsAutomated": "true"}, - } - - out := bytes.NewBufferString("") - err := SearchWrite(Context{Format: "{{json .}}", Output: out}, results, false, 0) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - t.Logf("Output: line %d: %s", i, line) - var m map[string]interface{} - if err := json.Unmarshal([]byte(line), &m); err != nil { - t.Fatal(err) - } - assert.Equal(t, m, expectedJSONs[i]) - } -} - -func TestSearchContextWriteJSONField(t *testing.T) { - results := []registrytypes.SearchResult{ - {Name: "result1", Description: "Official build", StarCount: 5000, IsOfficial: true, IsAutomated: false}, - {Name: "result2", Description: "Not official", StarCount: 5, IsOfficial: false, IsAutomated: true}, - } - out := bytes.NewBufferString("") - err := SearchWrite(Context{Format: "{{json .Name}}", Output: out}, results, false, 0) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - t.Logf("Output: line %d: %s", i, line) - var s string - if err := json.Unmarshal([]byte(line), &s); err != nil { - t.Fatal(err) - } - assert.Equal(t, s, results[i].Name) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/secret.go b/vendor/github.com/docker/cli/cli/command/formatter/secret.go deleted file mode 100644 index d025cd8f3..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/secret.go +++ /dev/null @@ -1,178 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - "time" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/docker/docker/api/types/swarm" - units "github.com/docker/go-units" -) - -const ( - defaultSecretTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}" - secretIDHeader = "ID" - secretCreatedHeader = "CREATED" - secretUpdatedHeader = "UPDATED" - secretInspectPrettyTemplate Format = `ID: {{.ID}} -Name: {{.Name}} -{{- if .Labels }} -Labels: -{{- range $k, $v := .Labels }} - - {{ $k }}{{if $v }}={{ $v }}{{ end }} -{{- end }}{{ end }} -Driver: {{.Driver}} -Created at: {{.CreatedAt}} -Updated at: {{.UpdatedAt}}` -) - -// NewSecretFormat returns a Format for rendering using a secret Context -func NewSecretFormat(source string, quiet bool) Format { - switch source { - case PrettyFormatKey: - return secretInspectPrettyTemplate - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - return defaultSecretTableFormat - } - return Format(source) -} - -// SecretWrite writes the context -func SecretWrite(ctx Context, secrets []swarm.Secret) error { - render := func(format func(subContext subContext) error) error { - for _, secret := range secrets { - secretCtx := &secretContext{s: secret} - if err := format(secretCtx); err != nil { - return err - } - } - return nil - } - return ctx.Write(newSecretContext(), render) -} - -func newSecretContext() *secretContext { - sCtx := &secretContext{} - - sCtx.header = map[string]string{ - "ID": secretIDHeader, - "Name": nameHeader, - "Driver": driverHeader, - "CreatedAt": secretCreatedHeader, - "UpdatedAt": secretUpdatedHeader, - "Labels": labelsHeader, - } - return sCtx -} - -type secretContext struct { - HeaderContext - s swarm.Secret -} - -func (c *secretContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *secretContext) ID() string { - return c.s.ID -} - -func (c *secretContext) Name() string { - return c.s.Spec.Annotations.Name -} - -func (c *secretContext) CreatedAt() string { - return units.HumanDuration(time.Now().UTC().Sub(c.s.Meta.CreatedAt)) + " ago" -} - -func (c *secretContext) Driver() string { - if c.s.Spec.Driver == nil { - return "" - } - return c.s.Spec.Driver.Name -} - -func (c *secretContext) UpdatedAt() string { - return units.HumanDuration(time.Now().UTC().Sub(c.s.Meta.UpdatedAt)) + " ago" -} - -func (c *secretContext) Labels() string { - mapLabels := c.s.Spec.Annotations.Labels - if mapLabels == nil { - return "" - } - var joinLabels []string - for k, v := range mapLabels { - joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v)) - } - return strings.Join(joinLabels, ",") -} - -func (c *secretContext) Label(name string) string { - if c.s.Spec.Annotations.Labels == nil { - return "" - } - return c.s.Spec.Annotations.Labels[name] -} - -// SecretInspectWrite renders the context for a list of secrets -func SecretInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) error { - if ctx.Format != secretInspectPrettyTemplate { - return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef) - } - render := func(format func(subContext subContext) error) error { - for _, ref := range refs { - secretI, _, err := getRef(ref) - if err != nil { - return err - } - secret, ok := secretI.(swarm.Secret) - if !ok { - return fmt.Errorf("got wrong object to inspect :%v", ok) - } - if err := format(&secretInspectContext{Secret: secret}); err != nil { - return err - } - } - return nil - } - return ctx.Write(&secretInspectContext{}, render) -} - -type secretInspectContext struct { - swarm.Secret - subContext -} - -func (ctx *secretInspectContext) ID() string { - return ctx.Secret.ID -} - -func (ctx *secretInspectContext) Name() string { - return ctx.Secret.Spec.Name -} - -func (ctx *secretInspectContext) Labels() map[string]string { - return ctx.Secret.Spec.Labels -} - -func (ctx *secretInspectContext) Driver() string { - if ctx.Secret.Spec.Driver == nil { - return "" - } - return ctx.Secret.Spec.Driver.Name -} - -func (ctx *secretInspectContext) CreatedAt() string { - return command.PrettyPrint(ctx.Secret.CreatedAt) -} - -func (ctx *secretInspectContext) UpdatedAt() string { - return command.PrettyPrint(ctx.Secret.UpdatedAt) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/secret_test.go b/vendor/github.com/docker/cli/cli/command/formatter/secret_test.go deleted file mode 100644 index 03f6ac1f5..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/secret_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package formatter - -import ( - "bytes" - "testing" - "time" - - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" -) - -func TestSecretContextFormatWrite(t *testing.T) { - // Check default output format (verbose and non-verbose mode) for table headers - cases := []struct { - context Context - expected string - }{ - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - {Context{Format: NewSecretFormat("table", false)}, - `ID NAME DRIVER CREATED UPDATED -1 passwords Less than a second ago Less than a second ago -2 id_rsa Less than a second ago Less than a second ago -`}, - {Context{Format: NewSecretFormat("table {{.Name}}", true)}, - `NAME -passwords -id_rsa -`}, - {Context{Format: NewSecretFormat("{{.ID}}-{{.Name}}", false)}, - `1-passwords -2-id_rsa -`}, - } - - secrets := []swarm.Secret{ - {ID: "1", - Meta: swarm.Meta{CreatedAt: time.Now(), UpdatedAt: time.Now()}, - Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "passwords"}}}, - {ID: "2", - Meta: swarm.Meta{CreatedAt: time.Now(), UpdatedAt: time.Now()}, - Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "id_rsa"}}}, - } - for _, testcase := range cases { - out := bytes.NewBufferString("") - testcase.context.Output = out - if err := SecretWrite(testcase.context, secrets); err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/service.go b/vendor/github.com/docker/cli/cli/command/formatter/service.go deleted file mode 100644 index be1437b6f..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/service.go +++ /dev/null @@ -1,538 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - "time" - - "github.com/docker/cli/cli/command/inspect" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - mounttypes "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/stringid" - units "github.com/docker/go-units" - "github.com/pkg/errors" -) - -const serviceInspectPrettyTemplate Format = ` -ID: {{.ID}} -Name: {{.Name}} -{{- if .Labels }} -Labels: -{{- range $k, $v := .Labels }} - {{ $k }}{{if $v }}={{ $v }}{{ end }} -{{- end }}{{ end }} -Service Mode: -{{- if .IsModeGlobal }} Global -{{- else if .IsModeReplicated }} Replicated -{{- if .ModeReplicatedReplicas }} - Replicas: {{ .ModeReplicatedReplicas }} -{{- end }}{{ end }} -{{- if .HasUpdateStatus }} -UpdateStatus: - State: {{ .UpdateStatusState }} -{{- if .HasUpdateStatusStarted }} - Started: {{ .UpdateStatusStarted }} -{{- end }} -{{- if .UpdateIsCompleted }} - Completed: {{ .UpdateStatusCompleted }} -{{- end }} - Message: {{ .UpdateStatusMessage }} -{{- end }} -Placement: -{{- if .TaskPlacementConstraints }} - Constraints: {{ .TaskPlacementConstraints }} -{{- end }} -{{- if .TaskPlacementPreferences }} - Preferences: {{ .TaskPlacementPreferences }} -{{- end }} -{{- if .HasUpdateConfig }} -UpdateConfig: - Parallelism: {{ .UpdateParallelism }} -{{- if .HasUpdateDelay}} - Delay: {{ .UpdateDelay }} -{{- end }} - On failure: {{ .UpdateOnFailure }} -{{- if .HasUpdateMonitor}} - Monitoring Period: {{ .UpdateMonitor }} -{{- end }} - Max failure ratio: {{ .UpdateMaxFailureRatio }} - Update order: {{ .UpdateOrder }} -{{- end }} -{{- if .HasRollbackConfig }} -RollbackConfig: - Parallelism: {{ .RollbackParallelism }} -{{- if .HasRollbackDelay}} - Delay: {{ .RollbackDelay }} -{{- end }} - On failure: {{ .RollbackOnFailure }} -{{- if .HasRollbackMonitor}} - Monitoring Period: {{ .RollbackMonitor }} -{{- end }} - Max failure ratio: {{ .RollbackMaxFailureRatio }} - Rollback order: {{ .RollbackOrder }} -{{- end }} -ContainerSpec: - Image: {{ .ContainerImage }} -{{- if .ContainerArgs }} - Args: {{ range $arg := .ContainerArgs }}{{ $arg }} {{ end }} -{{- end -}} -{{- if .ContainerEnv }} - Env: {{ range $env := .ContainerEnv }}{{ $env }} {{ end }} -{{- end -}} -{{- if .ContainerWorkDir }} - Dir: {{ .ContainerWorkDir }} -{{- end -}} -{{- if .ContainerUser }} - User: {{ .ContainerUser }} -{{- end }} -{{- if .ContainerMounts }} -Mounts: -{{- end }} -{{- range $mount := .ContainerMounts }} - Target = {{ $mount.Target }} - Source = {{ $mount.Source }} - ReadOnly = {{ $mount.ReadOnly }} - Type = {{ $mount.Type }} -{{- end -}} -{{- if .HasResources }} -Resources: -{{- if .HasResourceReservations }} - Reservations: -{{- if gt .ResourceReservationNanoCPUs 0.0 }} - CPU: {{ .ResourceReservationNanoCPUs }} -{{- end }} -{{- if .ResourceReservationMemory }} - Memory: {{ .ResourceReservationMemory }} -{{- end }}{{ end }} -{{- if .HasResourceLimits }} - Limits: -{{- if gt .ResourceLimitsNanoCPUs 0.0 }} - CPU: {{ .ResourceLimitsNanoCPUs }} -{{- end }} -{{- if .ResourceLimitMemory }} - Memory: {{ .ResourceLimitMemory }} -{{- end }}{{ end }}{{ end }} -{{- if .Networks }} -Networks: -{{- range $network := .Networks }} {{ $network }}{{ end }} {{ end }} -Endpoint Mode: {{ .EndpointMode }} -{{- if .Ports }} -Ports: -{{- range $port := .Ports }} - PublishedPort = {{ $port.PublishedPort }} - Protocol = {{ $port.Protocol }} - TargetPort = {{ $port.TargetPort }} - PublishMode = {{ $port.PublishMode }} -{{- end }} {{ end -}} -` - -// NewServiceFormat returns a Format for rendering using a Context -func NewServiceFormat(source string) Format { - switch source { - case PrettyFormatKey: - return serviceInspectPrettyTemplate - default: - return Format(strings.TrimPrefix(source, RawFormatKey)) - } -} - -func resolveNetworks(service swarm.Service, getNetwork inspect.GetRefFunc) map[string]string { - networkNames := make(map[string]string) - for _, network := range service.Spec.TaskTemplate.Networks { - if resolved, _, err := getNetwork(network.Target); err == nil { - if resolvedNetwork, ok := resolved.(types.NetworkResource); ok { - networkNames[resolvedNetwork.ID] = resolvedNetwork.Name - } - } - } - return networkNames -} - -// ServiceInspectWrite renders the context for a list of services -func ServiceInspectWrite(ctx Context, refs []string, getRef, getNetwork inspect.GetRefFunc) error { - if ctx.Format != serviceInspectPrettyTemplate { - return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef) - } - render := func(format func(subContext subContext) error) error { - for _, ref := range refs { - serviceI, _, err := getRef(ref) - if err != nil { - return err - } - service, ok := serviceI.(swarm.Service) - if !ok { - return errors.Errorf("got wrong object to inspect") - } - if err := format(&serviceInspectContext{Service: service, networkNames: resolveNetworks(service, getNetwork)}); err != nil { - return err - } - } - return nil - } - return ctx.Write(&serviceInspectContext{}, render) -} - -type serviceInspectContext struct { - swarm.Service - subContext - - // networkNames is a map from network IDs (as found in - // Networks[x].Target) to network names. - networkNames map[string]string -} - -func (ctx *serviceInspectContext) MarshalJSON() ([]byte, error) { - return marshalJSON(ctx) -} - -func (ctx *serviceInspectContext) ID() string { - return ctx.Service.ID -} - -func (ctx *serviceInspectContext) Name() string { - return ctx.Service.Spec.Name -} - -func (ctx *serviceInspectContext) Labels() map[string]string { - return ctx.Service.Spec.Labels -} - -func (ctx *serviceInspectContext) IsModeGlobal() bool { - return ctx.Service.Spec.Mode.Global != nil -} - -func (ctx *serviceInspectContext) IsModeReplicated() bool { - return ctx.Service.Spec.Mode.Replicated != nil -} - -func (ctx *serviceInspectContext) ModeReplicatedReplicas() *uint64 { - return ctx.Service.Spec.Mode.Replicated.Replicas -} - -func (ctx *serviceInspectContext) HasUpdateStatus() bool { - return ctx.Service.UpdateStatus != nil && ctx.Service.UpdateStatus.State != "" -} - -func (ctx *serviceInspectContext) UpdateStatusState() swarm.UpdateState { - return ctx.Service.UpdateStatus.State -} - -func (ctx *serviceInspectContext) HasUpdateStatusStarted() bool { - return ctx.Service.UpdateStatus.StartedAt != nil -} - -func (ctx *serviceInspectContext) UpdateStatusStarted() string { - return units.HumanDuration(time.Since(*ctx.Service.UpdateStatus.StartedAt)) + " ago" -} - -func (ctx *serviceInspectContext) UpdateIsCompleted() bool { - return ctx.Service.UpdateStatus.State == swarm.UpdateStateCompleted && ctx.Service.UpdateStatus.CompletedAt != nil -} - -func (ctx *serviceInspectContext) UpdateStatusCompleted() string { - return units.HumanDuration(time.Since(*ctx.Service.UpdateStatus.CompletedAt)) + " ago" -} - -func (ctx *serviceInspectContext) UpdateStatusMessage() string { - return ctx.Service.UpdateStatus.Message -} - -func (ctx *serviceInspectContext) TaskPlacementConstraints() []string { - if ctx.Service.Spec.TaskTemplate.Placement != nil { - return ctx.Service.Spec.TaskTemplate.Placement.Constraints - } - return nil -} - -func (ctx *serviceInspectContext) TaskPlacementPreferences() []string { - if ctx.Service.Spec.TaskTemplate.Placement == nil { - return nil - } - var strings []string - for _, pref := range ctx.Service.Spec.TaskTemplate.Placement.Preferences { - if pref.Spread != nil { - strings = append(strings, "spread="+pref.Spread.SpreadDescriptor) - } - } - return strings -} - -func (ctx *serviceInspectContext) HasUpdateConfig() bool { - return ctx.Service.Spec.UpdateConfig != nil -} - -func (ctx *serviceInspectContext) UpdateParallelism() uint64 { - return ctx.Service.Spec.UpdateConfig.Parallelism -} - -func (ctx *serviceInspectContext) HasUpdateDelay() bool { - return ctx.Service.Spec.UpdateConfig.Delay.Nanoseconds() > 0 -} - -func (ctx *serviceInspectContext) UpdateDelay() time.Duration { - return ctx.Service.Spec.UpdateConfig.Delay -} - -func (ctx *serviceInspectContext) UpdateOnFailure() string { - return ctx.Service.Spec.UpdateConfig.FailureAction -} - -func (ctx *serviceInspectContext) UpdateOrder() string { - return ctx.Service.Spec.UpdateConfig.Order -} - -func (ctx *serviceInspectContext) HasUpdateMonitor() bool { - return ctx.Service.Spec.UpdateConfig.Monitor.Nanoseconds() > 0 -} - -func (ctx *serviceInspectContext) UpdateMonitor() time.Duration { - return ctx.Service.Spec.UpdateConfig.Monitor -} - -func (ctx *serviceInspectContext) UpdateMaxFailureRatio() float32 { - return ctx.Service.Spec.UpdateConfig.MaxFailureRatio -} - -func (ctx *serviceInspectContext) HasRollbackConfig() bool { - return ctx.Service.Spec.RollbackConfig != nil -} - -func (ctx *serviceInspectContext) RollbackParallelism() uint64 { - return ctx.Service.Spec.RollbackConfig.Parallelism -} - -func (ctx *serviceInspectContext) HasRollbackDelay() bool { - return ctx.Service.Spec.RollbackConfig.Delay.Nanoseconds() > 0 -} - -func (ctx *serviceInspectContext) RollbackDelay() time.Duration { - return ctx.Service.Spec.RollbackConfig.Delay -} - -func (ctx *serviceInspectContext) RollbackOnFailure() string { - return ctx.Service.Spec.RollbackConfig.FailureAction -} - -func (ctx *serviceInspectContext) HasRollbackMonitor() bool { - return ctx.Service.Spec.RollbackConfig.Monitor.Nanoseconds() > 0 -} - -func (ctx *serviceInspectContext) RollbackMonitor() time.Duration { - return ctx.Service.Spec.RollbackConfig.Monitor -} - -func (ctx *serviceInspectContext) RollbackMaxFailureRatio() float32 { - return ctx.Service.Spec.RollbackConfig.MaxFailureRatio -} - -func (ctx *serviceInspectContext) RollbackOrder() string { - return ctx.Service.Spec.RollbackConfig.Order -} - -func (ctx *serviceInspectContext) ContainerImage() string { - return ctx.Service.Spec.TaskTemplate.ContainerSpec.Image -} - -func (ctx *serviceInspectContext) ContainerArgs() []string { - return ctx.Service.Spec.TaskTemplate.ContainerSpec.Args -} - -func (ctx *serviceInspectContext) ContainerEnv() []string { - return ctx.Service.Spec.TaskTemplate.ContainerSpec.Env -} - -func (ctx *serviceInspectContext) ContainerWorkDir() string { - return ctx.Service.Spec.TaskTemplate.ContainerSpec.Dir -} - -func (ctx *serviceInspectContext) ContainerUser() string { - return ctx.Service.Spec.TaskTemplate.ContainerSpec.User -} - -func (ctx *serviceInspectContext) ContainerMounts() []mounttypes.Mount { - return ctx.Service.Spec.TaskTemplate.ContainerSpec.Mounts -} - -func (ctx *serviceInspectContext) HasResources() bool { - return ctx.Service.Spec.TaskTemplate.Resources != nil -} - -func (ctx *serviceInspectContext) HasResourceReservations() bool { - if ctx.Service.Spec.TaskTemplate.Resources == nil || ctx.Service.Spec.TaskTemplate.Resources.Reservations == nil { - return false - } - return ctx.Service.Spec.TaskTemplate.Resources.Reservations.NanoCPUs > 0 || ctx.Service.Spec.TaskTemplate.Resources.Reservations.MemoryBytes > 0 -} - -func (ctx *serviceInspectContext) ResourceReservationNanoCPUs() float64 { - if ctx.Service.Spec.TaskTemplate.Resources.Reservations.NanoCPUs == 0 { - return float64(0) - } - return float64(ctx.Service.Spec.TaskTemplate.Resources.Reservations.NanoCPUs) / 1e9 -} - -func (ctx *serviceInspectContext) ResourceReservationMemory() string { - if ctx.Service.Spec.TaskTemplate.Resources.Reservations.MemoryBytes == 0 { - return "" - } - return units.BytesSize(float64(ctx.Service.Spec.TaskTemplate.Resources.Reservations.MemoryBytes)) -} - -func (ctx *serviceInspectContext) HasResourceLimits() bool { - if ctx.Service.Spec.TaskTemplate.Resources == nil || ctx.Service.Spec.TaskTemplate.Resources.Limits == nil { - return false - } - return ctx.Service.Spec.TaskTemplate.Resources.Limits.NanoCPUs > 0 || ctx.Service.Spec.TaskTemplate.Resources.Limits.MemoryBytes > 0 -} - -func (ctx *serviceInspectContext) ResourceLimitsNanoCPUs() float64 { - return float64(ctx.Service.Spec.TaskTemplate.Resources.Limits.NanoCPUs) / 1e9 -} - -func (ctx *serviceInspectContext) ResourceLimitMemory() string { - if ctx.Service.Spec.TaskTemplate.Resources.Limits.MemoryBytes == 0 { - return "" - } - return units.BytesSize(float64(ctx.Service.Spec.TaskTemplate.Resources.Limits.MemoryBytes)) -} - -func (ctx *serviceInspectContext) Networks() []string { - var out []string - for _, n := range ctx.Service.Spec.TaskTemplate.Networks { - if name, ok := ctx.networkNames[n.Target]; ok { - out = append(out, name) - } else { - out = append(out, n.Target) - } - } - return out -} - -func (ctx *serviceInspectContext) EndpointMode() string { - if ctx.Service.Spec.EndpointSpec == nil { - return "" - } - - return string(ctx.Service.Spec.EndpointSpec.Mode) -} - -func (ctx *serviceInspectContext) Ports() []swarm.PortConfig { - return ctx.Service.Endpoint.Ports -} - -const ( - defaultServiceTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Mode}}\t{{.Replicas}}\t{{.Image}}\t{{.Ports}}" - - serviceIDHeader = "ID" - modeHeader = "MODE" - replicasHeader = "REPLICAS" -) - -// NewServiceListFormat returns a Format for rendering using a service Context -func NewServiceListFormat(source string, quiet bool) Format { - switch source { - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - return defaultServiceTableFormat - case RawFormatKey: - if quiet { - return `id: {{.ID}}` - } - return `id: {{.ID}}\nname: {{.Name}}\nmode: {{.Mode}}\nreplicas: {{.Replicas}}\nimage: {{.Image}}\nports: {{.Ports}}\n` - } - return Format(source) -} - -// ServiceListInfo stores the information about mode and replicas to be used by template -type ServiceListInfo struct { - Mode string - Replicas string -} - -// ServiceListWrite writes the context -func ServiceListWrite(ctx Context, services []swarm.Service, info map[string]ServiceListInfo) error { - render := func(format func(subContext subContext) error) error { - for _, service := range services { - serviceCtx := &serviceContext{service: service, mode: info[service.ID].Mode, replicas: info[service.ID].Replicas} - if err := format(serviceCtx); err != nil { - return err - } - } - return nil - } - serviceCtx := serviceContext{} - serviceCtx.header = map[string]string{ - "ID": serviceIDHeader, - "Name": nameHeader, - "Mode": modeHeader, - "Replicas": replicasHeader, - "Image": imageHeader, - "Ports": portsHeader, - } - return ctx.Write(&serviceCtx, render) -} - -type serviceContext struct { - HeaderContext - service swarm.Service - mode string - replicas string -} - -func (c *serviceContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *serviceContext) ID() string { - return stringid.TruncateID(c.service.ID) -} - -func (c *serviceContext) Name() string { - return c.service.Spec.Name -} - -func (c *serviceContext) Mode() string { - return c.mode -} - -func (c *serviceContext) Replicas() string { - return c.replicas -} - -func (c *serviceContext) Image() string { - var image string - if c.service.Spec.TaskTemplate.ContainerSpec != nil { - image = c.service.Spec.TaskTemplate.ContainerSpec.Image - } - if ref, err := reference.ParseNormalizedNamed(image); err == nil { - // update image string for display, (strips any digest) - if nt, ok := ref.(reference.NamedTagged); ok { - if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil { - image = reference.FamiliarString(namedTagged) - } - } - } - - return image -} - -func (c *serviceContext) Ports() string { - if c.service.Endpoint.Ports == nil { - return "" - } - ports := []string{} - for _, pConfig := range c.service.Endpoint.Ports { - if pConfig.PublishMode == swarm.PortConfigPublishModeIngress { - ports = append(ports, fmt.Sprintf("*:%d->%d/%s", - pConfig.PublishedPort, - pConfig.TargetPort, - pConfig.Protocol, - )) - } - } - return strings.Join(ports, ",") -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/service_test.go b/vendor/github.com/docker/cli/cli/command/formatter/service_test.go deleted file mode 100644 index 35adb4be8..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/service_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - "testing" - - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestServiceContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - { - Context{Format: NewServiceListFormat("table", false)}, - `ID NAME MODE REPLICAS IMAGE PORTS -id_baz baz global 2/4 *:80->8080/tcp -id_bar bar replicated 2/4 *:80->8080/tcp -`, - }, - { - Context{Format: NewServiceListFormat("table", true)}, - `id_baz -id_bar -`, - }, - { - Context{Format: NewServiceListFormat("table {{.Name}}", false)}, - `NAME -baz -bar -`, - }, - { - Context{Format: NewServiceListFormat("table {{.Name}}", true)}, - `NAME -baz -bar -`, - }, - // Raw Format - { - Context{Format: NewServiceListFormat("raw", false)}, - string(golden.Get(t, "service-context-write-raw.golden")), - }, - { - Context{Format: NewServiceListFormat("raw", true)}, - `id: id_baz -id: id_bar -`, - }, - // Custom Format - { - Context{Format: NewServiceListFormat("{{.Name}}", false)}, - `baz -bar -`, - }, - } - - for _, testcase := range cases { - services := []swarm.Service{ - { - ID: "id_baz", - Spec: swarm.ServiceSpec{ - Annotations: swarm.Annotations{Name: "baz"}, - }, - Endpoint: swarm.Endpoint{ - Ports: []swarm.PortConfig{ - { - PublishMode: "ingress", - PublishedPort: 80, - TargetPort: 8080, - Protocol: "tcp", - }, - }, - }, - }, - { - ID: "id_bar", - Spec: swarm.ServiceSpec{ - Annotations: swarm.Annotations{Name: "bar"}, - }, - Endpoint: swarm.Endpoint{ - Ports: []swarm.PortConfig{ - { - PublishMode: "ingress", - PublishedPort: 80, - TargetPort: 8080, - Protocol: "tcp", - }, - }, - }, - }, - } - info := map[string]ServiceListInfo{ - "id_baz": { - Mode: "global", - Replicas: "2/4", - }, - "id_bar": { - Mode: "replicated", - Replicas: "2/4", - }, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := ServiceListWrite(testcase.context, services, info) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestServiceContextWriteJSON(t *testing.T) { - services := []swarm.Service{ - { - ID: "id_baz", - Spec: swarm.ServiceSpec{ - Annotations: swarm.Annotations{Name: "baz"}, - }, - Endpoint: swarm.Endpoint{ - Ports: []swarm.PortConfig{ - { - PublishMode: "ingress", - PublishedPort: 80, - TargetPort: 8080, - Protocol: "tcp", - }, - }, - }, - }, - { - ID: "id_bar", - Spec: swarm.ServiceSpec{ - Annotations: swarm.Annotations{Name: "bar"}, - }, - Endpoint: swarm.Endpoint{ - Ports: []swarm.PortConfig{ - { - PublishMode: "ingress", - PublishedPort: 80, - TargetPort: 8080, - Protocol: "tcp", - }, - }, - }, - }, - } - info := map[string]ServiceListInfo{ - "id_baz": { - Mode: "global", - Replicas: "2/4", - }, - "id_bar": { - Mode: "replicated", - Replicas: "2/4", - }, - } - expectedJSONs := []map[string]interface{}{ - {"ID": "id_baz", "Name": "baz", "Mode": "global", "Replicas": "2/4", "Image": "", "Ports": "*:80->8080/tcp"}, - {"ID": "id_bar", "Name": "bar", "Mode": "replicated", "Replicas": "2/4", "Image": "", "Ports": "*:80->8080/tcp"}, - } - - out := bytes.NewBufferString("") - err := ServiceListWrite(Context{Format: "{{json .}}", Output: out}, services, info) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var m map[string]interface{} - err := json.Unmarshal([]byte(line), &m) - require.NoError(t, err, msg) - assert.Equal(t, expectedJSONs[i], m, msg) - } -} -func TestServiceContextWriteJSONField(t *testing.T) { - services := []swarm.Service{ - {ID: "id_baz", Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: "baz"}}}, - {ID: "id_bar", Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: "bar"}}}, - } - info := map[string]ServiceListInfo{ - "id_baz": { - Mode: "global", - Replicas: "2/4", - }, - "id_bar": { - Mode: "replicated", - Replicas: "2/4", - }, - } - out := bytes.NewBufferString("") - err := ServiceListWrite(Context{Format: "{{json .Name}}", Output: out}, services, info) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var s string - err := json.Unmarshal([]byte(line), &s) - require.NoError(t, err, msg) - assert.Equal(t, services[i].Spec.Name, s, msg) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/stack.go b/vendor/github.com/docker/cli/cli/command/formatter/stack.go deleted file mode 100644 index 676bcc05f..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/stack.go +++ /dev/null @@ -1,67 +0,0 @@ -package formatter - -import ( - "strconv" -) - -const ( - defaultStackTableFormat = "table {{.Name}}\t{{.Services}}" - - stackServicesHeader = "SERVICES" -) - -// Stack contains deployed stack information. -type Stack struct { - // Name is the name of the stack - Name string - // Services is the number of the services - Services int -} - -// NewStackFormat returns a format for use with a stack Context -func NewStackFormat(source string) Format { - switch source { - case TableFormatKey: - return defaultStackTableFormat - } - return Format(source) -} - -// StackWrite writes formatted stacks using the Context -func StackWrite(ctx Context, stacks []*Stack) error { - render := func(format func(subContext subContext) error) error { - for _, stack := range stacks { - if err := format(&stackContext{s: stack}); err != nil { - return err - } - } - return nil - } - return ctx.Write(newStackContext(), render) -} - -type stackContext struct { - HeaderContext - s *Stack -} - -func newStackContext() *stackContext { - stackCtx := stackContext{} - stackCtx.header = map[string]string{ - "Name": nameHeader, - "Services": stackServicesHeader, - } - return &stackCtx -} - -func (s *stackContext) MarshalJSON() ([]byte, error) { - return marshalJSON(s) -} - -func (s *stackContext) Name() string { - return s.s.Name -} - -func (s *stackContext) Services() string { - return strconv.Itoa(s.s.Services) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/stack_test.go b/vendor/github.com/docker/cli/cli/command/formatter/stack_test.go deleted file mode 100644 index b18ae7f08..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/stack_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package formatter - -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestStackContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - { - Context{Format: NewStackFormat("table")}, - `NAME SERVICES -baz 2 -bar 1 -`, - }, - { - Context{Format: NewStackFormat("table {{.Name}}")}, - `NAME -baz -bar -`, - }, - // Custom Format - { - Context{Format: NewStackFormat("{{.Name}}")}, - `baz -bar -`, - }, - } - - stacks := []*Stack{ - {Name: "baz", Services: 2}, - {Name: "bar", Services: 1}, - } - for _, testcase := range cases { - out := bytes.NewBufferString("") - testcase.context.Output = out - err := StackWrite(testcase.context, stacks) - if err != nil { - assert.Error(t, err, testcase.expected) - } else { - assert.Equal(t, out.String(), testcase.expected) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/stats.go b/vendor/github.com/docker/cli/cli/command/formatter/stats.go deleted file mode 100644 index 06eedc715..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/stats.go +++ /dev/null @@ -1,218 +0,0 @@ -package formatter - -import ( - "fmt" - "sync" - - units "github.com/docker/go-units" -) - -const ( - winOSType = "windows" - defaultStatsTableFormat = "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}" - winDefaultStatsTableFormat = "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}" - - containerHeader = "CONTAINER" - cpuPercHeader = "CPU %" - netIOHeader = "NET I/O" - blockIOHeader = "BLOCK I/O" - memPercHeader = "MEM %" // Used only on Linux - winMemUseHeader = "PRIV WORKING SET" // Used only on Windows - memUseHeader = "MEM USAGE / LIMIT" // Used only on Linux - pidsHeader = "PIDS" // Used only on Linux -) - -// StatsEntry represents represents the statistics data collected from a container -type StatsEntry struct { - Container string - Name string - ID string - CPUPercentage float64 - Memory float64 // On Windows this is the private working set - MemoryLimit float64 // Not used on Windows - MemoryPercentage float64 // Not used on Windows - NetworkRx float64 - NetworkTx float64 - BlockRead float64 - BlockWrite float64 - PidsCurrent uint64 // Not used on Windows - IsInvalid bool -} - -// ContainerStats represents an entity to store containers statistics synchronously -type ContainerStats struct { - mutex sync.Mutex - StatsEntry - err error -} - -// GetError returns the container statistics error. -// This is used to determine whether the statistics are valid or not -func (cs *ContainerStats) GetError() error { - cs.mutex.Lock() - defer cs.mutex.Unlock() - return cs.err -} - -// SetErrorAndReset zeroes all the container statistics and store the error. -// It is used when receiving time out error during statistics collecting to reduce lock overhead -func (cs *ContainerStats) SetErrorAndReset(err error) { - cs.mutex.Lock() - defer cs.mutex.Unlock() - cs.CPUPercentage = 0 - cs.Memory = 0 - cs.MemoryPercentage = 0 - cs.MemoryLimit = 0 - cs.NetworkRx = 0 - cs.NetworkTx = 0 - cs.BlockRead = 0 - cs.BlockWrite = 0 - cs.PidsCurrent = 0 - cs.err = err - cs.IsInvalid = true -} - -// SetError sets container statistics error -func (cs *ContainerStats) SetError(err error) { - cs.mutex.Lock() - defer cs.mutex.Unlock() - cs.err = err - if err != nil { - cs.IsInvalid = true - } -} - -// SetStatistics set the container statistics -func (cs *ContainerStats) SetStatistics(s StatsEntry) { - cs.mutex.Lock() - defer cs.mutex.Unlock() - s.Container = cs.Container - cs.StatsEntry = s -} - -// GetStatistics returns container statistics with other meta data such as the container name -func (cs *ContainerStats) GetStatistics() StatsEntry { - cs.mutex.Lock() - defer cs.mutex.Unlock() - return cs.StatsEntry -} - -// NewStatsFormat returns a format for rendering an CStatsContext -func NewStatsFormat(source, osType string) Format { - if source == TableFormatKey { - if osType == winOSType { - return Format(winDefaultStatsTableFormat) - } - return Format(defaultStatsTableFormat) - } - return Format(source) -} - -// NewContainerStats returns a new ContainerStats entity and sets in it the given name -func NewContainerStats(container string) *ContainerStats { - return &ContainerStats{StatsEntry: StatsEntry{Container: container}} -} - -// ContainerStatsWrite renders the context for a list of containers statistics -func ContainerStatsWrite(ctx Context, containerStats []StatsEntry, osType string) error { - render := func(format func(subContext subContext) error) error { - for _, cstats := range containerStats { - containerStatsCtx := &containerStatsContext{ - s: cstats, - os: osType, - } - if err := format(containerStatsCtx); err != nil { - return err - } - } - return nil - } - memUsage := memUseHeader - if osType == winOSType { - memUsage = winMemUseHeader - } - containerStatsCtx := containerStatsContext{} - containerStatsCtx.header = map[string]string{ - "Container": containerHeader, - "Name": nameHeader, - "ID": containerIDHeader, - "CPUPerc": cpuPercHeader, - "MemUsage": memUsage, - "MemPerc": memPercHeader, - "NetIO": netIOHeader, - "BlockIO": blockIOHeader, - "PIDs": pidsHeader, - } - containerStatsCtx.os = osType - return ctx.Write(&containerStatsCtx, render) -} - -type containerStatsContext struct { - HeaderContext - s StatsEntry - os string -} - -func (c *containerStatsContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *containerStatsContext) Container() string { - return c.s.Container -} - -func (c *containerStatsContext) Name() string { - if len(c.s.Name) > 1 { - return c.s.Name[1:] - } - return "--" -} - -func (c *containerStatsContext) ID() string { - return c.s.ID -} - -func (c *containerStatsContext) CPUPerc() string { - if c.s.IsInvalid { - return fmt.Sprintf("--") - } - return fmt.Sprintf("%.2f%%", c.s.CPUPercentage) -} - -func (c *containerStatsContext) MemUsage() string { - if c.s.IsInvalid { - return fmt.Sprintf("-- / --") - } - if c.os == winOSType { - return units.BytesSize(c.s.Memory) - } - return fmt.Sprintf("%s / %s", units.BytesSize(c.s.Memory), units.BytesSize(c.s.MemoryLimit)) -} - -func (c *containerStatsContext) MemPerc() string { - if c.s.IsInvalid || c.os == winOSType { - return fmt.Sprintf("--") - } - return fmt.Sprintf("%.2f%%", c.s.MemoryPercentage) -} - -func (c *containerStatsContext) NetIO() string { - if c.s.IsInvalid { - return fmt.Sprintf("--") - } - return fmt.Sprintf("%s / %s", units.HumanSizeWithPrecision(c.s.NetworkRx, 3), units.HumanSizeWithPrecision(c.s.NetworkTx, 3)) -} - -func (c *containerStatsContext) BlockIO() string { - if c.s.IsInvalid { - return fmt.Sprintf("--") - } - return fmt.Sprintf("%s / %s", units.HumanSizeWithPrecision(c.s.BlockRead, 3), units.HumanSizeWithPrecision(c.s.BlockWrite, 3)) -} - -func (c *containerStatsContext) PIDs() string { - if c.s.IsInvalid || c.os == winOSType { - return fmt.Sprintf("--") - } - return fmt.Sprintf("%d", c.s.PidsCurrent) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/stats_test.go b/vendor/github.com/docker/cli/cli/command/formatter/stats_test.go deleted file mode 100644 index 078e8db32..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/stats_test.go +++ /dev/null @@ -1,266 +0,0 @@ -package formatter - -import ( - "bytes" - "testing" - - "github.com/docker/docker/pkg/stringid" - "github.com/stretchr/testify/assert" -) - -func TestContainerStatsContext(t *testing.T) { - containerID := stringid.GenerateRandomID() - - var ctx containerStatsContext - tt := []struct { - stats StatsEntry - osType string - expValue string - expHeader string - call func() string - }{ - {StatsEntry{Container: containerID}, "", containerID, containerHeader, ctx.Container}, - {StatsEntry{CPUPercentage: 5.5}, "", "5.50%", cpuPercHeader, ctx.CPUPerc}, - {StatsEntry{CPUPercentage: 5.5, IsInvalid: true}, "", "--", cpuPercHeader, ctx.CPUPerc}, - {StatsEntry{NetworkRx: 0.31, NetworkTx: 12.3}, "", "0.31B / 12.3B", netIOHeader, ctx.NetIO}, - {StatsEntry{NetworkRx: 0.31, NetworkTx: 12.3, IsInvalid: true}, "", "--", netIOHeader, ctx.NetIO}, - {StatsEntry{BlockRead: 0.1, BlockWrite: 2.3}, "", "0.1B / 2.3B", blockIOHeader, ctx.BlockIO}, - {StatsEntry{BlockRead: 0.1, BlockWrite: 2.3, IsInvalid: true}, "", "--", blockIOHeader, ctx.BlockIO}, - {StatsEntry{MemoryPercentage: 10.2}, "", "10.20%", memPercHeader, ctx.MemPerc}, - {StatsEntry{MemoryPercentage: 10.2, IsInvalid: true}, "", "--", memPercHeader, ctx.MemPerc}, - {StatsEntry{MemoryPercentage: 10.2}, "windows", "--", memPercHeader, ctx.MemPerc}, - {StatsEntry{Memory: 24, MemoryLimit: 30}, "", "24B / 30B", memUseHeader, ctx.MemUsage}, - {StatsEntry{Memory: 24, MemoryLimit: 30, IsInvalid: true}, "", "-- / --", memUseHeader, ctx.MemUsage}, - {StatsEntry{Memory: 24, MemoryLimit: 30}, "windows", "24B", winMemUseHeader, ctx.MemUsage}, - {StatsEntry{PidsCurrent: 10}, "", "10", pidsHeader, ctx.PIDs}, - {StatsEntry{PidsCurrent: 10, IsInvalid: true}, "", "--", pidsHeader, ctx.PIDs}, - {StatsEntry{PidsCurrent: 10}, "windows", "--", pidsHeader, ctx.PIDs}, - } - - for _, te := range tt { - ctx = containerStatsContext{s: te.stats, os: te.osType} - if v := te.call(); v != te.expValue { - t.Fatalf("Expected %q, got %q", te.expValue, v) - } - } -} - -func TestContainerStatsContextWrite(t *testing.T) { - tt := []struct { - context Context - expected string - }{ - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - { - Context{Format: "table {{.MemUsage}}"}, - `MEM USAGE / LIMIT -20B / 20B --- / -- -`, - }, - { - Context{Format: "{{.Container}} {{.ID}} {{.Name}}"}, - `container1 abcdef foo -container2 -- -`, - }, - { - Context{Format: "{{.Container}} {{.CPUPerc}}"}, - `container1 20.00% -container2 -- -`, - }, - } - - for _, te := range tt { - stats := []StatsEntry{ - { - Container: "container1", - ID: "abcdef", - Name: "/foo", - CPUPercentage: 20, - Memory: 20, - MemoryLimit: 20, - MemoryPercentage: 20, - NetworkRx: 20, - NetworkTx: 20, - BlockRead: 20, - BlockWrite: 20, - PidsCurrent: 2, - IsInvalid: false, - }, - { - Container: "container2", - CPUPercentage: 30, - Memory: 30, - MemoryLimit: 30, - MemoryPercentage: 30, - NetworkRx: 30, - NetworkTx: 30, - BlockRead: 30, - BlockWrite: 30, - PidsCurrent: 3, - IsInvalid: true, - }, - } - var out bytes.Buffer - te.context.Output = &out - err := ContainerStatsWrite(te.context, stats, "linux") - if err != nil { - assert.EqualError(t, err, te.expected) - } else { - assert.Equal(t, te.expected, out.String()) - } - } -} - -func TestContainerStatsContextWriteWindows(t *testing.T) { - tt := []struct { - context Context - expected string - }{ - { - Context{Format: "table {{.MemUsage}}"}, - `PRIV WORKING SET -20B --- / -- -`, - }, - { - Context{Format: "{{.Container}} {{.CPUPerc}}"}, - `container1 20.00% -container2 -- -`, - }, - { - Context{Format: "{{.Container}} {{.MemPerc}} {{.PIDs}}"}, - `container1 -- -- -container2 -- -- -`, - }, - } - - for _, te := range tt { - stats := []StatsEntry{ - { - Container: "container1", - CPUPercentage: 20, - Memory: 20, - MemoryLimit: 20, - MemoryPercentage: 20, - NetworkRx: 20, - NetworkTx: 20, - BlockRead: 20, - BlockWrite: 20, - PidsCurrent: 2, - IsInvalid: false, - }, - { - Container: "container2", - CPUPercentage: 30, - Memory: 30, - MemoryLimit: 30, - MemoryPercentage: 30, - NetworkRx: 30, - NetworkTx: 30, - BlockRead: 30, - BlockWrite: 30, - PidsCurrent: 3, - IsInvalid: true, - }, - } - var out bytes.Buffer - te.context.Output = &out - err := ContainerStatsWrite(te.context, stats, "windows") - if err != nil { - assert.EqualError(t, err, te.expected) - } else { - assert.Equal(t, te.expected, out.String()) - } - } -} - -func TestContainerStatsContextWriteWithNoStats(t *testing.T) { - var out bytes.Buffer - - contexts := []struct { - context Context - expected string - }{ - { - Context{ - Format: "{{.Container}}", - Output: &out, - }, - "", - }, - { - Context{ - Format: "table {{.Container}}", - Output: &out, - }, - "CONTAINER\n", - }, - { - Context{ - Format: "table {{.Container}}\t{{.CPUPerc}}", - Output: &out, - }, - "CONTAINER CPU %\n", - }, - } - - for _, context := range contexts { - ContainerStatsWrite(context.context, []StatsEntry{}, "linux") - assert.Equal(t, context.expected, out.String()) - // Clean buffer - out.Reset() - } -} - -func TestContainerStatsContextWriteWithNoStatsWindows(t *testing.T) { - var out bytes.Buffer - - contexts := []struct { - context Context - expected string - }{ - { - Context{ - Format: "{{.Container}}", - Output: &out, - }, - "", - }, - { - Context{ - Format: "table {{.Container}}\t{{.MemUsage}}", - Output: &out, - }, - "CONTAINER PRIV WORKING SET\n", - }, - { - Context{ - Format: "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}", - Output: &out, - }, - "CONTAINER CPU % PRIV WORKING SET\n", - }, - } - - for _, context := range contexts { - ContainerStatsWrite(context.context, []StatsEntry{}, "windows") - assert.Equal(t, context.expected, out.String()) - // Clean buffer - out.Reset() - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/task.go b/vendor/github.com/docker/cli/cli/command/formatter/task.go deleted file mode 100644 index 6172b320e..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/task.go +++ /dev/null @@ -1,150 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - "time" - - "github.com/docker/cli/cli/command" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/go-units" -) - -const ( - defaultTaskTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Image}}\t{{.Node}}\t{{.DesiredState}}\t{{.CurrentState}}\t{{.Error}}\t{{.Ports}}" - - nodeHeader = "NODE" - taskIDHeader = "ID" - desiredStateHeader = "DESIRED STATE" - currentStateHeader = "CURRENT STATE" - errorHeader = "ERROR" - - maxErrLength = 30 -) - -// NewTaskFormat returns a Format for rendering using a task Context -func NewTaskFormat(source string, quiet bool) Format { - switch source { - case TableFormatKey: - if quiet { - return defaultQuietFormat - } - return defaultTaskTableFormat - case RawFormatKey: - if quiet { - return `id: {{.ID}}` - } - return `id: {{.ID}}\nname: {{.Name}}\nimage: {{.Image}}\nnode: {{.Node}}\ndesired_state: {{.DesiredState}}\ncurrent_state: {{.CurrentState}}\nerror: {{.Error}}\nports: {{.Ports}}\n` - } - return Format(source) -} - -// TaskWrite writes the context -func TaskWrite(ctx Context, tasks []swarm.Task, names map[string]string, nodes map[string]string) error { - render := func(format func(subContext subContext) error) error { - for _, task := range tasks { - taskCtx := &taskContext{trunc: ctx.Trunc, task: task, name: names[task.ID], node: nodes[task.ID]} - if err := format(taskCtx); err != nil { - return err - } - } - return nil - } - taskCtx := taskContext{} - taskCtx.header = taskHeaderContext{ - "ID": taskIDHeader, - "Name": nameHeader, - "Image": imageHeader, - "Node": nodeHeader, - "DesiredState": desiredStateHeader, - "CurrentState": currentStateHeader, - "Error": errorHeader, - "Ports": portsHeader, - } - return ctx.Write(&taskCtx, render) -} - -type taskHeaderContext map[string]string - -type taskContext struct { - HeaderContext - trunc bool - task swarm.Task - name string - node string -} - -func (c *taskContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *taskContext) ID() string { - if c.trunc { - return stringid.TruncateID(c.task.ID) - } - return c.task.ID -} - -func (c *taskContext) Name() string { - return c.name -} - -func (c *taskContext) Image() string { - image := c.task.Spec.ContainerSpec.Image - if c.trunc { - ref, err := reference.ParseNormalizedNamed(image) - if err == nil { - // update image string for display, (strips any digest) - if nt, ok := ref.(reference.NamedTagged); ok { - if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil { - image = reference.FamiliarString(namedTagged) - } - } - } - } - return image -} - -func (c *taskContext) Node() string { - return c.node -} - -func (c *taskContext) DesiredState() string { - return command.PrettyPrint(c.task.DesiredState) -} - -func (c *taskContext) CurrentState() string { - return fmt.Sprintf("%s %s ago", - command.PrettyPrint(c.task.Status.State), - strings.ToLower(units.HumanDuration(time.Since(c.task.Status.Timestamp))), - ) -} - -func (c *taskContext) Error() string { - // Trim and quote the error message. - taskErr := c.task.Status.Err - if c.trunc && len(taskErr) > maxErrLength { - taskErr = fmt.Sprintf("%s…", taskErr[:maxErrLength-1]) - } - if len(taskErr) > 0 { - taskErr = fmt.Sprintf("\"%s\"", taskErr) - } - return taskErr -} - -func (c *taskContext) Ports() string { - if len(c.task.Status.PortStatus.Ports) == 0 { - return "" - } - ports := []string{} - for _, pConfig := range c.task.Status.PortStatus.Ports { - ports = append(ports, fmt.Sprintf("*:%d->%d/%s", - pConfig.PublishedPort, - pConfig.TargetPort, - pConfig.Protocol, - )) - } - return strings.Join(ports, ",") -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/task_test.go b/vendor/github.com/docker/cli/cli/command/formatter/task_test.go deleted file mode 100644 index 7e8edd299..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/task_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "strings" - "testing" - - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestTaskContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - { - Context{Format: NewTaskFormat("table", true)}, - `taskID1 -taskID2 -`, - }, - { - Context{Format: NewTaskFormat("table {{.Name}}\t{{.Node}}\t{{.Ports}}", false)}, - string(golden.Get(t, "task-context-write-table-custom.golden")), - }, - { - Context{Format: NewTaskFormat("table {{.Name}}", true)}, - `NAME -foobar_baz -foobar_bar -`, - }, - { - Context{Format: NewTaskFormat("raw", true)}, - `id: taskID1 -id: taskID2 -`, - }, - { - Context{Format: NewTaskFormat("{{.Name}} {{.Node}}", false)}, - `foobar_baz foo1 -foobar_bar foo2 -`, - }, - } - - for _, testcase := range cases { - tasks := []swarm.Task{ - {ID: "taskID1"}, - {ID: "taskID2"}, - } - names := map[string]string{ - "taskID1": "foobar_baz", - "taskID2": "foobar_bar", - } - nodes := map[string]string{ - "taskID1": "foo1", - "taskID2": "foo2", - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := TaskWrite(testcase.context, tasks, names, nodes) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestTaskContextWriteJSONField(t *testing.T) { - tasks := []swarm.Task{ - {ID: "taskID1"}, - {ID: "taskID2"}, - } - names := map[string]string{ - "taskID1": "foobar_baz", - "taskID2": "foobar_bar", - } - out := bytes.NewBufferString("") - err := TaskWrite(Context{Format: "{{json .ID}}", Output: out}, tasks, names, map[string]string{}) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - var s string - if err := json.Unmarshal([]byte(line), &s); err != nil { - t.Fatal(err) - } - assert.Equal(t, tasks[i].ID, s) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/testdata/container-context-write-special-headers.golden b/vendor/github.com/docker/cli/cli/command/formatter/testdata/container-context-write-special-headers.golden deleted file mode 100644 index 3fe21c8e4..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/testdata/container-context-write-special-headers.golden +++ /dev/null @@ -1,3 +0,0 @@ -CONTAINER ID IMAGE CREATED/STATUS/ PORTS .NAMES STATUS -conta "ubuntu" 24 hours ago//.FOOBAR_BAZ -conta "ubuntu" 24 hours ago//.FOOBAR_BAR diff --git a/vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-context-write-custom.golden b/vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-context-write-custom.golden deleted file mode 100644 index eaa466b4d..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-context-write-custom.golden +++ /dev/null @@ -1,5 +0,0 @@ -TYPE ACTIVE -Images 0 -Containers 0 -Local Volumes 0 -Build Cache diff --git a/vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-raw-format.golden b/vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-raw-format.golden deleted file mode 100644 index 4539c0c62..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/testdata/disk-usage-raw-format.golden +++ /dev/null @@ -1,24 +0,0 @@ -type: Images -total: 0 -active: 0 -size: 0B -reclaimable: 0B - -type: Containers -total: 0 -active: 0 -size: 0B -reclaimable: 0B - -type: Local Volumes -total: 0 -active: 0 -size: 0B -reclaimable: 0B - -type: Build Cache -total: -active: -size: 0B -reclaimable: 0B - diff --git a/vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-stars-table.golden b/vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-stars-table.golden deleted file mode 100644 index 1a66b4292..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-stars-table.golden +++ /dev/null @@ -1,2 +0,0 @@ -NAME DESCRIPTION STARS OFFICIAL AUTOMATED -result1 Official build 5000 [OK] diff --git a/vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-table.golden b/vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-table.golden deleted file mode 100644 index 72784fd01..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/testdata/search-context-write-table.golden +++ /dev/null @@ -1,3 +0,0 @@ -NAME DESCRIPTION STARS OFFICIAL AUTOMATED -result1 Official build 5000 [OK] -result2 Not official 5 [OK] diff --git a/vendor/github.com/docker/cli/cli/command/formatter/testdata/service-context-write-raw.golden b/vendor/github.com/docker/cli/cli/command/formatter/testdata/service-context-write-raw.golden deleted file mode 100644 index d62b9a244..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/testdata/service-context-write-raw.golden +++ /dev/null @@ -1,14 +0,0 @@ -id: id_baz -name: baz -mode: global -replicas: 2/4 -image: -ports: *:80->8080/tcp - -id: id_bar -name: bar -mode: replicated -replicas: 2/4 -image: -ports: *:80->8080/tcp - diff --git a/vendor/github.com/docker/cli/cli/command/formatter/testdata/task-context-write-table-custom.golden b/vendor/github.com/docker/cli/cli/command/formatter/testdata/task-context-write-table-custom.golden deleted file mode 100644 index 0f931ea98..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/testdata/task-context-write-table-custom.golden +++ /dev/null @@ -1,3 +0,0 @@ -NAME NODE PORTS -foobar_baz foo1 -foobar_bar foo2 diff --git a/vendor/github.com/docker/cli/cli/command/formatter/volume.go b/vendor/github.com/docker/cli/cli/command/formatter/volume.go deleted file mode 100644 index 342f2fb93..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/volume.go +++ /dev/null @@ -1,131 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - - "github.com/docker/docker/api/types" - units "github.com/docker/go-units" -) - -const ( - defaultVolumeQuietFormat = "{{.Name}}" - defaultVolumeTableFormat = "table {{.Driver}}\t{{.Name}}" - - volumeNameHeader = "VOLUME NAME" - mountpointHeader = "MOUNTPOINT" - linksHeader = "LINKS" - // Status header ? -) - -// NewVolumeFormat returns a format for use with a volume Context -func NewVolumeFormat(source string, quiet bool) Format { - switch source { - case TableFormatKey: - if quiet { - return defaultVolumeQuietFormat - } - return defaultVolumeTableFormat - case RawFormatKey: - if quiet { - return `name: {{.Name}}` - } - return `name: {{.Name}}\ndriver: {{.Driver}}\n` - } - return Format(source) -} - -// VolumeWrite writes formatted volumes using the Context -func VolumeWrite(ctx Context, volumes []*types.Volume) error { - render := func(format func(subContext subContext) error) error { - for _, volume := range volumes { - if err := format(&volumeContext{v: *volume}); err != nil { - return err - } - } - return nil - } - return ctx.Write(newVolumeContext(), render) -} - -type volumeHeaderContext map[string]string - -func (c volumeHeaderContext) Label(name string) string { - n := strings.Split(name, ".") - r := strings.NewReplacer("-", " ", "_", " ") - h := r.Replace(n[len(n)-1]) - - return h -} - -type volumeContext struct { - HeaderContext - v types.Volume -} - -func newVolumeContext() *volumeContext { - volumeCtx := volumeContext{} - volumeCtx.header = volumeHeaderContext{ - "Name": volumeNameHeader, - "Driver": driverHeader, - "Scope": scopeHeader, - "Mountpoint": mountpointHeader, - "Labels": labelsHeader, - "Links": linksHeader, - "Size": sizeHeader, - } - return &volumeCtx -} - -func (c *volumeContext) MarshalJSON() ([]byte, error) { - return marshalJSON(c) -} - -func (c *volumeContext) Name() string { - return c.v.Name -} - -func (c *volumeContext) Driver() string { - return c.v.Driver -} - -func (c *volumeContext) Scope() string { - return c.v.Scope -} - -func (c *volumeContext) Mountpoint() string { - return c.v.Mountpoint -} - -func (c *volumeContext) Labels() string { - if c.v.Labels == nil { - return "" - } - - var joinLabels []string - for k, v := range c.v.Labels { - joinLabels = append(joinLabels, fmt.Sprintf("%s=%s", k, v)) - } - return strings.Join(joinLabels, ",") -} - -func (c *volumeContext) Label(name string) string { - if c.v.Labels == nil { - return "" - } - return c.v.Labels[name] -} - -func (c *volumeContext) Links() string { - if c.v.UsageData == nil { - return "N/A" - } - return fmt.Sprintf("%d", c.v.UsageData.RefCount) -} - -func (c *volumeContext) Size() string { - if c.v.UsageData == nil { - return "N/A" - } - return units.HumanSize(float64(c.v.UsageData.Size)) -} diff --git a/vendor/github.com/docker/cli/cli/command/formatter/volume_test.go b/vendor/github.com/docker/cli/cli/command/formatter/volume_test.go deleted file mode 100644 index f2c21a83c..000000000 --- a/vendor/github.com/docker/cli/cli/command/formatter/volume_test.go +++ /dev/null @@ -1,183 +0,0 @@ -package formatter - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" - "testing" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/stringid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestVolumeContext(t *testing.T) { - volumeName := stringid.GenerateRandomID() - - var ctx volumeContext - cases := []struct { - volumeCtx volumeContext - expValue string - call func() string - }{ - {volumeContext{ - v: types.Volume{Name: volumeName}, - }, volumeName, ctx.Name}, - {volumeContext{ - v: types.Volume{Driver: "driver_name"}, - }, "driver_name", ctx.Driver}, - {volumeContext{ - v: types.Volume{Scope: "local"}, - }, "local", ctx.Scope}, - {volumeContext{ - v: types.Volume{Mountpoint: "mountpoint"}, - }, "mountpoint", ctx.Mountpoint}, - {volumeContext{ - v: types.Volume{}, - }, "", ctx.Labels}, - {volumeContext{ - v: types.Volume{Labels: map[string]string{"label1": "value1", "label2": "value2"}}, - }, "label1=value1,label2=value2", ctx.Labels}, - } - - for _, c := range cases { - ctx = c.volumeCtx - v := c.call() - if strings.Contains(v, ",") { - compareMultipleValues(t, v, c.expValue) - } else if v != c.expValue { - t.Fatalf("Expected %s, was %s\n", c.expValue, v) - } - } -} - -func TestVolumeContextWrite(t *testing.T) { - cases := []struct { - context Context - expected string - }{ - - // Errors - { - Context{Format: "{{InvalidFunction}}"}, - `Template parsing error: template: :1: function "InvalidFunction" not defined -`, - }, - { - Context{Format: "{{nil}}"}, - `Template parsing error: template: :1:2: executing "" at : nil is not a command -`, - }, - // Table format - { - Context{Format: NewVolumeFormat("table", false)}, - `DRIVER VOLUME NAME -foo foobar_baz -bar foobar_bar -`, - }, - { - Context{Format: NewVolumeFormat("table", true)}, - `foobar_baz -foobar_bar -`, - }, - { - Context{Format: NewVolumeFormat("table {{.Name}}", false)}, - `VOLUME NAME -foobar_baz -foobar_bar -`, - }, - { - Context{Format: NewVolumeFormat("table {{.Name}}", true)}, - `VOLUME NAME -foobar_baz -foobar_bar -`, - }, - // Raw Format - { - Context{Format: NewVolumeFormat("raw", false)}, - `name: foobar_baz -driver: foo - -name: foobar_bar -driver: bar - -`, - }, - { - Context{Format: NewVolumeFormat("raw", true)}, - `name: foobar_baz -name: foobar_bar -`, - }, - // Custom Format - { - Context{Format: NewVolumeFormat("{{.Name}}", false)}, - `foobar_baz -foobar_bar -`, - }, - } - - for _, testcase := range cases { - volumes := []*types.Volume{ - {Name: "foobar_baz", Driver: "foo"}, - {Name: "foobar_bar", Driver: "bar"}, - } - out := bytes.NewBufferString("") - testcase.context.Output = out - err := VolumeWrite(testcase.context, volumes) - if err != nil { - assert.EqualError(t, err, testcase.expected) - } else { - assert.Equal(t, testcase.expected, out.String()) - } - } -} - -func TestVolumeContextWriteJSON(t *testing.T) { - volumes := []*types.Volume{ - {Driver: "foo", Name: "foobar_baz"}, - {Driver: "bar", Name: "foobar_bar"}, - } - expectedJSONs := []map[string]interface{}{ - {"Driver": "foo", "Labels": "", "Links": "N/A", "Mountpoint": "", "Name": "foobar_baz", "Scope": "", "Size": "N/A"}, - {"Driver": "bar", "Labels": "", "Links": "N/A", "Mountpoint": "", "Name": "foobar_bar", "Scope": "", "Size": "N/A"}, - } - out := bytes.NewBufferString("") - err := VolumeWrite(Context{Format: "{{json .}}", Output: out}, volumes) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var m map[string]interface{} - err := json.Unmarshal([]byte(line), &m) - require.NoError(t, err, msg) - assert.Equal(t, expectedJSONs[i], m, msg) - } -} - -func TestVolumeContextWriteJSONField(t *testing.T) { - volumes := []*types.Volume{ - {Driver: "foo", Name: "foobar_baz"}, - {Driver: "bar", Name: "foobar_bar"}, - } - out := bytes.NewBufferString("") - err := VolumeWrite(Context{Format: "{{json .Name}}", Output: out}, volumes) - if err != nil { - t.Fatal(err) - } - for i, line := range strings.Split(strings.TrimSpace(out.String()), "\n") { - msg := fmt.Sprintf("Output: line %d: %s", i, line) - var s string - err := json.Unmarshal([]byte(line), &s) - require.NoError(t, err, msg) - assert.Equal(t, volumes[i].Name, s, msg) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/idresolver/client_test.go b/vendor/github.com/docker/cli/cli/command/idresolver/client_test.go deleted file mode 100644 index f84683b90..000000000 --- a/vendor/github.com/docker/cli/cli/command/idresolver/client_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package idresolver - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - nodeInspectFunc func(string) (swarm.Node, []byte, error) - serviceInspectFunc func(string) (swarm.Service, []byte, error) -} - -func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) { - if cli.nodeInspectFunc != nil { - return cli.nodeInspectFunc(nodeID) - } - return swarm.Node{}, []byte{}, nil -} - -func (cli *fakeClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { - if cli.serviceInspectFunc != nil { - return cli.serviceInspectFunc(serviceID) - } - return swarm.Service{}, []byte{}, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/idresolver/idresolver.go b/vendor/github.com/docker/cli/cli/command/idresolver/idresolver.go deleted file mode 100644 index 6088b64b5..000000000 --- a/vendor/github.com/docker/cli/cli/command/idresolver/idresolver.go +++ /dev/null @@ -1,70 +0,0 @@ -package idresolver - -import ( - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/pkg/errors" -) - -// IDResolver provides ID to Name resolution. -type IDResolver struct { - client client.APIClient - noResolve bool - cache map[string]string -} - -// New creates a new IDResolver. -func New(client client.APIClient, noResolve bool) *IDResolver { - return &IDResolver{ - client: client, - noResolve: noResolve, - cache: make(map[string]string), - } -} - -func (r *IDResolver) get(ctx context.Context, t interface{}, id string) (string, error) { - switch t.(type) { - case swarm.Node: - node, _, err := r.client.NodeInspectWithRaw(ctx, id) - if err != nil { - return id, nil - } - if node.Spec.Annotations.Name != "" { - return node.Spec.Annotations.Name, nil - } - if node.Description.Hostname != "" { - return node.Description.Hostname, nil - } - return id, nil - case swarm.Service: - service, _, err := r.client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{}) - if err != nil { - return id, nil - } - return service.Spec.Annotations.Name, nil - default: - return "", errors.Errorf("unsupported type") - } - -} - -// Resolve will attempt to resolve an ID to a Name by querying the manager. -// Results are stored into a cache. -// If the `-n` flag is used in the command-line, resolution is disabled. -func (r *IDResolver) Resolve(ctx context.Context, t interface{}, id string) (string, error) { - if r.noResolve { - return id, nil - } - if name, ok := r.cache[id]; ok { - return name, nil - } - name, err := r.get(ctx, t, id) - if err != nil { - return "", err - } - r.cache[id] = name - return name, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/idresolver/idresolver_test.go b/vendor/github.com/docker/cli/cli/command/idresolver/idresolver_test.go deleted file mode 100644 index 98bd306d1..000000000 --- a/vendor/github.com/docker/cli/cli/command/idresolver/idresolver_test.go +++ /dev/null @@ -1,144 +0,0 @@ -package idresolver - -import ( - "testing" - - "github.com/docker/docker/api/types/swarm" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestResolveError(t *testing.T) { - cli := &fakeClient{ - nodeInspectFunc: func(nodeID string) (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting node") - }, - } - - idResolver := New(cli, false) - _, err := idResolver.Resolve(context.Background(), struct{}{}, "nodeID") - - assert.EqualError(t, err, "unsupported type") -} - -func TestResolveWithNoResolveOption(t *testing.T) { - resolved := false - cli := &fakeClient{ - nodeInspectFunc: func(nodeID string) (swarm.Node, []byte, error) { - resolved = true - return swarm.Node{}, []byte{}, nil - }, - serviceInspectFunc: func(serviceID string) (swarm.Service, []byte, error) { - resolved = true - return swarm.Service{}, []byte{}, nil - }, - } - - idResolver := New(cli, true) - id, err := idResolver.Resolve(context.Background(), swarm.Node{}, "nodeID") - - assert.NoError(t, err) - assert.Equal(t, "nodeID", id) - assert.False(t, resolved) -} - -func TestResolveWithCache(t *testing.T) { - inspectCounter := 0 - cli := &fakeClient{ - nodeInspectFunc: func(nodeID string) (swarm.Node, []byte, error) { - inspectCounter++ - return *Node(NodeName("node-foo")), []byte{}, nil - }, - } - - idResolver := New(cli, false) - - ctx := context.Background() - for i := 0; i < 2; i++ { - id, err := idResolver.Resolve(ctx, swarm.Node{}, "nodeID") - assert.NoError(t, err) - assert.Equal(t, "node-foo", id) - } - - assert.Equal(t, 1, inspectCounter) -} - -func TestResolveNode(t *testing.T) { - testCases := []struct { - nodeID string - nodeInspectFunc func(string) (swarm.Node, []byte, error) - expectedID string - }{ - { - nodeID: "nodeID", - nodeInspectFunc: func(string) (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting node") - }, - expectedID: "nodeID", - }, - { - nodeID: "nodeID", - nodeInspectFunc: func(string) (swarm.Node, []byte, error) { - return *Node(NodeName("node-foo")), []byte{}, nil - }, - expectedID: "node-foo", - }, - { - nodeID: "nodeID", - nodeInspectFunc: func(string) (swarm.Node, []byte, error) { - return *Node(NodeName(""), Hostname("node-hostname")), []byte{}, nil - }, - expectedID: "node-hostname", - }, - } - - ctx := context.Background() - for _, tc := range testCases { - cli := &fakeClient{ - nodeInspectFunc: tc.nodeInspectFunc, - } - idResolver := New(cli, false) - id, err := idResolver.Resolve(ctx, swarm.Node{}, tc.nodeID) - - assert.NoError(t, err) - assert.Equal(t, tc.expectedID, id) - } -} - -func TestResolveService(t *testing.T) { - testCases := []struct { - serviceID string - serviceInspectFunc func(string) (swarm.Service, []byte, error) - expectedID string - }{ - { - serviceID: "serviceID", - serviceInspectFunc: func(string) (swarm.Service, []byte, error) { - return swarm.Service{}, []byte{}, errors.Errorf("error inspecting service") - }, - expectedID: "serviceID", - }, - { - serviceID: "serviceID", - serviceInspectFunc: func(string) (swarm.Service, []byte, error) { - return *Service(ServiceName("service-foo")), []byte{}, nil - }, - expectedID: "service-foo", - }, - } - - ctx := context.Background() - for _, tc := range testCases { - cli := &fakeClient{ - serviceInspectFunc: tc.serviceInspectFunc, - } - idResolver := New(cli, false) - id, err := idResolver.Resolve(ctx, swarm.Service{}, tc.serviceID) - - assert.NoError(t, err) - assert.Equal(t, tc.expectedID, id) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build.go b/vendor/github.com/docker/cli/cli/command/image/build.go deleted file mode 100644 index 19865717a..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build.go +++ /dev/null @@ -1,586 +0,0 @@ -package image - -import ( - "archive/tar" - "bufio" - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "regexp" - "runtime" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image/build" - "github.com/docker/cli/opts" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/idtools" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/urlutil" - units "github.com/docker/go-units" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type buildOptions struct { - context string - dockerfileName string - tags opts.ListOpts - labels opts.ListOpts - buildArgs opts.ListOpts - extraHosts opts.ListOpts - ulimits *opts.UlimitOpt - memory opts.MemBytes - memorySwap opts.MemSwapBytes - shmSize opts.MemBytes - cpuShares int64 - cpuPeriod int64 - cpuQuota int64 - cpuSetCpus string - cpuSetMems string - cgroupParent string - isolation string - quiet bool - noCache bool - rm bool - forceRm bool - pull bool - cacheFrom []string - compress bool - securityOpt []string - networkMode string - squash bool - target string - imageIDFile string - stream bool -} - -// dockerfileFromStdin returns true when the user specified that the Dockerfile -// should be read from stdin instead of a file -func (o buildOptions) dockerfileFromStdin() bool { - return o.dockerfileName == "-" -} - -// contextFromStdin returns true when the user specified that the build context -// should be read from stdin -func (o buildOptions) contextFromStdin() bool { - return o.context == "-" -} - -func newBuildOptions() buildOptions { - ulimits := make(map[string]*units.Ulimit) - return buildOptions{ - tags: opts.NewListOpts(validateTag), - buildArgs: opts.NewListOpts(opts.ValidateEnv), - ulimits: opts.NewUlimitOpt(&ulimits), - labels: opts.NewListOpts(opts.ValidateEnv), - extraHosts: opts.NewListOpts(opts.ValidateExtraHost), - } -} - -// NewBuildCommand creates a new `docker build` command -func NewBuildCommand(dockerCli command.Cli) *cobra.Command { - options := newBuildOptions() - - cmd := &cobra.Command{ - Use: "build [OPTIONS] PATH | URL | -", - Short: "Build an image from a Dockerfile", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.context = args[0] - return runBuild(dockerCli, options) - }, - } - - flags := cmd.Flags() - - flags.VarP(&options.tags, "tag", "t", "Name and optionally a tag in the 'name:tag' format") - flags.Var(&options.buildArgs, "build-arg", "Set build-time variables") - flags.Var(options.ulimits, "ulimit", "Ulimit options") - flags.StringVarP(&options.dockerfileName, "file", "f", "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')") - flags.VarP(&options.memory, "memory", "m", "Memory limit") - flags.Var(&options.memorySwap, "memory-swap", "Swap limit equal to memory plus swap: '-1' to enable unlimited swap") - flags.Var(&options.shmSize, "shm-size", "Size of /dev/shm") - flags.Int64VarP(&options.cpuShares, "cpu-shares", "c", 0, "CPU shares (relative weight)") - flags.Int64Var(&options.cpuPeriod, "cpu-period", 0, "Limit the CPU CFS (Completely Fair Scheduler) period") - flags.Int64Var(&options.cpuQuota, "cpu-quota", 0, "Limit the CPU CFS (Completely Fair Scheduler) quota") - flags.StringVar(&options.cpuSetCpus, "cpuset-cpus", "", "CPUs in which to allow execution (0-3, 0,1)") - flags.StringVar(&options.cpuSetMems, "cpuset-mems", "", "MEMs in which to allow execution (0-3, 0,1)") - flags.StringVar(&options.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container") - flags.StringVar(&options.isolation, "isolation", "", "Container isolation technology") - flags.Var(&options.labels, "label", "Set metadata for an image") - flags.BoolVar(&options.noCache, "no-cache", false, "Do not use cache when building the image") - flags.BoolVar(&options.rm, "rm", true, "Remove intermediate containers after a successful build") - flags.BoolVar(&options.forceRm, "force-rm", false, "Always remove intermediate containers") - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Suppress the build output and print image ID on success") - flags.BoolVar(&options.pull, "pull", false, "Always attempt to pull a newer version of the image") - flags.StringSliceVar(&options.cacheFrom, "cache-from", []string{}, "Images to consider as cache sources") - flags.BoolVar(&options.compress, "compress", false, "Compress the build context using gzip") - flags.StringSliceVar(&options.securityOpt, "security-opt", []string{}, "Security options") - flags.StringVar(&options.networkMode, "network", "default", "Set the networking mode for the RUN instructions during build") - flags.SetAnnotation("network", "version", []string{"1.25"}) - flags.Var(&options.extraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)") - flags.StringVar(&options.target, "target", "", "Set the target build stage to build.") - flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file") - - command.AddTrustVerificationFlags(flags) - - flags.BoolVar(&options.squash, "squash", false, "Squash newly built layers into a single new layer") - flags.SetAnnotation("squash", "experimental", nil) - flags.SetAnnotation("squash", "version", []string{"1.25"}) - - flags.BoolVar(&options.stream, "stream", false, "Stream attaches to server to negotiate build context") - flags.SetAnnotation("stream", "experimental", nil) - flags.SetAnnotation("stream", "version", []string{"1.31"}) - - return cmd -} - -// lastProgressOutput is the same as progress.Output except -// that it only output with the last update. It is used in -// non terminal scenarios to suppress verbose messages -type lastProgressOutput struct { - output progress.Output -} - -// WriteProgress formats progress information from a ProgressReader. -func (out *lastProgressOutput) WriteProgress(prog progress.Progress) error { - if !prog.LastUpdate { - return nil - } - - return out.output.WriteProgress(prog) -} - -// nolint: gocyclo -func runBuild(dockerCli command.Cli, options buildOptions) error { - var ( - buildCtx io.ReadCloser - dockerfileCtx io.ReadCloser - err error - contextDir string - tempDir string - relDockerfile string - progBuff io.Writer - buildBuff io.Writer - remote string - ) - - if options.dockerfileFromStdin() { - if options.contextFromStdin() { - return errors.New("invalid argument: can't use stdin for both build context and dockerfile") - } - dockerfileCtx = dockerCli.In() - } - - specifiedContext := options.context - progBuff = dockerCli.Out() - buildBuff = dockerCli.Out() - if options.quiet { - progBuff = bytes.NewBuffer(nil) - buildBuff = bytes.NewBuffer(nil) - } - if options.imageIDFile != "" { - // Avoid leaving a stale file if we eventually fail - if err := os.Remove(options.imageIDFile); err != nil && !os.IsNotExist(err) { - return errors.Wrap(err, "Removing image ID file") - } - } - - switch { - case options.contextFromStdin(): - // buildCtx is tar archive. if stdin was dockerfile then it is wrapped - buildCtx, relDockerfile, err = build.GetContextFromReader(dockerCli.In(), options.dockerfileName) - case isLocalDir(specifiedContext): - contextDir, relDockerfile, err = build.GetContextFromLocalDir(specifiedContext, options.dockerfileName) - case urlutil.IsGitURL(specifiedContext): - tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, options.dockerfileName) - case urlutil.IsURL(specifiedContext): - buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, specifiedContext, options.dockerfileName) - default: - return errors.Errorf("unable to prepare context: path %q not found", specifiedContext) - } - - if err != nil { - if options.quiet && urlutil.IsURL(specifiedContext) { - fmt.Fprintln(dockerCli.Err(), progBuff) - } - return errors.Errorf("unable to prepare context: %s", err) - } - - if tempDir != "" { - defer os.RemoveAll(tempDir) - contextDir = tempDir - } - - // read from a directory into tar archive - if buildCtx == nil && !options.stream { - excludes, err := build.ReadDockerignore(contextDir) - if err != nil { - return err - } - - if err := build.ValidateContextDirectory(contextDir, excludes); err != nil { - return errors.Errorf("error checking context: '%s'.", err) - } - - // And canonicalize dockerfile name to a platform-independent one - relDockerfile, err = archive.CanonicalTarNameForPath(relDockerfile) - if err != nil { - return errors.Errorf("cannot canonicalize dockerfile path %s: %v", relDockerfile, err) - } - - excludes = build.TrimBuildFilesFromExcludes(excludes, relDockerfile, options.dockerfileFromStdin()) - buildCtx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{ - ExcludePatterns: excludes, - ChownOpts: &idtools.IDPair{UID: 0, GID: 0}, - }) - if err != nil { - return err - } - } - - // replace Dockerfile if it was added from stdin and there is archive context - if dockerfileCtx != nil && buildCtx != nil { - buildCtx, relDockerfile, err = build.AddDockerfileToBuildContext(dockerfileCtx, buildCtx) - if err != nil { - return err - } - } - - // if streaming and dockerfile was not from stdin then read from file - // to the same reader that is usually stdin - if options.stream && dockerfileCtx == nil { - dockerfileCtx, err = os.Open(relDockerfile) - if err != nil { - return errors.Wrapf(err, "failed to open %s", relDockerfile) - } - defer dockerfileCtx.Close() - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - var resolvedTags []*resolvedTag - if command.IsTrusted() { - translator := func(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) { - return TrustedReference(ctx, dockerCli, ref, nil) - } - // if there is a tar wrapper, the dockerfile needs to be replaced inside it - if buildCtx != nil { - // Wrap the tar archive to replace the Dockerfile entry with the rewritten - // Dockerfile which uses trusted pulls. - buildCtx = replaceDockerfileTarWrapper(ctx, buildCtx, relDockerfile, translator, &resolvedTags) - } else if dockerfileCtx != nil { - // if there was not archive context still do the possible replacements in Dockerfile - newDockerfile, _, err := rewriteDockerfileFrom(ctx, dockerfileCtx, translator) - if err != nil { - return err - } - dockerfileCtx = ioutil.NopCloser(bytes.NewBuffer(newDockerfile)) - } - } - - if options.compress { - buildCtx, err = build.Compress(buildCtx) - if err != nil { - return err - } - } - - // Setup an upload progress bar - progressOutput := streamformatter.NewProgressOutput(progBuff) - if !dockerCli.Out().IsTerminal() { - progressOutput = &lastProgressOutput{output: progressOutput} - } - - // if up to this point nothing has set the context then we must have have - // another way for sending it(streaming) and set the context to the Dockerfile - if dockerfileCtx != nil && buildCtx == nil { - buildCtx = dockerfileCtx - } - - s, err := trySession(dockerCli, contextDir) - if err != nil { - return err - } - - var body io.Reader - if buildCtx != nil && !options.stream { - body = progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon") - } - - // add context stream to the session - if options.stream && s != nil { - syncDone := make(chan error) // used to signal first progress reporting completed. - // progress would also send errors but don't need it here as errors - // are handled by session.Run() and ImageBuild() - if err := addDirToSession(s, contextDir, progressOutput, syncDone); err != nil { - return err - } - - buf := newBufferedWriter(syncDone, buildBuff) - defer func() { - select { - case <-buf.flushed: - case <-ctx.Done(): - } - }() - buildBuff = buf - - remote = clientSessionRemote - body = buildCtx - } - - configFile := dockerCli.ConfigFile() - authConfigs, _ := configFile.GetAllCredentials() - buildOptions := types.ImageBuildOptions{ - Memory: options.memory.Value(), - MemorySwap: options.memorySwap.Value(), - Tags: options.tags.GetAll(), - SuppressOutput: options.quiet, - NoCache: options.noCache, - Remove: options.rm, - ForceRemove: options.forceRm, - PullParent: options.pull, - Isolation: container.Isolation(options.isolation), - CPUSetCPUs: options.cpuSetCpus, - CPUSetMems: options.cpuSetMems, - CPUShares: options.cpuShares, - CPUQuota: options.cpuQuota, - CPUPeriod: options.cpuPeriod, - CgroupParent: options.cgroupParent, - Dockerfile: relDockerfile, - ShmSize: options.shmSize.Value(), - Ulimits: options.ulimits.GetList(), - BuildArgs: configFile.ParseProxyConfig(dockerCli.Client().DaemonHost(), options.buildArgs.GetAll()), - AuthConfigs: authConfigs, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - CacheFrom: options.cacheFrom, - SecurityOpt: options.securityOpt, - NetworkMode: options.networkMode, - Squash: options.squash, - ExtraHosts: options.extraHosts.GetAll(), - Target: options.target, - RemoteContext: remote, - } - - if s != nil { - go func() { - logrus.Debugf("running session: %v", s.UUID()) - if err := s.Run(ctx, dockerCli.Client().DialSession); err != nil { - logrus.Error(err) - cancel() // cancel progress context - } - }() - buildOptions.SessionID = s.UUID() - } - - response, err := dockerCli.Client().ImageBuild(ctx, body, buildOptions) - if err != nil { - if options.quiet { - fmt.Fprintf(dockerCli.Err(), "%s", progBuff) - } - cancel() - return err - } - defer response.Body.Close() - - imageID := "" - aux := func(auxJSON *json.RawMessage) { - var result types.BuildResult - if err := json.Unmarshal(*auxJSON, &result); err != nil { - fmt.Fprintf(dockerCli.Err(), "Failed to parse aux message: %s", err) - } else { - imageID = result.ID - } - } - - err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, dockerCli.Out().FD(), dockerCli.Out().IsTerminal(), aux) - if err != nil { - if jerr, ok := err.(*jsonmessage.JSONError); ok { - // If no error code is set, default to 1 - if jerr.Code == 0 { - jerr.Code = 1 - } - if options.quiet { - fmt.Fprintf(dockerCli.Err(), "%s%s", progBuff, buildBuff) - } - return cli.StatusError{Status: jerr.Message, StatusCode: jerr.Code} - } - return err - } - - // Windows: show error message about modified file permissions if the - // daemon isn't running Windows. - if response.OSType != "windows" && runtime.GOOS == "windows" && !options.quiet { - fmt.Fprintln(dockerCli.Out(), "SECURITY WARNING: You are building a Docker "+ - "image from Windows against a non-Windows Docker host. All files and "+ - "directories added to build context will have '-rwxr-xr-x' permissions. "+ - "It is recommended to double check and reset permissions for sensitive "+ - "files and directories.") - } - - // Everything worked so if -q was provided the output from the daemon - // should be just the image ID and we'll print that to stdout. - if options.quiet { - imageID = fmt.Sprintf("%s", buildBuff) - fmt.Fprintf(dockerCli.Out(), imageID) - } - - if options.imageIDFile != "" { - if imageID == "" { - return errors.Errorf("Server did not provide an image ID. Cannot write %s", options.imageIDFile) - } - if err := ioutil.WriteFile(options.imageIDFile, []byte(imageID), 0666); err != nil { - return err - } - } - if command.IsTrusted() { - // Since the build was successful, now we must tag any of the resolved - // images from the above Dockerfile rewrite. - for _, resolved := range resolvedTags { - if err := TagTrusted(ctx, dockerCli, resolved.digestRef, resolved.tagRef); err != nil { - return err - } - } - } - - return nil -} - -func isLocalDir(c string) bool { - _, err := os.Stat(c) - return err == nil -} - -type translatorFunc func(context.Context, reference.NamedTagged) (reference.Canonical, error) - -// validateTag checks if the given image name can be resolved. -func validateTag(rawRepo string) (string, error) { - _, err := reference.ParseNormalizedNamed(rawRepo) - if err != nil { - return "", err - } - - return rawRepo, nil -} - -var dockerfileFromLinePattern = regexp.MustCompile(`(?i)^[\s]*FROM[ \f\r\t\v]+(?P[^ \f\r\t\v\n#]+)`) - -// resolvedTag records the repository, tag, and resolved digest reference -// from a Dockerfile rewrite. -type resolvedTag struct { - digestRef reference.Canonical - tagRef reference.NamedTagged -} - -// rewriteDockerfileFrom rewrites the given Dockerfile by resolving images in -// "FROM " instructions to a digest reference. `translator` is a -// function that takes a repository name and tag reference and returns a -// trusted digest reference. -func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator translatorFunc) (newDockerfile []byte, resolvedTags []*resolvedTag, err error) { - scanner := bufio.NewScanner(dockerfile) - buf := bytes.NewBuffer(nil) - - // Scan the lines of the Dockerfile, looking for a "FROM" line. - for scanner.Scan() { - line := scanner.Text() - - matches := dockerfileFromLinePattern.FindStringSubmatch(line) - if matches != nil && matches[1] != api.NoBaseImageSpecifier { - // Replace the line with a resolved "FROM repo@digest" - var ref reference.Named - ref, err = reference.ParseNormalizedNamed(matches[1]) - if err != nil { - return nil, nil, err - } - ref = reference.TagNameOnly(ref) - if ref, ok := ref.(reference.NamedTagged); ok && command.IsTrusted() { - trustedRef, err := translator(ctx, ref) - if err != nil { - return nil, nil, err - } - - line = dockerfileFromLinePattern.ReplaceAllLiteralString(line, fmt.Sprintf("FROM %s", reference.FamiliarString(trustedRef))) - resolvedTags = append(resolvedTags, &resolvedTag{ - digestRef: trustedRef, - tagRef: ref, - }) - } - } - - _, err := fmt.Fprintln(buf, line) - if err != nil { - return nil, nil, err - } - } - - return buf.Bytes(), resolvedTags, scanner.Err() -} - -// replaceDockerfileTarWrapper wraps the given input tar archive stream and -// replaces the entry with the given Dockerfile name with the contents of the -// new Dockerfile. Returns a new tar archive stream with the replaced -// Dockerfile. -func replaceDockerfileTarWrapper(ctx context.Context, inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag) io.ReadCloser { - pipeReader, pipeWriter := io.Pipe() - go func() { - tarReader := tar.NewReader(inputTarStream) - tarWriter := tar.NewWriter(pipeWriter) - - defer inputTarStream.Close() - - for { - hdr, err := tarReader.Next() - if err == io.EOF { - // Signals end of archive. - tarWriter.Close() - pipeWriter.Close() - return - } - if err != nil { - pipeWriter.CloseWithError(err) - return - } - - content := io.Reader(tarReader) - if hdr.Name == dockerfileName { - // This entry is the Dockerfile. Since the tar archive was - // generated from a directory on the local filesystem, the - // Dockerfile will only appear once in the archive. - var newDockerfile []byte - newDockerfile, *resolvedTags, err = rewriteDockerfileFrom(ctx, content, translator) - if err != nil { - pipeWriter.CloseWithError(err) - return - } - hdr.Size = int64(len(newDockerfile)) - content = bytes.NewBuffer(newDockerfile) - } - - if err := tarWriter.WriteHeader(hdr); err != nil { - pipeWriter.CloseWithError(err) - return - } - - if _, err := io.Copy(tarWriter, content); err != nil { - pipeWriter.CloseWithError(err) - return - } - } - }() - - return pipeReader -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build/context.go b/vendor/github.com/docker/cli/cli/command/image/build/context.go deleted file mode 100644 index a98cd7b23..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build/context.go +++ /dev/null @@ -1,402 +0,0 @@ -package build - -import ( - "archive/tar" - "bufio" - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "time" - - "github.com/docker/docker/builder/remotecontext/git" - "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/pools" - "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "github.com/pkg/errors" -) - -const ( - // DefaultDockerfileName is the Default filename with Docker commands, read by docker build - DefaultDockerfileName string = "Dockerfile" - // archiveHeaderSize is the number of bytes in an archive header - archiveHeaderSize = 512 -) - -// 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 { - contextRoot, err := getContextRoot(srcPath) - if err != nil { - return err - } - return filepath.Walk(contextRoot, func(filePath string, f os.FileInfo, err error) error { - if err != nil { - if os.IsPermission(err) { - return errors.Errorf("can't stat '%s'", filePath) - } - if os.IsNotExist(err) { - return nil - } - return err - } - - // skip this directory/file if it's not in the path, it won't get added to the context - if relFilePath, err := filepath.Rel(contextRoot, 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 - } - - // 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 errors.Errorf("no permission to read from '%s'", filePath) - } - currentFile.Close() - } - return nil - }) -} - -// GetContextFromReader will read the contents of the given reader as either a -// Dockerfile or tar archive. Returns a tar archive used as a context and a -// path to the Dockerfile inside the tar. -func GetContextFromReader(r io.ReadCloser, dockerfileName string) (out io.ReadCloser, relDockerfile string, err error) { - buf := bufio.NewReader(r) - - magic, err := buf.Peek(archiveHeaderSize) - if err != nil && err != io.EOF { - return nil, "", errors.Errorf("failed to peek context header from STDIN: %v", err) - } - - if IsArchive(magic) { - return ioutils.NewReadCloserWrapper(buf, func() error { return r.Close() }), dockerfileName, nil - } - - if dockerfileName == "-" { - return nil, "", errors.New("build context is not an archive") - } - - // Input should be read as a Dockerfile. - tmpDir, err := ioutil.TempDir("", "docker-build-context-") - if err != nil { - return nil, "", errors.Errorf("unable to create temporary context directory: %v", err) - } - - f, err := os.Create(filepath.Join(tmpDir, DefaultDockerfileName)) - if err != nil { - return nil, "", err - } - _, err = io.Copy(f, buf) - if err != nil { - f.Close() - return nil, "", err - } - - if err := f.Close(); err != nil { - return nil, "", err - } - if err := r.Close(); err != nil { - return nil, "", err - } - - tar, err := archive.Tar(tmpDir, archive.Uncompressed) - if err != nil { - return nil, "", err - } - - return ioutils.NewReadCloserWrapper(tar, func() error { - err := tar.Close() - os.RemoveAll(tmpDir) - return err - }), DefaultDockerfileName, nil - -} - -// IsArchive checks for the magic bytes of a tar or any supported compression -// algorithm. -func IsArchive(header []byte) bool { - compression := archive.DetectCompression(header) - if compression != archive.Uncompressed { - return true - } - r := tar.NewReader(bytes.NewBuffer(header)) - _, err := r.Next() - return err == nil -} - -// GetContextFromGitURL uses a Git URL as context for a `docker build`. The -// git repo is cloned into a temporary directory used as the context directory. -// Returns the absolute path to the temporary context directory, the relative -// path of the dockerfile in that context directory, and a non-nil error on -// success. -func GetContextFromGitURL(gitURL, dockerfileName string) (string, string, error) { - if _, err := exec.LookPath("git"); err != nil { - return "", "", errors.Wrapf(err, "unable to find 'git'") - } - absContextDir, err := git.Clone(gitURL) - if err != nil { - return "", "", errors.Wrapf(err, "unable to 'git clone' to temporary context directory") - } - - absContextDir, err = ResolveAndValidateContextPath(absContextDir) - if err != nil { - return "", "", err - } - relDockerfile, err := getDockerfileRelPath(absContextDir, dockerfileName) - return absContextDir, relDockerfile, err -} - -// GetContextFromURL uses a remote URL as context for a `docker build`. The -// remote resource is downloaded as either a Dockerfile or a tar archive. -// Returns the tar archive used for the context and a path of the -// dockerfile inside the tar. -func GetContextFromURL(out io.Writer, remoteURL, dockerfileName string) (io.ReadCloser, string, error) { - response, err := getWithStatusError(remoteURL) - if err != nil { - return nil, "", errors.Errorf("unable to download remote context %s: %v", remoteURL, err) - } - progressOutput := streamformatter.NewProgressOutput(out) - - // Pass the response body through a progress reader. - progReader := progress.NewProgressReader(response.Body, progressOutput, response.ContentLength, "", fmt.Sprintf("Downloading build context from remote url: %s", remoteURL)) - - return GetContextFromReader(ioutils.NewReadCloserWrapper(progReader, func() error { return response.Body.Close() }), dockerfileName) -} - -// getWithStatusError does an http.Get() and returns an error if the -// status code is 4xx or 5xx. -func getWithStatusError(url string) (resp *http.Response, err error) { - if resp, err = http.Get(url); err != nil { - return nil, err - } - if resp.StatusCode < 400 { - return resp, nil - } - msg := fmt.Sprintf("failed to GET %s with status %s", url, resp.Status) - body, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - return nil, errors.Wrapf(err, msg+": error reading body") - } - return nil, errors.Errorf(msg+": %s", bytes.TrimSpace(body)) -} - -// GetContextFromLocalDir uses the given local directory as context for a -// `docker build`. Returns the absolute path to the local context directory, -// the relative path of the dockerfile in that context directory, and a non-nil -// error on success. -func GetContextFromLocalDir(localDir, dockerfileName string) (string, string, error) { - localDir, err := ResolveAndValidateContextPath(localDir) - if err != nil { - return "", "", err - } - - // When using a local context directory, and the Dockerfile is specified - // with the `-f/--file` option then it is considered relative to the - // current directory and not the context directory. - if dockerfileName != "" && dockerfileName != "-" { - if dockerfileName, err = filepath.Abs(dockerfileName); err != nil { - return "", "", errors.Errorf("unable to get absolute path to Dockerfile: %v", err) - } - } - - relDockerfile, err := getDockerfileRelPath(localDir, dockerfileName) - return localDir, relDockerfile, err -} - -// ResolveAndValidateContextPath uses the given context directory for a `docker build` -// and returns the absolute path to the context directory. -func ResolveAndValidateContextPath(givenContextDir string) (string, error) { - absContextDir, err := filepath.Abs(givenContextDir) - if err != nil { - return "", errors.Errorf("unable to get absolute context directory of given context directory %q: %v", givenContextDir, err) - } - - // The context dir might be a symbolic link, so follow it to the actual - // target directory. - // - // FIXME. We use isUNC (always false on non-Windows platforms) to workaround - // an issue in golang. On Windows, EvalSymLinks does not work on UNC file - // paths (those starting with \\). This hack means that when using links - // on UNC paths, they will not be followed. - if !isUNC(absContextDir) { - absContextDir, err = filepath.EvalSymlinks(absContextDir) - if err != nil { - return "", errors.Errorf("unable to evaluate symlinks in context path: %v", err) - } - } - - stat, err := os.Lstat(absContextDir) - if err != nil { - return "", errors.Errorf("unable to stat context directory %q: %v", absContextDir, err) - } - - if !stat.IsDir() { - return "", errors.Errorf("context must be a directory: %s", absContextDir) - } - return absContextDir, err -} - -// getDockerfileRelPath returns the dockerfile path relative to the context -// directory -func getDockerfileRelPath(absContextDir, givenDockerfile string) (string, error) { - var err error - - if givenDockerfile == "-" { - return givenDockerfile, nil - } - - absDockerfile := givenDockerfile - if absDockerfile == "" { - // No -f/--file was specified so use the default relative to the - // context directory. - absDockerfile = filepath.Join(absContextDir, DefaultDockerfileName) - - // Just to be nice ;-) look for 'dockerfile' too but only - // use it if we found it, otherwise ignore this check - if _, err = os.Lstat(absDockerfile); os.IsNotExist(err) { - altPath := filepath.Join(absContextDir, strings.ToLower(DefaultDockerfileName)) - if _, err = os.Lstat(altPath); err == nil { - absDockerfile = altPath - } - } - } - - // If not already an absolute path, the Dockerfile path should be joined to - // the base directory. - if !filepath.IsAbs(absDockerfile) { - absDockerfile = filepath.Join(absContextDir, absDockerfile) - } - - // Evaluate symlinks in the path to the Dockerfile too. - // - // FIXME. We use isUNC (always false on non-Windows platforms) to workaround - // an issue in golang. On Windows, EvalSymLinks does not work on UNC file - // paths (those starting with \\). This hack means that when using links - // on UNC paths, they will not be followed. - if !isUNC(absDockerfile) { - absDockerfile, err = filepath.EvalSymlinks(absDockerfile) - if err != nil { - return "", errors.Errorf("unable to evaluate symlinks in Dockerfile path: %v", err) - - } - } - - if _, err := os.Lstat(absDockerfile); err != nil { - if os.IsNotExist(err) { - return "", errors.Errorf("Cannot locate Dockerfile: %q", absDockerfile) - } - return "", errors.Errorf("unable to stat Dockerfile: %v", err) - } - - relDockerfile, err := filepath.Rel(absContextDir, absDockerfile) - if err != nil { - return "", errors.Errorf("unable to get relative Dockerfile path: %v", err) - } - - if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) { - return "", errors.Errorf("the Dockerfile (%s) must be within the build context", givenDockerfile) - } - - return relDockerfile, nil -} - -// isUNC returns true if the path is UNC (one starting \\). It always returns -// false on Linux. -func isUNC(path string) bool { - return runtime.GOOS == "windows" && strings.HasPrefix(path, `\\`) -} - -// AddDockerfileToBuildContext from a ReadCloser, returns a new archive and -// the relative path to the dockerfile in the context. -func AddDockerfileToBuildContext(dockerfileCtx io.ReadCloser, buildCtx io.ReadCloser) (io.ReadCloser, string, error) { - file, err := ioutil.ReadAll(dockerfileCtx) - dockerfileCtx.Close() - if err != nil { - return nil, "", err - } - now := time.Now() - hdrTmpl := &tar.Header{ - Mode: 0600, - Uid: 0, - Gid: 0, - ModTime: now, - Typeflag: tar.TypeReg, - AccessTime: now, - ChangeTime: now, - } - randomName := ".dockerfile." + stringid.GenerateRandomID()[:20] - - buildCtx = archive.ReplaceFileTarWrapper(buildCtx, map[string]archive.TarModifierFunc{ - // Add the dockerfile with a random filename - randomName: func(_ string, h *tar.Header, content io.Reader) (*tar.Header, []byte, error) { - return hdrTmpl, file, nil - }, - // Update .dockerignore to include the random filename - ".dockerignore": func(_ string, h *tar.Header, content io.Reader) (*tar.Header, []byte, error) { - if h == nil { - h = hdrTmpl - } - - b := &bytes.Buffer{} - if content != nil { - if _, err := b.ReadFrom(content); err != nil { - return nil, nil, err - } - } else { - b.WriteString(".dockerignore") - } - b.WriteString("\n" + randomName + "\n") - return h, b.Bytes(), nil - }, - }) - return buildCtx, randomName, nil -} - -// Compress the build context for sending to the API -func Compress(buildCtx io.ReadCloser) (io.ReadCloser, error) { - pipeReader, pipeWriter := io.Pipe() - - go func() { - compressWriter, err := archive.CompressStream(pipeWriter, archive.Gzip) - if err != nil { - pipeWriter.CloseWithError(err) - } - defer buildCtx.Close() - - if _, err := pools.Copy(compressWriter, buildCtx); err != nil { - pipeWriter.CloseWithError( - errors.Wrap(err, "failed to compress context")) - compressWriter.Close() - return - } - compressWriter.Close() - pipeWriter.Close() - }() - - return pipeReader, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build/context_test.go b/vendor/github.com/docker/cli/cli/command/image/build/context_test.go deleted file mode 100644 index a15b535ad..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build/context_test.go +++ /dev/null @@ -1,300 +0,0 @@ -package build - -import ( - "archive/tar" - "bytes" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/pkg/archive" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const dockerfileContents = "FROM busybox" - -var prepareEmpty = func(t *testing.T) (string, func()) { - return "", func() {} -} - -var prepareNoFiles = func(t *testing.T) (string, func()) { - return createTestTempDir(t, "", "builder-context-test") -} - -var prepareOneFile = func(t *testing.T) (string, func()) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777) - return contextDir, cleanup -} - -func testValidateContextDirectory(t *testing.T, prepare func(t *testing.T) (string, func()), excludes []string) { - contextDir, cleanup := prepare(t) - defer cleanup() - - err := ValidateContextDirectory(contextDir, excludes) - require.NoError(t, err) -} - -func TestGetContextFromLocalDirNoDockerfile(t *testing.T) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - defer cleanup() - - _, _, err := GetContextFromLocalDir(contextDir, "") - testutil.ErrorContains(t, err, "Dockerfile") -} - -func TestGetContextFromLocalDirNotExistingDir(t *testing.T) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - defer cleanup() - - fakePath := filepath.Join(contextDir, "fake") - - _, _, err := GetContextFromLocalDir(fakePath, "") - testutil.ErrorContains(t, err, "fake") -} - -func TestGetContextFromLocalDirNotExistingDockerfile(t *testing.T) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - defer cleanup() - - fakePath := filepath.Join(contextDir, "fake") - - _, _, err := GetContextFromLocalDir(contextDir, fakePath) - testutil.ErrorContains(t, err, "fake") -} - -func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) { - contextDir, dirCleanup := createTestTempDir(t, "", "builder-context-test") - defer dirCleanup() - - createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777) - - chdirCleanup := chdir(t, contextDir) - defer chdirCleanup() - - absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "") - require.NoError(t, err) - - assert.Equal(t, contextDir, absContextDir) - assert.Equal(t, DefaultDockerfileName, relDockerfile) -} - -func TestGetContextFromLocalDirWithDockerfile(t *testing.T) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - defer cleanup() - - createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777) - - absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "") - require.NoError(t, err) - - assert.Equal(t, contextDir, absContextDir) - assert.Equal(t, DefaultDockerfileName, relDockerfile) -} - -func TestGetContextFromLocalDirLocalFile(t *testing.T) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - defer cleanup() - - createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777) - testFilename := createTestTempFile(t, contextDir, "tmpTest", "test", 0777) - - absContextDir, relDockerfile, err := GetContextFromLocalDir(testFilename, "") - - if err == nil { - t.Fatalf("Error should not be nil") - } - - if absContextDir != "" { - t.Fatalf("Absolute directory path should be empty, got: %s", absContextDir) - } - - if relDockerfile != "" { - t.Fatalf("Relative path to Dockerfile should be empty, got: %s", relDockerfile) - } -} - -func TestGetContextFromLocalDirWithCustomDockerfile(t *testing.T) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - defer cleanup() - - chdirCleanup := chdir(t, contextDir) - defer chdirCleanup() - - createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777) - - absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, DefaultDockerfileName) - require.NoError(t, err) - - assert.Equal(t, contextDir, absContextDir) - assert.Equal(t, DefaultDockerfileName, relDockerfile) -} - -func TestGetContextFromReaderString(t *testing.T) { - tarArchive, relDockerfile, err := GetContextFromReader(ioutil.NopCloser(strings.NewReader(dockerfileContents)), "") - - if err != nil { - t.Fatalf("Error when executing GetContextFromReader: %s", err) - } - - tarReader := tar.NewReader(tarArchive) - - _, err = tarReader.Next() - - if err != nil { - t.Fatalf("Error when reading tar archive: %s", err) - } - - buff := new(bytes.Buffer) - buff.ReadFrom(tarReader) - contents := buff.String() - - _, err = tarReader.Next() - - if err != io.EOF { - t.Fatalf("Tar stream too long: %s", err) - } - - require.NoError(t, tarArchive.Close()) - - if dockerfileContents != contents { - t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContents, contents) - } - - if relDockerfile != DefaultDockerfileName { - t.Fatalf("Relative path not equals %s, got: %s", DefaultDockerfileName, relDockerfile) - } -} - -func TestGetContextFromReaderTar(t *testing.T) { - contextDir, cleanup := createTestTempDir(t, "", "builder-context-test") - defer cleanup() - - createTestTempFile(t, contextDir, DefaultDockerfileName, dockerfileContents, 0777) - - tarStream, err := archive.Tar(contextDir, archive.Uncompressed) - require.NoError(t, err) - - tarArchive, relDockerfile, err := GetContextFromReader(tarStream, DefaultDockerfileName) - require.NoError(t, err) - - tarReader := tar.NewReader(tarArchive) - - header, err := tarReader.Next() - require.NoError(t, err) - - if header.Name != DefaultDockerfileName { - t.Fatalf("Dockerfile name should be: %s, got: %s", DefaultDockerfileName, header.Name) - } - - buff := new(bytes.Buffer) - buff.ReadFrom(tarReader) - contents := buff.String() - - _, err = tarReader.Next() - - if err != io.EOF { - t.Fatalf("Tar stream too long: %s", err) - } - - require.NoError(t, tarArchive.Close()) - - if dockerfileContents != contents { - t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContents, contents) - } - - if relDockerfile != DefaultDockerfileName { - t.Fatalf("Relative path not equals %s, got: %s", DefaultDockerfileName, relDockerfile) - } -} - -func TestValidateContextDirectoryEmptyContext(t *testing.T) { - // This isn't a valid test on Windows. See https://play.golang.org/p/RR6z6jxR81. - // The test will ultimately end up calling filepath.Abs(""). On Windows, - // golang will error. On Linux, golang will return /. Due to there being - // drive letters on Windows, this is probably the correct behaviour for - // Windows. - if runtime.GOOS == "windows" { - t.Skip("Invalid test on Windows") - } - testValidateContextDirectory(t, prepareEmpty, []string{}) -} - -func TestValidateContextDirectoryContextWithNoFiles(t *testing.T) { - testValidateContextDirectory(t, prepareNoFiles, []string{}) -} - -func TestValidateContextDirectoryWithOneFile(t *testing.T) { - testValidateContextDirectory(t, prepareOneFile, []string{}) -} - -func TestValidateContextDirectoryWithOneFileExcludes(t *testing.T) { - testValidateContextDirectory(t, prepareOneFile, []string{DefaultDockerfileName}) -} - -// createTestTempDir creates a temporary directory for testing. -// It returns the created path and a cleanup function which is meant to be used as deferred call. -// When an error occurs, it terminates the test. -func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) { - path, err := ioutil.TempDir(dir, prefix) - require.NoError(t, err) - return path, func() { require.NoError(t, os.RemoveAll(path)) } -} - -// createTestTempFile creates a temporary file within dir with specific contents and permissions. -// When an error occurs, it terminates the test -func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.FileMode) string { - filePath := filepath.Join(dir, filename) - err := ioutil.WriteFile(filePath, []byte(contents), perm) - require.NoError(t, err) - return filePath -} - -// chdir changes current working directory to dir. -// It returns a function which changes working directory back to the previous one. -// This function is meant to be executed as a deferred call. -// When an error occurs, it terminates the test. -func chdir(t *testing.T, dir string) func() { - workingDirectory, err := os.Getwd() - require.NoError(t, err) - require.NoError(t, os.Chdir(dir)) - return func() { require.NoError(t, os.Chdir(workingDirectory)) } -} - -func TestIsArchive(t *testing.T) { - var testcases = []struct { - doc string - header []byte - expected bool - }{ - { - doc: "nil is not a valid header", - header: nil, - expected: false, - }, - { - doc: "invalid header bytes", - header: []byte{0x00, 0x01, 0x02}, - expected: false, - }, - { - doc: "header for bzip2 archive", - header: []byte{0x42, 0x5A, 0x68}, - expected: true, - }, - { - doc: "header for 7zip archive is not supported", - header: []byte{0x50, 0x4b, 0x03, 0x04}, - expected: false, - }, - } - for _, testcase := range testcases { - assert.Equal(t, testcase.expected, IsArchive(testcase.header), testcase.doc) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build/context_unix.go b/vendor/github.com/docker/cli/cli/command/image/build/context_unix.go deleted file mode 100644 index cb2634f07..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build/context_unix.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !windows - -package build - -import ( - "path/filepath" -) - -func getContextRoot(srcPath string) (string, error) { - return filepath.Join(srcPath, "."), nil -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build/context_windows.go b/vendor/github.com/docker/cli/cli/command/image/build/context_windows.go deleted file mode 100644 index c577cfa7b..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build/context_windows.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build windows - -package build - -import ( - "path/filepath" - - "github.com/docker/docker/pkg/longpath" -) - -func getContextRoot(srcPath string) (string, error) { - cr, err := filepath.Abs(srcPath) - if err != nil { - return "", err - } - return longpath.AddPrefix(cr), nil -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build/dockerignore.go b/vendor/github.com/docker/cli/cli/command/image/build/dockerignore.go deleted file mode 100644 index 497c3f24f..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build/dockerignore.go +++ /dev/null @@ -1,39 +0,0 @@ -package build - -import ( - "os" - "path/filepath" - - "github.com/docker/docker/builder/dockerignore" - "github.com/docker/docker/pkg/fileutils" -) - -// ReadDockerignore reads the .dockerignore file in the context directory and -// returns the list of paths to exclude -func ReadDockerignore(contextDir string) ([]string, error) { - var excludes []string - - f, err := os.Open(filepath.Join(contextDir, ".dockerignore")) - switch { - case os.IsNotExist(err): - return excludes, nil - case err != nil: - return nil, err - } - defer f.Close() - - return dockerignore.ReadAll(f) -} - -// TrimBuildFilesFromExcludes removes the named Dockerfile and .dockerignore from -// the list of excluded files. The daemon will remove them from the final context -// but they must be in available in the context when passed to the API. -func TrimBuildFilesFromExcludes(excludes []string, dockerfile string, dockerfileFromStdin bool) []string { - if keep, _ := fileutils.Matches(".dockerignore", excludes); keep { - excludes = append(excludes, "!.dockerignore") - } - if keep, _ := fileutils.Matches(dockerfile, excludes); keep && !dockerfileFromStdin { - excludes = append(excludes, "!"+dockerfile) - } - return excludes -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build_session.go b/vendor/github.com/docker/cli/cli/command/image/build_session.go deleted file mode 100644 index 4281f9fe6..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build_session.go +++ /dev/null @@ -1,151 +0,0 @@ -package image - -import ( - "bytes" - "crypto/rand" - "crypto/sha256" - "encoding/hex" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "sync" - "time" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image/build" - cliconfig "github.com/docker/cli/cli/config" - "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/pkg/progress" - "github.com/moby/buildkit/session" - "github.com/moby/buildkit/session/filesync" - "github.com/pkg/errors" - "golang.org/x/time/rate" -) - -const clientSessionRemote = "client-session" - -func isSessionSupported(dockerCli command.Cli) bool { - return dockerCli.ServerInfo().HasExperimental && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.31") -} - -func trySession(dockerCli command.Cli, contextDir string) (*session.Session, error) { - var s *session.Session - if isSessionSupported(dockerCli) { - sharedKey, err := getBuildSharedKey(contextDir) - if err != nil { - return nil, errors.Wrap(err, "failed to get build shared key") - } - s, err = session.NewSession(filepath.Base(contextDir), sharedKey) - if err != nil { - return nil, errors.Wrap(err, "failed to create session") - } - } - return s, nil -} - -func addDirToSession(session *session.Session, contextDir string, progressOutput progress.Output, done chan error) error { - excludes, err := build.ReadDockerignore(contextDir) - if err != nil { - return err - } - - p := &sizeProgress{out: progressOutput, action: "Streaming build context to Docker daemon"} - - workdirProvider := filesync.NewFSSyncProvider(contextDir, excludes) - session.Allow(workdirProvider) - - // this will be replaced on parallel build jobs. keep the current - // progressbar for now - if snpc, ok := workdirProvider.(interface { - SetNextProgressCallback(func(int, bool), chan error) - }); ok { - snpc.SetNextProgressCallback(p.update, done) - } - - return nil -} - -type sizeProgress struct { - out progress.Output - action string - limiter *rate.Limiter -} - -func (sp *sizeProgress) update(size int, last bool) { - if sp.limiter == nil { - sp.limiter = rate.NewLimiter(rate.Every(100*time.Millisecond), 1) - } - if last || sp.limiter.Allow() { - sp.out.WriteProgress(progress.Progress{Action: sp.action, Current: int64(size), LastUpdate: last}) - } -} - -type bufferedWriter struct { - done chan error - io.Writer - buf *bytes.Buffer - flushed chan struct{} - mu sync.Mutex -} - -func newBufferedWriter(done chan error, w io.Writer) *bufferedWriter { - bw := &bufferedWriter{done: done, Writer: w, buf: new(bytes.Buffer), flushed: make(chan struct{})} - go func() { - <-done - bw.flushBuffer() - }() - return bw -} - -func (bw *bufferedWriter) Write(dt []byte) (int, error) { - select { - case <-bw.done: - bw.flushBuffer() - return bw.Writer.Write(dt) - default: - return bw.buf.Write(dt) - } -} - -func (bw *bufferedWriter) flushBuffer() { - bw.mu.Lock() - select { - case <-bw.flushed: - default: - bw.Writer.Write(bw.buf.Bytes()) - close(bw.flushed) - } - bw.mu.Unlock() -} - -func getBuildSharedKey(dir string) (string, error) { - // build session is hash of build dir with node based randomness - s := sha256.Sum256([]byte(fmt.Sprintf("%s:%s", tryNodeIdentifier(), dir))) - return hex.EncodeToString(s[:]), nil -} - -func tryNodeIdentifier() (out string) { - out = cliconfig.Dir() // return config dir as default on permission error - if err := os.MkdirAll(cliconfig.Dir(), 0700); err == nil { - sessionFile := filepath.Join(cliconfig.Dir(), ".buildNodeID") - if _, err := os.Lstat(sessionFile); err != nil { - if os.IsNotExist(err) { // create a new file with stored randomness - b := make([]byte, 32) - if _, err := rand.Read(b); err != nil { - return - } - if err := ioutil.WriteFile(sessionFile, []byte(hex.EncodeToString(b)), 0600); err != nil { - return - } - } - } - - dt, err := ioutil.ReadFile(sessionFile) - if err == nil { - return string(dt) - } - } - return -} diff --git a/vendor/github.com/docker/cli/cli/command/image/build_test.go b/vendor/github.com/docker/cli/cli/command/image/build_test.go deleted file mode 100644 index 1ccd70e45..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/build_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package image - -import ( - "bytes" - "io" - "io/ioutil" - "os" - "path/filepath" - "runtime" - "sort" - "syscall" - "testing" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/archive" - "github.com/gotestyourself/gotestyourself/fs" - "github.com/gotestyourself/gotestyourself/skip" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/context" -) - -func TestRunBuildResetsUidAndGidInContext(t *testing.T) { - skip.IfCondition(t, runtime.GOOS == "windows", "uid and gid not relevant on windows") - dest := fs.NewDir(t, "test-build-context-dest") - defer dest.Remove() - - fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { - assert.NoError(t, archive.Untar(context, dest.Path(), nil)) - - body := new(bytes.Buffer) - return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil - } - cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild}) - - dir := fs.NewDir(t, "test-build-context", - fs.WithFile("foo", "some content", fs.AsUser(65534, 65534)), - fs.WithFile("Dockerfile", ` - FROM alpine:3.6 - COPY foo bar / - `), - ) - defer dir.Remove() - - options := newBuildOptions() - options.context = dir.Path() - - err := runBuild(cli, options) - require.NoError(t, err) - - files, err := ioutil.ReadDir(dest.Path()) - require.NoError(t, err) - for _, fileInfo := range files { - assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Uid) - assert.Equal(t, uint32(0), fileInfo.Sys().(*syscall.Stat_t).Gid) - } -} -func TestRunBuildDockerfileFromStdinWithCompress(t *testing.T) { - dest, err := ioutil.TempDir("", "test-build-compress-dest") - require.NoError(t, err) - defer os.RemoveAll(dest) - - var dockerfileName string - fakeImageBuild := func(_ context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { - buffer := new(bytes.Buffer) - tee := io.TeeReader(context, buffer) - - assert.NoError(t, archive.Untar(tee, dest, nil)) - dockerfileName = options.Dockerfile - - header := buffer.Bytes()[:10] - assert.Equal(t, archive.Gzip, archive.DetectCompression(header)) - - body := new(bytes.Buffer) - return types.ImageBuildResponse{Body: ioutil.NopCloser(body)}, nil - } - - cli := test.NewFakeCli(&fakeClient{imageBuildFunc: fakeImageBuild}) - dockerfile := bytes.NewBufferString(` - FROM alpine:3.6 - COPY foo / - `) - cli.SetIn(command.NewInStream(ioutil.NopCloser(dockerfile))) - - dir, err := ioutil.TempDir("", "test-build-compress") - require.NoError(t, err) - defer os.RemoveAll(dir) - - ioutil.WriteFile(filepath.Join(dir, "foo"), []byte("some content"), 0644) - - options := newBuildOptions() - options.compress = true - options.dockerfileName = "-" - options.context = dir - - err = runBuild(cli, options) - require.NoError(t, err) - - files, err := ioutil.ReadDir(dest) - require.NoError(t, err) - actual := []string{} - for _, fileInfo := range files { - actual = append(actual, fileInfo.Name()) - } - sort.Strings(actual) - assert.Equal(t, []string{dockerfileName, ".dockerignore", "foo"}, actual) -} - -// TestRunBuildFromLocalGitHubDirNonExistingRepo tests that build contexts -// starting with `github.com/` are special-cased, and the build command attempts -// to clone the remote repo. -func TestRunBuildFromGitHubSpecialCase(t *testing.T) { - cmd := NewBuildCommand(test.NewFakeCli(nil)) - cmd.SetArgs([]string{"github.com/docker/no-such-repository"}) - cmd.SetOutput(ioutil.Discard) - err := cmd.Execute() - assert.Error(t, err) - assert.Contains(t, err.Error(), "unable to prepare context: unable to 'git clone'") -} - -// TestRunBuildFromLocalGitHubDirNonExistingRepo tests that a local directory -// starting with `github.com` takes precedence over the `github.com` special -// case. -func TestRunBuildFromLocalGitHubDir(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "docker-build-from-local-dir-") - require.NoError(t, err) - defer os.RemoveAll(tmpDir) - - buildDir := filepath.Join(tmpDir, "github.com", "docker", "no-such-repository") - err = os.MkdirAll(buildDir, 0777) - require.NoError(t, err) - err = ioutil.WriteFile(filepath.Join(buildDir, "Dockerfile"), []byte("FROM busybox\n"), 0644) - require.NoError(t, err) - - client := test.NewFakeCli(&fakeClient{}) - cmd := NewBuildCommand(client) - cmd.SetArgs([]string{buildDir}) - cmd.SetOutput(ioutil.Discard) - err = cmd.Execute() - require.NoError(t, err) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/client_test.go b/vendor/github.com/docker/cli/cli/command/image/client_test.go deleted file mode 100644 index b91eb7bd8..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/client_test.go +++ /dev/null @@ -1,124 +0,0 @@ -package image - -import ( - "io" - "io/ioutil" - "strings" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/image" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - imageTagFunc func(string, string) error - imageSaveFunc func(images []string) (io.ReadCloser, error) - imageRemoveFunc func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) - imagePushFunc func(ref string, options types.ImagePushOptions) (io.ReadCloser, error) - infoFunc func() (types.Info, error) - imagePullFunc func(ref string, options types.ImagePullOptions) (io.ReadCloser, error) - imagesPruneFunc func(pruneFilter filters.Args) (types.ImagesPruneReport, error) - imageLoadFunc func(input io.Reader, quiet bool) (types.ImageLoadResponse, error) - imageListFunc func(options types.ImageListOptions) ([]types.ImageSummary, error) - imageInspectFunc func(image string) (types.ImageInspect, []byte, error) - imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) - imageHistoryFunc func(image string) ([]image.HistoryResponseItem, error) - imageBuildFunc func(context.Context, io.Reader, types.ImageBuildOptions) (types.ImageBuildResponse, error) -} - -func (cli *fakeClient) ImageTag(_ context.Context, image, ref string) error { - if cli.imageTagFunc != nil { - return cli.imageTagFunc(image, ref) - } - return nil -} - -func (cli *fakeClient) ImageSave(_ context.Context, images []string) (io.ReadCloser, error) { - if cli.imageSaveFunc != nil { - return cli.imageSaveFunc(images) - } - return ioutil.NopCloser(strings.NewReader("")), nil -} - -func (cli *fakeClient) ImageRemove(_ context.Context, image string, - options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - if cli.imageRemoveFunc != nil { - return cli.imageRemoveFunc(image, options) - } - return []types.ImageDeleteResponseItem{}, nil -} - -func (cli *fakeClient) ImagePush(_ context.Context, ref string, options types.ImagePushOptions) (io.ReadCloser, error) { - if cli.imagePushFunc != nil { - return cli.imagePushFunc(ref, options) - } - return ioutil.NopCloser(strings.NewReader("")), nil -} - -func (cli *fakeClient) Info(_ context.Context) (types.Info, error) { - if cli.infoFunc != nil { - return cli.infoFunc() - } - return types.Info{}, nil -} - -func (cli *fakeClient) ImagePull(_ context.Context, ref string, options types.ImagePullOptions) (io.ReadCloser, error) { - if cli.imagePullFunc != nil { - cli.imagePullFunc(ref, options) - } - return ioutil.NopCloser(strings.NewReader("")), nil -} - -func (cli *fakeClient) ImagesPrune(_ context.Context, pruneFilter filters.Args) (types.ImagesPruneReport, error) { - if cli.imagesPruneFunc != nil { - return cli.imagesPruneFunc(pruneFilter) - } - return types.ImagesPruneReport{}, nil -} - -func (cli *fakeClient) ImageLoad(_ context.Context, input io.Reader, quiet bool) (types.ImageLoadResponse, error) { - if cli.imageLoadFunc != nil { - return cli.imageLoadFunc(input, quiet) - } - return types.ImageLoadResponse{}, nil -} - -func (cli *fakeClient) ImageList(ctx context.Context, options types.ImageListOptions) ([]types.ImageSummary, error) { - if cli.imageListFunc != nil { - return cli.imageListFunc(options) - } - return []types.ImageSummary{{}}, nil -} - -func (cli *fakeClient) ImageInspectWithRaw(_ context.Context, image string) (types.ImageInspect, []byte, error) { - if cli.imageInspectFunc != nil { - return cli.imageInspectFunc(image) - } - return types.ImageInspect{}, nil, nil -} - -func (cli *fakeClient) ImageImport(_ context.Context, source types.ImageImportSource, ref string, - options types.ImageImportOptions) (io.ReadCloser, error) { - if cli.imageImportFunc != nil { - return cli.imageImportFunc(source, ref, options) - } - return ioutil.NopCloser(strings.NewReader("")), nil -} - -func (cli *fakeClient) ImageHistory(_ context.Context, img string) ([]image.HistoryResponseItem, error) { - if cli.imageHistoryFunc != nil { - return cli.imageHistoryFunc(img) - } - return []image.HistoryResponseItem{{ID: img, Created: time.Now().Unix()}}, nil -} - -func (cli *fakeClient) ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) { - if cli.imageBuildFunc != nil { - return cli.imageBuildFunc(ctx, context, options) - } - return types.ImageBuildResponse{Body: ioutil.NopCloser(strings.NewReader(""))}, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/image/cmd.go b/vendor/github.com/docker/cli/cli/command/image/cmd.go deleted file mode 100644 index a12bf3395..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/cmd.go +++ /dev/null @@ -1,33 +0,0 @@ -package image - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewImageCommand returns a cobra command for `image` subcommands -func NewImageCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "image", - Short: "Manage images", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - } - cmd.AddCommand( - NewBuildCommand(dockerCli), - NewHistoryCommand(dockerCli), - NewImportCommand(dockerCli), - NewLoadCommand(dockerCli), - NewPullCommand(dockerCli), - NewPushCommand(dockerCli), - NewSaveCommand(dockerCli), - NewTagCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - newInspectCommand(dockerCli), - NewPruneCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/image/history.go b/vendor/github.com/docker/cli/cli/command/image/history.go deleted file mode 100644 index 27782d107..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/history.go +++ /dev/null @@ -1,64 +0,0 @@ -package image - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" -) - -type historyOptions struct { - image string - - human bool - quiet bool - noTrunc bool - format string -} - -// NewHistoryCommand creates a new `docker history` command -func NewHistoryCommand(dockerCli command.Cli) *cobra.Command { - var opts historyOptions - - cmd := &cobra.Command{ - Use: "history [OPTIONS] IMAGE", - Short: "Show the history of an image", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.image = args[0] - return runHistory(dockerCli, opts) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&opts.human, "human", "H", true, "Print sizes and dates in human readable format") - flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only show numeric IDs") - flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output") - flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template") - - return cmd -} - -func runHistory(dockerCli command.Cli, opts historyOptions) error { - ctx := context.Background() - - history, err := dockerCli.Client().ImageHistory(ctx, opts.image) - if err != nil { - return err - } - - format := opts.format - if len(format) == 0 { - format = formatter.TableFormatKey - } - - historyCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewHistoryFormat(format, opts.quiet, opts.human), - Trunc: !opts.noTrunc, - } - return formatter.HistoryWrite(historyCtx, opts.human, history) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/history_test.go b/vendor/github.com/docker/cli/cli/command/image/history_test.go deleted file mode 100644 index eb656e5cf..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/history_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package image - -import ( - "fmt" - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types/image" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNewHistoryCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - imageHistoryFunc func(img string) ([]image.HistoryResponseItem, error) - }{ - { - name: "wrong-args", - args: []string{}, - expectedError: "requires exactly 1 argument.", - }, - { - name: "client-error", - args: []string{"image:tag"}, - expectedError: "something went wrong", - imageHistoryFunc: func(img string) ([]image.HistoryResponseItem, error) { - return []image.HistoryResponseItem{{}}, errors.Errorf("something went wrong") - }, - }, - } - for _, tc := range testCases { - cmd := NewHistoryCommand(test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewHistoryCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - outputRegex string - imageHistoryFunc func(img string) ([]image.HistoryResponseItem, error) - }{ - { - name: "simple", - args: []string{"image:tag"}, - imageHistoryFunc: func(img string) ([]image.HistoryResponseItem, error) { - return []image.HistoryResponseItem{{ - ID: "1234567890123456789", - Created: time.Now().Unix(), - }}, nil - }, - }, - { - name: "quiet", - args: []string{"--quiet", "image:tag"}, - }, - // TODO: This test is failing since the output does not contain an RFC3339 date - //{ - // name: "non-human", - // args: []string{"--human=false", "image:tag"}, - // outputRegex: "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}", // RFC3339 date format match - //}, - { - name: "non-human-header", - args: []string{"--human=false", "image:tag"}, - outputRegex: "CREATED\\sAT", - }, - { - name: "quiet-no-trunc", - args: []string{"--quiet", "--no-trunc", "image:tag"}, - imageHistoryFunc: func(img string) ([]image.HistoryResponseItem, error) { - return []image.HistoryResponseItem{{ - ID: "1234567890123456789", - Created: time.Now().Unix(), - }}, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imageHistoryFunc: tc.imageHistoryFunc}) - cmd := NewHistoryCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - err := cmd.Execute() - assert.NoError(t, err) - actual := cli.OutBuffer().String() - if tc.outputRegex == "" { - golden.Assert(t, actual, fmt.Sprintf("history-command-success.%s.golden", tc.name)) - } else { - assert.Regexp(t, tc.outputRegex, actual) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/import.go b/vendor/github.com/docker/cli/cli/command/image/import.go deleted file mode 100644 index 1f7189a95..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/import.go +++ /dev/null @@ -1,87 +0,0 @@ -package image - -import ( - "io" - "os" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - dockeropts "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/pkg/urlutil" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type importOptions struct { - source string - reference string - changes dockeropts.ListOpts - message string -} - -// NewImportCommand creates a new `docker import` command -func NewImportCommand(dockerCli command.Cli) *cobra.Command { - var options importOptions - - cmd := &cobra.Command{ - Use: "import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]", - Short: "Import the contents from a tarball to create a filesystem image", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.source = args[0] - if len(args) > 1 { - options.reference = args[1] - } - return runImport(dockerCli, options) - }, - } - - flags := cmd.Flags() - - options.changes = dockeropts.NewListOpts(nil) - flags.VarP(&options.changes, "change", "c", "Apply Dockerfile instruction to the created image") - flags.StringVarP(&options.message, "message", "m", "", "Set commit message for imported image") - - return cmd -} - -func runImport(dockerCli command.Cli, options importOptions) error { - var ( - in io.Reader - srcName = options.source - ) - - if options.source == "-" { - in = dockerCli.In() - } else if !urlutil.IsURL(options.source) { - srcName = "-" - file, err := os.Open(options.source) - if err != nil { - return err - } - defer file.Close() - in = file - } - - source := types.ImageImportSource{ - Source: in, - SourceName: srcName, - } - - importOptions := types.ImageImportOptions{ - Message: options.message, - Changes: options.changes.GetAll(), - } - - clnt := dockerCli.Client() - - responseBody, err := clnt.ImageImport(context.Background(), source, options.reference, importOptions) - if err != nil { - return err - } - defer responseBody.Close() - - return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/import_test.go b/vendor/github.com/docker/cli/cli/command/image/import_test.go deleted file mode 100644 index 7f9bc2d8d..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/import_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package image - -import ( - "io" - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNewImportCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) - }{ - { - name: "wrong-args", - args: []string{}, - expectedError: "requires at least 1 argument.", - }, - { - name: "import-failed", - args: []string{"testdata/import-command-success.input.txt"}, - expectedError: "something went wrong", - imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) { - return nil, errors.Errorf("something went wrong") - }, - }, - } - for _, tc := range testCases { - cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewImportCommandInvalidFile(t *testing.T) { - cmd := NewImportCommand(test.NewFakeCli(&fakeClient{})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs([]string{"testdata/import-command-success.unexistent-file"}) - testutil.ErrorContains(t, cmd.Execute(), "testdata/import-command-success.unexistent-file") -} - -func TestNewImportCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - imageImportFunc func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) - }{ - { - name: "simple", - args: []string{"testdata/import-command-success.input.txt"}, - }, - { - name: "terminal-source", - args: []string{"-"}, - }, - { - name: "double", - args: []string{"-", "image:local"}, - imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) { - assert.Equal(t, "image:local", ref) - return ioutil.NopCloser(strings.NewReader("")), nil - }, - }, - { - name: "message", - args: []string{"--message", "test message", "-"}, - imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) { - assert.Equal(t, "test message", options.Message) - return ioutil.NopCloser(strings.NewReader("")), nil - }, - }, - { - name: "change", - args: []string{"--change", "ENV DEBUG true", "-"}, - imageImportFunc: func(source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) { - assert.Equal(t, "ENV DEBUG true", options.Changes[0]) - return ioutil.NopCloser(strings.NewReader("")), nil - }, - }, - } - for _, tc := range testCases { - cmd := NewImportCommand(test.NewFakeCli(&fakeClient{imageImportFunc: tc.imageImportFunc})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - assert.NoError(t, cmd.Execute()) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/inspect.go b/vendor/github.com/docker/cli/cli/command/image/inspect.go deleted file mode 100644 index a510e3076..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/inspect.go +++ /dev/null @@ -1,44 +0,0 @@ -package image - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/spf13/cobra" -) - -type inspectOptions struct { - format string - refs []string -} - -// newInspectCommand creates a new cobra.Command for `docker image inspect` -func newInspectCommand(dockerCli command.Cli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] IMAGE [IMAGE...]", - Short: "Display detailed information on one or more images", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.refs = args - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - return cmd -} - -func runInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - getRefFunc := func(ref string) (interface{}, []byte, error) { - return client.ImageInspectWithRaw(ctx, ref) - } - return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRefFunc) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/inspect_test.go b/vendor/github.com/docker/cli/cli/command/image/inspect_test.go deleted file mode 100644 index 4e94d0623..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/inspect_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package image - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestNewInspectCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - }{ - { - name: "wrong-args", - args: []string{}, - expectedError: "requires at least 1 argument.", - }, - } - for _, tc := range testCases { - cmd := newInspectCommand(test.NewFakeCli(&fakeClient{})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewInspectCommandSuccess(t *testing.T) { - imageInspectInvocationCount := 0 - testCases := []struct { - name string - args []string - imageCount int - imageInspectFunc func(image string) (types.ImageInspect, []byte, error) - }{ - { - name: "simple", - args: []string{"image"}, - imageCount: 1, - imageInspectFunc: func(image string) (types.ImageInspect, []byte, error) { - imageInspectInvocationCount++ - assert.Equal(t, "image", image) - return types.ImageInspect{}, nil, nil - }, - }, - { - name: "format", - imageCount: 1, - args: []string{"--format='{{.ID}}'", "image"}, - imageInspectFunc: func(image string) (types.ImageInspect, []byte, error) { - imageInspectInvocationCount++ - return types.ImageInspect{ID: image}, nil, nil - }, - }, - { - name: "simple-many", - args: []string{"image1", "image2"}, - imageCount: 2, - imageInspectFunc: func(image string) (types.ImageInspect, []byte, error) { - imageInspectInvocationCount++ - if imageInspectInvocationCount == 1 { - assert.Equal(t, "image1", image) - } else { - assert.Equal(t, "image2", image) - } - return types.ImageInspect{}, nil, nil - }, - }, - } - for _, tc := range testCases { - imageInspectInvocationCount = 0 - cli := test.NewFakeCli(&fakeClient{imageInspectFunc: tc.imageInspectFunc}) - cmd := newInspectCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - err := cmd.Execute() - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("inspect-command-success.%s.golden", tc.name)) - assert.Equal(t, imageInspectInvocationCount, tc.imageCount) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/list.go b/vendor/github.com/docker/cli/cli/command/image/list.go deleted file mode 100644 index 6dada8252..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/list.go +++ /dev/null @@ -1,95 +0,0 @@ -package image - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type imagesOptions struct { - matchName string - - quiet bool - all bool - noTrunc bool - showDigests bool - format string - filter opts.FilterOpt -} - -// NewImagesCommand creates a new `docker images` command -func NewImagesCommand(dockerCli command.Cli) *cobra.Command { - options := imagesOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "images [OPTIONS] [REPOSITORY[:TAG]]", - Short: "List images", - Args: cli.RequiresMaxArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - options.matchName = args[0] - } - return runImages(dockerCli, options) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only show numeric IDs") - flags.BoolVarP(&options.all, "all", "a", false, "Show all images (default hides intermediate images)") - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") - flags.BoolVar(&options.showDigests, "digests", false, "Show digests") - flags.StringVar(&options.format, "format", "", "Pretty-print images using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - cmd := *NewImagesCommand(dockerCli) - cmd.Aliases = []string{"images", "list"} - cmd.Use = "ls [OPTIONS] [REPOSITORY[:TAG]]" - return &cmd -} - -func runImages(dockerCli command.Cli, options imagesOptions) error { - ctx := context.Background() - - filters := options.filter.Value() - if options.matchName != "" { - filters.Add("reference", options.matchName) - } - - listOptions := types.ImageListOptions{ - All: options.all, - Filters: filters, - } - - images, err := dockerCli.Client().ImageList(ctx, listOptions) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().ImagesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().ImagesFormat - } else { - format = formatter.TableFormatKey - } - } - - imageCtx := formatter.ImageContext{ - Context: formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewImageFormat(format, options.quiet, options.showDigests), - Trunc: !options.noTrunc, - }, - Digest: options.showDigests, - } - return formatter.ImageWrite(imageCtx, images) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/list_test.go b/vendor/github.com/docker/cli/cli/command/image/list_test.go deleted file mode 100644 index 1755bb3e3..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/list_test.go +++ /dev/null @@ -1,98 +0,0 @@ -package image - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNewImagesCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - imageListFunc func(options types.ImageListOptions) ([]types.ImageSummary, error) - }{ - { - name: "wrong-args", - args: []string{"arg1", "arg2"}, - expectedError: "requires at most 1 argument.", - }, - { - name: "failed-list", - expectedError: "something went wrong", - imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) { - return []types.ImageSummary{{}}, errors.Errorf("something went wrong") - }, - }, - } - for _, tc := range testCases { - cmd := NewImagesCommand(test.NewFakeCli(&fakeClient{imageListFunc: tc.imageListFunc})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewImagesCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - imageFormat string - imageListFunc func(options types.ImageListOptions) ([]types.ImageSummary, error) - }{ - { - name: "simple", - }, - { - name: "format", - imageFormat: "raw", - }, - { - name: "quiet-format", - args: []string{"-q"}, - imageFormat: "table", - }, - { - name: "match-name", - args: []string{"image"}, - imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) { - assert.Equal(t, "image", options.Filters.Get("reference")[0]) - return []types.ImageSummary{{}}, nil - }, - }, - { - name: "filters", - args: []string{"--filter", "name=value"}, - imageListFunc: func(options types.ImageListOptions) ([]types.ImageSummary, error) { - assert.Equal(t, "value", options.Filters.Get("name")[0]) - return []types.ImageSummary{{}}, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imageListFunc: tc.imageListFunc}) - cli.SetConfigFile(&configfile.ConfigFile{ImagesFormat: tc.imageFormat}) - cmd := NewImagesCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - err := cmd.Execute() - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("list-command-success.%s.golden", tc.name)) - } -} - -func TestNewListCommandAlias(t *testing.T) { - cmd := newListCommand(test.NewFakeCli(&fakeClient{})) - assert.True(t, cmd.HasAlias("images")) - assert.True(t, cmd.HasAlias("list")) - assert.False(t, cmd.HasAlias("other")) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/load.go b/vendor/github.com/docker/cli/cli/command/image/load.go deleted file mode 100644 index 6708599fd..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/load.go +++ /dev/null @@ -1,77 +0,0 @@ -package image - -import ( - "io" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/pkg/system" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type loadOptions struct { - input string - quiet bool -} - -// NewLoadCommand creates a new `docker load` command -func NewLoadCommand(dockerCli command.Cli) *cobra.Command { - var opts loadOptions - - cmd := &cobra.Command{ - Use: "load [OPTIONS]", - Short: "Load an image from a tar archive or STDIN", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runLoad(dockerCli, opts) - }, - } - - flags := cmd.Flags() - - flags.StringVarP(&opts.input, "input", "i", "", "Read from tar archive file, instead of STDIN") - flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress the load output") - - return cmd -} - -func runLoad(dockerCli command.Cli, opts loadOptions) error { - - var input io.Reader = dockerCli.In() - if opts.input != "" { - // We use system.OpenSequential to use sequential file access on Windows, avoiding - // depleting the standby list un-necessarily. On Linux, this equates to a regular os.Open. - file, err := system.OpenSequential(opts.input) - if err != nil { - return err - } - defer file.Close() - input = file - } - - // To avoid getting stuck, verify that a tar file is given either in - // the input flag or through stdin and if not display an error message and exit. - if opts.input == "" && dockerCli.In().IsTerminal() { - return errors.Errorf("requested load from stdin, but stdin is empty") - } - - if !dockerCli.Out().IsTerminal() { - opts.quiet = true - } - response, err := dockerCli.Client().ImageLoad(context.Background(), input, opts.quiet) - if err != nil { - return err - } - defer response.Body.Close() - - if response.Body != nil && response.JSON { - return jsonmessage.DisplayJSONMessagesToStream(response.Body, dockerCli.Out(), nil) - } - - _, err = io.Copy(dockerCli.Out(), response.Body) - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/image/load_test.go b/vendor/github.com/docker/cli/cli/command/image/load_test.go deleted file mode 100644 index 5f05bca47..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/load_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package image - -import ( - "fmt" - "io" - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNewLoadCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - isTerminalIn bool - expectedError string - imageLoadFunc func(input io.Reader, quiet bool) (types.ImageLoadResponse, error) - }{ - { - name: "wrong-args", - args: []string{"arg"}, - expectedError: "accepts no arguments.", - }, - { - name: "input-to-terminal", - isTerminalIn: true, - expectedError: "requested load from stdin, but stdin is empty", - }, - { - name: "pull-error", - expectedError: "something went wrong", - imageLoadFunc: func(input io.Reader, quiet bool) (types.ImageLoadResponse, error) { - return types.ImageLoadResponse{}, errors.Errorf("something went wrong") - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imageLoadFunc: tc.imageLoadFunc}) - cli.In().SetIsTerminal(tc.isTerminalIn) - cmd := NewLoadCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewLoadCommandInvalidInput(t *testing.T) { - expectedError := "open *" - cmd := NewLoadCommand(test.NewFakeCli(&fakeClient{})) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs([]string{"--input", "*"}) - err := cmd.Execute() - testutil.ErrorContains(t, err, expectedError) -} - -func TestNewLoadCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - imageLoadFunc func(input io.Reader, quiet bool) (types.ImageLoadResponse, error) - }{ - { - name: "simple", - imageLoadFunc: func(input io.Reader, quiet bool) (types.ImageLoadResponse, error) { - return types.ImageLoadResponse{Body: ioutil.NopCloser(strings.NewReader("Success"))}, nil - }, - }, - { - name: "json", - imageLoadFunc: func(input io.Reader, quiet bool) (types.ImageLoadResponse, error) { - json := "{\"ID\": \"1\"}" - return types.ImageLoadResponse{ - Body: ioutil.NopCloser(strings.NewReader(json)), - JSON: true, - }, nil - }, - }, - { - name: "input-file", - args: []string{"--input", "testdata/load-command-success.input.txt"}, - imageLoadFunc: func(input io.Reader, quiet bool) (types.ImageLoadResponse, error) { - return types.ImageLoadResponse{Body: ioutil.NopCloser(strings.NewReader("Success"))}, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imageLoadFunc: tc.imageLoadFunc}) - cmd := NewLoadCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - err := cmd.Execute() - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("load-command-success.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/prune.go b/vendor/github.com/docker/cli/cli/command/image/prune.go deleted file mode 100644 index 8e521b61b..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/prune.go +++ /dev/null @@ -1,95 +0,0 @@ -package image - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - units "github.com/docker/go-units" - "github.com/spf13/cobra" -) - -type pruneOptions struct { - force bool - all bool - filter opts.FilterOpt -} - -// NewPruneCommand returns a new cobra prune command for images -func NewPruneCommand(dockerCli command.Cli) *cobra.Command { - options := pruneOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "prune [OPTIONS]", - Short: "Remove unused images", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - spaceReclaimed, output, err := runPrune(dockerCli, options) - if err != nil { - return err - } - if output != "" { - fmt.Fprintln(dockerCli.Out(), output) - } - fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) - return nil - }, - Tags: map[string]string{"version": "1.25"}, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") - flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused images, not just dangling ones") - flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'until=')") - - return cmd -} - -const ( - allImageWarning = `WARNING! This will remove all images without at least one container associated to them. -Are you sure you want to continue?` - danglingWarning = `WARNING! This will remove all dangling images. -Are you sure you want to continue?` -) - -func runPrune(dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint64, output string, err error) { - pruneFilters := options.filter.Value() - pruneFilters.Add("dangling", fmt.Sprintf("%v", !options.all)) - pruneFilters = command.PruneFilters(dockerCli, pruneFilters) - - warning := danglingWarning - if options.all { - warning = allImageWarning - } - if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) { - return - } - - report, err := dockerCli.Client().ImagesPrune(context.Background(), pruneFilters) - if err != nil { - return - } - - if len(report.ImagesDeleted) > 0 { - output = "Deleted Images:\n" - for _, st := range report.ImagesDeleted { - if st.Untagged != "" { - output += fmt.Sprintln("untagged:", st.Untagged) - } else { - output += fmt.Sprintln("deleted:", st.Deleted) - } - } - spaceReclaimed = report.SpaceReclaimed - } - - return -} - -// RunPrune calls the Image Prune API -// This returns the amount of space reclaimed and a detailed output string -func RunPrune(dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) { - return runPrune(dockerCli, pruneOptions{force: true, all: all, filter: filter}) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/prune_test.go b/vendor/github.com/docker/cli/cli/command/image/prune_test.go deleted file mode 100644 index 12f51b60f..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/prune_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package image - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNewPruneCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - imagesPruneFunc func(pruneFilter filters.Args) (types.ImagesPruneReport, error) - }{ - { - name: "wrong-args", - args: []string{"something"}, - expectedError: "accepts no arguments.", - }, - { - name: "prune-error", - args: []string{"--force"}, - expectedError: "something went wrong", - imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) { - return types.ImagesPruneReport{}, errors.Errorf("something went wrong") - }, - }, - } - for _, tc := range testCases { - cmd := NewPruneCommand(test.NewFakeCli(&fakeClient{ - imagesPruneFunc: tc.imagesPruneFunc, - })) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewPruneCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - imagesPruneFunc func(pruneFilter filters.Args) (types.ImagesPruneReport, error) - }{ - { - name: "all", - args: []string{"--all"}, - imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) { - assert.Equal(t, "false", pruneFilter.Get("dangling")[0]) - return types.ImagesPruneReport{}, nil - }, - }, - { - name: "force-deleted", - args: []string{"--force"}, - imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) { - assert.Equal(t, "true", pruneFilter.Get("dangling")[0]) - return types.ImagesPruneReport{ - ImagesDeleted: []types.ImageDeleteResponseItem{{Deleted: "image1"}}, - SpaceReclaimed: 1, - }, nil - }, - }, - { - name: "force-untagged", - args: []string{"--force"}, - imagesPruneFunc: func(pruneFilter filters.Args) (types.ImagesPruneReport, error) { - assert.Equal(t, "true", pruneFilter.Get("dangling")[0]) - return types.ImagesPruneReport{ - ImagesDeleted: []types.ImageDeleteResponseItem{{Untagged: "image1"}}, - SpaceReclaimed: 2, - }, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imagesPruneFunc: tc.imagesPruneFunc}) - cmd := NewPruneCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - err := cmd.Execute() - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("prune-command-success.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/pull.go b/vendor/github.com/docker/cli/cli/command/image/pull.go deleted file mode 100644 index e60e5a434..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/pull.go +++ /dev/null @@ -1,85 +0,0 @@ -package image - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/distribution/reference" - "github.com/docker/docker/registry" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type pullOptions struct { - remote string - all bool -} - -// NewPullCommand creates a new `docker pull` command -func NewPullCommand(dockerCli command.Cli) *cobra.Command { - var opts pullOptions - - cmd := &cobra.Command{ - Use: "pull [OPTIONS] NAME[:TAG|@DIGEST]", - Short: "Pull an image or a repository from a registry", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.remote = args[0] - return runPull(dockerCli, opts) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository") - command.AddTrustVerificationFlags(flags) - - return cmd -} - -func runPull(dockerCli command.Cli, opts pullOptions) error { - distributionRef, err := reference.ParseNormalizedNamed(opts.remote) - if err != nil { - return err - } - if opts.all && !reference.IsNameOnly(distributionRef) { - return errors.New("tag can't be used with --all-tags/-a") - } - - if !opts.all && reference.IsNameOnly(distributionRef) { - distributionRef = reference.TagNameOnly(distributionRef) - if tagged, ok := distributionRef.(reference.Tagged); ok { - fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", tagged.Tag()) - } - } - - // Resolve the Repository name from fqn to RepositoryInfo - repoInfo, err := registry.ParseRepositoryInfo(distributionRef) - if err != nil { - return err - } - - ctx := context.Background() - - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) - requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "pull") - - // Check if reference has a digest - _, isCanonical := distributionRef.(reference.Canonical) - if command.IsTrusted() && !isCanonical { - err = trustedPull(ctx, dockerCli, repoInfo, distributionRef, authConfig, requestPrivilege) - } else { - err = imagePullPrivileged(ctx, dockerCli, authConfig, reference.FamiliarString(distributionRef), requestPrivilege, opts.all) - } - if err != nil { - if strings.Contains(err.Error(), "when fetching 'plugin'") { - return errors.New(err.Error() + " - Use `docker plugin install`") - } - return err - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/image/pull_test.go b/vendor/github.com/docker/cli/cli/command/image/pull_test.go deleted file mode 100644 index 157b391fd..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/pull_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package image - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestNewPullCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - }{ - { - name: "wrong-args", - expectedError: "requires exactly 1 argument.", - args: []string{}, - }, - { - name: "invalid-name", - expectedError: "invalid reference format: repository name must be lowercase", - args: []string{"UPPERCASE_REPO"}, - }, - { - name: "all-tags-with-tag", - expectedError: "tag can't be used with --all-tags/-a", - args: []string{"--all-tags", "image:tag"}, - }, - { - name: "pull-error", - args: []string{"--disable-content-trust=false", "image:tag"}, - expectedError: "you are not authorized to perform this operation: server returned 401.", - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{}) - cmd := NewPullCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewPullCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - }{ - { - name: "simple", - args: []string{"image:tag"}, - }, - { - name: "simple-no-tag", - args: []string{"image"}, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{}) - cmd := NewPullCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - err := cmd.Execute() - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("pull-command-success.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/push.go b/vendor/github.com/docker/cli/cli/command/image/push.go deleted file mode 100644 index cc95897bd..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/push.go +++ /dev/null @@ -1,61 +0,0 @@ -package image - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/distribution/reference" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/registry" - "github.com/spf13/cobra" -) - -// NewPushCommand creates a new `docker push` command -func NewPushCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "push [OPTIONS] NAME[:TAG]", - Short: "Push an image or a repository to a registry", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runPush(dockerCli, args[0]) - }, - } - - flags := cmd.Flags() - - command.AddTrustSigningFlags(flags) - - return cmd -} - -func runPush(dockerCli command.Cli, remote string) error { - ref, err := reference.ParseNormalizedNamed(remote) - if err != nil { - return err - } - - // Resolve the Repository name from fqn to RepositoryInfo - repoInfo, err := registry.ParseRepositoryInfo(ref) - if err != nil { - return err - } - - ctx := context.Background() - - // Resolve the Auth config relevant for this server - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) - requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push") - - if command.IsTrusted() { - return trustedPush(ctx, dockerCli, repoInfo, ref, authConfig, requestPrivilege) - } - - responseBody, err := imagePushPrivileged(ctx, dockerCli, authConfig, ref, requestPrivilege) - if err != nil { - return err - } - - defer responseBody.Close() - return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/push_test.go b/vendor/github.com/docker/cli/cli/command/image/push_test.go deleted file mode 100644 index 48d78b7d0..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/push_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package image - -import ( - "io" - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNewPushCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - imagePushFunc func(ref string, options types.ImagePushOptions) (io.ReadCloser, error) - }{ - { - name: "wrong-args", - args: []string{}, - expectedError: "requires exactly 1 argument.", - }, - { - name: "invalid-name", - args: []string{"UPPERCASE_REPO"}, - expectedError: "invalid reference format: repository name must be lowercase", - }, - { - name: "push-failed", - args: []string{"image:repo"}, - expectedError: "Failed to push", - imagePushFunc: func(ref string, options types.ImagePushOptions) (io.ReadCloser, error) { - return ioutil.NopCloser(strings.NewReader("")), errors.Errorf("Failed to push") - }, - }, - { - name: "trust-error", - args: []string{"--disable-content-trust=false", "image:repo"}, - expectedError: "you are not authorized to perform this operation: server returned 401.", - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imagePushFunc: tc.imagePushFunc}) - cmd := NewPushCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewPushCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - }{ - { - name: "simple", - args: []string{"image:tag"}, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - imagePushFunc: func(ref string, options types.ImagePushOptions) (io.ReadCloser, error) { - return ioutil.NopCloser(strings.NewReader("")), nil - }, - }) - cmd := NewPushCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - assert.NoError(t, cmd.Execute()) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/remove.go b/vendor/github.com/docker/cli/cli/command/image/remove.go deleted file mode 100644 index 894d30574..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/remove.go +++ /dev/null @@ -1,82 +0,0 @@ -package image - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type removeOptions struct { - force bool - noPrune bool -} - -// NewRemoveCommand creates a new `docker remove` command -func NewRemoveCommand(dockerCli command.Cli) *cobra.Command { - var opts removeOptions - - cmd := &cobra.Command{ - Use: "rmi [OPTIONS] IMAGE [IMAGE...]", - Short: "Remove one or more images", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, opts, args) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&opts.force, "force", "f", false, "Force removal of the image") - flags.BoolVar(&opts.noPrune, "no-prune", false, "Do not delete untagged parents") - - return cmd -} - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - cmd := *NewRemoveCommand(dockerCli) - cmd.Aliases = []string{"rmi", "remove"} - cmd.Use = "rm [OPTIONS] IMAGE [IMAGE...]" - return &cmd -} - -func runRemove(dockerCli command.Cli, opts removeOptions, images []string) error { - client := dockerCli.Client() - ctx := context.Background() - - options := types.ImageRemoveOptions{ - Force: opts.force, - PruneChildren: !opts.noPrune, - } - - var errs []string - for _, img := range images { - dels, err := client.ImageRemove(ctx, img, options) - if err != nil { - errs = append(errs, err.Error()) - } else { - for _, del := range dels { - if del.Deleted != "" { - fmt.Fprintf(dockerCli.Out(), "Deleted: %s\n", del.Deleted) - } else { - fmt.Fprintf(dockerCli.Out(), "Untagged: %s\n", del.Untagged) - } - } - } - } - - if len(errs) > 0 { - msg := strings.Join(errs, "\n") - if !opts.force { - return errors.New(msg) - } - fmt.Fprintf(dockerCli.Err(), msg) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/image/remove_test.go b/vendor/github.com/docker/cli/cli/command/image/remove_test.go deleted file mode 100644 index e89e6ddaf..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/remove_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package image - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNewRemoveCommandAlias(t *testing.T) { - cmd := newRemoveCommand(test.NewFakeCli(&fakeClient{})) - assert.True(t, cmd.HasAlias("rmi")) - assert.True(t, cmd.HasAlias("remove")) - assert.False(t, cmd.HasAlias("other")) -} - -func TestNewRemoveCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - expectedError string - imageRemoveFunc func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) - }{ - { - name: "wrong args", - expectedError: "requires at least 1 argument.", - }, - { - name: "ImageRemove fail", - args: []string{"arg1"}, - expectedError: "error removing image", - imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - assert.False(t, options.Force) - assert.True(t, options.PruneChildren) - return []types.ImageDeleteResponseItem{}, errors.Errorf("error removing image") - }, - }, - } - for _, tc := range testCases { - cmd := NewRemoveCommand(test.NewFakeCli(&fakeClient{ - imageRemoveFunc: tc.imageRemoveFunc, - })) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewRemoveCommandSuccess(t *testing.T) { - testCases := []struct { - name string - args []string - imageRemoveFunc func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) - expectedErrMsg string - }{ - { - name: "Image Deleted", - args: []string{"image1"}, - imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - assert.Equal(t, "image1", image) - return []types.ImageDeleteResponseItem{{Deleted: image}}, nil - }, - }, - { - name: "Image Deleted with force option", - args: []string{"-f", "image1"}, - imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - assert.Equal(t, "image1", image) - return []types.ImageDeleteResponseItem{}, errors.Errorf("error removing image") - }, - expectedErrMsg: "error removing image", - }, - { - name: "Image Untagged", - args: []string{"image1"}, - imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - assert.Equal(t, "image1", image) - return []types.ImageDeleteResponseItem{{Untagged: image}}, nil - }, - }, - { - name: "Image Deleted and Untagged", - args: []string{"image1", "image2"}, - imageRemoveFunc: func(image string, options types.ImageRemoveOptions) ([]types.ImageDeleteResponseItem, error) { - if image == "image1" { - return []types.ImageDeleteResponseItem{{Untagged: image}}, nil - } - return []types.ImageDeleteResponseItem{{Deleted: image}}, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imageRemoveFunc: tc.imageRemoveFunc}) - cmd := NewRemoveCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - assert.NoError(t, cmd.Execute()) - if tc.expectedErrMsg != "" { - assert.Equal(t, tc.expectedErrMsg, cli.ErrBuffer().String()) - } - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("remove-command-success.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/save.go b/vendor/github.com/docker/cli/cli/command/image/save.go deleted file mode 100644 index 9cae97b37..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/save.go +++ /dev/null @@ -1,72 +0,0 @@ -package image - -import ( - "io" - "os" - "path/filepath" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type saveOptions struct { - images []string - output string -} - -// NewSaveCommand creates a new `docker save` command -func NewSaveCommand(dockerCli command.Cli) *cobra.Command { - var opts saveOptions - - cmd := &cobra.Command{ - Use: "save [OPTIONS] IMAGE [IMAGE...]", - Short: "Save one or more images to a tar archive (streamed to STDOUT by default)", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.images = args - return runSave(dockerCli, opts) - }, - } - - flags := cmd.Flags() - - flags.StringVarP(&opts.output, "output", "o", "", "Write to a file, instead of STDOUT") - - return cmd -} - -func runSave(dockerCli command.Cli, opts saveOptions) error { - if opts.output == "" && dockerCli.Out().IsTerminal() { - return errors.New("cowardly refusing to save to a terminal. Use the -o flag or redirect") - } - - if err := validateOutputPath(opts.output); err != nil { - return errors.Wrap(err, "failed to save image") - } - - responseBody, err := dockerCli.Client().ImageSave(context.Background(), opts.images) - if err != nil { - return err - } - defer responseBody.Close() - - if opts.output == "" { - _, err := io.Copy(dockerCli.Out(), responseBody) - return err - } - - return command.CopyToFile(opts.output, responseBody) -} - -func validateOutputPath(path string) error { - dir := filepath.Dir(path) - if dir != "" && dir != "." { - if _, err := os.Stat(dir); os.IsNotExist(err) { - return errors.Errorf("unable to validate output path: directory %q does not exist", dir) - } - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/image/save_test.go b/vendor/github.com/docker/cli/cli/command/image/save_test.go deleted file mode 100644 index f402da7e8..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/save_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package image - -import ( - "io" - "io/ioutil" - "os" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewSaveCommandErrors(t *testing.T) { - testCases := []struct { - name string - args []string - isTerminal bool - expectedError string - imageSaveFunc func(images []string) (io.ReadCloser, error) - }{ - { - name: "wrong args", - args: []string{}, - expectedError: "requires at least 1 argument.", - }, - { - name: "output to terminal", - args: []string{"output", "file", "arg1"}, - isTerminal: true, - expectedError: "cowardly refusing to save to a terminal. Use the -o flag or redirect", - }, - { - name: "ImageSave fail", - args: []string{"arg1"}, - isTerminal: false, - expectedError: "error saving image", - imageSaveFunc: func(images []string) (io.ReadCloser, error) { - return ioutil.NopCloser(strings.NewReader("")), errors.Errorf("error saving image") - }, - }, - { - name: "output directory does not exist", - args: []string{"-o", "fakedir/out.tar", "arg1"}, - expectedError: "failed to save image: unable to validate output path: directory \"fakedir\" does not exist", - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{imageSaveFunc: tc.imageSaveFunc}) - cli.Out().SetIsTerminal(tc.isTerminal) - cmd := NewSaveCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNewSaveCommandSuccess(t *testing.T) { - testCases := []struct { - args []string - isTerminal bool - imageSaveFunc func(images []string) (io.ReadCloser, error) - deferredFunc func() - }{ - { - args: []string{"-o", "save_tmp_file", "arg1"}, - isTerminal: true, - imageSaveFunc: func(images []string) (io.ReadCloser, error) { - require.Len(t, images, 1) - assert.Equal(t, "arg1", images[0]) - return ioutil.NopCloser(strings.NewReader("")), nil - }, - deferredFunc: func() { - os.Remove("save_tmp_file") - }, - }, - { - args: []string{"arg1", "arg2"}, - isTerminal: false, - imageSaveFunc: func(images []string) (io.ReadCloser, error) { - require.Len(t, images, 2) - assert.Equal(t, "arg1", images[0]) - assert.Equal(t, "arg2", images[1]) - return ioutil.NopCloser(strings.NewReader("")), nil - }, - }, - } - for _, tc := range testCases { - cmd := NewSaveCommand(test.NewFakeCli(&fakeClient{ - imageSaveFunc: func(images []string) (io.ReadCloser, error) { - return ioutil.NopCloser(strings.NewReader("")), nil - }, - })) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(tc.args) - assert.NoError(t, cmd.Execute()) - if tc.deferredFunc != nil { - tc.deferredFunc() - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/image/tag.go b/vendor/github.com/docker/cli/cli/command/image/tag.go deleted file mode 100644 index 2a50c127c..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/tag.go +++ /dev/null @@ -1,41 +0,0 @@ -package image - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -type tagOptions struct { - image string - name string -} - -// NewTagCommand creates a new `docker tag` command -func NewTagCommand(dockerCli command.Cli) *cobra.Command { - var opts tagOptions - - cmd := &cobra.Command{ - Use: "tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]", - Short: "Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - opts.image = args[0] - opts.name = args[1] - return runTag(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.SetInterspersed(false) - - return cmd -} - -func runTag(dockerCli command.Cli, opts tagOptions) error { - ctx := context.Background() - - return dockerCli.Client().ImageTag(ctx, opts.image, opts.name) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/tag_test.go b/vendor/github.com/docker/cli/cli/command/image/tag_test.go deleted file mode 100644 index 069852296..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/tag_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package image - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/stretchr/testify/assert" -) - -func TestCliNewTagCommandErrors(t *testing.T) { - testCases := [][]string{ - {}, - {"image1"}, - {"image1", "image2", "image3"}, - } - expectedError := "\"tag\" requires exactly 2 arguments." - for _, args := range testCases { - cmd := NewTagCommand(test.NewFakeCli(&fakeClient{})) - cmd.SetArgs(args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), expectedError) - } -} - -func TestCliNewTagCommand(t *testing.T) { - cmd := NewTagCommand( - test.NewFakeCli(&fakeClient{ - imageTagFunc: func(image string, ref string) error { - assert.Equal(t, "image1", image) - assert.Equal(t, "image2", ref) - return nil - }, - })) - cmd.SetArgs([]string{"image1", "image2"}) - cmd.SetOutput(ioutil.Discard) - assert.NoError(t, cmd.Execute()) - value, _ := cmd.Flags().GetBool("interspersed") - assert.False(t, value) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.quiet-no-trunc.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.quiet-no-trunc.golden deleted file mode 100644 index 65103f635..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.quiet-no-trunc.golden +++ /dev/null @@ -1 +0,0 @@ -1234567890123456789 diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.quiet.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.quiet.golden deleted file mode 100644 index 42c7c82cc..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.quiet.golden +++ /dev/null @@ -1 +0,0 @@ -tag diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.simple.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.simple.golden deleted file mode 100644 index 8aa590526..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/history-command-success.simple.golden +++ /dev/null @@ -1,2 +0,0 @@ -IMAGE CREATED CREATED BY SIZE COMMENT -123456789012 Less than a second ago 0B diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/import-command-success.input.txt b/vendor/github.com/docker/cli/cli/command/image/testdata/import-command-success.input.txt deleted file mode 100644 index 7ab5949b1..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/import-command-success.input.txt +++ /dev/null @@ -1 +0,0 @@ -file input test \ No newline at end of file diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.format.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.format.golden deleted file mode 100644 index f934996b0..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.format.golden +++ /dev/null @@ -1 +0,0 @@ -'image' diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.simple-many.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.simple-many.golden deleted file mode 100644 index f72c96f74..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.simple-many.golden +++ /dev/null @@ -1,56 +0,0 @@ -[ - { - "Id": "", - "RepoTags": null, - "RepoDigests": null, - "Parent": "", - "Comment": "", - "Created": "", - "Container": "", - "ContainerConfig": null, - "DockerVersion": "", - "Author": "", - "Config": null, - "Architecture": "", - "Os": "", - "Size": 0, - "VirtualSize": 0, - "GraphDriver": { - "Data": null, - "Name": "" - }, - "RootFS": { - "Type": "" - }, - "Metadata": { - "LastTagTime": "0001-01-01T00:00:00Z" - } - }, - { - "Id": "", - "RepoTags": null, - "RepoDigests": null, - "Parent": "", - "Comment": "", - "Created": "", - "Container": "", - "ContainerConfig": null, - "DockerVersion": "", - "Author": "", - "Config": null, - "Architecture": "", - "Os": "", - "Size": 0, - "VirtualSize": 0, - "GraphDriver": { - "Data": null, - "Name": "" - }, - "RootFS": { - "Type": "" - }, - "Metadata": { - "LastTagTime": "0001-01-01T00:00:00Z" - } - } -] diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.simple.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.simple.golden deleted file mode 100644 index 878463ffc..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/inspect-command-success.simple.golden +++ /dev/null @@ -1,29 +0,0 @@ -[ - { - "Id": "", - "RepoTags": null, - "RepoDigests": null, - "Parent": "", - "Comment": "", - "Created": "", - "Container": "", - "ContainerConfig": null, - "DockerVersion": "", - "Author": "", - "Config": null, - "Architecture": "", - "Os": "", - "Size": 0, - "VirtualSize": 0, - "GraphDriver": { - "Data": null, - "Name": "" - }, - "RootFS": { - "Type": "" - }, - "Metadata": { - "LastTagTime": "0001-01-01T00:00:00Z" - } - } -] diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.filters.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.filters.golden deleted file mode 100644 index e3b8109bc..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.filters.golden +++ /dev/null @@ -1 +0,0 @@ -REPOSITORY TAG IMAGE ID CREATED SIZE diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.format.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.format.golden deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.match-name.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.match-name.golden deleted file mode 100644 index e3b8109bc..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.match-name.golden +++ /dev/null @@ -1 +0,0 @@ -REPOSITORY TAG IMAGE ID CREATED SIZE diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.quiet-format.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.quiet-format.golden deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.simple.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.simple.golden deleted file mode 100644 index e3b8109bc..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/list-command-success.simple.golden +++ /dev/null @@ -1 +0,0 @@ -REPOSITORY TAG IMAGE ID CREATED SIZE diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.input-file.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.input-file.golden deleted file mode 100644 index 51da4200a..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.input-file.golden +++ /dev/null @@ -1 +0,0 @@ -Success \ No newline at end of file diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.input.txt b/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.input.txt deleted file mode 100644 index 7ab5949b1..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.input.txt +++ /dev/null @@ -1 +0,0 @@ -file input test \ No newline at end of file diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.json.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.json.golden deleted file mode 100644 index c17f16ecd..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.json.golden +++ /dev/null @@ -1 +0,0 @@ -1: diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.simple.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.simple.golden deleted file mode 100644 index 51da4200a..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/load-command-success.simple.golden +++ /dev/null @@ -1 +0,0 @@ -Success \ No newline at end of file diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.all.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.all.golden deleted file mode 100644 index 4d1445280..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.all.golden +++ /dev/null @@ -1,2 +0,0 @@ -WARNING! This will remove all images without at least one container associated to them. -Are you sure you want to continue? [y/N] Total reclaimed space: 0B diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.force-deleted.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.force-deleted.golden deleted file mode 100644 index 1b6efd4a9..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.force-deleted.golden +++ /dev/null @@ -1,4 +0,0 @@ -Deleted Images: -deleted: image1 - -Total reclaimed space: 1B diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.force-untagged.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.force-untagged.golden deleted file mode 100644 index 725468fe5..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/prune-command-success.force-untagged.golden +++ /dev/null @@ -1,4 +0,0 @@ -Deleted Images: -untagged: image1 - -Total reclaimed space: 2B diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/pull-command-success.simple-no-tag.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/pull-command-success.simple-no-tag.golden deleted file mode 100644 index 946de409a..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/pull-command-success.simple-no-tag.golden +++ /dev/null @@ -1 +0,0 @@ -Using default tag: latest diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/pull-command-success.simple.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/pull-command-success.simple.golden deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted and Untagged.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted and Untagged.golden deleted file mode 100644 index 94db08448..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted and Untagged.golden +++ /dev/null @@ -1,2 +0,0 @@ -Untagged: image1 -Deleted: image2 diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted with force option.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted with force option.golden deleted file mode 100644 index e69de29bb..000000000 diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted.golden deleted file mode 100644 index 445df11a9..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Deleted.golden +++ /dev/null @@ -1 +0,0 @@ -Deleted: image1 diff --git a/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Untagged.golden b/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Untagged.golden deleted file mode 100644 index ebbb4075e..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/testdata/remove-command-success.Image Untagged.golden +++ /dev/null @@ -1 +0,0 @@ -Untagged: image1 diff --git a/vendor/github.com/docker/cli/cli/command/image/trust.go b/vendor/github.com/docker/cli/cli/command/image/trust.go deleted file mode 100644 index 8d94164e5..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/trust.go +++ /dev/null @@ -1,384 +0,0 @@ -package image - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "io" - "path" - "sort" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/trust" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/registry" - "github.com/docker/notary/client" - "github.com/docker/notary/tuf/data" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" -) - -type target struct { - name string - digest digest.Digest - size int64 -} - -// trustedPush handles content trust pushing of an image -func trustedPush(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error { - responseBody, err := imagePushPrivileged(ctx, cli, authConfig, ref, requestPrivilege) - if err != nil { - return err - } - - defer responseBody.Close() - - return PushTrustedReference(cli, repoInfo, ref, authConfig, responseBody) -} - -// PushTrustedReference pushes a canonical reference to the trust server. -// nolint: gocyclo -func PushTrustedReference(streams command.Streams, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, in io.Reader) error { - // If it is a trusted push we would like to find the target entry which match the - // tag provided in the function and then do an AddTarget later. - target := &client.Target{} - // Count the times of calling for handleTarget, - // if it is called more that once, that should be considered an error in a trusted push. - cnt := 0 - handleTarget := func(aux *json.RawMessage) { - cnt++ - if cnt > 1 { - // handleTarget should only be called one. This will be treated as an error. - return - } - - var pushResult types.PushResult - err := json.Unmarshal(*aux, &pushResult) - if err == nil && pushResult.Tag != "" { - if dgst, err := digest.Parse(pushResult.Digest); err == nil { - h, err := hex.DecodeString(dgst.Hex()) - if err != nil { - target = nil - return - } - target.Name = pushResult.Tag - target.Hashes = data.Hashes{string(dgst.Algorithm()): h} - target.Length = int64(pushResult.Size) - } - } - } - - var tag string - switch x := ref.(type) { - case reference.Canonical: - return errors.New("cannot push a digest reference") - case reference.NamedTagged: - tag = x.Tag() - default: - // We want trust signatures to always take an explicit tag, - // otherwise it will act as an untrusted push. - if err := jsonmessage.DisplayJSONMessagesToStream(in, streams.Out(), nil); err != nil { - return err - } - fmt.Fprintln(streams.Out(), "No tag specified, skipping trust metadata push") - return nil - } - - if err := jsonmessage.DisplayJSONMessagesToStream(in, streams.Out(), handleTarget); err != nil { - return err - } - - if cnt > 1 { - return errors.Errorf("internal error: only one call to handleTarget expected") - } - - if target == nil { - fmt.Fprintln(streams.Out(), "No targets found, please provide a specific tag in order to sign it") - return nil - } - - fmt.Fprintln(streams.Out(), "Signing and pushing trust metadata") - - repo, err := trust.GetNotaryRepository(streams, repoInfo, authConfig, "push", "pull") - if err != nil { - fmt.Fprintf(streams.Out(), "Error establishing connection to notary repository: %s\n", err) - return err - } - - // get the latest repository metadata so we can figure out which roles to sign - err = repo.Update(false) - - switch err.(type) { - case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist: - keys := repo.CryptoService.ListKeys(data.CanonicalRootRole) - var rootKeyID string - // always select the first root key - if len(keys) > 0 { - sort.Strings(keys) - rootKeyID = keys[0] - } else { - rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, "", data.ECDSAKey) - if err != nil { - return err - } - rootKeyID = rootPublicKey.ID() - } - - // Initialize the notary repository with a remotely managed snapshot key - if err := repo.Initialize([]string{rootKeyID}, data.CanonicalSnapshotRole); err != nil { - return trust.NotaryError(repoInfo.Name.Name(), err) - } - fmt.Fprintf(streams.Out(), "Finished initializing %q\n", repoInfo.Name.Name()) - err = repo.AddTarget(target, data.CanonicalTargetsRole) - case nil: - // already initialized and we have successfully downloaded the latest metadata - err = addTargetToAllSignableRoles(repo, target) - default: - return trust.NotaryError(repoInfo.Name.Name(), err) - } - - if err == nil { - err = repo.Publish() - } - - if err != nil { - fmt.Fprintf(streams.Out(), "Failed to sign %q:%s - %s\n", repoInfo.Name.Name(), tag, err.Error()) - return trust.NotaryError(repoInfo.Name.Name(), err) - } - - fmt.Fprintf(streams.Out(), "Successfully signed %q:%s\n", repoInfo.Name.Name(), tag) - return nil -} - -// Attempt to add the image target to all the top level delegation roles we can -// (based on whether we have the signing key and whether the role's path allows -// us to). -// If there are no delegation roles, we add to the targets role. -func addTargetToAllSignableRoles(repo *client.NotaryRepository, target *client.Target) error { - var signableRoles []string - - // translate the full key names, which includes the GUN, into just the key IDs - allCanonicalKeyIDs := make(map[string]struct{}) - for fullKeyID := range repo.CryptoService.ListAllKeys() { - allCanonicalKeyIDs[path.Base(fullKeyID)] = struct{}{} - } - - allDelegationRoles, err := repo.GetDelegationRoles() - if err != nil { - return err - } - - // if there are no delegation roles, then just try to sign it into the targets role - if len(allDelegationRoles) == 0 { - return repo.AddTarget(target, data.CanonicalTargetsRole) - } - - // there are delegation roles, find every delegation role we have a key for, and - // attempt to sign into into all those roles. - for _, delegationRole := range allDelegationRoles { - // We do not support signing any delegation role that isn't a direct child of the targets role. - // Also don't bother checking the keys if we can't add the target - // to this role due to path restrictions - if path.Dir(delegationRole.Name) != data.CanonicalTargetsRole || !delegationRole.CheckPaths(target.Name) { - continue - } - - for _, canonicalKeyID := range delegationRole.KeyIDs { - if _, ok := allCanonicalKeyIDs[canonicalKeyID]; ok { - signableRoles = append(signableRoles, delegationRole.Name) - break - } - } - } - - if len(signableRoles) == 0 { - return errors.Errorf("no valid signing keys for delegation roles") - } - - return repo.AddTarget(target, signableRoles...) -} - -// imagePushPrivileged push the image -func imagePushPrivileged(ctx context.Context, cli command.Cli, authConfig types.AuthConfig, ref reference.Reference, requestPrivilege types.RequestPrivilegeFunc) (io.ReadCloser, error) { - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return nil, err - } - options := types.ImagePushOptions{ - RegistryAuth: encodedAuth, - PrivilegeFunc: requestPrivilege, - } - - return cli.Client().ImagePush(ctx, reference.FamiliarString(ref), options) -} - -// trustedPull handles content trust pulling of an image -func trustedPull(ctx context.Context, cli command.Cli, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error { - var refs []target - - notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull") - if err != nil { - fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err) - return err - } - - if tagged, isTagged := ref.(reference.NamedTagged); !isTagged { - // List all targets - targets, err := notaryRepo.ListTargets(trust.ReleasesRole, data.CanonicalTargetsRole) - if err != nil { - return trust.NotaryError(ref.Name(), err) - } - for _, tgt := range targets { - t, err := convertTarget(tgt.Target) - if err != nil { - fmt.Fprintf(cli.Out(), "Skipping target for %q\n", reference.FamiliarName(ref)) - continue - } - // Only list tags in the top level targets role or the releases delegation role - ignore - // all other delegation roles - if tgt.Role != trust.ReleasesRole && tgt.Role != data.CanonicalTargetsRole { - continue - } - refs = append(refs, t) - } - if len(refs) == 0 { - return trust.NotaryError(ref.Name(), errors.Errorf("No trusted tags for %s", ref.Name())) - } - } else { - t, err := notaryRepo.GetTargetByName(tagged.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole) - if err != nil { - return trust.NotaryError(ref.Name(), err) - } - // Only get the tag if it's in the top level targets role or the releases delegation role - // ignore it if it's in any other delegation roles - if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole { - return trust.NotaryError(ref.Name(), errors.Errorf("No trust data for %s", tagged.Tag())) - } - - logrus.Debugf("retrieving target for %s role\n", t.Role) - r, err := convertTarget(t.Target) - if err != nil { - return err - - } - refs = append(refs, r) - } - - for i, r := range refs { - displayTag := r.name - if displayTag != "" { - displayTag = ":" + displayTag - } - fmt.Fprintf(cli.Out(), "Pull (%d of %d): %s%s@%s\n", i+1, len(refs), reference.FamiliarName(ref), displayTag, r.digest) - - trustedRef, err := reference.WithDigest(reference.TrimNamed(ref), r.digest) - if err != nil { - return err - } - if err := imagePullPrivileged(ctx, cli, authConfig, reference.FamiliarString(trustedRef), requestPrivilege, false); err != nil { - return err - } - - tagged, err := reference.WithTag(reference.TrimNamed(ref), r.name) - if err != nil { - return err - } - - if err := TagTrusted(ctx, cli, trustedRef, tagged); err != nil { - return err - } - } - return nil -} - -// imagePullPrivileged pulls the image and displays it to the output -func imagePullPrivileged(ctx context.Context, cli command.Cli, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error { - - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return err - } - options := types.ImagePullOptions{ - RegistryAuth: encodedAuth, - PrivilegeFunc: requestPrivilege, - All: all, - } - - responseBody, err := cli.Client().ImagePull(ctx, ref, options) - if err != nil { - return err - } - defer responseBody.Close() - - return jsonmessage.DisplayJSONMessagesToStream(responseBody, cli.Out(), nil) -} - -// TrustedReference returns the canonical trusted reference for an image reference -func TrustedReference(ctx context.Context, cli command.Cli, ref reference.NamedTagged, rs registry.Service) (reference.Canonical, error) { - var ( - repoInfo *registry.RepositoryInfo - err error - ) - if rs != nil { - repoInfo, err = rs.ResolveRepository(ref) - } else { - repoInfo, err = registry.ParseRepositoryInfo(ref) - } - if err != nil { - return nil, err - } - - // Resolve the Auth config relevant for this server - authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index) - - notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull") - if err != nil { - fmt.Fprintf(cli.Out(), "Error establishing connection to trust repository: %s\n", err) - return nil, err - } - - t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole) - if err != nil { - return nil, trust.NotaryError(repoInfo.Name.Name(), err) - } - // Only list tags in the top level targets role or the releases delegation role - ignore - // all other delegation roles - if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole { - return nil, trust.NotaryError(repoInfo.Name.Name(), errors.Errorf("No trust data for %s", ref.Tag())) - } - r, err := convertTarget(t.Target) - if err != nil { - return nil, err - - } - - return reference.WithDigest(reference.TrimNamed(ref), r.digest) -} - -func convertTarget(t client.Target) (target, error) { - h, ok := t.Hashes["sha256"] - if !ok { - return target{}, errors.New("no valid hash, expecting sha256") - } - return target{ - name: t.Name, - digest: digest.NewDigestFromHex("sha256", hex.EncodeToString(h)), - size: t.Length, - }, nil -} - -// TagTrusted tags a trusted ref -// nolint: interfacer -func TagTrusted(ctx context.Context, cli command.Cli, trustedRef reference.Canonical, ref reference.NamedTagged) error { - // Use familiar references when interacting with client and output - familiarRef := reference.FamiliarString(ref) - trustedFamiliarRef := reference.FamiliarString(trustedRef) - - fmt.Fprintf(cli.Out(), "Tagging %s as %s\n", trustedFamiliarRef, familiarRef) - - return cli.Client().ImageTag(ctx, trustedFamiliarRef, familiarRef) -} diff --git a/vendor/github.com/docker/cli/cli/command/image/trust_test.go b/vendor/github.com/docker/cli/cli/command/image/trust_test.go deleted file mode 100644 index 0a57f9b3b..000000000 --- a/vendor/github.com/docker/cli/cli/command/image/trust_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package image - -import ( - "os" - "testing" - - "github.com/docker/cli/cli/trust" - registrytypes "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/registry" -) - -func unsetENV() { - os.Unsetenv("DOCKER_CONTENT_TRUST") - os.Unsetenv("DOCKER_CONTENT_TRUST_SERVER") -} - -func TestENVTrustServer(t *testing.T) { - defer unsetENV() - indexInfo := ®istrytypes.IndexInfo{Name: "testserver"} - if err := os.Setenv("DOCKER_CONTENT_TRUST_SERVER", "https://notary-test.com:5000"); err != nil { - t.Fatal("Failed to set ENV variable") - } - output, err := trust.Server(indexInfo) - expectedStr := "https://notary-test.com:5000" - if err != nil || output != expectedStr { - t.Fatalf("Expected server to be %s, got %s", expectedStr, output) - } -} - -func TestHTTPENVTrustServer(t *testing.T) { - defer unsetENV() - indexInfo := ®istrytypes.IndexInfo{Name: "testserver"} - if err := os.Setenv("DOCKER_CONTENT_TRUST_SERVER", "http://notary-test.com:5000"); err != nil { - t.Fatal("Failed to set ENV variable") - } - _, err := trust.Server(indexInfo) - if err == nil { - t.Fatal("Expected error with invalid scheme") - } -} - -func TestOfficialTrustServer(t *testing.T) { - indexInfo := ®istrytypes.IndexInfo{Name: "testserver", Official: true} - output, err := trust.Server(indexInfo) - if err != nil || output != registry.NotaryServer { - t.Fatalf("Expected server to be %s, got %s", registry.NotaryServer, output) - } -} - -func TestNonOfficialTrustServer(t *testing.T) { - indexInfo := ®istrytypes.IndexInfo{Name: "testserver", Official: false} - output, err := trust.Server(indexInfo) - expectedStr := "https://" + indexInfo.Name - if err != nil || output != expectedStr { - t.Fatalf("Expected server to be %s, got %s", expectedStr, output) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/in.go b/vendor/github.com/docker/cli/cli/command/in.go deleted file mode 100644 index 54855c6dc..000000000 --- a/vendor/github.com/docker/cli/cli/command/in.go +++ /dev/null @@ -1,56 +0,0 @@ -package command - -import ( - "errors" - "io" - "os" - "runtime" - - "github.com/docker/docker/pkg/term" -) - -// InStream is an input stream used by the DockerCli to read user input -type InStream struct { - CommonStream - in io.ReadCloser -} - -func (i *InStream) Read(p []byte) (int, error) { - return i.in.Read(p) -} - -// Close implements the Closer interface -func (i *InStream) Close() error { - return i.in.Close() -} - -// SetRawTerminal sets raw mode on the input terminal -func (i *InStream) SetRawTerminal() (err error) { - if os.Getenv("NORAW") != "" || !i.CommonStream.isTerminal { - return nil - } - i.CommonStream.state, err = term.SetRawTerminal(i.CommonStream.fd) - return err -} - -// CheckTty checks if we are trying to attach to a container tty -// from a non-tty client input stream, and if so, returns an error. -func (i *InStream) CheckTty(attachStdin, ttyMode bool) error { - // In order to attach to a container tty, input stream for the client must - // be a tty itself: redirecting or piping the client standard input is - // incompatible with `docker run -t`, `docker exec -t` or `docker attach`. - if ttyMode && attachStdin && !i.isTerminal { - eText := "the input device is not a TTY" - if runtime.GOOS == "windows" { - return errors.New(eText + ". If you are using mintty, try prefixing the command with 'winpty'") - } - return errors.New(eText) - } - return nil -} - -// NewInStream returns a new InStream object from a ReadCloser -func NewInStream(in io.ReadCloser) *InStream { - fd, isTerminal := term.GetFdInfo(in) - return &InStream{CommonStream: CommonStream{fd: fd, isTerminal: isTerminal}, in: in} -} diff --git a/vendor/github.com/docker/cli/cli/command/inspect/inspector.go b/vendor/github.com/docker/cli/cli/command/inspect/inspector.go deleted file mode 100644 index aef31e62d..000000000 --- a/vendor/github.com/docker/cli/cli/command/inspect/inspector.go +++ /dev/null @@ -1,199 +0,0 @@ -package inspect - -import ( - "bytes" - "encoding/json" - "io" - "strings" - "text/template" - - "github.com/docker/cli/cli" - "github.com/docker/cli/templates" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" -) - -// Inspector defines an interface to implement to process elements -type Inspector interface { - Inspect(typedElement interface{}, rawElement []byte) error - Flush() error -} - -// TemplateInspector uses a text template to inspect elements. -type TemplateInspector struct { - outputStream io.Writer - buffer *bytes.Buffer - tmpl *template.Template -} - -// NewTemplateInspector creates a new inspector with a template. -func NewTemplateInspector(outputStream io.Writer, tmpl *template.Template) Inspector { - return &TemplateInspector{ - outputStream: outputStream, - buffer: new(bytes.Buffer), - tmpl: tmpl, - } -} - -// NewTemplateInspectorFromString creates a new TemplateInspector from a string -// which is compiled into a template. -func NewTemplateInspectorFromString(out io.Writer, tmplStr string) (Inspector, error) { - if tmplStr == "" { - return NewIndentedInspector(out), nil - } - - tmpl, err := templates.Parse(tmplStr) - if err != nil { - return nil, errors.Errorf("Template parsing error: %s", err) - } - return NewTemplateInspector(out, tmpl), nil -} - -// GetRefFunc is a function which used by Inspect to fetch an object from a -// reference -type GetRefFunc func(ref string) (interface{}, []byte, error) - -// Inspect fetches objects by reference using GetRefFunc and writes the json -// representation to the output writer. -func Inspect(out io.Writer, references []string, tmplStr string, getRef GetRefFunc) error { - inspector, err := NewTemplateInspectorFromString(out, tmplStr) - if err != nil { - return cli.StatusError{StatusCode: 64, Status: err.Error()} - } - - var inspectErrs []string - for _, ref := range references { - element, raw, err := getRef(ref) - if err != nil { - inspectErrs = append(inspectErrs, err.Error()) - continue - } - - if err := inspector.Inspect(element, raw); err != nil { - inspectErrs = append(inspectErrs, err.Error()) - } - } - - if err := inspector.Flush(); err != nil { - logrus.Errorf("%s\n", err) - } - - if len(inspectErrs) != 0 { - return cli.StatusError{ - StatusCode: 1, - Status: strings.Join(inspectErrs, "\n"), - } - } - return nil -} - -// Inspect executes the inspect template. -// It decodes the raw element into a map if the initial execution fails. -// This allows docker cli to parse inspect structs injected with Swarm fields. -func (i *TemplateInspector) Inspect(typedElement interface{}, rawElement []byte) error { - buffer := new(bytes.Buffer) - if err := i.tmpl.Execute(buffer, typedElement); err != nil { - if rawElement == nil { - return errors.Errorf("Template parsing error: %v", err) - } - return i.tryRawInspectFallback(rawElement) - } - i.buffer.Write(buffer.Bytes()) - i.buffer.WriteByte('\n') - return nil -} - -// tryRawInspectFallback executes the inspect template with a raw interface. -// This allows docker cli to parse inspect structs injected with Swarm fields. -func (i *TemplateInspector) tryRawInspectFallback(rawElement []byte) error { - var raw interface{} - buffer := new(bytes.Buffer) - rdr := bytes.NewReader(rawElement) - dec := json.NewDecoder(rdr) - dec.UseNumber() - - if rawErr := dec.Decode(&raw); rawErr != nil { - return errors.Errorf("unable to read inspect data: %v", rawErr) - } - - tmplMissingKey := i.tmpl.Option("missingkey=error") - if rawErr := tmplMissingKey.Execute(buffer, raw); rawErr != nil { - return errors.Errorf("Template parsing error: %v", rawErr) - } - - i.buffer.Write(buffer.Bytes()) - i.buffer.WriteByte('\n') - return nil -} - -// Flush writes the result of inspecting all elements into the output stream. -func (i *TemplateInspector) Flush() error { - if i.buffer.Len() == 0 { - _, err := io.WriteString(i.outputStream, "\n") - return err - } - _, err := io.Copy(i.outputStream, i.buffer) - return err -} - -// IndentedInspector uses a buffer to stop the indented representation of an element. -type IndentedInspector struct { - outputStream io.Writer - elements []interface{} - rawElements [][]byte -} - -// NewIndentedInspector generates a new IndentedInspector. -func NewIndentedInspector(outputStream io.Writer) Inspector { - return &IndentedInspector{ - outputStream: outputStream, - } -} - -// Inspect writes the raw element with an indented json format. -func (i *IndentedInspector) Inspect(typedElement interface{}, rawElement []byte) error { - if rawElement != nil { - i.rawElements = append(i.rawElements, rawElement) - } else { - i.elements = append(i.elements, typedElement) - } - return nil -} - -// Flush writes the result of inspecting all elements into the output stream. -func (i *IndentedInspector) Flush() error { - if len(i.elements) == 0 && len(i.rawElements) == 0 { - _, err := io.WriteString(i.outputStream, "[]\n") - return err - } - - var buffer io.Reader - if len(i.rawElements) > 0 { - bytesBuffer := new(bytes.Buffer) - bytesBuffer.WriteString("[") - for idx, r := range i.rawElements { - bytesBuffer.Write(r) - if idx < len(i.rawElements)-1 { - bytesBuffer.WriteString(",") - } - } - bytesBuffer.WriteString("]") - indented := new(bytes.Buffer) - if err := json.Indent(indented, bytesBuffer.Bytes(), "", " "); err != nil { - return err - } - buffer = indented - } else { - b, err := json.MarshalIndent(i.elements, "", " ") - if err != nil { - return err - } - buffer = bytes.NewReader(b) - } - - if _, err := io.Copy(i.outputStream, buffer); err != nil { - return err - } - _, err := io.WriteString(i.outputStream, "\n") - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/inspect/inspector_test.go b/vendor/github.com/docker/cli/cli/command/inspect/inspector_test.go deleted file mode 100644 index 7d19fceda..000000000 --- a/vendor/github.com/docker/cli/cli/command/inspect/inspector_test.go +++ /dev/null @@ -1,259 +0,0 @@ -package inspect - -import ( - "bytes" - "strings" - "testing" - - "github.com/docker/cli/templates" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type testElement struct { - DNS string `json:"Dns"` -} - -func TestTemplateInspectorDefault(t *testing.T) { - b := new(bytes.Buffer) - tmpl, err := templates.Parse("{{.DNS}}") - if err != nil { - t.Fatal(err) - } - i := NewTemplateInspector(b, tmpl) - if err := i.Inspect(testElement{"0.0.0.0"}, nil); err != nil { - t.Fatal(err) - } - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - if b.String() != "0.0.0.0\n" { - t.Fatalf("Expected `0.0.0.0\\n`, got `%s`", b.String()) - } -} - -func TestTemplateInspectorEmpty(t *testing.T) { - b := new(bytes.Buffer) - tmpl, err := templates.Parse("{{.DNS}}") - if err != nil { - t.Fatal(err) - } - i := NewTemplateInspector(b, tmpl) - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - if b.String() != "\n" { - t.Fatalf("Expected `\\n`, got `%s`", b.String()) - } -} - -func TestTemplateInspectorTemplateError(t *testing.T) { - b := new(bytes.Buffer) - tmpl, err := templates.Parse("{{.Foo}}") - if err != nil { - t.Fatal(err) - } - i := NewTemplateInspector(b, tmpl) - - err = i.Inspect(testElement{"0.0.0.0"}, nil) - if err == nil { - t.Fatal("Expected error got nil") - } - - if !strings.HasPrefix(err.Error(), "Template parsing error") { - t.Fatalf("Expected template error, got %v", err) - } -} - -func TestTemplateInspectorRawFallback(t *testing.T) { - b := new(bytes.Buffer) - tmpl, err := templates.Parse("{{.Dns}}") - if err != nil { - t.Fatal(err) - } - i := NewTemplateInspector(b, tmpl) - if err := i.Inspect(testElement{"0.0.0.0"}, []byte(`{"Dns": "0.0.0.0"}`)); err != nil { - t.Fatal(err) - } - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - if b.String() != "0.0.0.0\n" { - t.Fatalf("Expected `0.0.0.0\\n`, got `%s`", b.String()) - } -} - -func TestTemplateInspectorRawFallbackError(t *testing.T) { - b := new(bytes.Buffer) - tmpl, err := templates.Parse("{{.Dns}}") - if err != nil { - t.Fatal(err) - } - i := NewTemplateInspector(b, tmpl) - err = i.Inspect(testElement{"0.0.0.0"}, []byte(`{"Foo": "0.0.0.0"}`)) - if err == nil { - t.Fatal("Expected error got nil") - } - - if !strings.HasPrefix(err.Error(), "Template parsing error") { - t.Fatalf("Expected template error, got %v", err) - } -} - -func TestTemplateInspectorMultiple(t *testing.T) { - b := new(bytes.Buffer) - tmpl, err := templates.Parse("{{.DNS}}") - if err != nil { - t.Fatal(err) - } - i := NewTemplateInspector(b, tmpl) - - if err := i.Inspect(testElement{"0.0.0.0"}, nil); err != nil { - t.Fatal(err) - } - if err := i.Inspect(testElement{"1.1.1.1"}, nil); err != nil { - t.Fatal(err) - } - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - if b.String() != "0.0.0.0\n1.1.1.1\n" { - t.Fatalf("Expected `0.0.0.0\\n1.1.1.1\\n`, got `%s`", b.String()) - } -} - -func TestIndentedInspectorDefault(t *testing.T) { - b := new(bytes.Buffer) - i := NewIndentedInspector(b) - if err := i.Inspect(testElement{"0.0.0.0"}, nil); err != nil { - t.Fatal(err) - } - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - - expected := `[ - { - "Dns": "0.0.0.0" - } -] -` - if b.String() != expected { - t.Fatalf("Expected `%s`, got `%s`", expected, b.String()) - } -} - -func TestIndentedInspectorMultiple(t *testing.T) { - b := new(bytes.Buffer) - i := NewIndentedInspector(b) - if err := i.Inspect(testElement{"0.0.0.0"}, nil); err != nil { - t.Fatal(err) - } - - if err := i.Inspect(testElement{"1.1.1.1"}, nil); err != nil { - t.Fatal(err) - } - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - - expected := `[ - { - "Dns": "0.0.0.0" - }, - { - "Dns": "1.1.1.1" - } -] -` - if b.String() != expected { - t.Fatalf("Expected `%s`, got `%s`", expected, b.String()) - } -} - -func TestIndentedInspectorEmpty(t *testing.T) { - b := new(bytes.Buffer) - i := NewIndentedInspector(b) - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - - expected := "[]\n" - if b.String() != expected { - t.Fatalf("Expected `%s`, got `%s`", expected, b.String()) - } -} - -func TestIndentedInspectorRawElements(t *testing.T) { - b := new(bytes.Buffer) - i := NewIndentedInspector(b) - if err := i.Inspect(testElement{"0.0.0.0"}, []byte(`{"Dns": "0.0.0.0", "Node": "0"}`)); err != nil { - t.Fatal(err) - } - - if err := i.Inspect(testElement{"1.1.1.1"}, []byte(`{"Dns": "1.1.1.1", "Node": "1"}`)); err != nil { - t.Fatal(err) - } - - if err := i.Flush(); err != nil { - t.Fatal(err) - } - - expected := `[ - { - "Dns": "0.0.0.0", - "Node": "0" - }, - { - "Dns": "1.1.1.1", - "Node": "1" - } -] -` - if b.String() != expected { - t.Fatalf("Expected `%s`, got `%s`", expected, b.String()) - } -} - -// moby/moby#32235 -// This test verifies that even if `tryRawInspectFallback` is called the fields containing -// numerical values are displayed correctly. -// For example, `docker inspect --format "{{.Id}} {{.Size}} alpine` and -// `docker inspect --format "{{.ID}} {{.Size}} alpine" will have the same output which is -// sha256:651aa95985aa4a17a38ffcf71f598ec461924ca96865facc2c5782ef2d2be07f 3983636 -func TestTemplateInspectorRawFallbackNumber(t *testing.T) { - // Using typedElem to automatically fall to tryRawInspectFallback. - typedElem := struct { - ID string `json:"Id"` - }{"ad3"} - testcases := []struct { - raw []byte - exp string - }{ - {raw: []byte(`{"Id": "ad3", "Size": 53317}`), exp: "53317 ad3\n"}, - {raw: []byte(`{"Id": "ad3", "Size": 53317.102}`), exp: "53317.102 ad3\n"}, - {raw: []byte(`{"Id": "ad3", "Size": 53317.0}`), exp: "53317.0 ad3\n"}, - } - b := new(bytes.Buffer) - tmpl, err := templates.Parse("{{.Size}} {{.Id}}") - require.NoError(t, err) - - i := NewTemplateInspector(b, tmpl) - for _, tc := range testcases { - err = i.Inspect(typedElem, tc.raw) - require.NoError(t, err) - - err = i.Flush() - require.NoError(t, err) - - assert.Equal(t, tc.exp, b.String()) - b.Reset() - } -} diff --git a/vendor/github.com/docker/cli/cli/command/network/client_test.go b/vendor/github.com/docker/cli/cli/command/network/client_test.go deleted file mode 100644 index 029499e93..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/client_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package network - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/network" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - networkCreateFunc func(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) - networkConnectFunc func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error - networkDisconnectFunc func(ctx context.Context, networkID, container string, force bool) error - networkListFunc func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) -} - -func (c *fakeClient) NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) { - if c.networkCreateFunc != nil { - return c.networkCreateFunc(ctx, name, options) - } - return types.NetworkCreateResponse{}, nil -} - -func (c *fakeClient) NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error { - if c.networkConnectFunc != nil { - return c.networkConnectFunc(ctx, networkID, container, config) - } - return nil -} - -func (c *fakeClient) NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error { - if c.networkDisconnectFunc != nil { - return c.networkDisconnectFunc(ctx, networkID, container, force) - } - return nil -} - -func (c *fakeClient) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { - if c.networkListFunc != nil { - return c.networkListFunc(ctx, options) - } - return []types.NetworkResource{}, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/network/cmd.go b/vendor/github.com/docker/cli/cli/command/network/cmd.go deleted file mode 100644 index 48edf1c4e..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/cmd.go +++ /dev/null @@ -1,28 +0,0 @@ -package network - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewNetworkCommand returns a cobra command for `network` subcommands -func NewNetworkCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "network", - Short: "Manage networks", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - } - cmd.AddCommand( - newConnectCommand(dockerCli), - newCreateCommand(dockerCli), - newDisconnectCommand(dockerCli), - newInspectCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - NewPruneCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/network/connect.go b/vendor/github.com/docker/cli/cli/command/network/connect.go deleted file mode 100644 index 9e925c344..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/connect.go +++ /dev/null @@ -1,62 +0,0 @@ -package network - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/network" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type connectOptions struct { - network string - container string - ipaddress string - ipv6address string - links opts.ListOpts - aliases []string - linklocalips []string -} - -func newConnectCommand(dockerCli command.Cli) *cobra.Command { - options := connectOptions{ - links: opts.NewListOpts(opts.ValidateLink), - } - - cmd := &cobra.Command{ - Use: "connect [OPTIONS] NETWORK CONTAINER", - Short: "Connect a container to a network", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - options.network = args[0] - options.container = args[1] - return runConnect(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.StringVar(&options.ipaddress, "ip", "", "IPv4 address (e.g., 172.30.100.104)") - flags.StringVar(&options.ipv6address, "ip6", "", "IPv6 address (e.g., 2001:db8::33)") - flags.Var(&options.links, "link", "Add link to another container") - flags.StringSliceVar(&options.aliases, "alias", []string{}, "Add network-scoped alias for the container") - flags.StringSliceVar(&options.linklocalips, "link-local-ip", []string{}, "Add a link-local address for the container") - - return cmd -} - -func runConnect(dockerCli command.Cli, options connectOptions) error { - client := dockerCli.Client() - - epConfig := &network.EndpointSettings{ - IPAMConfig: &network.EndpointIPAMConfig{ - IPv4Address: options.ipaddress, - IPv6Address: options.ipv6address, - LinkLocalIPs: options.linklocalips, - }, - Links: options.links.GetAll(), - Aliases: options.aliases, - } - - return client.NetworkConnect(context.Background(), options.network, options.container, epConfig) -} diff --git a/vendor/github.com/docker/cli/cli/command/network/connect_test.go b/vendor/github.com/docker/cli/cli/command/network/connect_test.go deleted file mode 100644 index 064aa041c..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/connect_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package network - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types/network" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestNetworkConnectErrors(t *testing.T) { - testCases := []struct { - args []string - networkConnectFunc func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error - expectedError string - }{ - { - expectedError: "requires exactly 2 arguments", - }, - { - args: []string{"toto", "titi"}, - networkConnectFunc: func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error { - return errors.Errorf("error connecting network") - }, - expectedError: "error connecting network", - }, - } - - for _, tc := range testCases { - cmd := newConnectCommand( - test.NewFakeCli(&fakeClient{ - networkConnectFunc: tc.networkConnectFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - - } -} - -func TestNetworkConnectWithFlags(t *testing.T) { - expectedOpts := []network.IPAMConfig{ - { - "192.168.4.0/24", - "192.168.4.0/24", - "192.168.4.1/24", - map[string]string{}, - }, - } - cli := test.NewFakeCli(&fakeClient{ - networkConnectFunc: func(ctx context.Context, networkID, container string, config *network.EndpointSettings) error { - assert.Equal(t, expectedOpts, config.IPAMConfig, "not expected driver error") - return nil - }, - }) - args := []string{"banana"} - cmd := newCreateCommand(cli) - - cmd.SetArgs(args) - cmd.Flags().Set("driver", "foo") - cmd.Flags().Set("ip-range", "192.168.4.0/24") - cmd.Flags().Set("gateway", "192.168.4.1/24") - cmd.Flags().Set("subnet", "192.168.4.0/24") - assert.NoError(t, cmd.Execute()) -} diff --git a/vendor/github.com/docker/cli/cli/command/network/create.go b/vendor/github.com/docker/cli/cli/command/network/create.go deleted file mode 100644 index 33bbdef5b..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/create.go +++ /dev/null @@ -1,248 +0,0 @@ -package network - -import ( - "fmt" - "net" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/network" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type createOptions struct { - name string - scope string - driver string - driverOpts opts.MapOpts - labels opts.ListOpts - internal bool - ipv6 bool - attachable bool - ingress bool - configOnly bool - configFrom string - - ipamDriver string - ipamSubnet []string - ipamIPRange []string - ipamGateway []string - ipamAux opts.MapOpts - ipamOpt opts.MapOpts -} - -func newCreateCommand(dockerCli command.Cli) *cobra.Command { - options := createOptions{ - driverOpts: *opts.NewMapOpts(nil, nil), - labels: opts.NewListOpts(opts.ValidateEnv), - ipamAux: *opts.NewMapOpts(nil, nil), - ipamOpt: *opts.NewMapOpts(nil, nil), - } - - cmd := &cobra.Command{ - Use: "create [OPTIONS] NETWORK", - Short: "Create a network", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.name = args[0] - return runCreate(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&options.driver, "driver", "d", "bridge", "Driver to manage the Network") - flags.VarP(&options.driverOpts, "opt", "o", "Set driver specific options") - flags.Var(&options.labels, "label", "Set metadata on a network") - flags.BoolVar(&options.internal, "internal", false, "Restrict external access to the network") - flags.BoolVar(&options.ipv6, "ipv6", false, "Enable IPv6 networking") - flags.BoolVar(&options.attachable, "attachable", false, "Enable manual container attachment") - flags.SetAnnotation("attachable", "version", []string{"1.25"}) - flags.BoolVar(&options.ingress, "ingress", false, "Create swarm routing-mesh network") - flags.SetAnnotation("ingress", "version", []string{"1.29"}) - flags.StringVar(&options.scope, "scope", "", "Control the network's scope") - flags.SetAnnotation("scope", "version", []string{"1.30"}) - flags.BoolVar(&options.configOnly, "config-only", false, "Create a configuration only network") - flags.SetAnnotation("config-only", "version", []string{"1.30"}) - flags.StringVar(&options.configFrom, "config-from", "", "The network from which copying the configuration") - flags.SetAnnotation("config-from", "version", []string{"1.30"}) - - flags.StringVar(&options.ipamDriver, "ipam-driver", "default", "IP Address Management Driver") - flags.StringSliceVar(&options.ipamSubnet, "subnet", []string{}, "Subnet in CIDR format that represents a network segment") - flags.StringSliceVar(&options.ipamIPRange, "ip-range", []string{}, "Allocate container ip from a sub-range") - flags.StringSliceVar(&options.ipamGateway, "gateway", []string{}, "IPv4 or IPv6 Gateway for the master subnet") - - flags.Var(&options.ipamAux, "aux-address", "Auxiliary IPv4 or IPv6 addresses used by Network driver") - flags.Var(&options.ipamOpt, "ipam-opt", "Set IPAM driver specific options") - - return cmd -} - -func runCreate(dockerCli command.Cli, options createOptions) error { - client := dockerCli.Client() - - ipamCfg, err := consolidateIpam(options.ipamSubnet, options.ipamIPRange, options.ipamGateway, options.ipamAux.GetAll()) - if err != nil { - return err - } - - // Construct network create request body - nc := types.NetworkCreate{ - Driver: options.driver, - Options: options.driverOpts.GetAll(), - IPAM: &network.IPAM{ - Driver: options.ipamDriver, - Config: ipamCfg, - Options: options.ipamOpt.GetAll(), - }, - CheckDuplicate: true, - Internal: options.internal, - EnableIPv6: options.ipv6, - Attachable: options.attachable, - Ingress: options.ingress, - Scope: options.scope, - ConfigOnly: options.configOnly, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - } - - if from := options.configFrom; from != "" { - nc.ConfigFrom = &network.ConfigReference{ - Network: from, - } - } - - resp, err := client.NetworkCreate(context.Background(), options.name, nc) - if err != nil { - return err - } - fmt.Fprintf(dockerCli.Out(), "%s\n", resp.ID) - return nil -} - -// Consolidates the ipam configuration as a group from different related configurations -// user can configure network with multiple non-overlapping subnets and hence it is -// possible to correlate the various related parameters and consolidate them. -// consolidateIpam consolidates subnets, ip-ranges, gateways and auxiliary addresses into -// structured ipam data. -// nolint: gocyclo -func consolidateIpam(subnets, ranges, gateways []string, auxaddrs map[string]string) ([]network.IPAMConfig, error) { - if len(subnets) < len(ranges) || len(subnets) < len(gateways) { - return nil, errors.Errorf("every ip-range or gateway must have a corresponding subnet") - } - iData := map[string]*network.IPAMConfig{} - - // Populate non-overlapping subnets into consolidation map - for _, s := range subnets { - for k := range iData { - ok1, err := subnetMatches(s, k) - if err != nil { - return nil, err - } - ok2, err := subnetMatches(k, s) - if err != nil { - return nil, err - } - if ok1 || ok2 { - return nil, errors.Errorf("multiple overlapping subnet configuration is not supported") - } - } - iData[s] = &network.IPAMConfig{Subnet: s, AuxAddress: map[string]string{}} - } - - // Validate and add valid ip ranges - for _, r := range ranges { - match := false - for _, s := range subnets { - ok, err := subnetMatches(s, r) - if err != nil { - return nil, err - } - if !ok { - continue - } - if iData[s].IPRange != "" { - return nil, errors.Errorf("cannot configure multiple ranges (%s, %s) on the same subnet (%s)", r, iData[s].IPRange, s) - } - d := iData[s] - d.IPRange = r - match = true - } - if !match { - return nil, errors.Errorf("no matching subnet for range %s", r) - } - } - - // Validate and add valid gateways - for _, g := range gateways { - match := false - for _, s := range subnets { - ok, err := subnetMatches(s, g) - if err != nil { - return nil, err - } - if !ok { - continue - } - if iData[s].Gateway != "" { - return nil, errors.Errorf("cannot configure multiple gateways (%s, %s) for the same subnet (%s)", g, iData[s].Gateway, s) - } - d := iData[s] - d.Gateway = g - match = true - } - if !match { - return nil, errors.Errorf("no matching subnet for gateway %s", g) - } - } - - // Validate and add aux-addresses - for key, aa := range auxaddrs { - match := false - for _, s := range subnets { - ok, err := subnetMatches(s, aa) - if err != nil { - return nil, err - } - if !ok { - continue - } - iData[s].AuxAddress[key] = aa - match = true - } - if !match { - return nil, errors.Errorf("no matching subnet for aux-address %s", aa) - } - } - - idl := []network.IPAMConfig{} - for _, v := range iData { - idl = append(idl, *v) - } - return idl, nil -} - -func subnetMatches(subnet, data string) (bool, error) { - var ( - ip net.IP - ) - - _, s, err := net.ParseCIDR(subnet) - if err != nil { - return false, errors.Wrap(err, "invalid subnet") - } - - if strings.Contains(data, "/") { - ip, _, err = net.ParseCIDR(data) - if err != nil { - return false, err - } - } else { - ip = net.ParseIP(data) - } - - return s.Contains(ip), nil -} diff --git a/vendor/github.com/docker/cli/cli/command/network/create_test.go b/vendor/github.com/docker/cli/cli/command/network/create_test.go deleted file mode 100644 index dda68046d..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/create_test.go +++ /dev/null @@ -1,175 +0,0 @@ -package network - -import ( - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/network" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/context" -) - -func TestNetworkCreateErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - networkCreateFunc func(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) - expectedError string - }{ - { - expectedError: "exactly 1 argument", - }, - { - args: []string{"toto"}, - networkCreateFunc: func(ctx context.Context, name string, createBody types.NetworkCreate) (types.NetworkCreateResponse, error) { - return types.NetworkCreateResponse{}, errors.Errorf("error creating network") - }, - expectedError: "error creating network", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "255.255.0.0/24", - "gateway": "255.0.255.0/24", - "subnet": "10.1.2.0.30.50", - }, - expectedError: "invalid CIDR address: 10.1.2.0.30.50", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "255.255.0.0.30/24", - "gateway": "255.0.255.0/24", - "subnet": "255.0.0.0/24", - }, - expectedError: "invalid CIDR address: 255.255.0.0.30/24", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "gateway": "255.0.0.0/24", - }, - expectedError: "every ip-range or gateway must have a corresponding subnet", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "255.0.0.0/24", - }, - expectedError: "every ip-range or gateway must have a corresponding subnet", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "255.0.0.0/24", - "gateway": "255.0.0.0/24", - }, - expectedError: "every ip-range or gateway must have a corresponding subnet", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "255.255.0.0/24", - "gateway": "255.0.255.0/24", - "subnet": "10.1.2.0/23,10.1.3.248/30", - }, - expectedError: "multiple overlapping subnet configuration is not supported", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "192.168.1.0/24,192.168.1.200/24", - "gateway": "192.168.1.1,192.168.1.4", - "subnet": "192.168.2.0/24,192.168.1.250/24", - }, - expectedError: "cannot configure multiple ranges (192.168.1.200/24, 192.168.1.0/24) on the same subnet (192.168.1.250/24)", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "255.255.200.0/24,255.255.120.0/24", - "gateway": "255.0.255.0/24", - "subnet": "255.255.255.0/24,255.255.0.255/24", - }, - expectedError: "no matching subnet for range 255.255.200.0/24", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "192.168.1.0/24", - "gateway": "192.168.1.1,192.168.1.4", - "subnet": "192.168.2.0/24,192.168.1.250/24", - }, - expectedError: "cannot configure multiple gateways (192.168.1.4, 192.168.1.1) for the same subnet (192.168.1.250/24)", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "ip-range": "192.168.1.0/24", - "gateway": "192.168.4.1,192.168.5.4", - "subnet": "192.168.2.0/24,192.168.1.250/24", - }, - expectedError: "no matching subnet for gateway 192.168.4.1", - }, - { - args: []string{"toto"}, - flags: map[string]string{ - "gateway": "255.255.0.0/24", - "subnet": "255.255.0.0/24", - "aux-address": "255.255.0.30/24", - }, - expectedError: "no matching subnet for aux-address", - }, - } - - for _, tc := range testCases { - cmd := newCreateCommand( - test.NewFakeCli(&fakeClient{ - networkCreateFunc: tc.networkCreateFunc, - }), - ) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - require.NoError(t, cmd.Flags().Set(key, value)) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - - } -} -func TestNetworkCreateWithFlags(t *testing.T) { - expectedDriver := "foo" - expectedOpts := []network.IPAMConfig{ - { - "192.168.4.0/24", - "192.168.4.0/24", - "192.168.4.1/24", - map[string]string{}, - }, - } - cli := test.NewFakeCli(&fakeClient{ - networkCreateFunc: func(ctx context.Context, name string, createBody types.NetworkCreate) (types.NetworkCreateResponse, error) { - assert.Equal(t, expectedDriver, createBody.Driver, "not expected driver error") - assert.Equal(t, expectedOpts, createBody.IPAM.Config, "not expected driver error") - return types.NetworkCreateResponse{ - ID: name, - }, nil - }, - }) - args := []string{"banana"} - cmd := newCreateCommand(cli) - - cmd.SetArgs(args) - cmd.Flags().Set("driver", "foo") - cmd.Flags().Set("ip-range", "192.168.4.0/24") - cmd.Flags().Set("gateway", "192.168.4.1/24") - cmd.Flags().Set("subnet", "192.168.4.0/24") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "banana", strings.TrimSpace(cli.OutBuffer().String())) -} diff --git a/vendor/github.com/docker/cli/cli/command/network/disconnect.go b/vendor/github.com/docker/cli/cli/command/network/disconnect.go deleted file mode 100644 index ab866cf2c..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/disconnect.go +++ /dev/null @@ -1,41 +0,0 @@ -package network - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -type disconnectOptions struct { - network string - container string - force bool -} - -func newDisconnectCommand(dockerCli command.Cli) *cobra.Command { - opts := disconnectOptions{} - - cmd := &cobra.Command{ - Use: "disconnect [OPTIONS] NETWORK CONTAINER", - Short: "Disconnect a container from a network", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - opts.network = args[0] - opts.container = args[1] - return runDisconnect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.force, "force", "f", false, "Force the container to disconnect from a network") - - return cmd -} - -func runDisconnect(dockerCli command.Cli, opts disconnectOptions) error { - client := dockerCli.Client() - - return client.NetworkDisconnect(context.Background(), opts.network, opts.container, opts.force) -} diff --git a/vendor/github.com/docker/cli/cli/command/network/disconnect_test.go b/vendor/github.com/docker/cli/cli/command/network/disconnect_test.go deleted file mode 100644 index e3920e977..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/disconnect_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package network - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -func TestNetworkDisconnectErrors(t *testing.T) { - testCases := []struct { - args []string - networkDisconnectFunc func(ctx context.Context, networkID, container string, force bool) error - expectedError string - }{ - { - expectedError: "requires exactly 2 arguments", - }, - { - args: []string{"toto", "titi"}, - networkDisconnectFunc: func(ctx context.Context, networkID, container string, force bool) error { - return errors.Errorf("error disconnecting network") - }, - expectedError: "error disconnecting network", - }, - } - - for _, tc := range testCases { - cmd := newDisconnectCommand( - test.NewFakeCli(&fakeClient{ - networkDisconnectFunc: tc.networkDisconnectFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/network/inspect.go b/vendor/github.com/docker/cli/cli/command/network/inspect.go deleted file mode 100644 index e4c2e5fb8..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/inspect.go +++ /dev/null @@ -1,48 +0,0 @@ -package network - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -type inspectOptions struct { - format string - names []string - verbose bool -} - -func newInspectCommand(dockerCli command.Cli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] NETWORK [NETWORK...]", - Short: "Display detailed information on one or more networks", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.names = args - return runInspect(dockerCli, opts) - }, - } - - cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - cmd.Flags().BoolVarP(&opts.verbose, "verbose", "v", false, "Verbose output for diagnostics") - - return cmd -} - -func runInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - - ctx := context.Background() - - getNetFunc := func(name string) (interface{}, []byte, error) { - return client.NetworkInspectWithRaw(ctx, name, types.NetworkInspectOptions{Verbose: opts.verbose}) - } - - return inspect.Inspect(dockerCli.Out(), opts.names, opts.format, getNetFunc) -} diff --git a/vendor/github.com/docker/cli/cli/command/network/list.go b/vendor/github.com/docker/cli/cli/command/network/list.go deleted file mode 100644 index 8a7c1f261..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/list.go +++ /dev/null @@ -1,75 +0,0 @@ -package network - -import ( - "sort" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type byNetworkName []types.NetworkResource - -func (r byNetworkName) Len() int { return len(r) } -func (r byNetworkName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byNetworkName) Less(i, j int) bool { return r[i].Name < r[j].Name } - -type listOptions struct { - quiet bool - noTrunc bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List networks", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display network IDs") - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Do not truncate the output") - flags.StringVar(&options.format, "format", "", "Pretty-print networks using a Go template") - flags.VarP(&options.filter, "filter", "f", "Provide filter values (e.g. 'driver=bridge')") - - return cmd -} - -func runList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - listOptions := types.NetworkListOptions{Filters: options.filter.Value()} - networkResources, err := client.NetworkList(context.Background(), listOptions) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().NetworksFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().NetworksFormat - } else { - format = formatter.TableFormatKey - } - } - - sort.Sort(byNetworkName(networkResources)) - - networksCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewNetworkFormat(format, options.quiet), - Trunc: !options.noTrunc, - } - return formatter.NetworkWrite(networksCtx, networkResources) -} diff --git a/vendor/github.com/docker/cli/cli/command/network/list_test.go b/vendor/github.com/docker/cli/cli/command/network/list_test.go deleted file mode 100644 index 63fc0a13c..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/list_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package network - -import ( - "testing" - - "io/ioutil" - - "strings" - - "github.com/docker/cli/internal/test" - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestNetworkListErrors(t *testing.T) { - testCases := []struct { - networkListFunc func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) - expectedError string - }{ - { - networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { - return []types.NetworkResource{}, errors.Errorf("error creating network") - }, - expectedError: "error creating network", - }, - } - - for _, tc := range testCases { - cmd := newListCommand( - test.NewFakeCli(&fakeClient{ - networkListFunc: tc.networkListFunc, - }), - ) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - - } -} - -func TestNetworkListWithFlags(t *testing.T) { - - filterArgs := filters.NewArgs() - filterArgs.Add("image.name", "ubuntu") - - expectedOpts := types.NetworkListOptions{ - Filters: filterArgs, - } - - cli := test.NewFakeCli(&fakeClient{ - networkListFunc: func(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { - assert.Equal(t, expectedOpts, options, "not expected options error") - return []types.NetworkResource{*NetworkResource(NetworkResourceID("123454321"), - NetworkResourceName("network_1"), - NetworkResourceDriver("09.7.01"), - NetworkResourceScope("global"))}, nil - }, - }) - cmd := newListCommand(cli) - - cmd.Flags().Set("filter", "image.name=ubuntu") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, strings.TrimSpace(cli.OutBuffer().String()), "network-list.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/network/prune.go b/vendor/github.com/docker/cli/cli/command/network/prune.go deleted file mode 100644 index b31db99da..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/prune.go +++ /dev/null @@ -1,76 +0,0 @@ -package network - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type pruneOptions struct { - force bool - filter opts.FilterOpt -} - -// NewPruneCommand returns a new cobra prune command for networks -func NewPruneCommand(dockerCli command.Cli) *cobra.Command { - options := pruneOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "prune [OPTIONS]", - Short: "Remove all unused networks", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - output, err := runPrune(dockerCli, options) - if err != nil { - return err - } - if output != "" { - fmt.Fprintln(dockerCli.Out(), output) - } - return nil - }, - Tags: map[string]string{"version": "1.25"}, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") - flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'until=')") - - return cmd -} - -const warning = `WARNING! This will remove all networks not used by at least one container. -Are you sure you want to continue?` - -func runPrune(dockerCli command.Cli, options pruneOptions) (output string, err error) { - pruneFilters := command.PruneFilters(dockerCli, options.filter.Value()) - - if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) { - return - } - - report, err := dockerCli.Client().NetworksPrune(context.Background(), pruneFilters) - if err != nil { - return - } - - if len(report.NetworksDeleted) > 0 { - output = "Deleted Networks:\n" - for _, id := range report.NetworksDeleted { - output += id + "\n" - } - } - - return -} - -// RunPrune calls the Network Prune API -// This returns the amount of space reclaimed and a detailed output string -func RunPrune(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - output, err := runPrune(dockerCli, pruneOptions{force: true, filter: filter}) - return 0, output, err -} diff --git a/vendor/github.com/docker/cli/cli/command/network/remove.go b/vendor/github.com/docker/cli/cli/command/network/remove.go deleted file mode 100644 index 3de7bdad3..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/remove.go +++ /dev/null @@ -1,54 +0,0 @@ -package network - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "rm NETWORK [NETWORK...]", - Aliases: []string{"remove"}, - Short: "Remove one or more networks", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, args) - }, - } -} - -const ingressWarning = "WARNING! Before removing the routing-mesh network, " + - "make sure all the nodes in your swarm run the same docker engine version. " + - "Otherwise, removal may not be effective and functionality of newly create " + - "ingress networks will be impaired.\nAre you sure you want to continue?" - -func runRemove(dockerCli command.Cli, networks []string) error { - client := dockerCli.Client() - ctx := context.Background() - status := 0 - - for _, name := range networks { - if nw, _, err := client.NetworkInspectWithRaw(ctx, name, types.NetworkInspectOptions{}); err == nil && - nw.Ingress && - !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), ingressWarning) { - continue - } - if err := client.NetworkRemove(ctx, name); err != nil { - fmt.Fprintf(dockerCli.Err(), "%s\n", err) - status = 1 - continue - } - fmt.Fprintf(dockerCli.Out(), "%s\n", name) - } - - if status != 0 { - return cli.StatusError{StatusCode: status} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/network/testdata/network-list.golden b/vendor/github.com/docker/cli/cli/command/network/testdata/network-list.golden deleted file mode 100644 index e77651090..000000000 --- a/vendor/github.com/docker/cli/cli/command/network/testdata/network-list.golden +++ /dev/null @@ -1,2 +0,0 @@ -NETWORK ID NAME DRIVER SCOPE -123454321 network_1 09.7.01 global \ No newline at end of file diff --git a/vendor/github.com/docker/cli/cli/command/node/client_test.go b/vendor/github.com/docker/cli/cli/command/node/client_test.go deleted file mode 100644 index 1f5cdc7ce..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/client_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package node - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - infoFunc func() (types.Info, error) - nodeInspectFunc func() (swarm.Node, []byte, error) - nodeListFunc func() ([]swarm.Node, error) - nodeRemoveFunc func() error - nodeUpdateFunc func(nodeID string, version swarm.Version, node swarm.NodeSpec) error - taskInspectFunc func(taskID string) (swarm.Task, []byte, error) - taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error) -} - -func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) { - if cli.nodeInspectFunc != nil { - return cli.nodeInspectFunc() - } - return swarm.Node{}, []byte{}, nil -} - -func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) { - if cli.nodeListFunc != nil { - return cli.nodeListFunc() - } - return []swarm.Node{}, nil -} - -func (cli *fakeClient) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error { - if cli.nodeRemoveFunc != nil { - return cli.nodeRemoveFunc() - } - return nil -} - -func (cli *fakeClient) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if cli.nodeUpdateFunc != nil { - return cli.nodeUpdateFunc(nodeID, version, node) - } - return nil -} - -func (cli *fakeClient) Info(ctx context.Context) (types.Info, error) { - if cli.infoFunc != nil { - return cli.infoFunc() - } - return types.Info{}, nil -} - -func (cli *fakeClient) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { - if cli.taskInspectFunc != nil { - return cli.taskInspectFunc(taskID) - } - return swarm.Task{}, []byte{}, nil -} - -func (cli *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { - if cli.taskListFunc != nil { - return cli.taskListFunc(options) - } - return []swarm.Task{}, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/cmd.go b/vendor/github.com/docker/cli/cli/command/node/cmd.go deleted file mode 100644 index b3090d5d7..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/cmd.go +++ /dev/null @@ -1,57 +0,0 @@ -package node - -import ( - "errors" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - apiclient "github.com/docker/docker/client" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -// NewNodeCommand returns a cobra command for `node` subcommands -func NewNodeCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "node", - Short: "Manage Swarm nodes", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.24"}, - } - cmd.AddCommand( - newDemoteCommand(dockerCli), - newInspectCommand(dockerCli), - newListCommand(dockerCli), - newPromoteCommand(dockerCli), - newRemoveCommand(dockerCli), - newPsCommand(dockerCli), - newUpdateCommand(dockerCli), - ) - return cmd -} - -// Reference returns the reference of a node. The special value "self" for a node -// reference is mapped to the current node, hence the node ID is retrieved using -// the `/info` endpoint. -func Reference(ctx context.Context, client apiclient.APIClient, ref string) (string, error) { - if ref == "self" { - info, err := client.Info(ctx) - if err != nil { - return "", err - } - if info.Swarm.NodeID == "" { - // If there's no node ID in /info, the node probably - // isn't a manager. Call a swarm-specific endpoint to - // get a more specific error message. - _, err = client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return "", err - } - return "", errors.New("node ID not found in /info") - } - return info.Swarm.NodeID, nil - } - return ref, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/demote.go b/vendor/github.com/docker/cli/cli/command/node/demote.go deleted file mode 100644 index 5250dfc0b..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/demote.go +++ /dev/null @@ -1,36 +0,0 @@ -package node - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/spf13/cobra" -) - -func newDemoteCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "demote NODE [NODE...]", - Short: "Demote one or more nodes from manager in the swarm", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runDemote(dockerCli, args) - }, - } -} - -func runDemote(dockerCli command.Cli, nodes []string) error { - demote := func(node *swarm.Node) error { - if node.Spec.Role == swarm.NodeRoleWorker { - fmt.Fprintf(dockerCli.Out(), "Node %s is already a worker.\n", node.ID) - return errNoRoleChange - } - node.Spec.Role = swarm.NodeRoleWorker - return nil - } - success := func(nodeID string) { - fmt.Fprintf(dockerCli.Out(), "Manager %s demoted in the swarm.\n", nodeID) - } - return updateNodes(dockerCli, nodes, demote, success) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/demote_test.go b/vendor/github.com/docker/cli/cli/command/node/demote_test.go deleted file mode 100644 index bf86e5227..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/demote_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package node - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/stretchr/testify/assert" -) - -func TestNodeDemoteErrors(t *testing.T) { - testCases := []struct { - args []string - nodeInspectFunc func() (swarm.Node, []byte, error) - nodeUpdateFunc func(nodeID string, version swarm.Version, node swarm.NodeSpec) error - expectedError string - }{ - { - expectedError: "requires at least 1 argument", - }, - { - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting the node") - }, - expectedError: "error inspecting the node", - }, - { - args: []string{"nodeID"}, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - return errors.Errorf("error updating the node") - }, - expectedError: "error updating the node", - }, - } - for _, tc := range testCases { - cmd := newDemoteCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: tc.nodeInspectFunc, - nodeUpdateFunc: tc.nodeUpdateFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNodeDemoteNoChange(t *testing.T) { - cmd := newDemoteCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if node.Role != swarm.NodeRoleWorker { - return errors.Errorf("expected role worker, got %s", node.Role) - } - return nil - }, - })) - cmd.SetArgs([]string{"nodeID"}) - assert.NoError(t, cmd.Execute()) -} - -func TestNodeDemoteMultipleNode(t *testing.T) { - cmd := newDemoteCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if node.Role != swarm.NodeRoleWorker { - return errors.Errorf("expected role worker, got %s", node.Role) - } - return nil - }, - })) - cmd.SetArgs([]string{"nodeID1", "nodeID2"}) - assert.NoError(t, cmd.Execute()) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/inspect.go b/vendor/github.com/docker/cli/cli/command/node/inspect.go deleted file mode 100644 index ffb4efe45..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/inspect.go +++ /dev/null @@ -1,72 +0,0 @@ -package node - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - nodeIds []string - format string - pretty bool -} - -func newInspectCommand(dockerCli command.Cli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] self|NODE [NODE...]", - Short: "Display detailed information on one or more nodes", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.nodeIds = args - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - flags.BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(ref string) (interface{}, []byte, error) { - nodeRef, err := Reference(ctx, client, ref) - if err != nil { - return nil, nil, err - } - node, _, err := client.NodeInspectWithRaw(ctx, nodeRef) - return node, nil, err - } - f := opts.format - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return fmt.Errorf("Cannot supply extra formatting options to the pretty template") - } - - nodeCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewNodeFormat(f, false), - } - - if err := formatter.NodeInspectWrite(nodeCtx, opts.nodeIds, getRef); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/inspect_test.go b/vendor/github.com/docker/cli/cli/command/node/inspect_test.go deleted file mode 100644 index 739a4783b..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/inspect_test.go +++ /dev/null @@ -1,119 +0,0 @@ -package node - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestNodeInspectErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - nodeInspectFunc func() (swarm.Node, []byte, error) - infoFunc func() (types.Info, error) - expectedError string - }{ - { - expectedError: "requires at least 1 argument", - }, - { - args: []string{"self"}, - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error asking for node info") - }, - expectedError: "error asking for node info", - }, - { - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting the node") - }, - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error asking for node info") - }, - expectedError: "error inspecting the node", - }, - { - args: []string{"self"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting the node") - }, - infoFunc: func() (types.Info, error) { - return types.Info{Swarm: swarm.Info{NodeID: "abc"}}, nil - }, - expectedError: "error inspecting the node", - }, - { - args: []string{"self"}, - flags: map[string]string{ - "pretty": "true", - }, - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error asking for node info") - }, - expectedError: "error asking for node info", - }, - } - for _, tc := range testCases { - cmd := newInspectCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: tc.nodeInspectFunc, - infoFunc: tc.infoFunc, - })) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNodeInspectPretty(t *testing.T) { - testCases := []struct { - name string - nodeInspectFunc func() (swarm.Node, []byte, error) - }{ - { - name: "simple", - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(NodeLabels(map[string]string{ - "lbl1": "value1", - })), []byte{}, nil - }, - }, - { - name: "manager", - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - }, - { - name: "manager-leader", - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager(Leader())), []byte{}, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - nodeInspectFunc: tc.nodeInspectFunc, - }) - cmd := newInspectCommand(cli) - cmd.SetArgs([]string{"nodeID"}) - cmd.Flags().Set("pretty", "true") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-inspect-pretty.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/node/list.go b/vendor/github.com/docker/cli/cli/command/node/list.go deleted file mode 100644 index 7dac79566..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/list.go +++ /dev/null @@ -1,85 +0,0 @@ -package node - -import ( - "sort" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/spf13/cobra" - "golang.org/x/net/context" - "vbom.ml/util/sortorder" -) - -type byHostname []swarm.Node - -func (n byHostname) Len() int { return len(n) } -func (n byHostname) Swap(i, j int) { n[i], n[j] = n[j], n[i] } -func (n byHostname) Less(i, j int) bool { - return sortorder.NaturalLess(n[i].Description.Hostname, n[j].Description.Hostname) -} - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List nodes in the swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print nodes using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - nodes, err := client.NodeList( - ctx, - types.NodeListOptions{Filters: options.filter.Value()}) - if err != nil { - return err - } - - info := types.Info{} - if len(nodes) > 0 && !options.quiet { - // only non-empty nodes and not quiet, should we call /info api - info, err = client.Info(ctx) - if err != nil { - return err - } - } - - format := options.format - if len(format) == 0 { - format = formatter.TableFormatKey - if len(dockerCli.ConfigFile().NodesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().NodesFormat - } - } - - nodesCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewNodeFormat(format, options.quiet), - } - sort.Sort(byHostname(nodes)) - return formatter.NodeWrite(nodesCtx, nodes, info) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/list_test.go b/vendor/github.com/docker/cli/cli/command/node/list_test.go deleted file mode 100644 index b3a42df46..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/list_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package node - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/stretchr/testify/assert" -) - -func TestNodeListErrorOnAPIFailure(t *testing.T) { - testCases := []struct { - nodeListFunc func() ([]swarm.Node, error) - infoFunc func() (types.Info, error) - expectedError string - }{ - { - nodeListFunc: func() ([]swarm.Node, error) { - return []swarm.Node{}, errors.Errorf("error listing nodes") - }, - expectedError: "error listing nodes", - }, - { - nodeListFunc: func() ([]swarm.Node, error) { - return []swarm.Node{ - { - ID: "nodeID", - }, - }, nil - }, - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error asking for node info") - }, - expectedError: "error asking for node info", - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - nodeListFunc: tc.nodeListFunc, - infoFunc: tc.infoFunc, - }) - cmd := newListCommand(cli) - cmd.SetOutput(ioutil.Discard) - assert.EqualError(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNodeList(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - nodeListFunc: func() ([]swarm.Node, error) { - return []swarm.Node{ - *Node(NodeID("nodeID1"), Hostname("node-2-foo"), Manager(Leader())), - *Node(NodeID("nodeID2"), Hostname("node-10-foo"), Manager()), - *Node(NodeID("nodeID3"), Hostname("node-1-foo")), - }, nil - }, - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID1", - }, - }, nil - }, - }) - - cmd := newListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "node-list-sort.golden") -} - -func TestNodeListQuietShouldOnlyPrintIDs(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - nodeListFunc: func() ([]swarm.Node, error) { - return []swarm.Node{ - *Node(NodeID("nodeID1")), - }, nil - }, - }) - cmd := newListCommand(cli) - cmd.Flags().Set("quiet", "true") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, cli.OutBuffer().String(), "nodeID1\n") -} - -func TestNodeListDefaultFormatFromConfig(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - nodeListFunc: func() ([]swarm.Node, error) { - return []swarm.Node{ - *Node(NodeID("nodeID1"), Hostname("nodeHostname1"), Manager(Leader())), - *Node(NodeID("nodeID2"), Hostname("nodeHostname2"), Manager()), - *Node(NodeID("nodeID3"), Hostname("nodeHostname3")), - }, nil - }, - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID1", - }, - }, nil - }, - }) - cli.SetConfigFile(&configfile.ConfigFile{ - NodesFormat: "{{.ID}}: {{.Hostname}} {{.Status}}/{{.ManagerStatus}}", - }) - cmd := newListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "node-list-format-from-config.golden") -} - -func TestNodeListFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - nodeListFunc: func() ([]swarm.Node, error) { - return []swarm.Node{ - *Node(NodeID("nodeID1"), Hostname("nodeHostname1"), Manager(Leader())), - *Node(NodeID("nodeID2"), Hostname("nodeHostname2"), Manager()), - }, nil - }, - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID1", - }, - }, nil - }, - }) - cli.SetConfigFile(&configfile.ConfigFile{ - NodesFormat: "{{.ID}}: {{.Hostname}} {{.Status}}/{{.ManagerStatus}}", - }) - cmd := newListCommand(cli) - cmd.Flags().Set("format", "{{.Hostname}}: {{.ManagerStatus}}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "node-list-format-flag.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/node/opts.go b/vendor/github.com/docker/cli/cli/command/node/opts.go deleted file mode 100644 index e30e5de91..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/opts.go +++ /dev/null @@ -1,23 +0,0 @@ -package node - -import ( - "github.com/docker/cli/opts" -) - -type nodeOptions struct { - annotations - role string - availability string -} - -type annotations struct { - labels opts.ListOpts -} - -func newNodeOptions() *nodeOptions { - return &nodeOptions{ - annotations: annotations{ - labels: opts.NewListOpts(nil), - }, - } -} diff --git a/vendor/github.com/docker/cli/cli/command/node/promote.go b/vendor/github.com/docker/cli/cli/command/node/promote.go deleted file mode 100644 index 4612cc13f..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/promote.go +++ /dev/null @@ -1,36 +0,0 @@ -package node - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/spf13/cobra" -) - -func newPromoteCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "promote NODE [NODE...]", - Short: "Promote one or more nodes to manager in the swarm", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runPromote(dockerCli, args) - }, - } -} - -func runPromote(dockerCli command.Cli, nodes []string) error { - promote := func(node *swarm.Node) error { - if node.Spec.Role == swarm.NodeRoleManager { - fmt.Fprintf(dockerCli.Out(), "Node %s is already a manager.\n", node.ID) - return errNoRoleChange - } - node.Spec.Role = swarm.NodeRoleManager - return nil - } - success := func(nodeID string) { - fmt.Fprintf(dockerCli.Out(), "Node %s promoted to a manager in the swarm.\n", nodeID) - } - return updateNodes(dockerCli, nodes, promote, success) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/promote_test.go b/vendor/github.com/docker/cli/cli/command/node/promote_test.go deleted file mode 100644 index 4c6634234..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/promote_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package node - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/stretchr/testify/assert" -) - -func TestNodePromoteErrors(t *testing.T) { - testCases := []struct { - args []string - nodeInspectFunc func() (swarm.Node, []byte, error) - nodeUpdateFunc func(nodeID string, version swarm.Version, node swarm.NodeSpec) error - expectedError string - }{ - { - expectedError: "requires at least 1 argument", - }, - { - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting the node") - }, - expectedError: "error inspecting the node", - }, - { - args: []string{"nodeID"}, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - return errors.Errorf("error updating the node") - }, - expectedError: "error updating the node", - }, - } - for _, tc := range testCases { - cmd := newPromoteCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: tc.nodeInspectFunc, - nodeUpdateFunc: tc.nodeUpdateFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNodePromoteNoChange(t *testing.T) { - cmd := newPromoteCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if node.Role != swarm.NodeRoleManager { - return errors.Errorf("expected role manager, got %s", node.Role) - } - return nil - }, - })) - cmd.SetArgs([]string{"nodeID"}) - assert.NoError(t, cmd.Execute()) -} - -func TestNodePromoteMultipleNode(t *testing.T) { - cmd := newPromoteCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if node.Role != swarm.NodeRoleManager { - return errors.Errorf("expected role manager, got %s", node.Role) - } - return nil - }, - })) - cmd.SetArgs([]string{"nodeID1", "nodeID2"}) - assert.NoError(t, cmd.Execute()) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/ps.go b/vendor/github.com/docker/cli/cli/command/node/ps.go deleted file mode 100644 index 5212e596f..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/ps.go +++ /dev/null @@ -1,104 +0,0 @@ -package node - -import ( - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/cli/command/task" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type psOptions struct { - nodeIDs []string - noResolve bool - noTrunc bool - quiet bool - format string - filter opts.FilterOpt -} - -func newPsCommand(dockerCli command.Cli) *cobra.Command { - options := psOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ps [OPTIONS] [NODE...]", - Short: "List tasks running on one or more nodes, defaults to current node", - Args: cli.RequiresMinArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { - options.nodeIDs = []string{"self"} - - if len(args) != 0 { - options.nodeIDs = args - } - - return runPs(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&options.noResolve, "no-resolve", false, "Do not map IDs to Names") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - flags.StringVar(&options.format, "format", "", "Pretty-print tasks using a Go template") - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display task IDs") - - return cmd -} - -func runPs(dockerCli command.Cli, options psOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var ( - errs []string - tasks []swarm.Task - ) - - for _, nodeID := range options.nodeIDs { - nodeRef, err := Reference(ctx, client, nodeID) - if err != nil { - errs = append(errs, err.Error()) - continue - } - - node, _, err := client.NodeInspectWithRaw(ctx, nodeRef) - if err != nil { - errs = append(errs, err.Error()) - continue - } - - filter := options.filter.Value() - filter.Add("node", node.ID) - - nodeTasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) - if err != nil { - errs = append(errs, err.Error()) - continue - } - - tasks = append(tasks, nodeTasks...) - } - - format := options.format - if len(format) == 0 { - format = task.DefaultFormat(dockerCli.ConfigFile(), options.quiet) - } - - if len(errs) == 0 || len(tasks) != 0 { - if err := task.Print(ctx, dockerCli, tasks, idresolver.New(client, options.noResolve), !options.noTrunc, options.quiet, format); err != nil { - errs = append(errs, err.Error()) - } - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/ps_test.go b/vendor/github.com/docker/cli/cli/command/node/ps_test.go deleted file mode 100644 index 836a130f7..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/ps_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package node - -import ( - "fmt" - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestNodePsErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - infoFunc func() (types.Info, error) - nodeInspectFunc func() (swarm.Node, []byte, error) - taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error) - taskInspectFunc func(taskID string) (swarm.Task, []byte, error) - expectedError string - }{ - { - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error asking for node info") - }, - expectedError: "error asking for node info", - }, - { - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting the node") - }, - expectedError: "error inspecting the node", - }, - { - args: []string{"nodeID"}, - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{}, errors.Errorf("error returning the task list") - }, - expectedError: "error returning the task list", - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - infoFunc: tc.infoFunc, - nodeInspectFunc: tc.nodeInspectFunc, - taskInspectFunc: tc.taskInspectFunc, - taskListFunc: tc.taskListFunc, - }) - cmd := newPsCommand(cli) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - assert.EqualError(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNodePs(t *testing.T) { - testCases := []struct { - name string - args []string - flags map[string]string - infoFunc func() (types.Info, error) - nodeInspectFunc func() (swarm.Node, []byte, error) - taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error) - taskInspectFunc func(taskID string) (swarm.Task, []byte, error) - }{ - { - name: "simple", - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{ - *Task(WithStatus(Timestamp(time.Now().Add(-2*time.Hour)), PortStatus([]swarm.PortConfig{ - { - TargetPort: 80, - PublishedPort: 80, - Protocol: "tcp", - }, - }))), - }, nil - }, - }, - { - name: "with-errors", - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{ - *Task(TaskID("taskID1"), TaskServiceID("failure"), - WithStatus(Timestamp(time.Now().Add(-2*time.Hour)), StatusErr("a task error"))), - *Task(TaskID("taskID2"), TaskServiceID("failure"), - WithStatus(Timestamp(time.Now().Add(-3*time.Hour)), StatusErr("a task error"))), - *Task(TaskID("taskID3"), TaskServiceID("failure"), - WithStatus(Timestamp(time.Now().Add(-4*time.Hour)), StatusErr("a task error"))), - }, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - infoFunc: tc.infoFunc, - nodeInspectFunc: tc.nodeInspectFunc, - taskInspectFunc: tc.taskInspectFunc, - taskListFunc: tc.taskListFunc, - }) - cmd := newPsCommand(cli) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("node-ps.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/node/remove.go b/vendor/github.com/docker/cli/cli/command/node/remove.go deleted file mode 100644 index d23ec2fb5..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/remove.go +++ /dev/null @@ -1,57 +0,0 @@ -package node - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type removeOptions struct { - force bool -} - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - opts := removeOptions{} - - cmd := &cobra.Command{ - Use: "rm [OPTIONS] NODE [NODE...]", - Aliases: []string{"remove"}, - Short: "Remove one or more nodes from the swarm", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, args, opts) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&opts.force, "force", "f", false, "Force remove a node from the swarm") - return cmd -} - -func runRemove(dockerCli command.Cli, args []string, opts removeOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - - for _, nodeID := range args { - err := client.NodeRemove(ctx, nodeID, types.NodeRemoveOptions{Force: opts.force}) - if err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintf(dockerCli.Out(), "%s\n", nodeID) - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/remove_test.go b/vendor/github.com/docker/cli/cli/command/node/remove_test.go deleted file mode 100644 index 78fc4f76f..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/remove_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package node - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestNodeRemoveErrors(t *testing.T) { - testCases := []struct { - args []string - nodeRemoveFunc func() error - expectedError string - }{ - { - expectedError: "requires at least 1 argument", - }, - { - args: []string{"nodeID"}, - nodeRemoveFunc: func() error { - return errors.Errorf("error removing the node") - }, - expectedError: "error removing the node", - }, - } - for _, tc := range testCases { - cmd := newRemoveCommand( - test.NewFakeCli(&fakeClient{ - nodeRemoveFunc: tc.nodeRemoveFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNodeRemoveMultiple(t *testing.T) { - cmd := newRemoveCommand(test.NewFakeCli(&fakeClient{})) - cmd.SetArgs([]string{"nodeID1", "nodeID2"}) - assert.NoError(t, cmd.Execute()) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.manager-leader.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.manager-leader.golden deleted file mode 100644 index 5cd95c5b9..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.manager-leader.golden +++ /dev/null @@ -1,24 +0,0 @@ -ID: nodeID -Name: defaultNodeName -Hostname: defaultNodeHostname -Joined at: 2009-11-10 23:00:00 +0000 utc -Status: - State: Ready - Availability: Active - Address: 127.0.0.1 -Manager Status: - Address: 127.0.0.1 - Raft Status: Reachable - Leader: Yes -Platform: - Operating System: linux - Architecture: x86_64 -Resources: - CPUs: 0 - Memory: 20MiB -Plugins: - Network: bridge, overlay - Volume: local -Engine Version: 1.13.0 -Engine Labels: - - engine=label diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.manager.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.manager.golden deleted file mode 100644 index a63718293..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.manager.golden +++ /dev/null @@ -1,24 +0,0 @@ -ID: nodeID -Name: defaultNodeName -Hostname: defaultNodeHostname -Joined at: 2009-11-10 23:00:00 +0000 utc -Status: - State: Ready - Availability: Active - Address: 127.0.0.1 -Manager Status: - Address: 127.0.0.1 - Raft Status: Reachable - Leader: No -Platform: - Operating System: linux - Architecture: x86_64 -Resources: - CPUs: 0 - Memory: 20MiB -Plugins: - Network: bridge, overlay - Volume: local -Engine Version: 1.13.0 -Engine Labels: - - engine=label diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.simple.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.simple.golden deleted file mode 100644 index 8aaf90899..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-inspect-pretty.simple.golden +++ /dev/null @@ -1,22 +0,0 @@ -ID: nodeID -Name: defaultNodeName -Labels: - - lbl1=value1 -Hostname: defaultNodeHostname -Joined at: 2009-11-10 23:00:00 +0000 utc -Status: - State: Ready - Availability: Active - Address: 127.0.0.1 -Platform: - Operating System: linux - Architecture: x86_64 -Resources: - CPUs: 0 - Memory: 20MiB -Plugins: - Network: bridge, overlay - Volume: local -Engine Version: 1.13.0 -Engine Labels: - - engine=label diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-format-flag.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-format-flag.golden deleted file mode 100644 index c898df13e..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-format-flag.golden +++ /dev/null @@ -1,2 +0,0 @@ -nodeHostname1: Leader -nodeHostname2: Reachable diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-format-from-config.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-format-from-config.golden deleted file mode 100644 index 91beb4a29..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-format-from-config.golden +++ /dev/null @@ -1,3 +0,0 @@ -nodeID1: nodeHostname1 Ready/Leader -nodeID2: nodeHostname2 Ready/Reachable -nodeID3: nodeHostname3 Ready/ diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-sort.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-sort.golden deleted file mode 100644 index ad8c34a81..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-list-sort.golden +++ /dev/null @@ -1,4 +0,0 @@ -ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS -nodeID3 node-1-foo Ready Active -nodeID1 * node-2-foo Ready Active Leader -nodeID2 node-10-foo Ready Active Reachable diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-ps.simple.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-ps.simple.golden deleted file mode 100644 index b1818b96b..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-ps.simple.golden +++ /dev/null @@ -1,2 +0,0 @@ -ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -taskID rl02d5gwz6chzu7il5fhtb8be.1 myimage:mytag defaultNodeName Ready Ready 2 hours ago *:80->80/tcp diff --git a/vendor/github.com/docker/cli/cli/command/node/testdata/node-ps.with-errors.golden b/vendor/github.com/docker/cli/cli/command/node/testdata/node-ps.with-errors.golden deleted file mode 100644 index 99e34931a..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/testdata/node-ps.with-errors.golden +++ /dev/null @@ -1,4 +0,0 @@ -ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -taskID1 failure.1 myimage:mytag defaultNodeName Ready Ready 2 hours ago "a task error" -taskID2 \_ failure.1 myimage:mytag defaultNodeName Ready Ready 3 hours ago "a task error" -taskID3 \_ failure.1 myimage:mytag defaultNodeName Ready Ready 4 hours ago "a task error" diff --git a/vendor/github.com/docker/cli/cli/command/node/update.go b/vendor/github.com/docker/cli/cli/command/node/update.go deleted file mode 100644 index 017cf7dcb..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/update.go +++ /dev/null @@ -1,120 +0,0 @@ -package node - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -var ( - errNoRoleChange = errors.New("role was already set to the requested value") -) - -func newUpdateCommand(dockerCli command.Cli) *cobra.Command { - options := newNodeOptions() - - cmd := &cobra.Command{ - Use: "update [OPTIONS] NODE", - Short: "Update a node", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runUpdate(dockerCli, cmd.Flags(), args[0]) - }, - } - - flags := cmd.Flags() - flags.StringVar(&options.role, flagRole, "", `Role of the node ("worker"|"manager")`) - flags.StringVar(&options.availability, flagAvailability, "", `Availability of the node ("active"|"pause"|"drain")`) - flags.Var(&options.annotations.labels, flagLabelAdd, "Add or update a node label (key=value)") - labelKeys := opts.NewListOpts(nil) - flags.Var(&labelKeys, flagLabelRemove, "Remove a node label if exists") - return cmd -} - -func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, nodeID string) error { - success := func(_ string) { - fmt.Fprintln(dockerCli.Out(), nodeID) - } - return updateNodes(dockerCli, []string{nodeID}, mergeNodeUpdate(flags), success) -} - -func updateNodes(dockerCli command.Cli, nodes []string, mergeNode func(node *swarm.Node) error, success func(nodeID string)) error { - client := dockerCli.Client() - ctx := context.Background() - - for _, nodeID := range nodes { - node, _, err := client.NodeInspectWithRaw(ctx, nodeID) - if err != nil { - return err - } - - err = mergeNode(&node) - if err != nil { - if err == errNoRoleChange { - continue - } - return err - } - err = client.NodeUpdate(ctx, node.ID, node.Version, node.Spec) - if err != nil { - return err - } - success(nodeID) - } - return nil -} - -func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) error { - return func(node *swarm.Node) error { - spec := &node.Spec - - if flags.Changed(flagRole) { - str, err := flags.GetString(flagRole) - if err != nil { - return err - } - spec.Role = swarm.NodeRole(str) - } - if flags.Changed(flagAvailability) { - str, err := flags.GetString(flagAvailability) - if err != nil { - return err - } - spec.Availability = swarm.NodeAvailability(str) - } - if spec.Annotations.Labels == nil { - spec.Annotations.Labels = make(map[string]string) - } - if flags.Changed(flagLabelAdd) { - labels := flags.Lookup(flagLabelAdd).Value.(*opts.ListOpts).GetAll() - for k, v := range opts.ConvertKVStringsToMap(labels) { - spec.Annotations.Labels[k] = v - } - } - if flags.Changed(flagLabelRemove) { - keys := flags.Lookup(flagLabelRemove).Value.(*opts.ListOpts).GetAll() - for _, k := range keys { - // if a key doesn't exist, fail the command explicitly - if _, exists := spec.Annotations.Labels[k]; !exists { - return errors.Errorf("key %s doesn't exist in node's labels", k) - } - delete(spec.Annotations.Labels, k) - } - } - return nil - } -} - -const ( - flagRole = "role" - flagAvailability = "availability" - flagLabelAdd = "label-add" - flagLabelRemove = "label-rm" -) diff --git a/vendor/github.com/docker/cli/cli/command/node/update_test.go b/vendor/github.com/docker/cli/cli/command/node/update_test.go deleted file mode 100644 index e1aa28a80..000000000 --- a/vendor/github.com/docker/cli/cli/command/node/update_test.go +++ /dev/null @@ -1,170 +0,0 @@ -package node - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/stretchr/testify/assert" -) - -func TestNodeUpdateErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - nodeInspectFunc func() (swarm.Node, []byte, error) - nodeUpdateFunc func(nodeID string, version swarm.Version, node swarm.NodeSpec) error - expectedError string - }{ - { - expectedError: "requires exactly 1 argument", - }, - { - args: []string{"node1", "node2"}, - expectedError: "requires exactly 1 argument", - }, - { - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting the node") - }, - expectedError: "error inspecting the node", - }, - { - args: []string{"nodeID"}, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - return errors.Errorf("error updating the node") - }, - expectedError: "error updating the node", - }, - { - args: []string{"nodeID"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(NodeLabels(map[string]string{ - "key": "value", - })), []byte{}, nil - }, - flags: map[string]string{ - "label-rm": "notpresent", - }, - expectedError: "key notpresent doesn't exist in node's labels", - }, - } - for _, tc := range testCases { - cmd := newUpdateCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: tc.nodeInspectFunc, - nodeUpdateFunc: tc.nodeUpdateFunc, - })) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestNodeUpdate(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - nodeInspectFunc func() (swarm.Node, []byte, error) - nodeUpdateFunc func(nodeID string, version swarm.Version, node swarm.NodeSpec) error - }{ - { - args: []string{"nodeID"}, - flags: map[string]string{ - "role": "manager", - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if node.Role != swarm.NodeRoleManager { - return errors.Errorf("expected role manager, got %s", node.Role) - } - return nil - }, - }, - { - args: []string{"nodeID"}, - flags: map[string]string{ - "availability": "drain", - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if node.Availability != swarm.NodeAvailabilityDrain { - return errors.Errorf("expected drain availability, got %s", node.Availability) - } - return nil - }, - }, - { - args: []string{"nodeID"}, - flags: map[string]string{ - "label-add": "lbl", - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if _, present := node.Annotations.Labels["lbl"]; !present { - return errors.Errorf("expected 'lbl' label, got %v", node.Annotations.Labels) - } - return nil - }, - }, - { - args: []string{"nodeID"}, - flags: map[string]string{ - "label-add": "key=value", - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if value, present := node.Annotations.Labels["key"]; !present || value != "value" { - return errors.Errorf("expected 'key' label to be 'value', got %v", node.Annotations.Labels) - } - return nil - }, - }, - { - args: []string{"nodeID"}, - flags: map[string]string{ - "label-rm": "key", - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(NodeLabels(map[string]string{ - "key": "value", - })), []byte{}, nil - }, - nodeUpdateFunc: func(nodeID string, version swarm.Version, node swarm.NodeSpec) error { - if len(node.Annotations.Labels) > 0 { - return errors.Errorf("expected no labels, got %v", node.Annotations.Labels) - } - return nil - }, - }, - } - for _, tc := range testCases { - cmd := newUpdateCommand( - test.NewFakeCli(&fakeClient{ - nodeInspectFunc: tc.nodeInspectFunc, - nodeUpdateFunc: tc.nodeUpdateFunc, - })) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - assert.NoError(t, cmd.Execute()) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/out.go b/vendor/github.com/docker/cli/cli/command/out.go deleted file mode 100644 index 89cc5d3aa..000000000 --- a/vendor/github.com/docker/cli/cli/command/out.go +++ /dev/null @@ -1,50 +0,0 @@ -package command - -import ( - "io" - "os" - - "github.com/docker/docker/pkg/term" - "github.com/sirupsen/logrus" -) - -// OutStream is an output stream used by the DockerCli to write normal program -// output. -type OutStream struct { - CommonStream - out io.Writer -} - -func (o *OutStream) Write(p []byte) (int, error) { - return o.out.Write(p) -} - -// SetRawTerminal sets raw mode on the input terminal -func (o *OutStream) SetRawTerminal() (err error) { - if os.Getenv("NORAW") != "" || !o.CommonStream.isTerminal { - return nil - } - o.CommonStream.state, err = term.SetRawTerminalOutput(o.CommonStream.fd) - return err -} - -// GetTtySize returns the height and width in characters of the tty -func (o *OutStream) GetTtySize() (uint, uint) { - if !o.isTerminal { - return 0, 0 - } - ws, err := term.GetWinsize(o.fd) - if err != nil { - logrus.Debugf("Error getting size: %s", err) - if ws == nil { - return 0, 0 - } - } - return uint(ws.Height), uint(ws.Width) -} - -// NewOutStream returns a new OutStream object from a Writer -func NewOutStream(out io.Writer) *OutStream { - fd, isTerminal := term.GetFdInfo(out) - return &OutStream{CommonStream: CommonStream{fd: fd, isTerminal: isTerminal}, out: out} -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/cmd.go b/vendor/github.com/docker/cli/cli/command/plugin/cmd.go deleted file mode 100644 index c29893493..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/cmd.go +++ /dev/null @@ -1,33 +0,0 @@ -package plugin - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewPluginCommand returns a cobra command for `plugin` subcommands -// nolint: interfacer -func NewPluginCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "plugin", - Short: "Manage plugins", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.25"}, - } - - cmd.AddCommand( - newDisableCommand(dockerCli), - newEnableCommand(dockerCli), - newInspectCommand(dockerCli), - newInstallCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - newSetCommand(dockerCli), - newPushCommand(dockerCli), - newCreateCommand(dockerCli), - newUpgradeCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/create.go b/vendor/github.com/docker/cli/cli/command/plugin/create.go deleted file mode 100644 index 56baa4ebe..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/create.go +++ /dev/null @@ -1,128 +0,0 @@ -package plugin - -import ( - "encoding/json" - "fmt" - "io" - "os" - "path/filepath" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/archive" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -// validateTag checks if the given repoName can be resolved. -func validateTag(rawRepo string) error { - _, err := reference.ParseNormalizedNamed(rawRepo) - - return err -} - -// validateConfig ensures that a valid config.json is available in the given path -func validateConfig(path string) error { - dt, err := os.Open(filepath.Join(path, "config.json")) - if err != nil { - return err - } - - m := types.PluginConfig{} - err = json.NewDecoder(dt).Decode(&m) - dt.Close() - - return err -} - -// validateContextDir validates the given dir and returns abs path on success. -func validateContextDir(contextDir string) (string, error) { - absContextDir, err := filepath.Abs(contextDir) - if err != nil { - return "", err - } - stat, err := os.Lstat(absContextDir) - if err != nil { - return "", err - } - - if !stat.IsDir() { - return "", errors.Errorf("context must be a directory") - } - - return absContextDir, nil -} - -type pluginCreateOptions struct { - repoName string - context string - compress bool -} - -func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command { - options := pluginCreateOptions{} - - cmd := &cobra.Command{ - Use: "create [OPTIONS] PLUGIN PLUGIN-DATA-DIR", - Short: "Create a plugin from a rootfs and configuration. Plugin data directory must contain config.json and rootfs directory.", - Args: cli.RequiresMinArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - options.repoName = args[0] - options.context = args[1] - return runCreate(dockerCli, options) - }, - } - - flags := cmd.Flags() - - flags.BoolVar(&options.compress, "compress", false, "Compress the context using gzip") - - return cmd -} - -func runCreate(dockerCli *command.DockerCli, options pluginCreateOptions) error { - var ( - createCtx io.ReadCloser - err error - ) - - if err := validateTag(options.repoName); err != nil { - return err - } - - absContextDir, err := validateContextDir(options.context) - if err != nil { - return err - } - - if err := validateConfig(options.context); err != nil { - return err - } - - compression := archive.Uncompressed - if options.compress { - logrus.Debugf("compression enabled") - compression = archive.Gzip - } - - createCtx, err = archive.TarWithOptions(absContextDir, &archive.TarOptions{ - Compression: compression, - }) - - if err != nil { - return err - } - - ctx := context.Background() - - createOptions := types.PluginCreateOptions{RepoName: options.repoName} - if err = dockerCli.Client().PluginCreate(ctx, createCtx, createOptions); err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), options.repoName) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/disable.go b/vendor/github.com/docker/cli/cli/command/plugin/disable.go deleted file mode 100644 index 1ab33ccf8..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/disable.go +++ /dev/null @@ -1,36 +0,0 @@ -package plugin - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -func newDisableCommand(dockerCli *command.DockerCli) *cobra.Command { - var force bool - - cmd := &cobra.Command{ - Use: "disable [OPTIONS] PLUGIN", - Short: "Disable a plugin", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runDisable(dockerCli, args[0], force) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&force, "force", "f", false, "Force the disable of an active plugin") - return cmd -} - -func runDisable(dockerCli *command.DockerCli, name string, force bool) error { - if err := dockerCli.Client().PluginDisable(context.Background(), name, types.PluginDisableOptions{Force: force}); err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), name) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/enable.go b/vendor/github.com/docker/cli/cli/command/plugin/enable.go deleted file mode 100644 index 53a7acd0c..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/enable.go +++ /dev/null @@ -1,48 +0,0 @@ -package plugin - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type enableOpts struct { - timeout int - name string -} - -func newEnableCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts enableOpts - - cmd := &cobra.Command{ - Use: "enable [OPTIONS] PLUGIN", - Short: "Enable a plugin", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.name = args[0] - return runEnable(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.IntVar(&opts.timeout, "timeout", 0, "HTTP client timeout (in seconds)") - return cmd -} - -func runEnable(dockerCli *command.DockerCli, opts *enableOpts) error { - name := opts.name - if opts.timeout < 0 { - return errors.Errorf("negative timeout %d is invalid", opts.timeout) - } - - if err := dockerCli.Client().PluginEnable(context.Background(), name, types.PluginEnableOptions{Timeout: opts.timeout}); err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), name) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/inspect.go b/vendor/github.com/docker/cli/cli/command/plugin/inspect.go deleted file mode 100644 index 00ae300d5..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/inspect.go +++ /dev/null @@ -1,42 +0,0 @@ -package plugin - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - pluginNames []string - format string -} - -func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] PLUGIN [PLUGIN...]", - Short: "Display detailed information on one or more plugins", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.pluginNames = args - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - return cmd -} - -func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - getRef := func(ref string) (interface{}, []byte, error) { - return client.PluginInspectWithRaw(ctx, ref) - } - - return inspect.Inspect(dockerCli.Out(), opts.pluginNames, opts.format, getRef) -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/install.go b/vendor/github.com/docker/cli/cli/command/plugin/install.go deleted file mode 100644 index 85fd8bad5..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/install.go +++ /dev/null @@ -1,168 +0,0 @@ -package plugin - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/registry" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -type pluginOptions struct { - remote string - localName string - grantPerms bool - disable bool - args []string - skipRemoteCheck bool -} - -func loadPullFlags(opts *pluginOptions, flags *pflag.FlagSet) { - flags.BoolVar(&opts.grantPerms, "grant-all-permissions", false, "Grant all permissions necessary to run the plugin") - command.AddTrustVerificationFlags(flags) -} - -func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command { - var options pluginOptions - cmd := &cobra.Command{ - Use: "install [OPTIONS] PLUGIN [KEY=VALUE...]", - Short: "Install a plugin", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.remote = args[0] - if len(args) > 1 { - options.args = args[1:] - } - return runInstall(dockerCli, options) - }, - } - - flags := cmd.Flags() - loadPullFlags(&options, flags) - flags.BoolVar(&options.disable, "disable", false, "Do not enable the plugin on install") - flags.StringVar(&options.localName, "alias", "", "Local name for plugin") - return cmd -} - -type pluginRegistryService struct { - registry.Service -} - -func (s pluginRegistryService) ResolveRepository(name reference.Named) (repoInfo *registry.RepositoryInfo, err error) { - repoInfo, err = s.Service.ResolveRepository(name) - if repoInfo != nil { - repoInfo.Class = "plugin" - } - return -} - -func newRegistryService() registry.Service { - return pluginRegistryService{ - Service: registry.NewService(registry.ServiceOptions{V2Only: true}), - } -} - -func buildPullConfig(ctx context.Context, dockerCli *command.DockerCli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) { - // Names with both tag and digest will be treated by the daemon - // as a pull by digest with a local name for the tag - // (if no local name is provided). - ref, err := reference.ParseNormalizedNamed(opts.remote) - if err != nil { - return types.PluginInstallOptions{}, err - } - - repoInfo, err := registry.ParseRepositoryInfo(ref) - if err != nil { - return types.PluginInstallOptions{}, err - } - - remote := ref.String() - - _, isCanonical := ref.(reference.Canonical) - if command.IsTrusted() && !isCanonical { - ref = reference.TagNameOnly(ref) - nt, ok := ref.(reference.NamedTagged) - if !ok { - return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String()) - } - - ctx := context.Background() - trusted, err := image.TrustedReference(ctx, dockerCli, nt, newRegistryService()) - if err != nil { - return types.PluginInstallOptions{}, err - } - remote = reference.FamiliarString(trusted) - } - - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) - - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return types.PluginInstallOptions{}, err - } - registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName) - - options := types.PluginInstallOptions{ - RegistryAuth: encodedAuth, - RemoteRef: remote, - Disabled: opts.disable, - AcceptAllPermissions: opts.grantPerms, - AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote), - // TODO: Rename PrivilegeFunc, it has nothing to do with privileges - PrivilegeFunc: registryAuthFunc, - Args: opts.args, - } - return options, nil -} - -func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error { - var localName string - if opts.localName != "" { - aref, err := reference.ParseNormalizedNamed(opts.localName) - if err != nil { - return err - } - if _, ok := aref.(reference.Canonical); ok { - return errors.Errorf("invalid name: %s", opts.localName) - } - localName = reference.FamiliarString(reference.TagNameOnly(aref)) - } - - ctx := context.Background() - options, err := buildPullConfig(ctx, dockerCli, opts, "plugin install") - if err != nil { - return err - } - responseBody, err := dockerCli.Client().PluginInstall(ctx, localName, options) - if err != nil { - if strings.Contains(err.Error(), "(image) when fetching") { - return errors.New(err.Error() + " - Use `docker image pull`") - } - return err - } - defer responseBody.Close() - if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil { - return err - } - fmt.Fprintf(dockerCli.Out(), "Installed plugin %s\n", opts.remote) // todo: return proper values from the API for this result - return nil -} - -func acceptPrivileges(dockerCli *command.DockerCli, name string) func(privileges types.PluginPrivileges) (bool, error) { - return func(privileges types.PluginPrivileges) (bool, error) { - fmt.Fprintf(dockerCli.Out(), "Plugin %q is requesting the following privileges:\n", name) - for _, privilege := range privileges { - fmt.Fprintf(dockerCli.Out(), " - %s: %v\n", privilege.Name, privilege.Value) - } - return command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Do you grant the above permissions?"), nil - } -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/list.go b/vendor/github.com/docker/cli/cli/command/plugin/list.go deleted file mode 100644 index c4bbeb5b4..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/list.go +++ /dev/null @@ -1,63 +0,0 @@ -package plugin - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - noTrunc bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli *command.DockerCli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Short: "List plugins", - Aliases: []string{"list"}, - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display plugin IDs") - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") - flags.StringVar(&options.format, "format", "", "Pretty-print plugins using a Go template") - flags.VarP(&options.filter, "filter", "f", "Provide filter values (e.g. 'enabled=true')") - - return cmd -} - -func runList(dockerCli *command.DockerCli, options listOptions) error { - plugins, err := dockerCli.Client().PluginList(context.Background(), options.filter.Value()) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().PluginsFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().PluginsFormat - } else { - format = formatter.TableFormatKey - } - } - - pluginsCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewPluginFormat(format, options.quiet), - Trunc: !options.noTrunc, - } - return formatter.PluginWrite(pluginsCtx, plugins) -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/push.go b/vendor/github.com/docker/cli/cli/command/plugin/push.go deleted file mode 100644 index 68d25157c..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/push.go +++ /dev/null @@ -1,69 +0,0 @@ -package plugin - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image" - "github.com/docker/distribution/reference" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/registry" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func newPushCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "push [OPTIONS] PLUGIN[:TAG]", - Short: "Push a plugin to a registry", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runPush(dockerCli, args[0]) - }, - } - - flags := cmd.Flags() - - command.AddTrustSigningFlags(flags) - - return cmd -} - -func runPush(dockerCli command.Cli, name string) error { - named, err := reference.ParseNormalizedNamed(name) - if err != nil { - return err - } - if _, ok := named.(reference.Canonical); ok { - return errors.Errorf("invalid name: %s", name) - } - - named = reference.TagNameOnly(named) - - ctx := context.Background() - - repoInfo, err := registry.ParseRepositoryInfo(named) - if err != nil { - return err - } - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) - - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return err - } - - responseBody, err := dockerCli.Client().PluginPush(ctx, reference.FamiliarString(named), encodedAuth) - if err != nil { - return err - } - defer responseBody.Close() - - if command.IsTrusted() { - repoInfo.Class = "plugin" - return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody) - } - - return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil) -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/remove.go b/vendor/github.com/docker/cli/cli/command/plugin/remove.go deleted file mode 100644 index 32211147e..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/remove.go +++ /dev/null @@ -1,55 +0,0 @@ -package plugin - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type rmOptions struct { - force bool - - plugins []string -} - -func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts rmOptions - - cmd := &cobra.Command{ - Use: "rm [OPTIONS] PLUGIN [PLUGIN...]", - Short: "Remove one or more plugins", - Aliases: []string{"remove"}, - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.plugins = args - return runRemove(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.force, "force", "f", false, "Force the removal of an active plugin") - return cmd -} - -func runRemove(dockerCli *command.DockerCli, opts *rmOptions) error { - ctx := context.Background() - - var errs cli.Errors - for _, name := range opts.plugins { - // TODO: pass names to api instead of making multiple api calls - if err := dockerCli.Client().PluginRemove(ctx, name, types.PluginRemoveOptions{Force: opts.force}); err != nil { - errs = append(errs, err) - continue - } - fmt.Fprintln(dockerCli.Out(), name) - } - // Do not simplify to `return errs` because even if errs == nil, it is not a nil-error interface value. - if errs != nil { - return errs - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/set.go b/vendor/github.com/docker/cli/cli/command/plugin/set.go deleted file mode 100644 index 7a69995cd..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/set.go +++ /dev/null @@ -1,22 +0,0 @@ -package plugin - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -func newSetCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "set PLUGIN KEY=VALUE [KEY=VALUE...]", - Short: "Change settings for a plugin", - Args: cli.RequiresMinArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - return dockerCli.Client().PluginSet(context.Background(), args[0], args[1:]) - }, - } - - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/upgrade.go b/vendor/github.com/docker/cli/cli/command/plugin/upgrade.go deleted file mode 100644 index 0e3f56ff6..000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/upgrade.go +++ /dev/null @@ -1,90 +0,0 @@ -package plugin - -import ( - "context" - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/distribution/reference" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func newUpgradeCommand(dockerCli *command.DockerCli) *cobra.Command { - var options pluginOptions - cmd := &cobra.Command{ - Use: "upgrade [OPTIONS] PLUGIN [REMOTE]", - Short: "Upgrade an existing plugin", - Args: cli.RequiresRangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - options.localName = args[0] - if len(args) == 2 { - options.remote = args[1] - } - return runUpgrade(dockerCli, options) - }, - Tags: map[string]string{"version": "1.26"}, - } - - flags := cmd.Flags() - loadPullFlags(&options, flags) - flags.BoolVar(&options.skipRemoteCheck, "skip-remote-check", false, "Do not check if specified remote plugin matches existing plugin image") - return cmd -} - -func runUpgrade(dockerCli *command.DockerCli, opts pluginOptions) error { - ctx := context.Background() - p, _, err := dockerCli.Client().PluginInspectWithRaw(ctx, opts.localName) - if err != nil { - return errors.Errorf("error reading plugin data: %v", err) - } - - if p.Enabled { - return errors.Errorf("the plugin must be disabled before upgrading") - } - - opts.localName = p.Name - if opts.remote == "" { - opts.remote = p.PluginReference - } - remote, err := reference.ParseNormalizedNamed(opts.remote) - if err != nil { - return errors.Wrap(err, "error parsing remote upgrade image reference") - } - remote = reference.TagNameOnly(remote) - - old, err := reference.ParseNormalizedNamed(p.PluginReference) - if err != nil { - return errors.Wrap(err, "error parsing current image reference") - } - old = reference.TagNameOnly(old) - - fmt.Fprintf(dockerCli.Out(), "Upgrading plugin %s from %s to %s\n", p.Name, reference.FamiliarString(old), reference.FamiliarString(remote)) - if !opts.skipRemoteCheck && remote.String() != old.String() { - if !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Plugin images do not match, are you sure?") { - return errors.New("canceling upgrade request") - } - } - - options, err := buildPullConfig(ctx, dockerCli, opts, "plugin upgrade") - if err != nil { - return err - } - - responseBody, err := dockerCli.Client().PluginUpgrade(ctx, opts.localName, options) - if err != nil { - if strings.Contains(err.Error(), "target is image") { - return errors.New(err.Error() + " - Use `docker image pull`") - } - return err - } - defer responseBody.Close() - if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil { - return err - } - fmt.Fprintf(dockerCli.Out(), "Upgraded plugin %s to %s\n", opts.localName, opts.remote) // todo: return proper values from the API for this result - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/registry.go b/vendor/github.com/docker/cli/cli/command/registry.go deleted file mode 100644 index f3958d8a4..000000000 --- a/vendor/github.com/docker/cli/cli/command/registry.go +++ /dev/null @@ -1,189 +0,0 @@ -package command - -import ( - "bufio" - "encoding/base64" - "encoding/json" - "fmt" - "io" - "os" - "runtime" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - registrytypes "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/pkg/term" - "github.com/docker/docker/registry" - "github.com/pkg/errors" -) - -// ElectAuthServer returns the default registry to use (by asking the daemon) -func ElectAuthServer(ctx context.Context, cli Cli) string { - // The daemon `/info` endpoint informs us of the default registry being - // used. This is essential in cross-platforms environment, where for - // example a Linux client might be interacting with a Windows daemon, hence - // the default registry URL might be Windows specific. - serverAddress := registry.IndexServer - if info, err := cli.Client().Info(ctx); err != nil { - fmt.Fprintf(cli.Err(), "Warning: failed to get default registry endpoint from daemon (%v). Using system default: %s\n", err, serverAddress) - } else if info.IndexServerAddress == "" { - fmt.Fprintf(cli.Err(), "Warning: Empty registry endpoint from daemon. Using system default: %s\n", serverAddress) - } else { - serverAddress = info.IndexServerAddress - } - return serverAddress -} - -// EncodeAuthToBase64 serializes the auth configuration as JSON base64 payload -func EncodeAuthToBase64(authConfig types.AuthConfig) (string, error) { - buf, err := json.Marshal(authConfig) - if err != nil { - return "", err - } - return base64.URLEncoding.EncodeToString(buf), nil -} - -// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info -// for the given command. -func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) types.RequestPrivilegeFunc { - return func() (string, error) { - fmt.Fprintf(cli.Out(), "\nPlease login prior to %s:\n", cmdName) - indexServer := registry.GetAuthConfigKey(index) - isDefaultRegistry := indexServer == ElectAuthServer(context.Background(), cli) - authConfig, err := ConfigureAuth(cli, "", "", indexServer, isDefaultRegistry) - if err != nil { - return "", err - } - return EncodeAuthToBase64(authConfig) - } -} - -// ResolveAuthConfig is like registry.ResolveAuthConfig, but if using the -// default index, it uses the default index name for the daemon's platform, -// not the client's platform. -func ResolveAuthConfig(ctx context.Context, cli Cli, index *registrytypes.IndexInfo) types.AuthConfig { - configKey := index.Name - if index.Official { - configKey = ElectAuthServer(ctx, cli) - } - - a, _ := cli.ConfigFile().GetAuthConfig(configKey) - return a -} - -// ConfigureAuth returns an AuthConfig from the specified user, password and server. -func ConfigureAuth(cli Cli, flUser, flPassword, serverAddress string, isDefaultRegistry bool) (types.AuthConfig, error) { - // On Windows, force the use of the regular OS stdin stream. Fixes #14336/#14210 - if runtime.GOOS == "windows" { - cli.SetIn(NewInStream(os.Stdin)) - } - - if !isDefaultRegistry { - serverAddress = registry.ConvertToHostname(serverAddress) - } - - authconfig, err := cli.ConfigFile().GetAuthConfig(serverAddress) - if err != nil { - return authconfig, err - } - - // Some links documenting this: - // - https://code.google.com/archive/p/mintty/issues/56 - // - https://github.com/docker/docker/issues/15272 - // - https://mintty.github.io/ (compatibility) - // Linux will hit this if you attempt `cat | docker login`, and Windows - // will hit this if you attempt docker login from mintty where stdin - // is a pipe, not a character based console. - if flPassword == "" && !cli.In().IsTerminal() { - return authconfig, errors.Errorf("Error: Cannot perform an interactive login from a non TTY device") - } - - authconfig.Username = strings.TrimSpace(authconfig.Username) - - if flUser = strings.TrimSpace(flUser); flUser == "" { - if isDefaultRegistry { - // if this is a default registry (docker hub), then display the following message. - fmt.Fprintln(cli.Out(), "Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.") - } - promptWithDefault(cli.Out(), "Username", authconfig.Username) - flUser = readInput(cli.In(), cli.Out()) - flUser = strings.TrimSpace(flUser) - if flUser == "" { - flUser = authconfig.Username - } - } - if flUser == "" { - return authconfig, errors.Errorf("Error: Non-null Username Required") - } - if flPassword == "" { - oldState, err := term.SaveState(cli.In().FD()) - if err != nil { - return authconfig, err - } - fmt.Fprintf(cli.Out(), "Password: ") - term.DisableEcho(cli.In().FD(), oldState) - - flPassword = readInput(cli.In(), cli.Out()) - fmt.Fprint(cli.Out(), "\n") - - term.RestoreTerminal(cli.In().FD(), oldState) - if flPassword == "" { - return authconfig, errors.Errorf("Error: Password Required") - } - } - - authconfig.Username = flUser - authconfig.Password = flPassword - authconfig.ServerAddress = serverAddress - authconfig.IdentityToken = "" - - return authconfig, nil -} - -func readInput(in io.Reader, out io.Writer) string { - reader := bufio.NewReader(in) - line, _, err := reader.ReadLine() - if err != nil { - fmt.Fprintln(out, err.Error()) - os.Exit(1) - } - return string(line) -} - -func promptWithDefault(out io.Writer, prompt string, configDefault string) { - if configDefault == "" { - fmt.Fprintf(out, "%s: ", prompt) - } else { - fmt.Fprintf(out, "%s (%s): ", prompt, configDefault) - } -} - -// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete image -func RetrieveAuthTokenFromImage(ctx context.Context, cli Cli, image string) (string, error) { - // Retrieve encoded auth token from the image reference - authConfig, err := resolveAuthConfigFromImage(ctx, cli, image) - if err != nil { - return "", err - } - encodedAuth, err := EncodeAuthToBase64(authConfig) - if err != nil { - return "", err - } - return encodedAuth, nil -} - -// resolveAuthConfigFromImage retrieves that AuthConfig using the image string -func resolveAuthConfigFromImage(ctx context.Context, cli Cli, image string) (types.AuthConfig, error) { - registryRef, err := reference.ParseNormalizedNamed(image) - if err != nil { - return types.AuthConfig{}, err - } - repoInfo, err := registry.ParseRepositoryInfo(registryRef) - if err != nil { - return types.AuthConfig{}, err - } - return ResolveAuthConfig(ctx, cli, repoInfo.Index), nil -} diff --git a/vendor/github.com/docker/cli/cli/command/registry/login.go b/vendor/github.com/docker/cli/cli/command/registry/login.go deleted file mode 100644 index 938fef8ab..000000000 --- a/vendor/github.com/docker/cli/cli/command/registry/login.go +++ /dev/null @@ -1,107 +0,0 @@ -package registry - -import ( - "fmt" - "io/ioutil" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/registry" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type loginOptions struct { - serverAddress string - user string - password string - passwordStdin bool -} - -// NewLoginCommand creates a new `docker login` command -func NewLoginCommand(dockerCli command.Cli) *cobra.Command { - var opts loginOptions - - cmd := &cobra.Command{ - Use: "login [OPTIONS] [SERVER]", - Short: "Log in to a Docker registry", - Long: "Log in to a Docker registry.\nIf no server is specified, the default is defined by the daemon.", - Args: cli.RequiresMaxArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) > 0 { - opts.serverAddress = args[0] - } - return runLogin(dockerCli, opts) - }, - } - - flags := cmd.Flags() - - flags.StringVarP(&opts.user, "username", "u", "", "Username") - flags.StringVarP(&opts.password, "password", "p", "", "Password") - flags.BoolVarP(&opts.passwordStdin, "password-stdin", "", false, "Take the password from stdin") - - return cmd -} - -func runLogin(dockerCli command.Cli, opts loginOptions) error { - ctx := context.Background() - clnt := dockerCli.Client() - - if opts.password != "" { - fmt.Fprintln(dockerCli.Err(), "WARNING! Using --password via the CLI is insecure. Use --password-stdin.") - if opts.passwordStdin { - return errors.New("--password and --password-stdin are mutually exclusive") - } - } - - if opts.passwordStdin { - if opts.user == "" { - return errors.New("Must provide --username with --password-stdin") - } - - contents, err := ioutil.ReadAll(dockerCli.In()) - if err != nil { - return err - } - - opts.password = strings.TrimSuffix(string(contents), "\n") - opts.password = strings.TrimSuffix(opts.password, "\r") - } - - var ( - serverAddress string - authServer = command.ElectAuthServer(ctx, dockerCli) - ) - if opts.serverAddress != "" && opts.serverAddress != registry.DefaultNamespace { - serverAddress = opts.serverAddress - } else { - serverAddress = authServer - } - - isDefaultRegistry := serverAddress == authServer - - authConfig, err := command.ConfigureAuth(dockerCli, opts.user, opts.password, serverAddress, isDefaultRegistry) - if err != nil { - return err - } - response, err := clnt.RegistryLogin(ctx, authConfig) - if err != nil { - return err - } - if response.IdentityToken != "" { - authConfig.Password = "" - authConfig.IdentityToken = response.IdentityToken - } - if err := dockerCli.ConfigFile().GetCredentialsStore(serverAddress).Store(authConfig); err != nil { - return errors.Errorf("Error saving credentials: %v", err) - } - - if response.Status != "" { - fmt.Fprintln(dockerCli.Out(), response.Status) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/registry/logout.go b/vendor/github.com/docker/cli/cli/command/registry/logout.go deleted file mode 100644 index cce626e58..000000000 --- a/vendor/github.com/docker/cli/cli/command/registry/logout.go +++ /dev/null @@ -1,77 +0,0 @@ -package registry - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/registry" - "github.com/spf13/cobra" -) - -// NewLogoutCommand creates a new `docker logout` command -func NewLogoutCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "logout [SERVER]", - Short: "Log out from a Docker registry", - Long: "Log out from a Docker registry.\nIf no server is specified, the default is defined by the daemon.", - Args: cli.RequiresMaxArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - var serverAddress string - if len(args) > 0 { - serverAddress = args[0] - } - return runLogout(dockerCli, serverAddress) - }, - } - - return cmd -} - -func runLogout(dockerCli command.Cli, serverAddress string) error { - ctx := context.Background() - var isDefaultRegistry bool - - if serverAddress == "" { - serverAddress = command.ElectAuthServer(ctx, dockerCli) - isDefaultRegistry = true - } - - var ( - loggedIn bool - regsToLogout []string - hostnameAddress = serverAddress - regsToTry = []string{serverAddress} - ) - if !isDefaultRegistry { - hostnameAddress = registry.ConvertToHostname(serverAddress) - // the tries below are kept for backward compatibility where a user could have - // saved the registry in one of the following format. - regsToTry = append(regsToTry, hostnameAddress, "http://"+hostnameAddress, "https://"+hostnameAddress) - } - - // check if we're logged in based on the records in the config file - // which means it couldn't have user/pass cause they may be in the creds store - for _, s := range regsToTry { - if _, ok := dockerCli.ConfigFile().AuthConfigs[s]; ok { - loggedIn = true - regsToLogout = append(regsToLogout, s) - } - } - - if !loggedIn { - fmt.Fprintf(dockerCli.Out(), "Not logged in to %s\n", hostnameAddress) - return nil - } - - fmt.Fprintf(dockerCli.Out(), "Removing login credentials for %s\n", hostnameAddress) - for _, r := range regsToLogout { - if err := dockerCli.ConfigFile().GetCredentialsStore(r).Erase(r); err != nil { - fmt.Fprintf(dockerCli.Err(), "WARNING: could not erase credentials: %v\n", err) - } - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/registry/search.go b/vendor/github.com/docker/cli/cli/command/registry/search.go deleted file mode 100644 index 49ac0f43c..000000000 --- a/vendor/github.com/docker/cli/cli/command/registry/search.go +++ /dev/null @@ -1,104 +0,0 @@ -package registry - -import ( - "sort" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - registrytypes "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/registry" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type searchOptions struct { - format string - term string - noTrunc bool - limit int - filter opts.FilterOpt - - // Deprecated - stars uint - automated bool -} - -// NewSearchCommand creates a new `docker search` command -func NewSearchCommand(dockerCli command.Cli) *cobra.Command { - options := searchOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "search [OPTIONS] TERM", - Short: "Search the Docker Hub for images", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.term = args[0] - return runSearch(dockerCli, options) - }, - } - - flags := cmd.Flags() - - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - flags.IntVar(&options.limit, "limit", registry.DefaultSearchLimit, "Max number of search results") - flags.StringVar(&options.format, "format", "", "Pretty-print search using a Go template") - - flags.BoolVar(&options.automated, "automated", false, "Only show automated builds") - flags.UintVarP(&options.stars, "stars", "s", 0, "Only displays with at least x stars") - - flags.MarkDeprecated("automated", "use --filter=is-automated=true instead") - flags.MarkDeprecated("stars", "use --filter=stars=3 instead") - - return cmd -} - -func runSearch(dockerCli command.Cli, options searchOptions) error { - indexInfo, err := registry.ParseSearchIndexInfo(options.term) - if err != nil { - return err - } - - ctx := context.Background() - - authConfig := command.ResolveAuthConfig(ctx, dockerCli, indexInfo) - requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, indexInfo, "search") - - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return err - } - - searchOptions := types.ImageSearchOptions{ - RegistryAuth: encodedAuth, - PrivilegeFunc: requestPrivilege, - Filters: options.filter.Value(), - Limit: options.limit, - } - - clnt := dockerCli.Client() - - unorderedResults, err := clnt.ImageSearch(ctx, options.term, searchOptions) - if err != nil { - return err - } - - results := searchResultsByStars(unorderedResults) - sort.Sort(results) - searchCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewSearchFormat(options.format), - Trunc: !options.noTrunc, - } - return formatter.SearchWrite(searchCtx, results, options.automated, int(options.stars)) -} - -// searchResultsByStars sorts search results in descending order by number of stars. -type searchResultsByStars []registrytypes.SearchResult - -func (r searchResultsByStars) Len() int { return len(r) } -func (r searchResultsByStars) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r searchResultsByStars) Less(i, j int) bool { return r[j].StarCount < r[i].StarCount } diff --git a/vendor/github.com/docker/cli/cli/command/registry_test.go b/vendor/github.com/docker/cli/cli/command/registry_test.go deleted file mode 100644 index 3f3d5f579..000000000 --- a/vendor/github.com/docker/cli/cli/command/registry_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package command_test - -import ( - "testing" - - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - - // Prevents a circular import with "github.com/docker/cli/internal/test" - . "github.com/docker/cli/cli/command" - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" -) - -type fakeClient struct { - client.Client - infoFunc func() (types.Info, error) -} - -func (cli *fakeClient) Info(_ context.Context) (types.Info, error) { - if cli.infoFunc != nil { - return cli.infoFunc() - } - return types.Info{}, nil -} - -func TestElectAuthServer(t *testing.T) { - testCases := []struct { - expectedAuthServer string - expectedWarning string - infoFunc func() (types.Info, error) - }{ - { - expectedAuthServer: "https://index.docker.io/v1/", - expectedWarning: "", - infoFunc: func() (types.Info, error) { - return types.Info{IndexServerAddress: "https://index.docker.io/v1/"}, nil - }, - }, - { - expectedAuthServer: "https://index.docker.io/v1/", - expectedWarning: "Empty registry endpoint from daemon", - infoFunc: func() (types.Info, error) { - return types.Info{IndexServerAddress: ""}, nil - }, - }, - { - expectedAuthServer: "https://foo.bar", - expectedWarning: "", - infoFunc: func() (types.Info, error) { - return types.Info{IndexServerAddress: "https://foo.bar"}, nil - }, - }, - { - expectedAuthServer: "https://index.docker.io/v1/", - expectedWarning: "failed to get default registry endpoint from daemon", - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error getting info") - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{infoFunc: tc.infoFunc}) - server := ElectAuthServer(context.Background(), cli) - assert.Equal(t, tc.expectedAuthServer, server) - actual := cli.ErrBuffer().String() - if tc.expectedWarning == "" { - assert.Empty(t, actual) - } else { - assert.Contains(t, actual, tc.expectedWarning) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/client_test.go b/vendor/github.com/docker/cli/cli/command/secret/client_test.go deleted file mode 100644 index bb4b412fc..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/client_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package secret - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error) - secretInspectFunc func(string) (swarm.Secret, []byte, error) - secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error) - secretRemoveFunc func(string) error -} - -func (c *fakeClient) SecretCreate(ctx context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) { - if c.secretCreateFunc != nil { - return c.secretCreateFunc(spec) - } - return types.SecretCreateResponse{}, nil -} - -func (c *fakeClient) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) { - if c.secretInspectFunc != nil { - return c.secretInspectFunc(id) - } - return swarm.Secret{}, nil, nil -} - -func (c *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) { - if c.secretListFunc != nil { - return c.secretListFunc(options) - } - return []swarm.Secret{}, nil -} - -func (c *fakeClient) SecretRemove(ctx context.Context, name string) error { - if c.secretRemoveFunc != nil { - return c.secretRemoveFunc(name) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/cmd.go b/vendor/github.com/docker/cli/cli/command/secret/cmd.go deleted file mode 100644 index 9f8e84345..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/cmd.go +++ /dev/null @@ -1,27 +0,0 @@ -package secret - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewSecretCommand returns a cobra command for `secret` subcommands -// nolint: interfacer -func NewSecretCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "secret", - Short: "Manage Docker secrets", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.25"}, - } - cmd.AddCommand( - newSecretListCommand(dockerCli), - newSecretCreateCommand(dockerCli), - newSecretInspectCommand(dockerCli), - newSecretRemoveCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/create.go b/vendor/github.com/docker/cli/cli/command/secret/create.go deleted file mode 100644 index 6ade18bdf..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/create.go +++ /dev/null @@ -1,102 +0,0 @@ -package secret - -import ( - "fmt" - "io" - "io/ioutil" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/system" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type createOptions struct { - name string - driver string - file string - labels opts.ListOpts -} - -func newSecretCreateCommand(dockerCli command.Cli) *cobra.Command { - options := createOptions{ - labels: opts.NewListOpts(opts.ValidateEnv), - } - - cmd := &cobra.Command{ - Use: "create [OPTIONS] SECRET [file|-]", - Short: "Create a secret from a file or STDIN as content", - Args: cli.RequiresRangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - options.name = args[0] - if len(args) == 2 { - options.file = args[1] - } - return runSecretCreate(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.VarP(&options.labels, "label", "l", "Secret labels") - flags.StringVarP(&options.driver, "driver", "d", "", "Secret driver") - flags.SetAnnotation("driver", "version", []string{"1.31"}) - - return cmd -} - -func runSecretCreate(dockerCli command.Cli, options createOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if options.driver != "" && options.file != "" { - return errors.Errorf("When using secret driver secret data must be empty") - } - - secretData, err := readSecretData(dockerCli.In(), options.file) - if err != nil { - return errors.Errorf("Error reading content from %q: %v", options.file, err) - } - spec := swarm.SecretSpec{ - Annotations: swarm.Annotations{ - Name: options.name, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - }, - Data: secretData, - } - if options.driver != "" { - spec.Driver = &swarm.Driver{ - Name: options.driver, - } - } - - r, err := client.SecretCreate(ctx, spec) - if err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), r.ID) - return nil -} - -func readSecretData(in io.ReadCloser, file string) ([]byte, error) { - // Read secret value from external driver - if file == "" { - return nil, nil - } - if file != "-" { - var err error - in, err = system.OpenSequential(file) - if err != nil { - return nil, err - } - defer in.Close() - } - data, err := ioutil.ReadAll(in) - if err != nil { - return nil, err - } - return data, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/create_test.go b/vendor/github.com/docker/cli/cli/command/secret/create_test.go deleted file mode 100644 index 442dd7a91..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/create_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package secret - -import ( - "io/ioutil" - "path/filepath" - "reflect" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -const secretDataFile = "secret-create-with-name.golden" - -func TestSecretCreateErrors(t *testing.T) { - testCases := []struct { - args []string - secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error) - expectedError string - }{ - {args: []string{"too", "many", "arguments"}, - expectedError: "requires at least 1 and at most 2 arguments", - }, - {args: []string{"create", "--driver", "driver", "-"}, - expectedError: "secret data must be empty", - }, - { - args: []string{"name", filepath.Join("testdata", secretDataFile)}, - secretCreateFunc: func(secretSpec swarm.SecretSpec) (types.SecretCreateResponse, error) { - return types.SecretCreateResponse{}, errors.Errorf("error creating secret") - }, - expectedError: "error creating secret", - }, - } - for _, tc := range testCases { - cmd := newSecretCreateCommand( - test.NewFakeCli(&fakeClient{ - secretCreateFunc: tc.secretCreateFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSecretCreateWithName(t *testing.T) { - name := "foo" - var actual []byte - cli := test.NewFakeCli(&fakeClient{ - secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) { - if spec.Name != name { - return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name) - } - - actual = spec.Data - - return types.SecretCreateResponse{ - ID: "ID-" + spec.Name, - }, nil - }, - }) - - cmd := newSecretCreateCommand(cli) - cmd.SetArgs([]string{name, filepath.Join("testdata", secretDataFile)}) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, string(actual), secretDataFile) - assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String())) -} - -func TestSecretCreateWithDriver(t *testing.T) { - expectedDriver := &swarm.Driver{ - Name: "secret-driver", - } - name := "foo" - - cli := test.NewFakeCli(&fakeClient{ - secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) { - if spec.Name != name { - return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name) - } - - if !reflect.DeepEqual(spec.Driver.Name, expectedDriver.Name) { - return types.SecretCreateResponse{}, errors.Errorf("expected driver %v, got %v", expectedDriver, spec.Labels) - } - - return types.SecretCreateResponse{ - ID: "ID-" + spec.Name, - }, nil - }, - }) - - cmd := newSecretCreateCommand(cli) - cmd.SetArgs([]string{name}) - cmd.Flags().Set("driver", expectedDriver.Name) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String())) -} - -func TestSecretCreateWithLabels(t *testing.T) { - expectedLabels := map[string]string{ - "lbl1": "Label-foo", - "lbl2": "Label-bar", - } - name := "foo" - - cli := test.NewFakeCli(&fakeClient{ - secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) { - if spec.Name != name { - return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name) - } - - if !reflect.DeepEqual(spec.Labels, expectedLabels) { - return types.SecretCreateResponse{}, errors.Errorf("expected labels %v, got %v", expectedLabels, spec.Labels) - } - - return types.SecretCreateResponse{ - ID: "ID-" + spec.Name, - }, nil - }, - }) - - cmd := newSecretCreateCommand(cli) - cmd.SetArgs([]string{name, filepath.Join("testdata", secretDataFile)}) - cmd.Flags().Set("label", "lbl1=Label-foo") - cmd.Flags().Set("label", "lbl2=Label-bar") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "ID-"+name, strings.TrimSpace(cli.OutBuffer().String())) -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/inspect.go b/vendor/github.com/docker/cli/cli/command/secret/inspect.go deleted file mode 100644 index 51410487a..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/inspect.go +++ /dev/null @@ -1,65 +0,0 @@ -package secret - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - names []string - format string - pretty bool -} - -func newSecretInspectCommand(dockerCli command.Cli) *cobra.Command { - opts := inspectOptions{} - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] SECRET [SECRET...]", - Short: "Display detailed information on one or more secrets", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.names = args - return runSecretInspect(dockerCli, opts) - }, - } - - cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - cmd.Flags().BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runSecretInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(id string) (interface{}, []byte, error) { - return client.SecretInspectWithRaw(ctx, id) - } - f := opts.format - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return fmt.Errorf("Cannot supply extra formatting options to the pretty template") - } - - secretCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewSecretFormat(f, false), - } - - if err := formatter.SecretInspectWrite(secretCtx, opts.names, getRef); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/inspect_test.go b/vendor/github.com/docker/cli/cli/command/secret/inspect_test.go deleted file mode 100644 index cb74e11ae..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/inspect_test.go +++ /dev/null @@ -1,174 +0,0 @@ -package secret - -import ( - "fmt" - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestSecretInspectErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - secretInspectFunc func(secretID string) (swarm.Secret, []byte, error) - expectedError string - }{ - { - expectedError: "requires at least 1 argument", - }, - { - args: []string{"foo"}, - secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) { - return swarm.Secret{}, nil, errors.Errorf("error while inspecting the secret") - }, - expectedError: "error while inspecting the secret", - }, - { - args: []string{"foo"}, - flags: map[string]string{ - "format": "{{invalid format}}", - }, - expectedError: "Template parsing error", - }, - { - args: []string{"foo", "bar"}, - secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) { - if secretID == "foo" { - return *Secret(SecretName("foo")), nil, nil - } - return swarm.Secret{}, nil, errors.Errorf("error while inspecting the secret") - }, - expectedError: "error while inspecting the secret", - }, - } - for _, tc := range testCases { - cmd := newSecretInspectCommand( - test.NewFakeCli(&fakeClient{ - secretInspectFunc: tc.secretInspectFunc, - }), - ) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSecretInspectWithoutFormat(t *testing.T) { - testCases := []struct { - name string - args []string - secretInspectFunc func(secretID string) (swarm.Secret, []byte, error) - }{ - { - name: "single-secret", - args: []string{"foo"}, - secretInspectFunc: func(name string) (swarm.Secret, []byte, error) { - if name != "foo" { - return swarm.Secret{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name) - } - return *Secret(SecretID("ID-foo"), SecretName("foo")), nil, nil - }, - }, - { - name: "multiple-secrets-with-labels", - args: []string{"foo", "bar"}, - secretInspectFunc: func(name string) (swarm.Secret, []byte, error) { - return *Secret(SecretID("ID-"+name), SecretName(name), SecretLabels(map[string]string{ - "label1": "label-foo", - })), nil, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - secretInspectFunc: tc.secretInspectFunc, - }) - cmd := newSecretInspectCommand(cli) - cmd.SetArgs(tc.args) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("secret-inspect-without-format.%s.golden", tc.name)) - } -} - -func TestSecretInspectWithFormat(t *testing.T) { - secretInspectFunc := func(name string) (swarm.Secret, []byte, error) { - return *Secret(SecretName("foo"), SecretLabels(map[string]string{ - "label1": "label-foo", - })), nil, nil - } - testCases := []struct { - name string - format string - args []string - secretInspectFunc func(name string) (swarm.Secret, []byte, error) - }{ - { - name: "simple-template", - format: "{{.Spec.Name}}", - args: []string{"foo"}, - secretInspectFunc: secretInspectFunc, - }, - { - name: "json-template", - format: "{{json .Spec.Labels}}", - args: []string{"foo"}, - secretInspectFunc: secretInspectFunc, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - secretInspectFunc: tc.secretInspectFunc, - }) - cmd := newSecretInspectCommand(cli) - cmd.SetArgs(tc.args) - cmd.Flags().Set("format", tc.format) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("secret-inspect-with-format.%s.golden", tc.name)) - } -} - -func TestSecretInspectPretty(t *testing.T) { - testCases := []struct { - name string - secretInspectFunc func(string) (swarm.Secret, []byte, error) - }{ - { - name: "simple", - secretInspectFunc: func(id string) (swarm.Secret, []byte, error) { - return *Secret( - SecretLabels(map[string]string{ - "lbl1": "value1", - }), - SecretID("secretID"), - SecretName("secretName"), - SecretDriver("driver"), - SecretCreatedAt(time.Time{}), - SecretUpdatedAt(time.Time{}), - ), []byte{}, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - secretInspectFunc: tc.secretInspectFunc, - }) - cmd := newSecretInspectCommand(cli) - cmd.SetArgs([]string{"secretID"}) - cmd.Flags().Set("pretty", "true") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("secret-inspect-pretty.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/ls.go b/vendor/github.com/docker/cli/cli/command/secret/ls.go deleted file mode 100644 index 35bc3da0f..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/ls.go +++ /dev/null @@ -1,61 +0,0 @@ -package secret - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newSecretListCommand(dockerCli command.Cli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List secrets", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runSecretList(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVarP(&options.format, "format", "", "", "Pretty-print secrets using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runSecretList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - secrets, err := client.SecretList(ctx, types.SecretListOptions{Filters: options.filter.Value()}) - if err != nil { - return err - } - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().SecretFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().SecretFormat - } else { - format = formatter.TableFormatKey - } - } - secretCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewSecretFormat(format, options.quiet), - } - return formatter.SecretWrite(secretCtx, secrets) -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/ls_test.go b/vendor/github.com/docker/cli/cli/command/secret/ls_test.go deleted file mode 100644 index 83f6742af..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/ls_test.go +++ /dev/null @@ -1,156 +0,0 @@ -package secret - -import ( - "bytes" - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestSecretListErrors(t *testing.T) { - testCases := []struct { - args []string - secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error) - expectedError string - }{ - { - args: []string{"foo"}, - expectedError: "accepts no argument", - }, - { - secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { - return []swarm.Secret{}, errors.Errorf("error listing secrets") - }, - expectedError: "error listing secrets", - }, - } - for _, tc := range testCases { - cmd := newSecretListCommand( - test.NewFakeCli(&fakeClient{ - secretListFunc: tc.secretListFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSecretList(t *testing.T) { - buf := new(bytes.Buffer) - cli := test.NewFakeCli(&fakeClient{ - secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { - return []swarm.Secret{ - *Secret(SecretID("ID-foo"), - SecretName("foo"), - SecretVersion(swarm.Version{Index: 10}), - SecretCreatedAt(time.Now().Add(-2*time.Hour)), - SecretUpdatedAt(time.Now().Add(-1*time.Hour)), - ), - *Secret(SecretID("ID-bar"), - SecretName("bar"), - SecretVersion(swarm.Version{Index: 11}), - SecretCreatedAt(time.Now().Add(-2*time.Hour)), - SecretUpdatedAt(time.Now().Add(-1*time.Hour)), - SecretDriver("driver"), - ), - }, nil - }, - }) - cmd := newSecretListCommand(cli) - cmd.SetOutput(buf) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "secret-list.golden") -} - -func TestSecretListWithQuietOption(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { - return []swarm.Secret{ - *Secret(SecretID("ID-foo"), SecretName("foo")), - *Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{ - "label": "label-bar", - })), - }, nil - }, - }) - cmd := newSecretListCommand(cli) - cmd.Flags().Set("quiet", "true") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "secret-list-with-quiet-option.golden") -} - -func TestSecretListWithConfigFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { - return []swarm.Secret{ - *Secret(SecretID("ID-foo"), SecretName("foo")), - *Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{ - "label": "label-bar", - })), - }, nil - }, - }) - cli.SetConfigFile(&configfile.ConfigFile{ - SecretFormat: "{{ .Name }} {{ .Labels }}", - }) - cmd := newSecretListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "secret-list-with-config-format.golden") -} - -func TestSecretListWithFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { - return []swarm.Secret{ - *Secret(SecretID("ID-foo"), SecretName("foo")), - *Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{ - "label": "label-bar", - })), - }, nil - }, - }) - cmd := newSecretListCommand(cli) - cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "secret-list-with-format.golden") -} - -func TestSecretListWithFilter(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { - assert.Equal(t, "foo", options.Filters.Get("name")[0], "foo") - assert.Equal(t, "lbl1=Label-bar", options.Filters.Get("label")[0]) - return []swarm.Secret{ - *Secret(SecretID("ID-foo"), - SecretName("foo"), - SecretVersion(swarm.Version{Index: 10}), - SecretCreatedAt(time.Now().Add(-2*time.Hour)), - SecretUpdatedAt(time.Now().Add(-1*time.Hour)), - ), - *Secret(SecretID("ID-bar"), - SecretName("bar"), - SecretVersion(swarm.Version{Index: 11}), - SecretCreatedAt(time.Now().Add(-2*time.Hour)), - SecretUpdatedAt(time.Now().Add(-1*time.Hour)), - ), - }, nil - }, - }) - cmd := newSecretListCommand(cli) - cmd.Flags().Set("filter", "name=foo") - cmd.Flags().Set("filter", "label=lbl1=Label-bar") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "secret-list-with-filter.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/remove.go b/vendor/github.com/docker/cli/cli/command/secret/remove.go deleted file mode 100644 index 969b9ceb7..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/remove.go +++ /dev/null @@ -1,53 +0,0 @@ -package secret - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type removeOptions struct { - names []string -} - -func newSecretRemoveCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "rm SECRET [SECRET...]", - Aliases: []string{"remove"}, - Short: "Remove one or more secrets", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts := removeOptions{ - names: args, - } - return runSecretRemove(dockerCli, opts) - }, - } -} - -func runSecretRemove(dockerCli command.Cli, opts removeOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - - for _, name := range opts.names { - if err := client.SecretRemove(ctx, name); err != nil { - errs = append(errs, err.Error()) - continue - } - - fmt.Fprintln(dockerCli.Out(), name) - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/remove_test.go b/vendor/github.com/docker/cli/cli/command/secret/remove_test.go deleted file mode 100644 index accb3ea04..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/remove_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package secret - -import ( - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestSecretRemoveErrors(t *testing.T) { - testCases := []struct { - args []string - secretRemoveFunc func(string) error - expectedError string - }{ - { - args: []string{}, - expectedError: "requires at least 1 argument.", - }, - { - args: []string{"foo"}, - secretRemoveFunc: func(name string) error { - return errors.Errorf("error removing secret") - }, - expectedError: "error removing secret", - }, - } - for _, tc := range testCases { - cmd := newSecretRemoveCommand( - test.NewFakeCli(&fakeClient{ - secretRemoveFunc: tc.secretRemoveFunc, - }), - ) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSecretRemoveWithName(t *testing.T) { - names := []string{"foo", "bar"} - var removedSecrets []string - cli := test.NewFakeCli(&fakeClient{ - secretRemoveFunc: func(name string) error { - removedSecrets = append(removedSecrets, name) - return nil - }, - }) - cmd := newSecretRemoveCommand(cli) - cmd.SetArgs(names) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, names, strings.Split(strings.TrimSpace(cli.OutBuffer().String()), "\n")) - assert.Equal(t, names, removedSecrets) -} - -func TestSecretRemoveContinueAfterError(t *testing.T) { - names := []string{"foo", "bar"} - var removedSecrets []string - - cli := test.NewFakeCli(&fakeClient{ - secretRemoveFunc: func(name string) error { - removedSecrets = append(removedSecrets, name) - if name == "foo" { - return errors.Errorf("error removing secret: %s", name) - } - return nil - }, - }) - - cmd := newSecretRemoveCommand(cli) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs(names) - assert.EqualError(t, cmd.Execute(), "error removing secret: foo") - assert.Equal(t, names, removedSecrets) -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-create-with-name.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-create-with-name.golden deleted file mode 100644 index 788642a93..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-create-with-name.golden +++ /dev/null @@ -1 +0,0 @@ -secret_foo_bar diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-pretty.simple.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-pretty.simple.golden deleted file mode 100644 index 37234eff7..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-pretty.simple.golden +++ /dev/null @@ -1,7 +0,0 @@ -ID: secretID -Name: secretName -Labels: - - lbl1=value1 -Driver: driver -Created at: 0001-01-01 00:00:00 +0000 utc -Updated at: 0001-01-01 00:00:00 +0000 utc diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-with-format.json-template.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-with-format.json-template.golden deleted file mode 100644 index aab678f85..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-with-format.json-template.golden +++ /dev/null @@ -1 +0,0 @@ -{"label1":"label-foo"} diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden deleted file mode 100644 index 257cc5642..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden +++ /dev/null @@ -1 +0,0 @@ -foo diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden deleted file mode 100644 index b01a400c5..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "ID": "ID-foo", - "Version": {}, - "CreatedAt": "0001-01-01T00:00:00Z", - "UpdatedAt": "0001-01-01T00:00:00Z", - "Spec": { - "Name": "foo", - "Labels": { - "label1": "label-foo" - } - } - }, - { - "ID": "ID-bar", - "Version": {}, - "CreatedAt": "0001-01-01T00:00:00Z", - "UpdatedAt": "0001-01-01T00:00:00Z", - "Spec": { - "Name": "bar", - "Labels": { - "label1": "label-foo" - } - } - } -] diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden deleted file mode 100644 index c4f41c106..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden +++ /dev/null @@ -1,12 +0,0 @@ -[ - { - "ID": "ID-foo", - "Version": {}, - "CreatedAt": "0001-01-01T00:00:00Z", - "UpdatedAt": "0001-01-01T00:00:00Z", - "Spec": { - "Name": "foo", - "Labels": null - } - } -] diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-config-format.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-config-format.golden deleted file mode 100644 index 11c39229b..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-config-format.golden +++ /dev/null @@ -1,2 +0,0 @@ -foo -bar label=label-bar diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-filter.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-filter.golden deleted file mode 100644 index 01ea6f3ae..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-filter.golden +++ /dev/null @@ -1,3 +0,0 @@ -ID NAME DRIVER CREATED UPDATED -ID-foo foo 2 hours ago About an hour ago -ID-bar bar 2 hours ago About an hour ago diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-format.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-format.golden deleted file mode 100644 index 11c39229b..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-format.golden +++ /dev/null @@ -1,2 +0,0 @@ -foo -bar label=label-bar diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-quiet-option.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-quiet-option.golden deleted file mode 100644 index 83fb6e897..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list-with-quiet-option.golden +++ /dev/null @@ -1,2 +0,0 @@ -ID-foo -ID-bar diff --git a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list.golden b/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list.golden deleted file mode 100644 index d8c204043..000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/testdata/secret-list.golden +++ /dev/null @@ -1,3 +0,0 @@ -ID NAME DRIVER CREATED UPDATED -ID-foo foo 2 hours ago About an hour ago -ID-bar bar driver 2 hours ago About an hour ago diff --git a/vendor/github.com/docker/cli/cli/command/service/client_test.go b/vendor/github.com/docker/cli/cli/command/service/client_test.go deleted file mode 100644 index 69c76951f..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/client_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package service - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" -) - -type fakeClient struct { - client.Client - serviceInspectWithRawFunc func(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) - serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) - serviceListFunc func(context.Context, types.ServiceListOptions) ([]swarm.Service, error) - infoFunc func(ctx context.Context) (types.Info, error) -} - -func (f *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) { - return nil, nil -} - -func (f *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { - return nil, nil -} - -func (f *fakeClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { - if f.serviceInspectWithRawFunc != nil { - return f.serviceInspectWithRawFunc(ctx, serviceID, options) - } - - return *Service(ServiceID(serviceID)), []byte{}, nil -} - -func (f *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - if f.serviceListFunc != nil { - return f.serviceListFunc(ctx, options) - } - - return nil, nil -} - -func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { - if f.serviceUpdateFunc != nil { - return f.serviceUpdateFunc(ctx, serviceID, version, service, options) - } - - return types.ServiceUpdateResponse{}, nil -} - -func (f *fakeClient) Info(ctx context.Context) (types.Info, error) { - if f.infoFunc == nil { - return types.Info{}, nil - } - return f.infoFunc(ctx) -} - -func newService(id string, name string) swarm.Service { - return swarm.Service{ - ID: id, - Spec: swarm.ServiceSpec{Annotations: swarm.Annotations{Name: name}}, - } -} diff --git a/vendor/github.com/docker/cli/cli/command/service/cmd.go b/vendor/github.com/docker/cli/cli/command/service/cmd.go deleted file mode 100644 index 107abf32d..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/cmd.go +++ /dev/null @@ -1,32 +0,0 @@ -package service - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewServiceCommand returns a cobra command for `service` subcommands -// nolint: interfacer -func NewServiceCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "service", - Short: "Manage services", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.24"}, - } - cmd.AddCommand( - newCreateCommand(dockerCli), - newInspectCommand(dockerCli), - newPsCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - newScaleCommand(dockerCli), - newUpdateCommand(dockerCli), - newLogsCommand(dockerCli), - newRollbackCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/service/create.go b/vendor/github.com/docker/cli/cli/command/service/create.go deleted file mode 100644 index 84944fd23..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/create.go +++ /dev/null @@ -1,131 +0,0 @@ -package service - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -func newCreateCommand(dockerCli command.Cli) *cobra.Command { - opts := newServiceOptions() - - cmd := &cobra.Command{ - Use: "create [OPTIONS] IMAGE [COMMAND] [ARG...]", - Short: "Create a new service", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.image = args[0] - if len(args) > 1 { - opts.args = args[1:] - } - return runCreate(dockerCli, cmd.Flags(), opts) - }, - } - flags := cmd.Flags() - flags.StringVar(&opts.mode, flagMode, "replicated", "Service mode (replicated or global)") - flags.StringVar(&opts.name, flagName, "", "Service name") - - addServiceFlags(flags, opts, buildServiceDefaultFlagMapping()) - - flags.VarP(&opts.labels, flagLabel, "l", "Service labels") - flags.Var(&opts.containerLabels, flagContainerLabel, "Container labels") - flags.VarP(&opts.env, flagEnv, "e", "Set environment variables") - flags.Var(&opts.envFile, flagEnvFile, "Read in a file of environment variables") - flags.Var(&opts.mounts, flagMount, "Attach a filesystem mount to the service") - flags.Var(&opts.constraints, flagConstraint, "Placement constraints") - flags.Var(&opts.placementPrefs, flagPlacementPref, "Add a placement preference") - flags.SetAnnotation(flagPlacementPref, "version", []string{"1.28"}) - flags.Var(&opts.networks, flagNetwork, "Network attachments") - flags.Var(&opts.secrets, flagSecret, "Specify secrets to expose to the service") - flags.SetAnnotation(flagSecret, "version", []string{"1.25"}) - flags.Var(&opts.configs, flagConfig, "Specify configurations to expose to the service") - flags.SetAnnotation(flagConfig, "version", []string{"1.30"}) - flags.VarP(&opts.endpoint.publishPorts, flagPublish, "p", "Publish a port as a node port") - flags.Var(&opts.groups, flagGroup, "Set one or more supplementary user groups for the container") - flags.SetAnnotation(flagGroup, "version", []string{"1.25"}) - flags.Var(&opts.dns, flagDNS, "Set custom DNS servers") - flags.SetAnnotation(flagDNS, "version", []string{"1.25"}) - flags.Var(&opts.dnsOption, flagDNSOption, "Set DNS options") - flags.SetAnnotation(flagDNSOption, "version", []string{"1.25"}) - flags.Var(&opts.dnsSearch, flagDNSSearch, "Set custom DNS search domains") - flags.SetAnnotation(flagDNSSearch, "version", []string{"1.25"}) - flags.Var(&opts.hosts, flagHost, "Set one or more custom host-to-IP mappings (host:ip)") - flags.SetAnnotation(flagHost, "version", []string{"1.25"}) - - flags.SetInterspersed(false) - return cmd -} - -func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions) error { - apiClient := dockerCli.Client() - createOpts := types.ServiceCreateOptions{} - - ctx := context.Background() - - service, err := opts.ToService(ctx, apiClient, flags) - if err != nil { - return err - } - - specifiedSecrets := opts.secrets.Value() - if len(specifiedSecrets) > 0 { - // parse and validate secrets - secrets, err := ParseSecrets(apiClient, specifiedSecrets) - if err != nil { - return err - } - service.TaskTemplate.ContainerSpec.Secrets = secrets - } - - specifiedConfigs := opts.configs.Value() - if len(specifiedConfigs) > 0 { - // parse and validate configs - configs, err := ParseConfigs(apiClient, specifiedConfigs) - if err != nil { - return err - } - service.TaskTemplate.ContainerSpec.Configs = configs - } - - if err := resolveServiceImageDigestContentTrust(dockerCli, &service); err != nil { - return err - } - - // only send auth if flag was set - if opts.registryAuth { - // Retrieve encoded auth token from the image reference - encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, opts.image) - if err != nil { - return err - } - createOpts.EncodedRegistryAuth = encodedAuth - } - - // query registry if flag disabling it was not set - if !opts.noResolveImage && versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.30") { - createOpts.QueryRegistry = true - } - - response, err := apiClient.ServiceCreate(ctx, service, createOpts) - if err != nil { - return err - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", response.ID) - - if opts.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") { - return nil - } - - return waitOnService(ctx, dockerCli, response.ID, opts.quiet) -} diff --git a/vendor/github.com/docker/cli/cli/command/service/helpers.go b/vendor/github.com/docker/cli/cli/command/service/helpers.go deleted file mode 100644 index f328c7059..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/helpers.go +++ /dev/null @@ -1,33 +0,0 @@ -package service - -import ( - "io" - "io/ioutil" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/service/progress" - "github.com/docker/docker/pkg/jsonmessage" - "golang.org/x/net/context" -) - -// waitOnService waits for the service to converge. It outputs a progress bar, -// if appropriate based on the CLI flags. -func waitOnService(ctx context.Context, dockerCli command.Cli, serviceID string, quiet bool) error { - errChan := make(chan error, 1) - pipeReader, pipeWriter := io.Pipe() - - go func() { - errChan <- progress.ServiceProgress(ctx, dockerCli.Client(), serviceID, pipeWriter) - }() - - if quiet { - go io.Copy(ioutil.Discard, pipeReader) - return <-errChan - } - - err := jsonmessage.DisplayJSONMessagesToStream(pipeReader, dockerCli.Out(), nil) - if err == nil { - err = <-errChan - } - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/service/inspect.go b/vendor/github.com/docker/cli/cli/command/service/inspect.go deleted file mode 100644 index dbe8ac8dd..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/inspect.go +++ /dev/null @@ -1,94 +0,0 @@ -package service - -import ( - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/docker/api/types" - apiclient "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type inspectOptions struct { - refs []string - format string - pretty bool -} - -func newInspectCommand(dockerCli command.Cli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] SERVICE [SERVICE...]", - Short: "Display detailed information on one or more services", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.refs = args - - if opts.pretty && len(opts.format) > 0 { - return errors.Errorf("--format is incompatible with human friendly format") - } - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - flags.BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(ref string) (interface{}, []byte, error) { - // Service inspect shows defaults values in empty fields. - service, _, err := client.ServiceInspectWithRaw(ctx, ref, types.ServiceInspectOptions{InsertDefaults: true}) - if err == nil || !apiclient.IsErrServiceNotFound(err) { - return service, nil, err - } - return nil, nil, errors.Errorf("Error: no such service: %s", ref) - } - - getNetwork := func(ref string) (interface{}, []byte, error) { - network, _, err := client.NetworkInspectWithRaw(ctx, ref, types.NetworkInspectOptions{Scope: "swarm"}) - if err == nil || !apiclient.IsErrNetworkNotFound(err) { - return network, nil, err - } - return nil, nil, errors.Errorf("Error: no such network: %s", ref) - } - - f := opts.format - if len(f) == 0 { - f = "raw" - if len(dockerCli.ConfigFile().ServiceInspectFormat) > 0 { - f = dockerCli.ConfigFile().ServiceInspectFormat - } - } - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return errors.Errorf("Cannot supply extra formatting options to the pretty template") - } - - serviceCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewServiceFormat(f), - } - - if err := formatter.ServiceInspectWrite(serviceCtx, opts.refs, getRef, getNetwork); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/inspect_test.go b/vendor/github.com/docker/cli/cli/command/service/inspect_test.go deleted file mode 100644 index d46419720..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/inspect_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package service - -import ( - "bytes" - "encoding/json" - "strings" - "testing" - "time" - - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" -) - -func formatServiceInspect(t *testing.T, format formatter.Format, now time.Time) string { - b := new(bytes.Buffer) - - endpointSpec := &swarm.EndpointSpec{ - Mode: "vip", - Ports: []swarm.PortConfig{ - { - Protocol: swarm.PortConfigProtocolTCP, - TargetPort: 5000, - }, - }, - } - - two := uint64(2) - - s := swarm.Service{ - ID: "de179gar9d0o7ltdybungplod", - Meta: swarm.Meta{ - Version: swarm.Version{Index: 315}, - CreatedAt: now, - UpdatedAt: now, - }, - Spec: swarm.ServiceSpec{ - Annotations: swarm.Annotations{ - Name: "my_service", - Labels: map[string]string{"com.label": "foo"}, - }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{ - Image: "foo/bar@sha256:this_is_a_test", - }, - Networks: []swarm.NetworkAttachmentConfig{ - { - Target: "5vpyomhb6ievnk0i0o60gcnei", - Aliases: []string{"web"}, - }, - }, - }, - Mode: swarm.ServiceMode{ - Replicated: &swarm.ReplicatedService{ - Replicas: &two, - }, - }, - EndpointSpec: endpointSpec, - }, - Endpoint: swarm.Endpoint{ - Spec: *endpointSpec, - Ports: []swarm.PortConfig{ - { - Protocol: swarm.PortConfigProtocolTCP, - TargetPort: 5000, - PublishedPort: 30000, - }, - }, - VirtualIPs: []swarm.EndpointVirtualIP{ - { - NetworkID: "6o4107cj2jx9tihgb0jyts6pj", - Addr: "10.255.0.4/16", - }, - }, - }, - UpdateStatus: &swarm.UpdateStatus{ - StartedAt: &now, - CompletedAt: &now, - }, - } - - ctx := formatter.Context{ - Output: b, - Format: format, - } - - err := formatter.ServiceInspectWrite(ctx, []string{"de179gar9d0o7ltdybungplod"}, - func(ref string) (interface{}, []byte, error) { - return s, nil, nil - }, - func(ref string) (interface{}, []byte, error) { - return types.NetworkResource{ - ID: "5vpyomhb6ievnk0i0o60gcnei", - Name: "mynetwork", - }, nil, nil - }, - ) - if err != nil { - t.Fatal(err) - } - return b.String() -} - -func TestPrettyPrintWithNoUpdateConfig(t *testing.T) { - s := formatServiceInspect(t, formatter.NewServiceFormat("pretty"), time.Now()) - if strings.Contains(s, "UpdateStatus") { - t.Fatal("Pretty print failed before parsing UpdateStatus") - } - if !strings.Contains(s, "mynetwork") { - t.Fatal("network name not found in inspect output") - } -} - -func TestJSONFormatWithNoUpdateConfig(t *testing.T) { - now := time.Now() - // s1: [{"ID":..}] - // s2: {"ID":..} - s1 := formatServiceInspect(t, formatter.NewServiceFormat(""), now) - s2 := formatServiceInspect(t, formatter.NewServiceFormat("{{json .}}"), now) - var m1Wrap []map[string]interface{} - if err := json.Unmarshal([]byte(s1), &m1Wrap); err != nil { - t.Fatal(err) - } - if len(m1Wrap) != 1 { - t.Fatalf("strange s1=%s", s1) - } - m1 := m1Wrap[0] - var m2 map[string]interface{} - if err := json.Unmarshal([]byte(s2), &m2); err != nil { - t.Fatal(err) - } - assert.Equal(t, m1, m2) -} diff --git a/vendor/github.com/docker/cli/cli/command/service/list.go b/vendor/github.com/docker/cli/cli/command/service/list.go deleted file mode 100644 index 63adce1ec..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/list.go +++ /dev/null @@ -1,139 +0,0 @@ -package service - -import ( - "fmt" - "sort" - - "vbom.ml/util/sortorder" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List services", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print services using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -type byName []swarm.Service - -func (n byName) Len() int { return len(n) } -func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] } -func (n byName) Less(i, j int) bool { return sortorder.NaturalLess(n[i].Spec.Name, n[j].Spec.Name) } - -func runList(dockerCli command.Cli, options listOptions) error { - ctx := context.Background() - client := dockerCli.Client() - - serviceFilters := options.filter.Value() - services, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceFilters}) - if err != nil { - return err - } - - sort.Sort(byName(services)) - info := map[string]formatter.ServiceListInfo{} - if len(services) > 0 && !options.quiet { - // only non-empty services and not quiet, should we call TaskList and NodeList api - taskFilter := filters.NewArgs() - for _, service := range services { - taskFilter.Add("service", service.ID) - } - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter}) - if err != nil { - return err - } - - nodes, err := client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return err - } - - info = GetServicesStatus(services, nodes, tasks) - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().ServicesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().ServicesFormat - } else { - format = formatter.TableFormatKey - } - } - - servicesCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewServiceListFormat(format, options.quiet), - } - return formatter.ServiceListWrite(servicesCtx, services, info) -} - -// GetServicesStatus returns a map of mode and replicas -func GetServicesStatus(services []swarm.Service, nodes []swarm.Node, tasks []swarm.Task) map[string]formatter.ServiceListInfo { - running := map[string]int{} - tasksNoShutdown := map[string]int{} - - activeNodes := make(map[string]struct{}) - for _, n := range nodes { - if n.Status.State != swarm.NodeStateDown { - activeNodes[n.ID] = struct{}{} - } - } - - for _, task := range tasks { - if task.DesiredState != swarm.TaskStateShutdown { - tasksNoShutdown[task.ServiceID]++ - } - - if _, nodeActive := activeNodes[task.NodeID]; nodeActive && task.Status.State == swarm.TaskStateRunning { - running[task.ServiceID]++ - } - } - - info := map[string]formatter.ServiceListInfo{} - for _, service := range services { - info[service.ID] = formatter.ServiceListInfo{} - if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil { - info[service.ID] = formatter.ServiceListInfo{ - Mode: "replicated", - Replicas: fmt.Sprintf("%d/%d", running[service.ID], *service.Spec.Mode.Replicated.Replicas), - } - } else if service.Spec.Mode.Global != nil { - info[service.ID] = formatter.ServiceListInfo{ - Mode: "global", - Replicas: fmt.Sprintf("%d/%d", running[service.ID], tasksNoShutdown[service.ID]), - } - } - } - return info -} diff --git a/vendor/github.com/docker/cli/cli/command/service/list_test.go b/vendor/github.com/docker/cli/cli/command/service/list_test.go deleted file mode 100644 index 679c73370..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/list_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package service - -import ( - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestServiceListOrder(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - newService("a57dbe8", "service-1-foo"), - newService("a57dbdd", "service-10-foo"), - newService("aaaaaaa", "service-2-foo"), - }, nil - }, - }) - cmd := newListCommand(cli) - cmd.Flags().Set("format", "{{.Name}}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "service-list-sort.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/service/logs.go b/vendor/github.com/docker/cli/cli/command/service/logs.go deleted file mode 100644 index 0482a8794..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/logs.go +++ /dev/null @@ -1,350 +0,0 @@ -package service - -import ( - "bytes" - "fmt" - "io" - "sort" - "strconv" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/service/logs" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/docker/pkg/stringid" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type logsOptions struct { - noResolve bool - noTrunc bool - noTaskIDs bool - follow bool - since string - timestamps bool - tail string - details bool - raw bool - - target string -} - -func newLogsCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts logsOptions - - cmd := &cobra.Command{ - Use: "logs [OPTIONS] SERVICE|TASK", - Short: "Fetch the logs of a service or task", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.target = args[0] - return runLogs(dockerCli, &opts) - }, - Tags: map[string]string{"version": "1.29"}, - } - - flags := cmd.Flags() - // options specific to service logs - flags.BoolVar(&opts.noResolve, "no-resolve", false, "Do not map IDs to Names in output") - flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&opts.raw, "raw", false, "Do not neatly format logs") - flags.SetAnnotation("raw", "version", []string{"1.30"}) - flags.BoolVar(&opts.noTaskIDs, "no-task-ids", false, "Do not include task IDs in output") - // options identical to container logs - flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output") - flags.StringVar(&opts.since, "since", "", "Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)") - flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps") - flags.BoolVar(&opts.details, "details", false, "Show extra details provided to logs") - flags.SetAnnotation("details", "version", []string{"1.30"}) - flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs") - return cmd -} - -func runLogs(dockerCli *command.DockerCli, opts *logsOptions) error { - ctx := context.Background() - - options := types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Since: opts.since, - Timestamps: opts.timestamps, - Follow: opts.follow, - Tail: opts.tail, - // get the details if we request it OR if we're not doing raw mode - // (we need them for the context to pretty print) - Details: opts.details || !opts.raw, - } - - cli := dockerCli.Client() - - var ( - maxLength = 1 - responseBody io.ReadCloser - tty bool - // logfunc is used to delay the call to logs so that we can do some - // processing before we actually get the logs - logfunc func(context.Context, string, types.ContainerLogsOptions) (io.ReadCloser, error) - ) - - service, _, err := cli.ServiceInspectWithRaw(ctx, opts.target, types.ServiceInspectOptions{}) - if err != nil { - // if it's any error other than service not found, it's Real - if !client.IsErrServiceNotFound(err) { - return err - } - task, _, err := cli.TaskInspectWithRaw(ctx, opts.target) - if err != nil { - if client.IsErrTaskNotFound(err) { - // if the task isn't found, rewrite the error to be clear - // that we looked for services AND tasks and found none - err = fmt.Errorf("no such task or service: %v", opts.target) - } - return err - } - - tty = task.Spec.ContainerSpec.TTY - maxLength = getMaxLength(task.Slot) - - // use the TaskLogs api function - logfunc = cli.TaskLogs - } else { - // use ServiceLogs api function - logfunc = cli.ServiceLogs - tty = service.Spec.TaskTemplate.ContainerSpec.TTY - if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil { - // if replicas are initialized, figure out if we need to pad them - replicas := *service.Spec.Mode.Replicated.Replicas - maxLength = getMaxLength(int(replicas)) - } - } - - // we can't prettify tty logs. tell the user that this is the case. - // this is why we assign the logs function to a variable and delay calling - // it. we want to check this before we make the call and checking twice in - // each branch is even sloppier than this CLI disaster already is - if tty && !opts.raw { - return errors.New("tty service logs only supported with --raw") - } - - // now get the logs - responseBody, err = logfunc(ctx, opts.target, options) - if err != nil { - return err - } - defer responseBody.Close() - - // tty logs get straight copied. they're not muxed with stdcopy - if tty { - _, err = io.Copy(dockerCli.Out(), responseBody) - return err - } - - // otherwise, logs are multiplexed. if we're doing pretty printing, also - // create a task formatter. - var stdout, stderr io.Writer - stdout = dockerCli.Out() - stderr = dockerCli.Err() - if !opts.raw { - taskFormatter := newTaskFormatter(cli, opts, maxLength) - - stdout = &logWriter{ctx: ctx, opts: opts, f: taskFormatter, w: stdout} - stderr = &logWriter{ctx: ctx, opts: opts, f: taskFormatter, w: stderr} - } - - _, err = stdcopy.StdCopy(stdout, stderr, responseBody) - return err -} - -// getMaxLength gets the maximum length of the number in base 10 -func getMaxLength(i int) int { - return len(strconv.Itoa(i)) -} - -type taskFormatter struct { - client client.APIClient - opts *logsOptions - padding int - - r *idresolver.IDResolver - // cache saves a pre-cooked logContext formatted string based on a - // logcontext object, so we don't have to resolve names every time - cache map[logContext]string -} - -func newTaskFormatter(client client.APIClient, opts *logsOptions, padding int) *taskFormatter { - return &taskFormatter{ - client: client, - opts: opts, - padding: padding, - r: idresolver.New(client, opts.noResolve), - cache: make(map[logContext]string), - } -} - -func (f *taskFormatter) format(ctx context.Context, logCtx logContext) (string, error) { - if cached, ok := f.cache[logCtx]; ok { - return cached, nil - } - - nodeName, err := f.r.Resolve(ctx, swarm.Node{}, logCtx.nodeID) - if err != nil { - return "", err - } - - serviceName, err := f.r.Resolve(ctx, swarm.Service{}, logCtx.serviceID) - if err != nil { - return "", err - } - - task, _, err := f.client.TaskInspectWithRaw(ctx, logCtx.taskID) - if err != nil { - return "", err - } - - taskName := fmt.Sprintf("%s.%d", serviceName, task.Slot) - if !f.opts.noTaskIDs { - if f.opts.noTrunc { - taskName += fmt.Sprintf(".%s", task.ID) - } else { - taskName += fmt.Sprintf(".%s", stringid.TruncateID(task.ID)) - } - } - - paddingCount := f.padding - getMaxLength(task.Slot) - padding := "" - if paddingCount > 0 { - padding = strings.Repeat(" ", paddingCount) - } - formatted := taskName + "@" + nodeName + padding - f.cache[logCtx] = formatted - return formatted, nil -} - -type logWriter struct { - ctx context.Context - opts *logsOptions - f *taskFormatter - w io.Writer -} - -func (lw *logWriter) Write(buf []byte) (int, error) { - // this works but ONLY because stdcopy calls write a whole line at a time. - // if this ends up horribly broken or panics, check to see if stdcopy has - // reneged on that assumption. (@god forgive me) - // also this only works because the logs format is, like, barely parsable. - // if something changes in the logs format, this is gonna break - - // there should always be at least 2 parts: details and message. if there - // is no timestamp, details will be first (index 0) when we split on - // spaces. if there is a timestamp, details will be 2nd (`index 1) - detailsIndex := 0 - numParts := 2 - if lw.opts.timestamps { - detailsIndex++ - numParts++ - } - - // break up the log line into parts. - parts := bytes.SplitN(buf, []byte(" "), numParts) - if len(parts) != numParts { - return 0, errors.Errorf("invalid context in log message: %v", string(buf)) - } - // parse the details out - details, err := logs.ParseLogDetails(string(parts[detailsIndex])) - if err != nil { - return 0, err - } - // and then create a context from the details - // this removes the context-specific details from the details map, so we - // can more easily print the details later - logCtx, err := lw.parseContext(details) - if err != nil { - return 0, err - } - - output := []byte{} - // if we included timestamps, add them to the front - if lw.opts.timestamps { - output = append(output, parts[0]...) - output = append(output, ' ') - } - // add the context, nice and formatted - formatted, err := lw.f.format(lw.ctx, logCtx) - if err != nil { - return 0, err - } - output = append(output, []byte(formatted+" | ")...) - // if the user asked for details, add them to be log message - if lw.opts.details { - // ugh i hate this it's basically a dupe of api/server/httputils/write_log_stream.go:stringAttrs() - // ok but we're gonna do it a bit different - - // there are optimizations that can be made here. for starters, i'd - // suggest caching the details keys. then, we can maybe draw maps and - // slices from a pool to avoid alloc overhead on them. idk if it's - // worth the time yet. - - // first we need a slice - d := make([]string, 0, len(details)) - // then let's add all the pairs - for k := range details { - d = append(d, k+"="+details[k]) - } - // then sort em - sort.Strings(d) - // then join and append - output = append(output, []byte(strings.Join(d, ","))...) - output = append(output, ' ') - } - - // add the log message itself, finally - output = append(output, parts[detailsIndex+1]...) - - _, err = lw.w.Write(output) - if err != nil { - return 0, err - } - - return len(buf), nil -} - -// parseContext returns a log context and REMOVES the context from the details map -func (lw *logWriter) parseContext(details map[string]string) (logContext, error) { - nodeID, ok := details["com.docker.swarm.node.id"] - if !ok { - return logContext{}, errors.Errorf("missing node id in details: %v", details) - } - delete(details, "com.docker.swarm.node.id") - - serviceID, ok := details["com.docker.swarm.service.id"] - if !ok { - return logContext{}, errors.Errorf("missing service id in details: %v", details) - } - delete(details, "com.docker.swarm.service.id") - - taskID, ok := details["com.docker.swarm.task.id"] - if !ok { - return logContext{}, errors.Errorf("missing task id in details: %s", details) - } - delete(details, "com.docker.swarm.task.id") - - return logContext{ - nodeID: nodeID, - serviceID: serviceID, - taskID: taskID, - }, nil -} - -type logContext struct { - nodeID string - serviceID string - taskID string -} diff --git a/vendor/github.com/docker/cli/cli/command/service/opts.go b/vendor/github.com/docker/cli/cli/command/service/opts.go deleted file mode 100644 index 37369f595..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/opts.go +++ /dev/null @@ -1,882 +0,0 @@ -package service - -import ( - "fmt" - "sort" - "strconv" - "strings" - "time" - - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/swarmkit/api" - "github.com/docker/swarmkit/api/defaults" - shlex "github.com/flynn-archive/go-shlex" - gogotypes "github.com/gogo/protobuf/types" - "github.com/pkg/errors" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -type int64Value interface { - Value() int64 -} - -// Uint64Opt represents a uint64. -type Uint64Opt struct { - value *uint64 -} - -// Set a new value on the option -func (i *Uint64Opt) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 64) - i.value = &v - return err -} - -// Type returns the type of this option, which will be displayed in `--help` output -func (i *Uint64Opt) Type() string { - return "uint" -} - -// String returns a string repr of this option -func (i *Uint64Opt) String() string { - if i.value != nil { - return fmt.Sprintf("%v", *i.value) - } - return "" -} - -// Value returns the uint64 -func (i *Uint64Opt) Value() *uint64 { - return i.value -} - -type floatValue float32 - -func (f *floatValue) Set(s string) error { - v, err := strconv.ParseFloat(s, 32) - *f = floatValue(v) - return err -} - -func (f *floatValue) Type() string { - return "float" -} - -func (f *floatValue) String() string { - return strconv.FormatFloat(float64(*f), 'g', -1, 32) -} - -func (f *floatValue) Value() float32 { - return float32(*f) -} - -// placementPrefOpts holds a list of placement preferences. -type placementPrefOpts struct { - prefs []swarm.PlacementPreference - strings []string -} - -func (opts *placementPrefOpts) String() string { - if len(opts.strings) == 0 { - return "" - } - return fmt.Sprintf("%v", opts.strings) -} - -// Set validates the input value and adds it to the internal slices. -// Note: in the future strategies other than "spread", may be supported, -// as well as additional comma-separated options. -func (opts *placementPrefOpts) Set(value string) error { - fields := strings.Split(value, "=") - if len(fields) != 2 { - return errors.New(`placement preference must be of the format "="`) - } - if fields[0] != "spread" { - return errors.Errorf("unsupported placement preference %s (only spread is supported)", fields[0]) - } - - opts.prefs = append(opts.prefs, swarm.PlacementPreference{ - Spread: &swarm.SpreadOver{ - SpreadDescriptor: fields[1], - }, - }) - opts.strings = append(opts.strings, value) - return nil -} - -// Type returns a string name for this Option type -func (opts *placementPrefOpts) Type() string { - return "pref" -} - -// ShlexOpt is a flag Value which parses a string as a list of shell words -type ShlexOpt []string - -// Set the value -func (s *ShlexOpt) Set(value string) error { - valueSlice, err := shlex.Split(value) - *s = ShlexOpt(valueSlice) - return err -} - -// Type returns the tyep of the value -func (s *ShlexOpt) Type() string { - return "command" -} - -func (s *ShlexOpt) String() string { - if len(*s) == 0 { - return "" - } - return fmt.Sprint(*s) -} - -// Value returns the value as a string slice -func (s *ShlexOpt) Value() []string { - return []string(*s) -} - -type updateOptions struct { - parallelism uint64 - delay time.Duration - monitor time.Duration - onFailure string - maxFailureRatio floatValue - order string -} - -func updateConfigFromDefaults(defaultUpdateConfig *api.UpdateConfig) *swarm.UpdateConfig { - defaultFailureAction := strings.ToLower(api.UpdateConfig_FailureAction_name[int32(defaultUpdateConfig.FailureAction)]) - defaultMonitor, _ := gogotypes.DurationFromProto(defaultUpdateConfig.Monitor) - return &swarm.UpdateConfig{ - Parallelism: defaultUpdateConfig.Parallelism, - Delay: defaultUpdateConfig.Delay, - Monitor: defaultMonitor, - FailureAction: defaultFailureAction, - MaxFailureRatio: defaultUpdateConfig.MaxFailureRatio, - Order: defaultOrder(defaultUpdateConfig.Order), - } -} - -func (opts updateOptions) updateConfig(flags *pflag.FlagSet) *swarm.UpdateConfig { - if !anyChanged(flags, flagUpdateParallelism, flagUpdateDelay, flagUpdateMonitor, flagUpdateFailureAction, flagUpdateMaxFailureRatio) { - return nil - } - - updateConfig := updateConfigFromDefaults(defaults.Service.Update) - - if flags.Changed(flagUpdateParallelism) { - updateConfig.Parallelism = opts.parallelism - } - if flags.Changed(flagUpdateDelay) { - updateConfig.Delay = opts.delay - } - if flags.Changed(flagUpdateMonitor) { - updateConfig.Monitor = opts.monitor - } - if flags.Changed(flagUpdateFailureAction) { - updateConfig.FailureAction = opts.onFailure - } - if flags.Changed(flagUpdateMaxFailureRatio) { - updateConfig.MaxFailureRatio = opts.maxFailureRatio.Value() - } - if flags.Changed(flagUpdateOrder) { - updateConfig.Order = opts.order - } - - return updateConfig -} - -func (opts updateOptions) rollbackConfig(flags *pflag.FlagSet) *swarm.UpdateConfig { - if !anyChanged(flags, flagRollbackParallelism, flagRollbackDelay, flagRollbackMonitor, flagRollbackFailureAction, flagRollbackMaxFailureRatio) { - return nil - } - - updateConfig := updateConfigFromDefaults(defaults.Service.Rollback) - - if flags.Changed(flagRollbackParallelism) { - updateConfig.Parallelism = opts.parallelism - } - if flags.Changed(flagRollbackDelay) { - updateConfig.Delay = opts.delay - } - if flags.Changed(flagRollbackMonitor) { - updateConfig.Monitor = opts.monitor - } - if flags.Changed(flagRollbackFailureAction) { - updateConfig.FailureAction = opts.onFailure - } - if flags.Changed(flagRollbackMaxFailureRatio) { - updateConfig.MaxFailureRatio = opts.maxFailureRatio.Value() - } - if flags.Changed(flagRollbackOrder) { - updateConfig.Order = opts.order - } - - return updateConfig -} - -type resourceOptions struct { - limitCPU opts.NanoCPUs - limitMemBytes opts.MemBytes - resCPU opts.NanoCPUs - resMemBytes opts.MemBytes -} - -func (r *resourceOptions) ToResourceRequirements() *swarm.ResourceRequirements { - return &swarm.ResourceRequirements{ - Limits: &swarm.Resources{ - NanoCPUs: r.limitCPU.Value(), - MemoryBytes: r.limitMemBytes.Value(), - }, - Reservations: &swarm.Resources{ - NanoCPUs: r.resCPU.Value(), - MemoryBytes: r.resMemBytes.Value(), - }, - } -} - -type restartPolicyOptions struct { - condition string - delay opts.DurationOpt - maxAttempts Uint64Opt - window opts.DurationOpt -} - -func defaultRestartPolicy() *swarm.RestartPolicy { - defaultMaxAttempts := defaults.Service.Task.Restart.MaxAttempts - rp := &swarm.RestartPolicy{ - MaxAttempts: &defaultMaxAttempts, - } - - if defaults.Service.Task.Restart.Delay != nil { - defaultRestartDelay, _ := gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay) - rp.Delay = &defaultRestartDelay - } - if defaults.Service.Task.Restart.Window != nil { - defaultRestartWindow, _ := gogotypes.DurationFromProto(defaults.Service.Task.Restart.Window) - rp.Window = &defaultRestartWindow - } - rp.Condition = defaultRestartCondition() - - return rp -} - -func defaultRestartCondition() swarm.RestartPolicyCondition { - switch defaults.Service.Task.Restart.Condition { - case api.RestartOnNone: - return "none" - case api.RestartOnFailure: - return "on-failure" - case api.RestartOnAny: - return "any" - default: - return "" - } -} - -func defaultOrder(order api.UpdateConfig_UpdateOrder) string { - switch order { - case api.UpdateConfig_STOP_FIRST: - return "stop-first" - case api.UpdateConfig_START_FIRST: - return "start-first" - default: - return "" - } -} - -func (r *restartPolicyOptions) ToRestartPolicy(flags *pflag.FlagSet) *swarm.RestartPolicy { - if !anyChanged(flags, flagRestartDelay, flagRestartMaxAttempts, flagRestartWindow, flagRestartCondition) { - return nil - } - - restartPolicy := defaultRestartPolicy() - - if flags.Changed(flagRestartDelay) { - restartPolicy.Delay = r.delay.Value() - } - if flags.Changed(flagRestartCondition) { - restartPolicy.Condition = swarm.RestartPolicyCondition(r.condition) - } - if flags.Changed(flagRestartMaxAttempts) { - restartPolicy.MaxAttempts = r.maxAttempts.Value() - } - if flags.Changed(flagRestartWindow) { - restartPolicy.Window = r.window.Value() - } - - return restartPolicy -} - -type credentialSpecOpt struct { - value *swarm.CredentialSpec - source string -} - -func (c *credentialSpecOpt) Set(value string) error { - c.source = value - c.value = &swarm.CredentialSpec{} - switch { - case strings.HasPrefix(value, "file://"): - c.value.File = strings.TrimPrefix(value, "file://") - case strings.HasPrefix(value, "registry://"): - c.value.Registry = strings.TrimPrefix(value, "registry://") - default: - return errors.New("Invalid credential spec - value must be prefixed file:// or registry:// followed by a value") - } - - return nil -} - -func (c *credentialSpecOpt) Type() string { - return "credential-spec" -} - -func (c *credentialSpecOpt) String() string { - return c.source -} - -func (c *credentialSpecOpt) Value() *swarm.CredentialSpec { - return c.value -} - -func convertNetworks(ctx context.Context, apiClient client.NetworkAPIClient, networks opts.NetworkOpt) ([]swarm.NetworkAttachmentConfig, error) { - var netAttach []swarm.NetworkAttachmentConfig - for _, net := range networks.Value() { - networkIDOrName := net.Target - _, err := apiClient.NetworkInspect(ctx, networkIDOrName, types.NetworkInspectOptions{Scope: "swarm"}) - if err != nil { - return nil, err - } - netAttach = append(netAttach, swarm.NetworkAttachmentConfig{ // nolint: gosimple - Target: net.Target, - Aliases: net.Aliases, - DriverOpts: net.DriverOpts, - }) - } - sort.Sort(byNetworkTarget(netAttach)) - return netAttach, nil -} - -type endpointOptions struct { - mode string - publishPorts opts.PortOpt -} - -func (e *endpointOptions) ToEndpointSpec() *swarm.EndpointSpec { - return &swarm.EndpointSpec{ - Mode: swarm.ResolutionMode(strings.ToLower(e.mode)), - Ports: e.publishPorts.Value(), - } -} - -type logDriverOptions struct { - name string - opts opts.ListOpts -} - -func newLogDriverOptions() logDriverOptions { - return logDriverOptions{opts: opts.NewListOpts(opts.ValidateEnv)} -} - -func (ldo *logDriverOptions) toLogDriver() *swarm.Driver { - if ldo.name == "" { - return nil - } - - // set the log driver only if specified. - return &swarm.Driver{ - Name: ldo.name, - Options: opts.ConvertKVStringsToMap(ldo.opts.GetAll()), - } -} - -type healthCheckOptions struct { - cmd string - interval opts.PositiveDurationOpt - timeout opts.PositiveDurationOpt - retries int - startPeriod opts.PositiveDurationOpt - noHealthcheck bool -} - -func (opts *healthCheckOptions) toHealthConfig() (*container.HealthConfig, error) { - var healthConfig *container.HealthConfig - haveHealthSettings := opts.cmd != "" || - opts.interval.Value() != nil || - opts.timeout.Value() != nil || - opts.retries != 0 - if opts.noHealthcheck { - if haveHealthSettings { - return nil, errors.Errorf("--%s conflicts with --health-* options", flagNoHealthcheck) - } - healthConfig = &container.HealthConfig{Test: []string{"NONE"}} - } else if haveHealthSettings { - var test []string - if opts.cmd != "" { - test = []string{"CMD-SHELL", opts.cmd} - } - var interval, timeout, startPeriod time.Duration - if ptr := opts.interval.Value(); ptr != nil { - interval = *ptr - } - if ptr := opts.timeout.Value(); ptr != nil { - timeout = *ptr - } - if ptr := opts.startPeriod.Value(); ptr != nil { - startPeriod = *ptr - } - healthConfig = &container.HealthConfig{ - Test: test, - Interval: interval, - Timeout: timeout, - Retries: opts.retries, - StartPeriod: startPeriod, - } - } - return healthConfig, nil -} - -// convertExtraHostsToSwarmHosts converts an array of extra hosts in cli -// : -// into a swarmkit host format: -// IP_address canonical_hostname [aliases...] -// This assumes input value (:) has already been validated -func convertExtraHostsToSwarmHosts(extraHosts []string) []string { - hosts := []string{} - for _, extraHost := range extraHosts { - parts := strings.SplitN(extraHost, ":", 2) - hosts = append(hosts, fmt.Sprintf("%s %s", parts[1], parts[0])) - } - return hosts -} - -type serviceOptions struct { - detach bool - quiet bool - - name string - labels opts.ListOpts - containerLabels opts.ListOpts - image string - entrypoint ShlexOpt - args []string - hostname string - env opts.ListOpts - envFile opts.ListOpts - workdir string - user string - groups opts.ListOpts - credentialSpec credentialSpecOpt - stopSignal string - tty bool - readOnly bool - mounts opts.MountOpt - dns opts.ListOpts - dnsSearch opts.ListOpts - dnsOption opts.ListOpts - hosts opts.ListOpts - - resources resourceOptions - stopGrace opts.DurationOpt - - replicas Uint64Opt - mode string - - restartPolicy restartPolicyOptions - constraints opts.ListOpts - placementPrefs placementPrefOpts - update updateOptions - rollback updateOptions - networks opts.NetworkOpt - endpoint endpointOptions - - registryAuth bool - noResolveImage bool - - logDriver logDriverOptions - - healthcheck healthCheckOptions - secrets opts.SecretOpt - configs opts.ConfigOpt -} - -func newServiceOptions() *serviceOptions { - return &serviceOptions{ - labels: opts.NewListOpts(opts.ValidateEnv), - constraints: opts.NewListOpts(nil), - containerLabels: opts.NewListOpts(opts.ValidateEnv), - env: opts.NewListOpts(opts.ValidateEnv), - envFile: opts.NewListOpts(nil), - groups: opts.NewListOpts(nil), - logDriver: newLogDriverOptions(), - dns: opts.NewListOpts(opts.ValidateIPAddress), - dnsOption: opts.NewListOpts(nil), - dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch), - hosts: opts.NewListOpts(opts.ValidateExtraHost), - } -} - -func (options *serviceOptions) ToServiceMode() (swarm.ServiceMode, error) { - serviceMode := swarm.ServiceMode{} - switch options.mode { - case "global": - if options.replicas.Value() != nil { - return serviceMode, errors.Errorf("replicas can only be used with replicated mode") - } - - serviceMode.Global = &swarm.GlobalService{} - case "replicated": - serviceMode.Replicated = &swarm.ReplicatedService{ - Replicas: options.replicas.Value(), - } - default: - return serviceMode, errors.Errorf("Unknown mode: %s, only replicated and global supported", options.mode) - } - return serviceMode, nil -} - -func (options *serviceOptions) ToStopGracePeriod(flags *pflag.FlagSet) *time.Duration { - if flags.Changed(flagStopGracePeriod) { - return options.stopGrace.Value() - } - return nil -} - -func (options *serviceOptions) ToService(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet) (swarm.ServiceSpec, error) { - var service swarm.ServiceSpec - - envVariables, err := opts.ReadKVStrings(options.envFile.GetAll(), options.env.GetAll()) - if err != nil { - return service, err - } - - currentEnv := make([]string, 0, len(envVariables)) - for _, env := range envVariables { // need to process each var, in order - k := strings.SplitN(env, "=", 2)[0] - for i, current := range currentEnv { // remove duplicates - if current == env { - continue // no update required, may hide this behind flag to preserve order of envVariables - } - if strings.HasPrefix(current, k+"=") { - currentEnv = append(currentEnv[:i], currentEnv[i+1:]...) - } - } - currentEnv = append(currentEnv, env) - } - - healthConfig, err := options.healthcheck.toHealthConfig() - if err != nil { - return service, err - } - - serviceMode, err := options.ToServiceMode() - if err != nil { - return service, err - } - - networks, err := convertNetworks(ctx, apiClient, options.networks) - if err != nil { - return service, err - } - - service = swarm.ServiceSpec{ - Annotations: swarm.Annotations{ - Name: options.name, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{ - Image: options.image, - Args: options.args, - Command: options.entrypoint.Value(), - Env: currentEnv, - Hostname: options.hostname, - Labels: opts.ConvertKVStringsToMap(options.containerLabels.GetAll()), - Dir: options.workdir, - User: options.user, - Groups: options.groups.GetAll(), - StopSignal: options.stopSignal, - TTY: options.tty, - ReadOnly: options.readOnly, - Mounts: options.mounts.Value(), - DNSConfig: &swarm.DNSConfig{ - Nameservers: options.dns.GetAll(), - Search: options.dnsSearch.GetAll(), - Options: options.dnsOption.GetAll(), - }, - Hosts: convertExtraHostsToSwarmHosts(options.hosts.GetAll()), - StopGracePeriod: options.ToStopGracePeriod(flags), - Healthcheck: healthConfig, - }, - Networks: networks, - Resources: options.resources.ToResourceRequirements(), - RestartPolicy: options.restartPolicy.ToRestartPolicy(flags), - Placement: &swarm.Placement{ - Constraints: options.constraints.GetAll(), - Preferences: options.placementPrefs.prefs, - }, - LogDriver: options.logDriver.toLogDriver(), - }, - Mode: serviceMode, - UpdateConfig: options.update.updateConfig(flags), - RollbackConfig: options.update.rollbackConfig(flags), - EndpointSpec: options.endpoint.ToEndpointSpec(), - } - - if options.credentialSpec.Value() != nil { - service.TaskTemplate.ContainerSpec.Privileges = &swarm.Privileges{ - CredentialSpec: options.credentialSpec.Value(), - } - } - - return service, nil -} - -type flagDefaults map[string]interface{} - -func (fd flagDefaults) getUint64(flagName string) uint64 { - if val, ok := fd[flagName].(uint64); ok { - return val - } - return 0 -} - -func (fd flagDefaults) getString(flagName string) string { - if val, ok := fd[flagName].(string); ok { - return val - } - return "" -} - -func buildServiceDefaultFlagMapping() flagDefaults { - defaultFlagValues := make(map[string]interface{}) - - defaultFlagValues[flagStopGracePeriod], _ = gogotypes.DurationFromProto(defaults.Service.Task.GetContainer().StopGracePeriod) - defaultFlagValues[flagRestartCondition] = `"` + defaultRestartCondition() + `"` - defaultFlagValues[flagRestartDelay], _ = gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay) - - if defaults.Service.Task.Restart.MaxAttempts != 0 { - defaultFlagValues[flagRestartMaxAttempts] = defaults.Service.Task.Restart.MaxAttempts - } - - defaultRestartWindow, _ := gogotypes.DurationFromProto(defaults.Service.Task.Restart.Window) - if defaultRestartWindow != 0 { - defaultFlagValues[flagRestartWindow] = defaultRestartWindow - } - - defaultFlagValues[flagUpdateParallelism] = defaults.Service.Update.Parallelism - defaultFlagValues[flagUpdateDelay] = defaults.Service.Update.Delay - defaultFlagValues[flagUpdateMonitor], _ = gogotypes.DurationFromProto(defaults.Service.Update.Monitor) - defaultFlagValues[flagUpdateFailureAction] = `"` + strings.ToLower(api.UpdateConfig_FailureAction_name[int32(defaults.Service.Update.FailureAction)]) + `"` - defaultFlagValues[flagUpdateMaxFailureRatio] = defaults.Service.Update.MaxFailureRatio - defaultFlagValues[flagUpdateOrder] = `"` + defaultOrder(defaults.Service.Update.Order) + `"` - - defaultFlagValues[flagRollbackParallelism] = defaults.Service.Rollback.Parallelism - defaultFlagValues[flagRollbackDelay] = defaults.Service.Rollback.Delay - defaultFlagValues[flagRollbackMonitor], _ = gogotypes.DurationFromProto(defaults.Service.Rollback.Monitor) - defaultFlagValues[flagRollbackFailureAction] = `"` + strings.ToLower(api.UpdateConfig_FailureAction_name[int32(defaults.Service.Rollback.FailureAction)]) + `"` - defaultFlagValues[flagRollbackMaxFailureRatio] = defaults.Service.Rollback.MaxFailureRatio - defaultFlagValues[flagRollbackOrder] = `"` + defaultOrder(defaults.Service.Rollback.Order) + `"` - - defaultFlagValues[flagEndpointMode] = "vip" - - return defaultFlagValues -} - -func addDetachFlag(flags *pflag.FlagSet, detach *bool) { - flags.BoolVarP(detach, flagDetach, "d", false, "Exit immediately instead of waiting for the service to converge") - flags.SetAnnotation(flagDetach, "version", []string{"1.29"}) -} - -// addServiceFlags adds all flags that are common to both `create` and `update`. -// Any flags that are not common are added separately in the individual command -func addServiceFlags(flags *pflag.FlagSet, opts *serviceOptions, defaultFlagValues flagDefaults) { - flagDesc := func(flagName string, desc string) string { - if defaultValue, ok := defaultFlagValues[flagName]; ok { - return fmt.Sprintf("%s (default %v)", desc, defaultValue) - } - return desc - } - - addDetachFlag(flags, &opts.detach) - flags.BoolVarP(&opts.quiet, flagQuiet, "q", false, "Suppress progress output") - - flags.StringVarP(&opts.workdir, flagWorkdir, "w", "", "Working directory inside the container") - flags.StringVarP(&opts.user, flagUser, "u", "", "Username or UID (format: [:])") - flags.Var(&opts.credentialSpec, flagCredentialSpec, "Credential spec for managed service account (Windows only)") - flags.SetAnnotation(flagCredentialSpec, "version", []string{"1.29"}) - flags.StringVar(&opts.hostname, flagHostname, "", "Container hostname") - flags.SetAnnotation(flagHostname, "version", []string{"1.25"}) - flags.Var(&opts.entrypoint, flagEntrypoint, "Overwrite the default ENTRYPOINT of the image") - - flags.Var(&opts.resources.limitCPU, flagLimitCPU, "Limit CPUs") - flags.Var(&opts.resources.limitMemBytes, flagLimitMemory, "Limit Memory") - flags.Var(&opts.resources.resCPU, flagReserveCPU, "Reserve CPUs") - flags.Var(&opts.resources.resMemBytes, flagReserveMemory, "Reserve Memory") - - flags.Var(&opts.stopGrace, flagStopGracePeriod, flagDesc(flagStopGracePeriod, "Time to wait before force killing a container (ns|us|ms|s|m|h)")) - flags.Var(&opts.replicas, flagReplicas, "Number of tasks") - - flags.StringVar(&opts.restartPolicy.condition, flagRestartCondition, "", flagDesc(flagRestartCondition, `Restart when condition is met ("none"|"on-failure"|"any")`)) - flags.Var(&opts.restartPolicy.delay, flagRestartDelay, flagDesc(flagRestartDelay, "Delay between restart attempts (ns|us|ms|s|m|h)")) - flags.Var(&opts.restartPolicy.maxAttempts, flagRestartMaxAttempts, flagDesc(flagRestartMaxAttempts, "Maximum number of restarts before giving up")) - - flags.Var(&opts.restartPolicy.window, flagRestartWindow, flagDesc(flagRestartWindow, "Window used to evaluate the restart policy (ns|us|ms|s|m|h)")) - - flags.Uint64Var(&opts.update.parallelism, flagUpdateParallelism, defaultFlagValues.getUint64(flagUpdateParallelism), "Maximum number of tasks updated simultaneously (0 to update all at once)") - flags.DurationVar(&opts.update.delay, flagUpdateDelay, 0, flagDesc(flagUpdateDelay, "Delay between updates (ns|us|ms|s|m|h)")) - flags.DurationVar(&opts.update.monitor, flagUpdateMonitor, 0, flagDesc(flagUpdateMonitor, "Duration after each task update to monitor for failure (ns|us|ms|s|m|h)")) - flags.SetAnnotation(flagUpdateMonitor, "version", []string{"1.25"}) - flags.StringVar(&opts.update.onFailure, flagUpdateFailureAction, "", flagDesc(flagUpdateFailureAction, `Action on update failure ("pause"|"continue"|"rollback")`)) - flags.Var(&opts.update.maxFailureRatio, flagUpdateMaxFailureRatio, flagDesc(flagUpdateMaxFailureRatio, "Failure rate to tolerate during an update")) - flags.SetAnnotation(flagUpdateMaxFailureRatio, "version", []string{"1.25"}) - flags.StringVar(&opts.update.order, flagUpdateOrder, "", flagDesc(flagUpdateOrder, `Update order ("start-first"|"stop-first")`)) - flags.SetAnnotation(flagUpdateOrder, "version", []string{"1.29"}) - - flags.Uint64Var(&opts.rollback.parallelism, flagRollbackParallelism, defaultFlagValues.getUint64(flagRollbackParallelism), - "Maximum number of tasks rolled back simultaneously (0 to roll back all at once)") - flags.SetAnnotation(flagRollbackParallelism, "version", []string{"1.28"}) - flags.DurationVar(&opts.rollback.delay, flagRollbackDelay, 0, flagDesc(flagRollbackDelay, "Delay between task rollbacks (ns|us|ms|s|m|h)")) - flags.SetAnnotation(flagRollbackDelay, "version", []string{"1.28"}) - flags.DurationVar(&opts.rollback.monitor, flagRollbackMonitor, 0, flagDesc(flagRollbackMonitor, "Duration after each task rollback to monitor for failure (ns|us|ms|s|m|h)")) - flags.SetAnnotation(flagRollbackMonitor, "version", []string{"1.28"}) - flags.StringVar(&opts.rollback.onFailure, flagRollbackFailureAction, "", flagDesc(flagRollbackFailureAction, `Action on rollback failure ("pause"|"continue")`)) - flags.SetAnnotation(flagRollbackFailureAction, "version", []string{"1.28"}) - flags.Var(&opts.rollback.maxFailureRatio, flagRollbackMaxFailureRatio, flagDesc(flagRollbackMaxFailureRatio, "Failure rate to tolerate during a rollback")) - flags.SetAnnotation(flagRollbackMaxFailureRatio, "version", []string{"1.28"}) - flags.StringVar(&opts.rollback.order, flagRollbackOrder, "", flagDesc(flagRollbackOrder, `Rollback order ("start-first"|"stop-first")`)) - flags.SetAnnotation(flagRollbackOrder, "version", []string{"1.29"}) - - flags.StringVar(&opts.endpoint.mode, flagEndpointMode, defaultFlagValues.getString(flagEndpointMode), "Endpoint mode (vip or dnsrr)") - - flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to swarm agents") - flags.BoolVar(&opts.noResolveImage, flagNoResolveImage, false, "Do not query the registry to resolve image digest and supported platforms") - flags.SetAnnotation(flagNoResolveImage, "version", []string{"1.30"}) - - flags.StringVar(&opts.logDriver.name, flagLogDriver, "", "Logging driver for service") - flags.Var(&opts.logDriver.opts, flagLogOpt, "Logging driver options") - - flags.StringVar(&opts.healthcheck.cmd, flagHealthCmd, "", "Command to run to check health") - flags.SetAnnotation(flagHealthCmd, "version", []string{"1.25"}) - flags.Var(&opts.healthcheck.interval, flagHealthInterval, "Time between running the check (ms|s|m|h)") - flags.SetAnnotation(flagHealthInterval, "version", []string{"1.25"}) - flags.Var(&opts.healthcheck.timeout, flagHealthTimeout, "Maximum time to allow one check to run (ms|s|m|h)") - flags.SetAnnotation(flagHealthTimeout, "version", []string{"1.25"}) - flags.IntVar(&opts.healthcheck.retries, flagHealthRetries, 0, "Consecutive failures needed to report unhealthy") - flags.SetAnnotation(flagHealthRetries, "version", []string{"1.25"}) - flags.Var(&opts.healthcheck.startPeriod, flagHealthStartPeriod, "Start period for the container to initialize before counting retries towards unstable (ms|s|m|h)") - flags.SetAnnotation(flagHealthStartPeriod, "version", []string{"1.29"}) - flags.BoolVar(&opts.healthcheck.noHealthcheck, flagNoHealthcheck, false, "Disable any container-specified HEALTHCHECK") - flags.SetAnnotation(flagNoHealthcheck, "version", []string{"1.25"}) - - flags.BoolVarP(&opts.tty, flagTTY, "t", false, "Allocate a pseudo-TTY") - flags.SetAnnotation(flagTTY, "version", []string{"1.25"}) - - flags.BoolVar(&opts.readOnly, flagReadOnly, false, "Mount the container's root filesystem as read only") - flags.SetAnnotation(flagReadOnly, "version", []string{"1.28"}) - - flags.StringVar(&opts.stopSignal, flagStopSignal, "", "Signal to stop the container") - flags.SetAnnotation(flagStopSignal, "version", []string{"1.28"}) -} - -const ( - flagCredentialSpec = "credential-spec" - flagPlacementPref = "placement-pref" - flagPlacementPrefAdd = "placement-pref-add" - flagPlacementPrefRemove = "placement-pref-rm" - flagConstraint = "constraint" - flagConstraintRemove = "constraint-rm" - flagConstraintAdd = "constraint-add" - flagContainerLabel = "container-label" - flagContainerLabelRemove = "container-label-rm" - flagContainerLabelAdd = "container-label-add" - flagDetach = "detach" - flagDNS = "dns" - flagDNSRemove = "dns-rm" - flagDNSAdd = "dns-add" - flagDNSOption = "dns-option" - flagDNSOptionRemove = "dns-option-rm" - flagDNSOptionAdd = "dns-option-add" - flagDNSSearch = "dns-search" - flagDNSSearchRemove = "dns-search-rm" - flagDNSSearchAdd = "dns-search-add" - flagEndpointMode = "endpoint-mode" - flagEntrypoint = "entrypoint" - flagEnv = "env" - flagEnvFile = "env-file" - flagEnvRemove = "env-rm" - flagEnvAdd = "env-add" - flagGroup = "group" - flagGroupAdd = "group-add" - flagGroupRemove = "group-rm" - flagHost = "host" - flagHostAdd = "host-add" - flagHostRemove = "host-rm" - flagHostname = "hostname" - flagLabel = "label" - flagLabelRemove = "label-rm" - flagLabelAdd = "label-add" - flagLimitCPU = "limit-cpu" - flagLimitMemory = "limit-memory" - flagMode = "mode" - flagMount = "mount" - flagMountRemove = "mount-rm" - flagMountAdd = "mount-add" - flagName = "name" - flagNetwork = "network" - flagNetworkAdd = "network-add" - flagNetworkRemove = "network-rm" - flagPublish = "publish" - flagPublishRemove = "publish-rm" - flagPublishAdd = "publish-add" - flagQuiet = "quiet" - flagReadOnly = "read-only" - flagReplicas = "replicas" - flagReserveCPU = "reserve-cpu" - flagReserveMemory = "reserve-memory" - flagRestartCondition = "restart-condition" - flagRestartDelay = "restart-delay" - flagRestartMaxAttempts = "restart-max-attempts" - flagRestartWindow = "restart-window" - flagRollback = "rollback" - flagRollbackDelay = "rollback-delay" - flagRollbackFailureAction = "rollback-failure-action" - flagRollbackMaxFailureRatio = "rollback-max-failure-ratio" - flagRollbackMonitor = "rollback-monitor" - flagRollbackOrder = "rollback-order" - flagRollbackParallelism = "rollback-parallelism" - flagStopGracePeriod = "stop-grace-period" - flagStopSignal = "stop-signal" - flagTTY = "tty" - flagUpdateDelay = "update-delay" - flagUpdateFailureAction = "update-failure-action" - flagUpdateMaxFailureRatio = "update-max-failure-ratio" - flagUpdateMonitor = "update-monitor" - flagUpdateOrder = "update-order" - flagUpdateParallelism = "update-parallelism" - flagUser = "user" - flagWorkdir = "workdir" - flagRegistryAuth = "with-registry-auth" - flagNoResolveImage = "no-resolve-image" - flagLogDriver = "log-driver" - flagLogOpt = "log-opt" - flagHealthCmd = "health-cmd" - flagHealthInterval = "health-interval" - flagHealthRetries = "health-retries" - flagHealthTimeout = "health-timeout" - flagHealthStartPeriod = "health-start-period" - flagNoHealthcheck = "no-healthcheck" - flagSecret = "secret" - flagSecretAdd = "secret-add" - flagSecretRemove = "secret-rm" - flagConfig = "config" - flagConfigAdd = "config-add" - flagConfigRemove = "config-rm" -) diff --git a/vendor/github.com/docker/cli/cli/command/service/opts_test.go b/vendor/github.com/docker/cli/cli/command/service/opts_test.go deleted file mode 100644 index 6bf00ef6b..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/opts_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package service - -import ( - "testing" - "time" - - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/container" - "github.com/stretchr/testify/assert" -) - -func TestMemBytesString(t *testing.T) { - var mem opts.MemBytes = 1048576 - assert.Equal(t, "1MiB", mem.String()) -} - -func TestMemBytesSetAndValue(t *testing.T) { - var mem opts.MemBytes - assert.NoError(t, mem.Set("5kb")) - assert.Equal(t, int64(5120), mem.Value()) -} - -func TestNanoCPUsString(t *testing.T) { - var cpus opts.NanoCPUs = 6100000000 - assert.Equal(t, "6.100", cpus.String()) -} - -func TestNanoCPUsSetAndValue(t *testing.T) { - var cpus opts.NanoCPUs - assert.NoError(t, cpus.Set("0.35")) - assert.Equal(t, int64(350000000), cpus.Value()) -} - -func TestUint64OptString(t *testing.T) { - value := uint64(2345678) - opt := Uint64Opt{value: &value} - assert.Equal(t, "2345678", opt.String()) - - opt = Uint64Opt{} - assert.Equal(t, "", opt.String()) -} - -func TestUint64OptSetAndValue(t *testing.T) { - var opt Uint64Opt - assert.NoError(t, opt.Set("14445")) - assert.Equal(t, uint64(14445), *opt.Value()) -} - -func TestHealthCheckOptionsToHealthConfig(t *testing.T) { - dur := time.Second - opt := healthCheckOptions{ - cmd: "curl", - interval: opts.PositiveDurationOpt{*opts.NewDurationOpt(&dur)}, - timeout: opts.PositiveDurationOpt{*opts.NewDurationOpt(&dur)}, - startPeriod: opts.PositiveDurationOpt{*opts.NewDurationOpt(&dur)}, - retries: 10, - } - config, err := opt.toHealthConfig() - assert.NoError(t, err) - assert.Equal(t, &container.HealthConfig{ - Test: []string{"CMD-SHELL", "curl"}, - Interval: time.Second, - Timeout: time.Second, - StartPeriod: time.Second, - Retries: 10, - }, config) -} - -func TestHealthCheckOptionsToHealthConfigNoHealthcheck(t *testing.T) { - opt := healthCheckOptions{ - noHealthcheck: true, - } - config, err := opt.toHealthConfig() - assert.NoError(t, err) - assert.Equal(t, &container.HealthConfig{ - Test: []string{"NONE"}, - }, config) -} - -func TestHealthCheckOptionsToHealthConfigConflict(t *testing.T) { - opt := healthCheckOptions{ - cmd: "curl", - noHealthcheck: true, - } - _, err := opt.toHealthConfig() - assert.EqualError(t, err, "--no-healthcheck conflicts with --health-* options") -} diff --git a/vendor/github.com/docker/cli/cli/command/service/parse.go b/vendor/github.com/docker/cli/cli/command/service/parse.go deleted file mode 100644 index 6f69cbb47..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/parse.go +++ /dev/null @@ -1,117 +0,0 @@ -package service - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - swarmtypes "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -// ParseSecrets retrieves the secrets with the requested names and fills -// secret IDs into the secret references. -func ParseSecrets(client client.SecretAPIClient, requestedSecrets []*swarmtypes.SecretReference) ([]*swarmtypes.SecretReference, error) { - if len(requestedSecrets) == 0 { - return []*swarmtypes.SecretReference{}, nil - } - - secretRefs := make(map[string]*swarmtypes.SecretReference) - ctx := context.Background() - - for _, secret := range requestedSecrets { - if _, exists := secretRefs[secret.File.Name]; exists { - return nil, errors.Errorf("duplicate secret target for %s not allowed", secret.SecretName) - } - secretRef := new(swarmtypes.SecretReference) - *secretRef = *secret - secretRefs[secret.File.Name] = secretRef - } - - args := filters.NewArgs() - for _, s := range secretRefs { - args.Add("name", s.SecretName) - } - - secrets, err := client.SecretList(ctx, types.SecretListOptions{ - Filters: args, - }) - if err != nil { - return nil, err - } - - foundSecrets := make(map[string]string) - for _, secret := range secrets { - foundSecrets[secret.Spec.Annotations.Name] = secret.ID - } - - addedSecrets := []*swarmtypes.SecretReference{} - - for _, ref := range secretRefs { - id, ok := foundSecrets[ref.SecretName] - if !ok { - return nil, errors.Errorf("secret not found: %s", ref.SecretName) - } - - // set the id for the ref to properly assign in swarm - // since swarm needs the ID instead of the name - ref.SecretID = id - addedSecrets = append(addedSecrets, ref) - } - - return addedSecrets, nil -} - -// ParseConfigs retrieves the configs from the requested names and converts -// them to config references to use with the spec -func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes.ConfigReference) ([]*swarmtypes.ConfigReference, error) { - if len(requestedConfigs) == 0 { - return []*swarmtypes.ConfigReference{}, nil - } - - configRefs := make(map[string]*swarmtypes.ConfigReference) - ctx := context.Background() - - for _, config := range requestedConfigs { - if _, exists := configRefs[config.File.Name]; exists { - return nil, errors.Errorf("duplicate config target for %s not allowed", config.ConfigName) - } - - configRef := new(swarmtypes.ConfigReference) - *configRef = *config - configRefs[config.File.Name] = configRef - } - - args := filters.NewArgs() - for _, s := range configRefs { - args.Add("name", s.ConfigName) - } - - configs, err := client.ConfigList(ctx, types.ConfigListOptions{ - Filters: args, - }) - if err != nil { - return nil, err - } - - foundConfigs := make(map[string]string) - for _, config := range configs { - foundConfigs[config.Spec.Annotations.Name] = config.ID - } - - addedConfigs := []*swarmtypes.ConfigReference{} - - for _, ref := range configRefs { - id, ok := foundConfigs[ref.ConfigName] - if !ok { - return nil, errors.Errorf("config not found: %s", ref.ConfigName) - } - - // set the id for the ref to properly assign in swarm - // since swarm needs the ID instead of the name - ref.ConfigID = id - addedConfigs = append(addedConfigs, ref) - } - - return addedConfigs, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/progress/progress.go b/vendor/github.com/docker/cli/cli/command/service/progress/progress.go deleted file mode 100644 index adff48684..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/progress/progress.go +++ /dev/null @@ -1,504 +0,0 @@ -package progress - -import ( - "errors" - "fmt" - "io" - "os" - "os/signal" - "strings" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "golang.org/x/net/context" -) - -var ( - numberedStates = map[swarm.TaskState]int64{ - swarm.TaskStateNew: 1, - swarm.TaskStateAllocated: 2, - swarm.TaskStatePending: 3, - swarm.TaskStateAssigned: 4, - swarm.TaskStateAccepted: 5, - swarm.TaskStatePreparing: 6, - swarm.TaskStateReady: 7, - swarm.TaskStateStarting: 8, - swarm.TaskStateRunning: 9, - - // The following states are not actually shown in progress - // output, but are used internally for ordering. - swarm.TaskStateComplete: 10, - swarm.TaskStateShutdown: 11, - swarm.TaskStateFailed: 12, - swarm.TaskStateRejected: 13, - } - - longestState int -) - -const ( - maxProgress = 9 - maxProgressBars = 20 -) - -type progressUpdater interface { - update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]struct{}, rollback bool) (bool, error) -} - -func init() { - for state := range numberedStates { - if !terminalState(state) && len(state) > longestState { - longestState = len(state) - } - } -} - -func terminalState(state swarm.TaskState) bool { - return numberedStates[state] > numberedStates[swarm.TaskStateRunning] -} - -func stateToProgress(state swarm.TaskState, rollback bool) int64 { - if !rollback { - return numberedStates[state] - } - return numberedStates[swarm.TaskStateRunning] - numberedStates[state] -} - -// ServiceProgress outputs progress information for convergence of a service. -// nolint: gocyclo -func ServiceProgress(ctx context.Context, client client.APIClient, serviceID string, progressWriter io.WriteCloser) error { - defer progressWriter.Close() - - progressOut := streamformatter.NewJSONProgressOutput(progressWriter, false) - - sigint := make(chan os.Signal, 1) - signal.Notify(sigint, os.Interrupt) - defer signal.Stop(sigint) - - taskFilter := filters.NewArgs() - taskFilter.Add("service", serviceID) - taskFilter.Add("_up-to-date", "true") - - getUpToDateTasks := func() ([]swarm.Task, error) { - return client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter}) - } - - var ( - updater progressUpdater - converged bool - convergedAt time.Time - monitor = 5 * time.Second - rollback bool - ) - - for { - service, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) - if err != nil { - return err - } - - if service.Spec.UpdateConfig != nil && service.Spec.UpdateConfig.Monitor != 0 { - monitor = service.Spec.UpdateConfig.Monitor - } - - if updater == nil { - updater, err = initializeUpdater(service, progressOut) - if err != nil { - return err - } - } - - if service.UpdateStatus != nil { - switch service.UpdateStatus.State { - case swarm.UpdateStateUpdating: - rollback = false - case swarm.UpdateStateCompleted: - if !converged { - return nil - } - case swarm.UpdateStatePaused: - return fmt.Errorf("service update paused: %s", service.UpdateStatus.Message) - case swarm.UpdateStateRollbackStarted: - if !rollback && service.UpdateStatus.Message != "" { - progressOut.WriteProgress(progress.Progress{ - ID: "rollback", - Action: service.UpdateStatus.Message, - }) - } - rollback = true - case swarm.UpdateStateRollbackPaused: - return fmt.Errorf("service rollback paused: %s", service.UpdateStatus.Message) - case swarm.UpdateStateRollbackCompleted: - if !converged { - return fmt.Errorf("service rolled back: %s", service.UpdateStatus.Message) - } - } - } - if converged && time.Since(convergedAt) >= monitor { - progressOut.WriteProgress(progress.Progress{ - ID: "verify", - Action: "Service converged", - }) - - return nil - } - - tasks, err := getUpToDateTasks() - if err != nil { - return err - } - - activeNodes, err := getActiveNodes(ctx, client) - if err != nil { - return err - } - - converged, err = updater.update(service, tasks, activeNodes, rollback) - if err != nil { - return err - } - if converged { - if convergedAt.IsZero() { - convergedAt = time.Now() - } - wait := monitor - time.Since(convergedAt) - if wait >= 0 { - progressOut.WriteProgress(progress.Progress{ - // Ideally this would have no ID, but - // the progress rendering code behaves - // poorly on an "action" with no ID. It - // returns the cursor to the beginning - // of the line, so the first character - // may be difficult to read. Then the - // output is overwritten by the shell - // prompt when the command finishes. - ID: "verify", - Action: fmt.Sprintf("Waiting %d seconds to verify that tasks are stable...", wait/time.Second+1), - }) - } - } else { - if !convergedAt.IsZero() { - progressOut.WriteProgress(progress.Progress{ - ID: "verify", - Action: "Detected task failure", - }) - } - convergedAt = time.Time{} - } - - select { - case <-time.After(200 * time.Millisecond): - case <-sigint: - if !converged { - progress.Message(progressOut, "", "Operation continuing in background.") - progress.Messagef(progressOut, "", "Use `docker service ps %s` to check progress.", serviceID) - } - return nil - } - } -} - -func getActiveNodes(ctx context.Context, client client.APIClient) (map[string]struct{}, error) { - nodes, err := client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return nil, err - } - - activeNodes := make(map[string]struct{}) - for _, n := range nodes { - if n.Status.State != swarm.NodeStateDown { - activeNodes[n.ID] = struct{}{} - } - } - return activeNodes, nil -} - -func initializeUpdater(service swarm.Service, progressOut progress.Output) (progressUpdater, error) { - if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil { - return &replicatedProgressUpdater{ - progressOut: progressOut, - }, nil - } - if service.Spec.Mode.Global != nil { - return &globalProgressUpdater{ - progressOut: progressOut, - }, nil - } - return nil, errors.New("unrecognized service mode") -} - -func writeOverallProgress(progressOut progress.Output, numerator, denominator int, rollback bool) { - if rollback { - progressOut.WriteProgress(progress.Progress{ - ID: "overall progress", - Action: fmt.Sprintf("rolling back update: %d out of %d tasks", numerator, denominator), - }) - return - } - progressOut.WriteProgress(progress.Progress{ - ID: "overall progress", - Action: fmt.Sprintf("%d out of %d tasks", numerator, denominator), - }) -} - -func truncError(errMsg string) string { - // Remove newlines from the error, which corrupt the output. - errMsg = strings.Replace(errMsg, "\n", " ", -1) - - // Limit the length to 75 characters, so that even on narrow terminals - // this will not overflow to the next line. - if len(errMsg) > 75 { - errMsg = errMsg[:74] + "…" - } - return errMsg -} - -type replicatedProgressUpdater struct { - progressOut progress.Output - - // used for mapping slots to a contiguous space - // this also causes progress bars to appear in order - slotMap map[int]int - - initialized bool - done bool -} - -func (u *replicatedProgressUpdater) update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]struct{}, rollback bool) (bool, error) { - if service.Spec.Mode.Replicated == nil || service.Spec.Mode.Replicated.Replicas == nil { - return false, errors.New("no replica count") - } - replicas := *service.Spec.Mode.Replicated.Replicas - - if !u.initialized { - u.slotMap = make(map[int]int) - - // Draw progress bars in order - writeOverallProgress(u.progressOut, 0, int(replicas), rollback) - - if replicas <= maxProgressBars { - for i := uint64(1); i <= replicas; i++ { - progress.Update(u.progressOut, fmt.Sprintf("%d/%d", i, replicas), " ") - } - } - u.initialized = true - } - - tasksBySlot := u.tasksBySlot(tasks, activeNodes) - - // If we had reached a converged state, check if we are still converged. - if u.done { - for _, task := range tasksBySlot { - if task.Status.State != swarm.TaskStateRunning { - u.done = false - break - } - } - } - - running := uint64(0) - - for _, task := range tasksBySlot { - mappedSlot := u.slotMap[task.Slot] - if mappedSlot == 0 { - mappedSlot = len(u.slotMap) + 1 - u.slotMap[task.Slot] = mappedSlot - } - - if !terminalState(task.DesiredState) && task.Status.State == swarm.TaskStateRunning { - running++ - } - - u.writeTaskProgress(task, mappedSlot, replicas, rollback) - } - - if !u.done { - writeOverallProgress(u.progressOut, int(running), int(replicas), rollback) - - if running == replicas { - u.done = true - } - } - - return running == replicas, nil -} - -func (u *replicatedProgressUpdater) tasksBySlot(tasks []swarm.Task, activeNodes map[string]struct{}) map[int]swarm.Task { - // If there are multiple tasks with the same slot number, favor the one - // with the *lowest* desired state. This can happen in restart - // scenarios. - tasksBySlot := make(map[int]swarm.Task) - for _, task := range tasks { - if numberedStates[task.DesiredState] == 0 || numberedStates[task.Status.State] == 0 { - continue - } - if existingTask, ok := tasksBySlot[task.Slot]; ok { - if numberedStates[existingTask.DesiredState] < numberedStates[task.DesiredState] { - continue - } - // If the desired states match, observed state breaks - // ties. This can happen with the "start first" service - // update mode. - if numberedStates[existingTask.DesiredState] == numberedStates[task.DesiredState] && - numberedStates[existingTask.Status.State] <= numberedStates[task.Status.State] { - continue - } - } - if task.NodeID != "" { - if _, nodeActive := activeNodes[task.NodeID]; !nodeActive { - continue - } - } - tasksBySlot[task.Slot] = task - } - - return tasksBySlot -} - -func (u *replicatedProgressUpdater) writeTaskProgress(task swarm.Task, mappedSlot int, replicas uint64, rollback bool) { - if u.done || replicas > maxProgressBars || uint64(mappedSlot) > replicas { - return - } - - if task.Status.Err != "" { - u.progressOut.WriteProgress(progress.Progress{ - ID: fmt.Sprintf("%d/%d", mappedSlot, replicas), - Action: truncError(task.Status.Err), - }) - return - } - - if !terminalState(task.DesiredState) && !terminalState(task.Status.State) { - u.progressOut.WriteProgress(progress.Progress{ - ID: fmt.Sprintf("%d/%d", mappedSlot, replicas), - Action: fmt.Sprintf("%-[1]*s", longestState, task.Status.State), - Current: stateToProgress(task.Status.State, rollback), - Total: maxProgress, - HideCounts: true, - }) - } -} - -type globalProgressUpdater struct { - progressOut progress.Output - - initialized bool - done bool -} - -func (u *globalProgressUpdater) update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]struct{}, rollback bool) (bool, error) { - tasksByNode := u.tasksByNode(tasks) - - // We don't have perfect knowledge of how many nodes meet the - // constraints for this service. But the orchestrator creates tasks - // for all eligible nodes at the same time, so we should see all those - // nodes represented among the up-to-date tasks. - nodeCount := len(tasksByNode) - - if !u.initialized { - if nodeCount == 0 { - // Two possibilities: either the orchestrator hasn't created - // the tasks yet, or the service doesn't meet constraints for - // any node. Either way, we wait. - u.progressOut.WriteProgress(progress.Progress{ - ID: "overall progress", - Action: "waiting for new tasks", - }) - return false, nil - } - - writeOverallProgress(u.progressOut, 0, nodeCount, rollback) - u.initialized = true - } - - // If we had reached a converged state, check if we are still converged. - if u.done { - for _, task := range tasksByNode { - if task.Status.State != swarm.TaskStateRunning { - u.done = false - break - } - } - } - - running := 0 - - for _, task := range tasksByNode { - if _, nodeActive := activeNodes[task.NodeID]; nodeActive { - if !terminalState(task.DesiredState) && task.Status.State == swarm.TaskStateRunning { - running++ - } - - u.writeTaskProgress(task, nodeCount, rollback) - } - } - - if !u.done { - writeOverallProgress(u.progressOut, running, nodeCount, rollback) - - if running == nodeCount { - u.done = true - } - } - - return running == nodeCount, nil -} - -func (u *globalProgressUpdater) tasksByNode(tasks []swarm.Task) map[string]swarm.Task { - // If there are multiple tasks with the same node ID, favor the one - // with the *lowest* desired state. This can happen in restart - // scenarios. - tasksByNode := make(map[string]swarm.Task) - for _, task := range tasks { - if numberedStates[task.DesiredState] == 0 || numberedStates[task.Status.State] == 0 { - continue - } - if existingTask, ok := tasksByNode[task.NodeID]; ok { - if numberedStates[existingTask.DesiredState] < numberedStates[task.DesiredState] { - continue - } - - // If the desired states match, observed state breaks - // ties. This can happen with the "start first" service - // update mode. - if numberedStates[existingTask.DesiredState] == numberedStates[task.DesiredState] && - numberedStates[existingTask.Status.State] <= numberedStates[task.Status.State] { - continue - } - - } - tasksByNode[task.NodeID] = task - } - - return tasksByNode -} - -func (u *globalProgressUpdater) writeTaskProgress(task swarm.Task, nodeCount int, rollback bool) { - if u.done || nodeCount > maxProgressBars { - return - } - - if task.Status.Err != "" { - u.progressOut.WriteProgress(progress.Progress{ - ID: stringid.TruncateID(task.NodeID), - Action: truncError(task.Status.Err), - }) - return - } - - if !terminalState(task.DesiredState) && !terminalState(task.Status.State) { - u.progressOut.WriteProgress(progress.Progress{ - ID: stringid.TruncateID(task.NodeID), - Action: fmt.Sprintf("%-[1]*s", longestState, task.Status.State), - Current: stateToProgress(task.Status.State, rollback), - Total: maxProgress, - HideCounts: true, - }) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/service/progress/progress_test.go b/vendor/github.com/docker/cli/cli/command/service/progress/progress_test.go deleted file mode 100644 index d1c118f7d..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/progress/progress_test.go +++ /dev/null @@ -1,374 +0,0 @@ -package progress - -import ( - "fmt" - "strconv" - "testing" - - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/progress" - "github.com/stretchr/testify/assert" -) - -type mockProgress struct { - p []progress.Progress -} - -func (mp *mockProgress) WriteProgress(p progress.Progress) error { - mp.p = append(mp.p, p) - return nil -} - -func (mp *mockProgress) clear() { - mp.p = nil -} - -type updaterTester struct { - t *testing.T - updater progressUpdater - p *mockProgress - service swarm.Service - activeNodes map[string]struct{} - rollback bool -} - -func (u updaterTester) testUpdater(tasks []swarm.Task, expectedConvergence bool, expectedProgress []progress.Progress) { - u.p.clear() - - converged, err := u.updater.update(u.service, tasks, u.activeNodes, u.rollback) - assert.NoError(u.t, err) - assert.Equal(u.t, expectedConvergence, converged) - assert.Equal(u.t, expectedProgress, u.p.p) -} - -func TestReplicatedProgressUpdaterOneReplica(t *testing.T) { - replicas := uint64(1) - - service := swarm.Service{ - Spec: swarm.ServiceSpec{ - Mode: swarm.ServiceMode{ - Replicated: &swarm.ReplicatedService{ - Replicas: &replicas, - }, - }, - }, - } - - p := &mockProgress{} - updaterTester := updaterTester{ - t: t, - updater: &replicatedProgressUpdater{ - progressOut: p, - }, - p: p, - activeNodes: map[string]struct{}{"a": {}, "b": {}}, - service: service, - } - - tasks := []swarm.Task{} - - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: "0 out of 1 tasks"}, - {ID: "1/1", Action: " "}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // Task with DesiredState beyond Running is ignored - tasks = append(tasks, - swarm.Task{ID: "1", - NodeID: "a", - DesiredState: swarm.TaskStateShutdown, - Status: swarm.TaskStatus{State: swarm.TaskStateNew}, - }) - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // Task with valid DesiredState and State updates progress bar - tasks[0].DesiredState = swarm.TaskStateRunning - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "1/1", Action: "new ", Current: 1, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // If the task exposes an error, we should show that instead of the - // progress bar. - tasks[0].Status.Err = "something is wrong" - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "1/1", Action: "something is wrong"}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // When the task reaches running, update should return true - tasks[0].Status.Err = "" - tasks[0].Status.State = swarm.TaskStateRunning - updaterTester.testUpdater(tasks, true, - []progress.Progress{ - {ID: "1/1", Action: "running ", Current: 9, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "1 out of 1 tasks"}, - }) - - // If the task fails, update should return false again - tasks[0].Status.Err = "task failed" - tasks[0].Status.State = swarm.TaskStateFailed - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "1/1", Action: "task failed"}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // If the task is restarted, progress output should be shown for the - // replacement task, not the old task. - tasks[0].DesiredState = swarm.TaskStateShutdown - tasks = append(tasks, - swarm.Task{ID: "2", - NodeID: "b", - DesiredState: swarm.TaskStateRunning, - Status: swarm.TaskStatus{State: swarm.TaskStateRunning}, - }) - updaterTester.testUpdater(tasks, true, - []progress.Progress{ - {ID: "1/1", Action: "running ", Current: 9, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "1 out of 1 tasks"}, - }) - - // Add a new task while the current one is still running, to simulate - // "start-then-stop" updates. - tasks = append(tasks, - swarm.Task{ID: "3", - NodeID: "b", - DesiredState: swarm.TaskStateRunning, - Status: swarm.TaskStatus{State: swarm.TaskStatePreparing}, - }) - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "1/1", Action: "preparing", Current: 6, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) -} - -func TestReplicatedProgressUpdaterManyReplicas(t *testing.T) { - replicas := uint64(50) - - service := swarm.Service{ - Spec: swarm.ServiceSpec{ - Mode: swarm.ServiceMode{ - Replicated: &swarm.ReplicatedService{ - Replicas: &replicas, - }, - }, - }, - } - - p := &mockProgress{} - updaterTester := updaterTester{ - t: t, - updater: &replicatedProgressUpdater{ - progressOut: p, - }, - p: p, - activeNodes: map[string]struct{}{"a": {}, "b": {}}, - service: service, - } - - tasks := []swarm.Task{} - - // No per-task progress bars because there are too many replicas - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: fmt.Sprintf("0 out of %d tasks", replicas)}, - {ID: "overall progress", Action: fmt.Sprintf("0 out of %d tasks", replicas)}, - }) - - for i := 0; i != int(replicas); i++ { - tasks = append(tasks, - swarm.Task{ - ID: strconv.Itoa(i), - Slot: i + 1, - NodeID: "a", - DesiredState: swarm.TaskStateRunning, - Status: swarm.TaskStatus{State: swarm.TaskStateNew}, - }) - - if i%2 == 1 { - tasks[i].NodeID = "b" - } - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: fmt.Sprintf("%d out of %d tasks", i, replicas)}, - }) - - tasks[i].Status.State = swarm.TaskStateRunning - updaterTester.testUpdater(tasks, uint64(i) == replicas-1, - []progress.Progress{ - {ID: "overall progress", Action: fmt.Sprintf("%d out of %d tasks", i+1, replicas)}, - }) - } -} - -func TestGlobalProgressUpdaterOneNode(t *testing.T) { - service := swarm.Service{ - Spec: swarm.ServiceSpec{ - Mode: swarm.ServiceMode{ - Global: &swarm.GlobalService{}, - }, - }, - } - - p := &mockProgress{} - updaterTester := updaterTester{ - t: t, - updater: &globalProgressUpdater{ - progressOut: p, - }, - p: p, - activeNodes: map[string]struct{}{"a": {}, "b": {}}, - service: service, - } - - tasks := []swarm.Task{} - - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: "waiting for new tasks"}, - }) - - // Task with DesiredState beyond Running is ignored - tasks = append(tasks, - swarm.Task{ID: "1", - NodeID: "a", - DesiredState: swarm.TaskStateShutdown, - Status: swarm.TaskStatus{State: swarm.TaskStateNew}, - }) - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: "0 out of 1 tasks"}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // Task with valid DesiredState and State updates progress bar - tasks[0].DesiredState = swarm.TaskStateRunning - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "a", Action: "new ", Current: 1, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // If the task exposes an error, we should show that instead of the - // progress bar. - tasks[0].Status.Err = "something is wrong" - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "a", Action: "something is wrong"}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // When the task reaches running, update should return true - tasks[0].Status.Err = "" - tasks[0].Status.State = swarm.TaskStateRunning - updaterTester.testUpdater(tasks, true, - []progress.Progress{ - {ID: "a", Action: "running ", Current: 9, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "1 out of 1 tasks"}, - }) - - // If the task fails, update should return false again - tasks[0].Status.Err = "task failed" - tasks[0].Status.State = swarm.TaskStateFailed - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "a", Action: "task failed"}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) - - // If the task is restarted, progress output should be shown for the - // replacement task, not the old task. - tasks[0].DesiredState = swarm.TaskStateShutdown - tasks = append(tasks, - swarm.Task{ID: "2", - NodeID: "a", - DesiredState: swarm.TaskStateRunning, - Status: swarm.TaskStatus{State: swarm.TaskStateRunning}, - }) - updaterTester.testUpdater(tasks, true, - []progress.Progress{ - {ID: "a", Action: "running ", Current: 9, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "1 out of 1 tasks"}, - }) - - // Add a new task while the current one is still running, to simulate - // "start-then-stop" updates. - tasks = append(tasks, - swarm.Task{ID: "3", - NodeID: "a", - DesiredState: swarm.TaskStateRunning, - Status: swarm.TaskStatus{State: swarm.TaskStatePreparing}, - }) - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "a", Action: "preparing", Current: 6, Total: 9, HideCounts: true}, - {ID: "overall progress", Action: "0 out of 1 tasks"}, - }) -} - -func TestGlobalProgressUpdaterManyNodes(t *testing.T) { - nodes := 50 - - service := swarm.Service{ - Spec: swarm.ServiceSpec{ - Mode: swarm.ServiceMode{ - Global: &swarm.GlobalService{}, - }, - }, - } - - p := &mockProgress{} - updaterTester := updaterTester{ - t: t, - updater: &globalProgressUpdater{ - progressOut: p, - }, - p: p, - activeNodes: map[string]struct{}{}, - service: service, - } - - for i := 0; i != nodes; i++ { - updaterTester.activeNodes[strconv.Itoa(i)] = struct{}{} - } - - tasks := []swarm.Task{} - - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: "waiting for new tasks"}, - }) - - for i := 0; i != nodes; i++ { - tasks = append(tasks, - swarm.Task{ - ID: "task" + strconv.Itoa(i), - NodeID: strconv.Itoa(i), - DesiredState: swarm.TaskStateRunning, - Status: swarm.TaskStatus{State: swarm.TaskStateNew}, - }) - } - - updaterTester.testUpdater(tasks, false, - []progress.Progress{ - {ID: "overall progress", Action: fmt.Sprintf("0 out of %d tasks", nodes)}, - {ID: "overall progress", Action: fmt.Sprintf("0 out of %d tasks", nodes)}, - }) - - for i := 0; i != nodes; i++ { - tasks[i].Status.State = swarm.TaskStateRunning - updaterTester.testUpdater(tasks, i == nodes-1, - []progress.Progress{ - {ID: "overall progress", Action: fmt.Sprintf("%d out of %d tasks", i+1, nodes)}, - }) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/service/ps.go b/vendor/github.com/docker/cli/cli/command/service/ps.go deleted file mode 100644 index e441f9e1a..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/ps.go +++ /dev/null @@ -1,152 +0,0 @@ -package service - -import ( - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/cli/command/node" - "github.com/docker/cli/cli/command/task" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type psOptions struct { - services []string - quiet bool - noResolve bool - noTrunc bool - format string - filter opts.FilterOpt -} - -func newPsCommand(dockerCli command.Cli) *cobra.Command { - options := psOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ps [OPTIONS] SERVICE [SERVICE...]", - Short: "List the tasks of one or more services", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.services = args - return runPS(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display task IDs") - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&options.noResolve, "no-resolve", false, "Do not map IDs to Names") - flags.StringVar(&options.format, "format", "", "Pretty-print tasks using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runPS(dockerCli command.Cli, options psOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - filter, notfound, err := createFilter(ctx, client, options) - if err != nil { - return err - } - if err := updateNodeFilter(ctx, client, filter); err != nil { - return err - } - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - format = task.DefaultFormat(dockerCli.ConfigFile(), options.quiet) - } - if err := task.Print(ctx, dockerCli, tasks, idresolver.New(client, options.noResolve), !options.noTrunc, options.quiet, format); err != nil { - return err - } - if len(notfound) != 0 { - return errors.New(strings.Join(notfound, "\n")) - } - return nil -} - -func createFilter(ctx context.Context, client client.APIClient, options psOptions) (filters.Args, []string, error) { - filter := options.filter.Value() - - serviceIDFilter := filters.NewArgs() - serviceNameFilter := filters.NewArgs() - for _, service := range options.services { - serviceIDFilter.Add("id", service) - serviceNameFilter.Add("name", service) - } - serviceByIDList, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceIDFilter}) - if err != nil { - return filter, nil, err - } - serviceByNameList, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceNameFilter}) - if err != nil { - return filter, nil, err - } - - var notfound []string - serviceCount := 0 -loop: - // Match services by 1. Full ID, 2. Full name, 3. ID prefix. An error is returned if the ID-prefix match is ambiguous - for _, service := range options.services { - for _, s := range serviceByIDList { - if s.ID == service { - filter.Add("service", s.ID) - serviceCount++ - continue loop - } - } - for _, s := range serviceByNameList { - if s.Spec.Annotations.Name == service { - filter.Add("service", s.ID) - serviceCount++ - continue loop - } - } - found := false - for _, s := range serviceByIDList { - if strings.HasPrefix(s.ID, service) { - if found { - return filter, nil, errors.New("multiple services found with provided prefix: " + service) - } - filter.Add("service", s.ID) - serviceCount++ - found = true - } - } - if !found { - notfound = append(notfound, "no such service: "+service) - } - } - if serviceCount == 0 { - return filter, nil, errors.New(strings.Join(notfound, "\n")) - } - return filter, notfound, err -} - -func updateNodeFilter(ctx context.Context, client client.APIClient, filter filters.Args) error { - if filter.Include("node") { - nodeFilters := filter.Get("node") - for _, nodeFilter := range nodeFilters { - nodeReference, err := node.Reference(ctx, client, nodeFilter) - if err != nil { - return err - } - filter.Del("node", nodeFilter) - filter.Add("node", nodeReference) - } - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/ps_test.go b/vendor/github.com/docker/cli/cli/command/service/ps_test.go deleted file mode 100644 index be2687028..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/ps_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package service - -import ( - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/context" -) - -func TestCreateFilter(t *testing.T) { - client := &fakeClient{ - serviceListFunc: func(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - {ID: "idmatch"}, - {ID: "idprefixmatch"}, - newService("cccccccc", "namematch"), - newService("01010101", "notfoundprefix"), - }, nil - }, - } - - filter := opts.NewFilterOpt() - require.NoError(t, filter.Set("node=somenode")) - options := psOptions{ - services: []string{"idmatch", "idprefix", "namematch", "notfound"}, - filter: filter, - } - - actual, notfound, err := createFilter(context.Background(), client, options) - require.NoError(t, err) - assert.Equal(t, notfound, []string{"no such service: notfound"}) - - expected := filters.NewArgs() - expected.Add("service", "idmatch") - expected.Add("service", "idprefixmatch") - expected.Add("service", "cccccccc") - expected.Add("node", "somenode") - assert.Equal(t, expected, actual) -} - -func TestCreateFilterWithAmbiguousIDPrefixError(t *testing.T) { - client := &fakeClient{ - serviceListFunc: func(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - {ID: "aaaone"}, - {ID: "aaatwo"}, - }, nil - }, - } - options := psOptions{ - services: []string{"aaa"}, - filter: opts.NewFilterOpt(), - } - _, _, err := createFilter(context.Background(), client, options) - assert.EqualError(t, err, "multiple services found with provided prefix: aaa") -} - -func TestCreateFilterNoneFound(t *testing.T) { - client := &fakeClient{} - options := psOptions{ - services: []string{"foo", "notfound"}, - filter: opts.NewFilterOpt(), - } - _, _, err := createFilter(context.Background(), client, options) - assert.EqualError(t, err, "no such service: foo\nno such service: notfound") -} - -func TestRunPSWarnsOnNotFound(t *testing.T) { - client := &fakeClient{ - serviceListFunc: func(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - {ID: "foo"}, - }, nil - }, - } - - cli := test.NewFakeCli(client) - options := psOptions{ - services: []string{"foo", "bar"}, - filter: opts.NewFilterOpt(), - format: "{{.ID}}", - } - err := runPS(cli, options) - assert.EqualError(t, err, "no such service: bar") -} - -func TestUpdateNodeFilter(t *testing.T) { - selfNodeID := "foofoo" - filter := filters.NewArgs() - filter.Add("node", "one") - filter.Add("node", "two") - filter.Add("node", "self") - - client := &fakeClient{ - infoFunc: func(_ context.Context) (types.Info, error) { - return types.Info{Swarm: swarm.Info{NodeID: selfNodeID}}, nil - }, - } - - updateNodeFilter(context.Background(), client, filter) - - expected := filters.NewArgs() - expected.Add("node", "one") - expected.Add("node", "two") - expected.Add("node", selfNodeID) - assert.Equal(t, expected, filter) -} diff --git a/vendor/github.com/docker/cli/cli/command/service/remove.go b/vendor/github.com/docker/cli/cli/command/service/remove.go deleted file mode 100644 index 38833b2e7..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/remove.go +++ /dev/null @@ -1,48 +0,0 @@ -package service - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - - cmd := &cobra.Command{ - Use: "rm SERVICE [SERVICE...]", - Aliases: []string{"remove"}, - Short: "Remove one or more services", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, args) - }, - } - cmd.Flags() - - return cmd -} - -func runRemove(dockerCli command.Cli, sids []string) error { - client := dockerCli.Client() - - ctx := context.Background() - - var errs []string - for _, sid := range sids { - err := client.ServiceRemove(ctx, sid) - if err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintf(dockerCli.Out(), "%s\n", sid) - } - if len(errs) > 0 { - return errors.Errorf(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/rollback.go b/vendor/github.com/docker/cli/cli/command/service/rollback.go deleted file mode 100644 index 375e6d510..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/rollback.go +++ /dev/null @@ -1,64 +0,0 @@ -package service - -import ( - "context" - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/spf13/cobra" -) - -func newRollbackCommand(dockerCli command.Cli) *cobra.Command { - options := newServiceOptions() - - cmd := &cobra.Command{ - Use: "rollback [OPTIONS] SERVICE", - Short: "Revert changes to a service's configuration", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runRollback(dockerCli, options, args[0]) - }, - Tags: map[string]string{"version": "1.31"}, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, flagQuiet, "q", false, "Suppress progress output") - addDetachFlag(flags, &options.detach) - - return cmd -} - -func runRollback(dockerCli command.Cli, options *serviceOptions, serviceID string) error { - apiClient := dockerCli.Client() - ctx := context.Background() - - service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) - if err != nil { - return err - } - - spec := &service.Spec - updateOpts := types.ServiceUpdateOptions{ - Rollback: "previous", - } - - response, err := apiClient.ServiceUpdate(ctx, service.ID, service.Version, *spec, updateOpts) - if err != nil { - return err - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID) - - if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") { - return nil - } - - return waitOnService(ctx, dockerCli, serviceID, options.quiet) -} diff --git a/vendor/github.com/docker/cli/cli/command/service/rollback_test.go b/vendor/github.com/docker/cli/cli/command/service/rollback_test.go deleted file mode 100644 index c06367664..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/rollback_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package service - -import ( - "fmt" - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestRollback(t *testing.T) { - testCases := []struct { - name string - args []string - serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) - expectedDockerCliErr string - }{ - { - name: "rollback-service", - args: []string{"service-id"}, - }, - { - name: "rollback-service-with-warnings", - args: []string{"service-id"}, - serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { - response := types.ServiceUpdateResponse{} - - response.Warnings = []string{ - "- warning 1", - "- warning 2", - } - - return response, nil - }, - expectedDockerCliErr: "- warning 1\n- warning 2", - }, - } - - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - serviceUpdateFunc: tc.serviceUpdateFunc, - }) - cmd := newRollbackCommand(cli) - cmd.SetArgs(tc.args) - cmd.Flags().Set("quiet", "true") - cmd.SetOutput(ioutil.Discard) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, strings.TrimSpace(cli.ErrBuffer().String()), tc.expectedDockerCliErr) - } -} - -func TestRollbackWithErrors(t *testing.T) { - testCases := []struct { - name string - args []string - serviceInspectWithRawFunc func(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) - serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) - expectedError string - }{ - { - name: "not-enough-args", - expectedError: "requires exactly 1 argument", - }, - { - name: "too-many-args", - args: []string{"service-id-1", "service-id-2"}, - expectedError: "requires exactly 1 argument", - }, - { - name: "service-does-not-exists", - args: []string{"service-id"}, - serviceInspectWithRawFunc: func(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { - return swarm.Service{}, []byte{}, fmt.Errorf("no such services: %s", serviceID) - }, - expectedError: "no such services: service-id", - }, - { - name: "service-update-failed", - args: []string{"service-id"}, - serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { - return types.ServiceUpdateResponse{}, fmt.Errorf("no such services: %s", serviceID) - }, - expectedError: "no such services: service-id", - }, - } - - for _, tc := range testCases { - cmd := newRollbackCommand( - test.NewFakeCli(&fakeClient{ - serviceInspectWithRawFunc: tc.serviceInspectWithRawFunc, - serviceUpdateFunc: tc.serviceUpdateFunc, - })) - cmd.SetArgs(tc.args) - cmd.Flags().Set("quiet", "true") - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/service/scale.go b/vendor/github.com/docker/cli/cli/command/service/scale.go deleted file mode 100644 index d38b01b4b..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/scale.go +++ /dev/null @@ -1,123 +0,0 @@ -package service - -import ( - "fmt" - "strconv" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type scaleOptions struct { - detach bool -} - -func newScaleCommand(dockerCli command.Cli) *cobra.Command { - options := &scaleOptions{} - - cmd := &cobra.Command{ - Use: "scale SERVICE=REPLICAS [SERVICE=REPLICAS...]", - Short: "Scale one or multiple replicated services", - Args: scaleArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runScale(dockerCli, options, args) - }, - } - - flags := cmd.Flags() - addDetachFlag(flags, &options.detach) - return cmd -} - -func scaleArgs(cmd *cobra.Command, args []string) error { - if err := cli.RequiresMinArgs(1)(cmd, args); err != nil { - return err - } - for _, arg := range args { - if parts := strings.SplitN(arg, "=", 2); len(parts) != 2 { - return errors.Errorf( - "Invalid scale specifier '%s'.\nSee '%s --help'.\n\nUsage: %s\n\n%s", - arg, - cmd.CommandPath(), - cmd.UseLine(), - cmd.Short, - ) - } - } - return nil -} - -func runScale(dockerCli command.Cli, options *scaleOptions, args []string) error { - var errs []string - var serviceIDs []string - ctx := context.Background() - - for _, arg := range args { - parts := strings.SplitN(arg, "=", 2) - serviceID, scaleStr := parts[0], parts[1] - - // validate input arg scale number - scale, err := strconv.ParseUint(scaleStr, 10, 64) - if err != nil { - errs = append(errs, fmt.Sprintf("%s: invalid replicas value %s: %v", serviceID, scaleStr, err)) - continue - } - - if err := runServiceScale(ctx, dockerCli, serviceID, scale); err != nil { - errs = append(errs, fmt.Sprintf("%s: %v", serviceID, err)) - } else { - serviceIDs = append(serviceIDs, serviceID) - } - - } - - if len(serviceIDs) > 0 { - if !options.detach && versions.GreaterThanOrEqualTo(dockerCli.Client().ClientVersion(), "1.29") { - for _, serviceID := range serviceIDs { - if err := waitOnService(ctx, dockerCli, serviceID, false); err != nil { - errs = append(errs, fmt.Sprintf("%s: %v", serviceID, err)) - } - } - } - } - - if len(errs) == 0 { - return nil - } - return errors.Errorf(strings.Join(errs, "\n")) -} - -func runServiceScale(ctx context.Context, dockerCli command.Cli, serviceID string, scale uint64) error { - client := dockerCli.Client() - - service, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) - if err != nil { - return err - } - - serviceMode := &service.Spec.Mode - if serviceMode.Replicated == nil { - return errors.Errorf("scale can only be used with replicated mode") - } - - serviceMode.Replicated.Replicas = &scale - - response, err := client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) - if err != nil { - return err - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - - fmt.Fprintf(dockerCli.Out(), "%s scaled to %d\n", serviceID, scale) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/testdata/service-list-sort.golden b/vendor/github.com/docker/cli/cli/command/service/testdata/service-list-sort.golden deleted file mode 100644 index 3b0cb2144..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/testdata/service-list-sort.golden +++ /dev/null @@ -1,3 +0,0 @@ -service-1-foo -service-2-foo -service-10-foo diff --git a/vendor/github.com/docker/cli/cli/command/service/trust.go b/vendor/github.com/docker/cli/cli/command/service/trust.go deleted file mode 100644 index e1be1e203..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/trust.go +++ /dev/null @@ -1,87 +0,0 @@ -package service - -import ( - "encoding/hex" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/trust" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/registry" - "github.com/docker/notary/tuf/data" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "golang.org/x/net/context" -) - -func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm.ServiceSpec) error { - if !command.IsTrusted() { - // When not using content trust, digest resolution happens later when - // contacting the registry to retrieve image information. - return nil - } - - ref, err := reference.ParseAnyReference(service.TaskTemplate.ContainerSpec.Image) - if err != nil { - return errors.Wrapf(err, "invalid reference %s", service.TaskTemplate.ContainerSpec.Image) - } - - // If reference does not have digest (is not canonical nor image id) - if _, ok := ref.(reference.Digested); !ok { - namedRef, ok := ref.(reference.Named) - if !ok { - return errors.New("failed to resolve image digest using content trust: reference is not named") - } - namedRef = reference.TagNameOnly(namedRef) - taggedRef, ok := namedRef.(reference.NamedTagged) - if !ok { - return errors.New("failed to resolve image digest using content trust: reference is not tagged") - } - - resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef) - if err != nil { - return errors.Wrap(err, "failed to resolve image digest using content trust") - } - resolvedFamiliar := reference.FamiliarString(resolvedImage) - logrus.Debugf("resolved image tag to %s using content trust", resolvedFamiliar) - service.TaskTemplate.ContainerSpec.Image = resolvedFamiliar - } - - return nil -} - -func trustedResolveDigest(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) { - repoInfo, err := registry.ParseRepositoryInfo(ref) - if err != nil { - return nil, err - } - - authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index) - - notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull") - if err != nil { - return nil, errors.Wrap(err, "error establishing connection to trust repository") - } - - t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole) - if err != nil { - return nil, trust.NotaryError(repoInfo.Name.Name(), err) - } - // Only get the tag if it's in the top level targets role or the releases delegation role - // ignore it if it's in any other delegation roles - if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole { - return nil, trust.NotaryError(repoInfo.Name.Name(), errors.Errorf("No trust data for %s", reference.FamiliarString(ref))) - } - - logrus.Debugf("retrieving target for %s role\n", t.Role) - h, ok := t.Hashes["sha256"] - if !ok { - return nil, errors.New("no valid hash, expecting sha256") - } - - dgst := digest.NewDigestFromHex("sha256", hex.EncodeToString(h)) - - // Allow returning canonical reference with tag - return reference.WithDigest(ref, dgst) -} diff --git a/vendor/github.com/docker/cli/cli/command/service/update.go b/vendor/github.com/docker/cli/cli/command/service/update.go deleted file mode 100644 index 6ee0dfc74..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/update.go +++ /dev/null @@ -1,1043 +0,0 @@ -package service - -import ( - "fmt" - "sort" - "strings" - "time" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - mounttypes "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/client" - "github.com/docker/swarmkit/api/defaults" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -func newUpdateCommand(dockerCli command.Cli) *cobra.Command { - options := newServiceOptions() - - cmd := &cobra.Command{ - Use: "update [OPTIONS] SERVICE", - Short: "Update a service", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runUpdate(dockerCli, cmd.Flags(), options, args[0]) - }, - } - - flags := cmd.Flags() - flags.String("image", "", "Service image tag") - flags.Var(&ShlexOpt{}, "args", "Service command args") - flags.Bool(flagRollback, false, "Rollback to previous specification") - flags.SetAnnotation(flagRollback, "version", []string{"1.25"}) - flags.Bool("force", false, "Force update even if no changes require it") - flags.SetAnnotation("force", "version", []string{"1.25"}) - addServiceFlags(flags, options, nil) - - flags.Var(newListOptsVar(), flagEnvRemove, "Remove an environment variable") - flags.Var(newListOptsVar(), flagGroupRemove, "Remove a previously added supplementary user group from the container") - flags.SetAnnotation(flagGroupRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagLabelRemove, "Remove a label by its key") - flags.Var(newListOptsVar(), flagContainerLabelRemove, "Remove a container label by its key") - flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path") - // flags.Var(newListOptsVar().WithValidator(validatePublishRemove), flagPublishRemove, "Remove a published port by its target port") - flags.Var(&opts.PortOpt{}, flagPublishRemove, "Remove a published port by its target port") - flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint") - flags.Var(newListOptsVar(), flagDNSRemove, "Remove a custom DNS server") - flags.SetAnnotation(flagDNSRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagDNSOptionRemove, "Remove a DNS option") - flags.SetAnnotation(flagDNSOptionRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagDNSSearchRemove, "Remove a DNS search domain") - flags.SetAnnotation(flagDNSSearchRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagHostRemove, "Remove a custom host-to-IP mapping (host:ip)") - flags.SetAnnotation(flagHostRemove, "version", []string{"1.25"}) - flags.Var(&options.labels, flagLabelAdd, "Add or update a service label") - flags.Var(&options.containerLabels, flagContainerLabelAdd, "Add or update a container label") - flags.Var(&options.env, flagEnvAdd, "Add or update an environment variable") - flags.Var(newListOptsVar(), flagSecretRemove, "Remove a secret") - flags.SetAnnotation(flagSecretRemove, "version", []string{"1.25"}) - flags.Var(&options.secrets, flagSecretAdd, "Add or update a secret on a service") - flags.SetAnnotation(flagSecretAdd, "version", []string{"1.25"}) - - flags.Var(newListOptsVar(), flagConfigRemove, "Remove a configuration file") - flags.SetAnnotation(flagConfigRemove, "version", []string{"1.30"}) - flags.Var(&options.configs, flagConfigAdd, "Add or update a config file on a service") - flags.SetAnnotation(flagConfigAdd, "version", []string{"1.30"}) - - flags.Var(&options.mounts, flagMountAdd, "Add or update a mount on a service") - flags.Var(&options.constraints, flagConstraintAdd, "Add or update a placement constraint") - flags.Var(&options.placementPrefs, flagPlacementPrefAdd, "Add a placement preference") - flags.SetAnnotation(flagPlacementPrefAdd, "version", []string{"1.28"}) - flags.Var(&placementPrefOpts{}, flagPlacementPrefRemove, "Remove a placement preference") - flags.SetAnnotation(flagPlacementPrefRemove, "version", []string{"1.28"}) - flags.Var(&options.networks, flagNetworkAdd, "Add a network") - flags.SetAnnotation(flagNetworkAdd, "version", []string{"1.29"}) - flags.Var(newListOptsVar(), flagNetworkRemove, "Remove a network") - flags.SetAnnotation(flagNetworkRemove, "version", []string{"1.29"}) - flags.Var(&options.endpoint.publishPorts, flagPublishAdd, "Add or update a published port") - flags.Var(&options.groups, flagGroupAdd, "Add an additional supplementary user group to the container") - flags.SetAnnotation(flagGroupAdd, "version", []string{"1.25"}) - flags.Var(&options.dns, flagDNSAdd, "Add or update a custom DNS server") - flags.SetAnnotation(flagDNSAdd, "version", []string{"1.25"}) - flags.Var(&options.dnsOption, flagDNSOptionAdd, "Add or update a DNS option") - flags.SetAnnotation(flagDNSOptionAdd, "version", []string{"1.25"}) - flags.Var(&options.dnsSearch, flagDNSSearchAdd, "Add or update a custom DNS search domain") - flags.SetAnnotation(flagDNSSearchAdd, "version", []string{"1.25"}) - flags.Var(&options.hosts, flagHostAdd, "Add or update a custom host-to-IP mapping (host:ip)") - flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"}) - - return cmd -} - -func newListOptsVar() *opts.ListOpts { - return opts.NewListOptsRef(&[]string{}, nil) -} - -// nolint: gocyclo -func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error { - apiClient := dockerCli.Client() - ctx := context.Background() - - service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) - if err != nil { - return err - } - - rollback, err := flags.GetBool(flagRollback) - if err != nil { - return err - } - - // There are two ways to do user-requested rollback. The old way is - // client-side, but with a sufficiently recent daemon we prefer - // server-side, because it will honor the rollback parameters. - var ( - clientSideRollback bool - serverSideRollback bool - ) - - spec := &service.Spec - if rollback { - // Rollback can't be combined with other flags. - otherFlagsPassed := false - flags.VisitAll(func(f *pflag.Flag) { - if f.Name == flagRollback || f.Name == flagDetach || f.Name == flagQuiet { - return - } - if flags.Changed(f.Name) { - otherFlagsPassed = true - } - }) - if otherFlagsPassed { - return errors.New("other flags may not be combined with --rollback") - } - - if versions.LessThan(apiClient.ClientVersion(), "1.28") { - clientSideRollback = true - spec = service.PreviousSpec - if spec == nil { - return errors.Errorf("service does not have a previous specification to roll back to") - } - } else { - serverSideRollback = true - } - } - - updateOpts := types.ServiceUpdateOptions{} - if serverSideRollback { - updateOpts.Rollback = "previous" - } - - err = updateService(ctx, apiClient, flags, spec) - if err != nil { - return err - } - - if flags.Changed("image") { - if err := resolveServiceImageDigestContentTrust(dockerCli, spec); err != nil { - return err - } - if !options.noResolveImage && versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.30") { - updateOpts.QueryRegistry = true - } - } - - updatedSecrets, err := getUpdatedSecrets(apiClient, flags, spec.TaskTemplate.ContainerSpec.Secrets) - if err != nil { - return err - } - - spec.TaskTemplate.ContainerSpec.Secrets = updatedSecrets - - updatedConfigs, err := getUpdatedConfigs(apiClient, flags, spec.TaskTemplate.ContainerSpec.Configs) - if err != nil { - return err - } - - spec.TaskTemplate.ContainerSpec.Configs = updatedConfigs - - // only send auth if flag was set - sendAuth, err := flags.GetBool(flagRegistryAuth) - if err != nil { - return err - } - if sendAuth { - // Retrieve encoded auth token from the image reference - // This would be the old image if it didn't change in this update - image := spec.TaskTemplate.ContainerSpec.Image - encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) - if err != nil { - return err - } - updateOpts.EncodedRegistryAuth = encodedAuth - } else if clientSideRollback { - updateOpts.RegistryAuthFrom = types.RegistryAuthFromPreviousSpec - } else { - updateOpts.RegistryAuthFrom = types.RegistryAuthFromSpec - } - - response, err := apiClient.ServiceUpdate(ctx, service.ID, service.Version, *spec, updateOpts) - if err != nil { - return err - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID) - - if options.detach || versions.LessThan(apiClient.ClientVersion(), "1.29") { - return nil - } - - return waitOnService(ctx, dockerCli, serviceID, options.quiet) -} - -// nolint: gocyclo -func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { - updateString := func(flag string, field *string) { - if flags.Changed(flag) { - *field, _ = flags.GetString(flag) - } - } - - updateInt64Value := func(flag string, field *int64) { - if flags.Changed(flag) { - *field = flags.Lookup(flag).Value.(int64Value).Value() - } - } - - updateFloatValue := func(flag string, field *float32) { - if flags.Changed(flag) { - *field = flags.Lookup(flag).Value.(*floatValue).Value() - } - } - - updateDuration := func(flag string, field *time.Duration) { - if flags.Changed(flag) { - *field, _ = flags.GetDuration(flag) - } - } - - updateDurationOpt := func(flag string, field **time.Duration) { - if flags.Changed(flag) { - val := *flags.Lookup(flag).Value.(*opts.DurationOpt).Value() - *field = &val - } - } - - updateUint64 := func(flag string, field *uint64) { - if flags.Changed(flag) { - *field, _ = flags.GetUint64(flag) - } - } - - updateUint64Opt := func(flag string, field **uint64) { - if flags.Changed(flag) { - val := *flags.Lookup(flag).Value.(*Uint64Opt).Value() - *field = &val - } - } - - cspec := spec.TaskTemplate.ContainerSpec - task := &spec.TaskTemplate - - taskResources := func() *swarm.ResourceRequirements { - if task.Resources == nil { - task.Resources = &swarm.ResourceRequirements{} - } - return task.Resources - } - - updateLabels(flags, &spec.Labels) - updateContainerLabels(flags, &cspec.Labels) - updateString("image", &cspec.Image) - updateStringToSlice(flags, "args", &cspec.Args) - updateStringToSlice(flags, flagEntrypoint, &cspec.Command) - updateEnvironment(flags, &cspec.Env) - updateString(flagWorkdir, &cspec.Dir) - updateString(flagUser, &cspec.User) - updateString(flagHostname, &cspec.Hostname) - if err := updateMounts(flags, &cspec.Mounts); err != nil { - return err - } - - if flags.Changed(flagLimitCPU) || flags.Changed(flagLimitMemory) { - taskResources().Limits = &swarm.Resources{} - updateInt64Value(flagLimitCPU, &task.Resources.Limits.NanoCPUs) - updateInt64Value(flagLimitMemory, &task.Resources.Limits.MemoryBytes) - } - if flags.Changed(flagReserveCPU) || flags.Changed(flagReserveMemory) { - taskResources().Reservations = &swarm.Resources{} - updateInt64Value(flagReserveCPU, &task.Resources.Reservations.NanoCPUs) - updateInt64Value(flagReserveMemory, &task.Resources.Reservations.MemoryBytes) - } - - updateDurationOpt(flagStopGracePeriod, &cspec.StopGracePeriod) - - if anyChanged(flags, flagRestartCondition, flagRestartDelay, flagRestartMaxAttempts, flagRestartWindow) { - if task.RestartPolicy == nil { - task.RestartPolicy = defaultRestartPolicy() - } - if flags.Changed(flagRestartCondition) { - value, _ := flags.GetString(flagRestartCondition) - task.RestartPolicy.Condition = swarm.RestartPolicyCondition(value) - } - updateDurationOpt(flagRestartDelay, &task.RestartPolicy.Delay) - updateUint64Opt(flagRestartMaxAttempts, &task.RestartPolicy.MaxAttempts) - updateDurationOpt(flagRestartWindow, &task.RestartPolicy.Window) - } - - if anyChanged(flags, flagConstraintAdd, flagConstraintRemove) { - if task.Placement == nil { - task.Placement = &swarm.Placement{} - } - updatePlacementConstraints(flags, task.Placement) - } - - if anyChanged(flags, flagPlacementPrefAdd, flagPlacementPrefRemove) { - if task.Placement == nil { - task.Placement = &swarm.Placement{} - } - updatePlacementPreferences(flags, task.Placement) - } - - if anyChanged(flags, flagNetworkAdd, flagNetworkRemove) { - if err := updateNetworks(ctx, apiClient, flags, spec); err != nil { - return err - } - } - - if err := updateReplicas(flags, &spec.Mode); err != nil { - return err - } - - if anyChanged(flags, flagUpdateParallelism, flagUpdateDelay, flagUpdateMonitor, flagUpdateFailureAction, flagUpdateMaxFailureRatio, flagUpdateOrder) { - if spec.UpdateConfig == nil { - spec.UpdateConfig = updateConfigFromDefaults(defaults.Service.Update) - } - updateUint64(flagUpdateParallelism, &spec.UpdateConfig.Parallelism) - updateDuration(flagUpdateDelay, &spec.UpdateConfig.Delay) - updateDuration(flagUpdateMonitor, &spec.UpdateConfig.Monitor) - updateString(flagUpdateFailureAction, &spec.UpdateConfig.FailureAction) - updateFloatValue(flagUpdateMaxFailureRatio, &spec.UpdateConfig.MaxFailureRatio) - updateString(flagUpdateOrder, &spec.UpdateConfig.Order) - } - - if anyChanged(flags, flagRollbackParallelism, flagRollbackDelay, flagRollbackMonitor, flagRollbackFailureAction, flagRollbackMaxFailureRatio, flagRollbackOrder) { - if spec.RollbackConfig == nil { - spec.RollbackConfig = updateConfigFromDefaults(defaults.Service.Rollback) - } - updateUint64(flagRollbackParallelism, &spec.RollbackConfig.Parallelism) - updateDuration(flagRollbackDelay, &spec.RollbackConfig.Delay) - updateDuration(flagRollbackMonitor, &spec.RollbackConfig.Monitor) - updateString(flagRollbackFailureAction, &spec.RollbackConfig.FailureAction) - updateFloatValue(flagRollbackMaxFailureRatio, &spec.RollbackConfig.MaxFailureRatio) - updateString(flagRollbackOrder, &spec.RollbackConfig.Order) - } - - if flags.Changed(flagEndpointMode) { - value, _ := flags.GetString(flagEndpointMode) - if spec.EndpointSpec == nil { - spec.EndpointSpec = &swarm.EndpointSpec{} - } - spec.EndpointSpec.Mode = swarm.ResolutionMode(value) - } - - if anyChanged(flags, flagGroupAdd, flagGroupRemove) { - if err := updateGroups(flags, &cspec.Groups); err != nil { - return err - } - } - - if anyChanged(flags, flagPublishAdd, flagPublishRemove) { - if spec.EndpointSpec == nil { - spec.EndpointSpec = &swarm.EndpointSpec{} - } - if err := updatePorts(flags, &spec.EndpointSpec.Ports); err != nil { - return err - } - } - - if anyChanged(flags, flagDNSAdd, flagDNSRemove, flagDNSOptionAdd, flagDNSOptionRemove, flagDNSSearchAdd, flagDNSSearchRemove) { - if cspec.DNSConfig == nil { - cspec.DNSConfig = &swarm.DNSConfig{} - } - if err := updateDNSConfig(flags, &cspec.DNSConfig); err != nil { - return err - } - } - - if anyChanged(flags, flagHostAdd, flagHostRemove) { - if err := updateHosts(flags, &cspec.Hosts); err != nil { - return err - } - } - - if err := updateLogDriver(flags, &spec.TaskTemplate); err != nil { - return err - } - - force, err := flags.GetBool("force") - if err != nil { - return err - } - - if force { - spec.TaskTemplate.ForceUpdate++ - } - - if err := updateHealthcheck(flags, cspec); err != nil { - return err - } - - if flags.Changed(flagTTY) { - tty, err := flags.GetBool(flagTTY) - if err != nil { - return err - } - cspec.TTY = tty - } - - if flags.Changed(flagReadOnly) { - readOnly, err := flags.GetBool(flagReadOnly) - if err != nil { - return err - } - cspec.ReadOnly = readOnly - } - - updateString(flagStopSignal, &cspec.StopSignal) - - return nil -} - -func updateStringToSlice(flags *pflag.FlagSet, flag string, field *[]string) { - if !flags.Changed(flag) { - return - } - - *field = flags.Lookup(flag).Value.(*ShlexOpt).Value() -} - -func anyChanged(flags *pflag.FlagSet, fields ...string) bool { - for _, flag := range fields { - if flags.Changed(flag) { - return true - } - } - return false -} - -func updatePlacementConstraints(flags *pflag.FlagSet, placement *swarm.Placement) { - if flags.Changed(flagConstraintAdd) { - values := flags.Lookup(flagConstraintAdd).Value.(*opts.ListOpts).GetAll() - placement.Constraints = append(placement.Constraints, values...) - } - toRemove := buildToRemoveSet(flags, flagConstraintRemove) - - newConstraints := []string{} - for _, constraint := range placement.Constraints { - if _, exists := toRemove[constraint]; !exists { - newConstraints = append(newConstraints, constraint) - } - } - // Sort so that result is predictable. - sort.Strings(newConstraints) - - placement.Constraints = newConstraints -} - -func updatePlacementPreferences(flags *pflag.FlagSet, placement *swarm.Placement) { - var newPrefs []swarm.PlacementPreference - - if flags.Changed(flagPlacementPrefRemove) { - for _, existing := range placement.Preferences { - removed := false - for _, removal := range flags.Lookup(flagPlacementPrefRemove).Value.(*placementPrefOpts).prefs { - if removal.Spread != nil && existing.Spread != nil && removal.Spread.SpreadDescriptor == existing.Spread.SpreadDescriptor { - removed = true - break - } - } - if !removed { - newPrefs = append(newPrefs, existing) - } - } - } else { - newPrefs = placement.Preferences - } - - if flags.Changed(flagPlacementPrefAdd) { - newPrefs = append(newPrefs, - flags.Lookup(flagPlacementPrefAdd).Value.(*placementPrefOpts).prefs...) - } - - placement.Preferences = newPrefs -} - -func updateContainerLabels(flags *pflag.FlagSet, field *map[string]string) { - if flags.Changed(flagContainerLabelAdd) { - if *field == nil { - *field = map[string]string{} - } - - values := flags.Lookup(flagContainerLabelAdd).Value.(*opts.ListOpts).GetAll() - for key, value := range opts.ConvertKVStringsToMap(values) { - (*field)[key] = value - } - } - - if *field != nil && flags.Changed(flagContainerLabelRemove) { - toRemove := flags.Lookup(flagContainerLabelRemove).Value.(*opts.ListOpts).GetAll() - for _, label := range toRemove { - delete(*field, label) - } - } -} - -func updateLabels(flags *pflag.FlagSet, field *map[string]string) { - if flags.Changed(flagLabelAdd) { - if *field == nil { - *field = map[string]string{} - } - - values := flags.Lookup(flagLabelAdd).Value.(*opts.ListOpts).GetAll() - for key, value := range opts.ConvertKVStringsToMap(values) { - (*field)[key] = value - } - } - - if *field != nil && flags.Changed(flagLabelRemove) { - toRemove := flags.Lookup(flagLabelRemove).Value.(*opts.ListOpts).GetAll() - for _, label := range toRemove { - delete(*field, label) - } - } -} - -func updateEnvironment(flags *pflag.FlagSet, field *[]string) { - if flags.Changed(flagEnvAdd) { - envSet := map[string]string{} - for _, v := range *field { - envSet[envKey(v)] = v - } - - value := flags.Lookup(flagEnvAdd).Value.(*opts.ListOpts) - for _, v := range value.GetAll() { - envSet[envKey(v)] = v - } - - *field = []string{} - for _, v := range envSet { - *field = append(*field, v) - } - } - - toRemove := buildToRemoveSet(flags, flagEnvRemove) - *field = removeItems(*field, toRemove, envKey) -} - -func getUpdatedSecrets(apiClient client.SecretAPIClient, flags *pflag.FlagSet, secrets []*swarm.SecretReference) ([]*swarm.SecretReference, error) { - newSecrets := []*swarm.SecretReference{} - - toRemove := buildToRemoveSet(flags, flagSecretRemove) - for _, secret := range secrets { - if _, exists := toRemove[secret.SecretName]; !exists { - newSecrets = append(newSecrets, secret) - } - } - - if flags.Changed(flagSecretAdd) { - values := flags.Lookup(flagSecretAdd).Value.(*opts.SecretOpt).Value() - - addSecrets, err := ParseSecrets(apiClient, values) - if err != nil { - return nil, err - } - newSecrets = append(newSecrets, addSecrets...) - } - - return newSecrets, nil -} - -func getUpdatedConfigs(apiClient client.ConfigAPIClient, flags *pflag.FlagSet, configs []*swarm.ConfigReference) ([]*swarm.ConfigReference, error) { - newConfigs := []*swarm.ConfigReference{} - - toRemove := buildToRemoveSet(flags, flagConfigRemove) - for _, config := range configs { - if _, exists := toRemove[config.ConfigName]; !exists { - newConfigs = append(newConfigs, config) - } - } - - if flags.Changed(flagConfigAdd) { - values := flags.Lookup(flagConfigAdd).Value.(*opts.ConfigOpt).Value() - - addConfigs, err := ParseConfigs(apiClient, values) - if err != nil { - return nil, err - } - newConfigs = append(newConfigs, addConfigs...) - } - - return newConfigs, nil -} - -func envKey(value string) string { - kv := strings.SplitN(value, "=", 2) - return kv[0] -} - -func buildToRemoveSet(flags *pflag.FlagSet, flag string) map[string]struct{} { - var empty struct{} - toRemove := make(map[string]struct{}) - - if !flags.Changed(flag) { - return toRemove - } - - toRemoveSlice := flags.Lookup(flag).Value.(*opts.ListOpts).GetAll() - for _, key := range toRemoveSlice { - toRemove[key] = empty - } - return toRemove -} - -func removeItems( - seq []string, - toRemove map[string]struct{}, - keyFunc func(string) string, -) []string { - newSeq := []string{} - for _, item := range seq { - if _, exists := toRemove[keyFunc(item)]; !exists { - newSeq = append(newSeq, item) - } - } - return newSeq -} - -type byMountSource []mounttypes.Mount - -func (m byMountSource) Len() int { return len(m) } -func (m byMountSource) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m byMountSource) Less(i, j int) bool { - a, b := m[i], m[j] - - if a.Source == b.Source { - return a.Target < b.Target - } - - return a.Source < b.Source -} - -func updateMounts(flags *pflag.FlagSet, mounts *[]mounttypes.Mount) error { - mountsByTarget := map[string]mounttypes.Mount{} - - if flags.Changed(flagMountAdd) { - values := flags.Lookup(flagMountAdd).Value.(*opts.MountOpt).Value() - for _, mount := range values { - if _, ok := mountsByTarget[mount.Target]; ok { - return errors.Errorf("duplicate mount target") - } - mountsByTarget[mount.Target] = mount - } - } - - // Add old list of mount points minus updated one. - for _, mount := range *mounts { - if _, ok := mountsByTarget[mount.Target]; !ok { - mountsByTarget[mount.Target] = mount - } - } - - newMounts := []mounttypes.Mount{} - - toRemove := buildToRemoveSet(flags, flagMountRemove) - - for _, mount := range mountsByTarget { - if _, exists := toRemove[mount.Target]; !exists { - newMounts = append(newMounts, mount) - } - } - sort.Sort(byMountSource(newMounts)) - *mounts = newMounts - return nil -} - -func updateGroups(flags *pflag.FlagSet, groups *[]string) error { - if flags.Changed(flagGroupAdd) { - values := flags.Lookup(flagGroupAdd).Value.(*opts.ListOpts).GetAll() - *groups = append(*groups, values...) - } - toRemove := buildToRemoveSet(flags, flagGroupRemove) - - newGroups := []string{} - for _, group := range *groups { - if _, exists := toRemove[group]; !exists { - newGroups = append(newGroups, group) - } - } - // Sort so that result is predictable. - sort.Strings(newGroups) - - *groups = newGroups - return nil -} - -func removeDuplicates(entries []string) []string { - hit := map[string]bool{} - newEntries := []string{} - for _, v := range entries { - if !hit[v] { - newEntries = append(newEntries, v) - hit[v] = true - } - } - return newEntries -} - -func updateDNSConfig(flags *pflag.FlagSet, config **swarm.DNSConfig) error { - newConfig := &swarm.DNSConfig{} - - nameservers := (*config).Nameservers - if flags.Changed(flagDNSAdd) { - values := flags.Lookup(flagDNSAdd).Value.(*opts.ListOpts).GetAll() - nameservers = append(nameservers, values...) - } - nameservers = removeDuplicates(nameservers) - toRemove := buildToRemoveSet(flags, flagDNSRemove) - for _, nameserver := range nameservers { - if _, exists := toRemove[nameserver]; !exists { - newConfig.Nameservers = append(newConfig.Nameservers, nameserver) - - } - } - // Sort so that result is predictable. - sort.Strings(newConfig.Nameservers) - - search := (*config).Search - if flags.Changed(flagDNSSearchAdd) { - values := flags.Lookup(flagDNSSearchAdd).Value.(*opts.ListOpts).GetAll() - search = append(search, values...) - } - search = removeDuplicates(search) - toRemove = buildToRemoveSet(flags, flagDNSSearchRemove) - for _, entry := range search { - if _, exists := toRemove[entry]; !exists { - newConfig.Search = append(newConfig.Search, entry) - } - } - // Sort so that result is predictable. - sort.Strings(newConfig.Search) - - options := (*config).Options - if flags.Changed(flagDNSOptionAdd) { - values := flags.Lookup(flagDNSOptionAdd).Value.(*opts.ListOpts).GetAll() - options = append(options, values...) - } - options = removeDuplicates(options) - toRemove = buildToRemoveSet(flags, flagDNSOptionRemove) - for _, option := range options { - if _, exists := toRemove[option]; !exists { - newConfig.Options = append(newConfig.Options, option) - } - } - // Sort so that result is predictable. - sort.Strings(newConfig.Options) - - *config = newConfig - return nil -} - -type byPortConfig []swarm.PortConfig - -func (r byPortConfig) Len() int { return len(r) } -func (r byPortConfig) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byPortConfig) Less(i, j int) bool { - // We convert PortConfig into `port/protocol`, e.g., `80/tcp` - // In updatePorts we already filter out with map so there is duplicate entries - return portConfigToString(&r[i]) < portConfigToString(&r[j]) -} - -func portConfigToString(portConfig *swarm.PortConfig) string { - protocol := portConfig.Protocol - mode := portConfig.PublishMode - return fmt.Sprintf("%v:%v/%s/%s", portConfig.PublishedPort, portConfig.TargetPort, protocol, mode) -} - -func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) error { - // The key of the map is `port/protocol`, e.g., `80/tcp` - portSet := map[string]swarm.PortConfig{} - - // Build the current list of portConfig - for _, entry := range *portConfig { - if _, ok := portSet[portConfigToString(&entry)]; !ok { - portSet[portConfigToString(&entry)] = entry - } - } - - newPorts := []swarm.PortConfig{} - - // Clean current ports - toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.PortOpt).Value() -portLoop: - for _, port := range portSet { - for _, pConfig := range toRemove { - if equalProtocol(port.Protocol, pConfig.Protocol) && - port.TargetPort == pConfig.TargetPort && - equalPublishMode(port.PublishMode, pConfig.PublishMode) { - continue portLoop - } - } - - newPorts = append(newPorts, port) - } - - // Check to see if there are any conflict in flags. - if flags.Changed(flagPublishAdd) { - ports := flags.Lookup(flagPublishAdd).Value.(*opts.PortOpt).Value() - - for _, port := range ports { - if _, ok := portSet[portConfigToString(&port)]; ok { - continue - } - //portSet[portConfigToString(&port)] = port - newPorts = append(newPorts, port) - } - } - - // Sort the PortConfig to avoid unnecessary updates - sort.Sort(byPortConfig(newPorts)) - *portConfig = newPorts - return nil -} - -func equalProtocol(prot1, prot2 swarm.PortConfigProtocol) bool { - return prot1 == prot2 || - (prot1 == swarm.PortConfigProtocol("") && prot2 == swarm.PortConfigProtocolTCP) || - (prot2 == swarm.PortConfigProtocol("") && prot1 == swarm.PortConfigProtocolTCP) -} - -func equalPublishMode(mode1, mode2 swarm.PortConfigPublishMode) bool { - return mode1 == mode2 || - (mode1 == swarm.PortConfigPublishMode("") && mode2 == swarm.PortConfigPublishModeIngress) || - (mode2 == swarm.PortConfigPublishMode("") && mode1 == swarm.PortConfigPublishModeIngress) -} - -func updateReplicas(flags *pflag.FlagSet, serviceMode *swarm.ServiceMode) error { - if !flags.Changed(flagReplicas) { - return nil - } - - if serviceMode == nil || serviceMode.Replicated == nil { - return errors.Errorf("replicas can only be used with replicated mode") - } - serviceMode.Replicated.Replicas = flags.Lookup(flagReplicas).Value.(*Uint64Opt).Value() - return nil -} - -func updateHosts(flags *pflag.FlagSet, hosts *[]string) error { - // Combine existing Hosts (in swarmkit format) with the host to add (convert to swarmkit format) - if flags.Changed(flagHostAdd) { - values := convertExtraHostsToSwarmHosts(flags.Lookup(flagHostAdd).Value.(*opts.ListOpts).GetAll()) - *hosts = append(*hosts, values...) - } - // Remove duplicate - *hosts = removeDuplicates(*hosts) - - keysToRemove := make(map[string]struct{}) - if flags.Changed(flagHostRemove) { - var empty struct{} - extraHostsToRemove := flags.Lookup(flagHostRemove).Value.(*opts.ListOpts).GetAll() - for _, entry := range extraHostsToRemove { - key := strings.SplitN(entry, ":", 2)[0] - keysToRemove[key] = empty - } - } - - newHosts := []string{} - for _, entry := range *hosts { - // Since this is in swarmkit format, we need to find the key, which is canonical_hostname of: - // IP_address canonical_hostname [aliases...] - parts := strings.Fields(entry) - if len(parts) > 1 { - key := parts[1] - if _, exists := keysToRemove[key]; !exists { - newHosts = append(newHosts, entry) - } - } else { - newHosts = append(newHosts, entry) - } - } - - // Sort so that result is predictable. - sort.Strings(newHosts) - - *hosts = newHosts - return nil -} - -// updateLogDriver updates the log driver only if the log driver flag is set. -// All options will be replaced with those provided on the command line. -func updateLogDriver(flags *pflag.FlagSet, taskTemplate *swarm.TaskSpec) error { - if !flags.Changed(flagLogDriver) { - return nil - } - - name, err := flags.GetString(flagLogDriver) - if err != nil { - return err - } - - if name == "" { - return nil - } - - taskTemplate.LogDriver = &swarm.Driver{ - Name: name, - Options: opts.ConvertKVStringsToMap(flags.Lookup(flagLogOpt).Value.(*opts.ListOpts).GetAll()), - } - - return nil -} - -func updateHealthcheck(flags *pflag.FlagSet, containerSpec *swarm.ContainerSpec) error { - if !anyChanged(flags, flagNoHealthcheck, flagHealthCmd, flagHealthInterval, flagHealthRetries, flagHealthTimeout, flagHealthStartPeriod) { - return nil - } - if containerSpec.Healthcheck == nil { - containerSpec.Healthcheck = &container.HealthConfig{} - } - noHealthcheck, err := flags.GetBool(flagNoHealthcheck) - if err != nil { - return err - } - if noHealthcheck { - if !anyChanged(flags, flagHealthCmd, flagHealthInterval, flagHealthRetries, flagHealthTimeout, flagHealthStartPeriod) { - containerSpec.Healthcheck = &container.HealthConfig{ - Test: []string{"NONE"}, - } - return nil - } - return errors.Errorf("--%s conflicts with --health-* options", flagNoHealthcheck) - } - if len(containerSpec.Healthcheck.Test) > 0 && containerSpec.Healthcheck.Test[0] == "NONE" { - containerSpec.Healthcheck.Test = nil - } - if flags.Changed(flagHealthInterval) { - val := *flags.Lookup(flagHealthInterval).Value.(*opts.PositiveDurationOpt).Value() - containerSpec.Healthcheck.Interval = val - } - if flags.Changed(flagHealthTimeout) { - val := *flags.Lookup(flagHealthTimeout).Value.(*opts.PositiveDurationOpt).Value() - containerSpec.Healthcheck.Timeout = val - } - if flags.Changed(flagHealthStartPeriod) { - val := *flags.Lookup(flagHealthStartPeriod).Value.(*opts.PositiveDurationOpt).Value() - containerSpec.Healthcheck.StartPeriod = val - } - if flags.Changed(flagHealthRetries) { - containerSpec.Healthcheck.Retries, _ = flags.GetInt(flagHealthRetries) - } - if flags.Changed(flagHealthCmd) { - cmd, _ := flags.GetString(flagHealthCmd) - if cmd != "" { - containerSpec.Healthcheck.Test = []string{"CMD-SHELL", cmd} - } else { - containerSpec.Healthcheck.Test = nil - } - } - return nil -} - -type byNetworkTarget []swarm.NetworkAttachmentConfig - -func (m byNetworkTarget) Len() int { return len(m) } -func (m byNetworkTarget) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m byNetworkTarget) Less(i, j int) bool { - return m[i].Target < m[j].Target -} - -func updateNetworks(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { - // spec.TaskTemplate.Networks takes precedence over the deprecated - // spec.Networks field. If spec.Network is in use, we'll migrate those - // values to spec.TaskTemplate.Networks. - specNetworks := spec.TaskTemplate.Networks - if len(specNetworks) == 0 { - specNetworks = spec.Networks - } - spec.Networks = nil - - toRemove := buildToRemoveSet(flags, flagNetworkRemove) - idsToRemove := make(map[string]struct{}) - for networkIDOrName := range toRemove { - network, err := apiClient.NetworkInspect(ctx, networkIDOrName, types.NetworkInspectOptions{Scope: "swarm"}) - if err != nil { - return err - } - idsToRemove[network.ID] = struct{}{} - } - - existingNetworks := make(map[string]struct{}) - var newNetworks []swarm.NetworkAttachmentConfig - for _, network := range specNetworks { - if _, exists := idsToRemove[network.Target]; exists { - continue - } - - newNetworks = append(newNetworks, network) - existingNetworks[network.Target] = struct{}{} - } - - if flags.Changed(flagNetworkAdd) { - values := flags.Lookup(flagNetworkAdd).Value.(*opts.NetworkOpt) - networks, err := convertNetworks(ctx, apiClient, *values) - if err != nil { - return err - } - for _, network := range networks { - if _, exists := existingNetworks[network.Target]; exists { - return errors.Errorf("service is already attached to network %s", network.Target) - } - newNetworks = append(newNetworks, network) - existingNetworks[network.Target] = struct{}{} - } - } - - sort.Sort(byNetworkTarget(newNetworks)) - - spec.TaskTemplate.Networks = newNetworks - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/update_test.go b/vendor/github.com/docker/cli/cli/command/service/update_test.go deleted file mode 100644 index 69e5fa1b1..000000000 --- a/vendor/github.com/docker/cli/cli/command/service/update_test.go +++ /dev/null @@ -1,508 +0,0 @@ -package service - -import ( - "reflect" - "sort" - "testing" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - mounttypes "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/context" -) - -func TestUpdateServiceArgs(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("args", "the \"new args\"") - - spec := &swarm.ServiceSpec{ - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{}, - }, - } - cspec := spec.TaskTemplate.ContainerSpec - cspec.Args = []string{"old", "args"} - - updateService(nil, nil, flags, spec) - assert.Equal(t, []string{"the", "new args"}, cspec.Args) -} - -func TestUpdateLabels(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("label-add", "toadd=newlabel") - flags.Set("label-rm", "toremove") - - labels := map[string]string{ - "toremove": "thelabeltoremove", - "tokeep": "value", - } - - updateLabels(flags, &labels) - assert.Len(t, labels, 2) - assert.Equal(t, "value", labels["tokeep"]) - assert.Equal(t, "newlabel", labels["toadd"]) -} - -func TestUpdateLabelsRemoveALabelThatDoesNotExist(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("label-rm", "dne") - - labels := map[string]string{"foo": "theoldlabel"} - updateLabels(flags, &labels) - assert.Len(t, labels, 1) -} - -func TestUpdatePlacementConstraints(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("constraint-add", "node=toadd") - flags.Set("constraint-rm", "node!=toremove") - - placement := &swarm.Placement{ - Constraints: []string{"node!=toremove", "container=tokeep"}, - } - - updatePlacementConstraints(flags, placement) - require.Len(t, placement.Constraints, 2) - assert.Equal(t, "container=tokeep", placement.Constraints[0]) - assert.Equal(t, "node=toadd", placement.Constraints[1]) -} - -func TestUpdatePlacementPrefs(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("placement-pref-add", "spread=node.labels.dc") - flags.Set("placement-pref-rm", "spread=node.labels.rack") - - placement := &swarm.Placement{ - Preferences: []swarm.PlacementPreference{ - { - Spread: &swarm.SpreadOver{ - SpreadDescriptor: "node.labels.rack", - }, - }, - { - Spread: &swarm.SpreadOver{ - SpreadDescriptor: "node.labels.row", - }, - }, - }, - } - - updatePlacementPreferences(flags, placement) - require.Len(t, placement.Preferences, 2) - assert.Equal(t, "node.labels.row", placement.Preferences[0].Spread.SpreadDescriptor) - assert.Equal(t, "node.labels.dc", placement.Preferences[1].Spread.SpreadDescriptor) -} - -func TestUpdateEnvironment(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("env-add", "toadd=newenv") - flags.Set("env-rm", "toremove") - - envs := []string{"toremove=theenvtoremove", "tokeep=value"} - - updateEnvironment(flags, &envs) - require.Len(t, envs, 2) - // Order has been removed in updateEnvironment (map) - sort.Strings(envs) - assert.Equal(t, "toadd=newenv", envs[0]) - assert.Equal(t, "tokeep=value", envs[1]) -} - -func TestUpdateEnvironmentWithDuplicateValues(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("env-add", "foo=newenv") - flags.Set("env-add", "foo=dupe") - flags.Set("env-rm", "foo") - - envs := []string{"foo=value"} - - updateEnvironment(flags, &envs) - assert.Len(t, envs, 0) -} - -func TestUpdateEnvironmentWithDuplicateKeys(t *testing.T) { - // Test case for #25404 - flags := newUpdateCommand(nil).Flags() - flags.Set("env-add", "A=b") - - envs := []string{"A=c"} - - updateEnvironment(flags, &envs) - require.Len(t, envs, 1) - assert.Equal(t, "A=b", envs[0]) -} - -func TestUpdateGroups(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("group-add", "wheel") - flags.Set("group-add", "docker") - flags.Set("group-rm", "root") - flags.Set("group-add", "foo") - flags.Set("group-rm", "docker") - - groups := []string{"bar", "root"} - - updateGroups(flags, &groups) - require.Len(t, groups, 3) - assert.Equal(t, "bar", groups[0]) - assert.Equal(t, "foo", groups[1]) - assert.Equal(t, "wheel", groups[2]) -} - -func TestUpdateDNSConfig(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - - // IPv4, with duplicates - flags.Set("dns-add", "1.1.1.1") - flags.Set("dns-add", "1.1.1.1") - flags.Set("dns-add", "2.2.2.2") - flags.Set("dns-rm", "3.3.3.3") - flags.Set("dns-rm", "2.2.2.2") - // IPv6 - flags.Set("dns-add", "2001:db8:abc8::1") - // Invalid dns record - assert.EqualError(t, flags.Set("dns-add", "x.y.z.w"), "x.y.z.w is not an ip address") - - // domains with duplicates - flags.Set("dns-search-add", "example.com") - flags.Set("dns-search-add", "example.com") - flags.Set("dns-search-add", "example.org") - flags.Set("dns-search-rm", "example.org") - // Invalid dns search domain - assert.EqualError(t, flags.Set("dns-search-add", "example$com"), "example$com is not a valid domain") - - flags.Set("dns-option-add", "ndots:9") - flags.Set("dns-option-rm", "timeout:3") - - config := &swarm.DNSConfig{ - Nameservers: []string{"3.3.3.3", "5.5.5.5"}, - Search: []string{"localdomain"}, - Options: []string{"timeout:3"}, - } - - updateDNSConfig(flags, &config) - - require.Len(t, config.Nameservers, 3) - assert.Equal(t, "1.1.1.1", config.Nameservers[0]) - assert.Equal(t, "2001:db8:abc8::1", config.Nameservers[1]) - assert.Equal(t, "5.5.5.5", config.Nameservers[2]) - - require.Len(t, config.Search, 2) - assert.Equal(t, "example.com", config.Search[0]) - assert.Equal(t, "localdomain", config.Search[1]) - - require.Len(t, config.Options, 1) - assert.Equal(t, config.Options[0], "ndots:9") -} - -func TestUpdateMounts(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("mount-add", "type=volume,source=vol2,target=/toadd") - flags.Set("mount-rm", "/toremove") - - mounts := []mounttypes.Mount{ - {Target: "/toremove", Source: "vol1", Type: mounttypes.TypeBind}, - {Target: "/tokeep", Source: "vol3", Type: mounttypes.TypeBind}, - } - - updateMounts(flags, &mounts) - require.Len(t, mounts, 2) - assert.Equal(t, "/toadd", mounts[0].Target) - assert.Equal(t, "/tokeep", mounts[1].Target) -} - -func TestUpdateMountsWithDuplicateMounts(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("mount-add", "type=volume,source=vol4,target=/toadd") - - mounts := []mounttypes.Mount{ - {Target: "/tokeep1", Source: "vol1", Type: mounttypes.TypeBind}, - {Target: "/toadd", Source: "vol2", Type: mounttypes.TypeBind}, - {Target: "/tokeep2", Source: "vol3", Type: mounttypes.TypeBind}, - } - - updateMounts(flags, &mounts) - require.Len(t, mounts, 3) - assert.Equal(t, "/tokeep1", mounts[0].Target) - assert.Equal(t, "/tokeep2", mounts[1].Target) - assert.Equal(t, "/toadd", mounts[2].Target) -} - -func TestUpdatePorts(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("publish-add", "1000:1000") - flags.Set("publish-rm", "333/udp") - - portConfigs := []swarm.PortConfig{ - {TargetPort: 333, Protocol: swarm.PortConfigProtocolUDP}, - {TargetPort: 555}, - } - - err := updatePorts(flags, &portConfigs) - assert.NoError(t, err) - require.Len(t, portConfigs, 2) - // Do a sort to have the order (might have changed by map) - targetPorts := []int{int(portConfigs[0].TargetPort), int(portConfigs[1].TargetPort)} - sort.Ints(targetPorts) - assert.Equal(t, 555, targetPorts[0]) - assert.Equal(t, 1000, targetPorts[1]) -} - -func TestUpdatePortsDuplicate(t *testing.T) { - // Test case for #25375 - flags := newUpdateCommand(nil).Flags() - flags.Set("publish-add", "80:80") - - portConfigs := []swarm.PortConfig{ - { - TargetPort: 80, - PublishedPort: 80, - Protocol: swarm.PortConfigProtocolTCP, - PublishMode: swarm.PortConfigPublishModeIngress, - }, - } - - err := updatePorts(flags, &portConfigs) - assert.NoError(t, err) - require.Len(t, portConfigs, 1) - assert.Equal(t, uint32(80), portConfigs[0].TargetPort) -} - -func TestUpdateHealthcheckTable(t *testing.T) { - type test struct { - flags [][2]string - initial *container.HealthConfig - expected *container.HealthConfig - err string - } - testCases := []test{ - { - flags: [][2]string{{"no-healthcheck", "true"}}, - initial: &container.HealthConfig{Test: []string{"CMD-SHELL", "cmd1"}, Retries: 10}, - expected: &container.HealthConfig{Test: []string{"NONE"}}, - }, - { - flags: [][2]string{{"health-cmd", "cmd1"}}, - initial: &container.HealthConfig{Test: []string{"NONE"}}, - expected: &container.HealthConfig{Test: []string{"CMD-SHELL", "cmd1"}}, - }, - { - flags: [][2]string{{"health-retries", "10"}}, - initial: &container.HealthConfig{Test: []string{"NONE"}}, - expected: &container.HealthConfig{Retries: 10}, - }, - { - flags: [][2]string{{"health-retries", "10"}}, - initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}}, - expected: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Retries: 10}, - }, - { - flags: [][2]string{{"health-interval", "1m"}}, - initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}}, - expected: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Interval: time.Minute}, - }, - { - flags: [][2]string{{"health-cmd", ""}}, - initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Retries: 10}, - expected: &container.HealthConfig{Retries: 10}, - }, - { - flags: [][2]string{{"health-retries", "0"}}, - initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, Retries: 10}, - expected: &container.HealthConfig{Test: []string{"CMD", "cmd1"}}, - }, - { - flags: [][2]string{{"health-start-period", "1m"}}, - initial: &container.HealthConfig{Test: []string{"CMD", "cmd1"}}, - expected: &container.HealthConfig{Test: []string{"CMD", "cmd1"}, StartPeriod: time.Minute}, - }, - { - flags: [][2]string{{"health-cmd", "cmd1"}, {"no-healthcheck", "true"}}, - err: "--no-healthcheck conflicts with --health-* options", - }, - { - flags: [][2]string{{"health-interval", "10m"}, {"no-healthcheck", "true"}}, - err: "--no-healthcheck conflicts with --health-* options", - }, - { - flags: [][2]string{{"health-timeout", "1m"}, {"no-healthcheck", "true"}}, - err: "--no-healthcheck conflicts with --health-* options", - }, - } - for i, c := range testCases { - flags := newUpdateCommand(nil).Flags() - for _, flag := range c.flags { - flags.Set(flag[0], flag[1]) - } - cspec := &swarm.ContainerSpec{ - Healthcheck: c.initial, - } - err := updateHealthcheck(flags, cspec) - if c.err != "" { - assert.EqualError(t, err, c.err) - } else { - assert.NoError(t, err) - if !reflect.DeepEqual(cspec.Healthcheck, c.expected) { - t.Errorf("incorrect result for test %d, expected health config:\n\t%#v\ngot:\n\t%#v", i, c.expected, cspec.Healthcheck) - } - } - } -} - -func TestUpdateHosts(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("host-add", "example.net:2.2.2.2") - flags.Set("host-add", "ipv6.net:2001:db8:abc8::1") - // remove with ipv6 should work - flags.Set("host-rm", "example.net:2001:db8:abc8::1") - // just hostname should work as well - flags.Set("host-rm", "example.net") - // bad format error - assert.EqualError(t, flags.Set("host-add", "$example.com$"), `bad format for add-host: "$example.com$"`) - - hosts := []string{"1.2.3.4 example.com", "4.3.2.1 example.org", "2001:db8:abc8::1 example.net"} - - updateHosts(flags, &hosts) - require.Len(t, hosts, 3) - assert.Equal(t, "1.2.3.4 example.com", hosts[0]) - assert.Equal(t, "2001:db8:abc8::1 ipv6.net", hosts[1]) - assert.Equal(t, "4.3.2.1 example.org", hosts[2]) -} - -func TestUpdatePortsRmWithProtocol(t *testing.T) { - flags := newUpdateCommand(nil).Flags() - flags.Set("publish-add", "8081:81") - flags.Set("publish-add", "8082:82") - flags.Set("publish-rm", "80") - flags.Set("publish-rm", "81/tcp") - flags.Set("publish-rm", "82/udp") - - portConfigs := []swarm.PortConfig{ - { - TargetPort: 80, - PublishedPort: 8080, - Protocol: swarm.PortConfigProtocolTCP, - PublishMode: swarm.PortConfigPublishModeIngress, - }, - } - - err := updatePorts(flags, &portConfigs) - assert.NoError(t, err) - require.Len(t, portConfigs, 2) - assert.Equal(t, uint32(81), portConfigs[0].TargetPort) - assert.Equal(t, uint32(82), portConfigs[1].TargetPort) -} - -type secretAPIClientMock struct { - listResult []swarm.Secret -} - -func (s secretAPIClientMock) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) { - return s.listResult, nil -} -func (s secretAPIClientMock) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (types.SecretCreateResponse, error) { - return types.SecretCreateResponse{}, nil -} -func (s secretAPIClientMock) SecretRemove(ctx context.Context, id string) error { - return nil -} -func (s secretAPIClientMock) SecretInspectWithRaw(ctx context.Context, name string) (swarm.Secret, []byte, error) { - return swarm.Secret{}, []byte{}, nil -} -func (s secretAPIClientMock) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error { - return nil -} - -// TestUpdateSecretUpdateInPlace tests the ability to update the "target" of an secret with "docker service update" -// by combining "--secret-rm" and "--secret-add" for the same secret. -func TestUpdateSecretUpdateInPlace(t *testing.T) { - apiClient := secretAPIClientMock{ - listResult: []swarm.Secret{ - { - ID: "tn9qiblgnuuut11eufquw5dev", - Spec: swarm.SecretSpec{Annotations: swarm.Annotations{Name: "foo"}}, - }, - }, - } - - flags := newUpdateCommand(nil).Flags() - flags.Set("secret-add", "source=foo,target=foo2") - flags.Set("secret-rm", "foo") - - secrets := []*swarm.SecretReference{ - { - File: &swarm.SecretReferenceFileTarget{ - Name: "foo", - UID: "0", - GID: "0", - Mode: 292, - }, - SecretID: "tn9qiblgnuuut11eufquw5dev", - SecretName: "foo", - }, - } - - updatedSecrets, err := getUpdatedSecrets(apiClient, flags, secrets) - - assert.NoError(t, err) - require.Len(t, updatedSecrets, 1) - assert.Equal(t, "tn9qiblgnuuut11eufquw5dev", updatedSecrets[0].SecretID) - assert.Equal(t, "foo", updatedSecrets[0].SecretName) - assert.Equal(t, "foo2", updatedSecrets[0].File.Name) -} - -func TestUpdateReadOnly(t *testing.T) { - spec := &swarm.ServiceSpec{ - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{}, - }, - } - cspec := spec.TaskTemplate.ContainerSpec - - // Update with --read-only=true, changed to true - flags := newUpdateCommand(nil).Flags() - flags.Set("read-only", "true") - updateService(nil, nil, flags, spec) - assert.True(t, cspec.ReadOnly) - - // Update without --read-only, no change - flags = newUpdateCommand(nil).Flags() - updateService(nil, nil, flags, spec) - assert.True(t, cspec.ReadOnly) - - // Update with --read-only=false, changed to false - flags = newUpdateCommand(nil).Flags() - flags.Set("read-only", "false") - updateService(nil, nil, flags, spec) - assert.False(t, cspec.ReadOnly) -} - -func TestUpdateStopSignal(t *testing.T) { - spec := &swarm.ServiceSpec{ - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{}, - }, - } - cspec := spec.TaskTemplate.ContainerSpec - - // Update with --stop-signal=SIGUSR1 - flags := newUpdateCommand(nil).Flags() - flags.Set("stop-signal", "SIGUSR1") - updateService(nil, nil, flags, spec) - assert.Equal(t, "SIGUSR1", cspec.StopSignal) - - // Update without --stop-signal, no change - flags = newUpdateCommand(nil).Flags() - updateService(nil, nil, flags, spec) - assert.Equal(t, "SIGUSR1", cspec.StopSignal) - - // Update with --stop-signal=SIGWINCH - flags = newUpdateCommand(nil).Flags() - flags.Set("stop-signal", "SIGWINCH") - updateService(nil, nil, flags, spec) - assert.Equal(t, "SIGWINCH", cspec.StopSignal) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/client_test.go b/vendor/github.com/docker/cli/cli/command/stack/client_test.go deleted file mode 100644 index bcb92db6c..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/client_test.go +++ /dev/null @@ -1,239 +0,0 @@ -package stack - -import ( - "strings" - - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/docker/api" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - - version string - - services []string - networks []string - secrets []string - configs []string - - removedServices []string - removedNetworks []string - removedSecrets []string - removedConfigs []string - - serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error) - networkListFunc func(options types.NetworkListOptions) ([]types.NetworkResource, error) - secretListFunc func(options types.SecretListOptions) ([]swarm.Secret, error) - configListFunc func(options types.ConfigListOptions) ([]swarm.Config, error) - nodeListFunc func(options types.NodeListOptions) ([]swarm.Node, error) - taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error) - nodeInspectWithRaw func(ref string) (swarm.Node, []byte, error) - - serviceUpdateFunc func(serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) - - serviceRemoveFunc func(serviceID string) error - networkRemoveFunc func(networkID string) error - secretRemoveFunc func(secretID string) error - configRemoveFunc func(configID string) error -} - -func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) { - return types.Version{ - Version: "docker-dev", - APIVersion: api.DefaultVersion, - }, nil -} - -func (cli *fakeClient) ClientVersion() string { - return cli.version -} - -func (cli *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) { - if cli.serviceListFunc != nil { - return cli.serviceListFunc(options) - } - - namespace := namespaceFromFilters(options.Filters) - servicesList := []swarm.Service{} - for _, name := range cli.services { - if belongToNamespace(name, namespace) { - servicesList = append(servicesList, serviceFromName(name)) - } - } - return servicesList, nil -} - -func (cli *fakeClient) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { - if cli.networkListFunc != nil { - return cli.networkListFunc(options) - } - - namespace := namespaceFromFilters(options.Filters) - networksList := []types.NetworkResource{} - for _, name := range cli.networks { - if belongToNamespace(name, namespace) { - networksList = append(networksList, networkFromName(name)) - } - } - return networksList, nil -} - -func (cli *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) { - if cli.secretListFunc != nil { - return cli.secretListFunc(options) - } - - namespace := namespaceFromFilters(options.Filters) - secretsList := []swarm.Secret{} - for _, name := range cli.secrets { - if belongToNamespace(name, namespace) { - secretsList = append(secretsList, secretFromName(name)) - } - } - return secretsList, nil -} - -func (cli *fakeClient) ConfigList(ctx context.Context, options types.ConfigListOptions) ([]swarm.Config, error) { - if cli.configListFunc != nil { - return cli.configListFunc(options) - } - - namespace := namespaceFromFilters(options.Filters) - configsList := []swarm.Config{} - for _, name := range cli.configs { - if belongToNamespace(name, namespace) { - configsList = append(configsList, configFromName(name)) - } - } - return configsList, nil -} - -func (cli *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) { - if cli.taskListFunc != nil { - return cli.taskListFunc(options) - } - return []swarm.Task{}, nil -} - -func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) { - if cli.nodeListFunc != nil { - return cli.nodeListFunc(options) - } - return []swarm.Node{}, nil -} - -func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) { - if cli.nodeInspectWithRaw != nil { - return cli.nodeInspectWithRaw(ref) - } - return swarm.Node{}, nil, nil -} - -func (cli *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { - if cli.serviceUpdateFunc != nil { - return cli.serviceUpdateFunc(serviceID, version, service, options) - } - - return types.ServiceUpdateResponse{}, nil -} - -func (cli *fakeClient) ServiceRemove(ctx context.Context, serviceID string) error { - if cli.serviceRemoveFunc != nil { - return cli.serviceRemoveFunc(serviceID) - } - - cli.removedServices = append(cli.removedServices, serviceID) - return nil -} - -func (cli *fakeClient) NetworkRemove(ctx context.Context, networkID string) error { - if cli.networkRemoveFunc != nil { - return cli.networkRemoveFunc(networkID) - } - - cli.removedNetworks = append(cli.removedNetworks, networkID) - return nil -} - -func (cli *fakeClient) SecretRemove(ctx context.Context, secretID string) error { - if cli.secretRemoveFunc != nil { - return cli.secretRemoveFunc(secretID) - } - - cli.removedSecrets = append(cli.removedSecrets, secretID) - return nil -} - -func (cli *fakeClient) ConfigRemove(ctx context.Context, configID string) error { - if cli.configRemoveFunc != nil { - return cli.configRemoveFunc(configID) - } - - cli.removedConfigs = append(cli.removedConfigs, configID) - return nil -} - -func serviceFromName(name string) swarm.Service { - return swarm.Service{ - ID: "ID-" + name, - Spec: swarm.ServiceSpec{ - Annotations: swarm.Annotations{Name: name}, - }, - } -} - -func networkFromName(name string) types.NetworkResource { - return types.NetworkResource{ - ID: "ID-" + name, - Name: name, - } -} - -func secretFromName(name string) swarm.Secret { - return swarm.Secret{ - ID: "ID-" + name, - Spec: swarm.SecretSpec{ - Annotations: swarm.Annotations{Name: name}, - }, - } -} - -func configFromName(name string) swarm.Config { - return swarm.Config{ - ID: "ID-" + name, - Spec: swarm.ConfigSpec{ - Annotations: swarm.Annotations{Name: name}, - }, - } -} - -func namespaceFromFilters(filters filters.Args) string { - label := filters.Get("label")[0] - return strings.TrimPrefix(label, convert.LabelNamespace+"=") -} - -func belongToNamespace(id, namespace string) bool { - return strings.HasPrefix(id, namespace+"_") -} - -func objectName(namespace, name string) string { - return namespace + "_" + name -} - -func objectID(name string) string { - return "ID-" + name -} - -func buildObjectIDs(objectNames []string) []string { - IDs := make([]string, len(objectNames)) - for i, name := range objectNames { - IDs[i] = objectID(name) - } - return IDs -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/cmd.go b/vendor/github.com/docker/cli/cli/command/stack/cmd.go deleted file mode 100644 index 8d4281cfc..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/cmd.go +++ /dev/null @@ -1,36 +0,0 @@ -package stack - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewStackCommand returns a cobra command for `stack` subcommands -// nolint: interfacer -func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "stack", - Short: "Manage Docker stacks", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.25"}, - } - cmd.AddCommand( - newDeployCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - newServicesCommand(dockerCli), - newPsCommand(dockerCli), - ) - return cmd -} - -// NewTopLevelDeployCommand returns a command for `docker deploy` -func NewTopLevelDeployCommand(dockerCli command.Cli) *cobra.Command { - cmd := newDeployCommand(dockerCli) - // Remove the aliases at the top level - cmd.Aliases = []string{} - cmd.Tags = map[string]string{"experimental": "", "version": "1.25"} - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/common.go b/vendor/github.com/docker/cli/cli/command/stack/common.go deleted file mode 100644 index d9f921af5..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/common.go +++ /dev/null @@ -1,73 +0,0 @@ -package stack - -import ( - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -func getStackFilter(namespace string) filters.Args { - filter := filters.NewArgs() - filter.Add("label", convert.LabelNamespace+"="+namespace) - return filter -} - -func getServiceFilter(namespace string) filters.Args { - return getStackFilter(namespace) -} - -func getStackFilterFromOpt(namespace string, opt opts.FilterOpt) filters.Args { - filter := opt.Value() - filter.Add("label", convert.LabelNamespace+"="+namespace) - return filter -} - -func getAllStacksFilter() filters.Args { - filter := filters.NewArgs() - filter.Add("label", convert.LabelNamespace) - return filter -} - -func getServices( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]swarm.Service, error) { - return apiclient.ServiceList( - ctx, - types.ServiceListOptions{Filters: getServiceFilter(namespace)}) -} - -func getStackNetworks( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]types.NetworkResource, error) { - return apiclient.NetworkList( - ctx, - types.NetworkListOptions{Filters: getStackFilter(namespace)}) -} - -func getStackSecrets( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]swarm.Secret, error) { - return apiclient.SecretList( - ctx, - types.SecretListOptions{Filters: getStackFilter(namespace)}) -} - -func getStackConfigs( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]swarm.Config, error) { - return apiclient.ConfigList( - ctx, - types.ConfigListOptions{Filters: getStackFilter(namespace)}) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy.go b/vendor/github.com/docker/cli/cli/command/stack/deploy.go deleted file mode 100644 index 8e14b70d2..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy.go +++ /dev/null @@ -1,123 +0,0 @@ -package stack - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/versions" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -const ( - defaultNetworkDriver = "overlay" - resolveImageAlways = "always" - resolveImageChanged = "changed" - resolveImageNever = "never" -) - -type deployOptions struct { - bundlefile string - composefile string - namespace string - resolveImage string - sendRegistryAuth bool - prune bool -} - -func newDeployCommand(dockerCli command.Cli) *cobra.Command { - var opts deployOptions - - cmd := &cobra.Command{ - Use: "deploy [OPTIONS] STACK", - Aliases: []string{"up"}, - Short: "Deploy a new stack or update an existing stack", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.namespace = args[0] - return runDeploy(dockerCli, opts) - }, - } - - flags := cmd.Flags() - addBundlefileFlag(&opts.bundlefile, flags) - addComposefileFlag(&opts.composefile, flags) - addRegistryAuthFlag(&opts.sendRegistryAuth, flags) - flags.BoolVar(&opts.prune, "prune", false, "Prune services that are no longer referenced") - flags.SetAnnotation("prune", "version", []string{"1.27"}) - flags.StringVar(&opts.resolveImage, "resolve-image", resolveImageAlways, - `Query the registry to resolve image digest and supported platforms ("`+resolveImageAlways+`"|"`+resolveImageChanged+`"|"`+resolveImageNever+`")`) - flags.SetAnnotation("resolve-image", "version", []string{"1.30"}) - return cmd -} - -func runDeploy(dockerCli command.Cli, opts deployOptions) error { - ctx := context.Background() - - if err := validateResolveImageFlag(dockerCli, &opts); err != nil { - return err - } - - switch { - case opts.bundlefile == "" && opts.composefile == "": - return errors.Errorf("Please specify either a bundle file (with --bundle-file) or a Compose file (with --compose-file).") - case opts.bundlefile != "" && opts.composefile != "": - return errors.Errorf("You cannot specify both a bundle file and a Compose file.") - case opts.bundlefile != "": - return deployBundle(ctx, dockerCli, opts) - default: - return deployCompose(ctx, dockerCli, opts) - } -} - -// validateResolveImageFlag validates the opts.resolveImage command line option -// and also turns image resolution off if the version is older than 1.30 -func validateResolveImageFlag(dockerCli command.Cli, opts *deployOptions) error { - if opts.resolveImage != resolveImageAlways && opts.resolveImage != resolveImageChanged && opts.resolveImage != resolveImageNever { - return errors.Errorf("Invalid option %s for flag --resolve-image", opts.resolveImage) - } - // client side image resolution should not be done when the supported - // server version is older than 1.30 - if versions.LessThan(dockerCli.Client().ClientVersion(), "1.30") { - opts.resolveImage = resolveImageNever - } - return nil -} - -// checkDaemonIsSwarmManager does an Info API call to verify that the daemon is -// a swarm manager. This is necessary because we must create networks before we -// create services, but the API call for creating a network does not return a -// proper status code when it can't create a network in the "global" scope. -func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error { - info, err := dockerCli.Client().Info(ctx) - if err != nil { - return err - } - if !info.Swarm.ControlAvailable { - return errors.New("this node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again") - } - return nil -} - -// pruneServices removes services that are no longer referenced in the source -func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert.Namespace, services map[string]struct{}) bool { - client := dockerCli.Client() - - oldServices, err := getServices(ctx, client, namespace.Name()) - if err != nil { - fmt.Fprintf(dockerCli.Err(), "Failed to list services: %s", err) - return true - } - - pruneServices := []swarm.Service{} - for _, service := range oldServices { - if _, exists := services[namespace.Descope(service.Spec.Name)]; !exists { - pruneServices = append(pruneServices, service) - } - } - return removeServices(ctx, dockerCli, pruneServices) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go b/vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go deleted file mode 100644 index 5c4d4546f..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go +++ /dev/null @@ -1,91 +0,0 @@ -package stack - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" -) - -func deployBundle(ctx context.Context, dockerCli command.Cli, opts deployOptions) error { - bundle, err := loadBundlefile(dockerCli.Err(), opts.namespace, opts.bundlefile) - if err != nil { - return err - } - - if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil { - return err - } - - namespace := convert.NewNamespace(opts.namespace) - - if opts.prune { - services := map[string]struct{}{} - for service := range bundle.Services { - services[service] = struct{}{} - } - pruneServices(ctx, dockerCli, namespace, services) - } - - networks := make(map[string]types.NetworkCreate) - for _, service := range bundle.Services { - for _, networkName := range service.Networks { - networks[networkName] = types.NetworkCreate{ - Labels: convert.AddStackLabel(namespace, nil), - } - } - } - - services := make(map[string]swarm.ServiceSpec) - for internalName, service := range bundle.Services { - name := namespace.Scope(internalName) - - var ports []swarm.PortConfig - for _, portSpec := range service.Ports { - ports = append(ports, swarm.PortConfig{ - Protocol: swarm.PortConfigProtocol(portSpec.Protocol), - TargetPort: portSpec.Port, - }) - } - - nets := []swarm.NetworkAttachmentConfig{} - for _, networkName := range service.Networks { - nets = append(nets, swarm.NetworkAttachmentConfig{ - Target: namespace.Scope(networkName), - Aliases: []string{internalName}, - }) - } - - serviceSpec := swarm.ServiceSpec{ - Annotations: swarm.Annotations{ - Name: name, - Labels: convert.AddStackLabel(namespace, service.Labels), - }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{ - Image: service.Image, - Command: service.Command, - Args: service.Args, - Env: service.Env, - // Service Labels will not be copied to Containers - // automatically during the deployment so we apply - // it here. - Labels: convert.AddStackLabel(namespace, nil), - }, - }, - EndpointSpec: &swarm.EndpointSpec{ - Ports: ports, - }, - Networks: nets, - } - - services[internalName] = serviceSpec - } - - if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil { - return err - } - return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.resolveImage) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile.go b/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile.go deleted file mode 100644 index e511a6f12..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile.go +++ /dev/null @@ -1,380 +0,0 @@ -package stack - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strings" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/cli/cli/compose/loader" - composetypes "github.com/docker/cli/cli/compose/types" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/swarm" - apiclient "github.com/docker/docker/client" - dockerclient "github.com/docker/docker/client" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -func deployCompose(ctx context.Context, dockerCli command.Cli, opts deployOptions) error { - configDetails, err := getConfigDetails(opts.composefile, dockerCli.In()) - if err != nil { - return err - } - - config, err := loader.Load(configDetails) - if err != nil { - if fpe, ok := err.(*loader.ForbiddenPropertiesError); ok { - return errors.Errorf("Compose file contains unsupported options:\n\n%s\n", - propertyWarnings(fpe.Properties)) - } - - return err - } - - unsupportedProperties := loader.GetUnsupportedProperties(configDetails) - if len(unsupportedProperties) > 0 { - fmt.Fprintf(dockerCli.Err(), "Ignoring unsupported options: %s\n\n", - strings.Join(unsupportedProperties, ", ")) - } - - deprecatedProperties := loader.GetDeprecatedProperties(configDetails) - if len(deprecatedProperties) > 0 { - fmt.Fprintf(dockerCli.Err(), "Ignoring deprecated options:\n\n%s\n\n", - propertyWarnings(deprecatedProperties)) - } - - if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil { - return err - } - - namespace := convert.NewNamespace(opts.namespace) - - if opts.prune { - services := map[string]struct{}{} - for _, service := range config.Services { - services[service.Name] = struct{}{} - } - pruneServices(ctx, dockerCli, namespace, services) - } - - serviceNetworks := getServicesDeclaredNetworks(config.Services) - networks, externalNetworks := convert.Networks(namespace, config.Networks, serviceNetworks) - if err := validateExternalNetworks(ctx, dockerCli.Client(), externalNetworks); err != nil { - return err - } - if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil { - return err - } - - secrets, err := convert.Secrets(namespace, config.Secrets) - if err != nil { - return err - } - if err := createSecrets(ctx, dockerCli, secrets); err != nil { - return err - } - - configs, err := convert.Configs(namespace, config.Configs) - if err != nil { - return err - } - if err := createConfigs(ctx, dockerCli, configs); err != nil { - return err - } - - services, err := convert.Services(namespace, config, dockerCli.Client()) - if err != nil { - return err - } - return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.resolveImage) -} - -func getServicesDeclaredNetworks(serviceConfigs []composetypes.ServiceConfig) map[string]struct{} { - serviceNetworks := map[string]struct{}{} - for _, serviceConfig := range serviceConfigs { - if len(serviceConfig.Networks) == 0 { - serviceNetworks["default"] = struct{}{} - continue - } - for network := range serviceConfig.Networks { - serviceNetworks[network] = struct{}{} - } - } - return serviceNetworks -} - -func propertyWarnings(properties map[string]string) string { - var msgs []string - for name, description := range properties { - msgs = append(msgs, fmt.Sprintf("%s: %s", name, description)) - } - sort.Strings(msgs) - return strings.Join(msgs, "\n\n") -} - -func getConfigDetails(composefile string, stdin io.Reader) (composetypes.ConfigDetails, error) { - var details composetypes.ConfigDetails - - if composefile == "-" { - workingDir, err := os.Getwd() - if err != nil { - return details, err - } - details.WorkingDir = workingDir - } else { - absPath, err := filepath.Abs(composefile) - if err != nil { - return details, err - } - details.WorkingDir = filepath.Dir(absPath) - } - - configFile, err := getConfigFile(composefile, stdin) - if err != nil { - return details, err - } - // TODO: support multiple files - details.ConfigFiles = []composetypes.ConfigFile{*configFile} - details.Environment, err = buildEnvironment(os.Environ()) - return details, err -} - -func buildEnvironment(env []string) (map[string]string, error) { - result := make(map[string]string, len(env)) - for _, s := range env { - // if value is empty, s is like "K=", not "K". - if !strings.Contains(s, "=") { - return result, errors.Errorf("unexpected environment %q", s) - } - kv := strings.SplitN(s, "=", 2) - result[kv[0]] = kv[1] - } - return result, nil -} - -func getConfigFile(filename string, stdin io.Reader) (*composetypes.ConfigFile, error) { - var bytes []byte - var err error - - if filename == "-" { - bytes, err = ioutil.ReadAll(stdin) - } else { - bytes, err = ioutil.ReadFile(filename) - } - if err != nil { - return nil, err - } - - config, err := loader.ParseYAML(bytes) - if err != nil { - return nil, err - } - - return &composetypes.ConfigFile{ - Filename: filename, - Config: config, - }, nil -} - -func validateExternalNetworks( - ctx context.Context, - client dockerclient.NetworkAPIClient, - externalNetworks []string, -) error { - for _, networkName := range externalNetworks { - if !container.NetworkMode(networkName).IsUserDefined() { - // Networks that are not user defined always exist on all nodes as - // local-scoped networks, so there's no need to inspect them. - continue - } - network, err := client.NetworkInspect(ctx, networkName, types.NetworkInspectOptions{}) - switch { - case dockerclient.IsErrNotFound(err): - return errors.Errorf("network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed", networkName) - case err != nil: - return err - case network.Scope != "swarm": - return errors.Errorf("network %q is declared as external, but it is not in the right scope: %q instead of \"swarm\"", networkName, network.Scope) - } - } - return nil -} - -func createSecrets( - ctx context.Context, - dockerCli command.Cli, - secrets []swarm.SecretSpec, -) error { - client := dockerCli.Client() - - for _, secretSpec := range secrets { - secret, _, err := client.SecretInspectWithRaw(ctx, secretSpec.Name) - switch { - case err == nil: - // secret already exists, then we update that - if err := client.SecretUpdate(ctx, secret.ID, secret.Meta.Version, secretSpec); err != nil { - return errors.Wrapf(err, "failed to update secret %s", secretSpec.Name) - } - case apiclient.IsErrSecretNotFound(err): - // secret does not exist, then we create a new one. - if _, err := client.SecretCreate(ctx, secretSpec); err != nil { - return errors.Wrapf(err, "failed to create secret %s", secretSpec.Name) - } - default: - return err - } - } - return nil -} - -func createConfigs( - ctx context.Context, - dockerCli command.Cli, - configs []swarm.ConfigSpec, -) error { - client := dockerCli.Client() - - for _, configSpec := range configs { - config, _, err := client.ConfigInspectWithRaw(ctx, configSpec.Name) - switch { - case err == nil: - // config already exists, then we update that - if err := client.ConfigUpdate(ctx, config.ID, config.Meta.Version, configSpec); err != nil { - errors.Wrapf(err, "failed to update config %s", configSpec.Name) - } - case apiclient.IsErrConfigNotFound(err): - // config does not exist, then we create a new one. - if _, err := client.ConfigCreate(ctx, configSpec); err != nil { - errors.Wrapf(err, "failed to create config %s", configSpec.Name) - } - default: - return err - } - } - return nil -} - -func createNetworks( - ctx context.Context, - dockerCli command.Cli, - namespace convert.Namespace, - networks map[string]types.NetworkCreate, -) error { - client := dockerCli.Client() - - existingNetworks, err := getStackNetworks(ctx, client, namespace.Name()) - if err != nil { - return err - } - - existingNetworkMap := make(map[string]types.NetworkResource) - for _, network := range existingNetworks { - existingNetworkMap[network.Name] = network - } - - for internalName, createOpts := range networks { - name := namespace.Scope(internalName) - if _, exists := existingNetworkMap[name]; exists { - continue - } - - if createOpts.Driver == "" { - createOpts.Driver = defaultNetworkDriver - } - - fmt.Fprintf(dockerCli.Out(), "Creating network %s\n", name) - if _, err := client.NetworkCreate(ctx, name, createOpts); err != nil { - return errors.Wrapf(err, "failed to create network %s", internalName) - } - } - return nil -} - -func deployServices( - ctx context.Context, - dockerCli command.Cli, - services map[string]swarm.ServiceSpec, - namespace convert.Namespace, - sendAuth bool, - resolveImage string, -) error { - apiClient := dockerCli.Client() - out := dockerCli.Out() - - existingServices, err := getServices(ctx, apiClient, namespace.Name()) - if err != nil { - return err - } - - existingServiceMap := make(map[string]swarm.Service) - for _, service := range existingServices { - existingServiceMap[service.Spec.Name] = service - } - - for internalName, serviceSpec := range services { - name := namespace.Scope(internalName) - - encodedAuth := "" - image := serviceSpec.TaskTemplate.ContainerSpec.Image - if sendAuth { - // Retrieve encoded auth token from the image reference - encodedAuth, err = command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) - if err != nil { - return err - } - } - - if service, exists := existingServiceMap[name]; exists { - fmt.Fprintf(out, "Updating service %s (id: %s)\n", name, service.ID) - - updateOpts := types.ServiceUpdateOptions{EncodedRegistryAuth: encodedAuth} - - switch { - case resolveImage == resolveImageAlways || (resolveImage == resolveImageChanged && image != service.Spec.Labels[convert.LabelImage]): - // image should be updated by the server using QueryRegistry - updateOpts.QueryRegistry = true - case image == service.Spec.Labels[convert.LabelImage]: - // image has not changed; update the serviceSpec with the - // existing information that was set by QueryRegistry on the - // previous deploy. Otherwise this will trigger an incorrect - // service update. - serviceSpec.TaskTemplate.ContainerSpec.Image = service.Spec.TaskTemplate.ContainerSpec.Image - } - response, err := apiClient.ServiceUpdate( - ctx, - service.ID, - service.Version, - serviceSpec, - updateOpts, - ) - if err != nil { - return errors.Wrapf(err, "failed to update service %s", name) - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - } else { - fmt.Fprintf(out, "Creating service %s\n", name) - - createOpts := types.ServiceCreateOptions{EncodedRegistryAuth: encodedAuth} - - // query registry if flag disabling it was not set - if resolveImage == resolveImageAlways || resolveImage == resolveImageChanged { - createOpts.QueryRegistry = true - } - - if _, err := apiClient.ServiceCreate(ctx, serviceSpec, createOpts); err != nil { - return errors.Wrapf(err, "failed to create service %s", name) - } - } - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile_test.go b/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile_test.go deleted file mode 100644 index 684e688c0..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package stack - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "github.com/docker/cli/internal/test/network" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/gotestyourself/gotestyourself/fs" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/context" -) - -func TestGetConfigDetails(t *testing.T) { - content := ` -version: "3.0" -services: - foo: - image: alpine:3.5 -` - file := fs.NewFile(t, "test-get-config-details", fs.WithContent(content)) - defer file.Remove() - - details, err := getConfigDetails(file.Path(), nil) - require.NoError(t, err) - assert.Equal(t, filepath.Dir(file.Path()), details.WorkingDir) - require.Len(t, details.ConfigFiles, 1) - assert.Equal(t, "3.0", details.ConfigFiles[0].Config["version"]) - assert.Len(t, details.Environment, len(os.Environ())) -} - -func TestGetConfigDetailsStdin(t *testing.T) { - content := ` -version: "3.0" -services: - foo: - image: alpine:3.5 -` - details, err := getConfigDetails("-", strings.NewReader(content)) - require.NoError(t, err) - cwd, err := os.Getwd() - require.NoError(t, err) - assert.Equal(t, cwd, details.WorkingDir) - require.Len(t, details.ConfigFiles, 1) - assert.Equal(t, "3.0", details.ConfigFiles[0].Config["version"]) - assert.Len(t, details.Environment, len(os.Environ())) -} - -type notFound struct { - error -} - -func (n notFound) NotFound() bool { - return true -} - -func TestValidateExternalNetworks(t *testing.T) { - var testcases = []struct { - inspectResponse types.NetworkResource - inspectError error - expectedMsg string - network string - }{ - { - inspectError: notFound{}, - expectedMsg: "could not be found. You need to create a swarm-scoped network", - }, - { - inspectError: errors.New("Unexpected"), - expectedMsg: "Unexpected", - }, - { - inspectError: errors.New("host net does not exist on swarm classic"), - network: "host", - }, - { - network: "user", - expectedMsg: "is not in the right scope", - }, - { - network: "user", - inspectResponse: types.NetworkResource{Scope: "swarm"}, - }, - } - - for _, testcase := range testcases { - fakeClient := &network.FakeClient{ - NetworkInspectFunc: func(_ context.Context, _ string, _ types.NetworkInspectOptions) (types.NetworkResource, error) { - return testcase.inspectResponse, testcase.inspectError - }, - } - networks := []string{testcase.network} - err := validateExternalNetworks(context.Background(), fakeClient, networks) - if testcase.expectedMsg == "" { - assert.NoError(t, err) - } else { - testutil.ErrorContains(t, err, testcase.expectedMsg) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy_test.go b/vendor/github.com/docker/cli/cli/command/stack/deploy_test.go deleted file mode 100644 index 15900f178..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package stack - -import ( - "testing" - - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" -) - -func TestPruneServices(t *testing.T) { - ctx := context.Background() - namespace := convert.NewNamespace("foo") - services := map[string]struct{}{ - "new": {}, - "keep": {}, - } - client := &fakeClient{services: []string{objectName("foo", "keep"), objectName("foo", "remove")}} - dockerCli := test.NewFakeCli(client) - - pruneServices(ctx, dockerCli, namespace, services) - assert.Equal(t, buildObjectIDs([]string{objectName("foo", "remove")}), client.removedServices) -} - -// TestServiceUpdateResolveImageChanged tests that the service's -// image digest is preserved if the image did not change in the compose file -func TestServiceUpdateResolveImageChanged(t *testing.T) { - namespace := convert.NewNamespace("mystack") - - var ( - receivedOptions types.ServiceUpdateOptions - receivedService swarm.ServiceSpec - ) - - client := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - { - Spec: swarm.ServiceSpec{ - Annotations: swarm.Annotations{ - Name: namespace.Name() + "_myservice", - Labels: map[string]string{"com.docker.stack.image": "foobar:1.2.3"}, - }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{ - Image: "foobar:1.2.3@sha256:deadbeef", - }, - }, - }, - }, - }, nil - }, - serviceUpdateFunc: func(serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { - receivedOptions = options - receivedService = service - return types.ServiceUpdateResponse{}, nil - }, - }) - - var testcases = []struct { - image string - expectedQueryRegistry bool - expectedImage string - }{ - // Image not changed - { - image: "foobar:1.2.3", - expectedQueryRegistry: false, - expectedImage: "foobar:1.2.3@sha256:deadbeef", - }, - // Image changed - { - image: "foobar:1.2.4", - expectedQueryRegistry: true, - expectedImage: "foobar:1.2.4", - }, - } - - ctx := context.Background() - - for _, testcase := range testcases { - t.Logf("Testing image %q", testcase.image) - spec := map[string]swarm.ServiceSpec{ - "myservice": { - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: &swarm.ContainerSpec{ - Image: testcase.image, - }, - }, - }, - } - err := deployServices(ctx, client, spec, namespace, false, resolveImageChanged) - assert.NoError(t, err) - assert.Equal(t, testcase.expectedQueryRegistry, receivedOptions.QueryRegistry) - assert.Equal(t, testcase.expectedImage, receivedService.TaskTemplate.ContainerSpec.Image) - - receivedService = swarm.ServiceSpec{} - receivedOptions = types.ServiceUpdateOptions{} - } -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/list.go b/vendor/github.com/docker/cli/cli/command/stack/list.go deleted file mode 100644 index 24da30512..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/list.go +++ /dev/null @@ -1,96 +0,0 @@ -package stack - -import ( - "sort" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" - "vbom.ml/util/sortorder" -) - -type listOptions struct { - format string -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - opts := listOptions{} - - cmd := &cobra.Command{ - Use: "ls", - Aliases: []string{"list"}, - Short: "List stacks", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVar(&opts.format, "format", "", "Pretty-print stacks using a Go template") - return cmd -} - -func runList(dockerCli command.Cli, opts listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - stacks, err := getStacks(ctx, client) - if err != nil { - return err - } - format := opts.format - if len(format) == 0 { - format = formatter.TableFormatKey - } - stackCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewStackFormat(format), - } - sort.Sort(byName(stacks)) - return formatter.StackWrite(stackCtx, stacks) -} - -type byName []*formatter.Stack - -func (n byName) Len() int { return len(n) } -func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] } -func (n byName) Less(i, j int) bool { return sortorder.NaturalLess(n[i].Name, n[j].Name) } - -func getStacks(ctx context.Context, apiclient client.APIClient) ([]*formatter.Stack, error) { - services, err := apiclient.ServiceList( - ctx, - types.ServiceListOptions{Filters: getAllStacksFilter()}) - if err != nil { - return nil, err - } - m := make(map[string]*formatter.Stack) - for _, service := range services { - labels := service.Spec.Labels - name, ok := labels[convert.LabelNamespace] - if !ok { - return nil, errors.Errorf("cannot get label %s for service %s", - convert.LabelNamespace, service.ID) - } - ztack, ok := m[name] - if !ok { - m[name] = &formatter.Stack{ - Name: name, - Services: 1, - } - } else { - ztack.Services++ - } - } - var stacks []*formatter.Stack - for _, stack := range m { - stacks = append(stacks, stack) - } - return stacks, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/list_test.go b/vendor/github.com/docker/cli/cli/command/stack/list_test.go deleted file mode 100644 index 90d32e0f9..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/list_test.go +++ /dev/null @@ -1,147 +0,0 @@ -package stack - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestListErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error) - expectedError string - }{ - { - args: []string{"foo"}, - expectedError: "accepts no argument", - }, - { - flags: map[string]string{ - "format": "{{invalid format}}", - }, - expectedError: "Template parsing error", - }, - { - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{}, errors.Errorf("error getting services") - }, - expectedError: "error getting services", - }, - { - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{*Service()}, nil - }, - expectedError: "cannot get label", - }, - } - - for _, tc := range testCases { - cmd := newListCommand(test.NewFakeCli(&fakeClient{ - serviceListFunc: tc.serviceListFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestListWithFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - *Service( - ServiceLabels(map[string]string{ - "com.docker.stack.namespace": "service-name-foo", - }), - )}, nil - }, - }) - cmd := newListCommand(cli) - cmd.Flags().Set("format", "{{ .Name }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-list-with-format.golden") -} - -func TestListWithoutFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - *Service( - ServiceLabels(map[string]string{ - "com.docker.stack.namespace": "service-name-foo", - }), - )}, nil - }, - }) - cmd := newListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-list-without-format.golden") -} - -func TestListOrder(t *testing.T) { - usecases := []struct { - golden string - swarmServices []swarm.Service - }{ - { - golden: "stack-list-sort.golden", - swarmServices: []swarm.Service{ - *Service( - ServiceLabels(map[string]string{ - "com.docker.stack.namespace": "service-name-foo", - }), - ), - *Service( - ServiceLabels(map[string]string{ - "com.docker.stack.namespace": "service-name-bar", - }), - ), - }, - }, - { - golden: "stack-list-sort-natural.golden", - swarmServices: []swarm.Service{ - *Service( - ServiceLabels(map[string]string{ - "com.docker.stack.namespace": "service-name-1-foo", - }), - ), - *Service( - ServiceLabels(map[string]string{ - "com.docker.stack.namespace": "service-name-10-foo", - }), - ), - *Service( - ServiceLabels(map[string]string{ - "com.docker.stack.namespace": "service-name-2-foo", - }), - ), - }, - }, - } - - for _, uc := range usecases { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return uc.swarmServices, nil - }, - }) - cmd := newListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), uc.golden) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/opts.go b/vendor/github.com/docker/cli/cli/command/stack/opts.go deleted file mode 100644 index c1634e26b..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/opts.go +++ /dev/null @@ -1,51 +0,0 @@ -package stack - -import ( - "fmt" - "io" - "os" - - "github.com/docker/cli/cli/command/bundlefile" - "github.com/pkg/errors" - "github.com/spf13/pflag" -) - -func addComposefileFlag(opt *string, flags *pflag.FlagSet) { - flags.StringVarP(opt, "compose-file", "c", "", "Path to a Compose file") - flags.SetAnnotation("compose-file", "version", []string{"1.25"}) -} - -func addBundlefileFlag(opt *string, flags *pflag.FlagSet) { - flags.StringVar(opt, "bundle-file", "", "Path to a Distributed Application Bundle file") - flags.SetAnnotation("bundle-file", "experimental", nil) -} - -func addRegistryAuthFlag(opt *bool, flags *pflag.FlagSet) { - flags.BoolVar(opt, "with-registry-auth", false, "Send registry authentication details to Swarm agents") -} - -func loadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefile.Bundlefile, error) { - defaultPath := fmt.Sprintf("%s.dab", namespace) - - if path == "" { - path = defaultPath - } - if _, err := os.Stat(path); err != nil { - return nil, errors.Errorf( - "Bundle %s not found. Specify the path with --file", - path) - } - - fmt.Fprintf(stderr, "Loading bundle from %s\n", path) - reader, err := os.Open(path) - if err != nil { - return nil, err - } - defer reader.Close() - - bundle, err := bundlefile.LoadFile(reader) - if err != nil { - return nil, errors.Errorf("Error reading %s: %v\n", path, err) - } - return bundle, err -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/opts_test.go b/vendor/github.com/docker/cli/cli/command/stack/opts_test.go deleted file mode 100644 index b57dcd89f..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/opts_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package stack - -import ( - "bytes" - "fmt" - "path/filepath" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestLoadBundlefileErrors(t *testing.T) { - testCases := []struct { - namespace string - path string - expectedError error - }{ - { - namespace: "namespace_foo", - expectedError: fmt.Errorf("Bundle %s.dab not found", "namespace_foo"), - }, - { - namespace: "namespace_foo", - path: "invalid_path", - expectedError: fmt.Errorf("Bundle %s not found", "invalid_path"), - }, - { - namespace: "namespace_foo", - path: filepath.Join("testdata", "bundlefile_with_invalid_syntax"), - expectedError: fmt.Errorf("Error reading"), - }, - } - - for _, tc := range testCases { - _, err := loadBundlefile(&bytes.Buffer{}, tc.namespace, tc.path) - assert.Error(t, err, tc.expectedError) - } -} - -func TestLoadBundlefile(t *testing.T) { - buf := new(bytes.Buffer) - - namespace := "" - path := filepath.Join("testdata", "bundlefile_with_two_services.dab") - bundleFile, err := loadBundlefile(buf, namespace, path) - - assert.NoError(t, err) - assert.Equal(t, len(bundleFile.Services), 2) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/ps.go b/vendor/github.com/docker/cli/cli/command/stack/ps.go deleted file mode 100644 index d586b1e1e..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/ps.go +++ /dev/null @@ -1,69 +0,0 @@ -package stack - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/cli/command/task" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type psOptions struct { - filter opts.FilterOpt - noTrunc bool - namespace string - noResolve bool - quiet bool - format string -} - -func newPsCommand(dockerCli command.Cli) *cobra.Command { - options := psOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ps [OPTIONS] STACK", - Short: "List the tasks in the stack", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.namespace = args[0] - return runPS(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&options.noResolve, "no-resolve", false, "Do not map IDs to Names") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display task IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print tasks using a Go template") - - return cmd -} - -func runPS(dockerCli command.Cli, options psOptions) error { - namespace := options.namespace - client := dockerCli.Client() - ctx := context.Background() - - filter := getStackFilterFromOpt(options.namespace, options.filter) - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) - if err != nil { - return err - } - - if len(tasks) == 0 { - return fmt.Errorf("nothing found in stack: %s", namespace) - } - - format := options.format - if len(format) == 0 { - format = task.DefaultFormat(dockerCli.ConfigFile(), options.quiet) - } - - return task.Print(ctx, dockerCli, tasks, idresolver.New(client, options.noResolve), !options.noTrunc, options.quiet, format) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/ps_test.go b/vendor/github.com/docker/cli/cli/command/stack/ps_test.go deleted file mode 100644 index 3bb22609b..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/ps_test.go +++ /dev/null @@ -1,163 +0,0 @@ -package stack - -import ( - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestStackPsErrors(t *testing.T) { - testCases := []struct { - args []string - taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error) - expectedError string - }{ - - { - args: []string{}, - expectedError: "requires exactly 1 argument", - }, - { - args: []string{"foo", "bar"}, - expectedError: "requires exactly 1 argument", - }, - { - args: []string{"foo"}, - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return nil, errors.Errorf("error getting tasks") - }, - expectedError: "error getting tasks", - }, - } - - for _, tc := range testCases { - cmd := newPsCommand(test.NewFakeCli(&fakeClient{ - taskListFunc: tc.taskListFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestStackPsEmptyStack(t *testing.T) { - fakeCli := test.NewFakeCli(&fakeClient{ - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{}, nil - }, - }) - cmd := newPsCommand(fakeCli) - cmd.SetArgs([]string{"foo"}) - - assert.Error(t, cmd.Execute()) - assert.EqualError(t, cmd.Execute(), "nothing found in stack: foo") - assert.Equal(t, "", fakeCli.OutBuffer().String()) -} - -func TestStackPsWithQuietOption(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{*Task(TaskID("id-foo"))}, nil - }, - }) - cmd := newPsCommand(cli) - cmd.SetArgs([]string{"foo"}) - cmd.Flags().Set("quiet", "true") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-ps-with-quiet-option.golden") - -} - -func TestStackPsWithNoTruncOption(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{*Task(TaskID("xn4cypcov06f2w8gsbaf2lst3"))}, nil - }, - }) - cmd := newPsCommand(cli) - cmd.SetArgs([]string{"foo"}) - cmd.Flags().Set("no-trunc", "true") - cmd.Flags().Set("format", "{{ .ID }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-ps-with-no-trunc-option.golden") -} - -func TestStackPsWithNoResolveOption(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{*Task( - TaskNodeID("id-node-foo"), - )}, nil - }, - nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) { - return *Node(NodeName("node-name-bar")), nil, nil - }, - }) - cmd := newPsCommand(cli) - cmd.SetArgs([]string{"foo"}) - cmd.Flags().Set("no-resolve", "true") - cmd.Flags().Set("format", "{{ .Node }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-ps-with-no-resolve-option.golden") -} - -func TestStackPsWithFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{*Task(TaskServiceID("service-id-foo"))}, nil - }, - }) - cmd := newPsCommand(cli) - cmd.SetArgs([]string{"foo"}) - cmd.Flags().Set("format", "{{ .Name }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-ps-with-format.golden") -} - -func TestStackPsWithConfigFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{*Task(TaskServiceID("service-id-foo"))}, nil - }, - }) - cli.SetConfigFile(&configfile.ConfigFile{ - TasksFormat: "{{ .Name }}", - }) - cmd := newPsCommand(cli) - cmd.SetArgs([]string{"foo"}) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-ps-with-config-format.golden") -} - -func TestStackPsWithoutFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return []swarm.Task{*Task( - TaskID("id-foo"), - TaskServiceID("service-id-foo"), - TaskNodeID("id-node"), - WithTaskSpec(TaskImage("myimage:mytag")), - TaskDesiredState(swarm.TaskStateReady), - WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))), - )}, nil - }, - nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) { - return *Node(NodeName("node-name-bar")), nil, nil - }, - }) - cmd := newPsCommand(cli) - cmd.SetArgs([]string{"foo"}) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-ps-without-format.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/remove.go b/vendor/github.com/docker/cli/cli/command/stack/remove.go deleted file mode 100644 index d595b6c3e..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/remove.go +++ /dev/null @@ -1,161 +0,0 @@ -package stack - -import ( - "fmt" - "sort" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/versions" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type removeOptions struct { - namespaces []string -} - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - var opts removeOptions - - cmd := &cobra.Command{ - Use: "rm STACK [STACK...]", - Aliases: []string{"remove", "down"}, - Short: "Remove one or more stacks", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.namespaces = args - return runRemove(dockerCli, opts) - }, - } - return cmd -} - -func runRemove(dockerCli command.Cli, opts removeOptions) error { - namespaces := opts.namespaces - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - for _, namespace := range namespaces { - services, err := getServices(ctx, client, namespace) - if err != nil { - return err - } - - networks, err := getStackNetworks(ctx, client, namespace) - if err != nil { - return err - } - - var secrets []swarm.Secret - if versions.GreaterThanOrEqualTo(client.ClientVersion(), "1.25") { - secrets, err = getStackSecrets(ctx, client, namespace) - if err != nil { - return err - } - } - - var configs []swarm.Config - if versions.GreaterThanOrEqualTo(client.ClientVersion(), "1.30") { - configs, err = getStackConfigs(ctx, client, namespace) - if err != nil { - return err - } - } - - if len(services)+len(networks)+len(secrets)+len(configs) == 0 { - fmt.Fprintf(dockerCli.Err(), "Nothing found in stack: %s\n", namespace) - continue - } - - hasError := removeServices(ctx, dockerCli, services) - hasError = removeSecrets(ctx, dockerCli, secrets) || hasError - hasError = removeConfigs(ctx, dockerCli, configs) || hasError - hasError = removeNetworks(ctx, dockerCli, networks) || hasError - - if hasError { - errs = append(errs, fmt.Sprintf("Failed to remove some resources from stack: %s", namespace)) - } - } - - if len(errs) > 0 { - return errors.Errorf(strings.Join(errs, "\n")) - } - return nil -} - -func sortServiceByName(services []swarm.Service) func(i, j int) bool { - return func(i, j int) bool { - return services[i].Spec.Name < services[j].Spec.Name - } -} - -func removeServices( - ctx context.Context, - dockerCli command.Cli, - services []swarm.Service, -) bool { - var hasError bool - sort.Slice(services, sortServiceByName(services)) - for _, service := range services { - fmt.Fprintf(dockerCli.Out(), "Removing service %s\n", service.Spec.Name) - if err := dockerCli.Client().ServiceRemove(ctx, service.ID); err != nil { - hasError = true - fmt.Fprintf(dockerCli.Err(), "Failed to remove service %s: %s", service.ID, err) - } - } - return hasError -} - -func removeNetworks( - ctx context.Context, - dockerCli command.Cli, - networks []types.NetworkResource, -) bool { - var hasError bool - for _, network := range networks { - fmt.Fprintf(dockerCli.Out(), "Removing network %s\n", network.Name) - if err := dockerCli.Client().NetworkRemove(ctx, network.ID); err != nil { - hasError = true - fmt.Fprintf(dockerCli.Err(), "Failed to remove network %s: %s", network.ID, err) - } - } - return hasError -} - -func removeSecrets( - ctx context.Context, - dockerCli command.Cli, - secrets []swarm.Secret, -) bool { - var hasError bool - for _, secret := range secrets { - fmt.Fprintf(dockerCli.Out(), "Removing secret %s\n", secret.Spec.Name) - if err := dockerCli.Client().SecretRemove(ctx, secret.ID); err != nil { - hasError = true - fmt.Fprintf(dockerCli.Err(), "Failed to remove secret %s: %s", secret.ID, err) - } - } - return hasError -} - -func removeConfigs( - ctx context.Context, - dockerCli command.Cli, - configs []swarm.Config, -) bool { - var hasError bool - for _, config := range configs { - fmt.Fprintf(dockerCli.Out(), "Removing config %s\n", config.Spec.Name) - if err := dockerCli.Client().ConfigRemove(ctx, config.ID); err != nil { - hasError = true - fmt.Fprintf(dockerCli.Err(), "Failed to remove config %s: %s", config.ID, err) - } - } - return hasError -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/remove_test.go b/vendor/github.com/docker/cli/cli/command/stack/remove_test.go deleted file mode 100644 index 0ce5cdacf..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/remove_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package stack - -import ( - "errors" - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/stretchr/testify/assert" -) - -func fakeClientForRemoveStackTest(version string) *fakeClient { - allServices := []string{ - objectName("foo", "service1"), - objectName("foo", "service2"), - objectName("bar", "service1"), - objectName("bar", "service2"), - } - allNetworks := []string{ - objectName("foo", "network1"), - objectName("bar", "network1"), - } - allSecrets := []string{ - objectName("foo", "secret1"), - objectName("foo", "secret2"), - objectName("bar", "secret1"), - } - allConfigs := []string{ - objectName("foo", "config1"), - objectName("foo", "config2"), - objectName("bar", "config1"), - } - return &fakeClient{ - version: version, - services: allServices, - networks: allNetworks, - secrets: allSecrets, - configs: allConfigs, - } -} - -func TestRemoveStackVersion124DoesNotRemoveConfigsOrSecrets(t *testing.T) { - client := fakeClientForRemoveStackTest("1.24") - cmd := newRemoveCommand(test.NewFakeCli(client)) - cmd.SetArgs([]string{"foo", "bar"}) - - assert.NoError(t, cmd.Execute()) - assert.Equal(t, buildObjectIDs(client.services), client.removedServices) - assert.Equal(t, buildObjectIDs(client.networks), client.removedNetworks) - assert.Nil(t, client.removedSecrets) - assert.Nil(t, client.removedConfigs) -} - -func TestRemoveStackVersion125DoesNotRemoveConfigs(t *testing.T) { - client := fakeClientForRemoveStackTest("1.25") - cmd := newRemoveCommand(test.NewFakeCli(client)) - cmd.SetArgs([]string{"foo", "bar"}) - - assert.NoError(t, cmd.Execute()) - assert.Equal(t, buildObjectIDs(client.services), client.removedServices) - assert.Equal(t, buildObjectIDs(client.networks), client.removedNetworks) - assert.Equal(t, buildObjectIDs(client.secrets), client.removedSecrets) - assert.Nil(t, client.removedConfigs) -} - -func TestRemoveStackVersion130RemovesEverything(t *testing.T) { - client := fakeClientForRemoveStackTest("1.30") - cmd := newRemoveCommand(test.NewFakeCli(client)) - cmd.SetArgs([]string{"foo", "bar"}) - - assert.NoError(t, cmd.Execute()) - assert.Equal(t, buildObjectIDs(client.services), client.removedServices) - assert.Equal(t, buildObjectIDs(client.networks), client.removedNetworks) - assert.Equal(t, buildObjectIDs(client.secrets), client.removedSecrets) - assert.Equal(t, buildObjectIDs(client.configs), client.removedConfigs) -} - -func TestRemoveStackSkipEmpty(t *testing.T) { - allServices := []string{objectName("bar", "service1"), objectName("bar", "service2")} - allServiceIDs := buildObjectIDs(allServices) - - allNetworks := []string{objectName("bar", "network1")} - allNetworkIDs := buildObjectIDs(allNetworks) - - allSecrets := []string{objectName("bar", "secret1")} - allSecretIDs := buildObjectIDs(allSecrets) - - allConfigs := []string{objectName("bar", "config1")} - allConfigIDs := buildObjectIDs(allConfigs) - - fakeClient := &fakeClient{ - version: "1.30", - services: allServices, - networks: allNetworks, - secrets: allSecrets, - configs: allConfigs, - } - fakeCli := test.NewFakeCli(fakeClient) - cmd := newRemoveCommand(fakeCli) - cmd.SetArgs([]string{"foo", "bar"}) - - assert.NoError(t, cmd.Execute()) - expectedList := []string{"Removing service bar_service1", - "Removing service bar_service2", - "Removing secret bar_secret1", - "Removing config bar_config1", - "Removing network bar_network1\n", - } - assert.Equal(t, strings.Join(expectedList, "\n"), fakeCli.OutBuffer().String()) - assert.Contains(t, fakeCli.ErrBuffer().String(), "Nothing found in stack: foo\n") - assert.Equal(t, allServiceIDs, fakeClient.removedServices) - assert.Equal(t, allNetworkIDs, fakeClient.removedNetworks) - assert.Equal(t, allSecretIDs, fakeClient.removedSecrets) - assert.Equal(t, allConfigIDs, fakeClient.removedConfigs) -} - -func TestRemoveContinueAfterError(t *testing.T) { - allServices := []string{objectName("foo", "service1"), objectName("bar", "service1")} - allServiceIDs := buildObjectIDs(allServices) - - allNetworks := []string{objectName("foo", "network1"), objectName("bar", "network1")} - allNetworkIDs := buildObjectIDs(allNetworks) - - allSecrets := []string{objectName("foo", "secret1"), objectName("bar", "secret1")} - allSecretIDs := buildObjectIDs(allSecrets) - - allConfigs := []string{objectName("foo", "config1"), objectName("bar", "config1")} - allConfigIDs := buildObjectIDs(allConfigs) - - removedServices := []string{} - cli := &fakeClient{ - version: "1.30", - services: allServices, - networks: allNetworks, - secrets: allSecrets, - configs: allConfigs, - - serviceRemoveFunc: func(serviceID string) error { - removedServices = append(removedServices, serviceID) - - if strings.Contains(serviceID, "foo") { - return errors.New("") - } - return nil - }, - } - cmd := newRemoveCommand(test.NewFakeCli(cli)) - cmd.SetOutput(ioutil.Discard) - cmd.SetArgs([]string{"foo", "bar"}) - - assert.EqualError(t, cmd.Execute(), "Failed to remove some resources from stack: foo") - assert.Equal(t, allServiceIDs, removedServices) - assert.Equal(t, allNetworkIDs, cli.removedNetworks) - assert.Equal(t, allSecretIDs, cli.removedSecrets) - assert.Equal(t, allConfigIDs, cli.removedConfigs) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/services.go b/vendor/github.com/docker/cli/cli/command/stack/services.go deleted file mode 100644 index 94fcb8bde..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/services.go +++ /dev/null @@ -1,94 +0,0 @@ -package stack - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/service" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type servicesOptions struct { - quiet bool - format string - filter opts.FilterOpt - namespace string -} - -func newServicesCommand(dockerCli command.Cli) *cobra.Command { - options := servicesOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "services [OPTIONS] STACK", - Short: "List the services in the stack", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.namespace = args[0] - return runServices(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print services using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runServices(dockerCli command.Cli, options servicesOptions) error { - ctx := context.Background() - client := dockerCli.Client() - - filter := getStackFilterFromOpt(options.namespace, options.filter) - services, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: filter}) - if err != nil { - return err - } - - // if no services in this stack, print message and exit 0 - if len(services) == 0 { - fmt.Fprintf(dockerCli.Err(), "Nothing found in stack: %s\n", options.namespace) - return nil - } - - info := map[string]formatter.ServiceListInfo{} - if !options.quiet { - taskFilter := filters.NewArgs() - for _, service := range services { - taskFilter.Add("service", service.ID) - } - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter}) - if err != nil { - return err - } - - nodes, err := client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return err - } - - info = service.GetServicesStatus(services, nodes, tasks) - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().ServicesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().ServicesFormat - } else { - format = formatter.TableFormatKey - } - } - - servicesCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewServiceListFormat(format, options.quiet), - } - return formatter.ServiceListWrite(servicesCtx, services, info) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/services_test.go b/vendor/github.com/docker/cli/cli/command/stack/services_test.go deleted file mode 100644 index 2f6d6e0e0..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/services_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package stack - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestStackServicesErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error) - nodeListFunc func(options types.NodeListOptions) ([]swarm.Node, error) - taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error) - expectedError string - }{ - { - args: []string{"foo"}, - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return nil, errors.Errorf("error getting services") - }, - expectedError: "error getting services", - }, - { - args: []string{"foo"}, - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{*Service()}, nil - }, - nodeListFunc: func(options types.NodeListOptions) ([]swarm.Node, error) { - return nil, errors.Errorf("error getting nodes") - }, - expectedError: "error getting nodes", - }, - { - args: []string{"foo"}, - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{*Service()}, nil - }, - taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) { - return nil, errors.Errorf("error getting tasks") - }, - expectedError: "error getting tasks", - }, - { - args: []string{"foo"}, - flags: map[string]string{ - "format": "{{invalid format}}", - }, - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{*Service()}, nil - }, - expectedError: "Template parsing error", - }, - } - - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: tc.serviceListFunc, - nodeListFunc: tc.nodeListFunc, - taskListFunc: tc.taskListFunc, - }) - cmd := newServicesCommand(cli) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestStackServicesEmptyServiceList(t *testing.T) { - fakeCli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{}, nil - }, - }) - cmd := newServicesCommand(fakeCli) - cmd.SetArgs([]string{"foo"}) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "", fakeCli.OutBuffer().String()) - assert.Equal(t, "Nothing found in stack: foo\n", fakeCli.ErrBuffer().String()) -} - -func TestStackServicesWithQuietOption(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{*Service(ServiceID("id-foo"))}, nil - }, - }) - cmd := newServicesCommand(cli) - cmd.Flags().Set("quiet", "true") - cmd.SetArgs([]string{"foo"}) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-services-with-quiet-option.golden") -} - -func TestStackServicesWithFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - *Service(ServiceName("service-name-foo")), - }, nil - }, - }) - cmd := newServicesCommand(cli) - cmd.SetArgs([]string{"foo"}) - cmd.Flags().Set("format", "{{ .Name }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-services-with-format.golden") -} - -func TestStackServicesWithConfigFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{ - *Service(ServiceName("service-name-foo")), - }, nil - }, - }) - cli.SetConfigFile(&configfile.ConfigFile{ - ServicesFormat: "{{ .Name }}", - }) - cmd := newServicesCommand(cli) - cmd.SetArgs([]string{"foo"}) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-services-with-config-format.golden") -} - -func TestStackServicesWithoutFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) { - return []swarm.Service{*Service( - ServiceName("name-foo"), - ServiceID("id-foo"), - ReplicatedService(2), - ServiceImage("busybox:latest"), - ServicePort(swarm.PortConfig{ - PublishMode: swarm.PortConfigPublishModeIngress, - PublishedPort: 0, - TargetPort: 3232, - Protocol: swarm.PortConfigProtocolTCP, - }), - )}, nil - }, - }) - cmd := newServicesCommand(cli) - cmd.SetArgs([]string{"foo"}) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "stack-services-without-format.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/bundlefile_with_two_services.dab b/vendor/github.com/docker/cli/cli/command/stack/testdata/bundlefile_with_two_services.dab deleted file mode 100644 index ced8180dc..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/bundlefile_with_two_services.dab +++ /dev/null @@ -1,29 +0,0 @@ -{ - "Services": { - "visualizer": { - "Image": "busybox@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f", - "Networks": [ - "webnet" - ], - "Ports": [ - { - "Port": 8080, - "Protocol": "tcp" - } - ] - }, - "web": { - "Image": "busybox@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f", - "Networks": [ - "webnet" - ], - "Ports": [ - { - "Port": 80, - "Protocol": "tcp" - } - ] - } - }, - "Version": "0.1" -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-sort-natural.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-sort-natural.golden deleted file mode 100644 index 71eb63fd3..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-sort-natural.golden +++ /dev/null @@ -1,4 +0,0 @@ -NAME SERVICES -service-name-1-foo 1 -service-name-2-foo 1 -service-name-10-foo 1 diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-sort.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-sort.golden deleted file mode 100644 index 6bd116ebc..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-sort.golden +++ /dev/null @@ -1,3 +0,0 @@ -NAME SERVICES -service-name-bar 1 -service-name-foo 1 diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-with-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-with-format.golden deleted file mode 100644 index b53e6401f..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-with-format.golden +++ /dev/null @@ -1 +0,0 @@ -service-name-foo diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-without-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-without-format.golden deleted file mode 100644 index 1b255654d..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-list-without-format.golden +++ /dev/null @@ -1,2 +0,0 @@ -NAME SERVICES -service-name-foo 1 diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-config-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-config-format.golden deleted file mode 100644 index 9ecebdafe..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-config-format.golden +++ /dev/null @@ -1 +0,0 @@ -service-id-foo.1 diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-format.golden deleted file mode 100644 index 9ecebdafe..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-format.golden +++ /dev/null @@ -1 +0,0 @@ -service-id-foo.1 diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-no-resolve-option.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-no-resolve-option.golden deleted file mode 100644 index b90d743b8..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-no-resolve-option.golden +++ /dev/null @@ -1 +0,0 @@ -id-node-foo diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-no-trunc-option.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-no-trunc-option.golden deleted file mode 100644 index 8179bf4d6..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-no-trunc-option.golden +++ /dev/null @@ -1 +0,0 @@ -xn4cypcov06f2w8gsbaf2lst3 diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-quiet-option.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-quiet-option.golden deleted file mode 100644 index e2faeb606..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-with-quiet-option.golden +++ /dev/null @@ -1 +0,0 @@ -id-foo diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-without-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-without-format.golden deleted file mode 100644 index ceb4f8411..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-ps-without-format.golden +++ /dev/null @@ -1,2 +0,0 @@ -ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -id-foo service-id-foo.1 myimage:mytag node-name-bar Ready Failed 2 hours ago diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-config-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-config-format.golden deleted file mode 100644 index b53e6401f..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-config-format.golden +++ /dev/null @@ -1 +0,0 @@ -service-name-foo diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-format.golden deleted file mode 100644 index b53e6401f..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-format.golden +++ /dev/null @@ -1 +0,0 @@ -service-name-foo diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-quiet-option.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-quiet-option.golden deleted file mode 100644 index e2faeb606..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-with-quiet-option.golden +++ /dev/null @@ -1 +0,0 @@ -id-foo diff --git a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-without-format.golden b/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-without-format.golden deleted file mode 100644 index dcca0dfae..000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/testdata/stack-services-without-format.golden +++ /dev/null @@ -1,2 +0,0 @@ -ID NAME MODE REPLICAS IMAGE PORTS -id-foo name-foo replicated 0/2 busybox:latest *:30000->3232/tcp diff --git a/vendor/github.com/docker/cli/cli/command/stream.go b/vendor/github.com/docker/cli/cli/command/stream.go deleted file mode 100644 index 71a43fa2e..000000000 --- a/vendor/github.com/docker/cli/cli/command/stream.go +++ /dev/null @@ -1,34 +0,0 @@ -package command - -import ( - "github.com/docker/docker/pkg/term" -) - -// CommonStream is an input stream used by the DockerCli to read user input -type CommonStream struct { - fd uintptr - isTerminal bool - state *term.State -} - -// FD returns the file descriptor number for this stream -func (s *CommonStream) FD() uintptr { - return s.fd -} - -// IsTerminal returns true if this stream is connected to a terminal -func (s *CommonStream) IsTerminal() bool { - return s.isTerminal -} - -// RestoreTerminal restores normal mode to the terminal -func (s *CommonStream) RestoreTerminal() { - if s.state != nil { - term.RestoreTerminal(s.fd, s.state) - } -} - -// SetIsTerminal sets the boolean used for isTerminal -func (s *CommonStream) SetIsTerminal(isTerminal bool) { - s.isTerminal = isTerminal -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/ca.go b/vendor/github.com/docker/cli/cli/command/swarm/ca.go deleted file mode 100644 index 1c2f2d268..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/ca.go +++ /dev/null @@ -1,135 +0,0 @@ -package swarm - -import ( - "fmt" - "io" - "io/ioutil" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/swarm/progress" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -type caOptions struct { - swarmCAOptions - rootCACert PEMFile - rootCAKey PEMFile - rotate bool - detach bool - quiet bool -} - -func newCACommand(dockerCli command.Cli) *cobra.Command { - opts := caOptions{} - - cmd := &cobra.Command{ - Use: "ca [OPTIONS]", - Short: "Display and rotate the root CA", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runCA(dockerCli, cmd.Flags(), opts) - }, - Tags: map[string]string{"version": "1.30"}, - } - - flags := cmd.Flags() - addSwarmCAFlags(flags, &opts.swarmCAOptions) - flags.BoolVar(&opts.rotate, flagRotate, false, "Rotate the swarm CA - if no certificate or key are provided, new ones will be generated") - flags.Var(&opts.rootCACert, flagCACert, "Path to the PEM-formatted root CA certificate to use for the new cluster") - flags.Var(&opts.rootCAKey, flagCAKey, "Path to the PEM-formatted root CA key to use for the new cluster") - - flags.BoolVarP(&opts.detach, "detach", "d", false, "Exit immediately instead of waiting for the root rotation to converge") - flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress progress output") - return cmd -} - -func runCA(dockerCli command.Cli, flags *pflag.FlagSet, opts caOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - swarmInspect, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if !opts.rotate { - for _, f := range []string{flagCACert, flagCAKey, flagCertExpiry, flagExternalCA} { - if flags.Changed(f) { - return fmt.Errorf("`--%s` flag requires the `--rotate` flag to update the CA", f) - } - } - return displayTrustRoot(dockerCli.Out(), swarmInspect) - } - - updateSwarmSpec(&swarmInspect.Spec, flags, opts) - if err := client.SwarmUpdate(ctx, swarmInspect.Version, swarmInspect.Spec, swarm.UpdateFlags{}); err != nil { - return err - } - - if opts.detach { - return nil - } - return attach(ctx, dockerCli, opts) -} - -func updateSwarmSpec(spec *swarm.Spec, flags *pflag.FlagSet, opts caOptions) { - opts.mergeSwarmSpecCAFlags(spec, flags) - caCert := opts.rootCACert.Contents() - caKey := opts.rootCAKey.Contents() - - if caCert != "" { - spec.CAConfig.SigningCACert = caCert - } - if caKey != "" { - spec.CAConfig.SigningCAKey = caKey - } - if caKey == "" && caCert == "" { - spec.CAConfig.ForceRotate++ - spec.CAConfig.SigningCACert = "" - spec.CAConfig.SigningCAKey = "" - } -} - -func attach(ctx context.Context, dockerCli command.Cli, opts caOptions) error { - client := dockerCli.Client() - errChan := make(chan error, 1) - pipeReader, pipeWriter := io.Pipe() - - go func() { - errChan <- progress.RootRotationProgress(ctx, client, pipeWriter) - }() - - if opts.quiet { - go io.Copy(ioutil.Discard, pipeReader) - return <-errChan - } - - err := jsonmessage.DisplayJSONMessagesToStream(pipeReader, dockerCli.Out(), nil) - if err == nil { - err = <-errChan - } - if err != nil { - return err - } - - swarmInspect, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - return displayTrustRoot(dockerCli.Out(), swarmInspect) -} - -func displayTrustRoot(out io.Writer, info swarm.Swarm) error { - if info.ClusterInfo.TLSInfo.TrustRoot == "" { - return errors.New("No CA information available") - } - fmt.Fprintln(out, strings.TrimSpace(info.ClusterInfo.TLSInfo.TrustRoot)) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/ca_test.go b/vendor/github.com/docker/cli/cli/command/swarm/ca_test.go deleted file mode 100644 index cb2668293..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/ca_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package swarm - -import ( - "bytes" - "io/ioutil" - "os" - "testing" - "time" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types/swarm" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func swarmSpecWithFullCAConfig() *swarm.Spec { - return &swarm.Spec{ - CAConfig: swarm.CAConfig{ - SigningCACert: "cacert", - SigningCAKey: "cakey", - ForceRotate: 1, - NodeCertExpiry: time.Duration(200), - ExternalCAs: []*swarm.ExternalCA{ - { - URL: "https://example.com/ca", - Protocol: swarm.ExternalCAProtocolCFSSL, - CACert: "excacert", - }, - }, - }, - } -} - -func TestDisplayTrustRootNoRoot(t *testing.T) { - buffer := new(bytes.Buffer) - err := displayTrustRoot(buffer, swarm.Swarm{}) - assert.EqualError(t, err, "No CA information available") -} - -func TestDisplayTrustRootInvalidFlags(t *testing.T) { - // we need an actual PEMfile to test - tmpfile, err := ioutil.TempFile("", "pemfile") - assert.NoError(t, err) - defer os.Remove(tmpfile.Name()) - tmpfile.Write([]byte(` ------BEGIN CERTIFICATE----- -MIIBajCCARCgAwIBAgIUe0+jYWhxN8fFOByC7yveIYgvx1kwCgYIKoZIzj0EAwIw -EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcwNjI3MTUxNDAwWhcNMzcwNjIyMTUx -NDAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH -A0IABGgbOZLd7b4b262+6m4ignIecbAZKim6djNiIS1Kl5IHciXYn7gnSpsayjn7 -GQABpgkdPeM9TEQowmtR1qSnORujQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB -Af8EBTADAQH/MB0GA1UdDgQWBBQ6Rtcn823/fxRZyheRDFpDzuBMpTAKBggqhkjO -PQQDAgNIADBFAiEAqD3Kb2rgsy6NoTk+zEgcUi/aGBCsvQDG3vML1PXN8j0CIBjj -4nDj+GmHXcnKa8wXx70Z8OZEpRQIiKDDLmcXuslp ------END CERTIFICATE----- -`)) - tmpfile.Close() - - errorTestCases := [][]string{ - { - "--ca-cert=" + tmpfile.Name(), - }, - { - "--ca-key=" + tmpfile.Name(), - }, - { // to make sure we're not erroring because we didn't provide a CA key along with the CA cert - - "--ca-cert=" + tmpfile.Name(), - "--ca-key=" + tmpfile.Name(), - }, - { - "--cert-expiry=2160h0m0s", - }, - { - "--external-ca=protocol=cfssl,url=https://some.com/https/url", - }, - { // to make sure we're not erroring because we didn't provide a CA cert and external CA - - "--ca-cert=" + tmpfile.Name(), - "--external-ca=protocol=cfssl,url=https://some.com/https/url", - }, - } - - for _, args := range errorTestCases { - cmd := newCACommand( - test.NewFakeCli(&fakeClient{ - swarmInspectFunc: func() (swarm.Swarm, error) { - return swarm.Swarm{ - ClusterInfo: swarm.ClusterInfo{ - TLSInfo: swarm.TLSInfo{ - TrustRoot: "root", - }, - }, - }, nil - }, - })) - assert.NoError(t, cmd.Flags().Parse(args)) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), "flag requires the `--rotate` flag to update the CA") - } -} - -func TestDisplayTrustRoot(t *testing.T) { - buffer := new(bytes.Buffer) - trustRoot := "trustme" - err := displayTrustRoot(buffer, swarm.Swarm{ - ClusterInfo: swarm.ClusterInfo{ - TLSInfo: swarm.TLSInfo{TrustRoot: trustRoot}, - }, - }) - require.NoError(t, err) - assert.Equal(t, trustRoot+"\n", buffer.String()) -} - -func TestUpdateSwarmSpecDefaultRotate(t *testing.T) { - spec := swarmSpecWithFullCAConfig() - flags := newCACommand(nil).Flags() - updateSwarmSpec(spec, flags, caOptions{}) - - expected := swarmSpecWithFullCAConfig() - expected.CAConfig.ForceRotate = 2 - expected.CAConfig.SigningCACert = "" - expected.CAConfig.SigningCAKey = "" - assert.Equal(t, expected, spec) -} - -func TestUpdateSwarmSpecPartial(t *testing.T) { - spec := swarmSpecWithFullCAConfig() - flags := newCACommand(nil).Flags() - updateSwarmSpec(spec, flags, caOptions{ - rootCACert: PEMFile{contents: "cacert"}, - }) - - expected := swarmSpecWithFullCAConfig() - expected.CAConfig.SigningCACert = "cacert" - assert.Equal(t, expected, spec) -} - -func TestUpdateSwarmSpecFullFlags(t *testing.T) { - flags := newCACommand(nil).Flags() - flags.Lookup(flagCertExpiry).Changed = true - spec := swarmSpecWithFullCAConfig() - updateSwarmSpec(spec, flags, caOptions{ - rootCACert: PEMFile{contents: "cacert"}, - rootCAKey: PEMFile{contents: "cakey"}, - swarmCAOptions: swarmCAOptions{nodeCertExpiry: 3 * time.Minute}, - }) - - expected := swarmSpecWithFullCAConfig() - expected.CAConfig.SigningCACert = "cacert" - expected.CAConfig.SigningCAKey = "cakey" - expected.CAConfig.NodeCertExpiry = 3 * time.Minute - assert.Equal(t, expected, spec) -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/client_test.go b/vendor/github.com/docker/cli/cli/command/swarm/client_test.go deleted file mode 100644 index 1d42b9499..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/client_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package swarm - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - infoFunc func() (types.Info, error) - swarmInitFunc func() (string, error) - swarmInspectFunc func() (swarm.Swarm, error) - nodeInspectFunc func() (swarm.Node, []byte, error) - swarmGetUnlockKeyFunc func() (types.SwarmUnlockKeyResponse, error) - swarmJoinFunc func() error - swarmLeaveFunc func() error - swarmUpdateFunc func(swarm swarm.Spec, flags swarm.UpdateFlags) error - swarmUnlockFunc func(req swarm.UnlockRequest) error -} - -func (cli *fakeClient) Info(ctx context.Context) (types.Info, error) { - if cli.infoFunc != nil { - return cli.infoFunc() - } - return types.Info{}, nil -} - -func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) { - if cli.nodeInspectFunc != nil { - return cli.nodeInspectFunc() - } - return swarm.Node{}, []byte{}, nil -} - -func (cli *fakeClient) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { - if cli.swarmInitFunc != nil { - return cli.swarmInitFunc() - } - return "", nil -} - -func (cli *fakeClient) SwarmInspect(ctx context.Context) (swarm.Swarm, error) { - if cli.swarmInspectFunc != nil { - return cli.swarmInspectFunc() - } - return swarm.Swarm{}, nil -} - -func (cli *fakeClient) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) { - if cli.swarmGetUnlockKeyFunc != nil { - return cli.swarmGetUnlockKeyFunc() - } - return types.SwarmUnlockKeyResponse{}, nil -} - -func (cli *fakeClient) SwarmJoin(ctx context.Context, req swarm.JoinRequest) error { - if cli.swarmJoinFunc != nil { - return cli.swarmJoinFunc() - } - return nil -} - -func (cli *fakeClient) SwarmLeave(ctx context.Context, force bool) error { - if cli.swarmLeaveFunc != nil { - return cli.swarmLeaveFunc() - } - return nil -} - -func (cli *fakeClient) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error { - if cli.swarmUpdateFunc != nil { - return cli.swarmUpdateFunc(swarm, flags) - } - return nil -} - -func (cli *fakeClient) SwarmUnlock(ctx context.Context, req swarm.UnlockRequest) error { - if cli.swarmUnlockFunc != nil { - return cli.swarmUnlockFunc(req) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/cmd.go b/vendor/github.com/docker/cli/cli/command/swarm/cmd.go deleted file mode 100644 index d2793f6b9..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/cmd.go +++ /dev/null @@ -1,31 +0,0 @@ -package swarm - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewSwarmCommand returns a cobra command for `swarm` subcommands -// nolint: interfacer -func NewSwarmCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "swarm", - Short: "Manage Swarm", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.24"}, - } - cmd.AddCommand( - newInitCommand(dockerCli), - newJoinCommand(dockerCli), - newJoinTokenCommand(dockerCli), - newUnlockKeyCommand(dockerCli), - newUpdateCommand(dockerCli), - newLeaveCommand(dockerCli), - newUnlockCommand(dockerCli), - newCACommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/init.go b/vendor/github.com/docker/cli/cli/command/swarm/init.go deleted file mode 100644 index 91b827eb9..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/init.go +++ /dev/null @@ -1,99 +0,0 @@ -package swarm - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -type initOptions struct { - swarmOptions - listenAddr NodeAddrOption - // Not a NodeAddrOption because it has no default port. - advertiseAddr string - dataPathAddr string - forceNewCluster bool - availability string -} - -func newInitCommand(dockerCli command.Cli) *cobra.Command { - opts := initOptions{ - listenAddr: NewListenAddrOption(), - } - - cmd := &cobra.Command{ - Use: "init [OPTIONS]", - Short: "Initialize a swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runInit(dockerCli, cmd.Flags(), opts) - }, - } - - flags := cmd.Flags() - flags.Var(&opts.listenAddr, flagListenAddr, "Listen address (format: [:port])") - flags.StringVar(&opts.advertiseAddr, flagAdvertiseAddr, "", "Advertised address (format: [:port])") - flags.StringVar(&opts.dataPathAddr, flagDataPathAddr, "", "Address or interface to use for data path traffic (format: )") - flags.BoolVar(&opts.forceNewCluster, "force-new-cluster", false, "Force create a new cluster from current state") - flags.BoolVar(&opts.autolock, flagAutolock, false, "Enable manager autolocking (requiring an unlock key to start a stopped manager)") - flags.StringVar(&opts.availability, flagAvailability, "active", `Availability of the node ("active"|"pause"|"drain")`) - addSwarmFlags(flags, &opts.swarmOptions) - return cmd -} - -func runInit(dockerCli command.Cli, flags *pflag.FlagSet, opts initOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - req := swarm.InitRequest{ - ListenAddr: opts.listenAddr.String(), - AdvertiseAddr: opts.advertiseAddr, - DataPathAddr: opts.dataPathAddr, - ForceNewCluster: opts.forceNewCluster, - Spec: opts.swarmOptions.ToSpec(flags), - AutoLockManagers: opts.swarmOptions.autolock, - } - if flags.Changed(flagAvailability) { - availability := swarm.NodeAvailability(strings.ToLower(opts.availability)) - switch availability { - case swarm.NodeAvailabilityActive, swarm.NodeAvailabilityPause, swarm.NodeAvailabilityDrain: - req.Availability = availability - default: - return errors.Errorf("invalid availability %q, only active, pause and drain are supported", opts.availability) - } - } - - nodeID, err := client.SwarmInit(ctx, req) - if err != nil { - if strings.Contains(err.Error(), "could not choose an IP address to advertise") || strings.Contains(err.Error(), "could not find the system's IP address") { - return errors.New(err.Error() + " - specify one with --advertise-addr") - } - return err - } - - fmt.Fprintf(dockerCli.Out(), "Swarm initialized: current node (%s) is now a manager.\n\n", nodeID) - - if err := printJoinCommand(ctx, dockerCli, nodeID, true, false); err != nil { - return err - } - - fmt.Fprint(dockerCli.Out(), "To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.\n\n") - - if req.AutoLockManagers { - unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) - if err != nil { - return errors.Wrap(err, "could not fetch unlock key") - } - printUnlockCommand(dockerCli.Out(), unlockKeyResp.UnlockKey) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/init_test.go b/vendor/github.com/docker/cli/cli/command/swarm/init_test.go deleted file mode 100644 index 24a1b9071..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/init_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package swarm - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestSwarmInitErrorOnAPIFailure(t *testing.T) { - testCases := []struct { - name string - flags map[string]string - swarmInitFunc func() (string, error) - swarmInspectFunc func() (swarm.Swarm, error) - swarmGetUnlockKeyFunc func() (types.SwarmUnlockKeyResponse, error) - nodeInspectFunc func() (swarm.Node, []byte, error) - expectedError string - }{ - { - name: "init-failed", - swarmInitFunc: func() (string, error) { - return "", errors.Errorf("error initializing the swarm") - }, - expectedError: "error initializing the swarm", - }, - { - name: "init-failed-with-ip-choice", - swarmInitFunc: func() (string, error) { - return "", errors.Errorf("could not choose an IP address to advertise") - }, - expectedError: "could not choose an IP address to advertise - specify one with --advertise-addr", - }, - { - name: "swarm-inspect-after-init-failed", - swarmInspectFunc: func() (swarm.Swarm, error) { - return swarm.Swarm{}, errors.Errorf("error inspecting the swarm") - }, - expectedError: "error inspecting the swarm", - }, - { - name: "node-inspect-after-init-failed", - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting the node") - }, - expectedError: "error inspecting the node", - }, - { - name: "swarm-get-unlock-key-after-init-failed", - flags: map[string]string{ - flagAutolock: "true", - }, - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{}, errors.Errorf("error getting swarm unlock key") - }, - expectedError: "could not fetch unlock key: error getting swarm unlock key", - }, - } - for _, tc := range testCases { - cmd := newInitCommand( - test.NewFakeCli(&fakeClient{ - swarmInitFunc: tc.swarmInitFunc, - swarmInspectFunc: tc.swarmInspectFunc, - swarmGetUnlockKeyFunc: tc.swarmGetUnlockKeyFunc, - nodeInspectFunc: tc.nodeInspectFunc, - })) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - assert.EqualError(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSwarmInit(t *testing.T) { - testCases := []struct { - name string - flags map[string]string - swarmInitFunc func() (string, error) - swarmInspectFunc func() (swarm.Swarm, error) - swarmGetUnlockKeyFunc func() (types.SwarmUnlockKeyResponse, error) - nodeInspectFunc func() (swarm.Node, []byte, error) - }{ - { - name: "init", - swarmInitFunc: func() (string, error) { - return "nodeID", nil - }, - }, - { - name: "init-autolock", - flags: map[string]string{ - flagAutolock: "true", - }, - swarmInitFunc: func() (string, error) { - return "nodeID", nil - }, - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{ - UnlockKey: "unlock-key", - }, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - swarmInitFunc: tc.swarmInitFunc, - swarmInspectFunc: tc.swarmInspectFunc, - swarmGetUnlockKeyFunc: tc.swarmGetUnlockKeyFunc, - nodeInspectFunc: tc.nodeInspectFunc, - }) - cmd := newInitCommand(cli) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("init-%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/join.go b/vendor/github.com/docker/cli/cli/command/swarm/join.go deleted file mode 100644 index 0f09527d0..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/join.go +++ /dev/null @@ -1,88 +0,0 @@ -package swarm - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -type joinOptions struct { - remote string - listenAddr NodeAddrOption - // Not a NodeAddrOption because it has no default port. - advertiseAddr string - dataPathAddr string - token string - availability string -} - -func newJoinCommand(dockerCli command.Cli) *cobra.Command { - opts := joinOptions{ - listenAddr: NewListenAddrOption(), - } - - cmd := &cobra.Command{ - Use: "join [OPTIONS] HOST:PORT", - Short: "Join a swarm as a node and/or manager", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.remote = args[0] - return runJoin(dockerCli, cmd.Flags(), opts) - }, - } - - flags := cmd.Flags() - flags.Var(&opts.listenAddr, flagListenAddr, "Listen address (format: [:port])") - flags.StringVar(&opts.advertiseAddr, flagAdvertiseAddr, "", "Advertised address (format: [:port])") - flags.StringVar(&opts.dataPathAddr, flagDataPathAddr, "", "Address or interface to use for data path traffic (format: )") - flags.StringVar(&opts.token, flagToken, "", "Token for entry into the swarm") - flags.StringVar(&opts.availability, flagAvailability, "active", `Availability of the node ("active"|"pause"|"drain")`) - return cmd -} - -func runJoin(dockerCli command.Cli, flags *pflag.FlagSet, opts joinOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - req := swarm.JoinRequest{ - JoinToken: opts.token, - ListenAddr: opts.listenAddr.String(), - AdvertiseAddr: opts.advertiseAddr, - DataPathAddr: opts.dataPathAddr, - RemoteAddrs: []string{opts.remote}, - } - if flags.Changed(flagAvailability) { - availability := swarm.NodeAvailability(strings.ToLower(opts.availability)) - switch availability { - case swarm.NodeAvailabilityActive, swarm.NodeAvailabilityPause, swarm.NodeAvailabilityDrain: - req.Availability = availability - default: - return errors.Errorf("invalid availability %q, only active, pause and drain are supported", opts.availability) - } - } - - err := client.SwarmJoin(ctx, req) - if err != nil { - return err - } - - info, err := client.Info(ctx) - if err != nil { - return err - } - - if info.Swarm.ControlAvailable { - fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a manager.") - } else { - fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a worker.") - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/join_test.go b/vendor/github.com/docker/cli/cli/command/swarm/join_test.go deleted file mode 100644 index 69546cd8c..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/join_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package swarm - -import ( - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestSwarmJoinErrors(t *testing.T) { - testCases := []struct { - name string - args []string - swarmJoinFunc func() error - infoFunc func() (types.Info, error) - expectedError string - }{ - { - name: "not-enough-args", - expectedError: "requires exactly 1 argument", - }, - { - name: "too-many-args", - args: []string{"remote1", "remote2"}, - expectedError: "requires exactly 1 argument", - }, - { - name: "join-failed", - args: []string{"remote"}, - swarmJoinFunc: func() error { - return errors.Errorf("error joining the swarm") - }, - expectedError: "error joining the swarm", - }, - { - name: "join-failed-on-init", - args: []string{"remote"}, - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error asking for node info") - }, - expectedError: "error asking for node info", - }, - } - for _, tc := range testCases { - cmd := newJoinCommand( - test.NewFakeCli(&fakeClient{ - swarmJoinFunc: tc.swarmJoinFunc, - infoFunc: tc.infoFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSwarmJoin(t *testing.T) { - testCases := []struct { - name string - infoFunc func() (types.Info, error) - expected string - }{ - { - name: "join-as-manager", - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - ControlAvailable: true, - }, - }, nil - }, - expected: "This node joined a swarm as a manager.", - }, - { - name: "join-as-worker", - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - ControlAvailable: false, - }, - }, nil - }, - expected: "This node joined a swarm as a worker.", - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - infoFunc: tc.infoFunc, - }) - cmd := newJoinCommand(cli) - cmd.SetArgs([]string{"remote"}) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, strings.TrimSpace(cli.OutBuffer().String()), tc.expected) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/join_token.go b/vendor/github.com/docker/cli/cli/command/swarm/join_token.go deleted file mode 100644 index b35efad8a..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/join_token.go +++ /dev/null @@ -1,119 +0,0 @@ -package swarm - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type joinTokenOptions struct { - role string - rotate bool - quiet bool -} - -func newJoinTokenCommand(dockerCli command.Cli) *cobra.Command { - opts := joinTokenOptions{} - - cmd := &cobra.Command{ - Use: "join-token [OPTIONS] (worker|manager)", - Short: "Manage join tokens", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.role = args[0] - return runJoinToken(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVar(&opts.rotate, flagRotate, false, "Rotate join token") - flags.BoolVarP(&opts.quiet, flagQuiet, "q", false, "Only display token") - - return cmd -} - -func runJoinToken(dockerCli command.Cli, opts joinTokenOptions) error { - worker := opts.role == "worker" - manager := opts.role == "manager" - - if !worker && !manager { - return errors.New("unknown role " + opts.role) - } - - client := dockerCli.Client() - ctx := context.Background() - - if opts.rotate { - flags := swarm.UpdateFlags{ - RotateWorkerToken: worker, - RotateManagerToken: manager, - } - - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if err := client.SwarmUpdate(ctx, sw.Version, sw.Spec, flags); err != nil { - return err - } - - if !opts.quiet { - fmt.Fprintf(dockerCli.Out(), "Successfully rotated %s join token.\n\n", opts.role) - } - } - - // second SwarmInspect in this function, - // this is necessary since SwarmUpdate after first changes the join tokens - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if opts.quiet && worker { - fmt.Fprintln(dockerCli.Out(), sw.JoinTokens.Worker) - return nil - } - - if opts.quiet && manager { - fmt.Fprintln(dockerCli.Out(), sw.JoinTokens.Manager) - return nil - } - - info, err := client.Info(ctx) - if err != nil { - return err - } - - return printJoinCommand(ctx, dockerCli, info.Swarm.NodeID, worker, manager) -} - -func printJoinCommand(ctx context.Context, dockerCli command.Cli, nodeID string, worker bool, manager bool) error { - client := dockerCli.Client() - - node, _, err := client.NodeInspectWithRaw(ctx, nodeID) - if err != nil { - return err - } - - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if node.ManagerStatus != nil { - if worker { - fmt.Fprintf(dockerCli.Out(), "To add a worker to this swarm, run the following command:\n\n docker swarm join --token %s %s\n\n", sw.JoinTokens.Worker, node.ManagerStatus.Addr) - } - if manager { - fmt.Fprintf(dockerCli.Out(), "To add a manager to this swarm, run the following command:\n\n docker swarm join --token %s %s\n\n", sw.JoinTokens.Manager, node.ManagerStatus.Addr) - } - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/join_token_test.go b/vendor/github.com/docker/cli/cli/command/swarm/join_token_test.go deleted file mode 100644 index 6ab503113..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/join_token_test.go +++ /dev/null @@ -1,212 +0,0 @@ -package swarm - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestSwarmJoinTokenErrors(t *testing.T) { - testCases := []struct { - name string - args []string - flags map[string]string - infoFunc func() (types.Info, error) - swarmInspectFunc func() (swarm.Swarm, error) - swarmUpdateFunc func(swarm swarm.Spec, flags swarm.UpdateFlags) error - nodeInspectFunc func() (swarm.Node, []byte, error) - expectedError string - }{ - { - name: "not-enough-args", - expectedError: "requires exactly 1 argument", - }, - { - name: "too-many-args", - args: []string{"worker", "manager"}, - expectedError: "requires exactly 1 argument", - }, - { - name: "invalid-args", - args: []string{"foo"}, - expectedError: "unknown role foo", - }, - { - name: "swarm-inspect-failed", - args: []string{"worker"}, - swarmInspectFunc: func() (swarm.Swarm, error) { - return swarm.Swarm{}, errors.Errorf("error inspecting the swarm") - }, - expectedError: "error inspecting the swarm", - }, - { - name: "swarm-inspect-rotate-failed", - args: []string{"worker"}, - flags: map[string]string{ - flagRotate: "true", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return swarm.Swarm{}, errors.Errorf("error inspecting the swarm") - }, - expectedError: "error inspecting the swarm", - }, - { - name: "swarm-update-failed", - args: []string{"worker"}, - flags: map[string]string{ - flagRotate: "true", - }, - swarmUpdateFunc: func(swarm swarm.Spec, flags swarm.UpdateFlags) error { - return errors.Errorf("error updating the swarm") - }, - expectedError: "error updating the swarm", - }, - { - name: "node-inspect-failed", - args: []string{"worker"}, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return swarm.Node{}, []byte{}, errors.Errorf("error inspecting node") - }, - expectedError: "error inspecting node", - }, - { - name: "info-failed", - args: []string{"worker"}, - infoFunc: func() (types.Info, error) { - return types.Info{}, errors.Errorf("error asking for node info") - }, - expectedError: "error asking for node info", - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - swarmInspectFunc: tc.swarmInspectFunc, - swarmUpdateFunc: tc.swarmUpdateFunc, - infoFunc: tc.infoFunc, - nodeInspectFunc: tc.nodeInspectFunc, - }) - cmd := newJoinTokenCommand(cli) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSwarmJoinToken(t *testing.T) { - testCases := []struct { - name string - args []string - flags map[string]string - infoFunc func() (types.Info, error) - swarmInspectFunc func() (swarm.Swarm, error) - nodeInspectFunc func() (swarm.Node, []byte, error) - }{ - { - name: "worker", - args: []string{"worker"}, - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID", - }, - }, nil - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - }, - { - name: "manager", - args: []string{"manager"}, - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID", - }, - }, nil - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - }, - { - name: "manager-rotate", - args: []string{"manager"}, - flags: map[string]string{ - flagRotate: "true", - }, - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - NodeID: "nodeID", - }, - }, nil - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - }, - { - name: "worker-quiet", - args: []string{"worker"}, - flags: map[string]string{ - flagQuiet: "true", - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - }, - { - name: "manager-quiet", - args: []string{"manager"}, - flags: map[string]string{ - flagQuiet: "true", - }, - nodeInspectFunc: func() (swarm.Node, []byte, error) { - return *Node(Manager()), []byte{}, nil - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - swarmInspectFunc: tc.swarmInspectFunc, - infoFunc: tc.infoFunc, - nodeInspectFunc: tc.nodeInspectFunc, - }) - cmd := newJoinTokenCommand(cli) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("jointoken-%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/leave.go b/vendor/github.com/docker/cli/cli/command/swarm/leave.go deleted file mode 100644 index c9b33fd0d..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/leave.go +++ /dev/null @@ -1,44 +0,0 @@ -package swarm - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -type leaveOptions struct { - force bool -} - -func newLeaveCommand(dockerCli command.Cli) *cobra.Command { - opts := leaveOptions{} - - cmd := &cobra.Command{ - Use: "leave [OPTIONS]", - Short: "Leave the swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runLeave(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.force, "force", "f", false, "Force this node to leave the swarm, ignoring warnings") - return cmd -} - -func runLeave(dockerCli command.Cli, opts leaveOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if err := client.SwarmLeave(ctx, opts.force); err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), "Node left the swarm.") - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/leave_test.go b/vendor/github.com/docker/cli/cli/command/swarm/leave_test.go deleted file mode 100644 index cd8aeb829..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/leave_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package swarm - -import ( - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestSwarmLeaveErrors(t *testing.T) { - testCases := []struct { - name string - args []string - swarmLeaveFunc func() error - expectedError string - }{ - { - name: "too-many-args", - args: []string{"foo"}, - expectedError: "accepts no arguments", - }, - { - name: "leave-failed", - swarmLeaveFunc: func() error { - return errors.Errorf("error leaving the swarm") - }, - expectedError: "error leaving the swarm", - }, - } - for _, tc := range testCases { - cmd := newLeaveCommand( - test.NewFakeCli(&fakeClient{ - swarmLeaveFunc: tc.swarmLeaveFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSwarmLeave(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{}) - cmd := newLeaveCommand(cli) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, "Node left the swarm.", strings.TrimSpace(cli.OutBuffer().String())) -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/opts.go b/vendor/github.com/docker/cli/cli/command/swarm/opts.go deleted file mode 100644 index b3baba273..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/opts.go +++ /dev/null @@ -1,270 +0,0 @@ -package swarm - -import ( - "encoding/csv" - "encoding/pem" - "fmt" - "io/ioutil" - "strings" - "time" - - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/pflag" -) - -const ( - defaultListenAddr = "0.0.0.0:2377" - - flagCertExpiry = "cert-expiry" - flagDispatcherHeartbeat = "dispatcher-heartbeat" - flagListenAddr = "listen-addr" - flagAdvertiseAddr = "advertise-addr" - flagDataPathAddr = "data-path-addr" - flagQuiet = "quiet" - flagRotate = "rotate" - flagToken = "token" - flagTaskHistoryLimit = "task-history-limit" - flagExternalCA = "external-ca" - flagMaxSnapshots = "max-snapshots" - flagSnapshotInterval = "snapshot-interval" - flagAutolock = "autolock" - flagAvailability = "availability" - flagCACert = "ca-cert" - flagCAKey = "ca-key" -) - -type swarmOptions struct { - swarmCAOptions - taskHistoryLimit int64 - dispatcherHeartbeat time.Duration - maxSnapshots uint64 - snapshotInterval uint64 - autolock bool -} - -// NodeAddrOption is a pflag.Value for listening addresses -type NodeAddrOption struct { - addr string -} - -// String prints the representation of this flag -func (a *NodeAddrOption) String() string { - return a.Value() -} - -// Set the value for this flag -func (a *NodeAddrOption) Set(value string) error { - addr, err := opts.ParseTCPAddr(value, a.addr) - if err != nil { - return err - } - a.addr = addr - return nil -} - -// Type returns the type of this flag -func (a *NodeAddrOption) Type() string { - return "node-addr" -} - -// Value returns the value of this option as addr:port -func (a *NodeAddrOption) Value() string { - return strings.TrimPrefix(a.addr, "tcp://") -} - -// NewNodeAddrOption returns a new node address option -func NewNodeAddrOption(addr string) NodeAddrOption { - return NodeAddrOption{addr} -} - -// NewListenAddrOption returns a NodeAddrOption with default values -func NewListenAddrOption() NodeAddrOption { - return NewNodeAddrOption(defaultListenAddr) -} - -// ExternalCAOption is a Value type for parsing external CA specifications. -type ExternalCAOption struct { - values []*swarm.ExternalCA -} - -// Set parses an external CA option. -func (m *ExternalCAOption) Set(value string) error { - parsed, err := parseExternalCA(value) - if err != nil { - return err - } - - m.values = append(m.values, parsed) - return nil -} - -// Type returns the type of this option. -func (m *ExternalCAOption) Type() string { - return "external-ca" -} - -// String returns a string repr of this option. -func (m *ExternalCAOption) String() string { - externalCAs := []string{} - for _, externalCA := range m.values { - repr := fmt.Sprintf("%s: %s", externalCA.Protocol, externalCA.URL) - externalCAs = append(externalCAs, repr) - } - return strings.Join(externalCAs, ", ") -} - -// Value returns the external CAs -func (m *ExternalCAOption) Value() []*swarm.ExternalCA { - return m.values -} - -// PEMFile represents the path to a pem-formatted file -type PEMFile struct { - path, contents string -} - -// Type returns the type of this option. -func (p *PEMFile) Type() string { - return "pem-file" -} - -// String returns the path to the pem file -func (p *PEMFile) String() string { - return p.path -} - -// Set parses a root rotation option -func (p *PEMFile) Set(value string) error { - contents, err := ioutil.ReadFile(value) - if err != nil { - return err - } - if pemBlock, _ := pem.Decode(contents); pemBlock == nil { - return errors.New("file contents must be in PEM format") - } - p.contents, p.path = string(contents), value - return nil -} - -// Contents returns the contents of the PEM file -func (p *PEMFile) Contents() string { - return p.contents -} - -// parseExternalCA parses an external CA specification from the command line, -// such as protocol=cfssl,url=https://example.com. -func parseExternalCA(caSpec string) (*swarm.ExternalCA, error) { - csvReader := csv.NewReader(strings.NewReader(caSpec)) - fields, err := csvReader.Read() - if err != nil { - return nil, err - } - - externalCA := swarm.ExternalCA{ - Options: make(map[string]string), - } - - var ( - hasProtocol bool - hasURL bool - ) - - for _, field := range fields { - parts := strings.SplitN(field, "=", 2) - - if len(parts) != 2 { - return nil, errors.Errorf("invalid field '%s' must be a key=value pair", field) - } - - key, value := parts[0], parts[1] - - switch strings.ToLower(key) { - case "protocol": - hasProtocol = true - if strings.ToLower(value) == string(swarm.ExternalCAProtocolCFSSL) { - externalCA.Protocol = swarm.ExternalCAProtocolCFSSL - } else { - return nil, errors.Errorf("unrecognized external CA protocol %s", value) - } - case "url": - hasURL = true - externalCA.URL = value - case "cacert": - cacontents, err := ioutil.ReadFile(value) - if err != nil { - return nil, errors.Wrap(err, "unable to read CA cert for external CA") - } - if pemBlock, _ := pem.Decode(cacontents); pemBlock == nil { - return nil, errors.New("CA cert for external CA must be in PEM format") - } - externalCA.CACert = string(cacontents) - default: - externalCA.Options[key] = value - } - } - - if !hasProtocol { - return nil, errors.New("the external-ca option needs a protocol= parameter") - } - if !hasURL { - return nil, errors.New("the external-ca option needs a url= parameter") - } - - return &externalCA, nil -} - -func addSwarmCAFlags(flags *pflag.FlagSet, opts *swarmCAOptions) { - flags.DurationVar(&opts.nodeCertExpiry, flagCertExpiry, 90*24*time.Hour, "Validity period for node certificates (ns|us|ms|s|m|h)") - flags.Var(&opts.externalCA, flagExternalCA, "Specifications of one or more certificate signing endpoints") -} - -func addSwarmFlags(flags *pflag.FlagSet, opts *swarmOptions) { - flags.Int64Var(&opts.taskHistoryLimit, flagTaskHistoryLimit, 5, "Task history retention limit") - flags.DurationVar(&opts.dispatcherHeartbeat, flagDispatcherHeartbeat, 5*time.Second, "Dispatcher heartbeat period (ns|us|ms|s|m|h)") - flags.Uint64Var(&opts.maxSnapshots, flagMaxSnapshots, 0, "Number of additional Raft snapshots to retain") - flags.SetAnnotation(flagMaxSnapshots, "version", []string{"1.25"}) - flags.Uint64Var(&opts.snapshotInterval, flagSnapshotInterval, 10000, "Number of log entries between Raft snapshots") - flags.SetAnnotation(flagSnapshotInterval, "version", []string{"1.25"}) - addSwarmCAFlags(flags, &opts.swarmCAOptions) -} - -func (opts *swarmOptions) mergeSwarmSpec(spec *swarm.Spec, flags *pflag.FlagSet) { - if flags.Changed(flagTaskHistoryLimit) { - spec.Orchestration.TaskHistoryRetentionLimit = &opts.taskHistoryLimit - } - if flags.Changed(flagDispatcherHeartbeat) { - spec.Dispatcher.HeartbeatPeriod = opts.dispatcherHeartbeat - } - if flags.Changed(flagMaxSnapshots) { - spec.Raft.KeepOldSnapshots = &opts.maxSnapshots - } - if flags.Changed(flagSnapshotInterval) { - spec.Raft.SnapshotInterval = opts.snapshotInterval - } - if flags.Changed(flagAutolock) { - spec.EncryptionConfig.AutoLockManagers = opts.autolock - } - opts.mergeSwarmSpecCAFlags(spec, flags) -} - -type swarmCAOptions struct { - nodeCertExpiry time.Duration - externalCA ExternalCAOption -} - -func (opts *swarmCAOptions) mergeSwarmSpecCAFlags(spec *swarm.Spec, flags *pflag.FlagSet) { - if flags.Changed(flagCertExpiry) { - spec.CAConfig.NodeCertExpiry = opts.nodeCertExpiry - } - if flags.Changed(flagExternalCA) { - spec.CAConfig.ExternalCAs = opts.externalCA.Value() - } -} - -func (opts *swarmOptions) ToSpec(flags *pflag.FlagSet) swarm.Spec { - var spec swarm.Spec - opts.mergeSwarmSpec(&spec, flags) - return spec -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/opts_test.go b/vendor/github.com/docker/cli/cli/command/swarm/opts_test.go deleted file mode 100644 index c694cc1bd..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/opts_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package swarm - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNodeAddrOptionSetHostAndPort(t *testing.T) { - opt := NewNodeAddrOption("old:123") - addr := "newhost:5555" - assert.NoError(t, opt.Set(addr)) - assert.Equal(t, addr, opt.Value()) -} - -func TestNodeAddrOptionSetHostOnly(t *testing.T) { - opt := NewListenAddrOption() - assert.NoError(t, opt.Set("newhost")) - assert.Equal(t, "newhost:2377", opt.Value()) -} - -func TestNodeAddrOptionSetHostOnlyIPv6(t *testing.T) { - opt := NewListenAddrOption() - assert.NoError(t, opt.Set("::1")) - assert.Equal(t, "[::1]:2377", opt.Value()) -} - -func TestNodeAddrOptionSetPortOnly(t *testing.T) { - opt := NewListenAddrOption() - assert.NoError(t, opt.Set(":4545")) - assert.Equal(t, "0.0.0.0:4545", opt.Value()) -} - -func TestNodeAddrOptionSetInvalidFormat(t *testing.T) { - opt := NewListenAddrOption() - assert.EqualError(t, opt.Set("http://localhost:4545"), "Invalid proto, expected tcp: http://localhost:4545") -} - -func TestExternalCAOptionErrors(t *testing.T) { - testCases := []struct { - externalCA string - expectedError string - }{ - { - externalCA: "", - expectedError: "EOF", - }, - { - externalCA: "anything", - expectedError: "invalid field 'anything' must be a key=value pair", - }, - { - externalCA: "foo=bar", - expectedError: "the external-ca option needs a protocol= parameter", - }, - { - externalCA: "protocol=baz", - expectedError: "unrecognized external CA protocol baz", - }, - { - externalCA: "protocol=cfssl", - expectedError: "the external-ca option needs a url= parameter", - }, - } - for _, tc := range testCases { - opt := &ExternalCAOption{} - assert.EqualError(t, opt.Set(tc.externalCA), tc.expectedError) - } -} - -func TestExternalCAOption(t *testing.T) { - testCases := []struct { - externalCA string - expected string - }{ - { - externalCA: "protocol=cfssl,url=anything", - expected: "cfssl: anything", - }, - { - externalCA: "protocol=CFSSL,url=anything", - expected: "cfssl: anything", - }, - { - externalCA: "protocol=Cfssl,url=https://example.com", - expected: "cfssl: https://example.com", - }, - { - externalCA: "protocol=Cfssl,url=https://example.com,foo=bar", - expected: "cfssl: https://example.com", - }, - { - externalCA: "protocol=Cfssl,url=https://example.com,foo=bar,foo=baz", - expected: "cfssl: https://example.com", - }, - } - for _, tc := range testCases { - opt := &ExternalCAOption{} - assert.NoError(t, opt.Set(tc.externalCA)) - assert.Equal(t, tc.expected, opt.String()) - } -} - -func TestExternalCAOptionMultiple(t *testing.T) { - opt := &ExternalCAOption{} - assert.NoError(t, opt.Set("protocol=cfssl,url=https://example.com")) - assert.NoError(t, opt.Set("protocol=CFSSL,url=anything")) - assert.Len(t, opt.Value(), 2) - assert.Equal(t, "cfssl: https://example.com, cfssl: anything", opt.String()) -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/progress/root_rotation.go b/vendor/github.com/docker/cli/cli/command/swarm/progress/root_rotation.go deleted file mode 100644 index 0b84d239e..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/progress/root_rotation.go +++ /dev/null @@ -1,121 +0,0 @@ -package progress - -import ( - "bytes" - "io" - "os" - "os/signal" - "time" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/streamformatter" - "github.com/opencontainers/go-digest" -) - -const ( - certsRotatedStr = " rotated TLS certificates" - rootsRotatedStr = " rotated CA certificates" - // rootsAction has a single space because rootsRotatedStr is one character shorter than certsRotatedStr. - // This makes sure the progress bar are aligned. - certsAction = "" - rootsAction = " " -) - -// RootRotationProgress outputs progress information for convergence of a root rotation. -func RootRotationProgress(ctx context.Context, dclient client.APIClient, progressWriter io.WriteCloser) error { - defer progressWriter.Close() - - progressOut := streamformatter.NewJSONProgressOutput(progressWriter, false) - - sigint := make(chan os.Signal, 1) - signal.Notify(sigint, os.Interrupt) - defer signal.Stop(sigint) - - // draw 2 progress bars, 1 for nodes with the correct cert, 1 for nodes with the correct trust root - progress.Update(progressOut, "desired root digest", "") - progress.Update(progressOut, certsRotatedStr, certsAction) - progress.Update(progressOut, rootsRotatedStr, rootsAction) - - var done bool - - for { - info, err := dclient.SwarmInspect(ctx) - if err != nil { - return err - } - - if done { - return nil - } - - nodes, err := dclient.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return err - } - - done = updateProgress(progressOut, info.ClusterInfo.TLSInfo, nodes, info.ClusterInfo.RootRotationInProgress) - - select { - case <-time.After(200 * time.Millisecond): - case <-sigint: - if !done { - progress.Message(progressOut, "", "Operation continuing in background.") - progress.Message(progressOut, "", "Use `swarmctl cluster inspect default` to check progress.") - } - return nil - } - } -} - -func updateProgress(progressOut progress.Output, desiredTLSInfo swarm.TLSInfo, nodes []swarm.Node, rootRotationInProgress bool) bool { - // write the current desired root cert's digest, because the desired root certs might be too long - progressOut.WriteProgress(progress.Progress{ - ID: "desired root digest", - Action: digest.FromBytes([]byte(desiredTLSInfo.TrustRoot)).String(), - }) - - // If we had reached a converged state, check if we are still converged. - var certsRight, trustRootsRight int64 - for _, n := range nodes { - if bytes.Equal(n.Description.TLSInfo.CertIssuerPublicKey, desiredTLSInfo.CertIssuerPublicKey) && - bytes.Equal(n.Description.TLSInfo.CertIssuerSubject, desiredTLSInfo.CertIssuerSubject) { - certsRight++ - } - - if n.Description.TLSInfo.TrustRoot == desiredTLSInfo.TrustRoot { - trustRootsRight++ - } - } - - total := int64(len(nodes)) - progressOut.WriteProgress(progress.Progress{ - ID: certsRotatedStr, - Action: certsAction, - Current: certsRight, - Total: total, - Units: "nodes", - }) - - rootsProgress := progress.Progress{ - ID: rootsRotatedStr, - Action: rootsAction, - Current: trustRootsRight, - Total: total, - Units: "nodes", - } - - if certsRight == total && !rootRotationInProgress { - progressOut.WriteProgress(rootsProgress) - return certsRight == total && trustRootsRight == total - } - - // we still have certs that need renewing, so display that there are zero roots rotated yet - rootsProgress.Current = 0 - progressOut.WriteProgress(rootsProgress) - return false -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/init-init-autolock.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/init-init-autolock.golden deleted file mode 100644 index cdd3c666b..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/init-init-autolock.golden +++ /dev/null @@ -1,11 +0,0 @@ -Swarm initialized: current node (nodeID) is now a manager. - -To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. - -To unlock a swarm manager after it restarts, run the `docker swarm unlock` -command and provide the following key: - - unlock-key - -Please remember to store this key in a password manager, since without it you -will not be able to restart the manager. diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/init-init.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/init-init.golden deleted file mode 100644 index 6e82be010..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/init-init.golden +++ /dev/null @@ -1,4 +0,0 @@ -Swarm initialized: current node (nodeID) is now a manager. - -To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. - diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager-quiet.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager-quiet.golden deleted file mode 100644 index 0c7cfc608..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager-quiet.golden +++ /dev/null @@ -1 +0,0 @@ -manager-join-token diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager-rotate.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager-rotate.golden deleted file mode 100644 index 4a978e762..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager-rotate.golden +++ /dev/null @@ -1,6 +0,0 @@ -Successfully rotated manager join token. - -To add a manager to this swarm, run the following command: - - docker swarm join --token manager-join-token 127.0.0.1 - diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager.golden deleted file mode 100644 index 7bcb73373..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-manager.golden +++ /dev/null @@ -1,4 +0,0 @@ -To add a manager to this swarm, run the following command: - - docker swarm join --token manager-join-token 127.0.0.1 - diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-worker-quiet.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-worker-quiet.golden deleted file mode 100644 index b445e191e..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-worker-quiet.golden +++ /dev/null @@ -1 +0,0 @@ -worker-join-token diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-worker.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-worker.golden deleted file mode 100644 index e6c3ab9af..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/jointoken-worker.golden +++ /dev/null @@ -1,4 +0,0 @@ -To add a worker to this swarm, run the following command: - - docker swarm join --token worker-join-token 127.0.0.1 - diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-quiet.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-quiet.golden deleted file mode 100644 index ed53505e2..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-quiet.golden +++ /dev/null @@ -1 +0,0 @@ -unlock-key diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-rotate-quiet.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-rotate-quiet.golden deleted file mode 100644 index ed53505e2..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-rotate-quiet.golden +++ /dev/null @@ -1 +0,0 @@ -unlock-key diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-rotate.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-rotate.golden deleted file mode 100644 index 89152b864..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key-rotate.golden +++ /dev/null @@ -1,9 +0,0 @@ -Successfully rotated manager unlock key. - -To unlock a swarm manager after it restarts, run the `docker swarm unlock` -command and provide the following key: - - unlock-key - -Please remember to store this key in a password manager, since without it you -will not be able to restart the manager. diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key.golden deleted file mode 100644 index 8316df478..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/unlockkeys-unlock-key.golden +++ /dev/null @@ -1,7 +0,0 @@ -To unlock a swarm manager after it restarts, run the `docker swarm unlock` -command and provide the following key: - - unlock-key - -Please remember to store this key in a password manager, since without it you -will not be able to restart the manager. diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-all-flags-quiet.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-all-flags-quiet.golden deleted file mode 100644 index 3d195a258..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-all-flags-quiet.golden +++ /dev/null @@ -1 +0,0 @@ -Swarm updated. diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-autolock-unlock-key.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-autolock-unlock-key.golden deleted file mode 100644 index a077b9e16..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-autolock-unlock-key.golden +++ /dev/null @@ -1,8 +0,0 @@ -Swarm updated. -To unlock a swarm manager after it restarts, run the `docker swarm unlock` -command and provide the following key: - - unlock-key - -Please remember to store this key in a password manager, since without it you -will not be able to restart the manager. diff --git a/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-noargs.golden b/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-noargs.golden deleted file mode 100644 index 381c0ccf1..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/testdata/update-noargs.golden +++ /dev/null @@ -1,13 +0,0 @@ -Update the swarm - -Usage: - update [OPTIONS] [flags] - -Flags: - --autolock Change manager autolocking setting (true|false) - --cert-expiry duration Validity period for node certificates (ns|us|ms|s|m|h) (default 2160h0m0s) - --dispatcher-heartbeat duration Dispatcher heartbeat period (ns|us|ms|s|m|h) (default 5s) - --external-ca external-ca Specifications of one or more certificate signing endpoints - --max-snapshots uint Number of additional Raft snapshots to retain - --snapshot-interval uint Number of log entries between Raft snapshots (default 10000) - --task-history-limit int Task history retention limit (default 5) diff --git a/vendor/github.com/docker/cli/cli/command/swarm/unlock.go b/vendor/github.com/docker/cli/cli/command/swarm/unlock.go deleted file mode 100644 index dd999a7f4..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/unlock.go +++ /dev/null @@ -1,78 +0,0 @@ -package swarm - -import ( - "bufio" - "fmt" - "io" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh/terminal" - "golang.org/x/net/context" -) - -type unlockOptions struct{} - -func newUnlockCommand(dockerCli command.Cli) *cobra.Command { - opts := unlockOptions{} - - cmd := &cobra.Command{ - Use: "unlock", - Short: "Unlock swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runUnlock(dockerCli, opts) - }, - } - - return cmd -} - -func runUnlock(dockerCli command.Cli, opts unlockOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - // First see if the node is actually part of a swarm, and if it is actually locked first. - // If it's in any other state than locked, don't ask for the key. - info, err := client.Info(ctx) - if err != nil { - return err - } - - switch info.Swarm.LocalNodeState { - case swarm.LocalNodeStateInactive: - return errors.New("Error: This node is not part of a swarm") - case swarm.LocalNodeStateLocked: - break - default: - return errors.New("Error: swarm is not locked") - } - - key, err := readKey(dockerCli.In(), "Please enter unlock key: ") - if err != nil { - return err - } - req := swarm.UnlockRequest{ - UnlockKey: key, - } - - return client.SwarmUnlock(ctx, req) -} - -func readKey(in *command.InStream, prompt string) (string, error) { - if in.IsTerminal() { - fmt.Print(prompt) - dt, err := terminal.ReadPassword(int(in.FD())) - fmt.Println() - return string(dt), err - } - key, err := bufio.NewReader(in).ReadString('\n') - if err == io.EOF { - err = nil - } - return strings.TrimSpace(key), err -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/unlock_key.go b/vendor/github.com/docker/cli/cli/command/swarm/unlock_key.go deleted file mode 100644 index 4618de7de..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/unlock_key.go +++ /dev/null @@ -1,89 +0,0 @@ -package swarm - -import ( - "fmt" - "io" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type unlockKeyOptions struct { - rotate bool - quiet bool -} - -func newUnlockKeyCommand(dockerCli command.Cli) *cobra.Command { - opts := unlockKeyOptions{} - - cmd := &cobra.Command{ - Use: "unlock-key [OPTIONS]", - Short: "Manage the unlock key", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runUnlockKey(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVar(&opts.rotate, flagRotate, false, "Rotate unlock key") - flags.BoolVarP(&opts.quiet, flagQuiet, "q", false, "Only display token") - - return cmd -} - -func runUnlockKey(dockerCli command.Cli, opts unlockKeyOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.rotate { - flags := swarm.UpdateFlags{RotateManagerUnlockKey: true} - - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if !sw.Spec.EncryptionConfig.AutoLockManagers { - return errors.New("cannot rotate because autolock is not turned on") - } - - if err := client.SwarmUpdate(ctx, sw.Version, sw.Spec, flags); err != nil { - return err - } - - if !opts.quiet { - fmt.Fprintf(dockerCli.Out(), "Successfully rotated manager unlock key.\n\n") - } - } - - unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) - if err != nil { - return errors.Wrap(err, "could not fetch unlock key") - } - - if unlockKeyResp.UnlockKey == "" { - return errors.New("no unlock key is set") - } - - if opts.quiet { - fmt.Fprintln(dockerCli.Out(), unlockKeyResp.UnlockKey) - return nil - } - - printUnlockCommand(dockerCli.Out(), unlockKeyResp.UnlockKey) - return nil -} - -func printUnlockCommand(out io.Writer, unlockKey string) { - if len(unlockKey) > 0 { - fmt.Fprintf(out, "To unlock a swarm manager after it restarts, "+ - "run the `docker swarm unlock`\ncommand and provide the following key:\n\n %s\n\n"+ - "Please remember to store this key in a password manager, since without it you\n"+ - "will not be able to restart the manager.\n", unlockKey) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/unlock_key_test.go b/vendor/github.com/docker/cli/cli/command/swarm/unlock_key_test.go deleted file mode 100644 index 97c04fc62..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/unlock_key_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package swarm - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestSwarmUnlockKeyErrors(t *testing.T) { - testCases := []struct { - name string - args []string - flags map[string]string - swarmInspectFunc func() (swarm.Swarm, error) - swarmUpdateFunc func(swarm swarm.Spec, flags swarm.UpdateFlags) error - swarmGetUnlockKeyFunc func() (types.SwarmUnlockKeyResponse, error) - expectedError string - }{ - { - name: "too-many-args", - args: []string{"foo"}, - expectedError: "accepts no arguments", - }, - { - name: "swarm-inspect-rotate-failed", - flags: map[string]string{ - flagRotate: "true", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return swarm.Swarm{}, errors.Errorf("error inspecting the swarm") - }, - expectedError: "error inspecting the swarm", - }, - { - name: "swarm-rotate-no-autolock-failed", - flags: map[string]string{ - flagRotate: "true", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - expectedError: "cannot rotate because autolock is not turned on", - }, - { - name: "swarm-update-failed", - flags: map[string]string{ - flagRotate: "true", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(Autolock()), nil - }, - swarmUpdateFunc: func(swarm swarm.Spec, flags swarm.UpdateFlags) error { - return errors.Errorf("error updating the swarm") - }, - expectedError: "error updating the swarm", - }, - { - name: "swarm-get-unlock-key-failed", - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{}, errors.Errorf("error getting unlock key") - }, - expectedError: "error getting unlock key", - }, - { - name: "swarm-no-unlock-key-failed", - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{ - UnlockKey: "", - }, nil - }, - expectedError: "no unlock key is set", - }, - } - for _, tc := range testCases { - cmd := newUnlockKeyCommand( - test.NewFakeCli(&fakeClient{ - swarmInspectFunc: tc.swarmInspectFunc, - swarmUpdateFunc: tc.swarmUpdateFunc, - swarmGetUnlockKeyFunc: tc.swarmGetUnlockKeyFunc, - })) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSwarmUnlockKey(t *testing.T) { - testCases := []struct { - name string - args []string - flags map[string]string - swarmInspectFunc func() (swarm.Swarm, error) - swarmUpdateFunc func(swarm swarm.Spec, flags swarm.UpdateFlags) error - swarmGetUnlockKeyFunc func() (types.SwarmUnlockKeyResponse, error) - }{ - { - name: "unlock-key", - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{ - UnlockKey: "unlock-key", - }, nil - }, - }, - { - name: "unlock-key-quiet", - flags: map[string]string{ - flagQuiet: "true", - }, - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{ - UnlockKey: "unlock-key", - }, nil - }, - }, - { - name: "unlock-key-rotate", - flags: map[string]string{ - flagRotate: "true", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(Autolock()), nil - }, - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{ - UnlockKey: "unlock-key", - }, nil - }, - }, - { - name: "unlock-key-rotate-quiet", - flags: map[string]string{ - flagQuiet: "true", - flagRotate: "true", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(Autolock()), nil - }, - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{ - UnlockKey: "unlock-key", - }, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - swarmInspectFunc: tc.swarmInspectFunc, - swarmUpdateFunc: tc.swarmUpdateFunc, - swarmGetUnlockKeyFunc: tc.swarmGetUnlockKeyFunc, - }) - cmd := newUnlockKeyCommand(cli) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("unlockkeys-%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/unlock_test.go b/vendor/github.com/docker/cli/cli/command/swarm/unlock_test.go deleted file mode 100644 index c7aee0a3c..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/unlock_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package swarm - -import ( - "io/ioutil" - "strings" - "testing" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestSwarmUnlockErrors(t *testing.T) { - testCases := []struct { - name string - args []string - swarmUnlockFunc func(req swarm.UnlockRequest) error - infoFunc func() (types.Info, error) - expectedError string - }{ - { - name: "too-many-args", - args: []string{"foo"}, - expectedError: "accepts no arguments", - }, - { - name: "is-not-part-of-a-swarm", - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - LocalNodeState: swarm.LocalNodeStateInactive, - }, - }, nil - }, - expectedError: "This node is not part of a swarm", - }, - { - name: "is-not-locked", - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - LocalNodeState: swarm.LocalNodeStateActive, - }, - }, nil - }, - expectedError: "Error: swarm is not locked", - }, - { - name: "unlockrequest-failed", - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - LocalNodeState: swarm.LocalNodeStateLocked, - }, - }, nil - }, - swarmUnlockFunc: func(req swarm.UnlockRequest) error { - return errors.Errorf("error unlocking the swarm") - }, - expectedError: "error unlocking the swarm", - }, - } - for _, tc := range testCases { - cmd := newUnlockCommand( - test.NewFakeCli(&fakeClient{ - infoFunc: tc.infoFunc, - swarmUnlockFunc: tc.swarmUnlockFunc, - })) - cmd.SetArgs(tc.args) - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSwarmUnlock(t *testing.T) { - input := "unlockKey" - dockerCli := test.NewFakeCli(&fakeClient{ - infoFunc: func() (types.Info, error) { - return types.Info{ - Swarm: swarm.Info{ - LocalNodeState: swarm.LocalNodeStateLocked, - }, - }, nil - }, - swarmUnlockFunc: func(req swarm.UnlockRequest) error { - if req.UnlockKey != input { - return errors.Errorf("Invalid unlock key") - } - return nil - }, - }) - dockerCli.SetIn(command.NewInStream(ioutil.NopCloser(strings.NewReader(input)))) - cmd := newUnlockCommand(dockerCli) - assert.NoError(t, cmd.Execute()) -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/update.go b/vendor/github.com/docker/cli/cli/command/swarm/update.go deleted file mode 100644 index 4d751bbd4..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/update.go +++ /dev/null @@ -1,72 +0,0 @@ -package swarm - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func newUpdateCommand(dockerCli command.Cli) *cobra.Command { - opts := swarmOptions{} - - cmd := &cobra.Command{ - Use: "update [OPTIONS]", - Short: "Update the swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runUpdate(dockerCli, cmd.Flags(), opts) - }, - PreRunE: func(cmd *cobra.Command, args []string) error { - if cmd.Flags().NFlag() == 0 { - return pflag.ErrHelp - } - return nil - }, - } - - cmd.Flags().BoolVar(&opts.autolock, flagAutolock, false, "Change manager autolocking setting (true|false)") - addSwarmFlags(cmd.Flags(), &opts) - return cmd -} - -func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, opts swarmOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var updateFlags swarm.UpdateFlags - - swarmInspect, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - prevAutoLock := swarmInspect.Spec.EncryptionConfig.AutoLockManagers - - opts.mergeSwarmSpec(&swarmInspect.Spec, flags) - - curAutoLock := swarmInspect.Spec.EncryptionConfig.AutoLockManagers - - err = client.SwarmUpdate(ctx, swarmInspect.Version, swarmInspect.Spec, updateFlags) - if err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), "Swarm updated.") - - if curAutoLock && !prevAutoLock { - unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) - if err != nil { - return errors.Wrap(err, "could not fetch unlock key") - } - printUnlockCommand(dockerCli.Out(), unlockKeyResp.UnlockKey) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/update_test.go b/vendor/github.com/docker/cli/cli/command/swarm/update_test.go deleted file mode 100644 index e2a003391..000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/update_test.go +++ /dev/null @@ -1,179 +0,0 @@ -package swarm - -import ( - "fmt" - "io/ioutil" - "testing" - "time" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestSwarmUpdateErrors(t *testing.T) { - testCases := []struct { - name string - args []string - flags map[string]string - swarmInspectFunc func() (swarm.Swarm, error) - swarmUpdateFunc func(swarm swarm.Spec, flags swarm.UpdateFlags) error - swarmGetUnlockKeyFunc func() (types.SwarmUnlockKeyResponse, error) - expectedError string - }{ - { - name: "too-many-args", - args: []string{"foo"}, - expectedError: "accepts no arguments", - }, - { - name: "swarm-inspect-error", - flags: map[string]string{ - flagTaskHistoryLimit: "10", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return swarm.Swarm{}, errors.Errorf("error inspecting the swarm") - }, - expectedError: "error inspecting the swarm", - }, - { - name: "swarm-update-error", - flags: map[string]string{ - flagTaskHistoryLimit: "10", - }, - swarmUpdateFunc: func(swarm swarm.Spec, flags swarm.UpdateFlags) error { - return errors.Errorf("error updating the swarm") - }, - expectedError: "error updating the swarm", - }, - { - name: "swarm-unlockkey-error", - flags: map[string]string{ - flagAutolock: "true", - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{}, errors.Errorf("error getting unlock key") - }, - expectedError: "error getting unlock key", - }, - } - for _, tc := range testCases { - cmd := newUpdateCommand( - test.NewFakeCli(&fakeClient{ - swarmInspectFunc: tc.swarmInspectFunc, - swarmUpdateFunc: tc.swarmUpdateFunc, - swarmGetUnlockKeyFunc: tc.swarmGetUnlockKeyFunc, - })) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestSwarmUpdate(t *testing.T) { - testCases := []struct { - name string - args []string - flags map[string]string - swarmInspectFunc func() (swarm.Swarm, error) - swarmUpdateFunc func(swarm swarm.Spec, flags swarm.UpdateFlags) error - swarmGetUnlockKeyFunc func() (types.SwarmUnlockKeyResponse, error) - }{ - { - name: "noargs", - }, - { - name: "all-flags-quiet", - flags: map[string]string{ - flagTaskHistoryLimit: "10", - flagDispatcherHeartbeat: "10s", - flagCertExpiry: "20s", - flagExternalCA: "protocol=cfssl,url=https://example.com.", - flagMaxSnapshots: "10", - flagSnapshotInterval: "100", - flagAutolock: "true", - flagQuiet: "true", - }, - swarmUpdateFunc: func(swarm swarm.Spec, flags swarm.UpdateFlags) error { - if *swarm.Orchestration.TaskHistoryRetentionLimit != 10 { - return errors.Errorf("historyLimit not correctly set") - } - heartbeatDuration, err := time.ParseDuration("10s") - if err != nil { - return err - } - if swarm.Dispatcher.HeartbeatPeriod != heartbeatDuration { - return errors.Errorf("heartbeatPeriodLimit not correctly set") - } - certExpiryDuration, err := time.ParseDuration("20s") - if err != nil { - return err - } - if swarm.CAConfig.NodeCertExpiry != certExpiryDuration { - return errors.Errorf("certExpiry not correctly set") - } - if len(swarm.CAConfig.ExternalCAs) != 1 { - return errors.Errorf("externalCA not correctly set") - } - if *swarm.Raft.KeepOldSnapshots != 10 { - return errors.Errorf("keepOldSnapshots not correctly set") - } - if swarm.Raft.SnapshotInterval != 100 { - return errors.Errorf("snapshotInterval not correctly set") - } - if !swarm.EncryptionConfig.AutoLockManagers { - return errors.Errorf("autolock not correctly set") - } - return nil - }, - }, - { - name: "autolock-unlock-key", - flags: map[string]string{ - flagTaskHistoryLimit: "10", - flagAutolock: "true", - }, - swarmUpdateFunc: func(swarm swarm.Spec, flags swarm.UpdateFlags) error { - if *swarm.Orchestration.TaskHistoryRetentionLimit != 10 { - return errors.Errorf("historyLimit not correctly set") - } - return nil - }, - swarmInspectFunc: func() (swarm.Swarm, error) { - return *Swarm(), nil - }, - swarmGetUnlockKeyFunc: func() (types.SwarmUnlockKeyResponse, error) { - return types.SwarmUnlockKeyResponse{ - UnlockKey: "unlock-key", - }, nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - swarmInspectFunc: tc.swarmInspectFunc, - swarmUpdateFunc: tc.swarmUpdateFunc, - swarmGetUnlockKeyFunc: tc.swarmGetUnlockKeyFunc, - }) - cmd := newUpdateCommand(cli) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(cli.OutBuffer()) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("update-%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/system/client_test.go b/vendor/github.com/docker/cli/cli/command/system/client_test.go deleted file mode 100644 index ed0e803ea..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/client_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package system - -import ( - "github.com/docker/docker/client" -) - -type fakeClient struct { - client.Client - - version string -} - -func (cli *fakeClient) ClientVersion() string { - return cli.version -} diff --git a/vendor/github.com/docker/cli/cli/command/system/cmd.go b/vendor/github.com/docker/cli/cli/command/system/cmd.go deleted file mode 100644 index 60979e722..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/cmd.go +++ /dev/null @@ -1,26 +0,0 @@ -package system - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewSystemCommand returns a cobra command for `system` subcommands -// nolint: interfacer -func NewSystemCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "system", - Short: "Manage Docker", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - } - cmd.AddCommand( - NewEventsCommand(dockerCli), - NewInfoCommand(dockerCli), - newDiskUsageCommand(dockerCli), - newPruneCommand(dockerCli), - ) - - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/system/df.go b/vendor/github.com/docker/cli/cli/command/system/df.go deleted file mode 100644 index 5146482f0..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/df.go +++ /dev/null @@ -1,69 +0,0 @@ -package system - -import ( - "errors" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type diskUsageOptions struct { - verbose bool - format string -} - -// newDiskUsageCommand creates a new cobra.Command for `docker df` -func newDiskUsageCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts diskUsageOptions - - cmd := &cobra.Command{ - Use: "df [OPTIONS]", - Short: "Show docker disk usage", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runDiskUsage(dockerCli, opts) - }, - Tags: map[string]string{"version": "1.25"}, - } - - flags := cmd.Flags() - - flags.BoolVarP(&opts.verbose, "verbose", "v", false, "Show detailed information on space usage") - flags.StringVar(&opts.format, "format", "", "Pretty-print images using a Go template") - - return cmd -} - -func runDiskUsage(dockerCli *command.DockerCli, opts diskUsageOptions) error { - if opts.verbose && len(opts.format) != 0 { - return errors.New("the verbose and the format options conflict") - } - - du, err := dockerCli.Client().DiskUsage(context.Background()) - if err != nil { - return err - } - - format := opts.format - if len(format) == 0 { - format = formatter.TableFormatKey - } - - duCtx := formatter.DiskUsageContext{ - Context: formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewDiskUsageFormat(format), - }, - LayersSize: du.LayersSize, - BuilderSize: du.BuilderSize, - Images: du.Images, - Containers: du.Containers, - Volumes: du.Volumes, - Verbose: opts.verbose, - } - - return duCtx.Write() -} diff --git a/vendor/github.com/docker/cli/cli/command/system/events.go b/vendor/github.com/docker/cli/cli/command/system/events.go deleted file mode 100644 index 6dbc51e2b..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/events.go +++ /dev/null @@ -1,139 +0,0 @@ -package system - -import ( - "fmt" - "io" - "io/ioutil" - "sort" - "strings" - "text/template" - "time" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/cli/templates" - "github.com/docker/docker/api/types" - eventtypes "github.com/docker/docker/api/types/events" - "github.com/docker/docker/pkg/jsonlog" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type eventsOptions struct { - since string - until string - filter opts.FilterOpt - format string -} - -// NewEventsCommand creates a new cobra.Command for `docker events` -func NewEventsCommand(dockerCli *command.DockerCli) *cobra.Command { - options := eventsOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "events [OPTIONS]", - Short: "Get real time events from the server", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runEvents(dockerCli, &options) - }, - } - - flags := cmd.Flags() - flags.StringVar(&options.since, "since", "", "Show all events created since timestamp") - flags.StringVar(&options.until, "until", "", "Stream events until this timestamp") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - flags.StringVar(&options.format, "format", "", "Format the output using the given Go template") - - return cmd -} - -func runEvents(dockerCli *command.DockerCli, options *eventsOptions) error { - tmpl, err := makeTemplate(options.format) - if err != nil { - return cli.StatusError{ - StatusCode: 64, - Status: "Error parsing format: " + err.Error()} - } - eventOptions := types.EventsOptions{ - Since: options.since, - Until: options.until, - Filters: options.filter.Value(), - } - - ctx, cancel := context.WithCancel(context.Background()) - events, errs := dockerCli.Client().Events(ctx, eventOptions) - defer cancel() - - out := dockerCli.Out() - - for { - select { - case event := <-events: - if err := handleEvent(out, event, tmpl); err != nil { - return err - } - case err := <-errs: - if err == io.EOF { - return nil - } - return err - } - } -} - -func handleEvent(out io.Writer, event eventtypes.Message, tmpl *template.Template) error { - if tmpl == nil { - return prettyPrintEvent(out, event) - } - - return formatEvent(out, event, tmpl) -} - -func makeTemplate(format string) (*template.Template, error) { - if format == "" { - return nil, nil - } - tmpl, err := templates.Parse(format) - if err != nil { - return tmpl, err - } - // we execute the template for an empty message, so as to validate - // a bad template like "{{.badFieldString}}" - return tmpl, tmpl.Execute(ioutil.Discard, &eventtypes.Message{}) -} - -// prettyPrintEvent prints all types of event information. -// Each output includes the event type, actor id, name and action. -// Actor attributes are printed at the end if the actor has any. -func prettyPrintEvent(out io.Writer, event eventtypes.Message) error { - if event.TimeNano != 0 { - fmt.Fprintf(out, "%s ", time.Unix(0, event.TimeNano).Format(jsonlog.RFC3339NanoFixed)) - } else if event.Time != 0 { - fmt.Fprintf(out, "%s ", time.Unix(event.Time, 0).Format(jsonlog.RFC3339NanoFixed)) - } - - fmt.Fprintf(out, "%s %s %s", event.Type, event.Action, event.Actor.ID) - - if len(event.Actor.Attributes) > 0 { - var attrs []string - var keys []string - for k := range event.Actor.Attributes { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { - v := event.Actor.Attributes[k] - attrs = append(attrs, fmt.Sprintf("%s=%s", k, v)) - } - fmt.Fprintf(out, " (%s)", strings.Join(attrs, ", ")) - } - fmt.Fprint(out, "\n") - return nil -} - -func formatEvent(out io.Writer, event eventtypes.Message, tmpl *template.Template) error { - defer out.Write([]byte{'\n'}) - return tmpl.Execute(out, event) -} diff --git a/vendor/github.com/docker/cli/cli/command/system/info.go b/vendor/github.com/docker/cli/cli/command/system/info.go deleted file mode 100644 index 9d366466a..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/info.go +++ /dev/null @@ -1,375 +0,0 @@ -package system - -import ( - "fmt" - "io" - "sort" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/debug" - "github.com/docker/cli/templates" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/go-units" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type infoOptions struct { - format string -} - -// NewInfoCommand creates a new cobra.Command for `docker info` -func NewInfoCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts infoOptions - - cmd := &cobra.Command{ - Use: "info [OPTIONS]", - Short: "Display system-wide information", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runInfo(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - - return cmd -} - -func runInfo(dockerCli *command.DockerCli, opts *infoOptions) error { - ctx := context.Background() - info, err := dockerCli.Client().Info(ctx) - if err != nil { - return err - } - if opts.format == "" { - return prettyPrintInfo(dockerCli, info) - } - return formatInfo(dockerCli, info, opts.format) -} - -// nolint: gocyclo -func prettyPrintInfo(dockerCli command.Cli, info types.Info) error { - fmt.Fprintln(dockerCli.Out(), "Containers:", info.Containers) - fmt.Fprintln(dockerCli.Out(), " Running:", info.ContainersRunning) - fmt.Fprintln(dockerCli.Out(), " Paused:", info.ContainersPaused) - fmt.Fprintln(dockerCli.Out(), " Stopped:", info.ContainersStopped) - fmt.Fprintln(dockerCli.Out(), "Images:", info.Images) - fprintlnNonEmpty(dockerCli.Out(), "Server Version:", info.ServerVersion) - fprintlnNonEmpty(dockerCli.Out(), "Storage Driver:", info.Driver) - if info.DriverStatus != nil { - for _, pair := range info.DriverStatus { - fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1]) - } - } - if info.SystemStatus != nil { - for _, pair := range info.SystemStatus { - fmt.Fprintf(dockerCli.Out(), "%s: %s\n", pair[0], pair[1]) - } - } - fprintlnNonEmpty(dockerCli.Out(), "Logging Driver:", info.LoggingDriver) - fprintlnNonEmpty(dockerCli.Out(), "Cgroup Driver:", info.CgroupDriver) - - fmt.Fprintln(dockerCli.Out(), "Plugins:") - fmt.Fprintln(dockerCli.Out(), " Volume:", strings.Join(info.Plugins.Volume, " ")) - fmt.Fprintln(dockerCli.Out(), " Network:", strings.Join(info.Plugins.Network, " ")) - - if len(info.Plugins.Authorization) != 0 { - fmt.Fprintln(dockerCli.Out(), " Authorization:", strings.Join(info.Plugins.Authorization, " ")) - } - - fmt.Fprintln(dockerCli.Out(), " Log:", strings.Join(info.Plugins.Log, " ")) - - fmt.Fprintln(dockerCli.Out(), "Swarm:", info.Swarm.LocalNodeState) - printSwarmInfo(dockerCli, info) - - if len(info.Runtimes) > 0 { - fmt.Fprint(dockerCli.Out(), "Runtimes:") - for name := range info.Runtimes { - fmt.Fprintf(dockerCli.Out(), " %s", name) - } - fmt.Fprint(dockerCli.Out(), "\n") - fmt.Fprintln(dockerCli.Out(), "Default Runtime:", info.DefaultRuntime) - } - - if info.OSType == "linux" { - fmt.Fprintln(dockerCli.Out(), "Init Binary:", info.InitBinary) - - for _, ci := range []struct { - Name string - Commit types.Commit - }{ - {"containerd", info.ContainerdCommit}, - {"runc", info.RuncCommit}, - {"init", info.InitCommit}, - } { - fmt.Fprintf(dockerCli.Out(), "%s version: %s", ci.Name, ci.Commit.ID) - if ci.Commit.ID != ci.Commit.Expected { - fmt.Fprintf(dockerCli.Out(), " (expected: %s)", ci.Commit.Expected) - } - fmt.Fprint(dockerCli.Out(), "\n") - } - if len(info.SecurityOptions) != 0 { - kvs, err := types.DecodeSecurityOptions(info.SecurityOptions) - if err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), "Security Options:") - for _, so := range kvs { - fmt.Fprintln(dockerCli.Out(), " "+so.Name) - for _, o := range so.Options { - switch o.Key { - case "profile": - if o.Value != "default" { - fmt.Fprintln(dockerCli.Err(), " WARNING: You're not using the default seccomp profile") - } - fmt.Fprintln(dockerCli.Out(), " Profile:", o.Value) - } - } - } - } - } - - // Isolation only has meaning on a Windows daemon. - if info.OSType == "windows" { - fmt.Fprintln(dockerCli.Out(), "Default Isolation:", info.Isolation) - } - - fprintlnNonEmpty(dockerCli.Out(), "Kernel Version:", info.KernelVersion) - fprintlnNonEmpty(dockerCli.Out(), "Operating System:", info.OperatingSystem) - fprintlnNonEmpty(dockerCli.Out(), "OSType:", info.OSType) - fprintlnNonEmpty(dockerCli.Out(), "Architecture:", info.Architecture) - fmt.Fprintln(dockerCli.Out(), "CPUs:", info.NCPU) - fmt.Fprintln(dockerCli.Out(), "Total Memory:", units.BytesSize(float64(info.MemTotal))) - fprintlnNonEmpty(dockerCli.Out(), "Name:", info.Name) - fprintlnNonEmpty(dockerCli.Out(), "ID:", info.ID) - fmt.Fprintln(dockerCli.Out(), "Docker Root Dir:", info.DockerRootDir) - fmt.Fprintln(dockerCli.Out(), "Debug Mode (client):", debug.IsEnabled()) - fmt.Fprintln(dockerCli.Out(), "Debug Mode (server):", info.Debug) - - if info.Debug { - fmt.Fprintln(dockerCli.Out(), " File Descriptors:", info.NFd) - fmt.Fprintln(dockerCli.Out(), " Goroutines:", info.NGoroutines) - fmt.Fprintln(dockerCli.Out(), " System Time:", info.SystemTime) - fmt.Fprintln(dockerCli.Out(), " EventsListeners:", info.NEventsListener) - } - - fprintlnNonEmpty(dockerCli.Out(), "HTTP Proxy:", info.HTTPProxy) - fprintlnNonEmpty(dockerCli.Out(), "HTTPS Proxy:", info.HTTPSProxy) - fprintlnNonEmpty(dockerCli.Out(), "No Proxy:", info.NoProxy) - - if info.IndexServerAddress != "" { - u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username - if len(u) > 0 { - fmt.Fprintln(dockerCli.Out(), "Username:", u) - } - fmt.Fprintln(dockerCli.Out(), "Registry:", info.IndexServerAddress) - } - - if info.Labels != nil { - fmt.Fprintln(dockerCli.Out(), "Labels:") - for _, lbl := range info.Labels { - fmt.Fprintln(dockerCli.Out(), " "+lbl) - } - // TODO: Engine labels with duplicate keys has been deprecated in 1.13 and will be error out - // after 3 release cycles (17.12). For now, a WARNING will be generated. The following will - // be removed eventually. - labelMap := map[string]string{} - for _, label := range info.Labels { - stringSlice := strings.SplitN(label, "=", 2) - if len(stringSlice) > 1 { - // If there is a conflict we will throw out a warning - if v, ok := labelMap[stringSlice[0]]; ok && v != stringSlice[1] { - fmt.Fprintln(dockerCli.Err(), "WARNING: labels with duplicate keys and conflicting values have been deprecated") - break - } - labelMap[stringSlice[0]] = stringSlice[1] - } - } - } - - fmt.Fprintln(dockerCli.Out(), "Experimental:", info.ExperimentalBuild) - fprintlnNonEmpty(dockerCli.Out(), "Cluster Store:", info.ClusterStore) - fprintlnNonEmpty(dockerCli.Out(), "Cluster Advertise:", info.ClusterAdvertise) - - if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) { - fmt.Fprintln(dockerCli.Out(), "Insecure Registries:") - for _, registry := range info.RegistryConfig.IndexConfigs { - if !registry.Secure { - fmt.Fprintln(dockerCli.Out(), " "+registry.Name) - } - } - - for _, registry := range info.RegistryConfig.InsecureRegistryCIDRs { - mask, _ := registry.Mask.Size() - fmt.Fprintf(dockerCli.Out(), " %s/%d\n", registry.IP.String(), mask) - } - } - - if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 { - fmt.Fprintln(dockerCli.Out(), "Registry Mirrors:") - for _, mirror := range info.RegistryConfig.Mirrors { - fmt.Fprintln(dockerCli.Out(), " "+mirror) - } - } - - fmt.Fprintln(dockerCli.Out(), "Live Restore Enabled:", info.LiveRestoreEnabled) - fmt.Fprint(dockerCli.Out(), "\n") - - // Only output these warnings if the server does not support these features - if info.OSType != "windows" { - printStorageDriverWarnings(dockerCli, info) - - if !info.MemoryLimit { - fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support") - } - if !info.SwapLimit { - fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support") - } - if !info.KernelMemory { - fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support") - } - if !info.OomKillDisable { - fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support") - } - if !info.CPUCfsQuota { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support") - } - if !info.CPUCfsPeriod { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support") - } - if !info.CPUShares { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support") - } - if !info.CPUSet { - fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support") - } - if !info.IPv4Forwarding { - fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled") - } - if !info.BridgeNfIptables { - fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled") - } - if !info.BridgeNfIP6tables { - fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled") - } - } - - return nil -} - -func printSwarmInfo(dockerCli command.Cli, info types.Info) { - if info.Swarm.LocalNodeState == swarm.LocalNodeStateInactive || info.Swarm.LocalNodeState == swarm.LocalNodeStateLocked { - return - } - fmt.Fprintln(dockerCli.Out(), " NodeID:", info.Swarm.NodeID) - if info.Swarm.Error != "" { - fmt.Fprintln(dockerCli.Out(), " Error:", info.Swarm.Error) - } - fmt.Fprintln(dockerCli.Out(), " Is Manager:", info.Swarm.ControlAvailable) - if info.Swarm.Cluster != nil && info.Swarm.ControlAvailable && info.Swarm.Error == "" && info.Swarm.LocalNodeState != swarm.LocalNodeStateError { - fmt.Fprintln(dockerCli.Out(), " ClusterID:", info.Swarm.Cluster.ID) - fmt.Fprintln(dockerCli.Out(), " Managers:", info.Swarm.Managers) - fmt.Fprintln(dockerCli.Out(), " Nodes:", info.Swarm.Nodes) - fmt.Fprintln(dockerCli.Out(), " Orchestration:") - taskHistoryRetentionLimit := int64(0) - if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil { - taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit - } - fmt.Fprintln(dockerCli.Out(), " Task History Retention Limit:", taskHistoryRetentionLimit) - fmt.Fprintln(dockerCli.Out(), " Raft:") - fmt.Fprintln(dockerCli.Out(), " Snapshot Interval:", info.Swarm.Cluster.Spec.Raft.SnapshotInterval) - if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil { - fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots) - } - fmt.Fprintln(dockerCli.Out(), " Heartbeat Tick:", info.Swarm.Cluster.Spec.Raft.HeartbeatTick) - fmt.Fprintln(dockerCli.Out(), " Election Tick:", info.Swarm.Cluster.Spec.Raft.ElectionTick) - fmt.Fprintln(dockerCli.Out(), " Dispatcher:") - fmt.Fprintln(dockerCli.Out(), " Heartbeat Period:", units.HumanDuration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod)) - fmt.Fprintln(dockerCli.Out(), " CA Configuration:") - fmt.Fprintln(dockerCli.Out(), " Expiry Duration:", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry)) - fmt.Fprintln(dockerCli.Out(), " Force Rotate:", info.Swarm.Cluster.Spec.CAConfig.ForceRotate) - if caCert := strings.TrimSpace(info.Swarm.Cluster.Spec.CAConfig.SigningCACert); caCert != "" { - fmt.Fprintf(dockerCli.Out(), " Signing CA Certificate: \n%s\n\n", caCert) - } - if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 { - fmt.Fprintln(dockerCli.Out(), " External CAs:") - for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs { - fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL) - } - } - fmt.Fprintln(dockerCli.Out(), " Autolock Managers:", info.Swarm.Cluster.Spec.EncryptionConfig.AutoLockManagers) - fmt.Fprintln(dockerCli.Out(), " Root Rotation In Progress:", info.Swarm.Cluster.RootRotationInProgress) - } - fmt.Fprintln(dockerCli.Out(), " Node Address:", info.Swarm.NodeAddr) - if len(info.Swarm.RemoteManagers) > 0 { - managers := []string{} - for _, entry := range info.Swarm.RemoteManagers { - managers = append(managers, entry.Addr) - } - sort.Strings(managers) - fmt.Fprintln(dockerCli.Out(), " Manager Addresses:") - for _, entry := range managers { - fmt.Fprintf(dockerCli.Out(), " %s\n", entry) - } - } -} - -func printStorageDriverWarnings(dockerCli command.Cli, info types.Info) { - if info.DriverStatus == nil { - return - } - - for _, pair := range info.DriverStatus { - if pair[0] == "Data loop file" { - fmt.Fprintf(dockerCli.Err(), "WARNING: %s: usage of loopback devices is "+ - "strongly discouraged for production use.\n "+ - "Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.\n", info.Driver) - } - if pair[0] == "Supports d_type" && pair[1] == "false" { - backingFs := getBackingFs(info) - - msg := fmt.Sprintf("WARNING: %s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.\n", info.Driver, backingFs) - if backingFs == "xfs" { - msg += " Reformat the filesystem with ftype=1 to enable d_type support.\n" - } - msg += " Running without d_type support will not be supported in future releases." - fmt.Fprintln(dockerCli.Err(), msg) - } - } -} - -func getBackingFs(info types.Info) string { - if info.DriverStatus == nil { - return "" - } - - for _, pair := range info.DriverStatus { - if pair[0] == "Backing Filesystem" { - return pair[1] - } - } - return "" -} - -func formatInfo(dockerCli *command.DockerCli, info types.Info, format string) error { - tmpl, err := templates.Parse(format) - if err != nil { - return cli.StatusError{StatusCode: 64, - Status: "Template parsing error: " + err.Error()} - } - err = tmpl.Execute(dockerCli.Out(), info) - dockerCli.Out().Write([]byte{'\n'}) - return err -} - -func fprintlnNonEmpty(w io.Writer, label, value string) { - if value != "" { - fmt.Fprintln(w, label, value) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/system/info_test.go b/vendor/github.com/docker/cli/cli/command/system/info_test.go deleted file mode 100644 index 4291623d1..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/info_test.go +++ /dev/null @@ -1,237 +0,0 @@ -package system - -import ( - "encoding/base64" - "net" - "testing" - "time" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -// helper function that base64 decodes a string and ignores the error -func base64Decode(val string) []byte { - decoded, _ := base64.StdEncoding.DecodeString(val) - return decoded -} - -var sampleInfoNoSwarm = types.Info{ - ID: "EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX", - Containers: 0, - ContainersRunning: 0, - ContainersPaused: 0, - ContainersStopped: 0, - Images: 0, - Driver: "aufs", - DriverStatus: [][2]string{ - {"Root Dir", "/var/lib/docker/aufs"}, - {"Backing Filesystem", "extfs"}, - {"Dirs", "0"}, - {"Dirperm1 Supported", "true"}, - }, - SystemStatus: nil, - Plugins: types.PluginsInfo{ - Volume: []string{"local"}, - Network: []string{"bridge", "host", "macvlan", "null", "overlay"}, - Authorization: nil, - Log: []string{"awslogs", "fluentd", "gcplogs", "gelf", "journald", "json-file", "logentries", "splunk", "syslog"}, - }, - MemoryLimit: true, - SwapLimit: true, - KernelMemory: true, - CPUCfsPeriod: true, - CPUCfsQuota: true, - CPUShares: true, - CPUSet: true, - IPv4Forwarding: true, - BridgeNfIptables: true, - BridgeNfIP6tables: true, - Debug: true, - NFd: 33, - OomKillDisable: true, - NGoroutines: 135, - SystemTime: "2017-08-24T17:44:34.077811894Z", - LoggingDriver: "json-file", - CgroupDriver: "cgroupfs", - NEventsListener: 0, - KernelVersion: "4.4.0-87-generic", - OperatingSystem: "Ubuntu 16.04.3 LTS", - OSType: "linux", - Architecture: "x86_64", - IndexServerAddress: "https://index.docker.io/v1/", - RegistryConfig: ®istry.ServiceConfig{ - AllowNondistributableArtifactsCIDRs: nil, - AllowNondistributableArtifactsHostnames: nil, - InsecureRegistryCIDRs: []*registry.NetIPNet{ - { - IP: net.ParseIP("127.0.0.0"), - Mask: net.IPv4Mask(255, 0, 0, 0), - }, - }, - IndexConfigs: map[string]*registry.IndexInfo{ - "docker.io": { - Name: "docker.io", - Mirrors: nil, - Secure: true, - Official: true, - }, - }, - Mirrors: nil, - }, - NCPU: 2, - MemTotal: 2097356800, - DockerRootDir: "/var/lib/docker", - HTTPProxy: "", - HTTPSProxy: "", - NoProxy: "", - Name: "system-sample", - Labels: []string{"provider=digitalocean"}, - ExperimentalBuild: false, - ServerVersion: "17.06.1-ce", - ClusterStore: "", - ClusterAdvertise: "", - Runtimes: map[string]types.Runtime{ - "runc": { - Path: "docker-runc", - Args: nil, - }, - }, - DefaultRuntime: "runc", - Swarm: swarm.Info{LocalNodeState: "inactive"}, - LiveRestoreEnabled: false, - Isolation: "", - InitBinary: "docker-init", - ContainerdCommit: types.Commit{ - ID: "6e23458c129b551d5c9871e5174f6b1b7f6d1170", - Expected: "6e23458c129b551d5c9871e5174f6b1b7f6d1170", - }, - RuncCommit: types.Commit{ - ID: "810190ceaa507aa2727d7ae6f4790c76ec150bd2", - Expected: "810190ceaa507aa2727d7ae6f4790c76ec150bd2", - }, - InitCommit: types.Commit{ - ID: "949e6fa", - Expected: "949e6fa", - }, - SecurityOptions: []string{"name=apparmor", "name=seccomp,profile=default"}, -} - -var sampleSwarmInfo = swarm.Info{ - NodeID: "qo2dfdig9mmxqkawulggepdih", - NodeAddr: "165.227.107.89", - LocalNodeState: "active", - ControlAvailable: true, - Error: "", - RemoteManagers: []swarm.Peer{ - { - NodeID: "qo2dfdig9mmxqkawulggepdih", - Addr: "165.227.107.89:2377", - }, - }, - Nodes: 1, - Managers: 1, - Cluster: &swarm.ClusterInfo{ - ID: "9vs5ygs0gguyyec4iqf2314c0", - Meta: swarm.Meta{ - Version: swarm.Version{Index: 11}, - CreatedAt: time.Date(2017, 8, 24, 17, 34, 19, 278062352, time.UTC), - UpdatedAt: time.Date(2017, 8, 24, 17, 34, 42, 398815481, time.UTC), - }, - Spec: swarm.Spec{ - Annotations: swarm.Annotations{ - Name: "default", - Labels: nil, - }, - Orchestration: swarm.OrchestrationConfig{ - TaskHistoryRetentionLimit: &[]int64{5}[0], - }, - Raft: swarm.RaftConfig{ - SnapshotInterval: 10000, - KeepOldSnapshots: &[]uint64{0}[0], - LogEntriesForSlowFollowers: 500, - ElectionTick: 3, - HeartbeatTick: 1, - }, - Dispatcher: swarm.DispatcherConfig{ - HeartbeatPeriod: 5000000000, - }, - CAConfig: swarm.CAConfig{ - NodeCertExpiry: 7776000000000000, - }, - TaskDefaults: swarm.TaskDefaults{}, - EncryptionConfig: swarm.EncryptionConfig{ - AutoLockManagers: true, - }, - }, - TLSInfo: swarm.TLSInfo{ - TrustRoot: ` ------BEGIN CERTIFICATE----- -MIIBajCCARCgAwIBAgIUaFCW5xsq8eyiJ+Pmcv3MCflMLnMwCgYIKoZIzj0EAwIw -EzERMA8GA1UEAxMIc3dhcm0tY2EwHhcNMTcwODI0MTcyOTAwWhcNMzcwODE5MTcy -OTAwWjATMREwDwYDVQQDEwhzd2FybS1jYTBZMBMGByqGSM49AgEGCCqGSM49AwEH -A0IABDy7NebyUJyUjWJDBUdnZoV6GBxEGKO4TZPNDwnxDxJcUdLVaB7WGa4/DLrW -UfsVgh1JGik2VTiLuTMA1tLlNPOjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB -Af8EBTADAQH/MB0GA1UdDgQWBBQl16XFtaaXiUAwEuJptJlDjfKskDAKBggqhkjO -PQQDAgNIADBFAiEAo9fTQNM5DP9bHVcTJYfl2Cay1bFu1E+lnpmN+EYJfeACIGKH -1pCUkZ+D0IB6CiEZGWSHyLuXPM1rlP+I5KuS7sB8 ------END CERTIFICATE----- -`, - CertIssuerSubject: base64Decode("MBMxETAPBgNVBAMTCHN3YXJtLWNh"), - CertIssuerPublicKey: base64Decode( - "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPLs15vJQnJSNYkMFR2dmhXoYHEQYo7hNk80PCfEPElxR0tVoHtYZrj8MutZR+xWCHUkaKTZVOIu5MwDW0uU08w=="), - }, - RootRotationInProgress: false, - }, -} - -func TestPrettyPrintInfo(t *testing.T) { - infoWithSwarm := sampleInfoNoSwarm - infoWithSwarm.Swarm = sampleSwarmInfo - - infoWithWarningsLinux := sampleInfoNoSwarm - infoWithWarningsLinux.MemoryLimit = false - infoWithWarningsLinux.SwapLimit = false - infoWithWarningsLinux.KernelMemory = false - infoWithWarningsLinux.OomKillDisable = false - infoWithWarningsLinux.CPUCfsQuota = false - infoWithWarningsLinux.CPUCfsPeriod = false - infoWithWarningsLinux.CPUShares = false - infoWithWarningsLinux.CPUSet = false - infoWithWarningsLinux.IPv4Forwarding = false - infoWithWarningsLinux.BridgeNfIptables = false - infoWithWarningsLinux.BridgeNfIP6tables = false - - for _, tc := range []struct { - dockerInfo types.Info - expectedGolden string - warningsGolden string - }{ - { - dockerInfo: sampleInfoNoSwarm, - expectedGolden: "docker-info-no-swarm", - }, - { - dockerInfo: infoWithSwarm, - expectedGolden: "docker-info-with-swarm", - }, - { - dockerInfo: infoWithWarningsLinux, - expectedGolden: "docker-info-no-swarm", - warningsGolden: "docker-info-warnings", - }, - } { - cli := test.NewFakeCli(&fakeClient{}) - assert.NoError(t, prettyPrintInfo(cli, tc.dockerInfo)) - golden.Assert(t, cli.OutBuffer().String(), tc.expectedGolden+".golden") - if tc.warningsGolden != "" { - golden.Assert(t, cli.ErrBuffer().String(), tc.warningsGolden+".golden") - } else { - assert.Equal(t, "", cli.ErrBuffer().String()) - } - } -} diff --git a/vendor/github.com/docker/cli/cli/command/system/inspect.go b/vendor/github.com/docker/cli/cli/command/system/inspect.go deleted file mode 100644 index 6d079cd69..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/inspect.go +++ /dev/null @@ -1,216 +0,0 @@ -package system - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/docker/docker/api/types" - apiclient "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - format string - inspectType string - size bool - ids []string -} - -// NewInspectCommand creates a new cobra.Command for `docker inspect` -func NewInspectCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] NAME|ID [NAME|ID...]", - Short: "Return low-level information on Docker objects", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.ids = args - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type") - flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container") - - return cmd -} - -func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { - var elementSearcher inspect.GetRefFunc - switch opts.inspectType { - case "", "container", "image", "node", "network", "service", "volume", "task", "plugin", "secret": - elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType) - default: - return errors.Errorf("%q is not a valid value for --type", opts.inspectType) - } - return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher) -} - -func inspectContainers(ctx context.Context, dockerCli *command.DockerCli, getSize bool) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize) - } -} - -func inspectImages(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().ImageInspectWithRaw(ctx, ref) - } -} - -func inspectNetwork(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().NetworkInspectWithRaw(ctx, ref, types.NetworkInspectOptions{}) - } -} - -func inspectNode(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().NodeInspectWithRaw(ctx, ref) - } -} - -func inspectService(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - // Service inspect shows defaults values in empty fields. - return dockerCli.Client().ServiceInspectWithRaw(ctx, ref, types.ServiceInspectOptions{InsertDefaults: true}) - } -} - -func inspectTasks(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().TaskInspectWithRaw(ctx, ref) - } -} - -func inspectVolume(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().VolumeInspectWithRaw(ctx, ref) - } -} - -func inspectPlugin(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().PluginInspectWithRaw(ctx, ref) - } -} - -func inspectSecret(ctx context.Context, dockerCli *command.DockerCli) inspect.GetRefFunc { - return func(ref string) (interface{}, []byte, error) { - return dockerCli.Client().SecretInspectWithRaw(ctx, ref) - } -} - -func inspectAll(ctx context.Context, dockerCli *command.DockerCli, getSize bool, typeConstraint string) inspect.GetRefFunc { - var inspectAutodetect = []struct { - objectType string - isSizeSupported bool - isSwarmObject bool - objectInspector func(string) (interface{}, []byte, error) - }{ - { - objectType: "container", - isSizeSupported: true, - objectInspector: inspectContainers(ctx, dockerCli, getSize), - }, - { - objectType: "image", - objectInspector: inspectImages(ctx, dockerCli), - }, - { - objectType: "network", - objectInspector: inspectNetwork(ctx, dockerCli), - }, - { - objectType: "volume", - objectInspector: inspectVolume(ctx, dockerCli), - }, - { - objectType: "service", - isSwarmObject: true, - objectInspector: inspectService(ctx, dockerCli), - }, - { - objectType: "task", - isSwarmObject: true, - objectInspector: inspectTasks(ctx, dockerCli), - }, - { - objectType: "node", - isSwarmObject: true, - objectInspector: inspectNode(ctx, dockerCli), - }, - { - objectType: "plugin", - objectInspector: inspectPlugin(ctx, dockerCli), - }, - { - objectType: "secret", - isSwarmObject: true, - objectInspector: inspectSecret(ctx, dockerCli), - }, - } - - // isSwarmManager does an Info API call to verify that the daemon is - // a swarm manager. - isSwarmManager := func() bool { - info, err := dockerCli.Client().Info(ctx) - if err != nil { - fmt.Fprintln(dockerCli.Err(), err) - return false - } - return info.Swarm.ControlAvailable - } - - isErrNotSupported := func(err error) bool { - return strings.Contains(err.Error(), "not supported") - } - - return func(ref string) (interface{}, []byte, error) { - const ( - swarmSupportUnknown = iota - swarmSupported - swarmUnsupported - ) - - isSwarmSupported := swarmSupportUnknown - - for _, inspectData := range inspectAutodetect { - if typeConstraint != "" && inspectData.objectType != typeConstraint { - continue - } - if typeConstraint == "" && inspectData.isSwarmObject { - if isSwarmSupported == swarmSupportUnknown { - if isSwarmManager() { - isSwarmSupported = swarmSupported - } else { - isSwarmSupported = swarmUnsupported - } - } - if isSwarmSupported == swarmUnsupported { - continue - } - } - v, raw, err := inspectData.objectInspector(ref) - if err != nil { - if typeConstraint == "" && (apiclient.IsErrNotFound(err) || isErrNotSupported(err)) { - continue - } - return v, raw, err - } - if getSize && !inspectData.isSizeSupported { - fmt.Fprintf(dockerCli.Err(), "WARNING: --size ignored for %s\n", inspectData.objectType) - } - return v, raw, err - } - return nil, nil, errors.Errorf("Error: No such object: %s", ref) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/system/prune.go b/vendor/github.com/docker/cli/cli/command/system/prune.go deleted file mode 100644 index d76d995e3..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/prune.go +++ /dev/null @@ -1,135 +0,0 @@ -package system - -import ( - "bytes" - "fmt" - "text/template" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/container" - "github.com/docker/cli/cli/command/image" - "github.com/docker/cli/cli/command/network" - "github.com/docker/cli/cli/command/volume" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/versions" - units "github.com/docker/go-units" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type pruneOptions struct { - force bool - all bool - pruneBuildCache bool - pruneVolumes bool - filter opts.FilterOpt -} - -// newPruneCommand creates a new cobra.Command for `docker prune` -func newPruneCommand(dockerCli command.Cli) *cobra.Command { - options := pruneOptions{filter: opts.NewFilterOpt(), pruneBuildCache: true} - - cmd := &cobra.Command{ - Use: "prune [OPTIONS]", - Short: "Remove unused data", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runPrune(dockerCli, options) - }, - Tags: map[string]string{"version": "1.25"}, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") - flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused images not just dangling ones") - flags.BoolVar(&options.pruneVolumes, "volumes", false, "Prune volumes") - flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'label==')") - // "filter" flag is available in 1.28 (docker 17.04) and up - flags.SetAnnotation("filter", "version", []string{"1.28"}) - - return cmd -} - -const confirmationTemplate = `WARNING! This will remove: -{{- range $_, $warning := . }} - - {{ $warning }} -{{- end }} -Are you sure you want to continue?` - -// runBuildCachePrune executes a prune command for build cache -func runBuildCachePrune(dockerCli command.Cli, _ opts.FilterOpt) (uint64, string, error) { - report, err := dockerCli.Client().BuildCachePrune(context.Background()) - if err != nil { - return 0, "", err - } - return report.SpaceReclaimed, "", nil -} - -func runPrune(dockerCli command.Cli, options pruneOptions) error { - // TODO version this once "until" filter is supported for volumes - if options.pruneVolumes && options.filter.Value().Include("until") { - return fmt.Errorf(`ERROR: The "until" filter is not supported with "--volumes"`) - } - if versions.LessThan(dockerCli.Client().ClientVersion(), "1.31") { - options.pruneBuildCache = false - } - if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(options)) { - return nil - } - imagePrune := func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error) { - return image.RunPrune(dockerCli, options.all, options.filter) - } - pruneFuncs := []func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error){ - container.RunPrune, - network.RunPrune, - } - if options.pruneVolumes { - pruneFuncs = append(pruneFuncs, volume.RunPrune) - } - pruneFuncs = append(pruneFuncs, imagePrune) - if options.pruneBuildCache { - pruneFuncs = append(pruneFuncs, runBuildCachePrune) - } - - var spaceReclaimed uint64 - for _, pruneFn := range pruneFuncs { - spc, output, err := pruneFn(dockerCli, options.filter) - if err != nil { - return err - } - spaceReclaimed += spc - if output != "" { - fmt.Fprintln(dockerCli.Out(), output) - } - } - - fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) - - return nil -} - -// confirmationMessage constructs a confirmation message that depends on the cli options. -func confirmationMessage(options pruneOptions) string { - t := template.Must(template.New("confirmation message").Parse(confirmationTemplate)) - - warnings := []string{ - "all stopped containers", - "all networks not used by at least one container", - } - if options.pruneVolumes { - warnings = append(warnings, "all volumes not used by at least one container") - } - if options.all { - warnings = append(warnings, "all images without at least one container associated to them") - } else { - warnings = append(warnings, "all dangling images") - } - if options.pruneBuildCache { - warnings = append(warnings, "all build cache") - } - - var buffer bytes.Buffer - t.Execute(&buffer, &warnings) - return buffer.String() -} diff --git a/vendor/github.com/docker/cli/cli/command/system/prune_test.go b/vendor/github.com/docker/cli/cli/command/system/prune_test.go deleted file mode 100644 index 0d694ce06..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/prune_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package system - -import ( - "testing" - - "github.com/docker/cli/internal/test" - "github.com/stretchr/testify/assert" -) - -func TestPrunePromptPre131(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{version: "1.30"}) - cmd := newPruneCommand(cli) - assert.NoError(t, cmd.Execute()) - assert.NotContains(t, cli.OutBuffer().String(), "all build cache") -} diff --git a/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-no-swarm.golden b/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-no-swarm.golden deleted file mode 100644 index 7a3e96673..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-no-swarm.golden +++ /dev/null @@ -1,51 +0,0 @@ -Containers: 0 - Running: 0 - Paused: 0 - Stopped: 0 -Images: 0 -Server Version: 17.06.1-ce -Storage Driver: aufs - Root Dir: /var/lib/docker/aufs - Backing Filesystem: extfs - Dirs: 0 - Dirperm1 Supported: true -Logging Driver: json-file -Cgroup Driver: cgroupfs -Plugins: - Volume: local - Network: bridge host macvlan null overlay - Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog -Swarm: inactive -Runtimes: runc -Default Runtime: runc -Init Binary: docker-init -containerd version: 6e23458c129b551d5c9871e5174f6b1b7f6d1170 -runc version: 810190ceaa507aa2727d7ae6f4790c76ec150bd2 -init version: 949e6fa -Security Options: - apparmor - seccomp - Profile: default -Kernel Version: 4.4.0-87-generic -Operating System: Ubuntu 16.04.3 LTS -OSType: linux -Architecture: x86_64 -CPUs: 2 -Total Memory: 1.953GiB -Name: system-sample -ID: EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX -Docker Root Dir: /var/lib/docker -Debug Mode (client): false -Debug Mode (server): true - File Descriptors: 33 - Goroutines: 135 - System Time: 2017-08-24T17:44:34.077811894Z - EventsListeners: 0 -Registry: https://index.docker.io/v1/ -Labels: - provider=digitalocean -Experimental: false -Insecure Registries: - 127.0.0.0/8 -Live Restore Enabled: false - diff --git a/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-warnings.golden b/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-warnings.golden deleted file mode 100644 index a7a4d792b..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-warnings.golden +++ /dev/null @@ -1,11 +0,0 @@ -WARNING: No memory limit support -WARNING: No swap limit support -WARNING: No kernel memory limit support -WARNING: No oom kill disable support -WARNING: No cpu cfs quota support -WARNING: No cpu cfs period support -WARNING: No cpu shares support -WARNING: No cpuset support -WARNING: IPv4 forwarding is disabled -WARNING: bridge-nf-call-iptables is disabled -WARNING: bridge-nf-call-ip6tables is disabled diff --git a/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-with-swarm.golden b/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-with-swarm.golden deleted file mode 100644 index 17bb70fa7..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/testdata/docker-info-with-swarm.golden +++ /dev/null @@ -1,73 +0,0 @@ -Containers: 0 - Running: 0 - Paused: 0 - Stopped: 0 -Images: 0 -Server Version: 17.06.1-ce -Storage Driver: aufs - Root Dir: /var/lib/docker/aufs - Backing Filesystem: extfs - Dirs: 0 - Dirperm1 Supported: true -Logging Driver: json-file -Cgroup Driver: cgroupfs -Plugins: - Volume: local - Network: bridge host macvlan null overlay - Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog -Swarm: active - NodeID: qo2dfdig9mmxqkawulggepdih - Is Manager: true - ClusterID: 9vs5ygs0gguyyec4iqf2314c0 - Managers: 1 - Nodes: 1 - Orchestration: - Task History Retention Limit: 5 - Raft: - Snapshot Interval: 10000 - Number of Old Snapshots to Retain: 0 - Heartbeat Tick: 1 - Election Tick: 3 - Dispatcher: - Heartbeat Period: 5 seconds - CA Configuration: - Expiry Duration: 3 months - Force Rotate: 0 - Autolock Managers: true - Root Rotation In Progress: false - Node Address: 165.227.107.89 - Manager Addresses: - 165.227.107.89:2377 -Runtimes: runc -Default Runtime: runc -Init Binary: docker-init -containerd version: 6e23458c129b551d5c9871e5174f6b1b7f6d1170 -runc version: 810190ceaa507aa2727d7ae6f4790c76ec150bd2 -init version: 949e6fa -Security Options: - apparmor - seccomp - Profile: default -Kernel Version: 4.4.0-87-generic -Operating System: Ubuntu 16.04.3 LTS -OSType: linux -Architecture: x86_64 -CPUs: 2 -Total Memory: 1.953GiB -Name: system-sample -ID: EKHL:QDUU:QZ7U:MKGD:VDXK:S27Q:GIPU:24B7:R7VT:DGN6:QCSF:2UBX -Docker Root Dir: /var/lib/docker -Debug Mode (client): false -Debug Mode (server): true - File Descriptors: 33 - Goroutines: 135 - System Time: 2017-08-24T17:44:34.077811894Z - EventsListeners: 0 -Registry: https://index.docker.io/v1/ -Labels: - provider=digitalocean -Experimental: false -Insecure Registries: - 127.0.0.0/8 -Live Restore Enabled: false - diff --git a/vendor/github.com/docker/cli/cli/command/system/version.go b/vendor/github.com/docker/cli/cli/command/system/version.go deleted file mode 100644 index 9cca599fe..000000000 --- a/vendor/github.com/docker/cli/cli/command/system/version.go +++ /dev/null @@ -1,130 +0,0 @@ -package system - -import ( - "runtime" - "time" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/templates" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -var versionTemplate = `Client: - Version: {{.Client.Version}} - API version: {{.Client.APIVersion}}{{if ne .Client.APIVersion .Client.DefaultAPIVersion}} (downgraded from {{.Client.DefaultAPIVersion}}){{end}} - Go version: {{.Client.GoVersion}} - Git commit: {{.Client.GitCommit}} - Built: {{.Client.BuildTime}} - OS/Arch: {{.Client.Os}}/{{.Client.Arch}}{{if .ServerOK}} - -Server: - Version: {{.Server.Version}} - API version: {{.Server.APIVersion}} (minimum version {{.Server.MinAPIVersion}}) - Go version: {{.Server.GoVersion}} - Git commit: {{.Server.GitCommit}} - Built: {{.Server.BuildTime}} - OS/Arch: {{.Server.Os}}/{{.Server.Arch}} - Experimental: {{.Server.Experimental}}{{end}}` - -type versionOptions struct { - format string -} - -// versionInfo contains version information of both the Client, and Server -type versionInfo struct { - Client clientVersion - Server *types.Version -} - -type clientVersion struct { - Version string - APIVersion string `json:"ApiVersion"` - DefaultAPIVersion string `json:"DefaultAPIVersion,omitempty"` - GitCommit string - GoVersion string - Os string - Arch string - BuildTime string `json:",omitempty"` -} - -// ServerOK returns true when the client could connect to the docker server -// and parse the information received. It returns false otherwise. -func (v versionInfo) ServerOK() bool { - return v.Server != nil -} - -// NewVersionCommand creates a new cobra.Command for `docker version` -func NewVersionCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts versionOptions - - cmd := &cobra.Command{ - Use: "version [OPTIONS]", - Short: "Show the Docker version information", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runVersion(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - - return cmd -} - -func runVersion(dockerCli *command.DockerCli, opts *versionOptions) error { - ctx := context.Background() - - templateFormat := versionTemplate - if opts.format != "" { - templateFormat = opts.format - } - - tmpl, err := templates.Parse(templateFormat) - if err != nil { - return cli.StatusError{StatusCode: 64, - Status: "Template parsing error: " + err.Error()} - } - - vd := versionInfo{ - Client: clientVersion{ - Version: cli.Version, - APIVersion: dockerCli.Client().ClientVersion(), - DefaultAPIVersion: dockerCli.DefaultVersion(), - GoVersion: runtime.Version(), - GitCommit: cli.GitCommit, - BuildTime: cli.BuildTime, - Os: runtime.GOOS, - Arch: runtime.GOARCH, - }, - } - - serverVersion, err := dockerCli.Client().ServerVersion(ctx) - if err == nil { - vd.Server = &serverVersion - } - - // first we need to make BuildTime more human friendly - t, errTime := time.Parse(time.RFC3339Nano, vd.Client.BuildTime) - if errTime == nil { - vd.Client.BuildTime = t.Format(time.ANSIC) - } - - if vd.ServerOK() { - t, errTime = time.Parse(time.RFC3339Nano, vd.Server.BuildTime) - if errTime == nil { - vd.Server.BuildTime = t.Format(time.ANSIC) - } - } - - if err2 := tmpl.Execute(dockerCli.Out(), vd); err2 != nil && err == nil { - err = err2 - } - dockerCli.Out().Write([]byte{'\n'}) - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/task/client_test.go b/vendor/github.com/docker/cli/cli/command/task/client_test.go deleted file mode 100644 index d04405c23..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/client_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package task - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.APIClient - nodeInspectWithRaw func(ref string) (swarm.Node, []byte, error) - serviceInspectWithRaw func(ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) -} - -func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) { - if cli.nodeInspectWithRaw != nil { - return cli.nodeInspectWithRaw(ref) - } - return swarm.Node{}, nil, nil -} - -func (cli *fakeClient) ServiceInspectWithRaw(ctx context.Context, ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { - if cli.serviceInspectWithRaw != nil { - return cli.serviceInspectWithRaw(ref, options) - } - return swarm.Service{}, nil, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/task/print.go b/vendor/github.com/docker/cli/cli/command/task/print.go deleted file mode 100644 index 6526c28be..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/print.go +++ /dev/null @@ -1,93 +0,0 @@ -package task - -import ( - "fmt" - "sort" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/docker/api/types/swarm" - "golang.org/x/net/context" -) - -type tasksBySlot []swarm.Task - -func (t tasksBySlot) Len() int { - return len(t) -} - -func (t tasksBySlot) Swap(i, j int) { - t[i], t[j] = t[j], t[i] -} - -func (t tasksBySlot) Less(i, j int) bool { - // Sort by slot. - if t[i].Slot != t[j].Slot { - return t[i].Slot < t[j].Slot - } - - // If same slot, sort by most recent. - return t[j].Meta.CreatedAt.Before(t[i].CreatedAt) -} - -// Print task information in a format. -// Besides this, command `docker node ps ` -// and `docker stack ps` will call this, too. -func Print(ctx context.Context, dockerCli command.Cli, tasks []swarm.Task, resolver *idresolver.IDResolver, trunc, quiet bool, format string) error { - sort.Stable(tasksBySlot(tasks)) - - names := map[string]string{} - nodes := map[string]string{} - - tasksCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewTaskFormat(format, quiet), - Trunc: trunc, - } - - prevName := "" - for _, task := range tasks { - serviceName, err := resolver.Resolve(ctx, swarm.Service{}, task.ServiceID) - if err != nil { - return err - } - - nodeValue, err := resolver.Resolve(ctx, swarm.Node{}, task.NodeID) - if err != nil { - return err - } - - var name string - if task.Slot != 0 { - name = fmt.Sprintf("%v.%v", serviceName, task.Slot) - } else { - name = fmt.Sprintf("%v.%v", serviceName, task.NodeID) - } - - // Indent the name if necessary - indentedName := name - if name == prevName { - indentedName = fmt.Sprintf(" \\_ %s", indentedName) - } - prevName = name - - names[task.ID] = name - if tasksCtx.Format.IsTable() { - names[task.ID] = indentedName - } - nodes[task.ID] = nodeValue - } - - return formatter.TaskWrite(tasksCtx, tasks, names, nodes) -} - -// DefaultFormat returns the default format from the config file, or table -// format if nothing is set in the config. -func DefaultFormat(configFile *configfile.ConfigFile, quiet bool) string { - if len(configFile.TasksFormat) > 0 && !quiet { - return configFile.TasksFormat - } - return formatter.TableFormatKey -} diff --git a/vendor/github.com/docker/cli/cli/command/task/print_test.go b/vendor/github.com/docker/cli/cli/command/task/print_test.go deleted file mode 100644 index 04ae1bb0e..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/print_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package task - -import ( - "testing" - "time" - - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/internal/test" - "golang.org/x/net/context" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestTaskPrintWithQuietOption(t *testing.T) { - quiet := true - trunc := false - noResolve := true - apiClient := &fakeClient{} - cli := test.NewFakeCli(apiClient) - tasks := []swarm.Task{*Task(TaskID("id-foo"))} - err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, formatter.TableFormatKey) - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), "task-print-with-quiet-option.golden") -} - -func TestTaskPrintWithNoTruncOption(t *testing.T) { - quiet := false - trunc := false - noResolve := true - apiClient := &fakeClient{} - cli := test.NewFakeCli(apiClient) - tasks := []swarm.Task{ - *Task(TaskID("id-foo-yov6omdek8fg3k5stosyp2m50")), - } - err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .ID }}") - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), "task-print-with-no-trunc-option.golden") -} - -func TestTaskPrintWithGlobalService(t *testing.T) { - quiet := false - trunc := false - noResolve := true - apiClient := &fakeClient{} - cli := test.NewFakeCli(apiClient) - tasks := []swarm.Task{ - *Task(TaskServiceID("service-id-foo"), TaskNodeID("node-id-bar"), TaskSlot(0)), - } - err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .Name }}") - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), "task-print-with-global-service.golden") -} - -func TestTaskPrintWithReplicatedService(t *testing.T) { - quiet := false - trunc := false - noResolve := true - apiClient := &fakeClient{} - cli := test.NewFakeCli(apiClient) - tasks := []swarm.Task{ - *Task(TaskServiceID("service-id-foo"), TaskSlot(1)), - } - err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .Name }}") - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), "task-print-with-replicated-service.golden") -} - -func TestTaskPrintWithIndentation(t *testing.T) { - quiet := false - trunc := false - noResolve := false - apiClient := &fakeClient{ - serviceInspectWithRaw: func(ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { - return *Service(ServiceName("service-name-foo")), nil, nil - }, - nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) { - return *Node(NodeName("node-name-bar")), nil, nil - }, - } - cli := test.NewFakeCli(apiClient) - tasks := []swarm.Task{ - *Task( - TaskID("id-foo"), - TaskServiceID("service-id-foo"), - TaskNodeID("id-node"), - WithTaskSpec(TaskImage("myimage:mytag")), - TaskDesiredState(swarm.TaskStateReady), - WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))), - ), - *Task( - TaskID("id-bar"), - TaskServiceID("service-id-foo"), - TaskNodeID("id-node"), - WithTaskSpec(TaskImage("myimage:mytag")), - TaskDesiredState(swarm.TaskStateReady), - WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))), - ), - } - err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, formatter.TableFormatKey) - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), "task-print-with-indentation.golden") -} - -func TestTaskPrintWithResolution(t *testing.T) { - quiet := false - trunc := false - noResolve := false - apiClient := &fakeClient{ - serviceInspectWithRaw: func(ref string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) { - return *Service(ServiceName("service-name-foo")), nil, nil - }, - nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) { - return *Node(NodeName("node-name-bar")), nil, nil - }, - } - cli := test.NewFakeCli(apiClient) - tasks := []swarm.Task{ - *Task(TaskServiceID("service-id-foo"), TaskSlot(1)), - } - err := Print(context.Background(), cli, tasks, idresolver.New(apiClient, noResolve), trunc, quiet, "{{ .Name }} {{ .Node }}") - assert.NoError(t, err) - golden.Assert(t, cli.OutBuffer().String(), "task-print-with-resolution.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-global-service.golden b/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-global-service.golden deleted file mode 100644 index fbc81248d..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-global-service.golden +++ /dev/null @@ -1 +0,0 @@ -service-id-foo.node-id-bar diff --git a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-indentation.golden b/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-indentation.golden deleted file mode 100644 index 8fa174a44..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-indentation.golden +++ /dev/null @@ -1,3 +0,0 @@ -ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS -id-foo service-name-foo.1 myimage:mytag node-name-bar Ready Failed 2 hours ago -id-bar \_ service-name-foo.1 myimage:mytag node-name-bar Ready Failed 2 hours ago diff --git a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-no-trunc-option.golden b/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-no-trunc-option.golden deleted file mode 100644 index 184d2de20..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-no-trunc-option.golden +++ /dev/null @@ -1 +0,0 @@ -id-foo-yov6omdek8fg3k5stosyp2m50 diff --git a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-quiet-option.golden b/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-quiet-option.golden deleted file mode 100644 index e2faeb606..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-quiet-option.golden +++ /dev/null @@ -1 +0,0 @@ -id-foo diff --git a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-replicated-service.golden b/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-replicated-service.golden deleted file mode 100644 index 9ecebdafe..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-replicated-service.golden +++ /dev/null @@ -1 +0,0 @@ -service-id-foo.1 diff --git a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-resolution.golden b/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-resolution.golden deleted file mode 100644 index 747d1af46..000000000 --- a/vendor/github.com/docker/cli/cli/command/task/testdata/task-print-with-resolution.golden +++ /dev/null @@ -1 +0,0 @@ -service-name-foo.1 node-name-bar diff --git a/vendor/github.com/docker/cli/cli/command/trust.go b/vendor/github.com/docker/cli/cli/command/trust.go deleted file mode 100644 index 51f760ac5..000000000 --- a/vendor/github.com/docker/cli/cli/command/trust.go +++ /dev/null @@ -1,47 +0,0 @@ -package command - -import ( - "os" - "strconv" - - "github.com/spf13/pflag" -) - -var ( - // TODO: make this not global - untrusted bool -) - -func init() { - untrusted = !getDefaultTrustState() -} - -// AddTrustVerificationFlags adds content trust flags to the provided flagset -func AddTrustVerificationFlags(fs *pflag.FlagSet) { - trusted := getDefaultTrustState() - fs.BoolVar(&untrusted, "disable-content-trust", !trusted, "Skip image verification") -} - -// AddTrustSigningFlags adds "signing" flags to the provided flagset -func AddTrustSigningFlags(fs *pflag.FlagSet) { - trusted := getDefaultTrustState() - fs.BoolVar(&untrusted, "disable-content-trust", !trusted, "Skip image signing") -} - -// getDefaultTrustState returns true if content trust is enabled through the $DOCKER_CONTENT_TRUST environment variable. -func getDefaultTrustState() bool { - var trusted bool - if e := os.Getenv("DOCKER_CONTENT_TRUST"); e != "" { - if t, err := strconv.ParseBool(e); t || err != nil { - // treat any other value as true - trusted = true - } - } - return trusted -} - -// IsTrusted returns true if content trust is enabled, either through the $DOCKER_CONTENT_TRUST environment variable, -// or through `--disabled-content-trust=false` on a command. -func IsTrusted() bool { - return !untrusted -} diff --git a/vendor/github.com/docker/cli/cli/command/utils.go b/vendor/github.com/docker/cli/cli/command/utils.go deleted file mode 100644 index 3f4acaa2e..000000000 --- a/vendor/github.com/docker/cli/cli/command/utils.go +++ /dev/null @@ -1,119 +0,0 @@ -package command - -import ( - "bufio" - "fmt" - "io" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/pkg/system" -) - -// CopyToFile writes the content of the reader to the specified file -func CopyToFile(outfile string, r io.Reader) error { - // We use sequential file access here to avoid depleting the standby list - // on Windows. On Linux, this is a call directly to ioutil.TempFile - tmpFile, err := system.TempFileSequential(filepath.Dir(outfile), ".docker_temp_") - if err != nil { - return err - } - - tmpPath := tmpFile.Name() - - _, err = io.Copy(tmpFile, r) - tmpFile.Close() - - if err != nil { - os.Remove(tmpPath) - return err - } - - if err = os.Rename(tmpPath, outfile); err != nil { - os.Remove(tmpPath) - return err - } - - return nil -} - -// capitalizeFirst capitalizes the first character of string -func capitalizeFirst(s string) string { - switch l := len(s); l { - case 0: - return s - case 1: - return strings.ToLower(s) - default: - return strings.ToUpper(string(s[0])) + strings.ToLower(s[1:]) - } -} - -// PrettyPrint outputs arbitrary data for human formatted output by uppercasing the first letter. -func PrettyPrint(i interface{}) string { - switch t := i.(type) { - case nil: - return "None" - case string: - return capitalizeFirst(t) - default: - return capitalizeFirst(fmt.Sprintf("%s", t)) - } -} - -// PromptForConfirmation requests and checks confirmation from user. -// This will display the provided message followed by ' [y/N] '. If -// the user input 'y' or 'Y' it returns true other false. If no -// message is provided "Are you sure you want to proceed? [y/N] " -// will be used instead. -func PromptForConfirmation(ins io.Reader, outs io.Writer, message string) bool { - if message == "" { - message = "Are you sure you want to proceed?" - } - message += " [y/N] " - - fmt.Fprintf(outs, message) - - // On Windows, force the use of the regular OS stdin stream. - if runtime.GOOS == "windows" { - ins = NewInStream(os.Stdin) - } - - reader := bufio.NewReader(ins) - answer, _, _ := reader.ReadLine() - return strings.ToLower(string(answer)) == "y" -} - -// PruneFilters returns consolidated prune filters obtained from config.json and cli -func PruneFilters(dockerCli Cli, pruneFilters filters.Args) filters.Args { - if dockerCli.ConfigFile() == nil { - return pruneFilters - } - for _, f := range dockerCli.ConfigFile().PruneFilters { - parts := strings.SplitN(f, "=", 2) - if len(parts) != 2 { - continue - } - if parts[0] == "label" { - // CLI label filter supersede config.json. - // If CLI label filter conflict with config.json, - // skip adding label! filter in config.json. - if pruneFilters.Include("label!") && pruneFilters.ExactMatch("label!", parts[1]) { - continue - } - } else if parts[0] == "label!" { - // CLI label! filter supersede config.json. - // If CLI label! filter conflict with config.json, - // skip adding label filter in config.json. - if pruneFilters.Include("label") && pruneFilters.ExactMatch("label", parts[1]) { - continue - } - } - pruneFilters.Add(parts[0], parts[1]) - } - - return pruneFilters -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/client_test.go b/vendor/github.com/docker/cli/cli/command/volume/client_test.go deleted file mode 100644 index c29655cdb..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/client_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package volume - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - volumetypes "github.com/docker/docker/api/types/volume" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -type fakeClient struct { - client.Client - volumeCreateFunc func(volumetypes.VolumesCreateBody) (types.Volume, error) - volumeInspectFunc func(volumeID string) (types.Volume, error) - volumeListFunc func(filter filters.Args) (volumetypes.VolumesListOKBody, error) - volumeRemoveFunc func(volumeID string, force bool) error - volumePruneFunc func(filter filters.Args) (types.VolumesPruneReport, error) -} - -func (c *fakeClient) VolumeCreate(ctx context.Context, options volumetypes.VolumesCreateBody) (types.Volume, error) { - if c.volumeCreateFunc != nil { - return c.volumeCreateFunc(options) - } - return types.Volume{}, nil -} - -func (c *fakeClient) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) { - if c.volumeInspectFunc != nil { - return c.volumeInspectFunc(volumeID) - } - return types.Volume{}, nil -} - -func (c *fakeClient) VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error) { - if c.volumeListFunc != nil { - return c.volumeListFunc(filter) - } - return volumetypes.VolumesListOKBody{}, nil -} - -func (c *fakeClient) VolumesPrune(ctx context.Context, filter filters.Args) (types.VolumesPruneReport, error) { - if c.volumePruneFunc != nil { - return c.volumePruneFunc(filter) - } - return types.VolumesPruneReport{}, nil -} - -func (c *fakeClient) VolumeRemove(ctx context.Context, volumeID string, force bool) error { - if c.volumeRemoveFunc != nil { - return c.volumeRemoveFunc(volumeID, force) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/cmd.go b/vendor/github.com/docker/cli/cli/command/volume/cmd.go deleted file mode 100644 index cf6e61dfb..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/cmd.go +++ /dev/null @@ -1,26 +0,0 @@ -package volume - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewVolumeCommand returns a cobra command for `volume` subcommands -func NewVolumeCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "volume COMMAND", - Short: "Manage volumes", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.21"}, - } - cmd.AddCommand( - newCreateCommand(dockerCli), - newInspectCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - NewPruneCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/create.go b/vendor/github.com/docker/cli/cli/command/volume/create.go deleted file mode 100644 index 5a1092266..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/create.go +++ /dev/null @@ -1,69 +0,0 @@ -package volume - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - volumetypes "github.com/docker/docker/api/types/volume" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type createOptions struct { - name string - driver string - driverOpts opts.MapOpts - labels opts.ListOpts -} - -func newCreateCommand(dockerCli command.Cli) *cobra.Command { - options := createOptions{ - driverOpts: *opts.NewMapOpts(nil, nil), - labels: opts.NewListOpts(opts.ValidateEnv), - } - - cmd := &cobra.Command{ - Use: "create [OPTIONS] [VOLUME]", - Short: "Create a volume", - Args: cli.RequiresMaxArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) == 1 { - if options.name != "" { - return errors.Errorf("Conflicting options: either specify --name or provide positional arg, not both\n") - } - options.name = args[0] - } - return runCreate(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.StringVarP(&options.driver, "driver", "d", "local", "Specify volume driver name") - flags.StringVar(&options.name, "name", "", "Specify volume name") - flags.Lookup("name").Hidden = true - flags.VarP(&options.driverOpts, "opt", "o", "Set driver specific options") - flags.Var(&options.labels, "label", "Set metadata for a volume") - - return cmd -} - -func runCreate(dockerCli command.Cli, options createOptions) error { - client := dockerCli.Client() - - volReq := volumetypes.VolumesCreateBody{ - Driver: options.driver, - DriverOpts: options.driverOpts.GetAll(), - Name: options.name, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - } - - vol, err := client.VolumeCreate(context.Background(), volReq) - if err != nil { - return err - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", vol.Name) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/create_test.go b/vendor/github.com/docker/cli/cli/command/volume/create_test.go deleted file mode 100644 index d7c6cb585..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/create_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package volume - -import ( - "io/ioutil" - "reflect" - "strings" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/cli/internal/test/testutil" - "github.com/docker/docker/api/types" - volumetypes "github.com/docker/docker/api/types/volume" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestVolumeCreateErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - volumeCreateFunc func(volumetypes.VolumesCreateBody) (types.Volume, error) - expectedError string - }{ - { - args: []string{"volumeName"}, - flags: map[string]string{ - "name": "volumeName", - }, - expectedError: "Conflicting options: either specify --name or provide positional arg, not both", - }, - { - args: []string{"too", "many"}, - expectedError: "requires at most 1 argument", - }, - { - volumeCreateFunc: func(createBody volumetypes.VolumesCreateBody) (types.Volume, error) { - return types.Volume{}, errors.Errorf("error creating volume") - }, - expectedError: "error creating volume", - }, - } - for _, tc := range testCases { - cmd := newCreateCommand( - test.NewFakeCli(&fakeClient{ - volumeCreateFunc: tc.volumeCreateFunc, - }), - ) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestVolumeCreateWithName(t *testing.T) { - name := "foo" - cli := test.NewFakeCli(&fakeClient{ - volumeCreateFunc: func(body volumetypes.VolumesCreateBody) (types.Volume, error) { - if body.Name != name { - return types.Volume{}, errors.Errorf("expected name %q, got %q", name, body.Name) - } - return types.Volume{ - Name: body.Name, - }, nil - }, - }) - - buf := cli.OutBuffer() - - // Test by flags - cmd := newCreateCommand(cli) - cmd.Flags().Set("name", name) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, name, strings.TrimSpace(buf.String())) - - // Then by args - buf.Reset() - cmd = newCreateCommand(cli) - cmd.SetArgs([]string{name}) - assert.NoError(t, cmd.Execute()) - assert.Equal(t, name, strings.TrimSpace(buf.String())) -} - -func TestVolumeCreateWithFlags(t *testing.T) { - expectedDriver := "foo" - expectedOpts := map[string]string{ - "bar": "1", - "baz": "baz", - } - expectedLabels := map[string]string{ - "lbl1": "v1", - "lbl2": "v2", - } - name := "banana" - - cli := test.NewFakeCli(&fakeClient{ - volumeCreateFunc: func(body volumetypes.VolumesCreateBody) (types.Volume, error) { - if body.Name != "" { - return types.Volume{}, errors.Errorf("expected empty name, got %q", body.Name) - } - if body.Driver != expectedDriver { - return types.Volume{}, errors.Errorf("expected driver %q, got %q", expectedDriver, body.Driver) - } - if !reflect.DeepEqual(body.DriverOpts, expectedOpts) { - return types.Volume{}, errors.Errorf("expected drivers opts %v, got %v", expectedOpts, body.DriverOpts) - } - if !reflect.DeepEqual(body.Labels, expectedLabels) { - return types.Volume{}, errors.Errorf("expected labels %v, got %v", expectedLabels, body.Labels) - } - return types.Volume{ - Name: name, - }, nil - }, - }) - - cmd := newCreateCommand(cli) - cmd.Flags().Set("driver", "foo") - cmd.Flags().Set("opt", "bar=1") - cmd.Flags().Set("opt", "baz=baz") - cmd.Flags().Set("label", "lbl1=v1") - cmd.Flags().Set("label", "lbl2=v2") - assert.NoError(t, cmd.Execute()) - assert.Equal(t, name, strings.TrimSpace(cli.OutBuffer().String())) -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/inspect.go b/vendor/github.com/docker/cli/cli/command/volume/inspect.go deleted file mode 100644 index b8729e21c..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/inspect.go +++ /dev/null @@ -1,45 +0,0 @@ -package volume - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - format string - names []string -} - -func newInspectCommand(dockerCli command.Cli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] VOLUME [VOLUME...]", - Short: "Display detailed information on one or more volumes", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.names = args - return runInspect(dockerCli, opts) - }, - } - - cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - - return cmd -} - -func runInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - - ctx := context.Background() - - getVolFunc := func(name string) (interface{}, []byte, error) { - i, err := client.VolumeInspect(ctx, name) - return i, nil, err - } - - return inspect.Inspect(dockerCli.Out(), opts.names, opts.format, getVolFunc) -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/inspect_test.go b/vendor/github.com/docker/cli/cli/command/volume/inspect_test.go deleted file mode 100644 index 934e9b27d..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/inspect_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package volume - -import ( - "fmt" - "io/ioutil" - "testing" - - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestVolumeInspectErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - volumeInspectFunc func(volumeID string) (types.Volume, error) - expectedError string - }{ - { - expectedError: "requires at least 1 argument", - }, - { - args: []string{"foo"}, - volumeInspectFunc: func(volumeID string) (types.Volume, error) { - return types.Volume{}, errors.Errorf("error while inspecting the volume") - }, - expectedError: "error while inspecting the volume", - }, - { - args: []string{"foo"}, - flags: map[string]string{ - "format": "{{invalid format}}", - }, - expectedError: "Template parsing error", - }, - { - args: []string{"foo", "bar"}, - volumeInspectFunc: func(volumeID string) (types.Volume, error) { - if volumeID == "foo" { - return types.Volume{ - Name: "foo", - }, nil - } - return types.Volume{}, errors.Errorf("error while inspecting the volume") - }, - expectedError: "error while inspecting the volume", - }, - } - for _, tc := range testCases { - cmd := newInspectCommand( - test.NewFakeCli(&fakeClient{ - volumeInspectFunc: tc.volumeInspectFunc, - }), - ) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestVolumeInspectWithoutFormat(t *testing.T) { - testCases := []struct { - name string - args []string - volumeInspectFunc func(volumeID string) (types.Volume, error) - }{ - { - name: "single-volume", - args: []string{"foo"}, - volumeInspectFunc: func(volumeID string) (types.Volume, error) { - if volumeID != "foo" { - return types.Volume{}, errors.Errorf("Invalid volumeID, expected %s, got %s", "foo", volumeID) - } - return *Volume(), nil - }, - }, - { - name: "multiple-volume-with-labels", - args: []string{"foo", "bar"}, - volumeInspectFunc: func(volumeID string) (types.Volume, error) { - return *Volume(VolumeName(volumeID), VolumeLabels(map[string]string{ - "foo": "bar", - })), nil - }, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - volumeInspectFunc: tc.volumeInspectFunc, - }) - cmd := newInspectCommand(cli) - cmd.SetArgs(tc.args) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("volume-inspect-without-format.%s.golden", tc.name)) - } -} - -func TestVolumeInspectWithFormat(t *testing.T) { - volumeInspectFunc := func(volumeID string) (types.Volume, error) { - return *Volume(VolumeLabels(map[string]string{ - "foo": "bar", - })), nil - } - testCases := []struct { - name string - format string - args []string - volumeInspectFunc func(volumeID string) (types.Volume, error) - }{ - { - name: "simple-template", - format: "{{.Name}}", - args: []string{"foo"}, - volumeInspectFunc: volumeInspectFunc, - }, - { - name: "json-template", - format: "{{json .Labels}}", - args: []string{"foo"}, - volumeInspectFunc: volumeInspectFunc, - }, - } - for _, tc := range testCases { - cli := test.NewFakeCli(&fakeClient{ - volumeInspectFunc: tc.volumeInspectFunc, - }) - cmd := newInspectCommand(cli) - cmd.SetArgs(tc.args) - cmd.Flags().Set("format", tc.format) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), fmt.Sprintf("volume-inspect-with-format.%s.golden", tc.name)) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/list.go b/vendor/github.com/docker/cli/cli/command/volume/list.go deleted file mode 100644 index d9b5ef80e..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/list.go +++ /dev/null @@ -1,73 +0,0 @@ -package volume - -import ( - "sort" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type byVolumeName []*types.Volume - -func (r byVolumeName) Len() int { return len(r) } -func (r byVolumeName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byVolumeName) Less(i, j int) bool { - return r[i].Name < r[j].Name -} - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List volumes", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display volume names") - flags.StringVar(&options.format, "format", "", "Pretty-print volumes using a Go template") - flags.VarP(&options.filter, "filter", "f", "Provide filter values (e.g. 'dangling=true')") - - return cmd -} - -func runList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - volumes, err := client.VolumeList(context.Background(), options.filter.Value()) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().VolumesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().VolumesFormat - } else { - format = formatter.TableFormatKey - } - } - - sort.Sort(byVolumeName(volumes.Volumes)) - - volumeCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewVolumeFormat(format, options.quiet), - } - return formatter.VolumeWrite(volumeCtx, volumes.Volumes) -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/list_test.go b/vendor/github.com/docker/cli/cli/command/volume/list_test.go deleted file mode 100644 index 264e1010a..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/list_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package volume - -import ( - "io/ioutil" - "testing" - - "github.com/docker/cli/cli/config/configfile" - "github.com/docker/cli/internal/test" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - volumetypes "github.com/docker/docker/api/types/volume" - "github.com/pkg/errors" - // Import builders to get the builder function as package function - . "github.com/docker/cli/internal/test/builders" - "github.com/docker/cli/internal/test/testutil" - "github.com/gotestyourself/gotestyourself/golden" - "github.com/stretchr/testify/assert" -) - -func TestVolumeListErrors(t *testing.T) { - testCases := []struct { - args []string - flags map[string]string - volumeListFunc func(filter filters.Args) (volumetypes.VolumesListOKBody, error) - expectedError string - }{ - { - args: []string{"foo"}, - expectedError: "accepts no argument", - }, - { - volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) { - return volumetypes.VolumesListOKBody{}, errors.Errorf("error listing volumes") - }, - expectedError: "error listing volumes", - }, - } - for _, tc := range testCases { - cmd := newListCommand( - test.NewFakeCli(&fakeClient{ - volumeListFunc: tc.volumeListFunc, - }), - ) - cmd.SetArgs(tc.args) - for key, value := range tc.flags { - cmd.Flags().Set(key, value) - } - cmd.SetOutput(ioutil.Discard) - testutil.ErrorContains(t, cmd.Execute(), tc.expectedError) - } -} - -func TestVolumeListWithoutFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) { - return volumetypes.VolumesListOKBody{ - Volumes: []*types.Volume{ - Volume(), - Volume(VolumeName("foo"), VolumeDriver("bar")), - Volume(VolumeName("baz"), VolumeLabels(map[string]string{ - "foo": "bar", - })), - }, - }, nil - }, - }) - cmd := newListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "volume-list-without-format.golden") -} - -func TestVolumeListWithConfigFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) { - return volumetypes.VolumesListOKBody{ - Volumes: []*types.Volume{ - Volume(), - Volume(VolumeName("foo"), VolumeDriver("bar")), - Volume(VolumeName("baz"), VolumeLabels(map[string]string{ - "foo": "bar", - })), - }, - }, nil - }, - }) - cli.SetConfigFile(&configfile.ConfigFile{ - VolumesFormat: "{{ .Name }} {{ .Driver }} {{ .Labels }}", - }) - cmd := newListCommand(cli) - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "volume-list-with-config-format.golden") -} - -func TestVolumeListWithFormat(t *testing.T) { - cli := test.NewFakeCli(&fakeClient{ - volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) { - return volumetypes.VolumesListOKBody{ - Volumes: []*types.Volume{ - Volume(), - Volume(VolumeName("foo"), VolumeDriver("bar")), - Volume(VolumeName("baz"), VolumeLabels(map[string]string{ - "foo": "bar", - })), - }, - }, nil - }, - }) - cmd := newListCommand(cli) - cmd.Flags().Set("format", "{{ .Name }} {{ .Driver }} {{ .Labels }}") - assert.NoError(t, cmd.Execute()) - golden.Assert(t, cli.OutBuffer().String(), "volume-list-with-format.golden") -} diff --git a/vendor/github.com/docker/cli/cli/command/volume/prune.go b/vendor/github.com/docker/cli/cli/command/volume/prune.go deleted file mode 100644 index 157f883b0..000000000 --- a/vendor/github.com/docker/cli/cli/command/volume/prune.go +++ /dev/null @@ -1,78 +0,0 @@ -package volume - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - units "github.com/docker/go-units" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type pruneOptions struct { - force bool - filter opts.FilterOpt -} - -// NewPruneCommand returns a new cobra prune command for volumes -func NewPruneCommand(dockerCli command.Cli) *cobra.Command { - options := pruneOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "prune [OPTIONS]", - Short: "Remove all unused volumes", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - spaceReclaimed, output, err := runPrune(dockerCli, options) - if err != nil { - return err - } - if output != "" { - fmt.Fprintln(dockerCli.Out(), output) - } - fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed))) - return nil - }, - Tags: map[string]string{"version": "1.25"}, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") - flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'label=