diff --git a/Gopkg.lock b/Gopkg.lock index fe71d33ed..94a37c200 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -4,7 +4,10 @@ [[projects]] branch = "master" name = "github.com/Azure/go-ansiterm" - packages = [".","winterm"] + packages = [ + ".", + "winterm" + ] revision = "d6e3b3328b783f23731bc4d058875b0371ff8109" [[projects]] @@ -51,9 +54,37 @@ [[projects]] name = "github.com/aws/aws-sdk-go" - packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/s3","service/s3/s3iface","service/s3/s3manager","service/sts"] - revision = "9ed0c8de252f04ac45a65358377103d5a1aa2d92" - version = "v1.12.66" + packages = [ + "aws", + "aws/awserr", + "aws/awsutil", + "aws/client", + "aws/client/metadata", + "aws/corehandlers", + "aws/credentials", + "aws/credentials/ec2rolecreds", + "aws/credentials/endpointcreds", + "aws/credentials/stscreds", + "aws/defaults", + "aws/ec2metadata", + "aws/endpoints", + "aws/request", + "aws/session", + "aws/signer/v4", + "internal/shareddefaults", + "private/protocol", + "private/protocol/query", + "private/protocol/query/queryutil", + "private/protocol/rest", + "private/protocol/restxml", + "private/protocol/xml/xmlutil", + "service/s3", + "service/s3/s3iface", + "service/s3/s3manager", + "service/sts" + ] + revision = "decd990ddc5dcdf2f73309cbcab90d06b996ca28" + version = "v1.12.67" [[projects]] branch = "master" @@ -80,13 +111,55 @@ [[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"] + 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]] + branch = "master" 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","opts","pkg/archive","pkg/fileutils","pkg/homedir","pkg/idtools","pkg/ioutils","pkg/jsonmessage","pkg/longpath","pkg/mount","pkg/pools","pkg/stdcopy","pkg/system","pkg/term","pkg/term/windows"] - revision = "fe8aac6f5ae413a967adb0adad0b54abdfb825c4" + 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", + "opts", + "pkg/archive", + "pkg/fileutils", + "pkg/homedir", + "pkg/idtools", + "pkg/ioutils", + "pkg/jsonmessage", + "pkg/longpath", + "pkg/mount", + "pkg/pools", + "pkg/stdcopy", + "pkg/system", + "pkg/term", + "pkg/term/windows" + ] + revision = "99cfb5f31ad82238573de3475bf5bb0435ac1ebc" [[projects]] name = "github.com/docker/go-connections" @@ -132,7 +205,14 @@ [[projects]] name = "github.com/fnproject/fn_go" - packages = ["client","client/apps","client/call","client/operations","client/routes","models"] + packages = [ + "client", + "client/apps", + "client/call", + "client/operations", + "client/routes", + "models" + ] revision = "847fec724330b2741336431502db292fc5a45211" version = "0.2.3" @@ -143,7 +223,10 @@ [[projects]] name = "github.com/garyburd/redigo" - packages = ["internal","redis"] + packages = [ + "internal", + "redis" + ] revision = "d1ed5c67e5794de818ea85e6b522fda02623a484" version = "v1.4.0" @@ -161,7 +244,11 @@ [[projects]] name = "github.com/gin-gonic/gin" - packages = [".","binding","render"] + packages = [ + ".", + "binding", + "render" + ] revision = "d459835d2b077e44f7c9b453505ee29881d5d12d" version = "v1.2" @@ -210,8 +297,17 @@ [[projects]] branch = "master" name = "github.com/go-openapi/runtime" - packages = [".","client","logger","middleware","middleware/denco","middleware/header","middleware/untyped","security"] - revision = "a76104f379d3c5041f2a56e69db3ad8404ce4826" + packages = [ + ".", + "client", + "logger", + "middleware", + "middleware/denco", + "middleware/header", + "middleware/untyped", + "security" + ] + revision = "be1313bd8283bc82b48033942f0f3730eaef2d90" [[projects]] branch = "master" @@ -252,7 +348,7 @@ branch = "master" name = "github.com/golang/protobuf" packages = ["proto"] - revision = "1e59b77b52bf8e4b449a57e6f79f21226d571845" + revision = "c65a0412e71e8b9b3bfd22925720d23c0f054237" [[projects]] branch = "master" @@ -286,7 +382,10 @@ [[projects]] branch = "master" name = "github.com/jmoiron/sqlx" - packages = [".","reflectx"] + packages = [ + ".", + "reflectx" + ] revision = "de8647470aafe4854c976707c431dbe1eb2822c6" [[projects]] @@ -298,18 +397,29 @@ [[projects]] branch = "master" name = "github.com/lib/pq" - packages = [".","oid"] - revision = "27ea5d92de30060e7121ddd543fe14e9a327e0cc" + packages = [ + ".", + "oid" + ] + revision = "61fe37aa2ee24fabcdbe5c4ac1d4ac566f88f345" [[projects]] branch = "master" name = "github.com/mailru/easyjson" - packages = ["buffer","jlexer","jwriter"] + packages = [ + "buffer", + "jlexer", + "jwriter" + ] revision = "32fa128f234d041f196a9f3e0fea5ac9772c08e1" [[projects]] name = "github.com/mattes/migrate" - packages = [".","database","source"] + packages = [ + ".", + "database", + "source" + ] revision = "035c07716cd373d88456ec4d701402df52584cb4" version = "v3.0.1" @@ -345,13 +455,19 @@ [[projects]] name = "github.com/opencontainers/image-spec" - packages = ["specs-go","specs-go/v1"] + packages = [ + "specs-go", + "specs-go/v1" + ] revision = "d60099175f88c47cd379c4738d158884749ed235" version = "v1.0.1" [[projects]] name = "github.com/opencontainers/runc" - packages = ["libcontainer/system","libcontainer/user"] + packages = [ + "libcontainer/system", + "libcontainer/user" + ] revision = "baf6536d6259209c3edfa2b22237af82942d3dfa" version = "v0.1.1" @@ -363,13 +479,24 @@ [[projects]] name = "github.com/opentracing/opentracing-go" - packages = [".","ext","log"] + packages = [ + ".", + "ext", + "log" + ] revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38" version = "v1.0.2" [[projects]] name = "github.com/openzipkin/zipkin-go-opentracing" - packages = [".","flag","thrift/gen-go/scribe","thrift/gen-go/zipkincore","types","wire"] + packages = [ + ".", + "flag", + "thrift/gen-go/scribe", + "thrift/gen-go/zipkincore", + "types", + "wire" + ] revision = "45e90b00710a4c34a1a7d8a78d90f9b010b0bd4d" version = "v0.3.2" @@ -405,7 +532,10 @@ [[projects]] name = "github.com/prometheus/client_golang" - packages = ["prometheus","prometheus/promhttp"] + packages = [ + "prometheus", + "prometheus/promhttp" + ] revision = "c5b7fccd204277076155f10851dad72b76a49317" version = "v0.8.0" @@ -418,14 +548,23 @@ [[projects]] branch = "master" name = "github.com/prometheus/common" - packages = ["expfmt","internal/bitbucket.org/ww/goautoneg","model"] + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model" + ] revision = "89604d197083d4781071d3c65855d24ecfb0a563" [[projects]] branch = "master" name = "github.com/prometheus/procfs" - packages = [".","xfs"] - revision = "b15cd069a83443be3154b719d0cc9fe8117f09fb" + packages = [ + ".", + "internal/util", + "nfsd", + "xfs" + ] + revision = "85fadb6e89903ef7cca6f6a804474cd5ea85b6e1" [[projects]] branch = "master" @@ -435,12 +574,22 @@ [[projects]] name = "github.com/rdallman/migrate" - packages = [".","database/mysql","database/postgres","database/sqlite3","source","source/go-bindata"] + packages = [ + ".", + "database/mysql", + "database/postgres", + "database/sqlite3", + "source", + "source/go-bindata" + ] revision = "bc72eeb997c7334cb5f05f5aefd2d70bc34d71ef" [[projects]] name = "github.com/sirupsen/logrus" - packages = [".","hooks/syslog"] + packages = [ + ".", + "hooks/syslog" + ] revision = "89742aefa4b206dcf400792f3bd35b542998eb3b" [[projects]] @@ -453,24 +602,47 @@ branch = "master" name = "golang.org/x/crypto" packages = ["ssh/terminal"] - revision = "a6600008915114d9c087fad9f03d75087b1a74df" + revision = "3d37316aaa6bd9929127ac9a527abf408178ea7b" [[projects]] branch = "master" name = "golang.org/x/net" - packages = ["context","context/ctxhttp","idna"] + packages = [ + "context", + "context/ctxhttp", + "idna" + ] revision = "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec" [[projects]] branch = "master" name = "golang.org/x/sys" - packages = ["unix","windows"] - revision = "2c42eef0765b9837fbdab12011af7830f55f88f0" + packages = [ + "unix", + "windows" + ] + revision = "af50095a40f9041b3b38960738837185c26e9419" [[projects]] branch = "master" name = "golang.org/x/text" - packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable","width"] + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable", + "width" + ] revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3" [[projects]] @@ -482,7 +654,10 @@ [[projects]] branch = "v2" name = "gopkg.in/mgo.v2" - packages = ["bson","internal/json"] + packages = [ + "bson", + "internal/json" + ] revision = "3f83fa5005286a7fe593b055f0d7771a7dce4655" [[projects]] @@ -494,6 +669,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "3f78f93ac5508cf8125bb9acba9c83f70b76b11e1977b98f54999d90f3dccee9" + inputs-digest = "556d3a6039ee958f59418b978bbb50d2733c1069bdcb67c931ffa0ab09195097" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index c340859a4..77600bbc6 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -25,14 +25,6 @@ ignored = ["github.com/fnproject/fn/cli"] 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" @@ -65,14 +57,6 @@ ignored = ["github.com/fnproject/fn/cli"] 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" @@ -85,22 +69,6 @@ ignored = ["github.com/fnproject/fn/cli"] 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" - [[constraint]] name = "github.com/aws/aws-sdk-go" version = "~1.12.59" diff --git a/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md b/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md index 986c5e5c0..b1a9a579a 100644 --- a/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md +++ b/vendor/github.com/aws/aws-sdk-go/CHANGELOG.md @@ -1,3 +1,10 @@ +Release v1.12.67 (2018-01-22) +=== + +### Service Client Updates +* `service/budgets`: Updates service API and documentation + * Add additional costTypes: IncludeDiscount, UseAmortized, to support finer control for different charges included in a cost budget. + Release v1.12.66 (2018-01-19) === diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go index 7bd32f3d6..73ac333a7 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/version.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws const SDKName = "aws-sdk-go" // SDKVersion is the version of this SDK -const SDKVersion = "1.12.66" +const SDKVersion = "1.12.67" diff --git a/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/api-2.json b/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/api-2.json index 1f9b8bdef..d33d9b433 100755 --- a/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/api-2.json +++ b/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/api-2.json @@ -283,7 +283,9 @@ "IncludeUpfront":{"shape":"NullableBoolean"}, "IncludeRecurring":{"shape":"NullableBoolean"}, "IncludeOtherSubscription":{"shape":"NullableBoolean"}, - "IncludeSupport":{"shape":"NullableBoolean"} + "IncludeSupport":{"shape":"NullableBoolean"}, + "IncludeDiscount":{"shape":"NullableBoolean"}, + "UseAmortized":{"shape":"NullableBoolean"} } }, "CreateBudgetRequest":{ diff --git a/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/docs-2.json b/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/docs-2.json index 2e5a54379..328186c82 100755 --- a/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/docs-2.json +++ b/vendor/github.com/aws/aws-sdk-go/models/apis/budgets/2016-10-20/docs-2.json @@ -321,7 +321,9 @@ "CostTypes$IncludeUpfront": "A boolean value whether to include upfront costs in the cost budget.", "CostTypes$IncludeRecurring": "A boolean value whether to include recurring costs in the cost budget.", "CostTypes$IncludeOtherSubscription": "A boolean value whether to include other subscription costs in the cost budget.", - "CostTypes$IncludeSupport": "A boolean value whether to include support costs in the cost budget." + "CostTypes$IncludeSupport": "A boolean value whether to include support costs in the cost budget.", + "CostTypes$IncludeDiscount": "A boolean value whether to include discounts in the cost budget.", + "CostTypes$UseAmortized": "A boolean value whether to include amortized costs in the cost budget." } }, "NumericValue": { diff --git a/vendor/github.com/aws/aws-sdk-go/service/budgets/api.go b/vendor/github.com/aws/aws-sdk-go/service/budgets/api.go index 2490161b2..c24f7bd2a 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/budgets/api.go +++ b/vendor/github.com/aws/aws-sdk-go/service/budgets/api.go @@ -1357,6 +1357,9 @@ type CostTypes struct { // A boolean value whether to include credits in the cost budget. IncludeCredit *bool `type:"boolean"` + // A boolean value whether to include discounts in the cost budget. + IncludeDiscount *bool `type:"boolean"` + // A boolean value whether to include other subscription costs in the cost budget. IncludeOtherSubscription *bool `type:"boolean"` @@ -1378,6 +1381,9 @@ type CostTypes struct { // A boolean value whether to include upfront costs in the cost budget. IncludeUpfront *bool `type:"boolean"` + // A boolean value whether to include amortized costs in the cost budget. + UseAmortized *bool `type:"boolean"` + // A boolean value whether to use blended costs in the cost budget. UseBlended *bool `type:"boolean"` } @@ -1398,6 +1404,12 @@ func (s *CostTypes) SetIncludeCredit(v bool) *CostTypes { return s } +// SetIncludeDiscount sets the IncludeDiscount field's value. +func (s *CostTypes) SetIncludeDiscount(v bool) *CostTypes { + s.IncludeDiscount = &v + return s +} + // SetIncludeOtherSubscription sets the IncludeOtherSubscription field's value. func (s *CostTypes) SetIncludeOtherSubscription(v bool) *CostTypes { s.IncludeOtherSubscription = &v @@ -1440,6 +1452,12 @@ func (s *CostTypes) SetIncludeUpfront(v bool) *CostTypes { return s } +// SetUseAmortized sets the UseAmortized field's value. +func (s *CostTypes) SetUseAmortized(v bool) *CostTypes { + s.UseAmortized = &v + return s +} + // SetUseBlended sets the UseBlended field's value. func (s *CostTypes) SetUseBlended(v bool) *CostTypes { s.UseBlended = &v diff --git a/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy.go b/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy.go index 8967f357a..9c180eabd 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy.go +++ b/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy.go @@ -63,9 +63,12 @@ func (strat HeaderV2SaveStrategy) Save(env Envelope, req *request.Request) error input.Metadata[http.CanonicalHeaderKey(matDescHeader)] = &env.MatDesc input.Metadata[http.CanonicalHeaderKey(wrapAlgorithmHeader)] = &env.WrapAlg input.Metadata[http.CanonicalHeaderKey(cekAlgorithmHeader)] = &env.CEKAlg - input.Metadata[http.CanonicalHeaderKey(tagLengthHeader)] = &env.TagLen input.Metadata[http.CanonicalHeaderKey(unencryptedMD5Header)] = &env.UnencryptedMD5 input.Metadata[http.CanonicalHeaderKey(unencryptedContentLengthHeader)] = &env.UnencryptedContentLen + + if len(env.TagLen) > 0 { + input.Metadata[http.CanonicalHeaderKey(tagLengthHeader)] = &env.TagLen + } return nil } diff --git a/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy_test.go b/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy_test.go index 54d6634fe..10e3d864b 100644 --- a/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy_test.go +++ b/vendor/github.com/aws/aws-sdk-go/service/s3/s3crypto/strategy_test.go @@ -11,38 +11,67 @@ import ( ) func TestHeaderV2SaveStrategy(t *testing.T) { - env := s3crypto.Envelope{ - CipherKey: "Foo", - IV: "Bar", - MatDesc: "{}", - WrapAlg: s3crypto.KMSWrap, - CEKAlg: s3crypto.AESGCMNoPadding, - TagLen: "128", - UnencryptedMD5: "hello", - UnencryptedContentLen: "0", - } - params := &s3.PutObjectInput{} - req := &request.Request{ - Params: params, - } - strat := s3crypto.HeaderV2SaveStrategy{} - err := strat.Save(env, req) - if err != nil { - t.Errorf("expected no error, but received %v", err) + cases := []struct { + env s3crypto.Envelope + expected map[string]*string + }{ + { + s3crypto.Envelope{ + CipherKey: "Foo", + IV: "Bar", + MatDesc: "{}", + WrapAlg: s3crypto.KMSWrap, + CEKAlg: s3crypto.AESGCMNoPadding, + TagLen: "128", + UnencryptedMD5: "hello", + UnencryptedContentLen: "0", + }, + map[string]*string{ + "X-Amz-Key-V2": aws.String("Foo"), + "X-Amz-Iv": aws.String("Bar"), + "X-Amz-Matdesc": aws.String("{}"), + "X-Amz-Wrap-Alg": aws.String(s3crypto.KMSWrap), + "X-Amz-Cek-Alg": aws.String(s3crypto.AESGCMNoPadding), + "X-Amz-Tag-Len": aws.String("128"), + "X-Amz-Unencrypted-Content-Md5": aws.String("hello"), + "X-Amz-Unencrypted-Content-Length": aws.String("0"), + }, + }, + { + s3crypto.Envelope{ + CipherKey: "Foo", + IV: "Bar", + MatDesc: "{}", + WrapAlg: s3crypto.KMSWrap, + CEKAlg: s3crypto.AESGCMNoPadding, + UnencryptedMD5: "hello", + UnencryptedContentLen: "0", + }, + map[string]*string{ + "X-Amz-Key-V2": aws.String("Foo"), + "X-Amz-Iv": aws.String("Bar"), + "X-Amz-Matdesc": aws.String("{}"), + "X-Amz-Wrap-Alg": aws.String(s3crypto.KMSWrap), + "X-Amz-Cek-Alg": aws.String(s3crypto.AESGCMNoPadding), + "X-Amz-Unencrypted-Content-Md5": aws.String("hello"), + "X-Amz-Unencrypted-Content-Length": aws.String("0"), + }, + }, } - expected := map[string]*string{ - "X-Amz-Key-V2": aws.String("Foo"), - "X-Amz-Iv": aws.String("Bar"), - "X-Amz-Matdesc": aws.String("{}"), - "X-Amz-Wrap-Alg": aws.String(s3crypto.KMSWrap), - "X-Amz-Cek-Alg": aws.String(s3crypto.AESGCMNoPadding), - "X-Amz-Tag-Len": aws.String("128"), - "X-Amz-Unencrypted-Content-Md5": aws.String("hello"), - "X-Amz-Unencrypted-Content-Length": aws.String("0"), - } + for _, c := range cases { + params := &s3.PutObjectInput{} + req := &request.Request{ + Params: params, + } + strat := s3crypto.HeaderV2SaveStrategy{} + err := strat.Save(c.env, req) + if err != nil { + t.Errorf("expected no error, but received %v", err) + } - if !reflect.DeepEqual(expected, params.Metadata) { - t.Errorf("expected %v, but received %v", expected, params.Metadata) + if !reflect.DeepEqual(c.expected, params.Metadata) { + t.Errorf("expected %v, but received %v", c.expected, params.Metadata) + } } } diff --git a/vendor/github.com/docker/docker/.DEREK.yml b/vendor/github.com/docker/docker/.DEREK.yml new file mode 100644 index 000000000..3fd678917 --- /dev/null +++ b/vendor/github.com/docker/docker/.DEREK.yml @@ -0,0 +1,17 @@ +curators: + - aboch + - alexellis + - andrewhsu + - anonymuse + - chanwit + - ehazlett + - fntlnz + - gianarb + - mgoelzer + - programmerq + - rheinwein + - ripcurld0 + - thajeztah + +features: + - comments diff --git a/vendor/github.com/docker/docker/.mailmap b/vendor/github.com/docker/docker/.mailmap index 928e8177d..1078d5456 100644 --- a/vendor/github.com/docker/docker/.mailmap +++ b/vendor/github.com/docker/docker/.mailmap @@ -6,323 +6,70 @@ # # For explanation on this file format: man git-shortlog -Patrick Stapleton -Shishir Mahajan -Erwin van der Koogh -Ahmed Kamal -Alessandro Boch -Tejesh Mehta -Cristian Staretu -Cristian Staretu -Cristian Staretu -Marcus Linke -Aleksandrs Fadins -Christopher Latham -Hu Keping -Wayne Chang -Chen Chao -Daehyeok Mun - - - - - - -Guillaume J. Charmes - - - - - -Thatcher Peskens -Thatcher Peskens -Thatcher Peskens dhrp -Jérôme Petazzoni -Jérôme Petazzoni -Jérôme Petazzoni -Joffrey F -Joffrey F -Joffrey F -Kir Kolyshkin -Kir Kolyshkin -Lorenzo Fontana +<21551195@zju.edu.cn> -Tim Terhorst -Andy Smith - - - - - - - - - -Walter Stanish - -Roberto Hashioka -Konstantin Pelykh -David Sissitka -Nolan Darilek - -Benoit Chesneau -Jordan Arentsen -Daniel Garcia -Miguel Angel Fernández -Bhiraj Butala -Faiz Khan -Victor Lyuboslavsky -Jean-Baptiste Barth -Matthew Mueller - -Shih-Yuan Lee -Daniel Mizyrycki root -Jean-Baptiste Dalido - - - - - - - - - - - - - - -Sven Dowideit -Sven Dowideit -Sven Dowideit -Sven Dowideit <¨SvenDowideit@home.org.au¨> -Sven Dowideit -Sven Dowideit -Sven Dowideit - -Akihiro Matsushima - -Alexander Morozov -Alexander Morozov - -O.S. Tezer - -Roberto G. Hashioka - - - - - -Sridhar Ratnakumar -Sridhar Ratnakumar -Liang-Chi Hsieh Aaron L. Xu +Abhinandan Prativadi +Adrien Gallouët +Ahmed Kamal +Ahmet Alp Balkan +AJ Bowen +AJ Bowen +Akihiro Matsushima +Akihiro Suda Aleksa Sarai Aleksa Sarai Aleksa Sarai -Will Weaver -Timothy Hobbs -Nathan LeClaire -Nathan LeClaire - - - - -Matthew Heon - - - - -Francisco Carriedo - - - - -Brian Goff - -Erica Windisch -Erica Windisch - -Hollie Teal - - - -Jessica Frazelle -Jessica Frazelle -Jessica Frazelle -Jessica Frazelle -Jessica Frazelle -Jessica Frazelle -Jessica Frazelle -Jessica Frazelle - - - -Sebastiaan van Stijn -Sebastiaan van Stijn -Thomas LEVEIL Thomas LÉVEIL - - -Antonio Murdaca -Antonio Murdaca -Antonio Murdaca -Antonio Murdaca -Antonio Murdaca -Darren Shepherd -Deshi Xiao -Deshi Xiao -Doug Davis -Giampaolo Mancini -Hakan Özler -K. Heller -Jacob Atzen -Jeff Nickoloff -Jérôme Petazzoni -John Harris -John Howard (VM) -John Howard (VM) -John Howard (VM) -John Howard (VM) -John Howard (VM) -Kevin Feyrer -Liao Qingwei -Luke Marsden -Madhan Raj Mookkandy -Madhu Venugopal -Mageee <21521230.zju.edu.cn> -Mansi Nahar -Mansi Nahar -Markus Kortlang -Mary Anthony -Mary Anthony moxiegirl -Mary Anthony -Matt Schurenko -Matt Williams -Matt Williams -Michael Spetsiotis -Nik Nyby -Ouyang Liduo -Paul Liljenberg -Pawel Konczalski -Philip Alexander Etling -Peter Jaffe -AJ Bowen soulshake -AJ Bowen soulshake -Tibor Vass -Tibor Vass -Vincent Bernat -Yestin Sun -bin liu -John Howard (VM) jhowardmsft -Ankush Agarwal -Tangi COLIN tangicolin +Aleksandrs Fadins +Alessandro Boch +Alex Chen +Alex Ellis +Alexander Larsson +Alexander Morozov +Alexander Morozov +Alexandre Beslic +Alicia Lauerman Allen Sun Allen Sun -Adrien Gallouët - +Andrew Weiss +Andrew Weiss +André Martins +Andy Rothfusz +Andy Smith +Ankush Agarwal +Antonio Murdaca +Antonio Murdaca +Antonio Murdaca +Antonio Murdaca +Antonio Murdaca Anuj Bahuguna +Anuj Bahuguna Anusha Ragunathan -Avi Miller -Brent Salisbury -Chander G -Chun Chen -Ying Li -Daehyeok Mun - -Daniel, Dao Quang Minh -Daniel Nephin -Dave Tucker -Doug Tangren -Euan Kemp -Frederick F. Kautz IV -Fengtu Wang -Ben Golub -Harold Cooper -hsinko <21551195@zju.edu.cn> -Josh Hawn -Justin Cormack - - -Kamil Domański -Lei Jitang - -Linus Heckemann - -Lynda O'Leary - -Marianna Tessel -Michael Huettermann -Moysés Borges - -Nigel Poulton -Qiang Huang - -Boaz Shuster -Shuwei Hao - -Soshi Katsuta - -Stefan Berger - -Stefan J. Wernli -Stephen Day - -Toli Kuznets -Tristan Carel - - - -Vincent Demeester -Vishnu Kannan -xlgao-zju xlgao -Yu Changchun y00277921 -Yu Changchun - - - - -Hao Shu Wei - - - - - - - -Shengbo Song mYmNeo -Shengbo Song - -Sylvain Bellemare - - - Arnaud Porterie - -David M. Karr - - - -Kenfe-Mickaël Laventure - - - - - -Runshen Zhu -Tom Barlow -Tom Sweeney -Xianlu Bird -Dan Feldman -Harry Zhang -Harry Zhang -Harry Zhang -Harry Zhang -Alex Chen alexchen -Alex Ellis -Alicia Lauerman +Arnaud Porterie +Arthur Gautier +Avi Miller Ben Bonnefoy +Ben Golub +Ben Toews +Benoit Chesneau +Bhiraj Butala Bhumika Bayani +Bilal Amarni +Bin Liu +Bin Liu Bingshen Wang +Boaz Shuster +Brandon Philips +Brandon Philips +Brent Salisbury +Brian Goff +Brian Goff +Brian Goff +Chander Govindarajan +Chao Wang +Charles Hooper +Chen Chao Chen Chuanliang Chen Mingjie Chen Qiu @@ -330,93 +77,365 @@ Chen Qiu <21321229@zju.edu.cn> Chris Dias Chris McKinnel Christopher Biscardi +Christopher Latham +Chun Chen +Corbin Coleman +Cristian Staretu +Cristian Staretu +Cristian Staretu CUI Wei cuiwei13 +Daehyeok Mun +Daehyeok Mun +Daehyeok Mun +Dan Feldman +Daniel Dao +Daniel Dao +Daniel Garcia +Daniel Gasienica Daniel Grunwell Daniel J Walsh +Daniel Mizyrycki +Daniel Mizyrycki +Daniel Mizyrycki +Daniel Nephin +Daniel Norberg +Danny Yates +Darren Shepherd Dattatraya Kumbhar +Dave Henderson +Dave Tucker +David M. Karr David Sheets +David Sissitka +Deshi Xiao +Deshi Xiao Diego Siqueira -Elan Ruusamäe +Diogo Monica +Dominik Honnef +Doug Davis +Doug Tangren Elan Ruusamäe +Elan Ruusamäe Eric G. Noriega +Eric Hanchrow +Erica Windisch +Erica Windisch +Erik Hollensbe +Erwin van der Koogh +Euan Kemp Eugen Krizo -Evgeny Shmarnev Evelyn Xu +Evgeny Shmarnev +Faiz Khan Felix Ruess +Feng Yan +Fengtu Wang +Francisco Carriedo +Frank Rosquin +Frederick F. Kautz IV Gabriel Nicolas Avellaneda Gang Qiao <1373319223@qq.com> George Kontridze +Gerwim Feiken +Giampaolo Mancini Gopikannan Venugopalsamy Gou Rao Greg Stephens +Guillaume J. Charmes +Guillaume J. Charmes +Guillaume J. Charmes +Guillaume J. Charmes +Guillaume J. Charmes +Gurjeet Singh Gustav Sinder +Hakan Özler +Hao Shu Wei +Hao Shu Wei +Harald Albers +Harold Cooper +Harry Zhang +Harry Zhang +Harry Zhang +Harry Zhang Harshal Patil Helen Xie -Hyzhou Zhy <1187766782@qq.com> +Hollie Teal +Hollie Teal +Hollie Teal +Hu Keping +Huu Nguyen Hyzhou Zhy +Hyzhou Zhy <1187766782@qq.com> +Jack Laxson +Jacob Atzen Jacob Tomlinson +Jean-Baptiste Barth +Jean-Baptiste Dalido +Jean-Tiare Le Bigot +Jeff Anderson +Jeff Nickoloff +Jeroen Franse +Jessica Frazelle +Jessica Frazelle +Jessica Frazelle +Jessica Frazelle +Jessica Frazelle +Jessica Frazelle +Jessica Frazelle +Jessica Frazelle +Jim Galasyn Jiuyue Ma +Joffrey F +Joffrey F +Joffrey F +Johan Euphrosine +John Harris +John Howard (VM) +John Howard (VM) +John Howard (VM) +John Howard (VM) +John Howard (VM) John Stephens +Jordan Arentsen +Jordan Jennings +Jorit Kleine-Möllhoff Jose Diaz-Gonzalez Josh Eveleth +Josh Hawn +Josh Horwitz Josh Soref Josh Wilson -Jim Galasyn +Joyce Jang +Julien Bordellier +Julien Bordellier +Justin Cormack +Justin Cormack +Justin Cormack +Justin Simonelis +Jérôme Petazzoni +Jérôme Petazzoni +Jérôme Petazzoni +K. Heller +Kai Qiang Wu (Kennan) +Kai Qiang Wu (Kennan) +Kamil Domański +Kamjar Gerami +Ken Cochrane +Ken Herner +Kenfe-Mickaël Laventure +Kevin Feyrer Kevin Kern +Kir Kolyshkin +Kir Kolyshkin +Konrad Kleine Konstantin Gribov +Konstantin Pelykh Kunal Kushwaha Lajos Papp +Lei Jitang +Lei Jitang Liang Mingqiang +Liang-Chi Hsieh +Liao Qingwei +Linus Heckemann +Linus Heckemann +Lokesh Mandvekar +Lorenzo Fontana +Louis Opter +Louis Opter +Luke Marsden Lyn -Markan Patel -Matthew Mosesohn -Michael Käufl -Michal Minář -Michael Hudson-Doyle -Mike Casas -Milind Chawre +Lynda O'Leary +Lynda O'Leary Ma Müller +Madhan Raj Mookkandy +Madhu Venugopal +Mageee <21521230.zju.edu.cn> +Mansi Nahar +Mansi Nahar +Marc Abramowitz +Marcelo Horacio Fortino +Marcus Linke +Marianna Tessel +Markan Patel +Markus Kortlang +Martin Redmond +Martin Redmond +Mary Anthony +Mary Anthony +Mary Anthony moxiegirl +Matt Bentley +Matt Schurenko +Matt Williams +Matt Williams +Matthew Heon +Matthew Mosesohn +Matthew Mueller +Matthias Kühnle +Mauricio Garavaglia +Michael Crosby +Michael Crosby +Michael Crosby +Michael Hudson-Doyle +Michael Huettermann +Michael Käufl +Michael Spetsiotis +Michal Minář +Miguel Angel Fernández +Mihai Borobocea +Mike Casas +Mike Goelzer +Milind Chawre +Misty Stanley-Jones +Mohit Soni Moorthy RS +Moysés Borges +Moysés Borges Nace Oroz +Nathan LeClaire +Nathan LeClaire Neil Horman +Nick Russo +Nigel Poulton +Nik Nyby +Nolan Darilek +O.S. Tezer +O.S. Tezer +Oh Jinkyun +Ouyang Liduo +Patrick Stapleton +Paul Liljenberg Pavel Tikhomirov +Pawel Konczalski Peter Choi Peter Dave Hello +Peter Jaffe +Peter Waller +Phil Estes +Philip Alexander Etling Philipp Gillé +Qiang Huang +Qiang Huang +Renaud Gaubert Robert Terhaar +Roberto G. Hashioka Roberto Muñoz Fernández Roman Dudin -Sandeep Bansal +Runshen Zhu Sandeep Bansal +Sandeep Bansal +Sargun Dhillon Sean Lee +Sebastiaan van Stijn +Sebastiaan van Stijn Shaun Kaasten +Shawn Landden +Shengbo Song +Shengbo Song +Shih-Yuan Lee +Shishir Mahajan Shukui Yang +Shuwei Hao +Shuwei Hao +Sjoerd Langkemper +Solomon Hykes +Solomon Hykes +Solomon Hykes +Soshi Katsuta +Soshi Katsuta +Sridhar Ratnakumar +Sridhar Ratnakumar +Srini Brahmaroutu Srinivasan Srivatsan +Stefan Berger +Stefan Berger +Stefan J. Wernli Stefan S. +Stephen Day +Stephen Day Steve Desmond Sun Gengze <690388648@qq.com> +Sven Dowideit +Sven Dowideit +Sven Dowideit +Sven Dowideit +Sven Dowideit +Sven Dowideit +Sven Dowideit <¨SvenDowideit@home.org.au¨> +Sylvain Bellemare +Sylvain Bellemare +Tangi Colin +Tejesh Mehta +Thatcher Peskens +Thatcher Peskens +Thatcher Peskens +Thomas Gazagnaire +Thomas Léveil +Thomas Léveil +Tibor Vass +Tibor Vass Tim Bart +Tim Bosse +Tim Ruffles +Tim Terhorst Tim Zju <21651152@zju.edu.cn> +Timothy Hobbs +Toli Kuznets +Tom Barlow +Tom Sweeney Tõnis Tiigi Trishna Guha -Wayne Song +Tristan Carel +Tristan Carel +Umesh Yadav +Victor Lyuboslavsky +Victor Vieux +Victor Vieux +Victor Vieux +Victor Vieux +Victor Vieux +Victor Vieux +Viktor Vojnovski +Vincent Batts +Vincent Bernat +Vincent Bernat +Vincent Demeester +Vincent Demeester +Vincent Demeester +Vishnu Kannan +Vladimir Rutsky +Walter Stanish Wang Guoliang Wang Jie Wang Ping Wang Yuexiao +Wayne Chang +Wayne Song +Wei Wu cizixs Wenjun Tang Wewang Xiaorenfine -Wei Wu cizixs +Will Weaver +Xianglin Gao +Xianlu Bird Xiaoyu Zhang Xuecong Liao Yamasaki Masahide +Yao Zaiyong Yassine Tijani +Yazhong Liu +Yestin Sun +Yi EungJun +Ying Li Ying Li Yong Tang +Yosef Fertel +Yu Changchun Yu Chengxia Yu Peng Yu Peng -Yao Zaiyong +Zachary Jaffee +Zachary Jaffee ZhangHang Zhenkun Bi Zhu Kunjia +Zou Yu diff --git a/vendor/github.com/docker/docker/AUTHORS b/vendor/github.com/docker/docker/AUTHORS index f465a8790..afafb2d72 100644 --- a/vendor/github.com/docker/docker/AUTHORS +++ b/vendor/github.com/docker/docker/AUTHORS @@ -26,6 +26,7 @@ Adam Walz Addam Hardy Aditi Rajagopal Aditya +Adnan Khan Adolfo Ochagavía Adria Casas Adrian Moisey @@ -43,6 +44,7 @@ ajneu Akash Gupta Akihiro Matsushima Akihiro Suda +Akim Demaille Akira Koyasu Akshay Karle Al Tobey @@ -105,6 +107,7 @@ Andre Dublin <81dublin@gmail.com> Andre Granovsky Andrea Luzzardi Andrea Turli +Andreas Elvers Andreas Köhler Andreas Savvides Andreas Tiefenthaler @@ -123,8 +126,9 @@ Andrew Macpherson Andrew Martin Andrew McDonnell Andrew Munsell +Andrew Pennebaker Andrew Po -Andrew Weiss +Andrew Weiss Andrew Williams Andrews Medina Andrey Petrov @@ -144,6 +148,7 @@ Anil Madhavapeddy Ankush Agarwal Anonmily Anran Qiao +Anshul Pundir Anthon van der Neut Anthony Baire Anthony Bishopric @@ -167,6 +172,7 @@ Arthur Barr Arthur Gautier Artur Meyster Arun Gupta +Asad Saeeduddin Asbjørn Enge averagehuman Avi Das @@ -199,7 +205,7 @@ Bhiraj Butala Bhumika Bayani Bilal Amarni Bill W -bin liu +Bin Liu Bingshen Wang Blake Geno Boaz Shuster @@ -213,12 +219,13 @@ boynux Bradley Cicenas Bradley Wright Brandon Liu -Brandon Philips +Brandon Philips Brandon Rhodes Brendan Dixon Brent Salisbury Brett Higgins Brett Kochendorfer +Brett Randall Brian (bex) Exelbierd Brian Bland Brian DeHamer @@ -266,7 +273,8 @@ Cedric Davies Cezar Sa Espinola Chad Swenson Chance Zibolski -Chander G +Chander Govindarajan +Chao Wang Charles Chan Charles Hooper Charles Law @@ -284,6 +292,8 @@ Chen Hanxiao Chen Min Chen Mingjie Chen Qiu +Cheng-mean Liu +Chetan Birajdar Chewey Chia-liang Kao chli @@ -306,6 +316,7 @@ Chris Swan Chris Wahl Chris Weyl Christian Berendt +Christian Brauner Christian Böhme Christian Persson Christian Rotzoll @@ -333,6 +344,7 @@ Colin Walters Collin Guarino Colm Hally companycy +Corbin Coleman Corey Farrell Cory Forsyth cressie176 @@ -363,6 +375,7 @@ Dan McPherson Dan Stine Dan Williams Daniel Antlinger +Daniel Dao Daniel Exner Daniel Farrell Daniel Garcia @@ -381,9 +394,9 @@ Daniel Von Fange Daniel X Moore Daniel YC Lin Daniel Zhang -Daniel, Dao Quang Minh Danny Berger Danny Yates +Danyal Khaliq Darren Coxall Darren Shepherd Darren Stahl @@ -431,6 +444,7 @@ Denis Defreyne Denis Gladkikh Denis Ollier Dennis Chen +Dennis Chen Dennis Docter Derek Derek @@ -516,6 +530,7 @@ Eric Paris Eric Rafaloff Eric Rosenberg Eric Sage +Eric Soderstrom Eric Yang Eric-Olivier Lamey Erica Windisch @@ -567,6 +582,7 @@ Felix Hupfeld Felix Rabe Felix Ruess Felix Schindler +Feng Yan Fengtu Wang Ferenc Szabo Fernando @@ -586,7 +602,6 @@ Florian Weingarten Florin Asavoaie Florin Patan fonglh -fortinux Foysal Iqbal Francesc Campoy Francis Chuang @@ -601,8 +616,7 @@ Frederick F. Kautz IV Frederik Loeffert Frederik Nordahl Jul Sabroe Freek Kalter -frosforever -fy2462 +Frieder Bluemle Félix Baylac-Jacqué Félix Cantournet Gabe Rosenhouse @@ -629,7 +643,8 @@ Georgi Hristozov Gereon Frey German DZ Gert van Valkenhoef -Gerwim +Gerwim Feiken +Ghislain Bourgeois Giampaolo Mancini Gianluca Borello Gildas Cuisinier @@ -673,6 +688,7 @@ Harry Zhang Harshal Patil Harshal Patil He Simei +He Xiaoxi He Xin heartlock <21521209@zju.edu.cn> Hector Castro @@ -708,6 +724,7 @@ Iavael Icaro Seara Ignacio Capurro Igor Dolzhikov +Igor Karpovich Iliana Weller Ilkka Laukkanen Ilya Dmitrichenko @@ -726,9 +743,11 @@ Ivan Markin J Bruni J. Nunn Jack Danger Canty +Jack Laxson Jacob Atzen Jacob Edelman Jacob Tomlinson +Jacob Vallejo Jacob Wen Jake Champlin Jake Moshenko @@ -785,6 +804,7 @@ Jean-Christophe Berthon Jean-Paul Calderone Jean-Pierre Huynh Jean-Tiare Le Bigot +Jeeva S. Chelladhurai Jeff Anderson Jeff Johnston Jeff Lindsay @@ -803,6 +823,7 @@ Jeremy Price Jeremy Qian Jeremy Unruh Jeremy Yallop +Jeroen Franse Jeroen Jacobs Jesse Dearing Jesse Dubay @@ -814,6 +835,7 @@ Ji.Zhilong Jian Zhang jianbosun Jie Luo +Jihyun Hwang Jilles Oldenbeuving Jim Alateras Jim Galasyn @@ -880,10 +902,11 @@ Jonathan Stoppani Jonh Wendell Joni Sar Joost Cassee -Jordan Jordan Arentsen +Jordan Jennings Jordan Sissel Jorge Marin +Jorit Kleine-Möllhoff Jose Diaz-Gonzalez Joseph Anthony Pasquale Holsten Joseph Hager @@ -900,9 +923,8 @@ Josh Soref Josh Wilson Josiah Kiehl José Tomás Albornoz +Joyce Jang JP -jrabbit -jroenf Julian Taylor Julien Barbier Julien Bisconti @@ -927,9 +949,9 @@ Jérôme Petazzoni Jörg Thalheim K. Heller Kai Blin -Kai Qiang Wu(Kennan) +Kai Qiang Wu (Kennan) Kamil Domański -kamjar gerami +Kamjar Gerami Kanstantsin Shautsou Kara Alexandra Karan Lyons @@ -938,6 +960,7 @@ kargakis Karl Grzeszczak Karol Duleba Karthik Nayak +Kate Heddleston Katie McLaughlin Kato Kazuyoshi Katrina Owen @@ -1025,6 +1048,7 @@ Levi Gross Lewis Daly Lewis Marshall Lewis Peckover +Li Yi Liam Macgillavry Liana Lo Liang Mingqiang @@ -1056,6 +1080,7 @@ Luca Orlandi Luca-Bogdan Grigorescu Lucas Chan Lucas Chi +Lucas Molas Luciano Mores Luis Martínez de Bartolomé Izquierdo Luiz Svoboda @@ -1087,11 +1112,13 @@ Marc Abramowitz Marc Kuo Marc Tamsky Marcel Edmund Franke +Marcelo Horacio Fortino Marcelo Salazar Marco Hennings Marcus Cobden Marcus Farkas Marcus Linke +Marcus Martins Marcus Ramberg Marek Goldmann Marian Marinov @@ -1204,6 +1231,7 @@ Mike Chelen Mike Danese Mike Dillon Mike Dougherty +Mike Estes Mike Gaffney Mike Goelzer Mike Leone @@ -1219,6 +1247,7 @@ mingqing Mingzhen Feng Misty Stanley-Jones Mitch Capper +Mizuki Urushida mlarcher Mohammad Banikazemi Mohammed Aaqib Ansari @@ -1262,20 +1291,21 @@ Neyazul Haque Nghia Tran Niall O'Higgins Nicholas E. Rabenau -nick Nick DeCoursin Nick Irvine Nick Parker Nick Payne +Nick Russo Nick Stenning Nick Stinemates NickrenREN Nicola Kabar Nicolas Borboën -Nicolas De loof +Nicolas De Loof Nicolas Dudebout Nicolas Goy Nicolas Kaiser +Nicolas Sterchele Nicolás Hock Isaza Nigel Poulton Nik Nyby @@ -1391,7 +1421,6 @@ Prayag Verma Przemek Hejman Pure White pysqz -qhuang Qiang Huang Qinglan Peng qudongfang @@ -1422,6 +1451,7 @@ Remy Suen Renato Riccieri Santos Zannon Renaud Gaubert Rhys Hiltner +Ri Xu Ricardo N Feliciano Rich Moyse Rich Seymour @@ -1493,6 +1523,7 @@ Ryan Liu Ryan McLaughlin Ryan O'Donnell Ryan Seto +Ryan Simmen Ryan Thomas Ryan Trauntvein Ryan Wallner @@ -1526,6 +1557,7 @@ Sankar சங்கர் Sanket Saurav Santhosh Manohar sapphiredev +Sargun Dhillon Sascha Andres Satnam Singh Satoshi Amemiya @@ -1569,6 +1601,7 @@ Shengbo Song Shev Yan Shih-Yuan Lee Shijiang Wei +Shijun Qin Shishir Mahajan Shoubhik Bose Shourya Sarcar @@ -1641,7 +1674,7 @@ Tabakhase Tadej Janež TAGOMORI Satoshi tang0th -Tangi COLIN +Tangi Colin Tatsuki Sugiura Tatsushi Inagaki Taylor Jones @@ -1662,7 +1695,7 @@ Thomas Gazagnaire Thomas Grainger Thomas Hansen Thomas Leonard -Thomas LEVEIL +Thomas Léveil Thomas Orozco Thomas Riccardi Thomas Schroeter @@ -1744,6 +1777,7 @@ Tyler Brock Tzu-Jung Lee uhayate Ulysse Carion +Umesh Yadav Utz Bacher vagrant Vaidas Jablonskis @@ -1763,7 +1797,6 @@ Viktor Stanchev Viktor Vojnovski VinayRaghavanKS Vincent Batts -Vincent Bernat Vincent Bernat Vincent Demeester Vincent Giersch @@ -1837,7 +1870,6 @@ xiekeyang Xinbo Weng Xinzi Zhou Xiuming Chen -xlgao-zju Xuecong Liao xuzhaokui Yahya @@ -1851,6 +1883,7 @@ Yanqiang Miao Yao Zaiyong Yassine Tijani Yasunori Mahata +Yazhong Liu Yestin Sun Yi EungJun Yibai Zhang @@ -1859,7 +1892,7 @@ Ying Li Yohei Ueda Yong Tang Yongzhi Pan -yorkie +Yosef Fertel You-Sheng Yang (楊有勝) Youcef YEKHLEF Yu Changchun @@ -1871,10 +1904,10 @@ Yuanhong Peng Yuhao Fang Yunxiang Huang Yurii Rashkovskii -yuzou +Yves Junqueira Zac Dover Zach Borboa -Zachary Jaffee +Zachary Jaffee Zain Memon Zaiste! Zane DeGraffenried @@ -1898,6 +1931,7 @@ Ziming Dong ZJUshuaizhou <21551191@zju.edu.cn> zmarouf Zoltan Tombol +Zou Yu zqh Zuhayr Elahi Zunayed Ali @@ -1907,3 +1941,4 @@ Zunayed Ali 尹吉峰 徐俊杰 搏通 +黄艳红00139573 diff --git a/vendor/github.com/docker/docker/CONTRIBUTING.md b/vendor/github.com/docker/docker/CONTRIBUTING.md index b7961e14e..519e238cc 100644 --- a/vendor/github.com/docker/docker/CONTRIBUTING.md +++ b/vendor/github.com/docker/docker/CONTRIBUTING.md @@ -303,14 +303,43 @@ 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. +[/project/GOVERNANCE.md](/project/GOVERNANCE.md) +file in this 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! +### Manage issues and pull requests using the Derek bot + +If you want to help label, assign, close or reopen issues or pull requests +without commit rights, ask a maintainer to add your Github handle to the +`.DEREK.yml` file. [Derek](https://github.com/alexellis/derek) is a bot that extends +Github's user permissions to help non-committers to manage issues and pull requests simply by commenting. + +For example: + +* Labels + +``` +Derek add label: kind/question +Derek remove label: status/claimed +``` + +* Assign work + +``` +Derek assign: username +Derek unassign: me +``` + +* Manage issues and PRs + +``` +Derek close +Derek reopen +``` + ## Moby community guidelines We want to keep the Moby community awesome, growing and collaborative. We need @@ -341,6 +370,11 @@ guidelines for the community as a whole: used to ping maintainers to review a pull request, a proposal or an issue. +The open source governance for this repository is handled via the [Moby Technical Steering Committee (TSC)](https://github.com/moby/tsc) +charter. For any concerns with the community process regarding technical contributions, +please contact the TSC. More information on project governance is available in +our [project/GOVERNANCE.md](/project/GOVERNANCE.md) document. + ### Guideline violations — 3 strikes method The point of this section is not to find opportunities to punish people, but we diff --git a/vendor/github.com/docker/docker/Dockerfile b/vendor/github.com/docker/docker/Dockerfile index e027d4855..bc61bafb9 100644 --- a/vendor/github.com/docker/docker/Dockerfile +++ b/vendor/github.com/docker/docker/Dockerfile @@ -52,6 +52,7 @@ RUN apt-get update && apt-get install -y \ libapparmor-dev \ libcap-dev \ libdevmapper-dev \ + libnet-dev \ libnl-3-dev \ libprotobuf-c0-dev \ libprotobuf-dev \ @@ -61,6 +62,7 @@ RUN apt-get update && apt-get install -y \ libudev-dev \ mercurial \ net-tools \ + pigz \ pkg-config \ protobuf-compiler \ protobuf-c-compiler \ @@ -86,7 +88,7 @@ RUN apt-get update && apt-get install -y \ # will need updating, to avoid errors. Ping #docker-maintainers on IRC # with a heads-up. # IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \ | tar -xzC /usr/local @@ -94,11 +96,9 @@ ENV PATH /go/bin:/usr/local/go/bin:$PATH ENV GOPATH /go # Install CRIU for checkpoint/restore support -ENV CRIU_VERSION 2.12.1 -# Install dependancy packages specific to criu -RUN apt-get install libnet-dev -y && \ - mkdir -p /usr/src/criu \ - && curl -sSL https://github.com/xemul/criu/archive/v${CRIU_VERSION}.tar.gz | tar -v -C /usr/src/criu/ -xz --strip-components=1 \ +ENV CRIU_VERSION 3.6 +RUN mkdir -p /usr/src/criu \ + && curl -sSL https://github.com/checkpoint-restore/criu/archive/v${CRIU_VERSION}.tar.gz | tar -C /usr/src/criu/ -xz --strip-components=1 \ && cd /usr/src/criu \ && make \ && make install-criu @@ -168,11 +168,12 @@ RUN echo "source $PWD/hack/make/.integration-test-helpers" >> /etc/bash.bashrc # Get useful and necessary Hub images so we can "docker load" locally instead of pulling COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/ +# TODO: when issue #35963 fixed, we can upgrade the busybox to multi-arch RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \ - buildpack-deps:jessie@sha256:85b379ec16065e4fe4127eb1c5fb1bcc03c559bd36dbb2e22ff496de55925fa6 \ + buildpack-deps:jessie@sha256:dd86dced7c9cd2a724e779730f0a53f93b7ef42228d4344b25ce9a42a1486251 \ busybox:latest@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f \ - debian:jessie@sha256:72f784399fd2719b4cb4e16ef8e369a39dc67f53d978cd3e2e7bf4e502c7b793 \ - hello-world:latest@sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7 + debian:jessie@sha256:287a20c5f73087ab406e6b364833e3fb7b3ae63ca0eb3486555dc27ed32c6e60 \ + hello-world:latest@sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c # See also ensureFrozenImagesLinux() in "integration-cli/fixtures_linux_daemon_test.go" (which needs to be updated when adding images to this list) # Install tomlv, vndr, runc, containerd, tini, docker-proxy dockercli @@ -190,7 +191,7 @@ RUN ln -s /usr/local/completion/bash/docker /etc/bash_completion.d/docker ENTRYPOINT ["hack/dind"] # Options for hack/validate/gometalinter -ENV GOMETALINTER_OPTS="--deadline 2m" +ENV GOMETALINTER_OPTS="--deadline=2m" # Upload docker source COPY . /go/src/github.com/docker/docker diff --git a/vendor/github.com/docker/docker/Dockerfile.aarch64 b/vendor/github.com/docker/docker/Dockerfile.aarch64 index 876d80935..e7f422d3c 100644 --- a/vendor/github.com/docker/docker/Dockerfile.aarch64 +++ b/vendor/github.com/docker/docker/Dockerfile.aarch64 @@ -15,7 +15,7 @@ # the case. Therefore, you don't have to disable it anymore. # -FROM arm64v8/debian:stretch +FROM debian:stretch # allow replacing httpredir or deb mirror ARG APT_MIRROR=deb.debian.org @@ -52,6 +52,7 @@ RUN apt-get update && apt-get install -y \ libudev-dev \ mercurial \ net-tools \ + pigz \ pkg-config \ protobuf-compiler \ protobuf-c-compiler \ @@ -73,7 +74,7 @@ RUN apt-get update && apt-get install -y \ # Install Go # IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-arm64.tar.gz" \ | tar -xzC /usr/local @@ -142,10 +143,10 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker # Get useful and necessary Hub images so we can "docker load" locally instead of pulling COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/ RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \ - aarch64/buildpack-deps:jessie@sha256:107f4a96837ed89c493fc205cd28508ed0b6b680b4bf3e514e9f0fa0f6667b77 \ - aarch64/busybox:latest@sha256:5a06b8b2fdf22dd1f4085c6c3efd23ee99af01b2d668d286bc4be6d8baa10efb \ - aarch64/debian:jessie@sha256:e6f90b568631705bd5cb27490977378ba762792b38d47c91c4da7a539f63079a \ - aarch64/hello-world:latest@sha256:bd1722550b97668b23ede297abf824d4855f4d9f600dab7b4db1a963dae7ec9e + buildpack-deps:jessie@sha256:dd86dced7c9cd2a724e779730f0a53f93b7ef42228d4344b25ce9a42a1486251 \ + busybox:latest@sha256:bbc3a03235220b170ba48a157dd097dd1379299370e1ed99ce976df0355d24f0 \ + debian:jessie@sha256:287a20c5f73087ab406e6b364833e3fb7b3ae63ca0eb3486555dc27ed32c6e60 \ + hello-world:latest@sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c # See also ensureFrozenImagesLinux() in "integration-cli/fixtures_linux_daemon_test.go" (which needs to be updated when adding images to this list) # Install tomlv, vndr, runc, containerd, tini, docker-proxy @@ -159,7 +160,7 @@ ENV PATH=/usr/local/cli:$PATH ENTRYPOINT ["hack/dind"] # Options for hack/validate/gometalinter -ENV GOMETALINTER_OPTS="--deadline 4m -j2" +ENV GOMETALINTER_OPTS="--deadline=4m -j2" # Upload docker source COPY . /go/src/github.com/docker/docker diff --git a/vendor/github.com/docker/docker/Dockerfile.armhf b/vendor/github.com/docker/docker/Dockerfile.armhf index 33304b55e..676464963 100644 --- a/vendor/github.com/docker/docker/Dockerfile.armhf +++ b/vendor/github.com/docker/docker/Dockerfile.armhf @@ -45,6 +45,7 @@ RUN apt-get update && apt-get install -y \ libtool \ libudev-dev \ mercurial \ + pigz \ pkg-config \ python-backports.ssl-match-hostname \ python-dev \ @@ -63,7 +64,7 @@ RUN apt-get update && apt-get install -y \ # Install Go # IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" \ | tar -xzC /usr/local ENV PATH /go/bin:/usr/local/go/bin:$PATH @@ -131,10 +132,10 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker # Get useful and necessary Hub images so we can "docker load" locally instead of pulling COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/ RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \ - armhf/buildpack-deps:jessie@sha256:eb2dad77ef53e88d94c3c83862d315c806ea1ca49b6e74f4db362381365ce489 \ - armhf/busybox:latest@sha256:016a1e149d2acc2a3789a160dfa60ce870794eea27ad5e96f7a101970e5e1689 \ - armhf/debian:jessie@sha256:ac59fa18b28d0ef751eabb5ba4c4b5a9063f99398bae2f70495aa8ed6139b577 \ - armhf/hello-world:latest@sha256:9701edc932223a66e49dd6c894a11db8c2cf4eccd1414f1ec105a623bf16b426 + buildpack-deps:jessie@sha256:dd86dced7c9cd2a724e779730f0a53f93b7ef42228d4344b25ce9a42a1486251 \ + busybox:latest@sha256:bbc3a03235220b170ba48a157dd097dd1379299370e1ed99ce976df0355d24f0 \ + debian:jessie@sha256:287a20c5f73087ab406e6b364833e3fb7b3ae63ca0eb3486555dc27ed32c6e60 \ + hello-world:latest@sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c # See also ensureFrozenImagesLinux() in "integration-cli/fixtures_linux_daemon_test.go" (which needs to be updated when adding images to this list) # Install tomlv, vndr, runc, containerd, tini, docker-proxy @@ -147,7 +148,7 @@ ENV PATH=/usr/local/cli:$PATH ENTRYPOINT ["hack/dind"] # Options for hack/validate/gometalinter -ENV GOMETALINTER_OPTS="--deadline 10m -j2" +ENV GOMETALINTER_OPTS="--deadline=10m -j2" # Upload docker source COPY . /go/src/github.com/docker/docker diff --git a/vendor/github.com/docker/docker/Dockerfile.e2e b/vendor/github.com/docker/docker/Dockerfile.e2e index c57d7d321..6c96c033a 100644 --- a/vendor/github.com/docker/docker/Dockerfile.e2e +++ b/vendor/github.com/docker/docker/Dockerfile.e2e @@ -1,5 +1,5 @@ ## Step 1: Build tests -FROM golang:1.8.5-alpine3.6 as builder +FROM golang:1.9.2-alpine3.6 as builder RUN apk add --update \ bash \ @@ -16,10 +16,10 @@ WORKDIR /go/src/github.com/docker/docker/ # Generate frozen images COPY contrib/download-frozen-image-v2.sh contrib/download-frozen-image-v2.sh RUN contrib/download-frozen-image-v2.sh /output/docker-frozen-images \ - buildpack-deps:jessie@sha256:85b379ec16065e4fe4127eb1c5fb1bcc03c559bd36dbb2e22ff496de55925fa6 \ - busybox:latest@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f \ - debian:jessie@sha256:72f784399fd2719b4cb4e16ef8e369a39dc67f53d978cd3e2e7bf4e502c7b793 \ - hello-world:latest@sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7 + buildpack-deps:jessie@sha256:dd86dced7c9cd2a724e779730f0a53f93b7ef42228d4344b25ce9a42a1486251 \ + busybox:latest@sha256:bbc3a03235220b170ba48a157dd097dd1379299370e1ed99ce976df0355d24f0 \ + debian:jessie@sha256:287a20c5f73087ab406e6b364833e3fb7b3ae63ca0eb3486555dc27ed32c6e60 \ + hello-world:latest@sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c # Download Docker CLI binary COPY hack/dockerfile hack/dockerfile @@ -47,6 +47,7 @@ RUN apk add --update \ g++ \ git \ iptables \ + pigz \ tar \ xz \ && rm -rf /var/cache/apk/* diff --git a/vendor/github.com/docker/docker/Dockerfile.ppc64le b/vendor/github.com/docker/docker/Dockerfile.ppc64le index 4abd8891f..15ee5f6d7 100644 --- a/vendor/github.com/docker/docker/Dockerfile.ppc64le +++ b/vendor/github.com/docker/docker/Dockerfile.ppc64le @@ -46,6 +46,7 @@ RUN apt-get update && apt-get install -y \ libtool \ libudev-dev \ mercurial \ + pigz \ pkg-config \ python-backports.ssl-match-hostname \ python-dev \ @@ -64,7 +65,7 @@ RUN apt-get update && apt-get install -y \ # Install Go # NOTE: official ppc64le go binaries weren't available until go 1.6.4 and 1.7.4 # IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" \ | tar -xzC /usr/local @@ -129,10 +130,10 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker # Get useful and necessary Hub images so we can "docker load" locally instead of pulling COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/ RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \ - ppc64le/buildpack-deps:jessie@sha256:1a2f2d2cc8738f14b336aeffc3503b5c9dedf9e1f26c7313cb4999534ad4716f \ - ppc64le/busybox:latest@sha256:54f34c83adfab20cf0e630d879e210f07b0062cd6caaf16346a61396d50e7584 \ - ppc64le/debian:jessie@sha256:ea8c5b105e3790f075145b40e4be1e4488c9f33f55e6cc45182047b80a68f892 \ - ppc64le/hello-world:latest@sha256:7d57adf137665f748956c86089320710b66d08584db3500ed98f4bb3da637c2d + buildpack-deps:jessie@sha256:dd86dced7c9cd2a724e779730f0a53f93b7ef42228d4344b25ce9a42a1486251 \ + busybox:latest@sha256:bbc3a03235220b170ba48a157dd097dd1379299370e1ed99ce976df0355d24f0 \ + debian:jessie@sha256:287a20c5f73087ab406e6b364833e3fb7b3ae63ca0eb3486555dc27ed32c6e60 \ + hello-world:latest@sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c # See also ensureFrozenImagesLinux() in "integration-cli/fixtures_linux_daemon_test.go" (which needs to be updated when adding images to this list) # Install tomlv, vndr, runc, containerd, tini, docker-proxy diff --git a/vendor/github.com/docker/docker/Dockerfile.s390x b/vendor/github.com/docker/docker/Dockerfile.s390x index 33dfc4319..57b778442 100644 --- a/vendor/github.com/docker/docker/Dockerfile.s390x +++ b/vendor/github.com/docker/docker/Dockerfile.s390x @@ -42,6 +42,7 @@ RUN apt-get update && apt-get install -y \ libtool \ libudev-dev \ mercurial \ + pigz \ pkg-config \ python-backports.ssl-match-hostname \ python-dev \ @@ -58,7 +59,7 @@ RUN apt-get update && apt-get install -y \ --no-install-recommends # IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" \ | tar -xzC /usr/local @@ -123,10 +124,10 @@ RUN ln -sv $PWD/contrib/completion/bash/docker /etc/bash_completion.d/docker # Get useful and necessary Hub images so we can "docker load" locally instead of pulling COPY contrib/download-frozen-image-v2.sh /go/src/github.com/docker/docker/contrib/ RUN ./contrib/download-frozen-image-v2.sh /docker-frozen-images \ - s390x/buildpack-deps:jessie@sha256:552dec28146e4d2591fc0309aebdbac9e4fb1f335d90c70a14bbf72fb8bb1be5 \ - s390x/busybox:latest@sha256:e32f40c39ca596a4317392bd32809bb188c4ae5864ea827c3219c75c50069964 \ - s390x/debian:jessie@sha256:6994e3ffa5a1dabea09d536f350b3ed2715292cb469417c42a82b70fcbff7d32 \ - s390x/hello-world:latest@sha256:602db500fee63934292260e65c0c528128ad1c1c7c6497f95bbbac7d4d5312f1 + buildpack-deps:jessie@sha256:dd86dced7c9cd2a724e779730f0a53f93b7ef42228d4344b25ce9a42a1486251 \ + busybox:latest@sha256:bbc3a03235220b170ba48a157dd097dd1379299370e1ed99ce976df0355d24f0 \ + debian:jessie@sha256:287a20c5f73087ab406e6b364833e3fb7b3ae63ca0eb3486555dc27ed32c6e60 \ + hello-world:latest@sha256:be0cd392e45be79ffeffa6b05338b98ebb16c87b255f48e297ec7f98e123905c # See also ensureFrozenImagesLinux() in "integration-cli/fixtures_linux_daemon_test.go" (which needs to be updated when adding images to this list) # Install tomlv, vndr, runc, containerd, tini, docker-proxy diff --git a/vendor/github.com/docker/docker/Dockerfile.simple b/vendor/github.com/docker/docker/Dockerfile.simple index c84025e67..578bbb219 100644 --- a/vendor/github.com/docker/docker/Dockerfile.simple +++ b/vendor/github.com/docker/docker/Dockerfile.simple @@ -27,6 +27,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates \ e2fsprogs \ iptables \ + pkg-config \ + pigz \ procps \ xfsprogs \ xz-utils \ @@ -40,7 +42,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # will need updating, to avoid errors. Ping #docker-maintainers on IRC # with a heads-up. # IMPORTANT: When updating this please note that stdlib archive/tar pkg is vendored -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" \ | tar -xzC /usr/local ENV PATH /go/bin:/usr/local/go/bin:$PATH diff --git a/vendor/github.com/docker/docker/Dockerfile.windows b/vendor/github.com/docker/docker/Dockerfile.windows index 2671aea8c..519a96124 100644 --- a/vendor/github.com/docker/docker/Dockerfile.windows +++ b/vendor/github.com/docker/docker/Dockerfile.windows @@ -161,7 +161,7 @@ SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPref # Environment variable notes: # - GO_VERSION must be consistent with 'Dockerfile' used by Linux. # - FROM_DOCKERFILE is used for detection of building within a container. -ENV GO_VERSION=1.8.5 ` +ENV GO_VERSION=1.9.2 ` GIT_VERSION=2.11.1 ` GOPATH=C:\go ` FROM_DOCKERFILE=1 diff --git a/vendor/github.com/docker/docker/MAINTAINERS b/vendor/github.com/docker/docker/MAINTAINERS index d81caba80..4c831d783 100644 --- a/vendor/github.com/docker/docker/MAINTAINERS +++ b/vendor/github.com/docker/docker/MAINTAINERS @@ -1,12 +1,14 @@ # Moby 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! +# This file describes the maintainer groups within the moby/moby project. +# More detail on Moby project governance is available in the +# project/GOVERNANCE.md file found in this repository. # # It is structured to be consumable by both humans and programs. # To extract its contents programmatically, use any TOML-compliant # parser. # +# TODO(estesp): This file should not necessarily depend on docker/opensource # This file is compiled into the MAINTAINERS file in docker/opensource. # [Org] @@ -368,7 +370,7 @@ [people.mlaventure] Name = "Kenfe-Mickaël Laventure" - Email = "mickael.laventure@docker.com" + Email = "mickael.laventure@gmail.com" GitHub = "mlaventure" [people.moxiegirl] @@ -465,4 +467,3 @@ Name = "Yong Tang" Email = "yong.tang.github@outlook.com" GitHub = "yongtang" - diff --git a/vendor/github.com/docker/docker/Makefile b/vendor/github.com/docker/docker/Makefile index 32988150c..6f5145a02 100644 --- a/vendor/github.com/docker/docker/Makefile +++ b/vendor/github.com/docker/docker/Makefile @@ -53,7 +53,8 @@ DOCKER_ENVS := \ -e http_proxy \ -e https_proxy \ -e no_proxy \ - -e VERSION + -e VERSION \ + -e PLATFORM # note: we _cannot_ add "-e DOCKER_BUILDTAGS" here because even if it's unset in the shell, that would shadow the "ENV DOCKER_BUILDTAGS" set in our Dockerfile, which is very important for our official builds # to allow `make BIND_DIR=. shell` or `make BIND_DIR= test` diff --git a/vendor/github.com/docker/docker/api/common.go b/vendor/github.com/docker/docker/api/common.go index af34d0b35..693d0a4eb 100644 --- a/vendor/github.com/docker/docker/api/common.go +++ b/vendor/github.com/docker/docker/api/common.go @@ -3,7 +3,7 @@ package api // Common constants for daemon and client. const ( // DefaultVersion of Current REST API - DefaultVersion string = "1.35" + DefaultVersion string = "1.36" // NoBaseImageSpecifier is the symbol used by the FROM // command to specify that no base image is to be used. diff --git a/vendor/github.com/docker/docker/api/server/backend/build/backend.go b/vendor/github.com/docker/docker/api/server/backend/build/backend.go index f93fba93b..a702d04a4 100644 --- a/vendor/github.com/docker/docker/api/server/backend/build/backend.go +++ b/vendor/github.com/docker/docker/api/server/backend/build/backend.go @@ -17,7 +17,7 @@ import ( // ImageComponent provides an interface for working with images type ImageComponent interface { SquashImage(from string, to string) (string, error) - TagImageWithReference(image.ID, string, reference.Named) error + TagImageWithReference(image.ID, reference.Named) error } // Builder defines interface for running a build diff --git a/vendor/github.com/docker/docker/api/server/backend/build/tag.go b/vendor/github.com/docker/docker/api/server/backend/build/tag.go index 7bd5dcdeb..5c3918a3e 100644 --- a/vendor/github.com/docker/docker/api/server/backend/build/tag.go +++ b/vendor/github.com/docker/docker/api/server/backend/build/tag.go @@ -3,11 +3,9 @@ package build import ( "fmt" "io" - "runtime" "github.com/docker/distribution/reference" "github.com/docker/docker/image" - "github.com/docker/docker/pkg/system" "github.com/pkg/errors" ) @@ -35,12 +33,7 @@ func NewTagger(backend ImageComponent, stdout io.Writer, names []string) (*Tagge // TagImages creates image tags for the imageID func (bt *Tagger) TagImages(imageID image.ID) error { for _, rt := range bt.repoAndTags { - // TODO @jhowardmsft LCOW support. Will need revisiting. - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - if err := bt.imageComponent.TagImageWithReference(imageID, platform, rt); err != nil { + if err := bt.imageComponent.TagImageWithReference(imageID, rt); err != nil { return err } fmt.Fprintf(bt.stdout, "Successfully tagged %s\n", reference.FamiliarString(rt)) diff --git a/vendor/github.com/docker/docker/api/server/httputils/errors.go b/vendor/github.com/docker/docker/api/server/httputils/errors.go index 05a842c3a..f5008223c 100644 --- a/vendor/github.com/docker/docker/api/server/httputils/errors.go +++ b/vendor/github.com/docker/docker/api/server/httputils/errors.go @@ -4,9 +4,9 @@ import ( "fmt" "net/http" - "github.com/docker/docker/api/errdefs" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/errdefs" "github.com/gorilla/mux" "github.com/sirupsen/logrus" "google.golang.org/grpc" @@ -35,7 +35,7 @@ func GetHTTPErrorStatusCode(err error) int { statusCode = http.StatusNotFound case errdefs.IsInvalidParameter(err): statusCode = http.StatusBadRequest - case errdefs.IsConflict(err): + case errdefs.IsConflict(err) || errdefs.IsAlreadyExists(err): statusCode = http.StatusConflict case errdefs.IsUnauthorized(err): statusCode = http.StatusUnauthorized @@ -47,7 +47,7 @@ func GetHTTPErrorStatusCode(err error) int { statusCode = http.StatusNotModified case errdefs.IsNotImplemented(err): statusCode = http.StatusNotImplemented - case errdefs.IsSystem(err) || errdefs.IsUnknown(err): + case errdefs.IsSystem(err) || errdefs.IsUnknown(err) || errdefs.IsDataLoss(err) || errdefs.IsDeadline(err) || errdefs.IsCancelled(err): statusCode = http.StatusInternalServerError default: statusCode = statusCodeFromGRPCError(err) diff --git a/vendor/github.com/docker/docker/api/server/httputils/httputils.go b/vendor/github.com/docker/docker/api/server/httputils/httputils.go index 57eeb4beb..81fbabac1 100644 --- a/vendor/github.com/docker/docker/api/server/httputils/httputils.go +++ b/vendor/github.com/docker/docker/api/server/httputils/httputils.go @@ -6,13 +6,16 @@ import ( "net/http" "strings" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/net/context" ) +type contextKey string + // APIVersionKey is the client's requested API version. -const APIVersionKey = "api-version" +const APIVersionKey contextKey = "api-version" // APIFunc is an adapter to allow the use of ordinary functions as Docker API endpoints. // Any function that has the appropriate signature can be registered as an API endpoint (e.g. getVersion). @@ -43,20 +46,6 @@ func CloseStreams(streams ...interface{}) { } } -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (e validationError) Cause() error { - return e.cause -} - -func (e validationError) InvalidParameter() {} - // CheckForJSON makes sure that the request's Content-Type is application/json. func CheckForJSON(r *http.Request) error { ct := r.Header.Get("Content-Type") @@ -72,7 +61,7 @@ func CheckForJSON(r *http.Request) error { if matchesContentType(ct, "application/json") { return nil } - return validationError{errors.Errorf("Content-Type specified (%s) must be 'application/json'", ct)} + return errdefs.InvalidParameter(errors.Errorf("Content-Type specified (%s) must be 'application/json'", ct)) } // ParseForm ensures the request form is parsed even with invalid content types. @@ -82,7 +71,7 @@ func ParseForm(r *http.Request) error { return nil } if err := r.ParseForm(); err != nil && !strings.HasPrefix(err.Error(), "mime:") { - return validationError{err} + return errdefs.InvalidParameter(err) } return nil } diff --git a/vendor/github.com/docker/docker/api/server/middleware/version.go b/vendor/github.com/docker/docker/api/server/middleware/version.go index 679552910..c3e289cd4 100644 --- a/vendor/github.com/docker/docker/api/server/middleware/version.go +++ b/vendor/github.com/docker/docker/api/server/middleware/version.go @@ -5,6 +5,7 @@ import ( "net/http" "runtime" + "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types/versions" "golang.org/x/net/context" ) @@ -57,8 +58,7 @@ func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http. if versions.GreaterThan(apiVersion, v.defaultVersion) { return versionUnsupportedError{version: apiVersion, maxVersion: v.defaultVersion} } - // nolint: golint - ctx = context.WithValue(ctx, "api-version", apiVersion) + ctx = context.WithValue(ctx, httputils.APIVersionKey, apiVersion) return handler(ctx, w, r, vars) } diff --git a/vendor/github.com/docker/docker/api/server/middleware/version_test.go b/vendor/github.com/docker/docker/api/server/middleware/version_test.go index 9cf7cc247..59df0675a 100644 --- a/vendor/github.com/docker/docker/api/server/middleware/version_test.go +++ b/vendor/github.com/docker/docker/api/server/middleware/version_test.go @@ -4,7 +4,6 @@ import ( "net/http" "net/http/httptest" "runtime" - "strings" "testing" "github.com/docker/docker/api/server/httputils" @@ -12,37 +11,16 @@ import ( "golang.org/x/net/context" ) -func TestVersionMiddleware(t *testing.T) { +func TestVersionMiddlewareVersion(t *testing.T) { + defaultVersion := "1.10.0" + minVersion := "1.2.0" + expectedVersion := defaultVersion handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if httputils.VersionFromContext(ctx) == "" { - t.Fatal("Expected version, got empty string") - } + v := httputils.VersionFromContext(ctx) + assert.Equal(t, expectedVersion, v) return nil } - defaultVersion := "1.10.0" - minVersion := "1.2.0" - m := NewVersionMiddleware(defaultVersion, defaultVersion, minVersion) - h := m.WrapHandler(handler) - - req, _ := http.NewRequest("GET", "/containers/json", nil) - resp := httptest.NewRecorder() - ctx := context.Background() - if err := h(ctx, resp, req, map[string]string{}); err != nil { - t.Fatal(err) - } -} - -func TestVersionMiddlewareVersionTooOld(t *testing.T) { - handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if httputils.VersionFromContext(ctx) == "" { - t.Fatal("Expected version, got empty string") - } - return nil - } - - defaultVersion := "1.10.0" - minVersion := "1.2.0" m := NewVersionMiddleware(defaultVersion, defaultVersion, minVersion) h := m.WrapHandler(handler) @@ -50,44 +28,45 @@ func TestVersionMiddlewareVersionTooOld(t *testing.T) { resp := httptest.NewRecorder() ctx := context.Background() - vars := map[string]string{"version": "0.1"} - err := h(ctx, resp, req, vars) - - if !strings.Contains(err.Error(), "client version 0.1 is too old. Minimum supported API version is 1.2.0") { - t.Fatalf("Expected too old client error, got %v", err) + tests := []struct { + reqVersion string + expectedVersion string + errString string + }{ + { + expectedVersion: "1.10.0", + }, + { + reqVersion: "1.9.0", + expectedVersion: "1.9.0", + }, + { + reqVersion: "0.1", + errString: "client version 0.1 is too old. Minimum supported API version is 1.2.0, please upgrade your client to a newer version", + }, + { + reqVersion: "9999.9999", + errString: "client version 9999.9999 is too new. Maximum supported API version is 1.10.0", + }, } -} -func TestVersionMiddlewareVersionTooNew(t *testing.T) { - handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if httputils.VersionFromContext(ctx) == "" { - t.Fatal("Expected version, got empty string") + for _, test := range tests { + expectedVersion = test.expectedVersion + + err := h(ctx, resp, req, map[string]string{"version": test.reqVersion}) + + if test.errString != "" { + assert.EqualError(t, err, test.errString) + } else { + assert.NoError(t, err) } - return nil - } - - defaultVersion := "1.10.0" - minVersion := "1.2.0" - m := NewVersionMiddleware(defaultVersion, defaultVersion, minVersion) - h := m.WrapHandler(handler) - - req, _ := http.NewRequest("GET", "/containers/json", nil) - resp := httptest.NewRecorder() - ctx := context.Background() - - vars := map[string]string{"version": "9999.9999"} - err := h(ctx, resp, req, vars) - - if !strings.Contains(err.Error(), "client version 9999.9999 is too new. Maximum supported API version is 1.10.0") { - t.Fatalf("Expected too new client error, got %v", err) } } func TestVersionMiddlewareWithErrorsReturnsHeaders(t *testing.T) { handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - if httputils.VersionFromContext(ctx) == "" { - t.Fatal("Expected version, got empty string") - } + v := httputils.VersionFromContext(ctx) + assert.NotEmpty(t, v) return nil } @@ -102,8 +81,8 @@ func TestVersionMiddlewareWithErrorsReturnsHeaders(t *testing.T) { vars := map[string]string{"version": "0.1"} err := h(ctx, resp, req, vars) - assert.Error(t, err) + hdr := resp.Result().Header assert.Contains(t, hdr.Get("Server"), "Docker/"+defaultVersion) assert.Contains(t, hdr.Get("Server"), runtime.GOOS) diff --git a/vendor/github.com/docker/docker/api/server/router/build/build_routes.go b/vendor/github.com/docker/docker/api/server/router/build/build_routes.go index fefb875de..491fa85a8 100644 --- a/vendor/github.com/docker/docker/api/server/router/build/build_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/build/build_routes.go @@ -18,6 +18,7 @@ import ( "github.com/docker/docker/api/types/backend" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/progress" "github.com/docker/docker/pkg/streamformatter" @@ -83,7 +84,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui } p := system.ParsePlatform(apiPlatform) if err := system.ValidatePlatform(p); err != nil { - return nil, validationError{fmt.Errorf("invalid platform: %s", err)} + return nil, errdefs.InvalidParameter(errors.Errorf("invalid platform: %s", err)) } options.Platform = p.OS } @@ -104,14 +105,14 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui } if runtime.GOOS != "windows" && options.SecurityOpt != nil { - return nil, validationError{fmt.Errorf("The daemon on this platform does not support setting security options on build")} + return nil, errdefs.InvalidParameter(errors.New("The daemon on this platform does not support setting security options on build")) } var buildUlimits = []*units.Ulimit{} ulimitsJSON := r.FormValue("ulimits") if ulimitsJSON != "" { if err := json.Unmarshal([]byte(ulimitsJSON), &buildUlimits); err != nil { - return nil, errors.Wrap(validationError{err}, "error reading ulimit settings") + return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading ulimit settings") } options.Ulimits = buildUlimits } @@ -132,7 +133,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui if buildArgsJSON != "" { var buildArgs = map[string]*string{} if err := json.Unmarshal([]byte(buildArgsJSON), &buildArgs); err != nil { - return nil, errors.Wrap(validationError{err}, "error reading build args") + return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading build args") } options.BuildArgs = buildArgs } @@ -141,7 +142,7 @@ func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBui if labelsJSON != "" { var labels = map[string]string{} if err := json.Unmarshal([]byte(labelsJSON), &labels); err != nil { - return nil, errors.Wrap(validationError{err}, "error reading labels") + return nil, errors.Wrap(errdefs.InvalidParameter(err), "error reading labels") } options.Labels = labels } @@ -167,16 +168,6 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r * return httputils.WriteJSON(w, http.StatusOK, report) } -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (e validationError) InvalidParameter() {} - func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { var ( notVerboseBuffer = bytes.NewBuffer(nil) @@ -210,7 +201,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r * buildOptions.AuthConfigs = getAuthConfigs(r.Header) if buildOptions.Squash && !br.daemon.HasExperimental() { - return validationError{errors.New("squash is only supported with experimental mode")} + return errdefs.InvalidParameter(errors.New("squash is only supported with experimental mode")) } out := io.Writer(output) diff --git a/vendor/github.com/docker/docker/api/server/router/container/container.go b/vendor/github.com/docker/docker/api/server/router/container/container.go index 90ae6dc38..e3637824b 100644 --- a/vendor/github.com/docker/docker/api/server/router/container/container.go +++ b/vendor/github.com/docker/docker/api/server/router/container/container.go @@ -5,20 +5,6 @@ import ( "github.com/docker/docker/api/server/router" ) -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (e validationError) Cause() error { - return e.cause -} - -func (e validationError) InvalidParameter() {} - // containerRouter is a router to talk with the container controller type containerRouter struct { backend Backend diff --git a/vendor/github.com/docker/docker/api/server/router/container/container_routes.go b/vendor/github.com/docker/docker/api/server/router/container/container_routes.go index d845fdd00..5f8456d70 100644 --- a/vendor/github.com/docker/docker/api/server/router/container/container_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/container/container_routes.go @@ -8,7 +8,6 @@ import ( "strconv" "syscall" - "github.com/docker/docker/api/errdefs" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/backend" @@ -16,6 +15,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/versions" containerpkg "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/signal" "github.com/pkg/errors" @@ -88,7 +88,7 @@ func (s *containerRouter) getContainersLogs(ctx context.Context, w http.Response // with the appropriate status code. stdout, stderr := httputils.BoolValue(r, "stdout"), httputils.BoolValue(r, "stderr") if !(stdout || stderr) { - return validationError{errors.New("Bad parameters: you must choose at least one stream")} + return errdefs.InvalidParameter(errors.New("Bad parameters: you must choose at least one stream")) } containerName := vars["name"] @@ -203,7 +203,7 @@ func (s *containerRouter) postContainersKill(ctx context.Context, w http.Respons if sigStr := r.Form.Get("signal"); sigStr != "" { var err error if sig, err = signal.ParseSignal(sigStr); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } } @@ -468,11 +468,11 @@ func (s *containerRouter) postContainersResize(ctx context.Context, w http.Respo height, err := strconv.Atoi(r.Form.Get("h")) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } width, err := strconv.Atoi(r.Form.Get("w")) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } return s.backend.ContainerResize(vars["name"], height, width) @@ -490,7 +490,7 @@ func (s *containerRouter) postContainersAttach(ctx context.Context, w http.Respo hijacker, ok := w.(http.Hijacker) if !ok { - return validationError{errors.Errorf("error attaching to container %s, hijack connection missing", containerName)} + return errdefs.InvalidParameter(errors.Errorf("error attaching to container %s, hijack connection missing", containerName)) } setupStreams := func() (io.ReadCloser, io.Writer, io.Writer, error) { @@ -593,7 +593,11 @@ func (s *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons close(done) select { case <-started: - logrus.Errorf("Error attaching websocket: %s", err) + if err != nil { + logrus.Errorf("Error attaching websocket: %s", err) + } else { + logrus.Debug("websocket connection was closed by client") + } return nil default: } @@ -607,7 +611,7 @@ func (s *containerRouter) postContainersPrune(ctx context.Context, w http.Respon pruneFilters, err := filters.FromJSON(r.Form.Get("filters")) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } pruneReport, err := s.backend.ContainersPrune(ctx, pruneFilters) diff --git a/vendor/github.com/docker/docker/api/server/router/container/exec.go b/vendor/github.com/docker/docker/api/server/router/container/exec.go index 97c27d844..6dfca729c 100644 --- a/vendor/github.com/docker/docker/api/server/router/container/exec.go +++ b/vendor/github.com/docker/docker/api/server/router/container/exec.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/stdcopy" "github.com/sirupsen/logrus" "golang.org/x/net/context" @@ -137,11 +138,11 @@ func (s *containerRouter) postContainerExecResize(ctx context.Context, w http.Re } height, err := strconv.Atoi(r.Form.Get("h")) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } width, err := strconv.Atoi(r.Form.Get("w")) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } return s.backend.ContainerExecResize(vars["name"], height, width) diff --git a/vendor/github.com/docker/docker/api/server/router/image/image_routes.go b/vendor/github.com/docker/docker/api/server/router/image/image_routes.go index dabab3bcf..dc16a23af 100644 --- a/vendor/github.com/docker/docker/api/server/router/image/image_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/image/image_routes.go @@ -13,9 +13,9 @@ import ( "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/backend" - "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/system" @@ -46,9 +46,6 @@ func (s *imageRouter) postCommit(ctx context.Context, w http.ResponseWriter, r * if err != nil && err != io.EOF { //Do not fail if body is empty. return err } - if c == nil { - c = &container.Config{} - } commitCfg := &backend.ContainerCommitConfig{ ContainerCommitConfig: types.ContainerCommitConfig{ @@ -148,20 +145,6 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite return nil } -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (e validationError) Cause() error { - return e.cause -} - -func (validationError) InvalidParameter() {} - func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { metaHeaders := map[string][]string{} for k, v := range r.Header { @@ -185,7 +168,7 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, } else { // the old format is supported for compatibility if there was no authConfig header if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil { - return errors.Wrap(validationError{err}, "Bad parameters and missing X-Registry-Auth") + return errors.Wrap(errdefs.InvalidParameter(err), "Bad parameters and missing X-Registry-Auth") } } diff --git a/vendor/github.com/docker/docker/api/server/router/network/backend.go b/vendor/github.com/docker/docker/api/server/router/network/backend.go index a32a0b9c0..186ae8fc7 100644 --- a/vendor/github.com/docker/docker/api/server/router/network/backend.go +++ b/vendor/github.com/docker/docker/api/server/router/network/backend.go @@ -17,6 +17,6 @@ type Backend interface { CreateNetwork(nc types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error - DeleteNetwork(name string) error + DeleteNetwork(networkID string) error NetworksPrune(ctx context.Context, pruneFilters filters.Args) (*types.NetworksPruneReport, error) } diff --git a/vendor/github.com/docker/docker/api/server/router/network/network_routes.go b/vendor/github.com/docker/docker/api/server/router/network/network_routes.go index a67bb9f0b..ffd0f392d 100644 --- a/vendor/github.com/docker/docker/api/server/router/network/network_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/network/network_routes.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/errdefs" "github.com/docker/libnetwork" netconst "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/networkdb" @@ -100,22 +101,8 @@ func (e ambigousResultsError) Error() string { func (ambigousResultsError) InvalidParameter() {} -type conflictError struct { - cause error -} - -func (e conflictError) Error() string { - return e.cause.Error() -} - -func (e conflictError) Cause() error { - return e.cause -} - -func (e conflictError) Conflict() {} - func nameConflict(name string) error { - return conflictError{libnetwork.NetworkNameError(name)} + return errdefs.Conflict(libnetwork.NetworkNameError(name)) } func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { @@ -288,7 +275,12 @@ func (n *networkRouter) postNetworkConnect(ctx context.Context, w http.ResponseW return err } - return n.backend.ConnectContainerToNetwork(connect.Container, vars["id"], connect.EndpointConfig) + // Always make sure there is no ambiguity with respect to the network ID/name + nw, err := n.backend.FindNetwork(vars["id"]) + if err != nil { + return err + } + return n.backend.ConnectContainerToNetwork(connect.Container, nw.ID(), connect.EndpointConfig) } func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { @@ -312,15 +304,19 @@ func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter if err := httputils.ParseForm(r); err != nil { return err } - if _, err := n.cluster.GetNetwork(vars["id"]); err == nil { - if err = n.cluster.RemoveNetwork(vars["id"]); err != nil { + + nw, err := n.findUniqueNetwork(vars["id"]) + if err != nil { + return err + } + if nw.Scope == "swarm" { + if err = n.cluster.RemoveNetwork(nw.ID); err != nil { + return err + } + } else { + if err := n.backend.DeleteNetwork(nw.ID); err != nil { return err } - w.WriteHeader(http.StatusNoContent) - return nil - } - if err := n.backend.DeleteNetwork(vars["id"]); err != nil { - return err } w.WriteHeader(http.StatusNoContent) return nil @@ -518,3 +514,79 @@ func (n *networkRouter) postNetworksPrune(ctx context.Context, w http.ResponseWr } return httputils.WriteJSON(w, http.StatusOK, pruneReport) } + +// findUniqueNetwork will search network across different scopes (both local and swarm). +// NOTE: This findUniqueNetwork is different from FindNetwork in the daemon. +// In case multiple networks have duplicate names, return error. +// First find based on full ID, return immediately once one is found. +// If a network appears both in swarm and local, assume it is in local first +// For full name and partial ID, save the result first, and process later +// in case multiple records was found based on the same term +// TODO (yongtang): should we wrap with version here for backward compatibility? +func (n *networkRouter) findUniqueNetwork(term string) (types.NetworkResource, error) { + listByFullName := map[string]types.NetworkResource{} + listByPartialID := map[string]types.NetworkResource{} + + nw := n.backend.GetNetworks() + for _, network := range nw { + if network.ID() == term { + return *n.buildDetailedNetworkResources(network, false), nil + + } + if network.Name() == term && !network.Info().Ingress() { + // No need to check the ID collision here as we are still in + // local scope and the network ID is unique in this scope. + listByFullName[network.ID()] = *n.buildDetailedNetworkResources(network, false) + } + if strings.HasPrefix(network.ID(), term) { + // No need to check the ID collision here as we are still in + // local scope and the network ID is unique in this scope. + listByPartialID[network.ID()] = *n.buildDetailedNetworkResources(network, false) + } + } + + nr, _ := n.cluster.GetNetworks() + for _, network := range nr { + if network.ID == term { + return network, nil + } + if network.Name == term { + // Check the ID collision as we are in swarm scope here, and + // the map (of the listByFullName) may have already had a + // network with the same ID (from local scope previously) + if _, ok := listByFullName[network.ID]; !ok { + listByFullName[network.ID] = network + } + } + if strings.HasPrefix(network.ID, term) { + // Check the ID collision as we are in swarm scope here, and + // the map (of the listByPartialID) may have already had a + // network with the same ID (from local scope previously) + if _, ok := listByPartialID[network.ID]; !ok { + listByPartialID[network.ID] = network + } + } + } + + // Find based on full name, returns true only if no duplicates + if len(listByFullName) == 1 { + for _, v := range listByFullName { + return v, nil + } + } + if len(listByFullName) > 1 { + return types.NetworkResource{}, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on name)", term, len(listByFullName))) + } + + // Find based on partial ID, returns true only if no duplicates + if len(listByPartialID) == 1 { + for _, v := range listByPartialID { + return v, nil + } + } + if len(listByPartialID) > 1 { + return types.NetworkResource{}, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID))) + } + + return types.NetworkResource{}, errdefs.NotFound(libnetwork.ErrNoSuchNetwork(term)) +} diff --git a/vendor/github.com/docker/docker/api/server/router/session/session_routes.go b/vendor/github.com/docker/docker/api/server/router/session/session_routes.go index bccd76422..8eb8074eb 100644 --- a/vendor/github.com/docker/docker/api/server/router/session/session_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/session/session_routes.go @@ -3,27 +3,14 @@ package session import ( "net/http" + "github.com/docker/docker/errdefs" "golang.org/x/net/context" ) -type invalidRequest struct { - cause error -} - -func (e invalidRequest) Error() string { - return e.cause.Error() -} - -func (e invalidRequest) Cause() error { - return e.cause -} - -func (e invalidRequest) InvalidParameter() {} - func (sr *sessionRouter) startSession(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { err := sr.backend.HandleHTTPRequest(ctx, w, r) if err != nil { - return invalidRequest{err} + return errdefs.InvalidParameter(err) } return nil } diff --git a/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go b/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go index 5b6c19d9c..bd98acfcf 100644 --- a/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/swarm/cluster_routes.go @@ -12,6 +12,7 @@ import ( "github.com/docker/docker/api/types/filters" types "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/versions" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/net/context" @@ -57,20 +58,6 @@ func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter return httputils.WriteJSON(w, http.StatusOK, swarm) } -type invalidRequestError struct { - err error -} - -func (e invalidRequestError) Error() string { - return e.err.Error() -} - -func (e invalidRequestError) Cause() error { - return e.err -} - -func (e invalidRequestError) InvalidParameter() {} - func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { var swarm types.Spec if err := json.NewDecoder(r.Body).Decode(&swarm); err != nil { @@ -81,7 +68,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { err := fmt.Errorf("invalid swarm version '%s': %v", rawVersion, err) - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } var flags types.UpdateFlags @@ -90,7 +77,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, rot, err := strconv.ParseBool(value) if err != nil { err := fmt.Errorf("invalid value for rotateWorkerToken: %s", value) - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } flags.RotateWorkerToken = rot @@ -100,7 +87,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, rot, err := strconv.ParseBool(value) if err != nil { err := fmt.Errorf("invalid value for rotateManagerToken: %s", value) - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } flags.RotateManagerToken = rot @@ -109,7 +96,7 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter, if value := r.URL.Query().Get("rotateManagerUnlockKey"); value != "" { rot, err := strconv.ParseBool(value) if err != nil { - return invalidRequestError{fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value)} + return errdefs.InvalidParameter(fmt.Errorf("invalid value for rotateManagerUnlockKey: %s", value)) } flags.RotateManagerUnlockKey = rot @@ -153,7 +140,7 @@ func (sr *swarmRouter) getServices(ctx context.Context, w http.ResponseWriter, r } filter, err := filters.FromJSON(r.Form.Get("filters")) if err != nil { - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } services, err := sr.backend.GetServices(basictypes.ServiceListOptions{Filters: filter}) @@ -172,7 +159,7 @@ func (sr *swarmRouter) getService(ctx context.Context, w http.ResponseWriter, r insertDefaults, err = strconv.ParseBool(value) if err != nil { err := fmt.Errorf("invalid value for insertDefaults: %s", value) - return errors.Wrapf(invalidRequestError{err}, "invalid value for insertDefaults: %s", value) + return errors.Wrapf(errdefs.InvalidParameter(err), "invalid value for insertDefaults: %s", value) } } @@ -218,7 +205,7 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter, version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { err := fmt.Errorf("invalid service version '%s': %v", rawVersion, err) - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } var flags basictypes.ServiceUpdateOptions @@ -311,7 +298,7 @@ func (sr *swarmRouter) updateNode(ctx context.Context, w http.ResponseWriter, r version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { err := fmt.Errorf("invalid node version '%s': %v", rawVersion, err) - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } if err := sr.backend.UpdateNode(vars["id"], version, node); err != nil { @@ -417,13 +404,13 @@ func (sr *swarmRouter) getSecret(ctx context.Context, w http.ResponseWriter, r * func (sr *swarmRouter) updateSecret(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { var secret types.SecretSpec if err := json.NewDecoder(r.Body).Decode(&secret); err != nil { - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } rawVersion := r.URL.Query().Get("version") version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { - return invalidRequestError{fmt.Errorf("invalid secret version")} + return errdefs.InvalidParameter(fmt.Errorf("invalid secret version")) } id := vars["id"] @@ -484,13 +471,13 @@ func (sr *swarmRouter) getConfig(ctx context.Context, w http.ResponseWriter, r * func (sr *swarmRouter) updateConfig(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { var config types.ConfigSpec if err := json.NewDecoder(r.Body).Decode(&config); err != nil { - return invalidRequestError{err} + return errdefs.InvalidParameter(err) } rawVersion := r.URL.Query().Get("version") version, err := strconv.ParseUint(rawVersion, 10, 64) if err != nil { - return invalidRequestError{fmt.Errorf("invalid config version")} + return errdefs.InvalidParameter(fmt.Errorf("invalid config version")) } id := vars["id"] diff --git a/vendor/github.com/docker/docker/api/server/router/system/system_routes.go b/vendor/github.com/docker/docker/api/server/router/system/system_routes.go index 8f6aecd77..535956d65 100644 --- a/vendor/github.com/docker/docker/api/server/router/system/system_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/system/system_routes.go @@ -6,7 +6,6 @@ import ( "net/http" "time" - "github.com/docker/docker/api" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/events" @@ -65,7 +64,6 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { info := s.backend.SystemVersion() - info.APIVersion = api.DefaultVersion return httputils.WriteJSON(w, http.StatusOK, info) } diff --git a/vendor/github.com/docker/docker/api/server/router/volume/volume_routes.go b/vendor/github.com/docker/docker/api/server/router/volume/volume_routes.go index bfff51ab1..fef68960b 100644 --- a/vendor/github.com/docker/docker/api/server/router/volume/volume_routes.go +++ b/vendor/github.com/docker/docker/api/server/router/volume/volume_routes.go @@ -2,11 +2,14 @@ package volume import ( "encoding/json" + "errors" + "io" "net/http" "github.com/docker/docker/api/server/httputils" "github.com/docker/docker/api/types/filters" volumetypes "github.com/docker/docker/api/types/volume" + "github.com/docker/docker/errdefs" "golang.org/x/net/context" ) @@ -45,6 +48,9 @@ func (v *volumeRouter) postVolumesCreate(ctx context.Context, w http.ResponseWri var req volumetypes.VolumesCreateBody if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + if err == io.EOF { + return errdefs.InvalidParameter(errors.New("got EOF while reading request body")) + } return err } diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml index a6b5ee5cf..8ff7415d6 100644 --- a/vendor/github.com/docker/docker/api/swagger.yaml +++ b/vendor/github.com/docker/docker/api/swagger.yaml @@ -19,10 +19,10 @@ produces: consumes: - "application/json" - "text/plain" -basePath: "/v1.35" +basePath: "/v1.36" info: title: "Docker Engine API" - version: "1.35" + version: "1.36" x-logo: url: "https://docs.docker.com/images/logo-docker-main.png" description: | @@ -49,8 +49,8 @@ info: the URL is not supported by the daemon, a HTTP `400 Bad Request` error message is returned. - If you omit the version-prefix, the current version of the API (v1.35) is used. - For example, calling `/info` is the same as calling `/v1.35/info`. Using the + If you omit the version-prefix, the current version of the API (v1.36) is used. + For example, calling `/info` is the same as calling `/v1.36/info`. Using the API without a version-prefix is deprecated and will be removed in a future release. Engine releases in the near future should support this version of the API, @@ -254,6 +254,7 @@ definitions: properties: Propagation: description: "A propagation mode with the value `[r]private`, `[r]shared`, or `[r]slave`." + type: "string" enum: - "private" - "rprivate" @@ -332,6 +333,7 @@ definitions: Memory: description: "Memory limit in bytes." type: "integer" + format: "int64" default: 0 # Applicable to UNIX platforms CgroupParent: @@ -606,17 +608,7 @@ definitions: description: "Network mode to use for this container. Supported standard values are: `bridge`, `host`, `none`, and `container:`. Any other value is taken as a custom network's name to which this container should connect to." PortBindings: - type: "object" - description: "A map of exposed container ports and the host port they should map to." - additionalProperties: - type: "object" - properties: - HostIp: - type: "string" - description: "The host IP address" - HostPort: - type: "string" - description: "The host port number, as a string" + $ref: "#/definitions/PortMap" RestartPolicy: $ref: "#/definitions/RestartPolicy" AutoRemove: @@ -832,9 +824,7 @@ definitions: type: "string" Cmd: description: "Command to run specified as a string or an array of strings." - type: - - "array" - - "string" + type: "array" items: type: "string" Healthcheck: @@ -862,9 +852,7 @@ definitions: The entry point for the container as a string or an array of strings. If the array consists of exactly one empty string (`[""]`) then the entry point is reset to system default (i.e., the entry point used by docker when there is no `ENTRYPOINT` instruction in the `Dockerfile`). - type: - - "array" - - "string" + type: "array" items: type: "string" NetworkDisabled: @@ -1508,10 +1496,23 @@ definitions: type: "string" progressDetail: $ref: "#/definitions/ProgressDetail" + aux: + $ref: "#/definitions/ImageID" + + ImageID: + type: "object" + description: "Image ID or Digest" + properties: + ID: + type: "string" + example: + ID: "sha256:85f05633ddc1c50679be2b16a0479ab6f7637f8884e0cfe0f4d20e1ebb3d6e7c" CreateImageInfo: type: "object" properties: + id: + type: "string" error: type: "string" status: @@ -1544,9 +1545,9 @@ definitions: ProgressDetail: type: "object" properties: - code: + current: type: "integer" - message: + total: type: "integer" ErrorResponse: @@ -4501,6 +4502,8 @@ paths: description: "Container created successfully" schema: type: "object" + title: "ContainerCreateResponse" + description: "OK response to ContainerCreate operation" required: [Id, Warnings] properties: Id: @@ -4549,6 +4552,7 @@ paths: description: "no error" schema: type: "object" + title: "ContainerInspectResponse" properties: Id: description: "The ID of the container" @@ -4833,6 +4837,8 @@ paths: description: "no error" schema: type: "object" + title: "ContainerTopResponse" + description: "OK response to ContainerTop operation" properties: Titles: description: "The ps column titles" @@ -4993,6 +4999,8 @@ paths: items: type: "object" x-go-name: "ContainerChangeResponseItem" + title: "ContainerChangeResponseItem" + description: "change item in response to ContainerChanges operation" required: [Path, Kind] properties: Path: @@ -5371,6 +5379,8 @@ paths: description: "The container has been updated." schema: type: "object" + title: "ContainerUpdateResponse" + description: "OK response to ContainerUpdate operation" properties: Warnings: type: "array" @@ -5724,6 +5734,8 @@ paths: description: "The container has exit." schema: type: "object" + title: "ContainerWaitResponse" + description: "OK response to ContainerWait operation" required: [StatusCode] properties: StatusCode: @@ -5969,6 +5981,7 @@ paths: description: "No error" schema: type: "object" + title: "ContainerPruneResponse" properties: ContainersDeleted: description: "Container IDs that were deleted" @@ -6225,6 +6238,7 @@ paths: description: "No error" schema: type: "object" + title: "BuildPruneResponse" properties: SpaceReclaimed: description: "Disk space reclaimed in bytes" @@ -6410,6 +6424,8 @@ paths: items: type: "object" x-go-name: HistoryResponseItem + title: "HistoryResponseItem" + description: "individual image layer information in response to ImageHistory operation" required: [Id, Created, CreatedBy, Tags, Size, Comment] properties: Id: @@ -6616,6 +6632,7 @@ paths: type: "array" items: type: "object" + title: "ImageSearchResponseItem" properties: description: type: "string" @@ -6691,6 +6708,7 @@ paths: description: "No error" schema: type: "object" + title: "ImagePruneResponse" properties: ImagesDeleted: description: "Images that were deleted" @@ -6718,6 +6736,7 @@ paths: description: "An identity token was generated successfully." schema: type: "object" + title: "SystemAuthResponse" required: [Status] properties: Status: @@ -6772,7 +6791,30 @@ paths: description: "no error" schema: type: "object" + title: "SystemVersionResponse" properties: + Platform: + type: "object" + required: [Name] + properties: + Name: + type: "string" + Components: + type: "array" + items: + type: "object" + x-go-name: ComponentVersion + required: [Name, Version] + properties: + Name: + type: "string" + Version: + type: "string" + x-nullable: false + Details: + type: "object" + x-nullable: true + Version: type: "string" ApiVersion: @@ -6902,7 +6944,7 @@ paths: Various objects within Docker report events when something happens to them. - Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, and `update` + Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `exec_die`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, and `update` Images report these events: `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, and `untag` @@ -6928,6 +6970,7 @@ paths: description: "no error" schema: type: "object" + title: "SystemEventsResponse" properties: Type: description: "The type of object emitting the event" @@ -7011,6 +7054,7 @@ paths: description: "no error" schema: type: "object" + title: "SystemDataUsageResponse" properties: LayersSize: type: "integer" @@ -7268,6 +7312,9 @@ paths: User: type: "string" description: "The user, and optionally, group to run the exec process inside the container. Format is one of: `user`, `user:group`, `uid`, or `uid:gid`." + WorkingDir: + type: "string" + description: "The working directory for the exec process inside the container." example: AttachStdin: false AttachStdout: true @@ -7366,7 +7413,12 @@ paths: description: "No error" schema: type: "object" + title: "ExecInspectResponse" properties: + CanRemove: + type: "boolean" + DetachKeys: + type: "string" ID: type: "string" Running: @@ -7432,6 +7484,7 @@ paths: description: "Summary volume data that matches the query" schema: type: "object" + title: "VolumeListResponse" required: [Volumes, Warnings] properties: Volumes: @@ -7613,6 +7666,7 @@ paths: description: "No error" schema: type: "object" + title: "VolumePruneResponse" properties: VolumesDeleted: description: "Volumes that were deleted" @@ -7791,6 +7845,7 @@ paths: description: "No error" schema: type: "object" + title: "NetworkCreateResponse" properties: Id: description: "The ID of the created network." @@ -7993,6 +8048,7 @@ paths: description: "No error" schema: type: "object" + title: "NetworkPruneResponse" properties: NetworksDeleted: description: "Networks that were deleted" @@ -8044,6 +8100,7 @@ paths: items: description: "Describes a permission the user has to accept upon installing the plugin." type: "object" + title: "PluginPrivilegeItem" properties: Name: type: "string" @@ -8746,6 +8803,7 @@ paths: description: "no error" schema: type: "object" + title: "UnlockKeyResponse" properties: UnlockKey: description: "The swarm's unlock key." @@ -8837,6 +8895,7 @@ paths: description: "no error" schema: type: "object" + title: "ServiceCreateResponse" properties: ID: description: "The ID of the created service." @@ -9508,13 +9567,7 @@ paths: 201: description: "no error" schema: - type: "object" - properties: - ID: - description: "The ID of the created secret." - type: "string" - example: - ID: "ktnbjxoalbkvbvedmg1urrz8h" + $ref: "#/definitions/IdResponse" 409: description: "name conflicts with an existing object" schema: @@ -9713,13 +9766,7 @@ paths: 201: description: "no error" schema: - type: "object" - properties: - ID: - description: "The ID of the created config." - type: "string" - example: - ID: "ktnbjxoalbkvbvedmg1urrz8h" + $ref: "#/definitions/IdResponse" 409: description: "name conflicts with an existing object" schema: @@ -9865,6 +9912,7 @@ paths: schema: type: "object" x-go-name: DistributionInspect + title: "DistributionInspectResponse" required: [Descriptor, Platforms] properties: Descriptor: diff --git a/vendor/github.com/docker/docker/api/templates/server/operation.gotmpl b/vendor/github.com/docker/docker/api/templates/server/operation.gotmpl index 3ff63ef94..8bed59d92 100644 --- a/vendor/github.com/docker/docker/api/templates/server/operation.gotmpl +++ b/vendor/github.com/docker/docker/api/templates/server/operation.gotmpl @@ -20,7 +20,7 @@ import ( {{ range .ExtraSchemas }} -// {{ .Name }} {{ template "docstring" . }} +// {{ .Name }} {{ comment .Description }} // swagger:model {{ .Name }} {{ template "schema" . }} {{ end }} diff --git a/vendor/github.com/docker/docker/api/types/configs.go b/vendor/github.com/docker/docker/api/types/configs.go index 20c19f213..54d3e39fb 100644 --- a/vendor/github.com/docker/docker/api/types/configs.go +++ b/vendor/github.com/docker/docker/api/types/configs.go @@ -50,6 +50,7 @@ type ExecConfig struct { Detach bool // Execute in detach mode DetachKeys string // Escape keys for detach Env []string // Environment variables + WorkingDir string // Working directory Cmd []string // Execution commands and args } diff --git a/vendor/github.com/docker/docker/api/types/container/container_changes.go b/vendor/github.com/docker/docker/api/types/container/container_changes.go index 767945a53..c909d6ca3 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_changes.go +++ b/vendor/github.com/docker/docker/api/types/container/container_changes.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerChangeResponseItem container change response item +// ContainerChangeResponseItem change item in response to ContainerChanges operation // swagger:model ContainerChangeResponseItem type ContainerChangeResponseItem struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_create.go b/vendor/github.com/docker/docker/api/types/container/container_create.go index c95023b81..49efa0f2c 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_create.go +++ b/vendor/github.com/docker/docker/api/types/container/container_create.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerCreateCreatedBody container create created body +// ContainerCreateCreatedBody OK response to ContainerCreate operation // swagger:model ContainerCreateCreatedBody type ContainerCreateCreatedBody struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_top.go b/vendor/github.com/docker/docker/api/types/container/container_top.go index 78bc37ee5..ba41edcf3 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_top.go +++ b/vendor/github.com/docker/docker/api/types/container/container_top.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerTopOKBody container top o k body +// ContainerTopOKBody OK response to ContainerTop operation // swagger:model ContainerTopOKBody type ContainerTopOKBody struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_update.go b/vendor/github.com/docker/docker/api/types/container/container_update.go index 2339366fb..7630ae54c 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_update.go +++ b/vendor/github.com/docker/docker/api/types/container/container_update.go @@ -7,7 +7,7 @@ package container // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// ContainerUpdateOKBody container update o k body +// ContainerUpdateOKBody OK response to ContainerUpdate operation // swagger:model ContainerUpdateOKBody type ContainerUpdateOKBody struct { diff --git a/vendor/github.com/docker/docker/api/types/container/container_wait.go b/vendor/github.com/docker/docker/api/types/container/container_wait.go index 47fb17578..9e3910a6b 100644 --- a/vendor/github.com/docker/docker/api/types/container/container_wait.go +++ b/vendor/github.com/docker/docker/api/types/container/container_wait.go @@ -15,7 +15,7 @@ type ContainerWaitOKBodyError struct { Message string `json:"Message,omitempty"` } -// ContainerWaitOKBody container wait o k body +// ContainerWaitOKBody OK response to ContainerWait operation // swagger:model ContainerWaitOKBody type ContainerWaitOKBody struct { diff --git a/vendor/github.com/docker/docker/api/types/image/image_history.go b/vendor/github.com/docker/docker/api/types/image/image_history.go index 0dd30c729..d6b354bcd 100644 --- a/vendor/github.com/docker/docker/api/types/image/image_history.go +++ b/vendor/github.com/docker/docker/api/types/image/image_history.go @@ -7,7 +7,7 @@ package image // See hack/generate-swagger-api.sh // ---------------------------------------------------------------------------- -// HistoryResponseItem history response item +// HistoryResponseItem individual image layer information in response to ImageHistory operation // swagger:model HistoryResponseItem type HistoryResponseItem struct { diff --git a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto b/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto index 06eb7ba65..6d63b7783 100644 --- a/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto +++ b/vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime"; + // PluginSpec defines the base payload which clients can specify for creating // a service with the plugin runtime. message PluginSpec { diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go index f7ac77297..7814e6b93 100644 --- a/vendor/github.com/docker/docker/api/types/types.go +++ b/vendor/github.com/docker/docker/api/types/types.go @@ -107,9 +107,21 @@ type Ping struct { Experimental bool } +// ComponentVersion describes the version information for a specific component. +type ComponentVersion struct { + Name string + Version string + Details map[string]string `json:",omitempty"` +} + // Version contains response of Engine API: // GET "/version" type Version struct { + Platform struct{ Name string } `json:",omitempty"` + Components []ComponentVersion `json:",omitempty"` + + // The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility + Version string APIVersion string `json:"ApiVersion"` MinAPIVersion string `json:"MinAPIVersion,omitempty"` diff --git a/vendor/github.com/docker/docker/builder/builder.go b/vendor/github.com/docker/docker/builder/builder.go index 5a3e2cd8c..b7d5edea0 100644 --- a/vendor/github.com/docker/docker/builder/builder.go +++ b/vendor/github.com/docker/docker/builder/builder.go @@ -44,7 +44,7 @@ type Backend interface { // ContainerCreateWorkdir creates the workdir ContainerCreateWorkdir(containerID string) error - CreateImage(config []byte, parent string, platform string) (Image, error) + CreateImage(config []byte, parent string) (Image, error) ImageCacheBuilder } @@ -79,7 +79,7 @@ type Result struct { // ImageCacheBuilder represents a generator for stateful image cache. type ImageCacheBuilder interface { // MakeImageCache creates a stateful image cache. - MakeImageCache(cacheFrom []string, platform string) ImageCache + MakeImageCache(cacheFrom []string) ImageCache } // ImageCache abstracts an image cache. @@ -102,6 +102,6 @@ type Image interface { type ReleaseableLayer interface { Release() error Mount() (containerfs.ContainerFS, error) - Commit(platform string) (ReleaseableLayer, error) + Commit() (ReleaseableLayer, error) DiffID() layer.DiffID } diff --git a/vendor/github.com/docker/docker/builder/dockerfile/builder.go b/vendor/github.com/docker/docker/builder/dockerfile/builder.go index b62d6fc02..374f301ac 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/builder.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/builder.go @@ -17,6 +17,7 @@ import ( "github.com/docker/docker/builder/dockerfile/parser" "github.com/docker/docker/builder/fscache" "github.com/docker/docker/builder/remotecontext" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/streamformatter" "github.com/docker/docker/pkg/stringid" @@ -122,7 +123,7 @@ func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) ( PathCache: bm.pathCache, IDMappings: bm.idMappings, } - return newBuilder(ctx, builderOptions, os).build(source, dockerfile) + return newBuilder(ctx, builderOptions).build(source, dockerfile) } func (bm *BuildManager) initializeClientSession(ctx context.Context, cancel func(), options *types.ImageBuildOptions) (builder.Source, error) { @@ -189,7 +190,7 @@ type Builder struct { } // newBuilder creates a new Dockerfile builder from an optional dockerfile and a Options. -func newBuilder(clientCtx context.Context, options builderOptions, os string) *Builder { +func newBuilder(clientCtx context.Context, options builderOptions) *Builder { config := options.Options if config == nil { config = new(types.ImageBuildOptions) @@ -206,7 +207,7 @@ func newBuilder(clientCtx context.Context, options builderOptions, os string) *B idMappings: options.IDMappings, imageSources: newImageSources(clientCtx, options), pathCache: options.PathCache, - imageProber: newImageProber(options.Backend, config.CacheFrom, os, config.NoCache), + imageProber: newImageProber(options.Backend, config.CacheFrom, config.NoCache), containerManager: newContainerManager(options.Backend), } @@ -225,7 +226,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil if instructions.IsUnknownInstruction(err) { buildsFailed.WithValues(metricsUnknownInstructionError).Inc() } - return nil, validationError{err} + return nil, errdefs.InvalidParameter(err) } if b.options.Target != "" { targetIx, found := instructions.HasStage(stages, b.options.Target) @@ -356,29 +357,27 @@ func addNodesForLabelOption(dockerfile *parser.Node, labels map[string]string) { // coming from the query parameter of the same name. // // TODO: Remove? -func BuildFromConfig(config *container.Config, changes []string) (*container.Config, error) { +func BuildFromConfig(config *container.Config, changes []string, os string) (*container.Config, error) { + if !system.IsOSSupported(os) { + return nil, errdefs.InvalidParameter(system.ErrNotSupportedOperatingSystem) + } if len(changes) == 0 { return config, nil } dockerfile, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n"))) if err != nil { - return nil, validationError{err} - } - - os := runtime.GOOS - if dockerfile.OS != "" { - os = dockerfile.OS + return nil, errdefs.InvalidParameter(err) } b := newBuilder(context.Background(), builderOptions{ Options: &types.ImageBuildOptions{NoCache: true}, - }, os) + }) // ensure that the commands are valid for _, n := range dockerfile.AST.Children { if !validCommitCommands[n.Value] { - return nil, validationError{errors.Errorf("%s is not a valid change command", n.Value)} + return nil, errdefs.InvalidParameter(errors.Errorf("%s is not a valid change command", n.Value)) } } @@ -390,18 +389,20 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con for _, n := range dockerfile.AST.Children { cmd, err := instructions.ParseCommand(n) if err != nil { - return nil, validationError{err} + return nil, errdefs.InvalidParameter(err) } commands = append(commands, cmd) } dispatchRequest := newDispatchRequest(b, dockerfile.EscapeToken, nil, newBuildArgs(b.options.BuildArgs), newStagesBuildResults()) - dispatchRequest.state.runConfig = config + // We make mutations to the configuration, ensure we have a copy + dispatchRequest.state.runConfig = copyRunConfig(config) dispatchRequest.state.imageID = config.Image + dispatchRequest.state.operatingSystem = os for _, cmd := range commands { err := dispatch(dispatchRequest, cmd) if err != nil { - return nil, validationError{err} + return nil, errdefs.InvalidParameter(err) } dispatchRequest.state.updateRunConfig() } diff --git a/vendor/github.com/docker/docker/builder/dockerfile/containerbackend.go b/vendor/github.com/docker/docker/builder/dockerfile/containerbackend.go index add0a876d..523cc5076 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/containerbackend.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/containerbackend.go @@ -28,7 +28,7 @@ func newContainerManager(docker builder.ExecBackend) *containerManager { } // Create a container -func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig, platform string) (container.ContainerCreateCreatedBody, error) { +func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig) (container.ContainerCreateCreatedBody, error) { container, err := c.backend.ContainerCreate(types.ContainerCreateConfig{ Config: runConfig, HostConfig: hostConfig, diff --git a/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go b/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go index 8d3ea7ed6..4239e3ccc 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/dispatchers.go @@ -20,6 +20,7 @@ import ( "github.com/docker/docker/builder" "github.com/docker/docker/builder/dockerfile/instructions" "github.com/docker/docker/builder/dockerfile/parser" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/signal" @@ -155,7 +156,9 @@ func initializeStage(d dispatchRequest, cmd *instructions.Stage) error { return err } state := d.state - state.beginStage(cmd.Name, image) + if err := state.beginStage(cmd.Name, image); err != nil { + return err + } if len(state.runConfig.OnBuild) > 0 { triggers := state.runConfig.OnBuild state.runConfig.OnBuild = nil @@ -260,8 +263,8 @@ func dispatchOnbuild(d dispatchRequest, c *instructions.OnbuildCommand) error { func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error { runConfig := d.state.runConfig var err error - optionsOS := system.ParsePlatform(d.builder.options.Platform).OS - runConfig.WorkingDir, err = normalizeWorkdir(optionsOS, runConfig.WorkingDir, c.Path) + baseImageOS := system.ParsePlatform(d.state.operatingSystem).OS + runConfig.WorkingDir, err = normalizeWorkdir(baseImageOS, runConfig.WorkingDir, c.Path) if err != nil { return err } @@ -277,7 +280,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error { } comment := "WORKDIR " + runConfig.WorkingDir - runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment, optionsOS)) + runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment, baseImageOS)) containerID, err := d.builder.probeAndCreate(d.state, runConfigWithCommentCmd) if err != nil || containerID == "" { return err @@ -289,10 +292,10 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error { return d.builder.commitContainer(d.state, containerID, runConfigWithCommentCmd) } -func resolveCmdLine(cmd instructions.ShellDependantCmdLine, runConfig *container.Config, platform string) []string { +func resolveCmdLine(cmd instructions.ShellDependantCmdLine, runConfig *container.Config, os string) []string { result := cmd.CmdLine if cmd.PrependShell && result != nil { - result = append(getShell(runConfig, platform), result...) + result = append(getShell(runConfig, os), result...) } return result } @@ -308,10 +311,11 @@ func resolveCmdLine(cmd instructions.ShellDependantCmdLine, runConfig *container // RUN [ "echo", "hi" ] # echo hi // func dispatchRun(d dispatchRequest, c *instructions.RunCommand) error { - + if !system.IsOSSupported(d.state.operatingSystem) { + return system.ErrNotSupportedOperatingSystem + } stateRunConfig := d.state.runConfig - optionsOS := system.ParsePlatform(d.builder.options.Platform).OS - cmdFromArgs := resolveCmdLine(c.ShellDependantCmdLine, stateRunConfig, optionsOS) + cmdFromArgs := resolveCmdLine(c.ShellDependantCmdLine, stateRunConfig, d.state.operatingSystem) buildArgs := d.state.buildArgs.FilterAllowed(stateRunConfig.Env) saveCmd := cmdFromArgs @@ -510,7 +514,7 @@ func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) er _, err := signal.ParseSignal(c.Signal) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } d.state.runConfig.StopSignal = c.Signal return d.builder.commit(d.state, fmt.Sprintf("STOPSIGNAL %v", c.Signal)) diff --git a/vendor/github.com/docker/docker/builder/dockerfile/dispatchers_test.go b/vendor/github.com/docker/docker/builder/dockerfile/dispatchers_test.go index dc9148bca..29cecd8fc 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/dispatchers_test.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/dispatchers_test.go @@ -31,7 +31,7 @@ func newBuilderWithMockBackend() *Builder { Options: &types.ImageBuildOptions{Platform: runtime.GOOS}, Backend: mockBackend, }), - imageProber: newImageProber(mockBackend, nil, runtime.GOOS, false), + imageProber: newImageProber(mockBackend, nil, false), containerManager: newContainerManager(mockBackend), } return b @@ -427,10 +427,10 @@ func TestRunWithBuildArgs(t *testing.T) { } mockBackend := b.docker.(*MockBackend) - mockBackend.makeImageCacheFunc = func(_ []string, _ string) builder.ImageCache { + mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache { return imageCache } - b.imageProber = newImageProber(mockBackend, nil, runtime.GOOS, false) + b.imageProber = newImageProber(mockBackend, nil, false) mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ReleaseableLayer, error) { return &mockImage{ id: "abcdef", diff --git a/vendor/github.com/docker/docker/builder/dockerfile/errors.go b/vendor/github.com/docker/docker/builder/dockerfile/errors.go deleted file mode 100644 index 25664dee7..000000000 --- a/vendor/github.com/docker/docker/builder/dockerfile/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -package dockerfile - -type validationError struct { - err error -} - -func (e validationError) Error() string { - return e.err.Error() -} - -func (e validationError) InvalidParameter() {} - -func (e validationError) Cause() error { - return e.err -} diff --git a/vendor/github.com/docker/docker/builder/dockerfile/evaluator.go b/vendor/github.com/docker/docker/builder/dockerfile/evaluator.go index 6236a194d..f60869d7c 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/evaluator.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/evaluator.go @@ -21,12 +21,14 @@ package dockerfile import ( "reflect" + "runtime" "strconv" "strings" "github.com/docker/docker/api/types/container" "github.com/docker/docker/builder" "github.com/docker/docker/builder/dockerfile/instructions" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/system" "github.com/docker/docker/runconfig/opts" "github.com/pkg/errors" @@ -37,7 +39,7 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) { optionsOS := system.ParsePlatform(d.builder.options.Platform).OS err := c.CheckPlatform(optionsOS) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } } runConfigEnv := d.state.runConfig.Env @@ -48,7 +50,7 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) { return d.shlex.ProcessWord(word, envs) }) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } } @@ -103,13 +105,14 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) { // dispatchState is a data object which is modified by dispatchers type dispatchState struct { - runConfig *container.Config - maintainer string - cmdSet bool - imageID string - baseImage builder.Image - stageName string - buildArgs *buildArgs + runConfig *container.Config + maintainer string + cmdSet bool + imageID string + baseImage builder.Image + stageName string + buildArgs *buildArgs + operatingSystem string } func newDispatchState(baseArgs *buildArgs) *dispatchState { @@ -209,9 +212,16 @@ func (s *dispatchState) hasFromImage() bool { return s.imageID != "" || (s.baseImage != nil && s.baseImage.ImageID() == "") } -func (s *dispatchState) beginStage(stageName string, image builder.Image) { +func (s *dispatchState) beginStage(stageName string, image builder.Image) error { s.stageName = stageName s.imageID = image.ImageID() + s.operatingSystem = image.OperatingSystem() + if s.operatingSystem == "" { // In case it isn't set + s.operatingSystem = runtime.GOOS + } + if !system.IsOSSupported(s.operatingSystem) { + return system.ErrNotSupportedOperatingSystem + } if image.RunConfig() != nil { // copy avoids referencing the same instance when 2 stages have the same base @@ -223,12 +233,13 @@ func (s *dispatchState) beginStage(stageName string, image builder.Image) { s.setDefaultPath() s.runConfig.OpenStdin = false s.runConfig.StdinOnce = false + return nil } // Add the default PATH to runConfig.ENV if one exists for the operating system and there // is no PATH set. Note that Windows containers on Windows won't have one as it's set by HCS func (s *dispatchState) setDefaultPath() { - defaultPath := system.DefaultPathEnv(s.baseImage.OperatingSystem()) + defaultPath := system.DefaultPathEnv(s.operatingSystem) if defaultPath == "" { return } diff --git a/vendor/github.com/docker/docker/builder/dockerfile/imageprobe.go b/vendor/github.com/docker/docker/builder/dockerfile/imageprobe.go index 239eb9e38..1a6df6938 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/imageprobe.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/imageprobe.go @@ -19,13 +19,13 @@ type imageProber struct { cacheBusted bool } -func newImageProber(cacheBuilder builder.ImageCacheBuilder, cacheFrom []string, platform string, noCache bool) ImageProber { +func newImageProber(cacheBuilder builder.ImageCacheBuilder, cacheFrom []string, noCache bool) ImageProber { if noCache { return &nopProber{} } reset := func() builder.ImageCache { - return cacheBuilder.MakeImageCache(cacheFrom, platform) + return cacheBuilder.MakeImageCache(cacheFrom) } return &imageProber{cache: reset(), reset: reset} } diff --git a/vendor/github.com/docker/docker/builder/dockerfile/internals.go b/vendor/github.com/docker/docker/builder/dockerfile/internals.go index c38f48afc..5ce5f8974 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/internals.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/internals.go @@ -11,7 +11,7 @@ import ( "os" "path" "path/filepath" - "strconv" + "runtime" "strings" "github.com/docker/docker/api/types" @@ -23,10 +23,8 @@ import ( "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/pkg/symlink" "github.com/docker/docker/pkg/system" "github.com/docker/go-connections/nat" - lcUser "github.com/opencontainers/runc/libcontainer/user" "github.com/pkg/errors" ) @@ -124,8 +122,7 @@ func (b *Builder) commitContainer(dispatchState *dispatchState, id string, conta } func (b *Builder) exportImage(state *dispatchState, imageMount *imageMount, runConfig *container.Config) error { - optionsPlatform := system.ParsePlatform(b.options.Platform) - newLayer, err := imageMount.Layer().Commit(optionsPlatform.OS) + newLayer, err := imageMount.Layer().Commit() if err != nil { return err } @@ -153,7 +150,7 @@ func (b *Builder) exportImage(state *dispatchState, imageMount *imageMount, runC return errors.Wrap(err, "failed to encode image config") } - exportedImage, err := b.docker.CreateImage(config, state.imageID, parentImage.OS) + exportedImage, err := b.docker.CreateImage(config, state.imageID) if err != nil { return errors.Wrapf(err, "failed to export image") } @@ -216,82 +213,6 @@ func (b *Builder) performCopy(state *dispatchState, inst copyInstruction) error return b.exportImage(state, imageMount, runConfigWithCommentCmd) } -func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) { - var userStr, grpStr string - parts := strings.Split(chown, ":") - if len(parts) > 2 { - return idtools.IDPair{}, errors.New("invalid chown string format: " + chown) - } - if len(parts) == 1 { - // if no group specified, use the user spec as group as well - userStr, grpStr = parts[0], parts[0] - } else { - userStr, grpStr = parts[0], parts[1] - } - - passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath) - if err != nil { - return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs") - } - groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath) - if err != nil { - return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs") - } - uid, err := lookupUser(userStr, passwdPath) - if err != nil { - return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr) - } - gid, err := lookupGroup(grpStr, groupPath) - if err != nil { - return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr) - } - - // convert as necessary because of user namespaces - chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid}) - if err != nil { - return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping") - } - return chownPair, nil -} - -func lookupUser(userStr, filepath string) (int, error) { - // if the string is actually a uid integer, parse to int and return - // as we don't need to translate with the help of files - uid, err := strconv.Atoi(userStr) - if err == nil { - return uid, nil - } - users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool { - return u.Name == userStr - }) - if err != nil { - return 0, err - } - if len(users) == 0 { - return 0, errors.New("no such user: " + userStr) - } - return users[0].Uid, nil -} - -func lookupGroup(groupStr, filepath string) (int, error) { - // if the string is actually a gid integer, parse to int and return - // as we don't need to translate with the help of files - gid, err := strconv.Atoi(groupStr) - if err == nil { - return gid, nil - } - groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool { - return g.Name == groupStr - }) - if err != nil { - return 0, err - } - if len(groups) == 0 { - return 0, errors.New("no such group: " + groupStr) - } - return groups[0].Gid, nil -} - func createDestInfo(workingDir string, inst copyInstruction, imageMount *imageMount, platform string) (copyInfo, error) { // Twiddle the destination when it's a relative path - meaning, make it // relative to the WORKINGDIR @@ -501,15 +422,13 @@ func (b *Builder) probeAndCreate(dispatchState *dispatchState, runConfig *contai } // Set a log config to override any default value set on the daemon hostConfig := &container.HostConfig{LogConfig: defaultLogConfig} - optionsPlatform := system.ParsePlatform(b.options.Platform) - container, err := b.containerManager.Create(runConfig, hostConfig, optionsPlatform.OS) + container, err := b.containerManager.Create(runConfig, hostConfig) return container.ID, err } func (b *Builder) create(runConfig *container.Config) (string, error) { hostConfig := hostConfigFromOptions(b.options) - optionsPlatform := system.ParsePlatform(b.options.Platform) - container, err := b.containerManager.Create(runConfig, hostConfig, optionsPlatform.OS) + container, err := b.containerManager.Create(runConfig, hostConfig) if err != nil { return "", err } @@ -534,7 +453,7 @@ func hostConfigFromOptions(options *types.ImageBuildOptions) *container.HostConf Ulimits: options.Ulimits, } - return &container.HostConfig{ + hc := &container.HostConfig{ SecurityOpt: options.SecurityOpt, Isolation: options.Isolation, ShmSize: options.ShmSize, @@ -544,6 +463,17 @@ func hostConfigFromOptions(options *types.ImageBuildOptions) *container.HostConf LogConfig: defaultLogConfig, ExtraHosts: options.ExtraHosts, } + + // For WCOW, the default of 20GB hard-coded in the platform + // is too small for builder scenarios where many users are + // using RUN statements to install large amounts of data. + // Use 127GB as that's the default size of a VHD in Hyper-V. + if runtime.GOOS == "windows" && options.Platform == "windows" { + hc.StorageOpt = make(map[string]string) + hc.StorageOpt["size"] = "127GB" + } + + return hc } // fromSlash works like filepath.FromSlash but with a given OS platform field diff --git a/vendor/github.com/docker/docker/builder/dockerfile/internals_linux.go b/vendor/github.com/docker/docker/builder/dockerfile/internals_linux.go new file mode 100644 index 000000000..131477924 --- /dev/null +++ b/vendor/github.com/docker/docker/builder/dockerfile/internals_linux.go @@ -0,0 +1,88 @@ +package dockerfile + +import ( + "path/filepath" + "strconv" + "strings" + + "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/symlink" + lcUser "github.com/opencontainers/runc/libcontainer/user" + "github.com/pkg/errors" +) + +func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) { + var userStr, grpStr string + parts := strings.Split(chown, ":") + if len(parts) > 2 { + return idtools.IDPair{}, errors.New("invalid chown string format: " + chown) + } + if len(parts) == 1 { + // if no group specified, use the user spec as group as well + userStr, grpStr = parts[0], parts[0] + } else { + userStr, grpStr = parts[0], parts[1] + } + + passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath) + if err != nil { + return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs") + } + groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath) + if err != nil { + return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs") + } + uid, err := lookupUser(userStr, passwdPath) + if err != nil { + return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr) + } + gid, err := lookupGroup(grpStr, groupPath) + if err != nil { + return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr) + } + + // convert as necessary because of user namespaces + chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid}) + if err != nil { + return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping") + } + return chownPair, nil +} + +func lookupUser(userStr, filepath string) (int, error) { + // if the string is actually a uid integer, parse to int and return + // as we don't need to translate with the help of files + uid, err := strconv.Atoi(userStr) + if err == nil { + return uid, nil + } + users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool { + return u.Name == userStr + }) + if err != nil { + return 0, err + } + if len(users) == 0 { + return 0, errors.New("no such user: " + userStr) + } + return users[0].Uid, nil +} + +func lookupGroup(groupStr, filepath string) (int, error) { + // if the string is actually a gid integer, parse to int and return + // as we don't need to translate with the help of files + gid, err := strconv.Atoi(groupStr) + if err == nil { + return gid, nil + } + groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool { + return g.Name == groupStr + }) + if err != nil { + return 0, err + } + if len(groups) == 0 { + return 0, errors.New("no such group: " + groupStr) + } + return groups[0].Gid, nil +} diff --git a/vendor/github.com/docker/docker/builder/dockerfile/internals_linux_test.go b/vendor/github.com/docker/docker/builder/dockerfile/internals_linux_test.go new file mode 100644 index 000000000..dd23a3330 --- /dev/null +++ b/vendor/github.com/docker/docker/builder/dockerfile/internals_linux_test.go @@ -0,0 +1,138 @@ +package dockerfile + +import ( + "os" + "path/filepath" + "testing" + + "github.com/docker/docker/pkg/idtools" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestChownFlagParsing(t *testing.T) { + testFiles := map[string]string{ + "passwd": `root:x:0:0::/bin:/bin/false +bin:x:1:1::/bin:/bin/false +wwwwww:x:21:33::/bin:/bin/false +unicorn:x:1001:1002::/bin:/bin/false + `, + "group": `root:x:0: +bin:x:1: +wwwwww:x:33: +unicorn:x:1002: +somegrp:x:5555: +othergrp:x:6666: + `, + } + // test mappings for validating use of maps + idMaps := []idtools.IDMap{ + { + ContainerID: 0, + HostID: 100000, + Size: 65536, + }, + } + remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps) + unmapped := &idtools.IDMappings{} + + contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test") + defer cleanup() + + if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil { + t.Fatalf("error creating test directory: %v", err) + } + + for filename, content := range testFiles { + createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644) + } + + // positive tests + for _, testcase := range []struct { + name string + chownStr string + idMapping *idtools.IDMappings + expected idtools.IDPair + }{ + { + name: "UIDNoMap", + chownStr: "1", + idMapping: unmapped, + expected: idtools.IDPair{UID: 1, GID: 1}, + }, + { + name: "UIDGIDNoMap", + chownStr: "0:1", + idMapping: unmapped, + expected: idtools.IDPair{UID: 0, GID: 1}, + }, + { + name: "UIDWithMap", + chownStr: "0", + idMapping: remapped, + expected: idtools.IDPair{UID: 100000, GID: 100000}, + }, + { + name: "UIDGIDWithMap", + chownStr: "1:33", + idMapping: remapped, + expected: idtools.IDPair{UID: 100001, GID: 100033}, + }, + { + name: "UserNoMap", + chownStr: "bin:5555", + idMapping: unmapped, + expected: idtools.IDPair{UID: 1, GID: 5555}, + }, + { + name: "GroupWithMap", + chownStr: "0:unicorn", + idMapping: remapped, + expected: idtools.IDPair{UID: 100000, GID: 101002}, + }, + { + name: "UserOnlyWithMap", + chownStr: "unicorn", + idMapping: remapped, + expected: idtools.IDPair{UID: 101001, GID: 101002}, + }, + } { + t.Run(testcase.name, func(t *testing.T) { + idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) + require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr) + assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure") + }) + } + + // error tests + for _, testcase := range []struct { + name string + chownStr string + idMapping *idtools.IDMappings + descr string + }{ + { + name: "BadChownFlagFormat", + chownStr: "bob:1:555", + idMapping: unmapped, + descr: "invalid chown string format: bob:1:555", + }, + { + name: "UserNoExist", + chownStr: "bob", + idMapping: unmapped, + descr: "can't find uid for user bob: no such user: bob", + }, + { + name: "GroupNoExist", + chownStr: "root:bob", + idMapping: unmapped, + descr: "can't find gid for group bob: no such group: bob", + }, + } { + t.Run(testcase.name, func(t *testing.T) { + _, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) + assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match") + }) + } +} diff --git a/vendor/github.com/docker/docker/builder/dockerfile/internals_test.go b/vendor/github.com/docker/docker/builder/dockerfile/internals_test.go index 83a207c45..04c8c4bac 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/internals_test.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/internals_test.go @@ -2,8 +2,6 @@ package dockerfile import ( "fmt" - "os" - "path/filepath" "runtime" "testing" @@ -13,7 +11,6 @@ import ( "github.com/docker/docker/builder" "github.com/docker/docker/builder/remotecontext" "github.com/docker/docker/pkg/archive" - "github.com/docker/docker/pkg/idtools" "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -171,130 +168,3 @@ func TestDeepCopyRunConfig(t *testing.T) { copy.Shell[0] = "sh" assert.Equal(t, fullMutableRunConfig(), runConfig) } - -func TestChownFlagParsing(t *testing.T) { - testFiles := map[string]string{ - "passwd": `root:x:0:0::/bin:/bin/false -bin:x:1:1::/bin:/bin/false -wwwwww:x:21:33::/bin:/bin/false -unicorn:x:1001:1002::/bin:/bin/false - `, - "group": `root:x:0: -bin:x:1: -wwwwww:x:33: -unicorn:x:1002: -somegrp:x:5555: -othergrp:x:6666: - `, - } - // test mappings for validating use of maps - idMaps := []idtools.IDMap{ - { - ContainerID: 0, - HostID: 100000, - Size: 65536, - }, - } - remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps) - unmapped := &idtools.IDMappings{} - - contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test") - defer cleanup() - - if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil { - t.Fatalf("error creating test directory: %v", err) - } - - for filename, content := range testFiles { - createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644) - } - - // positive tests - for _, testcase := range []struct { - name string - chownStr string - idMapping *idtools.IDMappings - expected idtools.IDPair - }{ - { - name: "UIDNoMap", - chownStr: "1", - idMapping: unmapped, - expected: idtools.IDPair{UID: 1, GID: 1}, - }, - { - name: "UIDGIDNoMap", - chownStr: "0:1", - idMapping: unmapped, - expected: idtools.IDPair{UID: 0, GID: 1}, - }, - { - name: "UIDWithMap", - chownStr: "0", - idMapping: remapped, - expected: idtools.IDPair{UID: 100000, GID: 100000}, - }, - { - name: "UIDGIDWithMap", - chownStr: "1:33", - idMapping: remapped, - expected: idtools.IDPair{UID: 100001, GID: 100033}, - }, - { - name: "UserNoMap", - chownStr: "bin:5555", - idMapping: unmapped, - expected: idtools.IDPair{UID: 1, GID: 5555}, - }, - { - name: "GroupWithMap", - chownStr: "0:unicorn", - idMapping: remapped, - expected: idtools.IDPair{UID: 100000, GID: 101002}, - }, - { - name: "UserOnlyWithMap", - chownStr: "unicorn", - idMapping: remapped, - expected: idtools.IDPair{UID: 101001, GID: 101002}, - }, - } { - t.Run(testcase.name, func(t *testing.T) { - idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) - require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr) - assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure") - }) - } - - // error tests - for _, testcase := range []struct { - name string - chownStr string - idMapping *idtools.IDMappings - descr string - }{ - { - name: "BadChownFlagFormat", - chownStr: "bob:1:555", - idMapping: unmapped, - descr: "invalid chown string format: bob:1:555", - }, - { - name: "UserNoExist", - chownStr: "bob", - idMapping: unmapped, - descr: "can't find uid for user bob: no such user: bob", - }, - { - name: "GroupNoExist", - chownStr: "root:bob", - idMapping: unmapped, - descr: "can't find gid for group bob: no such group: bob", - }, - } { - t.Run(testcase.name, func(t *testing.T) { - _, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping) - assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match") - }) - } -} diff --git a/vendor/github.com/docker/docker/builder/dockerfile/internals_windows.go b/vendor/github.com/docker/docker/builder/dockerfile/internals_windows.go new file mode 100644 index 000000000..931df2f02 --- /dev/null +++ b/vendor/github.com/docker/docker/builder/dockerfile/internals_windows.go @@ -0,0 +1,7 @@ +package dockerfile + +import "github.com/docker/docker/pkg/idtools" + +func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) { + return idMappings.RootPair(), nil +} diff --git a/vendor/github.com/docker/docker/builder/dockerfile/mockbackend_test.go b/vendor/github.com/docker/docker/builder/dockerfile/mockbackend_test.go index 986861cbb..6c19f17eb 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/mockbackend_test.go +++ b/vendor/github.com/docker/docker/builder/dockerfile/mockbackend_test.go @@ -20,7 +20,7 @@ type MockBackend struct { containerCreateFunc func(config types.ContainerCreateConfig) (container.ContainerCreateCreatedBody, error) commitFunc func(string, *backend.ContainerCommitConfig) (string, error) getImageFunc func(string) (builder.Image, builder.ReleaseableLayer, error) - makeImageCacheFunc func(cacheFrom []string, platform string) builder.ImageCache + makeImageCacheFunc func(cacheFrom []string) builder.ImageCache } func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error { @@ -73,14 +73,14 @@ func (m *MockBackend) GetImageAndReleasableLayer(ctx context.Context, refOrID st return &mockImage{id: "theid"}, &mockLayer{}, nil } -func (m *MockBackend) MakeImageCache(cacheFrom []string, platform string) builder.ImageCache { +func (m *MockBackend) MakeImageCache(cacheFrom []string) builder.ImageCache { if m.makeImageCacheFunc != nil { - return m.makeImageCacheFunc(cacheFrom, platform) + return m.makeImageCacheFunc(cacheFrom) } return nil } -func (m *MockBackend) CreateImage(config []byte, parent string, platform string) (builder.Image, error) { +func (m *MockBackend) CreateImage(config []byte, parent string) (builder.Image, error) { return nil, nil } @@ -127,7 +127,7 @@ func (l *mockLayer) Mount() (containerfs.ContainerFS, error) { return containerfs.NewLocalContainerFS("mountPath"), nil } -func (l *mockLayer) Commit(string) (builder.ReleaseableLayer, error) { +func (l *mockLayer) Commit() (builder.ReleaseableLayer, error) { return nil, nil } diff --git a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/docker/Dockerfile b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/docker/Dockerfile index 5153453ff..77aecd9ba 100644 --- a/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/docker/Dockerfile +++ b/vendor/github.com/docker/docker/builder/dockerfile/parser/testfiles/docker/Dockerfile @@ -9,7 +9,7 @@ # docker run -v `pwd`:/go/src/github.com/docker/docker --privileged -i -t docker bash # # # Run the test suite: -# docker run --privileged docker hack/make.sh test-unit test-integration-cli test-docker-py +# docker run --privileged docker hack/make.sh test-unit test-integration test-docker-py # # # Publish a release: # docker run --privileged \ diff --git a/vendor/github.com/docker/docker/builder/fscache/fscache.go b/vendor/github.com/docker/docker/builder/fscache/fscache.go index 7cb4c5cbe..679d5e457 100644 --- a/vendor/github.com/docker/docker/builder/fscache/fscache.go +++ b/vendor/github.com/docker/docker/builder/fscache/fscache.go @@ -485,10 +485,7 @@ func (s *fsCacheStore) delete(id string) error { }); err != nil { return err } - if err := s.fs.Remove(src.BackendID); err != nil { - return err - } - return nil + return s.fs.Remove(src.BackendID) } type sourceMeta struct { diff --git a/vendor/github.com/docker/docker/builder/remotecontext/errors.go b/vendor/github.com/docker/docker/builder/remotecontext/errors.go deleted file mode 100644 index 8ee33bc60..000000000 --- a/vendor/github.com/docker/docker/builder/remotecontext/errors.go +++ /dev/null @@ -1,75 +0,0 @@ -package remotecontext - -type notFoundError string - -func (e notFoundError) Error() string { - return string(e) -} - -func (notFoundError) NotFound() {} - -type requestError string - -func (e requestError) Error() string { - return string(e) -} - -func (e requestError) InvalidParameter() {} - -type unauthorizedError string - -func (e unauthorizedError) Error() string { - return string(e) -} - -func (unauthorizedError) Unauthorized() {} - -type forbiddenError string - -func (e forbiddenError) Error() string { - return string(e) -} - -func (forbiddenError) Forbidden() {} - -type dnsError struct { - cause error -} - -func (e dnsError) Error() string { - return e.cause.Error() -} - -func (e dnsError) NotFound() {} - -func (e dnsError) Cause() error { - return e.cause -} - -type systemError struct { - cause error -} - -func (e systemError) Error() string { - return e.cause.Error() -} - -func (e systemError) SystemError() {} - -func (e systemError) Cause() error { - return e.cause -} - -type unknownError struct { - cause error -} - -func (e unknownError) Error() string { - return e.cause.Error() -} - -func (unknownError) Unknown() {} - -func (e unknownError) Cause() error { - return e.cause -} diff --git a/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils.go b/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils.go index 7bc226815..67cff594a 100644 --- a/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils.go +++ b/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils.go @@ -29,6 +29,10 @@ func Clone(remoteURL string) (string, error) { return "", err } + return cloneGitRepo(repo) +} + +func cloneGitRepo(repo gitRepo) (checkoutDir string, err error) { fetch := fetchArgs(repo.remote, repo.ref) root, err := ioutil.TempDir("", "docker-build-git") @@ -36,6 +40,12 @@ func Clone(remoteURL string) (string, error) { return "", err } + defer func() { + if err != nil { + os.RemoveAll(root) + } + }() + if out, err := gitWithinDir(root, "init"); err != nil { return "", errors.Wrapf(err, "failed to init repo at %s: %s", root, out) } @@ -50,7 +60,19 @@ func Clone(remoteURL string) (string, error) { return "", errors.Wrapf(err, "error fetching: %s", output) } - return checkoutGit(root, repo.ref, repo.subdir) + checkoutDir, err = checkoutGit(root, repo.ref, repo.subdir) + if err != nil { + return "", err + } + + cmd := exec.Command("git", "submodule", "update", "--init", "--recursive", "--depth=1") + cmd.Dir = root + output, err := cmd.CombinedOutput() + if err != nil { + return "", errors.Wrapf(err, "error initializing submodules: %s", output) + } + + return checkoutDir, nil } func parseRemoteURL(remoteURL string) (gitRepo, error) { @@ -96,7 +118,7 @@ func getRefAndSubdir(fragment string) (ref string, subdir string) { } func fetchArgs(remoteURL string, ref string) []string { - args := []string{"fetch", "--recurse-submodules=yes"} + args := []string{"fetch"} if supportsShallowClone(remoteURL) { args = append(args, "--depth", "1") diff --git a/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils_test.go b/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils_test.go index c638a498f..fd58d6bd9 100644 --- a/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils_test.go +++ b/vendor/github.com/docker/docker/builder/remotecontext/git/gitutils_test.go @@ -7,6 +7,7 @@ import ( "net/http/httptest" "net/url" "os" + "os/exec" "path/filepath" "runtime" "strings" @@ -61,7 +62,7 @@ func TestCloneArgsSmartHttp(t *testing.T) { }) args := fetchArgs(serverURL.String(), "master") - exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"} + exp := []string{"fetch", "--depth", "1", "origin", "master"} assert.Equal(t, exp, args) } @@ -77,13 +78,13 @@ func TestCloneArgsDumbHttp(t *testing.T) { }) args := fetchArgs(serverURL.String(), "master") - exp := []string{"fetch", "--recurse-submodules=yes", "origin", "master"} + exp := []string{"fetch", "origin", "master"} assert.Equal(t, exp, args) } func TestCloneArgsGit(t *testing.T) { args := fetchArgs("git://github.com/docker/docker", "master") - exp := []string{"fetch", "--recurse-submodules=yes", "--depth", "1", "origin", "master"} + exp := []string{"fetch", "--depth", "1", "origin", "master"} assert.Equal(t, exp, args) } @@ -165,24 +166,55 @@ func TestCheckoutGit(t *testing.T) { _, err = gitWithinDir(gitDir, "checkout", "master") require.NoError(t, err) + // set up submodule + subrepoDir := filepath.Join(root, "subrepo") + _, err = git("init", subrepoDir) + require.NoError(t, err) + + _, err = gitWithinDir(subrepoDir, "config", "user.email", "test@docker.com") + require.NoError(t, err) + + _, err = gitWithinDir(subrepoDir, "config", "user.name", "Docker test") + require.NoError(t, err) + + err = ioutil.WriteFile(filepath.Join(subrepoDir, "subfile"), []byte("subcontents"), 0644) + require.NoError(t, err) + + _, err = gitWithinDir(subrepoDir, "add", "-A") + require.NoError(t, err) + + _, err = gitWithinDir(subrepoDir, "commit", "-am", "Subrepo initial") + require.NoError(t, err) + + cmd := exec.Command("git", "submodule", "add", subrepoDir, "sub") // this command doesn't work with --work-tree + cmd.Dir = gitDir + require.NoError(t, cmd.Run()) + + _, err = gitWithinDir(gitDir, "add", "-A") + require.NoError(t, err) + + _, err = gitWithinDir(gitDir, "commit", "-am", "With submodule") + require.NoError(t, err) + type singleCase struct { - frag string - exp string - fail bool + frag string + exp string + fail bool + submodule bool } cases := []singleCase{ - {"", "FROM scratch", false}, - {"master", "FROM scratch", false}, - {":subdir", "FROM scratch" + eol + "EXPOSE 5000", false}, - {":nosubdir", "", true}, // missing directory error - {":Dockerfile", "", true}, // not a directory error - {"master:nosubdir", "", true}, - {"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false}, - {"master:../subdir", "", true}, - {"test", "FROM scratch" + eol + "EXPOSE 3000", false}, - {"test:", "FROM scratch" + eol + "EXPOSE 3000", false}, - {"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false}, + {"", "FROM scratch", false, true}, + {"master", "FROM scratch", false, true}, + {":subdir", "FROM scratch" + eol + "EXPOSE 5000", false, false}, + {":nosubdir", "", true, false}, // missing directory error + {":Dockerfile", "", true, false}, // not a directory error + {"master:nosubdir", "", true, false}, + {"master:subdir", "FROM scratch" + eol + "EXPOSE 5000", false, false}, + {"master:../subdir", "", true, false}, + {"test", "FROM scratch" + eol + "EXPOSE 3000", false, false}, + {"test:", "FROM scratch" + eol + "EXPOSE 3000", false, false}, + {"test:subdir", "FROM busybox" + eol + "EXPOSE 5000", false, false}, } if runtime.GOOS != "windows" { @@ -197,12 +229,23 @@ func TestCheckoutGit(t *testing.T) { for _, c := range cases { ref, subdir := getRefAndSubdir(c.frag) - r, err := checkoutGit(gitDir, ref, subdir) + r, err := cloneGitRepo(gitRepo{remote: gitDir, ref: ref, subdir: subdir}) if c.fail { assert.Error(t, err) continue } + require.NoError(t, err) + defer os.RemoveAll(r) + if c.submodule { + b, err := ioutil.ReadFile(filepath.Join(r, "sub/subfile")) + require.NoError(t, err) + assert.Equal(t, "subcontents", string(b)) + } else { + _, err := os.Stat(filepath.Join(r, "sub/subfile")) + require.Error(t, err) + require.True(t, os.IsNotExist(err)) + } b, err := ioutil.ReadFile(filepath.Join(r, "Dockerfile")) require.NoError(t, err) diff --git a/vendor/github.com/docker/docker/builder/remotecontext/remote.go b/vendor/github.com/docker/docker/builder/remotecontext/remote.go index ee0282f70..b67914cc1 100644 --- a/vendor/github.com/docker/docker/builder/remotecontext/remote.go +++ b/vendor/github.com/docker/docker/builder/remotecontext/remote.go @@ -10,6 +10,7 @@ import ( "net/url" "regexp" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/ioutils" "github.com/pkg/errors" ) @@ -26,7 +27,7 @@ var mimeRe = regexp.MustCompile(acceptableRemoteMIME) func downloadRemote(remoteURL string) (string, io.ReadCloser, error) { response, err := GetWithStatusError(remoteURL) if err != nil { - return "", nil, fmt.Errorf("error downloading remote context %s: %v", remoteURL, err) + return "", nil, errors.Wrapf(err, "error downloading remote context %s", remoteURL) } contentType, contextReader, err := inspectResponse( @@ -35,7 +36,7 @@ func downloadRemote(remoteURL string) (string, io.ReadCloser, error) { response.ContentLength) if err != nil { response.Body.Close() - return "", nil, fmt.Errorf("error detecting content type for remote %s: %v", remoteURL, err) + return "", nil, errors.Wrapf(err, "error detecting content type for remote %s", remoteURL) } return contentType, ioutils.NewReadCloserWrapper(contextReader, response.Body.Close), nil @@ -47,10 +48,10 @@ func GetWithStatusError(address string) (resp *http.Response, err error) { if resp, err = http.Get(address); err != nil { if uerr, ok := err.(*url.Error); ok { if derr, ok := uerr.Err.(*net.DNSError); ok && !derr.IsTimeout { - return nil, dnsError{err} + return nil, errdefs.NotFound(err) } } - return nil, systemError{err} + return nil, errdefs.System(err) } if resp.StatusCode < 400 { return resp, nil @@ -59,21 +60,21 @@ func GetWithStatusError(address string) (resp *http.Response, err error) { body, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { - return nil, errors.Wrap(systemError{err}, msg+": error reading body") + return nil, errdefs.System(errors.New(msg + ": error reading body")) } msg += ": " + string(bytes.TrimSpace(body)) switch resp.StatusCode { case http.StatusNotFound: - return nil, notFoundError(msg) + return nil, errdefs.NotFound(errors.New(msg)) case http.StatusBadRequest: - return nil, requestError(msg) + return nil, errdefs.InvalidParameter(errors.New(msg)) case http.StatusUnauthorized: - return nil, unauthorizedError(msg) + return nil, errdefs.Unauthorized(errors.New(msg)) case http.StatusForbidden: - return nil, forbiddenError(msg) + return nil, errdefs.Forbidden(errors.New(msg)) } - return nil, unknownError{errors.New(msg)} + return nil, errdefs.Unknown(errors.New(msg)) } // inspectResponse looks into the http response data at r to determine whether its diff --git a/vendor/github.com/docker/docker/client/container_copy.go b/vendor/github.com/docker/docker/client/container_copy.go index 30ba6803f..b7d5252ab 100644 --- a/vendor/github.com/docker/docker/client/container_copy.go +++ b/vendor/github.com/docker/docker/client/container_copy.go @@ -30,7 +30,7 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri } // CopyToContainer copies content into the container filesystem. -// Note that `content` must be a Reader for a TAR +// Note that `content` must be a Reader for a TAR archive func (cli *Client) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error { query := url.Values{} query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. @@ -59,7 +59,7 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string, } // CopyFromContainer gets the content from the container and returns it as a Reader -// to manipulate it in the host. It's up to the caller to close the reader. +// for a TAR archive to manipulate it in the host. It's up to the caller to close the reader. func (cli *Client) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) { query := make(url.Values, 1) query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. diff --git a/vendor/github.com/docker/docker/client/container_logs.go b/vendor/github.com/docker/docker/client/container_logs.go index 35c297c5f..562c8b4bc 100644 --- a/vendor/github.com/docker/docker/client/container_logs.go +++ b/vendor/github.com/docker/docker/client/container_logs.go @@ -74,7 +74,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) if err != nil { - return nil, err + return nil, wrapResponseError(err, resp, "container", container) } return resp.body, nil } diff --git a/vendor/github.com/docker/docker/client/container_logs_test.go b/vendor/github.com/docker/docker/client/container_logs_test.go index 8cb763512..41849cf57 100644 --- a/vendor/github.com/docker/docker/client/container_logs_test.go +++ b/vendor/github.com/docker/docker/client/container_logs_test.go @@ -18,6 +18,16 @@ import ( "golang.org/x/net/context" ) +func TestContainerLogsNotFoundError(t *testing.T) { + client := &Client{ + client: newMockClient(errorMock(http.StatusNotFound, "Not found")), + } + _, err := client.ContainerLogs(context.Background(), "container_id", types.ContainerLogsOptions{}) + if !IsErrNotFound(err) { + t.Fatalf("expected a not found error, got %v", err) + } +} + func TestContainerLogsError(t *testing.T) { client := &Client{ client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), diff --git a/vendor/github.com/docker/docker/client/interface.go b/vendor/github.com/docker/docker/client/interface.go index dd8b388cf..9fb8194fe 100644 --- a/vendor/github.com/docker/docker/client/interface.go +++ b/vendor/github.com/docker/docker/client/interface.go @@ -6,11 +6,11 @@ import ( "time" "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" + containertypes "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/image" - "github.com/docker/docker/api/types/network" + networktypes "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/swarm" volumetypes "github.com/docker/docker/api/types/volume" @@ -43,8 +43,8 @@ type CommonAPIClient interface { type ContainerAPIClient interface { ContainerAttach(ctx context.Context, container string, options types.ContainerAttachOptions) (types.HijackedResponse, error) ContainerCommit(ctx context.Context, container string, options types.ContainerCommitOptions) (types.IDResponse, error) - ContainerCreate(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, containerName string) (container.ContainerCreateCreatedBody, error) - ContainerDiff(ctx context.Context, container string) ([]container.ContainerChangeResponseItem, error) + ContainerCreate(ctx context.Context, config *containertypes.Config, hostConfig *containertypes.HostConfig, networkingConfig *networktypes.NetworkingConfig, containerName string) (containertypes.ContainerCreateCreatedBody, error) + ContainerDiff(ctx context.Context, container string) ([]containertypes.ContainerChangeResponseItem, error) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (types.IDResponse, error) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) @@ -65,10 +65,10 @@ type ContainerAPIClient interface { ContainerStats(ctx context.Context, container string, stream bool) (types.ContainerStats, error) ContainerStart(ctx context.Context, container string, options types.ContainerStartOptions) error ContainerStop(ctx context.Context, container string, timeout *time.Duration) error - ContainerTop(ctx context.Context, container string, arguments []string) (container.ContainerTopOKBody, error) + ContainerTop(ctx context.Context, container string, arguments []string) (containertypes.ContainerTopOKBody, error) ContainerUnpause(ctx context.Context, container string) error - ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) - ContainerWait(ctx context.Context, container string, condition container.WaitCondition) (<-chan container.ContainerWaitOKBody, <-chan error) + ContainerUpdate(ctx context.Context, container string, updateConfig containertypes.UpdateConfig) (containertypes.ContainerUpdateOKBody, error) + ContainerWait(ctx context.Context, container string, condition containertypes.WaitCondition) (<-chan containertypes.ContainerWaitOKBody, <-chan error) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error ContainersPrune(ctx context.Context, pruneFilters filters.Args) (types.ContainersPruneReport, error) @@ -100,13 +100,13 @@ type ImageAPIClient interface { // NetworkAPIClient defines API client methods for the networks type NetworkAPIClient interface { - NetworkConnect(ctx context.Context, networkID, container string, config *network.EndpointSettings) error + NetworkConnect(ctx context.Context, network, container string, config *networktypes.EndpointSettings) error NetworkCreate(ctx context.Context, name string, options types.NetworkCreate) (types.NetworkCreateResponse, error) - NetworkDisconnect(ctx context.Context, networkID, container string, force bool) error - NetworkInspect(ctx context.Context, networkID string, options types.NetworkInspectOptions) (types.NetworkResource, error) - NetworkInspectWithRaw(ctx context.Context, networkID string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) + NetworkDisconnect(ctx context.Context, network, container string, force bool) error + NetworkInspect(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, error) + NetworkInspectWithRaw(ctx context.Context, network string, options types.NetworkInspectOptions) (types.NetworkResource, []byte, error) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) - NetworkRemove(ctx context.Context, networkID string) error + NetworkRemove(ctx context.Context, network string) error NetworksPrune(ctx context.Context, pruneFilter filters.Args) (types.NetworksPruneReport, error) } diff --git a/vendor/github.com/docker/docker/cmd/dockerd/config.go b/vendor/github.com/docker/docker/cmd/dockerd/config.go index b9d586a4b..c55332e18 100644 --- a/vendor/github.com/docker/docker/cmd/dockerd/config.go +++ b/vendor/github.com/docker/docker/cmd/dockerd/config.go @@ -59,13 +59,15 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) { flags.IntVar(&maxConcurrentDownloads, "max-concurrent-downloads", config.DefaultMaxConcurrentDownloads, "Set the max concurrent downloads for each pull") flags.IntVar(&maxConcurrentUploads, "max-concurrent-uploads", config.DefaultMaxConcurrentUploads, "Set the max concurrent uploads for each push") flags.IntVar(&conf.ShutdownTimeout, "shutdown-timeout", defaultShutdownTimeout, "Set the default shutdown timeout") + flags.IntVar(&conf.NetworkDiagnosticPort, "network-diagnostic-port", 0, "TCP port number of the network diagnostic server") + flags.MarkHidden("network-diagnostic-port") flags.StringVar(&conf.SwarmDefaultAdvertiseAddr, "swarm-default-advertise-addr", "", "Set default address or interface for swarm advertised address") flags.BoolVar(&conf.Experimental, "experimental", false, "Enable experimental features") flags.StringVar(&conf.MetricsAddress, "metrics-addr", "", "Set default address and port to serve the metrics api on") - flags.Var(opts.NewListOptsRef(&conf.NodeGenericResources, opts.ValidateSingleGenericResource), "node-generic-resource", "Advertise user-defined resource") + flags.Var(opts.NewListOptsRef(&conf.NodeGenericResources, opts.ValidateSingleGenericResource), "node-generic-resources", "Advertise user-defined resource") flags.IntVar(&conf.NetworkControlPlaneMTU, "network-control-plane-mtu", config.DefaultNetworkMtu, "Network Control plane MTU") @@ -90,6 +92,8 @@ func installRegistryServiceFlags(options *registry.ServiceOptions, flags *pflag. flags.Var(insecureRegistries, "insecure-registry", "Enable insecure registry communication") if runtime.GOOS != "windows" { + // TODO: Remove this flag after 3 release cycles (18.03) flags.BoolVar(&options.V2Only, "disable-legacy-registry", true, "Disable contacting legacy registries") + flags.MarkHidden("disable-legacy-registry") } } diff --git a/vendor/github.com/docker/docker/cmd/dockerd/config_experimental.go b/vendor/github.com/docker/docker/cmd/dockerd/config_experimental.go deleted file mode 100644 index 355a29e85..000000000 --- a/vendor/github.com/docker/docker/cmd/dockerd/config_experimental.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "github.com/docker/docker/daemon/config" - "github.com/spf13/pflag" -) - -func attachExperimentalFlags(conf *config.Config, cmd *pflag.FlagSet) { -} diff --git a/vendor/github.com/docker/docker/cmd/dockerd/config_solaris.go b/vendor/github.com/docker/docker/cmd/dockerd/config_solaris.go deleted file mode 100644 index ed6706490..000000000 --- a/vendor/github.com/docker/docker/cmd/dockerd/config_solaris.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "github.com/docker/docker/daemon/config" - "github.com/spf13/pflag" -) - -// installConfigFlags adds flags to the pflag.FlagSet to configure the daemon -func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) { - // First handle install flags which are consistent cross-platform - installCommonConfigFlags(conf, flags) - - // Then install flags common to unix platforms - installUnixConfigFlags(conf, flags) - - attachExperimentalFlags(conf, flags) -} diff --git a/vendor/github.com/docker/docker/cmd/dockerd/config_unix.go b/vendor/github.com/docker/docker/cmd/dockerd/config_unix.go index b3bd741c9..a3b0e36a0 100644 --- a/vendor/github.com/docker/docker/cmd/dockerd/config_unix.go +++ b/vendor/github.com/docker/docker/cmd/dockerd/config_unix.go @@ -44,6 +44,4 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) { flags.Var(&conf.ShmSize, "default-shm-size", "Default shm size for containers") flags.BoolVar(&conf.NoNewPrivileges, "no-new-privileges", false, "Set no-new-privileges by default for new containers") flags.StringVar(&conf.IpcMode, "default-ipc-mode", config.DefaultIpcMode, `Default mode for containers ipc ("shareable" | "private")`) - - attachExperimentalFlags(conf, flags) } diff --git a/vendor/github.com/docker/docker/cmd/dockerd/daemon.go b/vendor/github.com/docker/docker/cmd/dockerd/daemon.go index 02a03141d..d73b63a0f 100644 --- a/vendor/github.com/docker/docker/cmd/dockerd/daemon.go +++ b/vendor/github.com/docker/docker/cmd/dockerd/daemon.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "strings" "time" @@ -472,8 +473,15 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) { return nil, err } - if !conf.V2Only { - logrus.Warnf(`The "disable-legacy-registry" option is deprecated and wil be removed in Docker v17.12. Interacting with legacy (v1) registries will no longer be supported in Docker v17.12"`) + if runtime.GOOS != "windows" { + if flags.Changed("disable-legacy-registry") { + // TODO: Remove this error after 3 release cycles (18.03) + return nil, errors.New("ERROR: The '--disable-legacy-registry' flag has been removed. Interacting with legacy (v1) registries is no longer supported") + } + if !conf.V2Only { + // TODO: Remove this error after 3 release cycles (18.03) + return nil, errors.New("ERROR: The 'disable-legacy-registry' configuration option has been removed. Interacting with legacy (v1) registries is no longer supported") + } } if flags.Changed("graph") { diff --git a/vendor/github.com/docker/docker/cmd/dockerd/daemon_linux.go b/vendor/github.com/docker/docker/cmd/dockerd/daemon_linux.go index b58f0f08a..b09fed929 100644 --- a/vendor/github.com/docker/docker/cmd/dockerd/daemon_linux.go +++ b/vendor/github.com/docker/docker/cmd/dockerd/daemon_linux.go @@ -1,5 +1,3 @@ -// +build linux - package main import systemdDaemon "github.com/coreos/go-systemd/daemon" diff --git a/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix.go b/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix.go index 41e6b61ff..a65d8ed01 100644 --- a/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix.go +++ b/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/cmd/dockerd/hack" "github.com/docker/docker/daemon" "github.com/docker/docker/libcontainerd" - "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/libnetwork/portallocator" "golang.org/x/sys/unix" ) @@ -38,24 +37,13 @@ func getDaemonConfDir(_ string) string { } func (cli *DaemonCli) getPlatformRemoteOptions() ([]libcontainerd.RemoteOption, error) { - // On older kernel, letting putting the containerd-shim in its own - // namespace will effectively prevent operations such as unlink, rename - // and remove on mountpoints that were present at the time the shim - // namespace was created. This would led to a famous EBUSY will trying to - // remove shm mounts. - var noNewNS bool - if !kernel.CheckKernelVersion(3, 18, 0) { - noNewNS = true - } - opts := []libcontainerd.RemoteOption{ libcontainerd.WithOOMScore(cli.Config.OOMScoreAdjust), libcontainerd.WithPlugin("linux", &linux.Config{ - Shim: daemon.DefaultShimBinary, - Runtime: daemon.DefaultRuntimeBinary, - RuntimeRoot: filepath.Join(cli.Config.Root, "runc"), - ShimDebug: cli.Config.Debug, - ShimNoMountNS: noNewNS, + Shim: daemon.DefaultShimBinary, + Runtime: daemon.DefaultRuntimeBinary, + RuntimeRoot: filepath.Join(cli.Config.Root, "runc"), + ShimDebug: cli.Config.Debug, }), } if cli.Config.Debug { diff --git a/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix_test.go b/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix_test.go index 475ff9efa..41c392e1b 100644 --- a/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix_test.go +++ b/vendor/github.com/docker/docker/cmd/dockerd/daemon_unix_test.go @@ -97,15 +97,3 @@ func TestLoadDaemonConfigWithTrueDefaultValuesLeaveDefaults(t *testing.T) { assert.True(t, loadedConfig.EnableUserlandProxy) } - -func TestLoadDaemonConfigWithLegacyRegistryOptions(t *testing.T) { - content := `{"disable-legacy-registry": false}` - tempFile := fs.NewFile(t, "config", fs.WithContent(content)) - defer tempFile.Remove() - - opts := defaultOptions(tempFile.Path()) - loadedConfig, err := loadDaemonCliConfig(opts) - require.NoError(t, err) - require.NotNil(t, loadedConfig) - assert.False(t, loadedConfig.V2Only) -} diff --git a/vendor/github.com/docker/docker/container/container.go b/vendor/github.com/docker/docker/container/container.go index 3e8a37024..f19f9893f 100644 --- a/vendor/github.com/docker/docker/container/container.go +++ b/vendor/github.com/docker/docker/container/container.go @@ -15,7 +15,7 @@ import ( "syscall" "time" - "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" containertypes "github.com/docker/docker/api/types/container" mounttypes "github.com/docker/docker/api/types/mount" networktypes "github.com/docker/docker/api/types/network" @@ -27,7 +27,6 @@ import ( "github.com/docker/docker/daemon/network" "github.com/docker/docker/image" "github.com/docker/docker/layer" - "github.com/docker/docker/libcontainerd" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" @@ -1004,7 +1003,7 @@ func (container *Container) CloseStreams() error { } // InitializeStdio is called by libcontainerd to connect the stdio. -func (container *Container) InitializeStdio(iop *libcontainerd.IOPipe) (containerd.IO, error) { +func (container *Container) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) { if err := container.startLogging(); err != nil { container.Reset(false) return nil, err @@ -1020,17 +1019,26 @@ func (container *Container) InitializeStdio(iop *libcontainerd.IOPipe) (containe } } - return &cio{IO: iop, sc: container.StreamConfig}, nil + return &rio{IO: iop, sc: container.StreamConfig}, nil +} + +// MountsResourcePath returns the path where mounts are stored for the given mount +func (container *Container) MountsResourcePath(mount string) (string, error) { + return container.GetRootResourcePath(filepath.Join("mounts", mount)) } // SecretMountPath returns the path of the secret mount for the container -func (container *Container) SecretMountPath() string { - return filepath.Join(container.Root, "secrets") +func (container *Container) SecretMountPath() (string, error) { + return container.MountsResourcePath("secrets") } // SecretFilePath returns the path to the location of a secret on the host. -func (container *Container) SecretFilePath(secretRef swarmtypes.SecretReference) string { - return filepath.Join(container.SecretMountPath(), secretRef.SecretID) +func (container *Container) SecretFilePath(secretRef swarmtypes.SecretReference) (string, error) { + secrets, err := container.SecretMountPath() + if err != nil { + return "", err + } + return filepath.Join(secrets, secretRef.SecretID), nil } func getSecretTargetPath(r *swarmtypes.SecretReference) string { @@ -1043,13 +1051,17 @@ func getSecretTargetPath(r *swarmtypes.SecretReference) string { // ConfigsDirPath returns the path to the directory where configs are stored on // disk. -func (container *Container) ConfigsDirPath() string { - return filepath.Join(container.Root, "configs") +func (container *Container) ConfigsDirPath() (string, error) { + return container.GetRootResourcePath("configs") } // ConfigFilePath returns the path to the on-disk location of a config. -func (container *Container) ConfigFilePath(configRef swarmtypes.ConfigReference) string { - return filepath.Join(container.ConfigsDirPath(), configRef.ConfigID) +func (container *Container) ConfigFilePath(configRef swarmtypes.ConfigReference) (string, error) { + configs, err := container.ConfigsDirPath() + if err != nil { + return "", err + } + return filepath.Join(configs, configRef.ConfigID), nil } // CreateDaemonEnvironment creates a new environment variable slice for this container. @@ -1078,19 +1090,19 @@ func (container *Container) CreateDaemonEnvironment(tty bool, linkedEnv []string return env } -type cio struct { - containerd.IO +type rio struct { + cio.IO sc *stream.Config } -func (i *cio) Close() error { +func (i *rio) Close() error { i.IO.Close() return i.sc.CloseStreams() } -func (i *cio) Wait() { +func (i *rio) Wait() { i.sc.Wait() i.IO.Wait() diff --git a/vendor/github.com/docker/docker/container/container_unix.go b/vendor/github.com/docker/docker/container/container_unix.go index 28a3722c7..63ad2389c 100644 --- a/vendor/github.com/docker/docker/container/container_unix.go +++ b/vendor/github.com/docker/docker/container/container_unix.go @@ -151,7 +151,7 @@ func (container *Container) CopyImagePathContent(v volume.Volume, destination st // ShmResourcePath returns path to shm func (container *Container) ShmResourcePath() (string, error) { - return container.GetRootResourcePath("shm") + return container.MountsResourcePath("shm") } // HasMountFor checks if path is a mountpoint @@ -218,49 +218,61 @@ func (container *Container) IpcMounts() []Mount { } // SecretMounts returns the mounts for the secret path. -func (container *Container) SecretMounts() []Mount { +func (container *Container) SecretMounts() ([]Mount, error) { var mounts []Mount for _, r := range container.SecretReferences { if r.File == nil { continue } + src, err := container.SecretFilePath(*r) + if err != nil { + return nil, err + } mounts = append(mounts, Mount{ - Source: container.SecretFilePath(*r), + Source: src, Destination: getSecretTargetPath(r), Writable: false, }) } - return mounts + return mounts, nil } // UnmountSecrets unmounts the local tmpfs for secrets func (container *Container) UnmountSecrets() error { - if _, err := os.Stat(container.SecretMountPath()); err != nil { + p, err := container.SecretMountPath() + if err != nil { + return err + } + if _, err := os.Stat(p); err != nil { if os.IsNotExist(err) { return nil } return err } - return detachMounted(container.SecretMountPath()) + return mount.RecursiveUnmount(p) } // ConfigMounts returns the mounts for configs. -func (container *Container) ConfigMounts() []Mount { +func (container *Container) ConfigMounts() ([]Mount, error) { var mounts []Mount for _, configRef := range container.ConfigReferences { if configRef.File == nil { continue } + src, err := container.ConfigFilePath(*configRef) + if err != nil { + return nil, err + } mounts = append(mounts, Mount{ - Source: container.ConfigFilePath(*configRef), + Source: src, Destination: configRef.File.Name, Writable: false, }) } - return mounts + return mounts, nil } type conflictingUpdateOptions string @@ -332,6 +344,12 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi if resources.KernelMemory != 0 { cResources.KernelMemory = resources.KernelMemory } + if resources.CPURealtimePeriod != 0 { + cResources.CPURealtimePeriod = resources.CPURealtimePeriod + } + if resources.CPURealtimeRuntime != 0 { + cResources.CPURealtimeRuntime = resources.CPURealtimeRuntime + } // update HostConfig of container if hostConfig.RestartPolicy.Name != "" { diff --git a/vendor/github.com/docker/docker/container/container_windows.go b/vendor/github.com/docker/docker/container/container_windows.go index 5cb2e456c..94a4e1c0b 100644 --- a/vendor/github.com/docker/docker/container/container_windows.go +++ b/vendor/github.com/docker/docker/container/container_windows.go @@ -1,5 +1,3 @@ -// +build windows - package container import ( @@ -56,22 +54,30 @@ func (container *Container) CreateSecretSymlinks() error { // SecretMounts returns the mount for the secret path. // All secrets are stored in a single mount on Windows. Target symlinks are // created for each secret, pointing to the files in this mount. -func (container *Container) SecretMounts() []Mount { +func (container *Container) SecretMounts() ([]Mount, error) { var mounts []Mount if len(container.SecretReferences) > 0 { + src, err := container.SecretMountPath() + if err != nil { + return nil, err + } mounts = append(mounts, Mount{ - Source: container.SecretMountPath(), + Source: src, Destination: containerInternalSecretMountPath, Writable: false, }) } - return mounts + return mounts, nil } // UnmountSecrets unmounts the fs for secrets func (container *Container) UnmountSecrets() error { - return os.RemoveAll(container.SecretMountPath()) + p, err := container.SecretMountPath() + if err != nil { + return err + } + return os.RemoveAll(p) } // CreateConfigSymlinks creates symlinks to files in the config mount. @@ -98,17 +104,21 @@ func (container *Container) CreateConfigSymlinks() error { // ConfigMounts returns the mount for configs. // All configs are stored in a single mount on Windows. Target symlinks are // created for each config, pointing to the files in this mount. -func (container *Container) ConfigMounts() []Mount { +func (container *Container) ConfigMounts() ([]Mount, error) { var mounts []Mount if len(container.ConfigReferences) > 0 { + src, err := container.ConfigsDirPath() + if err != nil { + return nil, err + } mounts = append(mounts, Mount{ - Source: container.ConfigsDirPath(), + Source: src, Destination: containerInternalConfigsDirPath, Writable: false, }) } - return mounts + return mounts, nil } // DetachAndUnmount unmounts all volumes. diff --git a/vendor/github.com/docker/docker/container/state.go b/vendor/github.com/docker/docker/container/state.go index 3af4015ed..81c3b4594 100644 --- a/vendor/github.com/docker/docker/container/state.go +++ b/vendor/github.com/docker/docker/container/state.go @@ -102,15 +102,6 @@ func (s *State) String() string { return fmt.Sprintf("Exited (%d) %s ago", s.ExitCodeValue, units.HumanDuration(time.Now().UTC().Sub(s.FinishedAt))) } -// HealthString returns a single string to describe health status. -func (s *State) HealthString() string { - if s.Health == nil { - return types.NoHealthcheck - } - - return s.Health.String() -} - // IsValidHealthString checks if the provided string is a valid container health status or not. func IsValidHealthString(s string) bool { return s == types.Starting || diff --git a/vendor/github.com/docker/docker/container/state_solaris.go b/vendor/github.com/docker/docker/container/state_solaris.go deleted file mode 100644 index 1229650ef..000000000 --- a/vendor/github.com/docker/docker/container/state_solaris.go +++ /dev/null @@ -1,7 +0,0 @@ -package container - -// setFromExitStatus is a platform specific helper function to set the state -// based on the ExitStatus structure. -func (s *State) setFromExitStatus(exitStatus *ExitStatus) { - s.ExitCodeValue = exitStatus.ExitCode -} diff --git a/vendor/github.com/docker/docker/container/stream/streams.go b/vendor/github.com/docker/docker/container/stream/streams.go index 106e2b181..0ec164a48 100644 --- a/vendor/github.com/docker/docker/container/stream/streams.go +++ b/vendor/github.com/docker/docker/container/stream/streams.go @@ -7,7 +7,7 @@ import ( "strings" "sync" - "github.com/docker/docker/libcontainerd" + "github.com/containerd/containerd/cio" "github.com/docker/docker/pkg/broadcaster" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/pools" @@ -114,7 +114,7 @@ func (c *Config) CloseStreams() error { } // CopyToPipe connects streamconfig with a libcontainerd.IOPipe -func (c *Config) CopyToPipe(iop *libcontainerd.IOPipe) { +func (c *Config) CopyToPipe(iop *cio.DirectIO) { copyFunc := func(w io.Writer, r io.ReadCloser) { c.Add(1) go func() { diff --git a/vendor/github.com/docker/docker/container/view.go b/vendor/github.com/docker/docker/container/view.go index 164827c55..2d178e188 100644 --- a/vendor/github.com/docker/docker/container/view.go +++ b/vendor/github.com/docker/docker/container/view.go @@ -14,9 +14,8 @@ import ( ) const ( - memdbContainersTable = "containers" - memdbNamesTable = "names" - + memdbContainersTable = "containers" + memdbNamesTable = "names" memdbIDIndex = "id" memdbContainerIDIndex = "containerid" ) @@ -191,11 +190,7 @@ func (db *memDB) ReserveName(name, containerID string) error { } return nil } - - if err := txn.Insert(memdbNamesTable, nameAssociation{name: name, containerID: containerID}); err != nil { - return err - } - return nil + return txn.Insert(memdbNamesTable, nameAssociation{name: name, containerID: containerID}) }) } @@ -295,6 +290,10 @@ func (v *memdbView) GetAllNames() map[string][]string { // transform maps a (deep) copied Container object to what queries need. // A lock on the Container is not held because these are immutable deep copies. func (v *memdbView) transform(container *Container) *Snapshot { + health := types.NoHealthcheck + if container.Health != nil { + health = container.Health.Status() + } snapshot := &Snapshot{ Container: types.Container{ ID: container.ID, @@ -313,7 +312,7 @@ func (v *memdbView) transform(container *Container) *Snapshot { Managed: container.Managed, ExposedPorts: make(nat.PortSet), PortBindings: make(nat.PortSet), - Health: container.HealthString(), + Health: health, Running: container.Running, Paused: container.Paused, ExitCode: container.ExitCode(), diff --git a/vendor/github.com/docker/docker/container/view_test.go b/vendor/github.com/docker/docker/container/view_test.go index 4535a8fad..c425aaf73 100644 --- a/vendor/github.com/docker/docker/container/view_test.go +++ b/vendor/github.com/docker/docker/container/view_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/pborman/uuid" "github.com/stretchr/testify/assert" @@ -159,3 +160,26 @@ func TestNames(t *testing.T) { view = db.Snapshot() assert.Equal(t, map[string][]string{"containerid4": {"name1", "name2"}}, view.GetAllNames()) } + +// Test case for GitHub issue 35920 +func TestViewWithHealthCheck(t *testing.T) { + var ( + db, _ = NewViewDB() + one = newContainer(t) + ) + one.Health = &Health{ + Health: types.Health{ + Status: "starting", + }, + } + if err := one.CheckpointTo(db); err != nil { + t.Fatal(err) + } + s, err := db.Snapshot().Get(one.ID) + if err != nil { + t.Fatal(err) + } + if s == nil || s.Health != "starting" { + t.Fatalf("expected Health=starting. Got: %+v", s) + } +} diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-jessie/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-jessie/Dockerfile index 865d6aaea..a0a6612b7 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-jessie/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-jessie/Dockerfile @@ -7,7 +7,7 @@ FROM aarch64/debian:jessie RUN echo deb http://ftp.debian.org/debian jessie-backports main > /etc/apt/sources.list.d/backports.list RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev libseccomp-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-arm64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-stretch/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-stretch/Dockerfile index 2b561bee7..90525dbb1 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-stretch/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/debian-stretch/Dockerfile @@ -6,7 +6,7 @@ FROM aarch64/debian:stretch RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-dev libseccomp-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-arm64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-trusty/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-trusty/Dockerfile index e1b85ec74..5d2d58ea1 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-trusty/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-trusty/Dockerfile @@ -6,7 +6,7 @@ FROM aarch64/ubuntu:trusty RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-arm64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-xenial/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-xenial/Dockerfile index 6f8bc95b1..cb9b681d4 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-xenial/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/aarch64/ubuntu-xenial/Dockerfile @@ -6,7 +6,7 @@ FROM aarch64/ubuntu:xenial RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-dev libseccomp-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-arm64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-jessie/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-jessie/Dockerfile index 668fc3c1f..5b8b7852f 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-jessie/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-jessie/Dockerfile @@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-stretch/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-stretch/Dockerfile index a23eba39d..aa96240b9 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-stretch/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-stretch/Dockerfile @@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-wheezy/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-wheezy/Dockerfile index 2652706f4..2f4e051af 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-wheezy/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/debian-wheezy/Dockerfile @@ -12,7 +12,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list.d RUN apt-get update && apt-get install -y -t wheezy-backports btrfs-tools --no-install-recommends && rm -rf /var/lib/apt/lists/* RUN apt-get update && apt-get install -y apparmor bash-completion build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-trusty/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-trusty/Dockerfile index 4fce6f31f..a0105663e 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-trusty/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-trusty/Dockerfile @@ -6,7 +6,7 @@ FROM ubuntu:trusty RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-xenial/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-xenial/Dockerfile index ed9c4a9f3..e2768c33d 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-xenial/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-xenial/Dockerfile @@ -6,7 +6,7 @@ FROM ubuntu:xenial RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-yakkety/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-yakkety/Dockerfile index a7dd9b722..419522c13 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-yakkety/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-yakkety/Dockerfile @@ -6,7 +6,7 @@ FROM ubuntu:yakkety RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-zesty/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-zesty/Dockerfile index 5074efe2b..98314f1ed 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-zesty/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/amd64/ubuntu-zesty/Dockerfile @@ -6,7 +6,7 @@ FROM ubuntu:zesty RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/debian-jessie/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/debian-jessie/Dockerfile index 558d35393..048e7747d 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/debian-jessie/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/debian-jessie/Dockerfile @@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/raspbian-jessie/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/raspbian-jessie/Dockerfile index 31a6688d1..c80a3f6a4 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/raspbian-jessie/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/raspbian-jessie/Dockerfile @@ -10,7 +10,7 @@ RUN sed -ri "s/(httpredir|deb).debian.org/$APT_MIRROR/g" /etc/apt/sources.list RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 # GOARM is the ARM architecture version which is unrelated to the above Golang version ENV GOARM 6 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-trusty/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-trusty/Dockerfile index a9899a06d..b6fc393aa 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-trusty/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-trusty/Dockerfile @@ -6,7 +6,7 @@ FROM armhf/ubuntu:trusty RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-xenial/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-xenial/Dockerfile index 2766f330b..cc9284ffd 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-xenial/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-xenial/Dockerfile @@ -6,7 +6,7 @@ FROM armhf/ubuntu:xenial RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-yakkety/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-yakkety/Dockerfile index 27edd04d3..57a77acd7 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-yakkety/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/armhf/ubuntu-yakkety/Dockerfile @@ -6,7 +6,7 @@ FROM armhf/ubuntu:yakkety RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config vim-common libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-trusty/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-trusty/Dockerfile index b85a68e4e..d29ac5138 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-trusty/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-trusty/Dockerfile @@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:trusty RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libsystemd-journal-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-xenial/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-xenial/Dockerfile index abb5b2313..730bacb07 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-xenial/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-xenial/Dockerfile @@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:xenial RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libseccomp-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-yakkety/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-yakkety/Dockerfile index d72581659..27cfd292a 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-yakkety/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/ppc64le/ubuntu-yakkety/Dockerfile @@ -6,7 +6,7 @@ FROM ppc64le/ubuntu:yakkety RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev pkg-config vim-common libseccomp-dev libsystemd-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-xenial/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-xenial/Dockerfile index 6d61ed7f5..223389737 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-xenial/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-xenial/Dockerfile @@ -6,7 +6,7 @@ FROM s390x/ubuntu:xenial RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config libsystemd-dev vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-yakkety/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-yakkety/Dockerfile index e30e87504..b2a0cf573 100644 --- a/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-yakkety/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/deb/s390x/ubuntu-yakkety/Dockerfile @@ -6,7 +6,7 @@ FROM s390x/ubuntu:yakkety RUN apt-get update && apt-get install -y apparmor bash-completion btrfs-tools build-essential cmake curl ca-certificates debhelper dh-apparmor dh-systemd git libapparmor-dev libdevmapper-dev libseccomp-dev pkg-config libsystemd-dev vim-common --no-install-recommends && rm -rf /var/lib/apt/lists/* -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/amazonlinux-latest/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/amazonlinux-latest/Dockerfile index 8e755cd0a..1f0a0b7c0 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/amazonlinux-latest/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/amazonlinux-latest/Dockerfile @@ -5,9 +5,9 @@ FROM amazonlinux:latest RUN yum groupinstall -y "Development Tools" -RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common +RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/centos-7/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/centos-7/Dockerfile index 8a220649e..5767b8cd0 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/centos-7/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/centos-7/Dockerfile @@ -6,9 +6,9 @@ FROM centos:7 RUN yum groupinstall -y "Development Tools" RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs -RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common +RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile index e0b369aa4..1e075238c 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-24/Dockerfile @@ -6,9 +6,9 @@ FROM fedora:24 RUN dnf -y upgrade RUN dnf install -y @development-tools fedora-packager -RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common +RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile index f259a5cea..23e24638e 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/fedora-25/Dockerfile @@ -6,9 +6,9 @@ FROM fedora:25 RUN dnf -y upgrade RUN dnf install -y @development-tools fedora-packager -RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common +RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/opensuse-13.2/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/opensuse-13.2/Dockerfile index 7f1386399..b55bfee8e 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/opensuse-13.2/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/opensuse-13.2/Dockerfile @@ -5,9 +5,9 @@ FROM opensuse:13.2 RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build -RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim systemd-rpm-macros +RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim systemd-rpm-macros -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-6/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-6/Dockerfile index b75f2dc3e..1b395c2c6 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-6/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-6/Dockerfile @@ -8,9 +8,9 @@ RUN yum install -y yum-utils && curl -o /etc/yum.repos.d/public-yum-ol6.repo htt RUN yum install -y kernel-uek-devel-4.1.12-32.el6uek RUN yum groupinstall -y "Development Tools" -RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common +RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libselinux-devel pkgconfig selinux-policy selinux-policy-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-7/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-7/Dockerfile index f4dc894f1..ec6db986b 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-7/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/oraclelinux-7/Dockerfile @@ -5,9 +5,9 @@ FROM oraclelinux:7 RUN yum groupinstall -y "Development Tools" -RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common +RUN yum install -y --enablerepo=ol7_optional_latest btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/photon-1.0/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/photon-1.0/Dockerfile index 01d5fea10..be9463c21 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/photon-1.0/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/amd64/photon-1.0/Dockerfile @@ -5,9 +5,9 @@ FROM photon:1.0 RUN tdnf install -y wget curl ca-certificates gzip make rpm-build sed gcc linux-api-headers glibc-devel binutils libseccomp elfutils -RUN tdnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common +RUN tdnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkg-config selinux-policy selinux-policy-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-amd64.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/armhf/centos-7/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/armhf/centos-7/Dockerfile index 79c2ef162..8e77e8b09 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/armhf/centos-7/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/armhf/centos-7/Dockerfile @@ -7,9 +7,9 @@ FROM multiarch/centos:7.2.1511-armhfp-clean RUN yum install -y yum-plugin-ovl RUN yum groupinstall --skip-broken -y "Development Tools" RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs -RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common +RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-armv6l.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/centos-7/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/centos-7/Dockerfile index ebce3c022..8bcc4be8c 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/centos-7/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/centos-7/Dockerfile @@ -6,10 +6,10 @@ FROM ppc64le/centos:7 RUN yum groupinstall -y "Development Tools" RUN yum -y swap -- remove systemd-container systemd-container-libs -- install systemd systemd-libs -RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common +RUN yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 -RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local +ENV GO_VERSION 1.9.2 +RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin ENV AUTO_GOPATH 1 diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/fedora-24/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/fedora-24/Dockerfile index 18dd7d4de..32321fe9c 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/fedora-24/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/fedora-24/Dockerfile @@ -6,9 +6,9 @@ FROM ppc64le/fedora:24 RUN dnf -y upgrade RUN dnf install -y @development-tools fedora-packager -RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel systemd-devel tar git cmake +RUN dnf install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/opensuse-42.1/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/opensuse-42.1/Dockerfile index 3343f021c..04f158cc4 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/opensuse-42.1/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/ppc64le/opensuse-42.1/Dockerfile @@ -7,10 +7,10 @@ FROM ppc64le/opensuse:42.1 RUN zypper addrepo -n ppc64le-oss -f https://download.opensuse.org/ports/ppc/distribution/leap/42.1/repo/oss/ ppc64le-oss RUN zypper addrepo -n ppc64le-updates -f https://download.opensuse.org/ports/update/42.1/ ppc64le-updates RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build -RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim +RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim -ENV GO_VERSION 1.8.5 -RUN curl -fSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local +ENV GO_VERSION 1.9.2 +RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-ppc64le.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin ENV AUTO_GOPATH 1 diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/clefos-base-s390x-7/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/clefos-base-s390x-7/Dockerfile index ef875b8fc..27195d3b4 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/clefos-base-s390x-7/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/clefos-base-s390x-7/Dockerfile @@ -6,9 +6,9 @@ FROM sinenomine/clefos-base-s390x RUN touch /var/lib/rpm/* && yum groupinstall -y "Development Tools" -RUN touch /var/lib/rpm/* && yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common +RUN touch /var/lib/rpm/* && yum install -y btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel libselinux-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim-common -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/opensuse-tumbleweed-1/Dockerfile b/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/opensuse-tumbleweed-1/Dockerfile index a05bee509..275fab5e9 100644 --- a/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/opensuse-tumbleweed-1/Dockerfile +++ b/vendor/github.com/docker/docker/contrib/builder/rpm/s390x/opensuse-tumbleweed-1/Dockerfile @@ -7,9 +7,9 @@ FROM opensuse/s390x:tumbleweed RUN zypper ar https://download.opensuse.org/ports/zsystems/tumbleweed/repo/oss/ tumbleweed RUN zypper --non-interactive install ca-certificates* curl gzip rpm-build -RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel libtool-ltdl-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim systemd-rpm-macros +RUN zypper --non-interactive install libbtrfs-devel device-mapper-devel glibc-static libselinux-devel pkg-config selinux-policy selinux-policy-devel sqlite-devel systemd-devel tar git cmake vim systemd-rpm-macros -ENV GO_VERSION 1.8.5 +ENV GO_VERSION 1.9.2 RUN curl -fsSL "https://golang.org/dl/go${GO_VERSION}.linux-s390x.tar.gz" | tar xzC /usr/local ENV PATH $PATH:/usr/local/go/bin diff --git a/vendor/github.com/docker/docker/contrib/download-frozen-image-v2.sh b/vendor/github.com/docker/docker/contrib/download-frozen-image-v2.sh index 2dfe247b5..54b592307 100755 --- a/vendor/github.com/docker/docker/contrib/download-frozen-image-v2.sh +++ b/vendor/github.com/docker/docker/contrib/download-frozen-image-v2.sh @@ -6,7 +6,6 @@ set -eo pipefail # debian latest f6fab3b798be 10 weeks ago 85.1 MB # debian latest f6fab3b798be3174f45aa1eb731f8182705555f89c9026d8c1ef230cbf8301dd 10 weeks ago 85.1 MB - if ! command -v curl &> /dev/null; then echo >&2 'error: "curl" not found!' exit 1 @@ -64,7 +63,7 @@ fetch_blob() { -D- )" curlHeaders="$(echo "$curlHeaders" | tr -d '\r')" - if echo "$curlHeaders" | grep -qE "^HTTP/[0-9].[0-9] 3"; then + if grep -qE "^HTTP/[0-9].[0-9] 3" <<<"$curlHeaders"; then rm -f "$targetFile" local blobRedirect="$(echo "$curlHeaders" | awk -F ': ' 'tolower($1) == "location" { print $2; exit }')" @@ -80,6 +79,109 @@ fetch_blob() { fi } +# handle 'application/vnd.docker.distribution.manifest.v2+json' manifest +handle_single_manifest_v2() { + local manifestJson="$1"; shift + + local configDigest="$(echo "$manifestJson" | jq --raw-output '.config.digest')" + local imageId="${configDigest#*:}" # strip off "sha256:" + + local configFile="$imageId.json" + fetch_blob "$token" "$image" "$configDigest" "$dir/$configFile" -s + + local layersFs="$(echo "$manifestJson" | jq --raw-output --compact-output '.layers[]')" + local IFS="$newlineIFS" + local layers=( $layersFs ) + unset IFS + + echo "Downloading '$imageIdentifier' (${#layers[@]} layers)..." + local layerId= + local layerFiles=() + for i in "${!layers[@]}"; do + local layerMeta="${layers[$i]}" + + local layerMediaType="$(echo "$layerMeta" | jq --raw-output '.mediaType')" + local layerDigest="$(echo "$layerMeta" | jq --raw-output '.digest')" + + # save the previous layer's ID + local parentId="$layerId" + # create a new fake layer ID based on this layer's digest and the previous layer's fake ID + layerId="$(echo "$parentId"$'\n'"$layerDigest" | sha256sum | cut -d' ' -f1)" + # this accounts for the possibility that an image contains the same layer twice (and thus has a duplicate digest value) + + mkdir -p "$dir/$layerId" + echo '1.0' > "$dir/$layerId/VERSION" + + if [ ! -s "$dir/$layerId/json" ]; then + local parentJson="$(printf ', parent: "%s"' "$parentId")" + local addJson="$(printf '{ id: "%s"%s }' "$layerId" "${parentId:+$parentJson}")" + # this starter JSON is taken directly from Docker's own "docker save" output for unimportant layers + jq "$addJson + ." > "$dir/$layerId/json" <<-'EOJSON' + { + "created": "0001-01-01T00:00:00Z", + "container_config": { + "Hostname": "", + "Domainname": "", + "User": "", + "AttachStdin": false, + "AttachStdout": false, + "AttachStderr": false, + "Tty": false, + "OpenStdin": false, + "StdinOnce": false, + "Env": null, + "Cmd": null, + "Image": "", + "Volumes": null, + "WorkingDir": "", + "Entrypoint": null, + "OnBuild": null, + "Labels": null + } + } + EOJSON + fi + + case "$layerMediaType" in + application/vnd.docker.image.rootfs.diff.tar.gzip) + local layerTar="$layerId/layer.tar" + layerFiles=( "${layerFiles[@]}" "$layerTar" ) + # TODO figure out why "-C -" doesn't work here + # "curl: (33) HTTP server doesn't seem to support byte ranges. Cannot resume." + # "HTTP/1.1 416 Requested Range Not Satisfiable" + if [ -f "$dir/$layerTar" ]; then + # TODO hackpatch for no -C support :'( + echo "skipping existing ${layerId:0:12}" + continue + fi + local token="$(curl -fsSL "$authBase/token?service=$authService&scope=repository:$image:pull" | jq --raw-output '.token')" + fetch_blob "$token" "$image" "$layerDigest" "$dir/$layerTar" --progress + ;; + + *) + echo >&2 "error: unknown layer mediaType ($imageIdentifier, $layerDigest): '$layerMediaType'" + exit 1 + ;; + esac + done + + # change "$imageId" to be the ID of the last layer we added (needed for old-style "repositories" file which is created later -- specifically for older Docker daemons) + imageId="$layerId" + + # munge the top layer image manifest to have the appropriate image configuration for older daemons + local imageOldConfig="$(jq --raw-output --compact-output '{ id: .id } + if .parent then { parent: .parent } else {} end' "$dir/$imageId/json")" + jq --raw-output "$imageOldConfig + del(.history, .rootfs)" "$dir/$configFile" > "$dir/$imageId/json" + + local manifestJsonEntry="$( + echo '{}' | jq --raw-output '. + { + Config: "'"$configFile"'", + RepoTags: ["'"${image#library\/}:$tag"'"], + Layers: '"$(echo '[]' | jq --raw-output ".$(for layerFile in "${layerFiles[@]}"; do echo " + [ \"$layerFile\" ]"; done)")"' + }' + )" + manifestJsonEntries=( "${manifestJsonEntries[@]}" "$manifestJsonEntry" ) +} + while [ $# -gt 0 ]; do imageTag="$1" shift @@ -101,6 +203,7 @@ while [ $# -gt 0 ]; do curl -fsSL \ -H "Authorization: Bearer $token" \ -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \ + -H 'Accept: application/vnd.docker.distribution.manifest.list.v2+json' \ -H 'Accept: application/vnd.docker.distribution.manifest.v1+json' \ "$registryBase/v2/$image/manifests/$digest" )" @@ -119,105 +222,40 @@ while [ $# -gt 0 ]; do case "$mediaType" in application/vnd.docker.distribution.manifest.v2+json) - configDigest="$(echo "$manifestJson" | jq --raw-output '.config.digest')" - imageId="${configDigest#*:}" # strip off "sha256:" - - configFile="$imageId.json" - fetch_blob "$token" "$image" "$configDigest" "$dir/$configFile" -s - - layersFs="$(echo "$manifestJson" | jq --raw-output --compact-output '.layers[]')" + handle_single_manifest_v2 "$manifestJson" + ;; + application/vnd.docker.distribution.manifest.list.v2+json) + layersFs="$(echo "$manifestJson" | jq --raw-output --compact-output '.manifests[]')" IFS="$newlineIFS" layers=( $layersFs ) unset IFS - echo "Downloading '$imageIdentifier' (${#layers[@]} layers)..." - layerId= - layerFiles=() + found="" + # parse first level multi-arch manifest for i in "${!layers[@]}"; do layerMeta="${layers[$i]}" - - layerMediaType="$(echo "$layerMeta" | jq --raw-output '.mediaType')" - layerDigest="$(echo "$layerMeta" | jq --raw-output '.digest')" - - # save the previous layer's ID - parentId="$layerId" - # create a new fake layer ID based on this layer's digest and the previous layer's fake ID - layerId="$(echo "$parentId"$'\n'"$layerDigest" | sha256sum | cut -d' ' -f1)" - # this accounts for the possibility that an image contains the same layer twice (and thus has a duplicate digest value) - - mkdir -p "$dir/$layerId" - echo '1.0' > "$dir/$layerId/VERSION" - - if [ ! -s "$dir/$layerId/json" ]; then - parentJson="$(printf ', parent: "%s"' "$parentId")" - addJson="$(printf '{ id: "%s"%s }' "$layerId" "${parentId:+$parentJson}")" - # this starter JSON is taken directly from Docker's own "docker save" output for unimportant layers - jq "$addJson + ." > "$dir/$layerId/json" <<-'EOJSON' - { - "created": "0001-01-01T00:00:00Z", - "container_config": { - "Hostname": "", - "Domainname": "", - "User": "", - "AttachStdin": false, - "AttachStdout": false, - "AttachStderr": false, - "Tty": false, - "OpenStdin": false, - "StdinOnce": false, - "Env": null, - "Cmd": null, - "Image": "", - "Volumes": null, - "WorkingDir": "", - "Entrypoint": null, - "OnBuild": null, - "Labels": null - } - } - EOJSON + maniArch="$(echo "$layerMeta" | jq --raw-output '.platform.architecture')" + if [ "$maniArch" = "$(go env GOARCH)" ]; then + digest="$(echo "$layerMeta" | jq --raw-output '.digest')" + # get second level single manifest + submanifestJson="$( + curl -fsSL \ + -H "Authorization: Bearer $token" \ + -H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \ + -H 'Accept: application/vnd.docker.distribution.manifest.list.v2+json' \ + -H 'Accept: application/vnd.docker.distribution.manifest.v1+json' \ + "$registryBase/v2/$image/manifests/$digest" + )" + handle_single_manifest_v2 "$submanifestJson" + found="found" + break fi - - case "$layerMediaType" in - application/vnd.docker.image.rootfs.diff.tar.gzip) - layerTar="$layerId/layer.tar" - layerFiles=( "${layerFiles[@]}" "$layerTar" ) - # TODO figure out why "-C -" doesn't work here - # "curl: (33) HTTP server doesn't seem to support byte ranges. Cannot resume." - # "HTTP/1.1 416 Requested Range Not Satisfiable" - if [ -f "$dir/$layerTar" ]; then - # TODO hackpatch for no -C support :'( - echo "skipping existing ${layerId:0:12}" - continue - fi - token="$(curl -fsSL "$authBase/token?service=$authService&scope=repository:$image:pull" | jq --raw-output '.token')" - fetch_blob "$token" "$image" "$layerDigest" "$dir/$layerTar" --progress - ;; - - *) - echo >&2 "error: unknown layer mediaType ($imageIdentifier, $layerDigest): '$layerMediaType'" - exit 1 - ;; - esac done - - # change "$imageId" to be the ID of the last layer we added (needed for old-style "repositories" file which is created later -- specifically for older Docker daemons) - imageId="$layerId" - - # munge the top layer image manifest to have the appropriate image configuration for older daemons - imageOldConfig="$(jq --raw-output --compact-output '{ id: .id } + if .parent then { parent: .parent } else {} end' "$dir/$imageId/json")" - jq --raw-output "$imageOldConfig + del(.history, .rootfs)" "$dir/$configFile" > "$dir/$imageId/json" - - manifestJsonEntry="$( - echo '{}' | jq --raw-output '. + { - Config: "'"$configFile"'", - RepoTags: ["'"${image#library\/}:$tag"'"], - Layers: '"$(echo '[]' | jq --raw-output ".$(for layerFile in "${layerFiles[@]}"; do echo " + [ \"$layerFile\" ]"; done)")"' - }' - )" - manifestJsonEntries=( "${manifestJsonEntries[@]}" "$manifestJsonEntry" ) + if [ -z "$found" ]; then + echo >&2 "error: manifest for $maniArch is not found" + exit 1 + fi ;; - *) echo >&2 "error: unknown manifest mediaType ($imageIdentifier): '$mediaType'" exit 1 diff --git a/vendor/github.com/docker/docker/daemon/archive.go b/vendor/github.com/docker/docker/daemon/archive.go index c52d3b850..69301342e 100644 --- a/vendor/github.com/docker/docker/daemon/archive.go +++ b/vendor/github.com/docker/docker/daemon/archive.go @@ -7,6 +7,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/ioutils" @@ -54,7 +55,7 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err // Make sure an online file-system operation is permitted. if err := daemon.isOnlineFSOperationPermitted(container); err != nil { - return nil, systemError{err} + return nil, errdefs.System(err) } data, err := daemon.containerCopy(container, res) @@ -65,7 +66,7 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err if os.IsNotExist(err) { return nil, containerFileNotFound{res, name} } - return nil, systemError{err} + return nil, errdefs.System(err) } // ContainerStatPath stats the filesystem resource at the specified path in the @@ -78,7 +79,7 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C // Make sure an online file-system operation is permitted. if err := daemon.isOnlineFSOperationPermitted(container); err != nil { - return nil, systemError{err} + return nil, errdefs.System(err) } stat, err = daemon.containerStatPath(container, path) @@ -89,7 +90,7 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C if os.IsNotExist(err) { return nil, containerFileNotFound{path, name} } - return nil, systemError{err} + return nil, errdefs.System(err) } // ContainerArchivePath creates an archive of the filesystem resource at the @@ -103,7 +104,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io // Make sure an online file-system operation is permitted. if err := daemon.isOnlineFSOperationPermitted(container); err != nil { - return nil, nil, systemError{err} + return nil, nil, errdefs.System(err) } content, stat, err = daemon.containerArchivePath(container, path) @@ -114,7 +115,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io if os.IsNotExist(err) { return nil, nil, containerFileNotFound{path, name} } - return nil, nil, systemError{err} + return nil, nil, errdefs.System(err) } // ContainerExtractToDir extracts the given archive to the specified location @@ -131,7 +132,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, copyUIDGID, noOve // Make sure an online file-system operation is permitted. if err := daemon.isOnlineFSOperationPermitted(container); err != nil { - return systemError{err} + return errdefs.System(err) } err = daemon.containerExtractToDir(container, path, copyUIDGID, noOverwriteDirNonDir, content) @@ -142,7 +143,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, copyUIDGID, noOve if os.IsNotExist(err) { return containerFileNotFound{path, name} } - return systemError{err} + return errdefs.System(err) } // containerStatPath stats the filesystem resource at the specified path in this diff --git a/vendor/github.com/docker/docker/daemon/archive_tarcopyoptions_windows.go b/vendor/github.com/docker/docker/daemon/archive_tarcopyoptions_windows.go index 535efd222..500e1285d 100644 --- a/vendor/github.com/docker/docker/daemon/archive_tarcopyoptions_windows.go +++ b/vendor/github.com/docker/docker/daemon/archive_tarcopyoptions_windows.go @@ -1,5 +1,3 @@ -// +build windows - package daemon import ( diff --git a/vendor/github.com/docker/docker/daemon/attach.go b/vendor/github.com/docker/docker/daemon/attach.go index 651a964c0..d63eaa663 100644 --- a/vendor/github.com/docker/docker/daemon/attach.go +++ b/vendor/github.com/docker/docker/daemon/attach.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/container/stream" "github.com/docker/docker/daemon/logger" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/pkg/term" "github.com/pkg/errors" @@ -22,7 +23,7 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA if c.DetachKeys != "" { keys, err = term.ToBytes(c.DetachKeys) if err != nil { - return validationError{errors.Errorf("Invalid detach keys (%s) provided", c.DetachKeys)} + return errdefs.InvalidParameter(errors.Errorf("Invalid detach keys (%s) provided", c.DetachKeys)) } } @@ -32,11 +33,11 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, c *backend.ContainerA } if container.IsPaused() { err := fmt.Errorf("container %s is paused, unpause the container before attach", prefixOrName) - return stateConflictError{err} + return errdefs.Conflict(err) } if container.IsRestarting() { err := fmt.Errorf("container %s is restarting, wait until the container is running", prefixOrName) - return stateConflictError{err} + return errdefs.Conflict(err) } cfg := stream.AttachConfig{ diff --git a/vendor/github.com/docker/docker/daemon/build.go b/vendor/github.com/docker/docker/daemon/build.go index 6a0081484..b69ff897b 100644 --- a/vendor/github.com/docker/docker/daemon/build.go +++ b/vendor/github.com/docker/docker/daemon/build.go @@ -2,7 +2,6 @@ package daemon import ( "io" - "runtime" "github.com/docker/distribution/reference" "github.com/docker/docker/api/types" @@ -13,6 +12,7 @@ import ( "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/pkg/system" "github.com/docker/docker/registry" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -55,7 +55,7 @@ func (rl *releaseableLayer) Mount() (containerfs.ContainerFS, error) { return mountPath, nil } -func (rl *releaseableLayer) Commit(os string) (builder.ReleaseableLayer, error) { +func (rl *releaseableLayer) Commit() (builder.ReleaseableLayer, error) { var chainID layer.ChainID if rl.roLayer != nil { chainID = rl.roLayer.ChainID() @@ -67,15 +67,11 @@ func (rl *releaseableLayer) Commit(os string) (builder.ReleaseableLayer, error) } defer stream.Close() - newLayer, err := rl.layerStore.Register(stream, chainID, layer.OS(os)) + newLayer, err := rl.layerStore.Register(stream, chainID) if err != nil { return nil, err } - - if layer.IsEmpty(newLayer.DiffID()) { - _, err := rl.layerStore.Release(newLayer) - return &releaseableLayer{layerStore: rl.layerStore}, err - } + // TODO: An optimization would be to handle empty layers before returning return &releaseableLayer{layerStore: rl.layerStore, roLayer: newLayer}, nil } @@ -146,7 +142,7 @@ func newReleasableLayerForImage(img *image.Image, layerStore layer.Store) (build } // TODO: could this use the regular daemon PullImage ? -func (daemon *Daemon) pullForBuilder(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer, platform string) (*image.Image, error) { +func (daemon *Daemon) pullForBuilder(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer, os string) (*image.Image, error) { ref, err := reference.ParseNormalizedNamed(name) if err != nil { return nil, err @@ -165,7 +161,7 @@ func (daemon *Daemon) pullForBuilder(ctx context.Context, name string, authConfi pullRegistryAuth = &resolvedConfig } - if err := daemon.pullImageWithReference(ctx, ref, platform, nil, pullRegistryAuth, output); err != nil { + if err := daemon.pullImageWithReference(ctx, ref, os, nil, pullRegistryAuth, output); err != nil { return nil, err } return daemon.GetImage(name) @@ -176,7 +172,10 @@ func (daemon *Daemon) pullForBuilder(ctx context.Context, name string, authConfi // leaking of layers. func (daemon *Daemon) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ReleaseableLayer, error) { if refOrID == "" { - layer, err := newReleasableLayerForImage(nil, daemon.stores[opts.OS].layerStore) + if !system.IsOSSupported(opts.OS) { + return nil, nil, system.ErrNotSupportedOperatingSystem + } + layer, err := newReleasableLayerForImage(nil, daemon.layerStores[opts.OS]) return nil, layer, err } @@ -187,7 +186,10 @@ func (daemon *Daemon) GetImageAndReleasableLayer(ctx context.Context, refOrID st } // TODO: shouldn't we error out if error is different from "not found" ? if image != nil { - layer, err := newReleasableLayerForImage(image, daemon.stores[opts.OS].layerStore) + if !system.IsOSSupported(image.OperatingSystem()) { + return nil, nil, system.ErrNotSupportedOperatingSystem + } + layer, err := newReleasableLayerForImage(image, daemon.layerStores[image.OperatingSystem()]) return image, layer, err } } @@ -196,29 +198,29 @@ func (daemon *Daemon) GetImageAndReleasableLayer(ctx context.Context, refOrID st if err != nil { return nil, nil, err } - layer, err := newReleasableLayerForImage(image, daemon.stores[opts.OS].layerStore) + if !system.IsOSSupported(image.OperatingSystem()) { + return nil, nil, system.ErrNotSupportedOperatingSystem + } + layer, err := newReleasableLayerForImage(image, daemon.layerStores[image.OperatingSystem()]) return image, layer, err } // CreateImage creates a new image by adding a config and ID to the image store. // This is similar to LoadImage() except that it receives JSON encoded bytes of // an image instead of a tar archive. -func (daemon *Daemon) CreateImage(config []byte, parent string, platform string) (builder.Image, error) { - if platform == "" { - platform = runtime.GOOS - } - id, err := daemon.stores[platform].imageStore.Create(config) +func (daemon *Daemon) CreateImage(config []byte, parent string) (builder.Image, error) { + id, err := daemon.imageStore.Create(config) if err != nil { return nil, errors.Wrapf(err, "failed to create image") } if parent != "" { - if err := daemon.stores[platform].imageStore.SetParent(id, image.ID(parent)); err != nil { + if err := daemon.imageStore.SetParent(id, image.ID(parent)); err != nil { return nil, errors.Wrapf(err, "failed to set parent %s", parent) } } - return daemon.stores[platform].imageStore.Get(id) + return daemon.imageStore.Get(id) } // IDMappings returns uid/gid mappings for the builder diff --git a/vendor/github.com/docker/docker/daemon/cache.go b/vendor/github.com/docker/docker/daemon/cache.go index 5ad68ec0a..ab3a24986 100644 --- a/vendor/github.com/docker/docker/daemon/cache.go +++ b/vendor/github.com/docker/docker/daemon/cache.go @@ -7,12 +7,12 @@ import ( ) // MakeImageCache creates a stateful image cache. -func (daemon *Daemon) MakeImageCache(sourceRefs []string, platform string) builder.ImageCache { +func (daemon *Daemon) MakeImageCache(sourceRefs []string) builder.ImageCache { if len(sourceRefs) == 0 { - return cache.NewLocal(daemon.stores[platform].imageStore) + return cache.NewLocal(daemon.imageStore) } - cache := cache.New(daemon.stores[platform].imageStore) + cache := cache.New(daemon.imageStore) for _, ref := range sourceRefs { img, err := daemon.GetImage(ref) diff --git a/vendor/github.com/docker/docker/daemon/checkpoint.go b/vendor/github.com/docker/docker/daemon/checkpoint.go index 5765af7c5..78930de4d 100644 --- a/vendor/github.com/docker/docker/daemon/checkpoint.go +++ b/vendor/github.com/docker/docker/daemon/checkpoint.go @@ -22,7 +22,7 @@ func getCheckpointDir(checkDir, checkpointID, ctrName, ctrID, ctrCheckpointDir s var checkpointDir string var err2 error if checkDir != "" { - checkpointDir = filepath.Join(checkDir, ctrID, "checkpoints") + checkpointDir = checkDir } else { checkpointDir = ctrCheckpointDir } @@ -34,9 +34,6 @@ func getCheckpointDir(checkDir, checkpointID, ctrName, ctrID, ctrCheckpointDir s err2 = fmt.Errorf("checkpoint with name %s already exists for container %s", checkpointID, ctrName) case err != nil && os.IsNotExist(err): err2 = os.MkdirAll(checkpointAbsDir, 0700) - if os.IsExist(err2) { - err2 = nil - } case err != nil: err2 = err case err == nil: diff --git a/vendor/github.com/docker/docker/daemon/cluster/controllers/plugin/controller.go b/vendor/github.com/docker/docker/daemon/cluster/controllers/plugin/controller.go index b48c9fd4e..d4f24e82d 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/controllers/plugin/controller.go +++ b/vendor/github.com/docker/docker/daemon/cluster/controllers/plugin/controller.go @@ -6,9 +6,9 @@ import ( "net/http" "github.com/docker/distribution/reference" - "github.com/docker/docker/api/errdefs" enginetypes "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm/runtime" + "github.com/docker/docker/errdefs" "github.com/docker/docker/plugin" "github.com/docker/docker/plugin/v2" "github.com/docker/swarmkit/api" diff --git a/vendor/github.com/docker/docker/daemon/cluster/errors.go b/vendor/github.com/docker/docker/daemon/cluster/errors.go index 0ffe78b98..9b2e81e0a 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/errors.go +++ b/vendor/github.com/docker/docker/daemon/cluster/errors.go @@ -20,48 +20,6 @@ const ( errSwarmNotManager notAvailableError = "This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager." ) -type notFoundError struct { - cause error -} - -func (e notFoundError) Error() string { - return e.cause.Error() -} - -func (e notFoundError) NotFound() {} - -func (e notFoundError) Cause() error { - return e.cause -} - -type ambiguousResultsError struct { - cause error -} - -func (e ambiguousResultsError) Error() string { - return e.cause.Error() -} - -func (e ambiguousResultsError) InvalidParameter() {} - -func (e ambiguousResultsError) Cause() error { - return e.cause -} - -type convertError struct { - cause error -} - -func (e convertError) Error() string { - return e.cause.Error() -} - -func (e convertError) InvalidParameter() {} - -func (e convertError) Cause() error { - return e.cause -} - type notAllowedError string func (e notAllowedError) Error() string { @@ -70,20 +28,6 @@ func (e notAllowedError) Error() string { func (e notAllowedError) Forbidden() {} -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (e validationError) InvalidParameter() {} - -func (e validationError) Cause() error { - return e.cause -} - type notAvailableError string func (e notAvailableError) Error() string { diff --git a/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go b/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go index f6763d15c..9a0f1cb95 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go +++ b/vendor/github.com/docker/docker/daemon/cluster/executor/backend.go @@ -27,7 +27,7 @@ import ( // Backend defines the executor component for a swarm agent. type Backend interface { CreateManagedNetwork(clustertypes.NetworkCreateRequest) error - DeleteManagedNetwork(name string) error + DeleteManagedNetwork(networkID string) error FindNetwork(idName string) (libnetwork.Network, error) SetupIngress(clustertypes.NetworkCreateRequest, string) (<-chan struct{}, error) ReleaseIngress() (<-chan struct{}, error) diff --git a/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go b/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go index 81e740af1..9ba64c486 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go +++ b/vendor/github.com/docker/docker/daemon/cluster/executor/container/adapter.go @@ -143,8 +143,8 @@ func (c *containerAdapter) pullImage(ctx context.Context) error { } func (c *containerAdapter) createNetworks(ctx context.Context) error { - for _, network := range c.container.networks() { - ncr, err := c.container.networkCreateRequest(network) + for name := range c.container.networksAttachments { + ncr, err := c.container.networkCreateRequest(name) if err != nil { return err } @@ -162,15 +162,15 @@ func (c *containerAdapter) createNetworks(ctx context.Context) error { } func (c *containerAdapter) removeNetworks(ctx context.Context) error { - for _, nid := range c.container.networks() { - if err := c.backend.DeleteManagedNetwork(nid); err != nil { + for name, v := range c.container.networksAttachments { + if err := c.backend.DeleteManagedNetwork(v.Network.ID); err != nil { switch err.(type) { case *libnetwork.ActiveEndpointsError: continue case libnetwork.ErrNoSuchNetwork: continue default: - log.G(ctx).Errorf("network %s remove failed: %v", nid, err) + log.G(ctx).Errorf("network %s remove failed: %v", name, err) return err } } @@ -262,11 +262,7 @@ func (c *containerAdapter) create(ctx context.Context) error { return err } - if err := c.backend.UpdateContainerServiceConfig(cr.ID, c.container.serviceConfig()); err != nil { - return err - } - - return nil + return c.backend.UpdateContainerServiceConfig(cr.ID, c.container.serviceConfig()) } // checkMounts ensures that the provided mounts won't have any host-specific diff --git a/vendor/github.com/docker/docker/daemon/cluster/executor/container/container.go b/vendor/github.com/docker/docker/daemon/cluster/executor/container/container.go index 4f41fb3e2..2ebc6a2d7 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/executor/container/container.go +++ b/vendor/github.com/docker/docker/daemon/cluster/executor/container/container.go @@ -575,19 +575,6 @@ func (c *containerConfig) serviceConfig() *clustertypes.ServiceConfig { return svcCfg } -// networks returns a list of network names attached to the container. The -// returned name can be used to lookup the corresponding network create -// options. -func (c *containerConfig) networks() []string { - var networks []string - - for name := range c.networksAttachments { - networks = append(networks, name) - } - - return networks -} - func (c *containerConfig) networkCreateRequest(name string) (clustertypes.NetworkCreateRequest, error) { na, ok := c.networksAttachments[name] if !ok { diff --git a/vendor/github.com/docker/docker/daemon/cluster/executor/container/controller.go b/vendor/github.com/docker/docker/daemon/cluster/executor/container/controller.go index dda12591a..df14a7a76 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/executor/container/controller.go +++ b/vendor/github.com/docker/docker/daemon/cluster/executor/container/controller.go @@ -183,7 +183,7 @@ func (r *controller) Start(ctx context.Context) error { for { if err := r.adapter.start(ctx); err != nil { - if _, ok := err.(libnetwork.ErrNoSuchNetwork); ok { + if _, ok := errors.Cause(err).(libnetwork.ErrNoSuchNetwork); ok { // Retry network creation again if we // failed because some of the networks // were not found. diff --git a/vendor/github.com/docker/docker/daemon/cluster/executor/container/executor.go b/vendor/github.com/docker/docker/daemon/cluster/executor/container/executor.go index 14e41fa83..b032163f9 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/executor/container/executor.go +++ b/vendor/github.com/docker/docker/daemon/cluster/executor/container/executor.go @@ -146,6 +146,11 @@ func (e *executor) Configure(ctx context.Context, node *api.Node) error { attachments[na.Network.ID] = na.Addresses[0] } + if (ingressNA == nil) && (node.Attachment != nil) { + ingressNA = node.Attachment + attachments[ingressNA.Network.ID] = ingressNA.Addresses[0] + } + if ingressNA == nil { e.backend.ReleaseIngress() return e.backend.GetAttachmentStore().ResetAttachments(attachments) diff --git a/vendor/github.com/docker/docker/daemon/cluster/helpers.go b/vendor/github.com/docker/docker/daemon/cluster/helpers.go index fd50eef66..9541bff39 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/helpers.go +++ b/vendor/github.com/docker/docker/daemon/cluster/helpers.go @@ -3,6 +3,7 @@ package cluster import ( "fmt" + "github.com/docker/docker/errdefs" swarmapi "github.com/docker/swarmkit/api" "github.com/pkg/errors" "golang.org/x/net/context" @@ -48,11 +49,11 @@ func getNode(ctx context.Context, c swarmapi.ControlClient, input string) (*swar if len(rl.Nodes) == 0 { err := fmt.Errorf("node %s not found", input) - return nil, notFoundError{err} + return nil, errdefs.NotFound(err) } if l := len(rl.Nodes); l > 1 { - return nil, ambiguousResultsError{fmt.Errorf("node %s is ambiguous (%d matches found)", input, l)} + return nil, errdefs.InvalidParameter(fmt.Errorf("node %s is ambiguous (%d matches found)", input, l)) } return rl.Nodes[0], nil @@ -84,11 +85,11 @@ func getService(ctx context.Context, c swarmapi.ControlClient, input string, ins if len(rl.Services) == 0 { err := fmt.Errorf("service %s not found", input) - return nil, notFoundError{err} + return nil, errdefs.NotFound(err) } if l := len(rl.Services); l > 1 { - return nil, ambiguousResultsError{fmt.Errorf("service %s is ambiguous (%d matches found)", input, l)} + return nil, errdefs.InvalidParameter(fmt.Errorf("service %s is ambiguous (%d matches found)", input, l)) } if !insertDefaults { @@ -128,11 +129,11 @@ func getTask(ctx context.Context, c swarmapi.ControlClient, input string) (*swar if len(rl.Tasks) == 0 { err := fmt.Errorf("task %s not found", input) - return nil, notFoundError{err} + return nil, errdefs.NotFound(err) } if l := len(rl.Tasks); l > 1 { - return nil, ambiguousResultsError{fmt.Errorf("task %s is ambiguous (%d matches found)", input, l)} + return nil, errdefs.InvalidParameter(fmt.Errorf("task %s is ambiguous (%d matches found)", input, l)) } return rl.Tasks[0], nil @@ -164,11 +165,11 @@ func getSecret(ctx context.Context, c swarmapi.ControlClient, input string) (*sw if len(rl.Secrets) == 0 { err := fmt.Errorf("secret %s not found", input) - return nil, notFoundError{err} + return nil, errdefs.NotFound(err) } if l := len(rl.Secrets); l > 1 { - return nil, ambiguousResultsError{fmt.Errorf("secret %s is ambiguous (%d matches found)", input, l)} + return nil, errdefs.InvalidParameter(fmt.Errorf("secret %s is ambiguous (%d matches found)", input, l)) } return rl.Secrets[0], nil @@ -200,11 +201,11 @@ func getConfig(ctx context.Context, c swarmapi.ControlClient, input string) (*sw if len(rl.Configs) == 0 { err := fmt.Errorf("config %s not found", input) - return nil, notFoundError{err} + return nil, errdefs.NotFound(err) } if l := len(rl.Configs); l > 1 { - return nil, ambiguousResultsError{fmt.Errorf("config %s is ambiguous (%d matches found)", input, l)} + return nil, errdefs.InvalidParameter(fmt.Errorf("config %s is ambiguous (%d matches found)", input, l)) } return rl.Configs[0], nil @@ -238,7 +239,7 @@ func getNetwork(ctx context.Context, c swarmapi.ControlClient, input string) (*s } if l := len(rl.Networks); l > 1 { - return nil, ambiguousResultsError{fmt.Errorf("network %s is ambiguous (%d matches found)", input, l)} + return nil, errdefs.InvalidParameter(fmt.Errorf("network %s is ambiguous (%d matches found)", input, l)) } return rl.Networks[0], nil diff --git a/vendor/github.com/docker/docker/daemon/cluster/listen_addr_linux.go b/vendor/github.com/docker/docker/daemon/cluster/listen_addr_linux.go index 3d4f239bd..2f342fd60 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/listen_addr_linux.go +++ b/vendor/github.com/docker/docker/daemon/cluster/listen_addr_linux.go @@ -1,5 +1,3 @@ -// +build linux - package cluster import ( diff --git a/vendor/github.com/docker/docker/daemon/cluster/listen_addr_solaris.go b/vendor/github.com/docker/docker/daemon/cluster/listen_addr_solaris.go deleted file mode 100644 index 57a894b25..000000000 --- a/vendor/github.com/docker/docker/daemon/cluster/listen_addr_solaris.go +++ /dev/null @@ -1,57 +0,0 @@ -package cluster - -import ( - "bufio" - "fmt" - "net" - "os/exec" - "strings" -) - -func (c *Cluster) resolveSystemAddr() (net.IP, error) { - defRouteCmd := "/usr/sbin/ipadm show-addr -p -o addr " + - "`/usr/sbin/route get default | /usr/bin/grep interface | " + - "/usr/bin/awk '{print $2}'`" - out, err := exec.Command("/usr/bin/bash", "-c", defRouteCmd).Output() - if err != nil { - return nil, fmt.Errorf("cannot get default route: %v", err) - } - - defInterface := strings.SplitN(string(out), "/", 2) - defInterfaceIP := net.ParseIP(defInterface[0]) - - return defInterfaceIP, nil -} - -func listSystemIPs() []net.IP { - var systemAddrs []net.IP - cmd := exec.Command("/usr/sbin/ipadm", "show-addr", "-p", "-o", "addr") - cmdReader, err := cmd.StdoutPipe() - if err != nil { - return nil - } - - if err := cmd.Start(); err != nil { - return nil - } - - scanner := bufio.NewScanner(cmdReader) - go func() { - for scanner.Scan() { - text := scanner.Text() - nameAddrPair := strings.SplitN(text, "/", 2) - // Let go of loopback interfaces and docker interfaces - systemAddrs = append(systemAddrs, net.ParseIP(nameAddrPair[0])) - } - }() - - if err := scanner.Err(); err != nil { - fmt.Printf("scan underwent err: %+v\n", err) - } - - if err := cmd.Wait(); err != nil { - fmt.Printf("run command wait: %+v\n", err) - } - - return systemAddrs -} diff --git a/vendor/github.com/docker/docker/daemon/cluster/networks.go b/vendor/github.com/docker/docker/daemon/cluster/networks.go index 04582eb31..4e92e0eed 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/networks.go +++ b/vendor/github.com/docker/docker/daemon/cluster/networks.go @@ -7,6 +7,7 @@ import ( "github.com/docker/docker/api/types/network" types "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/daemon/cluster/convert" + "github.com/docker/docker/errdefs" "github.com/docker/docker/runconfig" swarmapi "github.com/docker/swarmkit/api" "github.com/pkg/errors" @@ -298,7 +299,7 @@ func (c *Cluster) populateNetworkID(ctx context.Context, client swarmapi.Control // and use its id for the request. apiNetwork, err = getNetwork(ctx, client, ln.Name()) if err != nil { - return errors.Wrap(notFoundError{err}, "could not find the corresponding predefined swarm network") + return errors.Wrap(errdefs.NotFound(err), "could not find the corresponding predefined swarm network") } goto setid } diff --git a/vendor/github.com/docker/docker/daemon/cluster/nodes.go b/vendor/github.com/docker/docker/daemon/cluster/nodes.go index 582e7cdc7..879d272e7 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/nodes.go +++ b/vendor/github.com/docker/docker/daemon/cluster/nodes.go @@ -4,6 +4,7 @@ import ( apitypes "github.com/docker/docker/api/types" types "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/daemon/cluster/convert" + "github.com/docker/docker/errdefs" swarmapi "github.com/docker/swarmkit/api" "golang.org/x/net/context" ) @@ -64,7 +65,7 @@ func (c *Cluster) UpdateNode(input string, version uint64, spec types.NodeSpec) return c.lockedManagerAction(func(ctx context.Context, state nodeState) error { nodeSpec, err := convert.NodeSpecToGRPC(spec) if err != nil { - return convertError{err} + return errdefs.InvalidParameter(err) } ctx, cancel := c.getRequestContext() diff --git a/vendor/github.com/docker/docker/daemon/cluster/services.go b/vendor/github.com/docker/docker/daemon/cluster/services.go index f3fba8d9d..931d17c75 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/services.go +++ b/vendor/github.com/docker/docker/daemon/cluster/services.go @@ -16,6 +16,7 @@ import ( types "github.com/docker/docker/api/types/swarm" timetypes "github.com/docker/docker/api/types/time" "github.com/docker/docker/daemon/cluster/convert" + "github.com/docker/docker/errdefs" runconfigopts "github.com/docker/docker/runconfig/opts" swarmapi "github.com/docker/swarmkit/api" gogotypes "github.com/gogo/protobuf/types" @@ -128,7 +129,7 @@ func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string, queryRe serviceSpec, err := convert.ServiceSpecToGRPC(s) if err != nil { - return convertError{err} + return errdefs.InvalidParameter(err) } resp = &apitypes.ServiceCreateResponse{} @@ -232,7 +233,7 @@ func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec typ serviceSpec, err := convert.ServiceSpecToGRPC(spec) if err != nil { - return convertError{err} + return errdefs.InvalidParameter(err) } currentService, err := getService(ctx, state.controlClient, serviceIDOrName, false) diff --git a/vendor/github.com/docker/docker/daemon/cluster/swarm.go b/vendor/github.com/docker/docker/daemon/cluster/swarm.go index 61223691b..3c7a23b71 100644 --- a/vendor/github.com/docker/docker/daemon/cluster/swarm.go +++ b/vendor/github.com/docker/docker/daemon/cluster/swarm.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/types/filters" types "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/daemon/cluster/convert" + "github.com/docker/docker/errdefs" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/signal" swarmapi "github.com/docker/swarmkit/api" @@ -44,7 +45,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) { } if err := validateAndSanitizeInitRequest(&req); err != nil { - return "", validationError{err} + return "", errdefs.InvalidParameter(err) } listenHost, listenPort, err := resolveListenAddr(req.ListenAddr) @@ -140,7 +141,7 @@ func (c *Cluster) Join(req types.JoinRequest) error { c.mu.Unlock() if err := validateAndSanitizeJoinRequest(&req); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } listenHost, listenPort, err := resolveListenAddr(req.ListenAddr) @@ -228,12 +229,19 @@ func (c *Cluster) Update(version uint64, spec types.Spec, flags types.UpdateFlag return err } + // Validate spec name. + if spec.Annotations.Name == "" { + spec.Annotations.Name = "default" + } else if spec.Annotations.Name != "default" { + return errdefs.InvalidParameter(errors.New(`swarm spec must be named "default"`)) + } + // In update, client should provide the complete spec of the swarm, including // Name and Labels. If a field is specified with 0 or nil, then the default value // will be used to swarmkit. clusterSpec, err := convert.SwarmSpecToGRPC(spec) if err != nil { - return convertError{err} + return errdefs.InvalidParameter(err) } _, err = state.controlClient.UpdateCluster( @@ -304,7 +312,7 @@ func (c *Cluster) UnlockSwarm(req types.UnlockRequest) error { key, err := encryption.ParseHumanReadableKey(req.UnlockKey) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } config := nr.config diff --git a/vendor/github.com/docker/docker/daemon/commit.go b/vendor/github.com/docker/docker/daemon/commit.go index 005313224..de621168a 100644 --- a/vendor/github.com/docker/docker/daemon/commit.go +++ b/vendor/github.com/docker/docker/daemon/commit.go @@ -13,9 +13,11 @@ import ( containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/builder/dockerfile" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/ioutils" + "github.com/docker/docker/pkg/system" "github.com/pkg/errors" ) @@ -136,20 +138,27 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str if container.IsDead() { err := fmt.Errorf("You cannot commit container %s which is Dead", container.ID) - return "", stateConflictError{err} + return "", errdefs.Conflict(err) } if container.IsRemovalInProgress() { err := fmt.Errorf("You cannot commit container %s which is being removed", container.ID) - return "", stateConflictError{err} + return "", errdefs.Conflict(err) } if c.Pause && !container.IsPaused() { daemon.containerPause(container) defer daemon.containerUnpause(container) } + if !system.IsOSSupported(container.OS) { + return "", system.ErrNotSupportedOperatingSystem + } - newConfig, err := dockerfile.BuildFromConfig(c.Config, c.Changes) + if c.MergeConfigs && c.Config == nil { + c.Config = container.Config + } + + newConfig, err := dockerfile.BuildFromConfig(c.Config, c.Changes, container.OS) if err != nil { return "", err } @@ -175,17 +184,17 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str parent = new(image.Image) parent.RootFS = image.NewRootFS() } else { - parent, err = daemon.stores[container.OS].imageStore.Get(container.ImageID) + parent, err = daemon.imageStore.Get(container.ImageID) if err != nil { return "", err } } - l, err := daemon.stores[container.OS].layerStore.Register(rwTar, parent.RootFS.ChainID(), layer.OS(container.OS)) + l, err := daemon.layerStores[container.OS].Register(rwTar, parent.RootFS.ChainID()) if err != nil { return "", err } - defer layer.ReleaseAndLog(daemon.stores[container.OS].layerStore, l) + defer layer.ReleaseAndLog(daemon.layerStores[container.OS], l) containerConfig := c.ContainerConfig if containerConfig == nil { @@ -204,13 +213,13 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str return "", err } - id, err := daemon.stores[container.OS].imageStore.Create(config) + id, err := daemon.imageStore.Create(config) if err != nil { return "", err } if container.ImageID != "" { - if err := daemon.stores[container.OS].imageStore.SetParent(id, container.ImageID); err != nil { + if err := daemon.imageStore.SetParent(id, container.ImageID); err != nil { return "", err } } @@ -229,7 +238,7 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str return "", err } } - if err := daemon.TagImageWithReference(id, container.OS, newTag); err != nil { + if err := daemon.TagImageWithReference(id, newTag); err != nil { return "", err } imageRef = reference.FamiliarString(newTag) @@ -246,13 +255,14 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str } func (daemon *Daemon) exportContainerRw(container *container.Container) (arch io.ReadCloser, err error) { - rwlayer, err := daemon.stores[container.OS].layerStore.GetRWLayer(container.ID) + // Note: Indexing by OS is safe as only called from `Commit` which has already performed validation + rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID) if err != nil { return nil, err } defer func() { if err != nil { - daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer) + daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer) } }() @@ -273,7 +283,7 @@ func (daemon *Daemon) exportContainerRw(container *container.Container) (arch io return ioutils.NewReadCloserWrapper(archive, func() error { archive.Close() err = rwlayer.Unmount() - daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer) + daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer) return err }), nil diff --git a/vendor/github.com/docker/docker/daemon/config/config.go b/vendor/github.com/docker/docker/daemon/config/config.go index 1e22a6fea..1466c0b71 100644 --- a/vendor/github.com/docker/docker/daemon/config/config.go +++ b/vendor/github.com/docker/docker/daemon/config/config.go @@ -85,26 +85,27 @@ type CommonTLSOptions struct { // It includes json tags to deserialize configuration from a file // using the same names that the flags in the command line use. type CommonConfig struct { - AuthzMiddleware *authorization.Middleware `json:"-"` - AuthorizationPlugins []string `json:"authorization-plugins,omitempty"` // AuthorizationPlugins holds list of authorization plugins - AutoRestart bool `json:"-"` - Context map[string][]string `json:"-"` - DisableBridge bool `json:"-"` - DNS []string `json:"dns,omitempty"` - DNSOptions []string `json:"dns-opts,omitempty"` - DNSSearch []string `json:"dns-search,omitempty"` - ExecOptions []string `json:"exec-opts,omitempty"` - GraphDriver string `json:"storage-driver,omitempty"` - GraphOptions []string `json:"storage-opts,omitempty"` - Labels []string `json:"labels,omitempty"` - Mtu int `json:"mtu,omitempty"` - Pidfile string `json:"pidfile,omitempty"` - RawLogs bool `json:"raw-logs,omitempty"` - RootDeprecated string `json:"graph,omitempty"` - Root string `json:"data-root,omitempty"` - ExecRoot string `json:"exec-root,omitempty"` - SocketGroup string `json:"group,omitempty"` - CorsHeaders string `json:"api-cors-header,omitempty"` + AuthzMiddleware *authorization.Middleware `json:"-"` + AuthorizationPlugins []string `json:"authorization-plugins,omitempty"` // AuthorizationPlugins holds list of authorization plugins + AutoRestart bool `json:"-"` + Context map[string][]string `json:"-"` + DisableBridge bool `json:"-"` + DNS []string `json:"dns,omitempty"` + DNSOptions []string `json:"dns-opts,omitempty"` + DNSSearch []string `json:"dns-search,omitempty"` + ExecOptions []string `json:"exec-opts,omitempty"` + GraphDriver string `json:"storage-driver,omitempty"` + GraphOptions []string `json:"storage-opts,omitempty"` + Labels []string `json:"labels,omitempty"` + Mtu int `json:"mtu,omitempty"` + NetworkDiagnosticPort int `json:"network-diagnostic-port,omitempty"` + Pidfile string `json:"pidfile,omitempty"` + RawLogs bool `json:"raw-logs,omitempty"` + RootDeprecated string `json:"graph,omitempty"` + Root string `json:"data-root,omitempty"` + ExecRoot string `json:"exec-root,omitempty"` + SocketGroup string `json:"group,omitempty"` + CorsHeaders string `json:"api-cors-header,omitempty"` // TrustKeyPath is used to generate the daemon ID and for signing schema 1 manifests // when pushing to a registry which does not support schema 2. This field is marked as @@ -166,7 +167,7 @@ type CommonConfig struct { sync.Mutex // FIXME(vdemeester) This part is not that clear and is mainly dependent on cli flags // It should probably be handled outside this package. - ValuesSet map[string]interface{} + ValuesSet map[string]interface{} `json:"-"` Experimental bool `json:"experimental"` // Experimental indicates whether experimental features should be exposed or not @@ -510,11 +511,7 @@ func Validate(config *Config) error { } // validate platform-specific settings - if err := config.ValidatePlatformConfig(); err != nil { - return err - } - - return nil + return config.ValidatePlatformConfig() } // ModifiedDiscoverySettings returns whether the discovery configuration has been modified or not. diff --git a/vendor/github.com/docker/docker/daemon/config/config_solaris.go b/vendor/github.com/docker/docker/daemon/config/config_solaris.go deleted file mode 100644 index 6b1e061b5..000000000 --- a/vendor/github.com/docker/docker/daemon/config/config_solaris.go +++ /dev/null @@ -1,30 +0,0 @@ -package config - -// Config defines the configuration of a docker daemon. -// These are the configuration settings that you pass -// to the docker daemon when you launch it with say: `docker -d -e lxc` -type Config struct { - CommonConfig - - // These fields are common to all unix platforms. - CommonUnixConfig -} - -// BridgeConfig stores all the bridge driver specific -// configuration. -type BridgeConfig struct { - commonBridgeConfig - - // Fields below here are platform specific. - commonUnixBridgeConfig -} - -// IsSwarmCompatible defines if swarm mode can be enabled in this config -func (conf *Config) IsSwarmCompatible() error { - return nil -} - -// ValidatePlatformConfig checks if any platform-specific configuration settings are invalid. -func (conf *Config) ValidatePlatformConfig() error { - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/configs_linux.go b/vendor/github.com/docker/docker/daemon/configs_linux.go index af20ad78b..d498c951e 100644 --- a/vendor/github.com/docker/docker/daemon/configs_linux.go +++ b/vendor/github.com/docker/docker/daemon/configs_linux.go @@ -1,5 +1,3 @@ -// +build linux - package daemon func configsSupported() bool { diff --git a/vendor/github.com/docker/docker/daemon/configs_windows.go b/vendor/github.com/docker/docker/daemon/configs_windows.go index 7cb2e9c43..d498c951e 100644 --- a/vendor/github.com/docker/docker/daemon/configs_windows.go +++ b/vendor/github.com/docker/docker/daemon/configs_windows.go @@ -1,5 +1,3 @@ -// +build windows - package daemon func configsSupported() bool { diff --git a/vendor/github.com/docker/docker/daemon/container.go b/vendor/github.com/docker/docker/daemon/container.go index 26faedfdf..d55c98f5a 100644 --- a/vendor/github.com/docker/docker/daemon/container.go +++ b/vendor/github.com/docker/docker/daemon/container.go @@ -13,12 +13,14 @@ import ( "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/container" "github.com/docker/docker/daemon/network" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/truncindex" "github.com/docker/docker/runconfig" + "github.com/docker/docker/volume" "github.com/docker/go-connections/nat" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" @@ -53,7 +55,7 @@ func (daemon *Daemon) GetContainer(prefixOrName string) (*container.Container, e if indexError == truncindex.ErrNotExist { return nil, containerNotFound(prefixOrName) } - return nil, systemError{indexError} + return nil, errdefs.System(indexError) } return daemon.containers.Get(containerID), nil } @@ -138,7 +140,7 @@ func (daemon *Daemon) newContainer(name string, operatingSystem string, config * if config.Hostname == "" { config.Hostname, err = os.Hostname() if err != nil { - return nil, systemError{err} + return nil, errdefs.System(err) } } } else { @@ -293,6 +295,14 @@ func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *conta return nil, errors.Errorf("can't create 'AutoRemove' container with restart policy") } + // Validate mounts; check if host directories still exist + parser := volume.NewParser(platform) + for _, cfg := range hostConfig.Mounts { + if err := parser.ValidateMountConfig(&cfg); err != nil { + return nil, err + } + } + for _, extraHost := range hostConfig.ExtraHosts { if _, err := opts.ValidateExtraHost(extraHost); err != nil { return nil, err diff --git a/vendor/github.com/docker/docker/daemon/container_linux.go b/vendor/github.com/docker/docker/daemon/container_linux.go index d05992d0f..d63f4b72a 100644 --- a/vendor/github.com/docker/docker/daemon/container_linux.go +++ b/vendor/github.com/docker/docker/daemon/container_linux.go @@ -4,6 +4,7 @@ package daemon import ( "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" ) func (daemon *Daemon) saveApparmorConfig(container *container.Container) error { @@ -14,7 +15,7 @@ func (daemon *Daemon) saveApparmorConfig(container *container.Container) error { } if err := parseSecurityOpt(container, container.HostConfig); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } if !container.HostConfig.Privileged { diff --git a/vendor/github.com/docker/docker/daemon/container_operations.go b/vendor/github.com/docker/docker/daemon/container_operations.go index fc08f8263..3900e95e8 100644 --- a/vendor/github.com/docker/docker/daemon/container_operations.go +++ b/vendor/github.com/docker/docker/daemon/container_operations.go @@ -14,6 +14,7 @@ import ( networktypes "github.com/docker/docker/api/types/network" "github.com/docker/docker/container" "github.com/docker/docker/daemon/network" + "github.com/docker/docker/errdefs" "github.com/docker/docker/opts" "github.com/docker/docker/pkg/stringid" "github.com/docker/docker/runconfig" @@ -251,8 +252,8 @@ func (daemon *Daemon) updateNetworkSettings(container *container.Container, n li return runconfig.ErrConflictHostNetwork } - for s := range container.NetworkSettings.Networks { - sn, err := daemon.FindNetwork(s) + for s, v := range container.NetworkSettings.Networks { + sn, err := daemon.FindNetwork(getNetworkID(s, v.EndpointSettings)) if err != nil { continue } @@ -308,8 +309,8 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error { // Find if container is connected to the default bridge network var n libnetwork.Network - for name := range container.NetworkSettings.Networks { - sn, err := daemon.FindNetwork(name) + for name, v := range container.NetworkSettings.Networks { + sn, err := daemon.FindNetwork(getNetworkID(name, v.EndpointSettings)) if err != nil { continue } @@ -339,7 +340,7 @@ func (daemon *Daemon) updateNetwork(container *container.Container) error { } func (daemon *Daemon) findAndAttachNetwork(container *container.Container, idOrName string, epConfig *networktypes.EndpointSettings) (libnetwork.Network, *networktypes.NetworkingConfig, error) { - n, err := daemon.FindNetwork(idOrName) + n, err := daemon.FindNetwork(getNetworkID(idOrName, epConfig)) if err != nil { // We should always be able to find the network for a // managed container. @@ -377,16 +378,16 @@ func (daemon *Daemon) findAndAttachNetwork(container *container.Container, idOrN // trigger attachment in the swarm cluster manager. if daemon.clusterProvider != nil { var err error - config, err = daemon.clusterProvider.AttachNetwork(idOrName, container.ID, addresses) + config, err = daemon.clusterProvider.AttachNetwork(getNetworkID(idOrName, epConfig), container.ID, addresses) if err != nil { return nil, nil, err } } - n, err = daemon.FindNetwork(idOrName) + n, err = daemon.FindNetwork(getNetworkID(idOrName, epConfig)) if err != nil { if daemon.clusterProvider != nil { - if err := daemon.clusterProvider.DetachNetwork(idOrName, container.ID); err != nil { + if err := daemon.clusterProvider.DetachNetwork(getNetworkID(idOrName, epConfig), container.ID); err != nil { logrus.Warnf("Could not rollback attachment for container %s to network %s: %v", container.ID, idOrName, err) } } @@ -922,7 +923,7 @@ func (daemon *Daemon) getNetworkedContainer(containerID, connectedContainerID st } if !nc.IsRunning() { err := fmt.Errorf("cannot join network of a non running container: %s", connectedContainerID) - return nil, stateConflictError{err} + return nil, errdefs.Conflict(err) } if nc.IsRestarting() { return nil, errContainerIsRestarting(connectedContainerID) @@ -949,7 +950,7 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) { var networks []libnetwork.Network for n, epSettings := range settings { - if nw, err := daemon.FindNetwork(n); err == nil { + if nw, err := daemon.FindNetwork(getNetworkID(n, epSettings.EndpointSettings)); err == nil { networks = append(networks, nw) } @@ -965,6 +966,9 @@ func (daemon *Daemon) releaseNetwork(container *container.Container) { logrus.Warnf("error locating sandbox id %s: %v", sid, err) return } + if err := sb.DisableService(); err != nil { + logrus.WithFields(logrus.Fields{"container": container.ID, "sandbox": sid}).WithError(err).Error("Error removing service from sandbox") + } if err := sb.Delete(); err != nil { logrus.Errorf("Error deleting sandbox id %s for container %s: %v", sid, container.ID, err) @@ -1087,3 +1091,12 @@ func (daemon *Daemon) DeactivateContainerServiceBinding(containerName string) er } return sb.DisableService() } + +func getNetworkID(name string, endpointSettings *networktypes.EndpointSettings) string { + // We only want to prefer NetworkID for user defined networks. + // For systems like bridge, none, etc. the name is preferred (otherwise restart may cause issues) + if containertypes.NetworkMode(name).IsUserDefined() && endpointSettings != nil && endpointSettings.NetworkID != "" { + return endpointSettings.NetworkID + } + return name +} diff --git a/vendor/github.com/docker/docker/daemon/container_operations_unix.go b/vendor/github.com/docker/docker/daemon/container_operations_unix.go index 09b9b3f4b..a123df3a9 100644 --- a/vendor/github.com/docker/docker/daemon/container_operations_unix.go +++ b/vendor/github.com/docker/docker/daemon/container_operations_unix.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/daemon/links" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/stringid" @@ -91,7 +92,7 @@ func (daemon *Daemon) getPidContainer(container *container.Container) (*containe func containerIsRunning(c *container.Container) error { if !c.IsRunning() { - return stateConflictError{errors.Errorf("container %s is not running", c.ID)} + return errdefs.Conflict(errors.Errorf("container %s is not running", c.ID)) } return nil } @@ -164,7 +165,10 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { return nil } - localMountPath := c.SecretMountPath() + localMountPath, err := c.SecretMountPath() + if err != nil { + return errors.Wrap(err, "error getting secrets mount dir") + } logrus.Debugf("secrets: setting up secret dir: %s", localMountPath) // retrieve possible remapped range start for root UID, GID @@ -203,7 +207,10 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { // secrets are created in the SecretMountPath on the host, at a // single level - fPath := c.SecretFilePath(*s) + fPath, err := c.SecretFilePath(*s) + if err != nil { + return errors.Wrap(err, "error getting secret file path") + } if err := idtools.MkdirAllAndChown(filepath.Dir(fPath), 0700, rootIDs); err != nil { return errors.Wrap(err, "error creating secret mount path") } @@ -249,7 +256,10 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) { return nil } - localPath := c.ConfigsDirPath() + localPath, err := c.ConfigsDirPath() + if err != nil { + return err + } logrus.Debugf("configs: setting up config dir: %s", localPath) // retrieve possible remapped range start for root UID, GID @@ -278,7 +288,10 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) { continue } - fPath := c.ConfigFilePath(*configRef) + fPath, err := c.ConfigFilePath(*configRef) + if err != nil { + return err + } log := logrus.WithFields(logrus.Fields{"name": configRef.File.Name, "path": fPath}) @@ -378,3 +391,22 @@ func (daemon *Daemon) initializeNetworkingPaths(container *container.Container, container.ResolvConfPath = nc.ResolvConfPath return nil } + +func (daemon *Daemon) setupContainerMountsRoot(c *container.Container) error { + // get the root mount path so we can make it unbindable + p, err := c.MountsResourcePath("") + if err != nil { + return err + } + + if err := idtools.MkdirAllAndChown(p, 0700, daemon.idMappings.RootPair()); err != nil { + return err + } + + if err := mount.MakeUnbindable(p); err != nil { + // Setting unbindable is a precaution and is not neccessary for correct operation. + // Do not error out if this fails. + logrus.WithError(err).WithField("resource", p).WithField("container", c.ID).Warn("Error setting container resource mounts to unbindable, this may cause mount leakages, preventing removal of this container.") + } + return nil +} diff --git a/vendor/github.com/docker/docker/daemon/container_operations_windows.go b/vendor/github.com/docker/docker/daemon/container_operations_windows.go index 51762a244..c762fc99c 100644 --- a/vendor/github.com/docker/docker/daemon/container_operations_windows.go +++ b/vendor/github.com/docker/docker/daemon/container_operations_windows.go @@ -21,7 +21,10 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) { return nil } - localPath := c.ConfigsDirPath() + localPath, err := c.ConfigsDirPath() + if err != nil { + return err + } logrus.Debugf("configs: setting up config dir: %s", localPath) // create local config root @@ -48,7 +51,10 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) { continue } - fPath := c.ConfigFilePath(*configRef) + fPath, err := c.ConfigFilePath(*configRef) + if err != nil { + return err + } log := logrus.WithFields(logrus.Fields{"name": configRef.File.Name, "path": fPath}) @@ -94,7 +100,10 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { return nil } - localMountPath := c.SecretMountPath() + localMountPath, err := c.SecretMountPath() + if err != nil { + return err + } logrus.Debugf("secrets: setting up secret dir: %s", localMountPath) // create local secret root @@ -123,7 +132,10 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { // secrets are created in the SecretMountPath on the host, at a // single level - fPath := c.SecretFilePath(*s) + fPath, err := c.SecretFilePath(*s) + if err != nil { + return err + } logrus.WithFields(logrus.Fields{ "name": s.File.Name, "path": fPath, diff --git a/vendor/github.com/docker/docker/daemon/container_windows.go b/vendor/github.com/docker/docker/daemon/container_windows.go index 6fdd1e678..6db130ab0 100644 --- a/vendor/github.com/docker/docker/daemon/container_windows.go +++ b/vendor/github.com/docker/docker/daemon/container_windows.go @@ -1,5 +1,3 @@ -//+build windows - package daemon import ( diff --git a/vendor/github.com/docker/docker/daemon/create.go b/vendor/github.com/docker/docker/daemon/create.go index e4d17cc2d..4ba5ad9e2 100644 --- a/vendor/github.com/docker/docker/daemon/create.go +++ b/vendor/github.com/docker/docker/daemon/create.go @@ -13,6 +13,7 @@ import ( containertypes "github.com/docker/docker/api/types/container" networktypes "github.com/docker/docker/api/types/network" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/idtools" @@ -36,7 +37,7 @@ func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (conta func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, managed bool) (containertypes.ContainerCreateCreatedBody, error) { start := time.Now() if params.Config == nil { - return containertypes.ContainerCreateCreatedBody{}, validationError{errors.New("Config cannot be empty in order to create a container")} + return containertypes.ContainerCreateCreatedBody{}, errdefs.InvalidParameter(errors.New("Config cannot be empty in order to create a container")) } os := runtime.GOOS @@ -55,12 +56,12 @@ func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, manage warnings, err := daemon.verifyContainerSettings(os, params.HostConfig, params.Config, false) if err != nil { - return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, validationError{err} + return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, errdefs.InvalidParameter(err) } err = verifyNetworkingConfig(params.NetworkingConfig) if err != nil { - return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, validationError{err} + return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, errdefs.InvalidParameter(err) } if params.HostConfig == nil { @@ -68,7 +69,7 @@ func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, manage } err = daemon.adaptContainerSettings(params.HostConfig, params.AdjustCPUShares) if err != nil { - return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, validationError{err} + return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, errdefs.InvalidParameter(err) } container, err := daemon.create(params, managed) @@ -115,11 +116,11 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) ( } if err := daemon.mergeAndVerifyConfig(params.Config, img); err != nil { - return nil, validationError{err} + return nil, errdefs.InvalidParameter(err) } if err := daemon.mergeAndVerifyLogConfig(¶ms.HostConfig.LogConfig); err != nil { - return nil, validationError{err} + return nil, errdefs.InvalidParameter(err) } if container, err = daemon.newContainer(params.Name, os, params.Config, params.HostConfig, imgID, managed); err != nil { @@ -158,7 +159,7 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) ( // Set RWLayer for container after mount labels have been set if err := daemon.setRWLayer(container); err != nil { - return nil, systemError{err} + return nil, errdefs.System(err) } rootIDs := daemon.idMappings.RootPair() @@ -256,7 +257,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig) func (daemon *Daemon) setRWLayer(container *container.Container) error { var layerID layer.ChainID if container.ImageID != "" { - img, err := daemon.stores[container.OS].imageStore.Get(container.ImageID) + img, err := daemon.imageStore.Get(container.ImageID) if err != nil { return err } @@ -269,7 +270,9 @@ func (daemon *Daemon) setRWLayer(container *container.Container) error { StorageOpt: container.HostConfig.StorageOpt, } - rwLayer, err := daemon.stores[container.OS].layerStore.CreateRWLayer(container.ID, layerID, rwLayerOpts) + // Indexing by OS is safe here as validation of OS has already been performed in create() (the only + // caller), and guaranteed non-nil + rwLayer, err := daemon.layerStores[container.OS].CreateRWLayer(container.ID, layerID, rwLayerOpts) if err != nil { return err } diff --git a/vendor/github.com/docker/docker/daemon/daemon.go b/vendor/github.com/docker/docker/daemon/daemon.go index 96b39e882..16510316b 100644 --- a/vendor/github.com/docker/docker/daemon/daemon.go +++ b/vendor/github.com/docker/docker/daemon/daemon.go @@ -18,7 +18,6 @@ import ( "sync" "time" - "github.com/docker/docker/api/errdefs" "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/swarm" @@ -29,6 +28,7 @@ import ( "github.com/docker/docker/daemon/exec" "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/network" + "github.com/docker/docker/errdefs" "github.com/sirupsen/logrus" // register graph drivers _ "github.com/docker/docker/daemon/graphdriver/register" @@ -62,57 +62,53 @@ import ( "github.com/pkg/errors" ) -// MainNamespace is the name of the namespace used for users containers -const MainNamespace = "moby" +// ContainersNamespace is the name of the namespace used for users containers +const ContainersNamespace = "moby" var ( errSystemNotSupported = errors.New("the Docker daemon is not supported on this platform") ) -type daemonStore struct { - graphDriver string - imageRoot string - imageStore image.Store - layerStore layer.Store - distributionMetadataStore dmetadata.Store -} - // Daemon holds information about the Docker daemon. type Daemon struct { - ID string - repository string - containers container.Store - containersReplica container.ViewDB - execCommands *exec.Store - downloadManager *xfer.LayerDownloadManager - uploadManager *xfer.LayerUploadManager - trustKey libtrust.PrivateKey - idIndex *truncindex.TruncIndex - configStore *config.Config - statsCollector *stats.Collector - defaultLogConfig containertypes.LogConfig - RegistryService registry.Service - EventsService *events.Events - netController libnetwork.NetworkController - volumes *store.VolumeStore - discoveryWatcher discovery.Reloader - root string - seccompEnabled bool - apparmorEnabled bool - shutdown bool - idMappings *idtools.IDMappings - stores map[string]daemonStore // By container target platform - referenceStore refstore.Store - PluginStore *plugin.Store // todo: remove - pluginManager *plugin.Manager - linkIndex *linkIndex - containerd libcontainerd.Client - containerdRemote libcontainerd.Remote - defaultIsolation containertypes.Isolation // Default isolation mode on Windows - clusterProvider cluster.Provider - cluster Cluster - genericResources []swarm.GenericResource - metricsPluginListener net.Listener + ID string + repository string + containers container.Store + containersReplica container.ViewDB + execCommands *exec.Store + downloadManager *xfer.LayerDownloadManager + uploadManager *xfer.LayerUploadManager + trustKey libtrust.PrivateKey + idIndex *truncindex.TruncIndex + configStore *config.Config + statsCollector *stats.Collector + defaultLogConfig containertypes.LogConfig + RegistryService registry.Service + EventsService *events.Events + netController libnetwork.NetworkController + volumes *store.VolumeStore + discoveryWatcher discovery.Reloader + root string + seccompEnabled bool + apparmorEnabled bool + shutdown bool + idMappings *idtools.IDMappings + graphDrivers map[string]string // By operating system + referenceStore refstore.Store + imageStore image.Store + imageRoot string + layerStores map[string]layer.Store // By operating system + distributionMetadataStore dmetadata.Store + PluginStore *plugin.Store // todo: remove + pluginManager *plugin.Manager + linkIndex *linkIndex + containerd libcontainerd.Client + containerdRemote libcontainerd.Remote + defaultIsolation containertypes.Isolation // Default isolation mode on Windows + clusterProvider cluster.Provider + cluster Cluster + genericResources []swarm.GenericResource + metricsPluginListener net.Listener machineMemory uint64 @@ -159,11 +155,14 @@ func (daemon *Daemon) restore() error { logrus.Errorf("Failed to load container %v: %v", id, err) continue } - + if !system.IsOSSupported(container.OS) { + logrus.Errorf("Failed to load container %v: %s (%q)", id, system.ErrNotSupportedOperatingSystem, container.OS) + continue + } // Ignore the container if it does not support the current driver being used by the graph - currentDriverForContainerOS := daemon.stores[container.OS].graphDriver + currentDriverForContainerOS := daemon.graphDrivers[container.OS] if (container.Driver == "" && currentDriverForContainerOS == "aufs") || container.Driver == currentDriverForContainerOS { - rwlayer, err := daemon.stores[container.OS].layerStore.GetRWLayer(container.ID) + rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID) if err != nil { logrus.Errorf("Failed to load container mount %v: %v", id, err) continue @@ -247,6 +246,11 @@ func (daemon *Daemon) restore() error { logrus.WithError(err).Errorf("Failed to delete container %s from containerd", c.ID) return } + } else if !daemon.configStore.LiveRestoreEnabled { + if err := daemon.kill(c, c.StopSignal()); err != nil && !errdefs.IsNotFound(err) { + logrus.WithError(err).WithField("container", c.ID).Error("error shutting down container") + return + } } if c.IsRunning() || c.IsPaused() { @@ -317,24 +321,24 @@ func (daemon *Daemon) restore() error { activeSandboxes[c.NetworkSettings.SandboxID] = options mapLock.Unlock() } - } else { - // get list of containers we need to restart + } - // Do not autostart containers which - // has endpoints in a swarm scope - // network yet since the cluster is - // not initialized yet. We will start - // it after the cluster is - // initialized. - if daemon.configStore.AutoRestart && c.ShouldRestart() && !c.NetworkSettings.HasSwarmEndpoint { - mapLock.Lock() - restartContainers[c] = make(chan struct{}) - mapLock.Unlock() - } else if c.HostConfig != nil && c.HostConfig.AutoRemove { - mapLock.Lock() - removeContainers[c.ID] = c - mapLock.Unlock() - } + // get list of containers we need to restart + + // Do not autostart containers which + // has endpoints in a swarm scope + // network yet since the cluster is + // not initialized yet. We will start + // it after the cluster is + // initialized. + if daemon.configStore.AutoRestart && c.ShouldRestart() && !c.NetworkSettings.HasSwarmEndpoint { + mapLock.Lock() + restartContainers[c] = make(chan struct{}) + mapLock.Unlock() + } else if c.HostConfig != nil && c.HostConfig.AutoRemove { + mapLock.Lock() + removeContainers[c.ID] = c + mapLock.Unlock() } c.Lock() @@ -675,14 +679,14 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe } daemonRepo := filepath.Join(config.Root, "containers") - if err := idtools.MkdirAllAndChown(daemonRepo, 0700, rootIDs); err != nil && !os.IsExist(err) { + if err := idtools.MkdirAllAndChown(daemonRepo, 0700, rootIDs); err != nil { return nil, err } // Create the directory where we'll store the runtime scripts (i.e. in // order to support runtimeArgs) daemonRuntimes := filepath.Join(config.Root, "runtimes") - if err := system.MkdirAll(daemonRuntimes, 0700, ""); err != nil && !os.IsExist(err) { + if err := system.MkdirAll(daemonRuntimes, 0700, ""); err != nil { return nil, err } if err := d.loadRuntimes(); err != nil { @@ -690,7 +694,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe } if runtime.GOOS == "windows" { - if err := system.MkdirAll(filepath.Join(config.Root, "credentialspecs"), 0, ""); err != nil && !os.IsExist(err) { + if err := system.MkdirAll(filepath.Join(config.Root, "credentialspecs"), 0, ""); err != nil { return nil, err } } @@ -701,11 +705,12 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe // lcow. Unix platforms however run a single graphdriver for all containers, and it can // be set through an environment variable, a daemon start parameter, or chosen through // initialization of the layerstore through driver priority order for example. - d.stores = make(map[string]daemonStore) + d.graphDrivers = make(map[string]string) + d.layerStores = make(map[string]layer.Store) if runtime.GOOS == "windows" { - d.stores["windows"] = daemonStore{graphDriver: "windowsfilter"} + d.graphDrivers[runtime.GOOS] = "windowsfilter" if system.LCOWSupported() { - d.stores["linux"] = daemonStore{graphDriver: "lcow"} + d.graphDrivers["linux"] = "lcow" } } else { driverName := os.Getenv("DOCKER_DRIVER") @@ -714,7 +719,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe } else { logrus.Infof("Setting the storage driver from the $DOCKER_DRIVER environment variable (%s)", driverName) } - d.stores[runtime.GOOS] = daemonStore{graphDriver: driverName} // May still be empty. Layerstore init determines instead. + d.graphDrivers[runtime.GOOS] = driverName // May still be empty. Layerstore init determines instead. } d.RegistryService = registryService @@ -745,12 +750,11 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe return nil, errors.Wrap(err, "couldn't create plugin manager") } - var graphDrivers []string - for operatingSystem, ds := range d.stores { - ls, err := layer.NewStoreFromOptions(layer.StoreOptions{ - StorePath: config.Root, + for operatingSystem, gd := range d.graphDrivers { + d.layerStores[operatingSystem], err = layer.NewStoreFromOptions(layer.StoreOptions{ + Root: config.Root, MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), - GraphDriver: ds.graphDriver, + GraphDriver: gd, GraphDriverOptions: config.GraphOptions, IDMappings: idMappings, PluginGetter: d.PluginStore, @@ -760,40 +764,37 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe if err != nil { return nil, err } - ds.graphDriver = ls.DriverName() // As layerstore may set the driver - ds.layerStore = ls - d.stores[operatingSystem] = ds - graphDrivers = append(graphDrivers, ls.DriverName()) } - // Configure and validate the kernels security support - if err := configureKernelSecuritySupport(config, graphDrivers); err != nil { + // As layerstore initialization may set the driver + for os := range d.graphDrivers { + d.graphDrivers[os] = d.layerStores[os].DriverName() + } + + // Configure and validate the kernels security support. Note this is a Linux/FreeBSD + // operation only, so it is safe to pass *just* the runtime OS graphdriver. + if err := configureKernelSecuritySupport(config, d.graphDrivers[runtime.GOOS]); err != nil { return nil, err } logrus.Debugf("Max Concurrent Downloads: %d", *config.MaxConcurrentDownloads) - lsMap := make(map[string]layer.Store) - for operatingSystem, ds := range d.stores { - lsMap[operatingSystem] = ds.layerStore - } - d.downloadManager = xfer.NewLayerDownloadManager(lsMap, *config.MaxConcurrentDownloads) + d.downloadManager = xfer.NewLayerDownloadManager(d.layerStores, *config.MaxConcurrentDownloads) logrus.Debugf("Max Concurrent Uploads: %d", *config.MaxConcurrentUploads) d.uploadManager = xfer.NewLayerUploadManager(*config.MaxConcurrentUploads) - for operatingSystem, ds := range d.stores { - imageRoot := filepath.Join(config.Root, "image", ds.graphDriver) - ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) - if err != nil { - return nil, err - } - var is image.Store - is, err = image.NewImageStore(ifs, operatingSystem, ds.layerStore) - if err != nil { - return nil, err - } - ds.imageRoot = imageRoot - ds.imageStore = is - d.stores[operatingSystem] = ds + d.imageRoot = filepath.Join(config.Root, "image", d.graphDrivers[runtime.GOOS]) + ifs, err := image.NewFSStoreBackend(filepath.Join(d.imageRoot, "imagedb")) + if err != nil { + return nil, err + } + + lgrMap := make(map[string]image.LayerGetReleaser) + for os, ls := range d.layerStores { + lgrMap[os] = ls + } + d.imageStore, err = image.NewImageStore(ifs, lgrMap) + if err != nil { + return nil, err } // Configure the volumes driver @@ -825,30 +826,25 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe // operating systems, the list of graphdrivers available isn't user configurable. // For backwards compatibility, we just put it under the windowsfilter // directory regardless. - refStoreLocation := filepath.Join(d.stores[runtime.GOOS].imageRoot, `repositories.json`) + refStoreLocation := filepath.Join(d.imageRoot, `repositories.json`) rs, err := refstore.NewReferenceStore(refStoreLocation) if err != nil { return nil, fmt.Errorf("Couldn't create reference store repository: %s", err) } d.referenceStore = rs - for platform, ds := range d.stores { - dms, err := dmetadata.NewFSMetadataStore(filepath.Join(ds.imageRoot, "distribution"), platform) - if err != nil { - return nil, err - } + d.distributionMetadataStore, err = dmetadata.NewFSMetadataStore(filepath.Join(d.imageRoot, "distribution")) + if err != nil { + return nil, err + } - ds.distributionMetadataStore = dms - d.stores[platform] = ds - - // No content-addressability migration on Windows as it never supported pre-CA - if runtime.GOOS != "windows" { - migrationStart := time.Now() - if err := v1.Migrate(config.Root, ds.graphDriver, ds.layerStore, ds.imageStore, rs, dms); err != nil { - logrus.Errorf("Graph migration failed: %q. Your old graph data was found to be too inconsistent for upgrading to content-addressable storage. Some of the old data was probably not upgraded. We recommend starting over with a clean storage directory if possible.", err) - } - logrus.Infof("Graph migration to content-addressability took %.2f seconds", time.Since(migrationStart).Seconds()) + // No content-addressability migration on Windows as it never supported pre-CA + if runtime.GOOS != "windows" { + migrationStart := time.Now() + if err := v1.Migrate(config.Root, d.graphDrivers[runtime.GOOS], d.layerStores[runtime.GOOS], d.imageStore, rs, d.distributionMetadataStore); err != nil { + logrus.Errorf("Graph migration failed: %q. Your old graph data was found to be too inconsistent for upgrading to content-addressable storage. Some of the old data was probably not upgraded. We recommend starting over with a clean storage directory if possible.", err) } + logrus.Infof("Graph migration to content-addressability took %.2f seconds", time.Since(migrationStart).Seconds()) } // Discovery is only enabled when the daemon is launched with an address to advertise. When @@ -890,7 +886,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe go d.execCommandGC() - d.containerd, err = containerdRemote.NewClient(MainNamespace, d) + d.containerd, err = containerdRemote.NewClient(ContainersNamespace, d) if err != nil { return nil, err } @@ -917,13 +913,13 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe engineMemory.Set(float64(info.MemTotal)) gd := "" - for platform, ds := range d.stores { + for os, driver := range d.graphDrivers { if len(gd) > 0 { gd += ", " } - gd += ds.graphDriver - if len(d.stores) > 1 { - gd = fmt.Sprintf("%s (%s)", gd, platform) + gd += driver + if len(d.graphDrivers) > 1 { + gd = fmt.Sprintf("%s (%s)", gd, os) } } logrus.WithFields(logrus.Fields{ @@ -1004,7 +1000,7 @@ func (daemon *Daemon) Shutdown() error { logrus.Errorf("Stop container error: %v", err) return } - if mountid, err := daemon.stores[c.OS].layerStore.GetMountID(c.ID); err == nil { + if mountid, err := daemon.layerStores[c.OS].GetMountID(c.ID); err == nil { daemon.cleanupMountsByID(mountid) } logrus.Debugf("container stopped %s", c.ID) @@ -1017,10 +1013,10 @@ func (daemon *Daemon) Shutdown() error { } } - for platform, ds := range daemon.stores { - if ds.layerStore != nil { - if err := ds.layerStore.Cleanup(); err != nil { - logrus.Errorf("Error during layer Store.Cleanup(): %v %s", err, platform) + for os, ls := range daemon.layerStores { + if ls != nil { + if err := ls.Cleanup(); err != nil { + logrus.Errorf("Error during layer Store.Cleanup(): %v %s", err, os) } } } @@ -1041,11 +1037,7 @@ func (daemon *Daemon) Shutdown() error { daemon.netController.Stop() } - if err := daemon.cleanupMounts(); err != nil { - return err - } - - return nil + return daemon.cleanupMounts() } // Mount sets container.BaseFS @@ -1106,8 +1098,8 @@ func (daemon *Daemon) Subnets() ([]net.IPNet, []net.IPNet) { } // GraphDriverName returns the name of the graph driver used by the layer.Store -func (daemon *Daemon) GraphDriverName(platform string) string { - return daemon.stores[platform].layerStore.DriverName() +func (daemon *Daemon) GraphDriverName(os string) string { + return daemon.layerStores[os].DriverName() } // prepareTempDir prepares and returns the default directory to use diff --git a/vendor/github.com/docker/docker/daemon/daemon_experimental.go b/vendor/github.com/docker/docker/daemon/daemon_experimental.go deleted file mode 100644 index fb0251d4a..000000000 --- a/vendor/github.com/docker/docker/daemon/daemon_experimental.go +++ /dev/null @@ -1,7 +0,0 @@ -package daemon - -import "github.com/docker/docker/api/types/container" - -func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) { - return nil, nil -} diff --git a/vendor/github.com/docker/docker/daemon/daemon_test.go b/vendor/github.com/docker/docker/daemon/daemon_test.go index 422be1fd7..0f6bed1c4 100644 --- a/vendor/github.com/docker/docker/daemon/daemon_test.go +++ b/vendor/github.com/docker/docker/daemon/daemon_test.go @@ -9,6 +9,7 @@ import ( containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" _ "github.com/docker/docker/pkg/discovery/memory" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/truncindex" @@ -17,6 +18,8 @@ import ( "github.com/docker/docker/volume/local" "github.com/docker/docker/volume/store" "github.com/docker/go-connections/nat" + "github.com/docker/libnetwork" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) @@ -311,3 +314,12 @@ func TestValidateContainerIsolation(t *testing.T) { _, err := d.verifyContainerSettings(runtime.GOOS, &containertypes.HostConfig{Isolation: containertypes.Isolation("invalid")}, nil, false) assert.EqualError(t, err, "invalid isolation 'invalid' on "+runtime.GOOS) } + +func TestFindNetworkErrorType(t *testing.T) { + d := Daemon{} + _, err := d.FindNetwork("fakeNet") + _, ok := errors.Cause(err).(libnetwork.ErrNoSuchNetwork) + if !errdefs.IsNotFound(err) || !ok { + assert.Fail(t, "The FindNetwork method MUST always return an error that implements the NotFound interface and is ErrNoSuchNetwork") + } +} diff --git a/vendor/github.com/docker/docker/daemon/daemon_unix.go b/vendor/github.com/docker/docker/daemon/daemon_unix.go index b0b624772..74046147a 100644 --- a/vendor/github.com/docker/docker/daemon/daemon_unix.go +++ b/vendor/github.com/docker/docker/daemon/daemon_unix.go @@ -4,7 +4,6 @@ package daemon import ( "bufio" - "bytes" "context" "fmt" "io/ioutil" @@ -574,11 +573,6 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. var warnings []string sysInfo := sysinfo.New(true) - warnings, err := daemon.verifyExperimentalContainerSettings(hostConfig, config) - if err != nil { - return warnings, err - } - w, err := verifyContainerResources(&hostConfig.Resources, sysInfo, update) // no matter err is nil or not, w could have data in itself. @@ -685,51 +679,6 @@ func (daemon *Daemon) initRuntimes(runtimes map[string]types.Runtime) (err error return nil } -// reloadPlatform updates configuration with platform specific options -// and updates the passed attributes -func (daemon *Daemon) reloadPlatform(conf *config.Config, attributes map[string]string) error { - if err := conf.ValidatePlatformConfig(); err != nil { - return err - } - - if conf.IsValueSet("runtimes") { - // Always set the default one - conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary} - if err := daemon.initRuntimes(conf.Runtimes); err != nil { - return err - } - daemon.configStore.Runtimes = conf.Runtimes - } - - if conf.DefaultRuntime != "" { - daemon.configStore.DefaultRuntime = conf.DefaultRuntime - } - - if conf.IsValueSet("default-shm-size") { - daemon.configStore.ShmSize = conf.ShmSize - } - - if conf.IpcMode != "" { - daemon.configStore.IpcMode = conf.IpcMode - } - - // Update attributes - var runtimeList bytes.Buffer - for name, rt := range daemon.configStore.Runtimes { - if runtimeList.Len() > 0 { - runtimeList.WriteRune(' ') - } - runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt)) - } - - attributes["runtimes"] = runtimeList.String() - attributes["default-runtime"] = daemon.configStore.DefaultRuntime - attributes["default-shm-size"] = fmt.Sprintf("%d", daemon.configStore.ShmSize) - attributes["default-ipc-mode"] = daemon.configStore.IpcMode - - return nil -} - // verifyDaemonSettings performs validation of daemon config struct func verifyDaemonSettings(conf *config.Config) error { // Check for mutually incompatible config options @@ -819,22 +768,14 @@ func overlaySupportsSelinux() (bool, error) { } // configureKernelSecuritySupport configures and validates security support for the kernel -func configureKernelSecuritySupport(config *config.Config, driverNames []string) error { +func configureKernelSecuritySupport(config *config.Config, driverName string) error { if config.EnableSelinuxSupport { if !selinuxEnabled() { logrus.Warn("Docker could not enable SELinux on the host system") return nil } - overlayFound := false - for _, d := range driverNames { - if d == "overlay" || d == "overlay2" { - overlayFound = true - break - } - } - - if overlayFound { + if driverName == "overlay" || driverName == "overlay2" { // If driver is overlay or overlay2, make sure kernel // supports selinux with overlay. supported, err := overlaySupportsSelinux() @@ -843,7 +784,7 @@ func configureKernelSecuritySupport(config *config.Config, driverNames []string) } if !supported { - logrus.Warnf("SELinux is not supported with the %v graph driver on this kernel", driverNames) + logrus.Warnf("SELinux is not supported with the %v graph driver on this kernel", driverName) } } } else { @@ -1506,15 +1447,12 @@ func (daemon *Daemon) initCgroupsPath(path string) error { if err := maybeCreateCPURealTimeFile(sysinfo.CPURealtimePeriod, daemon.configStore.CPURealtimePeriod, "cpu.rt_period_us", path); err != nil { return err } - if err := maybeCreateCPURealTimeFile(sysinfo.CPURealtimeRuntime, daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path); err != nil { - return err - } - return nil + return maybeCreateCPURealTimeFile(sysinfo.CPURealtimeRuntime, daemon.configStore.CPURealtimeRuntime, "cpu.rt_runtime_us", path) } func maybeCreateCPURealTimeFile(sysinfoPresent bool, configValue int64, file string, path string) error { if sysinfoPresent && configValue != 0 { - if err := os.MkdirAll(path, 0755); err != nil && !os.IsExist(err) { + if err := os.MkdirAll(path, 0755); err != nil { return err } if err := ioutil.WriteFile(filepath.Join(path, file), []byte(strconv.FormatInt(configValue, 10)), 0700); err != nil { diff --git a/vendor/github.com/docker/docker/daemon/daemon_windows.go b/vendor/github.com/docker/docker/daemon/daemon_windows.go index a79ed4f07..e3b207247 100644 --- a/vendor/github.com/docker/docker/daemon/daemon_windows.go +++ b/vendor/github.com/docker/docker/daemon/daemon_windows.go @@ -3,7 +3,6 @@ package daemon import ( "context" "fmt" - "os" "path/filepath" "strings" @@ -27,7 +26,6 @@ import ( winlibnetwork "github.com/docker/libnetwork/drivers/windows" "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/options" - blkiodev "github.com/opencontainers/runc/libcontainer/configs" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/sys/windows" @@ -48,10 +46,6 @@ func getPluginExecRoot(root string) string { return filepath.Join(root, "plugins") } -func getBlkioWeightDevices(config *containertypes.HostConfig) ([]blkiodev.WeightDevice, error) { - return nil, nil -} - func (daemon *Daemon) parseSecurityOpt(container *container.Container, hostConfig *containertypes.HostConfig) error { return parseSecurityOpt(container, hostConfig) } @@ -213,12 +207,6 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes. return warnings, err } -// reloadPlatform updates configuration with platform specific options -// and updates the passed attributes -func (daemon *Daemon) reloadPlatform(config *config.Config, attributes map[string]string) error { - return nil -} - // verifyDaemonSettings performs validation of daemon config struct func verifyDaemonSettings(config *config.Config) error { return nil @@ -268,7 +256,7 @@ func ensureServicesInstalled(services []string) error { } // configureKernelSecuritySupport configures and validate security support for the kernel -func configureKernelSecuritySupport(config *config.Config, driverNames []string) error { +func configureKernelSecuritySupport(config *config.Config, driverName string) error { return nil } @@ -350,6 +338,9 @@ func (daemon *Daemon) initNetworkController(config *config.Config, activeSandbox } controller.WalkNetworks(s) + + drvOptions := make(map[string]string) + if n != nil { // global networks should not be deleted by local HNS if n.Info().Scope() == datastore.GlobalScope { @@ -358,14 +349,23 @@ func (daemon *Daemon) initNetworkController(config *config.Config, activeSandbox v.Name = n.Name() // This will not cause network delete from HNS as the network // is not yet populated in the libnetwork windows driver + + // restore option if it existed before + drvOptions = n.Info().DriverOptions() n.Delete() } - netOption := map[string]string{ winlibnetwork.NetworkName: v.Name, winlibnetwork.HNSID: v.Id, } + // add persisted driver options + for k, v := range drvOptions { + if k != winlibnetwork.NetworkName && k != winlibnetwork.HNSID { + netOption[k] = v + } + } + v4Conf := []*libnetwork.IpamConf{} for _, subnet := range v.Subnets { ipamV4Conf := libnetwork.IpamConf{} @@ -473,7 +473,7 @@ func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) { func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPair) error { config.Root = rootDir // Create the root directory if it doesn't exists - if err := system.MkdirAllWithACL(config.Root, 0, system.SddlAdministratorsLocalSystem); err != nil && !os.IsExist(err) { + if err := system.MkdirAllWithACL(config.Root, 0, system.SddlAdministratorsLocalSystem); err != nil { return err } return nil diff --git a/vendor/github.com/docker/docker/daemon/delete.go b/vendor/github.com/docker/docker/daemon/delete.go index 4d56d1452..f16d38beb 100644 --- a/vendor/github.com/docker/docker/daemon/delete.go +++ b/vendor/github.com/docker/docker/daemon/delete.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/system" "github.com/docker/docker/volume" @@ -31,7 +32,7 @@ func (daemon *Daemon) ContainerRm(name string, config *types.ContainerRmConfig) // Container state RemovalInProgress should be used to avoid races. if inProgress := container.SetRemovalInProgress(); inProgress { err := fmt.Errorf("removal of container %s is already in progress", name) - return stateConflictError{err} + return errdefs.Conflict(err) } defer container.ResetRemovalInProgress() @@ -87,12 +88,15 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo procedure = "Unpause and then " + strings.ToLower(procedure) } err := fmt.Errorf("You cannot remove a %s container %s. %s", state, container.ID, procedure) - return stateConflictError{err} + return errdefs.Conflict(err) } if err := daemon.Kill(container); err != nil { return fmt.Errorf("Could not kill running container %s, cannot remove - %v", container.ID, err) } } + if !system.IsOSSupported(container.OS) { + return fmt.Errorf("cannot remove %s: %s ", container.ID, system.ErrNotSupportedOperatingSystem) + } // stop collection of stats for the container regardless // if stats are currently getting collected. @@ -117,7 +121,7 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo // When container creation fails and `RWLayer` has not been created yet, we // do not call `ReleaseRWLayer` if container.RWLayer != nil { - metadata, err := daemon.stores[container.OS].layerStore.ReleaseRWLayer(container.RWLayer) + metadata, err := daemon.layerStores[container.OS].ReleaseRWLayer(container.RWLayer) layer.LogReleaseMetadata(metadata) if err != nil && err != layer.ErrMountDoesNotExist && !os.IsNotExist(errors.Cause(err)) { e := errors.Wrapf(err, "driver %q failed to remove root filesystem for %s", daemon.GraphDriverName(container.OS), container.ID) @@ -164,7 +168,7 @@ func (daemon *Daemon) VolumeRm(name string, force bool) error { err = daemon.volumeRm(v) if err != nil && volumestore.IsInUse(err) { - return stateConflictError{err} + return errdefs.Conflict(err) } if err == nil || force { diff --git a/vendor/github.com/docker/docker/daemon/disk_usage.go b/vendor/github.com/docker/docker/daemon/disk_usage.go index 7142ef078..c9b86604b 100644 --- a/vendor/github.com/docker/docker/daemon/disk_usage.go +++ b/vendor/github.com/docker/docker/daemon/disk_usage.go @@ -15,12 +15,12 @@ import ( "github.com/sirupsen/logrus" ) -func (daemon *Daemon) getLayerRefs(platform string) map[layer.ChainID]int { - tmpImages := daemon.stores[platform].imageStore.Map() +func (daemon *Daemon) getLayerRefs() map[layer.ChainID]int { + tmpImages := daemon.imageStore.Map() layerRefs := map[layer.ChainID]int{} for id, img := range tmpImages { dgst := digest.Digest(id) - if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.stores[platform].imageStore.Children(id)) != 0 { + if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.imageStore.Children(id)) != 0 { continue } @@ -53,7 +53,6 @@ func (daemon *Daemon) SystemDiskUsage(ctx context.Context) (*types.DiskUsage, er } // Get all top images with extra attributes - // TODO @jhowardmsft LCOW. This may need revisiting allImages, err := daemon.Images(filters.NewArgs(), false, true) if err != nil { return nil, fmt.Errorf("failed to retrieve image list: %v", err) @@ -96,9 +95,9 @@ func (daemon *Daemon) SystemDiskUsage(ctx context.Context) (*types.DiskUsage, er // Get total layers size on disk var allLayersSize int64 - for platform := range daemon.stores { - layerRefs := daemon.getLayerRefs(platform) - allLayers := daemon.stores[platform].layerStore.Map() + layerRefs := daemon.getLayerRefs() + for _, ls := range daemon.layerStores { + allLayers := ls.Map() for _, l := range allLayers { select { case <-ctx.Done(): @@ -109,10 +108,10 @@ func (daemon *Daemon) SystemDiskUsage(ctx context.Context) (*types.DiskUsage, er if _, ok := layerRefs[l.ChainID()]; ok { allLayersSize += size } else { - logrus.Warnf("found leaked image layer %v platform %s", l.ChainID(), platform) + logrus.Warnf("found leaked image layer %v", l.ChainID()) } } else { - logrus.Warnf("failed to get diff size for layer %v %s", l.ChainID(), platform) + logrus.Warnf("failed to get diff size for layer %v", l.ChainID()) } } } diff --git a/vendor/github.com/docker/docker/daemon/errors.go b/vendor/github.com/docker/docker/daemon/errors.go index 889261fa3..e3a16b058 100644 --- a/vendor/github.com/docker/docker/daemon/errors.go +++ b/vendor/github.com/docker/docker/daemon/errors.go @@ -5,12 +5,13 @@ import ( "strings" "syscall" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" "google.golang.org/grpc" ) func errNotRunning(id string) error { - return stateConflictError{errors.Errorf("Container %s is not running", id)} + return errdefs.Conflict(errors.Errorf("Container %s is not running", id)) } func containerNotFound(id string) error { @@ -21,10 +22,6 @@ func volumeNotFound(id string) error { return objNotFoundError{"volume", id} } -func networkNotFound(id string) error { - return objNotFoundError{"network", id} -} - type objNotFoundError struct { object string id string @@ -36,23 +33,9 @@ func (e objNotFoundError) Error() string { func (e objNotFoundError) NotFound() {} -type stateConflictError struct { - cause error -} - -func (e stateConflictError) Error() string { - return e.cause.Error() -} - -func (e stateConflictError) Cause() error { - return e.cause -} - -func (e stateConflictError) Conflict() {} - func errContainerIsRestarting(containerID string) error { cause := errors.Errorf("Container %s is restarting, wait until the container is running", containerID) - return stateConflictError{cause} + return errdefs.Conflict(cause) } func errExecNotFound(id string) error { @@ -61,12 +44,12 @@ func errExecNotFound(id string) error { func errExecPaused(id string) error { cause := errors.Errorf("Container %s is paused, unpause the container before exec", id) - return stateConflictError{cause} + return errdefs.Conflict(cause) } func errNotPaused(id string) error { cause := errors.Errorf("Container %s is already paused", id) - return stateConflictError{cause} + return errdefs.Conflict(cause) } type nameConflictError struct { @@ -80,34 +63,6 @@ func (e nameConflictError) Error() string { func (nameConflictError) Conflict() {} -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (e validationError) InvalidParameter() {} - -func (e validationError) Cause() error { - return e.cause -} - -type notAllowedError struct { - cause error -} - -func (e notAllowedError) Error() string { - return e.cause.Error() -} - -func (e notAllowedError) Forbidden() {} - -func (e notAllowedError) Cause() error { - return e.cause -} - type containerNotModifiedError struct { running bool } @@ -121,20 +76,6 @@ func (e containerNotModifiedError) Error() string { func (e containerNotModifiedError) NotModified() {} -type systemError struct { - cause error -} - -func (e systemError) Error() string { - return e.cause.Error() -} - -func (e systemError) SystemError() {} - -func (e systemError) Cause() error { - return e.cause -} - type invalidIdentifier string func (e invalidIdentifier) Error() string { @@ -176,20 +117,6 @@ func (e invalidFilter) Error() string { func (e invalidFilter) InvalidParameter() {} -type unknownError struct { - cause error -} - -func (e unknownError) Error() string { - return e.cause.Error() -} - -func (unknownError) Unknown() {} - -func (e unknownError) Cause() error { - return e.cause -} - type startInvalidConfigError string func (e startInvalidConfigError) Error() string { @@ -203,7 +130,7 @@ func translateContainerdStartErr(cmd string, setExitCode func(int), err error) e contains := func(s1, s2 string) bool { return strings.Contains(strings.ToLower(s1), s2) } - var retErr error = unknownError{errors.New(errDesc)} + var retErr = errdefs.Unknown(errors.New(errDesc)) // if we receive an internal error from the initial start of a container then lets // return it instead of entering the restart loop // set to 127 for container cmd not found/does not exist) diff --git a/vendor/github.com/docker/docker/daemon/events/events.go b/vendor/github.com/docker/docker/daemon/events/events.go index d1529e1ce..6a4990fec 100644 --- a/vendor/github.com/docker/docker/daemon/events/events.go +++ b/vendor/github.com/docker/docker/daemon/events/events.go @@ -28,7 +28,7 @@ func New() *Events { } } -// Subscribe adds new listener to events, returns slice of 64 stored +// Subscribe adds new listener to events, returns slice of 256 stored // last events, a channel in which you can expect new events (in form // of interface{}, so you need type assertion), and a function to call // to stop the stream of events. @@ -46,7 +46,7 @@ func (e *Events) Subscribe() ([]eventtypes.Message, chan interface{}, func()) { return current, l, cancel } -// SubscribeTopic adds new listener to events, returns slice of 64 stored +// SubscribeTopic adds new listener to events, returns slice of 256 stored // last events, a channel in which you can expect new events (in form // of interface{}, so you need type assertion). func (e *Events) SubscribeTopic(since, until time.Time, ef *Filter) ([]eventtypes.Message, chan interface{}) { diff --git a/vendor/github.com/docker/docker/daemon/events/events_test.go b/vendor/github.com/docker/docker/daemon/events/events_test.go index ebb222cfb..d74f2580b 100644 --- a/vendor/github.com/docker/docker/daemon/events/events_test.go +++ b/vendor/github.com/docker/docker/daemon/events/events_test.go @@ -135,21 +135,28 @@ func TestLogEvents(t *testing.T) { t.Fatalf("Must be %d events, got %d", eventsLimit, len(current)) } first := current[0] - if first.Status != "action_16" { - t.Fatalf("First action is %s, must be action_16", first.Status) + + // TODO remove this once we removed the deprecated `ID`, `Status`, and `From` fields + if first.Action != first.Status { + // Verify that the (deprecated) Status is set to the expected value + t.Fatalf("Action (%s) does not match Status (%s)", first.Action, first.Status) + } + + if first.Action != "action_16" { + t.Fatalf("First action is %s, must be action_16", first.Action) } last := current[len(current)-1] - if last.Status != "action_271" { - t.Fatalf("Last action is %s, must be action_271", last.Status) + if last.Action != "action_271" { + t.Fatalf("Last action is %s, must be action_271", last.Action) } firstC := msgs[0] - if firstC.Status != "action_272" { - t.Fatalf("First action is %s, must be action_272", firstC.Status) + if firstC.Action != "action_272" { + t.Fatalf("First action is %s, must be action_272", firstC.Action) } lastC := msgs[len(msgs)-1] - if lastC.Status != "action_281" { - t.Fatalf("Last action is %s, must be action_281", lastC.Status) + if lastC.Action != "action_281" { + t.Fatalf("Last action is %s, must be action_281", lastC.Action) } } diff --git a/vendor/github.com/docker/docker/daemon/exec.go b/vendor/github.com/docker/docker/daemon/exec.go index afdfc9c2b..35c583106 100644 --- a/vendor/github.com/docker/docker/daemon/exec.go +++ b/vendor/github.com/docker/docker/daemon/exec.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/container/stream" "github.com/docker/docker/daemon/exec" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/pools" "github.com/docker/docker/pkg/signal" "github.com/docker/docker/pkg/term" @@ -31,14 +32,6 @@ func (d *Daemon) registerExecCommand(container *container.Container, config *exe d.execCommands.Add(config.ID, config) } -func (d *Daemon) registerExecPidUnlocked(container *container.Container, config *exec.Config) { - logrus.Debugf("registering pid %v for exec %v", config.Pid, config.ID) - // Storing execs in container in order to kill them gracefully whenever the container is stopped or removed. - container.ExecCommands.SetPidUnlocked(config.ID, config.Pid) - // Storing execs in daemon for easy access via Engine API. - d.execCommands.SetPidUnlocked(config.ID, config.Pid) -} - // ExecExists looks up the exec instance and returns a bool if it exists or not. // It will also return the error produced by `getConfig` func (d *Daemon) ExecExists(name string) (bool, error) { @@ -130,6 +123,7 @@ func (d *Daemon) ContainerExecCreate(name string, config *types.ExecConfig) (str execConfig.Tty = config.Tty execConfig.Privileged = config.Privileged execConfig.User = config.User + execConfig.WorkingDir = config.WorkingDir linkedEnv, err := d.setupLinkedContainers(cntr) if err != nil { @@ -139,10 +133,16 @@ func (d *Daemon) ContainerExecCreate(name string, config *types.ExecConfig) (str if len(execConfig.User) == 0 { execConfig.User = cntr.Config.User } + if len(execConfig.WorkingDir) == 0 { + execConfig.WorkingDir = cntr.Config.WorkingDir + } d.registerExecCommand(cntr, execConfig) - d.LogContainerEvent(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " ")) + attributes := map[string]string{ + "execID": execConfig.ID, + } + d.LogContainerEventWithAttributes(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "), attributes) return execConfig.ID, nil } @@ -165,19 +165,22 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R if ec.ExitCode != nil { ec.Unlock() err := fmt.Errorf("Error: Exec command %s has already run", ec.ID) - return stateConflictError{err} + return errdefs.Conflict(err) } if ec.Running { ec.Unlock() - return stateConflictError{fmt.Errorf("Error: Exec command %s is already running", ec.ID)} + return errdefs.Conflict(fmt.Errorf("Error: Exec command %s is already running", ec.ID)) } ec.Running = true ec.Unlock() c := d.containers.Get(ec.ContainerID) logrus.Debugf("starting exec command %s in container %s", ec.ID, c.ID) - d.LogContainerEvent(c, "exec_start: "+ec.Entrypoint+" "+strings.Join(ec.Args, " ")) + attributes := map[string]string{ + "execID": ec.ID, + } + d.LogContainerEventWithAttributes(c, "exec_start: "+ec.Entrypoint+" "+strings.Join(ec.Args, " "), attributes) defer func() { if err != nil { @@ -219,7 +222,7 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R Args: append([]string{ec.Entrypoint}, ec.Args...), Env: ec.Env, Terminal: ec.Tty, - Cwd: c.Config.WorkingDir, + Cwd: ec.WorkingDir, } if p.Cwd == "" { p.Cwd = "/" @@ -253,7 +256,6 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R return translateContainerdStartErr(ec.Entrypoint, ec.SetExitCode, err) } ec.Pid = systemPid - d.registerExecPidUnlocked(c, ec) c.ExecCommands.Unlock() ec.Unlock() @@ -272,9 +274,12 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R case err := <-attachErr: if err != nil { if _, ok := err.(term.EscapeError); !ok { - return errors.Wrap(systemError{err}, "exec attach failed") + return errdefs.System(errors.Wrap(err, "exec attach failed")) } - d.LogContainerEvent(c, "exec_detach") + attributes := map[string]string{ + "execID": ec.ID, + } + d.LogContainerEventWithAttributes(c, "exec_detach", attributes) } } return nil diff --git a/vendor/github.com/docker/docker/daemon/exec/exec.go b/vendor/github.com/docker/docker/daemon/exec/exec.go index 7aa2383e3..08ec67dc3 100644 --- a/vendor/github.com/docker/docker/daemon/exec/exec.go +++ b/vendor/github.com/docker/docker/daemon/exec/exec.go @@ -4,9 +4,8 @@ import ( "runtime" "sync" - "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" "github.com/docker/docker/container/stream" - "github.com/docker/docker/libcontainerd" "github.com/docker/docker/pkg/stringid" "github.com/sirupsen/logrus" ) @@ -31,6 +30,7 @@ type Config struct { Tty bool Privileged bool User string + WorkingDir string Env []string Pid int } @@ -43,26 +43,26 @@ func NewConfig() *Config { } } -type cio struct { - containerd.IO +type rio struct { + cio.IO sc *stream.Config } -func (i *cio) Close() error { +func (i *rio) Close() error { i.IO.Close() return i.sc.CloseStreams() } -func (i *cio) Wait() { +func (i *rio) Wait() { i.sc.Wait() i.IO.Wait() } // InitializeStdio is called by libcontainerd to connect the stdio. -func (c *Config) InitializeStdio(iop *libcontainerd.IOPipe) (containerd.IO, error) { +func (c *Config) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) { c.StreamConfig.CopyToPipe(iop) if c.StreamConfig.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" { @@ -73,7 +73,7 @@ func (c *Config) InitializeStdio(iop *libcontainerd.IOPipe) (containerd.IO, erro } } - return &cio{IO: iop, sc: c.StreamConfig}, nil + return &rio{IO: iop, sc: c.StreamConfig}, nil } // CloseStreams closes the stdio streams for the exec @@ -88,16 +88,14 @@ func (c *Config) SetExitCode(code int) { // Store keeps track of the exec configurations. type Store struct { - byID map[string]*Config - byPid map[int]*Config + byID map[string]*Config sync.RWMutex } // NewStore initializes a new exec store. func NewStore() *Store { return &Store{ - byID: make(map[string]*Config), - byPid: make(map[int]*Config), + byID: make(map[string]*Config), } } @@ -119,14 +117,6 @@ func (e *Store) Add(id string, Config *Config) { e.Unlock() } -// SetPidUnlocked adds an association between a Pid and a config, it does not -// synchronized with other operations. -func (e *Store) SetPidUnlocked(id string, pid int) { - if config, ok := e.byID[id]; ok { - e.byPid[pid] = config - } -} - // Get returns an exec configuration by its id. func (e *Store) Get(id string) *Config { e.RLock() @@ -135,18 +125,9 @@ func (e *Store) Get(id string) *Config { return res } -// ByPid returns an exec configuration by its pid. -func (e *Store) ByPid(pid int) *Config { - e.RLock() - res := e.byPid[pid] - e.RUnlock() - return res -} - // Delete removes an exec configuration from the store. func (e *Store) Delete(id string, pid int) { e.Lock() - delete(e.byPid, pid) delete(e.byID, id) e.Unlock() } diff --git a/vendor/github.com/docker/docker/daemon/exec_solaris.go b/vendor/github.com/docker/docker/daemon/exec_solaris.go deleted file mode 100644 index 7c1fc20a0..000000000 --- a/vendor/github.com/docker/docker/daemon/exec_solaris.go +++ /dev/null @@ -1,11 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/container" - "github.com/docker/docker/daemon/exec" - specs "github.com/opencontainers/runtime-spec/specs-go" -) - -func (daemon *Daemon) execSetPlatformOpt(_ *container.Container, _ *exec.Config, _ *specs.Process) error { - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/export.go b/vendor/github.com/docker/docker/daemon/export.go index c0e6affbe..3a5af632d 100644 --- a/vendor/github.com/docker/docker/daemon/export.go +++ b/vendor/github.com/docker/docker/daemon/export.go @@ -6,8 +6,10 @@ import ( "runtime" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/ioutils" + "github.com/docker/docker/pkg/system" ) // ContainerExport writes the contents of the container to the given @@ -24,12 +26,12 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error { if container.IsDead() { err := fmt.Errorf("You cannot export container %s which is Dead", container.ID) - return stateConflictError{err} + return errdefs.Conflict(err) } if container.IsRemovalInProgress() { err := fmt.Errorf("You cannot export container %s which is being removed", container.ID) - return stateConflictError{err} + return errdefs.Conflict(err) } data, err := daemon.containerExport(container) @@ -46,13 +48,16 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error { } func (daemon *Daemon) containerExport(container *container.Container) (arch io.ReadCloser, err error) { - rwlayer, err := daemon.stores[container.OS].layerStore.GetRWLayer(container.ID) + if !system.IsOSSupported(container.OS) { + return nil, fmt.Errorf("cannot export %s: %s ", container.ID, system.ErrNotSupportedOperatingSystem) + } + rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID) if err != nil { return nil, err } defer func() { if err != nil { - daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer) + daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer) } }() @@ -73,7 +78,7 @@ func (daemon *Daemon) containerExport(container *container.Container) (arch io.R arch = ioutils.NewReadCloserWrapper(archive, func() error { err := archive.Close() rwlayer.Unmount() - daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer) + daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer) return err }) daemon.LogContainerEvent(container, "export") diff --git a/vendor/github.com/docker/docker/daemon/getsize_unix.go b/vendor/github.com/docker/docker/daemon/getsize_unix.go index fff90f275..deefcd9f9 100644 --- a/vendor/github.com/docker/docker/daemon/getsize_unix.go +++ b/vendor/github.com/docker/docker/daemon/getsize_unix.go @@ -15,12 +15,14 @@ func (daemon *Daemon) getSize(containerID string) (int64, int64) { err error ) - rwlayer, err := daemon.stores[runtime.GOOS].layerStore.GetRWLayer(containerID) + // Safe to index by runtime.GOOS as Unix hosts don't support multiple + // container operating systems. + rwlayer, err := daemon.layerStores[runtime.GOOS].GetRWLayer(containerID) if err != nil { logrus.Errorf("Failed to compute size of container rootfs %v: %v", containerID, err) return sizeRw, sizeRootfs } - defer daemon.stores[runtime.GOOS].layerStore.ReleaseRWLayer(rwlayer) + defer daemon.layerStores[runtime.GOOS].ReleaseRWLayer(rwlayer) sizeRw, err = rwlayer.Size() if err != nil { diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/aufs/aufs.go b/vendor/github.com/docker/docker/daemon/graphdriver/aufs/aufs.go index 5a1f3d1fd..f019e9555 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/aufs/aufs.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/aufs/aufs.go @@ -89,7 +89,16 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, graphdriver.ErrNotSupported } - fsMagic, err := graphdriver.GetFSMagic(root) + // Perform feature detection on /var/lib/docker/aufs if it's an existing directory. + // This covers situations where /var/lib/docker/aufs is a mount, and on a different + // filesystem than /var/lib/docker. + // If the path does not exist, fall back to using /var/lib/docker for feature detection. + testdir := root + if _, err := os.Stat(testdir); os.IsNotExist(err) { + testdir = filepath.Dir(testdir) + } + + fsMagic, err := graphdriver.GetFSMagic(testdir) if err != nil { return nil, err } @@ -122,13 +131,8 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap if err != nil { return nil, err } - // Create the root aufs driver dir and return - // if it already exists - // If not populate the dir structure + // Create the root aufs driver dir if err := idtools.MkdirAllAndChown(root, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil { - if os.IsExist(err) { - return a, nil - } return nil, err } @@ -575,10 +579,7 @@ func (a *Driver) unmount(mountPath string) error { if mounted, err := a.mounted(mountPath); err != nil || !mounted { return err } - if err := Unmount(mountPath); err != nil { - return err - } - return nil + return Unmount(mountPath) } func (a *Driver) mounted(mountpoint string) (bool, error) { diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/aufs/mount.go b/vendor/github.com/docker/docker/daemon/graphdriver/aufs/mount.go index 100e7537a..8198f95a8 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/aufs/mount.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/aufs/mount.go @@ -14,8 +14,5 @@ func Unmount(target string) error { if err := exec.Command("auplink", target, "flush").Run(); err != nil { logrus.Warnf("Couldn't run auplink before unmount %s: %s", target, err) } - if err := unix.Unmount(target, 0); err != nil { - return err - } - return nil + return unix.Unmount(target, 0) } diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/btrfs/btrfs.go b/vendor/github.com/docker/docker/daemon/graphdriver/btrfs/btrfs.go index 0dabf711d..d4b9b8912 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/btrfs/btrfs.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/btrfs/btrfs.go @@ -51,7 +51,16 @@ type btrfsOptions struct { // An error is returned if BTRFS is not supported. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { - fsMagic, err := graphdriver.GetFSMagic(home) + // Perform feature detection on /var/lib/docker/btrfs if it's an existing directory. + // This covers situations where /var/lib/docker/btrfs is a mount, and on a different + // filesystem than /var/lib/docker. + // If the path does not exist, fall back to using /var/lib/docker for feature detection. + testdir := home + if _, err := os.Stat(testdir); os.IsNotExist(err) { + testdir = filepath.Dir(testdir) + } + + fsMagic, err := graphdriver.GetFSMagic(testdir) if err != nil { return nil, err } @@ -589,16 +598,10 @@ func (d *Driver) setStorageSize(dir string, driver *Driver) error { if d.options.minSpace > 0 && driver.options.size < d.options.minSpace { return fmt.Errorf("btrfs: storage size cannot be less than %s", units.HumanSize(float64(d.options.minSpace))) } - if err := d.subvolEnableQuota(); err != nil { return err } - - if err := subvolLimitQgroup(dir, driver.options.size); err != nil { - return err - } - - return nil + return subvolLimitQgroup(dir, driver.options.size) } // Remove the filesystem with given id. @@ -625,10 +628,7 @@ func (d *Driver) Remove(id string) error { if err := system.EnsureRemoveAll(dir); err != nil { return err } - if err := d.subvolRescanQuota(); err != nil { - return err - } - return nil + return d.subvolRescanQuota() } // Get the requested filesystem id. diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy.go b/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy.go index 8ec458d6a..78518e816 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy.go @@ -11,6 +11,7 @@ package copy */ import "C" import ( + "container/list" "fmt" "io" "os" @@ -65,7 +66,7 @@ func copyRegular(srcPath, dstPath string, fileinfo os.FileInfo, copyWithFileRang // as the ioctl may not have been available (therefore EINVAL) if err == unix.EXDEV || err == unix.ENOSYS { *copyWithFileRange = false - } else if err != nil { + } else { return err } } @@ -106,11 +107,28 @@ func copyXattr(srcPath, dstPath, attr string) error { return nil } +type fileID struct { + dev uint64 + ino uint64 +} + +type dirMtimeInfo struct { + dstPath *string + stat *syscall.Stat_t +} + // DirCopy copies or hardlinks the contents of one directory to another, // properly handling xattrs, and soft links -func DirCopy(srcDir, dstDir string, copyMode Mode) error { +// +// Copying xattrs can be opted out of by passing false for copyXattrs. +func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error { copyWithFileRange := true copyWithFileClone := true + + // This is a map of source file inodes to dst file paths + copiedFiles := make(map[fileID]string) + + dirsToSetMtimes := list.New() err := filepath.Walk(srcDir, func(srcPath string, f os.FileInfo, err error) error { if err != nil { return err @@ -136,15 +154,21 @@ func DirCopy(srcDir, dstDir string, copyMode Mode) error { switch f.Mode() & os.ModeType { case 0: // Regular file + id := fileID{dev: stat.Dev, ino: stat.Ino} if copyMode == Hardlink { isHardlink = true if err2 := os.Link(srcPath, dstPath); err2 != nil { return err2 } + } else if hardLinkDstPath, ok := copiedFiles[id]; ok { + if err2 := os.Link(hardLinkDstPath, dstPath); err2 != nil { + return err2 + } } else { if err2 := copyRegular(srcPath, dstPath, f, ©WithFileRange, ©WithFileClone); err2 != nil { return err2 } + copiedFiles[id] = dstPath } case os.ModeDir: @@ -192,16 +216,10 @@ func DirCopy(srcDir, dstDir string, copyMode Mode) error { return err } - if err := copyXattr(srcPath, dstPath, "security.capability"); err != nil { - return err - } - - // We need to copy this attribute if it appears in an overlay upper layer, as - // this function is used to copy those. It is set by overlay if a directory - // is removed and then re-created and should not inherit anything from the - // same dir in the lower dir. - if err := copyXattr(srcPath, dstPath, "trusted.overlay.opaque"); err != nil { - return err + if copyXattrs { + if err := doCopyXattrs(srcPath, dstPath); err != nil { + return err + } } isSymlink := f.Mode()&os.ModeSymlink != 0 @@ -216,7 +234,9 @@ func DirCopy(srcDir, dstDir string, copyMode Mode) error { // system.Chtimes doesn't support a NOFOLLOW flag atm // nolint: unconvert - if !isSymlink { + if f.IsDir() { + dirsToSetMtimes.PushFront(&dirMtimeInfo{dstPath: &dstPath, stat: stat}) + } else if !isSymlink { aTime := time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec)) mTime := time.Unix(int64(stat.Mtim.Sec), int64(stat.Mtim.Nsec)) if err := system.Chtimes(dstPath, aTime, mTime); err != nil { @@ -230,5 +250,28 @@ func DirCopy(srcDir, dstDir string, copyMode Mode) error { } return nil }) - return err + if err != nil { + return err + } + for e := dirsToSetMtimes.Front(); e != nil; e = e.Next() { + mtimeInfo := e.Value.(*dirMtimeInfo) + ts := []syscall.Timespec{mtimeInfo.stat.Atim, mtimeInfo.stat.Mtim} + if err := system.LUtimesNano(*mtimeInfo.dstPath, ts); err != nil { + return err + } + } + + return nil +} + +func doCopyXattrs(srcPath, dstPath string) error { + if err := copyXattr(srcPath, dstPath, "security.capability"); err != nil { + return err + } + + // We need to copy this attribute if it appears in an overlay upper layer, as + // this function is used to copy those. It is set by overlay if a directory + // is removed and then re-created and should not inherit anything from the + // same dir in the lower dir. + return copyXattr(srcPath, dstPath, "trusted.overlay.opaque") } diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy_test.go b/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy_test.go index 6976503e1..d21699114 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy_test.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/copy/copy_test.go @@ -3,15 +3,20 @@ package copy import ( + "fmt" "io/ioutil" "math/rand" "os" "path/filepath" + "syscall" "testing" + "time" "github.com/docker/docker/pkg/parsers/kernel" + "github.com/docker/docker/pkg/system" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/sys/unix" ) func TestIsCopyFileRangeSyscallAvailable(t *testing.T) { @@ -45,6 +50,84 @@ func TestCopyWithoutRange(t *testing.T) { doCopyTest(t, ©WithFileRange, ©WithFileClone) } +func TestCopyDir(t *testing.T) { + srcDir, err := ioutil.TempDir("", "srcDir") + require.NoError(t, err) + populateSrcDir(t, srcDir, 3) + + dstDir, err := ioutil.TempDir("", "testdst") + require.NoError(t, err) + defer os.RemoveAll(dstDir) + + assert.NoError(t, DirCopy(srcDir, dstDir, Content, false)) + require.NoError(t, filepath.Walk(srcDir, func(srcPath string, f os.FileInfo, err error) error { + if err != nil { + return err + } + + // Rebase path + relPath, err := filepath.Rel(srcDir, srcPath) + require.NoError(t, err) + if relPath == "." { + return nil + } + + dstPath := filepath.Join(dstDir, relPath) + require.NoError(t, err) + + // If we add non-regular dirs and files to the test + // then we need to add more checks here. + dstFileInfo, err := os.Lstat(dstPath) + require.NoError(t, err) + + srcFileSys := f.Sys().(*syscall.Stat_t) + dstFileSys := dstFileInfo.Sys().(*syscall.Stat_t) + + t.Log(relPath) + if srcFileSys.Dev == dstFileSys.Dev { + assert.NotEqual(t, srcFileSys.Ino, dstFileSys.Ino) + } + // Todo: check size, and ctim is not equal + /// on filesystems that have granular ctimes + assert.Equal(t, srcFileSys.Mode, dstFileSys.Mode) + assert.Equal(t, srcFileSys.Uid, dstFileSys.Uid) + assert.Equal(t, srcFileSys.Gid, dstFileSys.Gid) + assert.Equal(t, srcFileSys.Mtim, dstFileSys.Mtim) + + return nil + })) +} + +func randomMode(baseMode int) os.FileMode { + for i := 0; i < 7; i++ { + baseMode = baseMode | (1&rand.Intn(2))< 1 { return containerfs.NewLocalContainerFS(mergedDir), nil @@ -364,7 +372,13 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro defer func() { if err != nil { if c := d.ctr.Decrement(mergedDir); c <= 0 { - unix.Unmount(mergedDir, 0) + if mntErr := unix.Unmount(mergedDir, 0); mntErr != nil { + logrus.Debugf("Failed to unmount %s: %v: %v", id, mntErr, err) + } + // Cleanup the created merged directory; see the comment in Put's rmdir + if rmErr := unix.Rmdir(mergedDir); rmErr != nil && !os.IsNotExist(rmErr) { + logrus.Warnf("Failed to remove %s: %v: %v", id, rmErr, err) + } } } }() @@ -372,6 +386,13 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro if err != nil { return nil, err } + rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) + if err != nil { + return nil, err + } + if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.IDPair{rootUID, rootGID}); err != nil { + return nil, err + } var ( lowerDir = path.Join(d.dir(string(lowerID)), "root") upperDir = path.Join(dir, "upper") @@ -383,10 +404,6 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro } // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a // user namespace requires this to move a directory from lower to upper. - rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) - if err != nil { - return nil, err - } if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil { return nil, err } @@ -394,6 +411,8 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro } // Put unmounts the mount path created for the give id. +// It also removes the 'merged' directory to force the kernel to unmount the +// overlay mount in other namespaces. func (d *Driver) Put(id string) error { d.locker.Lock(id) defer d.locker.Unlock(id) @@ -408,6 +427,17 @@ func (d *Driver) Put(id string) error { if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil { logrus.Debugf("Failed to unmount %s overlay: %v", id, err) } + + // Remove the mountpoint here. Removing the mountpoint (in newer kernels) + // will cause all other instances of this mount in other mount namespaces + // to be unmounted. This is necessary to avoid cases where an overlay mount + // that is present in another namespace will cause subsequent mounts + // operations to fail with ebusy. We ignore any errors here because this may + // fail on older kernels which don't have + // torvalds/linux@8ed936b5671bfb33d89bc60bdcc7cf0470ba52fe applied. + if err := unix.Rmdir(mountpoint); err != nil { + logrus.Debugf("Failed to remove %s overlay: %v", id, err) + } return nil } @@ -446,7 +476,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64 } }() - if err = copy.DirCopy(parentRootDir, tmpRootDir, copy.Hardlink); err != nil { + if err = copy.DirCopy(parentRootDir, tmpRootDir, copy.Hardlink, true); err != nil { return 0, err } diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/check.go b/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/check.go index f29630bd2..c1c44200f 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/check.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/check.go @@ -100,3 +100,35 @@ func doesSupportNativeDiff(d string) error { return nil } + +// supportsMultipleLowerDir checks if the system supports multiple lowerdirs, +// which is required for the overlay2 driver. On 4.x kernels, multiple lowerdirs +// are always available (so this check isn't needed), and backported to RHEL and +// CentOS 3.x kernels (3.10.0-693.el7.x86_64 and up). This function is to detect +// support on those kernels, without doing a kernel version compare. +func supportsMultipleLowerDir(d string) error { + td, err := ioutil.TempDir(d, "multiple-lowerdir-check") + if err != nil { + return err + } + defer func() { + if err := os.RemoveAll(td); err != nil { + logrus.Warnf("Failed to remove check directory %v: %v", td, err) + } + }() + + for _, dir := range []string{"lower1", "lower2", "upper", "work", "merged"} { + if err := os.Mkdir(filepath.Join(td, dir), 0755); err != nil { + return err + } + } + + opts := fmt.Sprintf("lowerdir=%s:%s,upperdir=%s,workdir=%s", path.Join(td, "lower2"), path.Join(td, "lower1"), path.Join(td, "upper"), path.Join(td, "work")) + if err := unix.Mount("overlay", filepath.Join(td, "merged"), "overlay", 0, opts); err != nil { + return errors.Wrap(err, "failed to mount overlay") + } + if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil { + logrus.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err) + } + return nil +} diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/overlay.go b/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/overlay.go index c2023c725..4b596ae33 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/overlay.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/overlay2/overlay.go @@ -16,8 +16,6 @@ import ( "strings" "sync" - "github.com/sirupsen/logrus" - "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/daemon/graphdriver/overlayutils" "github.com/docker/docker/daemon/graphdriver/quota" @@ -32,9 +30,10 @@ import ( "github.com/docker/docker/pkg/parsers" "github.com/docker/docker/pkg/parsers/kernel" "github.com/docker/docker/pkg/system" - units "github.com/docker/go-units" - + "github.com/docker/go-units" + rsystem "github.com/opencontainers/runc/libcontainer/system" "github.com/opencontainers/selinux/go-selinux/label" + "github.com/sirupsen/logrus" "golang.org/x/sys/unix" ) @@ -77,7 +76,7 @@ const ( maxDepth = 128 // idLength represents the number of random characters - // which can be used to create the unique link identifer + // which can be used to create the unique link identifier // for every layer. If this value is too long then the // page size limit for the mount command may be exceeded. // The idLength should be selected such that following equation @@ -91,7 +90,8 @@ type overlayOptions struct { quota quota.Quota } -// Driver contains information about the home directory and the list of active mounts that are created using this driver. +// Driver contains information about the home directory and the list of active +// mounts that are created using this driver. type Driver struct { home string uidMaps []idtools.IDMap @@ -116,9 +116,11 @@ func init() { graphdriver.Register(driverName, Init) } -// Init returns the a native diff driver for overlay filesystem. -// If overlay filesystem is not supported on the host, graphdriver.ErrNotSupported is returned as error. -// If an overlay filesystem is not supported over an existing filesystem then error graphdriver.ErrIncompatibleFS is returned. +// Init returns the native diff driver for overlay filesystem. +// If overlay filesystem is not supported on the host, the error +// graphdriver.ErrNotSupported is returned. +// If an overlay filesystem is not supported over an existing filesystem then +// the error graphdriver.ErrIncompatibleFS is returned. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { opts, err := parseOptions(options) if err != nil { @@ -134,14 +136,17 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap if err != nil { return nil, err } - if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 4, Major: 0, Minor: 0}) < 0 { - if !opts.overrideKernelCheck { - return nil, graphdriver.ErrNotSupported - } - logrus.Warn("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update") + + // Perform feature detection on /var/lib/docker/overlay2 if it's an existing directory. + // This covers situations where /var/lib/docker/overlay2 is a mount, and on a different + // filesystem than /var/lib/docker. + // If the path does not exist, fall back to using /var/lib/docker for feature detection. + testdir := home + if _, err := os.Stat(testdir); os.IsNotExist(err) { + testdir = filepath.Dir(testdir) } - fsMagic, err := graphdriver.GetFSMagic(home) + fsMagic, err := graphdriver.GetFSMagic(testdir) if err != nil { return nil, err } @@ -149,9 +154,8 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap backingFs = fsName } - // check if they are running over btrfs, aufs, zfs, overlay, or ecryptfs switch fsMagic { - case graphdriver.FsMagicAufs, graphdriver.FsMagicZfs, graphdriver.FsMagicOverlay, graphdriver.FsMagicEcryptfs: + case graphdriver.FsMagicAufs, graphdriver.FsMagicEcryptfs, graphdriver.FsMagicNfsFs, graphdriver.FsMagicOverlay, graphdriver.FsMagicZfs: logrus.Errorf("'overlay2' is not supported over %s", backingFs) return nil, graphdriver.ErrIncompatibleFS case graphdriver.FsMagicBtrfs: @@ -166,12 +170,34 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap } } + if kernel.CompareKernelVersion(*v, kernel.VersionInfo{Kernel: 4, Major: 0, Minor: 0}) < 0 { + if opts.overrideKernelCheck { + logrus.Warn("Using pre-4.0.0 kernel for overlay2, mount failures may require kernel update") + } else { + if err := supportsMultipleLowerDir(testdir); err != nil { + logrus.Debugf("Multiple lower dirs not supported: %v", err) + return nil, graphdriver.ErrNotSupported + } + } + } + supportsDType, err := fsutils.SupportsDType(testdir) + if err != nil { + return nil, err + } + if !supportsDType { + if !graphdriver.IsInitialized(home) { + return nil, overlayutils.ErrDTypeNotSupported("overlay2", backingFs) + } + // allow running without d_type only for existing setups (#27443) + logrus.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs)) + } + rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } // Create the driver home dir - if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0700, idtools.IDPair{rootUID, rootGID}); err != nil && !os.IsExist(err) { + if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0700, idtools.IDPair{rootUID, rootGID}); err != nil { return nil, err } @@ -179,15 +205,6 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } - supportsDType, err := fsutils.SupportsDType(home) - if err != nil { - return nil, err - } - if !supportsDType { - // not a fatal error until v17.12 (#27443) - logrus.Warn(overlayutils.ErrDTypeNotSupported("overlay2", backingFs)) - } - d := &Driver{ home: home, uidMaps: uidMaps, @@ -289,8 +306,8 @@ func (d *Driver) Status() [][2]string { } } -// GetMetadata returns meta data about the overlay driver such as -// LowerDir, UpperDir, WorkDir and MergeDir used to store data. +// GetMetadata returns metadata about the overlay driver such as the LowerDir, +// UpperDir, WorkDir, and MergeDir used to store data. func (d *Driver) GetMetadata(id string) (map[string]string, error) { dir := d.dir(id) if _, err := os.Stat(dir); err != nil { @@ -414,9 +431,6 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr if err := idtools.MkdirAndChown(path.Join(dir, "work"), 0700, root); err != nil { return err } - if err := idtools.MkdirAndChown(path.Join(dir, "merged"), 0700, root); err != nil { - return err - } lower, err := d.getLower(parent) if err != nil { @@ -545,6 +559,10 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e if mntErr := unix.Unmount(mergedDir, 0); mntErr != nil { logrus.Errorf("error unmounting %v: %v", mergedDir, mntErr) } + // Cleanup the created merged directory; see the comment in Put's rmdir + if rmErr := unix.Rmdir(mergedDir); rmErr != nil && !os.IsNotExist(rmErr) { + logrus.Debugf("Failed to remove %s: %v: %v", id, rmErr, err) + } } } }() @@ -560,6 +578,14 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e mount := unix.Mount mountTarget := mergedDir + rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) + if err != nil { + return nil, err + } + if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.IDPair{rootUID, rootGID}); err != nil { + return nil, err + } + pageSize := unix.Getpagesize() // Go can return a larger page size than supported by the system @@ -594,11 +620,6 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e // chown "workdir/work" to the remapped root UID/GID. Overlay fs inside a // user namespace requires this to move a directory from lower to upper. - rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) - if err != nil { - return nil, err - } - if err := os.Chown(path.Join(workDir, "work"), rootUID, rootGID); err != nil { return nil, err } @@ -607,6 +628,8 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e } // Put unmounts the mount path created for the give id. +// It also removes the 'merged' directory to force the kernel to unmount the +// overlay mount in other namespaces. func (d *Driver) Put(id string) error { d.locker.Lock(id) defer d.locker.Unlock(id) @@ -627,6 +650,16 @@ func (d *Driver) Put(id string) error { if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil { logrus.Debugf("Failed to unmount %s overlay: %s - %v", id, mountpoint, err) } + // Remove the mountpoint here. Removing the mountpoint (in newer kernels) + // will cause all other instances of this mount in other mount namespaces + // to be unmounted. This is necessary to avoid cases where an overlay mount + // that is present in another namespace will cause subsequent mounts + // operations to fail with ebusy. We ignore any errors here because this may + // fail on older kernels which don't have + // torvalds/linux@8ed936b5671bfb33d89bc60bdcc7cf0470ba52fe applied. + if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) { + logrus.Debugf("Failed to remove %s overlay: %v", id, err) + } return nil } @@ -636,7 +669,8 @@ func (d *Driver) Exists(id string) bool { return err == nil } -// isParent returns if the passed in parent is the direct parent of the passed in layer +// isParent determines whether the given parent is the direct parent of the +// given layer id func (d *Driver) isParent(id, parent string) bool { lowers, err := d.getLowerDirs(id) if err != nil { @@ -671,6 +705,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64 UIDMaps: d.uidMaps, GIDMaps: d.gidMaps, WhiteoutFormat: archive.OverlayWhiteoutFormat, + InUserNS: rsystem.RunningInUserNS(), }); err != nil { return 0, err } @@ -711,8 +746,8 @@ func (d *Driver) Diff(id, parent string) (io.ReadCloser, error) { }) } -// Changes produces a list of changes between the specified layer -// and its parent layer. If parent is "", then all changes will be ADD changes. +// Changes produces a list of changes between the specified layer and its +// parent layer. If parent is "", then all changes will be ADD changes. func (d *Driver) Changes(id, parent string) ([]archive.Change, error) { if useNaiveDiff(d.home) || !d.isParent(id, parent) { return d.naiveDiff.Changes(id, parent) diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/overlayutils/overlayutils.go b/vendor/github.com/docker/docker/daemon/graphdriver/overlayutils/overlayutils.go index 7491c3457..9f71c60d5 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/overlayutils/overlayutils.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/overlayutils/overlayutils.go @@ -3,8 +3,9 @@ package overlayutils import ( - "errors" "fmt" + + "github.com/docker/docker/daemon/graphdriver" ) // ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type. @@ -13,6 +14,7 @@ func ErrDTypeNotSupported(driver, backingFs string) error { if backingFs == "xfs" { msg += " Reformat the filesystem with ftype=1 to enable d_type support." } - msg += " Running without d_type support will no longer be supported in Docker 17.12." - return errors.New(msg) + msg += " Backing filesystems without d_type support are not supported." + + return graphdriver.NotSupportedError(msg) } diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/quota/errors.go b/vendor/github.com/docker/docker/daemon/graphdriver/quota/errors.go index 1741f2f5d..6d755904a 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/quota/errors.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/quota/errors.go @@ -1,6 +1,6 @@ package quota -import "github.com/docker/docker/api/errdefs" +import "github.com/docker/docker/errdefs" var ( _ errdefs.ErrNotImplemented = (*errQuotaNotSupported)(nil) diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota.go b/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota.go index e25965baf..8efe5cd8a 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota.go @@ -350,11 +350,17 @@ func makeBackingFsDev(home string) (string, error) { backingFsBlockDev := path.Join(home, "backingFsBlockDev") // Re-create just in case someone copied the home directory over to a new device unix.Unlink(backingFsBlockDev) - if err := unix.Mknod(backingFsBlockDev, unix.S_IFBLK|0600, int(stat.Dev)); err != nil { + err := unix.Mknod(backingFsBlockDev, unix.S_IFBLK|0600, int(stat.Dev)) + switch err { + case nil: + return backingFsBlockDev, nil + + case unix.ENOSYS: + return "", ErrQuotaNotSupported + + default: return "", fmt.Errorf("Failed to mknod %s: %v", backingFsBlockDev, err) } - - return backingFsBlockDev, nil } func hasQuotaSupport(backingFsBlockDev string) (bool, error) { diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota_test.go b/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota_test.go index 2b47a58db..b5091472f 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota_test.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/quota/projectquota_test.go @@ -10,6 +10,7 @@ import ( "path/filepath" "testing" + "github.com/gotestyourself/gotestyourself/fs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/sys/unix" @@ -22,7 +23,7 @@ const imageSize = 64 * 1024 * 1024 func TestBlockDev(t *testing.T) { mkfs, err := exec.LookPath("mkfs.xfs") if err != nil { - t.Fatal("mkfs.xfs not installed") + t.Skip("mkfs.xfs not found in PATH") } // create a sparse image @@ -52,18 +53,11 @@ func TestBlockDev(t *testing.T) { t.Fatal(err) } - runTest(t, "testBlockDevQuotaDisabled", wrapMountTest(imageFileName, false, testBlockDevQuotaDisabled)) - runTest(t, "testBlockDevQuotaEnabled", wrapMountTest(imageFileName, true, testBlockDevQuotaEnabled)) - runTest(t, "testSmallerThanQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testSmallerThanQuota))) - runTest(t, "testBiggerThanQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testBiggerThanQuota))) - runTest(t, "testRetrieveQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testRetrieveQuota))) -} - -func runTest(t *testing.T, testName string, testFunc func(*testing.T)) { - if success := t.Run(testName, testFunc); !success { - out, _ := exec.Command("dmesg").CombinedOutput() - t.Log(string(out)) - } + t.Run("testBlockDevQuotaDisabled", wrapMountTest(imageFileName, false, testBlockDevQuotaDisabled)) + t.Run("testBlockDevQuotaEnabled", wrapMountTest(imageFileName, true, testBlockDevQuotaEnabled)) + t.Run("testSmallerThanQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testSmallerThanQuota))) + t.Run("testBiggerThanQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testBiggerThanQuota))) + t.Run("testRetrieveQuota", wrapMountTest(imageFileName, true, wrapQuotaTest(testRetrieveQuota))) } func wrapMountTest(imageFileName string, enableQuota bool, testFunc func(t *testing.T, mountPoint, backingFsDev string)) func(*testing.T) { @@ -74,25 +68,22 @@ func wrapMountTest(imageFileName string, enableQuota bool, testFunc func(t *test mountOptions = mountOptions + ",prjquota" } - // create a mountPoint - mountPoint, err := ioutil.TempDir("", "xfs-mountPoint") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(mountPoint) + mountPointDir := fs.NewDir(t, "xfs-mountPoint") + defer mountPointDir.Remove() + mountPoint := mountPointDir.Path() out, err := exec.Command("mount", "-o", mountOptions, imageFileName, mountPoint).CombinedOutput() - if len(out) > 0 { - t.Log(string(out)) - } if err != nil { - t.Fatal("mount failed") + _, err := os.Stat("/proc/fs/xfs") + if os.IsNotExist(err) { + t.Skip("no /proc/fs/xfs") + } } + require.NoError(t, err, "mount failed: %s", out) + defer func() { - if err := unix.Unmount(mountPoint, 0); err != nil { - t.Fatal(err) - } + require.NoError(t, unix.Unmount(mountPoint, 0)) }() backingFsDev, err := makeBackingFsDev(mountPoint) diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/vfs/copy_linux.go b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/copy_linux.go new file mode 100644 index 000000000..1a63a1180 --- /dev/null +++ b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/copy_linux.go @@ -0,0 +1,7 @@ +package vfs + +import "github.com/docker/docker/daemon/graphdriver/copy" + +func dirCopy(srcDir, dstDir string) error { + return copy.DirCopy(srcDir, dstDir, copy.Content, false) +} diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/vfs/copy_unsupported.go b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/copy_unsupported.go new file mode 100644 index 000000000..fcc4b691a --- /dev/null +++ b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/copy_unsupported.go @@ -0,0 +1,9 @@ +// +build !linux + +package vfs + +import "github.com/docker/docker/pkg/chrootarchive" + +func dirCopy(srcDir, dstDir string) error { + return chrootarchive.NewArchiver(nil).CopyWithTar(srcDir, dstDir) +} diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/vfs/driver.go b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/driver.go index 610476fd8..5f9cad4ae 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/vfs/driver.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/driver.go @@ -7,7 +7,6 @@ import ( "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/daemon/graphdriver/quota" - "github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/system" @@ -16,8 +15,8 @@ import ( ) var ( - // CopyWithTar defines the copy method to use. - CopyWithTar = chrootarchive.NewArchiver(nil).CopyWithTar + // CopyDir defines the copy method to use. + CopyDir = dirCopy ) func init() { @@ -36,9 +35,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } - if err := setupDriverQuota(d); err != nil { - return nil, err - } + setupDriverQuota(d) return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil } @@ -133,7 +130,7 @@ func (d *Driver) create(id, parent string, size uint64) error { if err != nil { return fmt.Errorf("%s: %s", parent, err) } - return CopyWithTar(parentDir.Path(), dir) + return CopyDir(parentDir.Path(), dir) } func (d *Driver) dir(id string) string { diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/vfs/quota_linux.go b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/quota_linux.go index 032c15b9e..f871befba 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/vfs/quota_linux.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/vfs/quota_linux.go @@ -1,21 +1,20 @@ -// +build linux - package vfs -import "github.com/docker/docker/daemon/graphdriver/quota" +import ( + "github.com/docker/docker/daemon/graphdriver/quota" + "github.com/sirupsen/logrus" +) type driverQuota struct { quotaCtl *quota.Control } -func setupDriverQuota(driver *Driver) error { +func setupDriverQuota(driver *Driver) { if quotaCtl, err := quota.NewControl(driver.home); err == nil { driver.quotaCtl = quotaCtl } else if err != quota.ErrQuotaNotSupported { - return err + logrus.Warnf("Unable to setup quota: %v\n", err) } - - return nil } func (d *Driver) setupQuota(dir string, size uint64) error { diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/windows/windows.go b/vendor/github.com/docker/docker/daemon/graphdriver/windows/windows.go index f3d239d76..3c05a01b0 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/windows/windows.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/windows/windows.go @@ -931,8 +931,6 @@ func parseStorageOpt(storageOpt map[string]string) (*storageOptions, error) { return nil, err } options.size = uint64(size) - default: - return nil, fmt.Errorf("Unknown storage option: %s", key) } } return &options, nil diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs.go b/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs.go index 51d31bcfc..8b3f78d82 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs.go @@ -181,9 +181,10 @@ func (d *Driver) String() string { return "zfs" } -// Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver. +// Cleanup is called on daemon shutdown. It unmounts the bind mount +// created by mount.MakePrivate() in Init(). func (d *Driver) Cleanup() error { - return nil + return mount.Unmount(d.options.mountPath) } // Status returns information about the ZFS filesystem. It returns a two dimensional array of information @@ -357,11 +358,24 @@ func (d *Driver) Remove(id string) error { } // Get returns the mountpoint for the given id after creating the target directories if necessary. -func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { +func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr error) { mountpoint := d.mountPath(id) if count := d.ctr.Increment(mountpoint); count > 1 { return containerfs.NewLocalContainerFS(mountpoint), nil } + defer func() { + if retErr != nil { + if c := d.ctr.Decrement(mountpoint); c <= 0 { + if mntErr := unix.Unmount(mountpoint, 0); mntErr != nil { + logrus.Errorf("Error unmounting %v: %v", mountpoint, mntErr) + } + if rmErr := unix.Rmdir(mountpoint); rmErr != nil && !os.IsNotExist(rmErr) { + logrus.Debugf("Failed to remove %s: %v", id, rmErr) + } + + } + } + }() filesystem := d.zfsPath(id) options := label.FormatMountLabel("", mountLabel) @@ -369,25 +383,20 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) { rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) if err != nil { - d.ctr.Decrement(mountpoint) return nil, err } // Create the target directories if they don't exist if err := idtools.MkdirAllAndChown(mountpoint, 0755, idtools.IDPair{rootUID, rootGID}); err != nil { - d.ctr.Decrement(mountpoint) return nil, err } if err := mount.Mount(filesystem, mountpoint, "zfs", options); err != nil { - d.ctr.Decrement(mountpoint) return nil, fmt.Errorf("error creating zfs mount of %s to %s: %v", filesystem, mountpoint, err) } // this could be our first mount after creation of the filesystem, and the root dir may still have root // permissions instead of the remapped root uid:gid (if user namespaces are enabled): if err := os.Chown(mountpoint, rootUID, rootGID); err != nil { - mount.Unmount(mountpoint) - d.ctr.Decrement(mountpoint) return nil, fmt.Errorf("error modifying zfs mountpoint (%s) directory ownership: %v", mountpoint, err) } @@ -400,16 +409,16 @@ func (d *Driver) Put(id string) error { if count := d.ctr.Decrement(mountpoint); count > 0 { return nil } - mounted, err := graphdriver.Mounted(graphdriver.FsMagicZfs, mountpoint) - if err != nil || !mounted { - return err - } logrus.Debugf(`[zfs] unmount("%s")`, mountpoint) - if err := mount.Unmount(mountpoint); err != nil { - return fmt.Errorf("error unmounting to %s: %v", mountpoint, err) + if err := unix.Unmount(mountpoint, unix.MNT_DETACH); err != nil { + logrus.Warnf("Failed to unmount %s mount %s: %v", id, mountpoint, err) } + if err := unix.Rmdir(mountpoint); err != nil && !os.IsNotExist(err) { + logrus.Debugf("Failed to remove %s mount point %s: %v", id, mountpoint, err) + } + return nil } diff --git a/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs_linux.go b/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs_linux.go index 71d6d3cb4..62ef63528 100644 --- a/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs_linux.go +++ b/vendor/github.com/docker/docker/daemon/graphdriver/zfs/zfs_linux.go @@ -1,21 +1,22 @@ package zfs import ( - "fmt" - "github.com/docker/docker/daemon/graphdriver" "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" ) -func checkRootdirFs(rootdir string) error { - var buf unix.Statfs_t - if err := unix.Statfs(rootdir, &buf); err != nil { - return fmt.Errorf("Failed to access '%s': %s", rootdir, err) +func checkRootdirFs(rootDir string) error { + fsMagic, err := graphdriver.GetFSMagic(rootDir) + if err != nil { + return err + } + backingFS := "unknown" + if fsName, ok := graphdriver.FsNames[fsMagic]; ok { + backingFS = fsName } - if graphdriver.FsMagic(buf.Type) != graphdriver.FsMagicZfs { - logrus.Debugf("[zfs] no zfs dataset found for rootdir '%s'", rootdir) + if fsMagic != graphdriver.FsMagicZfs { + logrus.WithField("root", rootDir).WithField("backingFS", backingFS).WithField("driver", "zfs").Error("No zfs dataset found for root") return graphdriver.ErrPrerequisites } diff --git a/vendor/github.com/docker/docker/daemon/health.go b/vendor/github.com/docker/docker/daemon/health.go index 26ae20f9b..ff3d54d45 100644 --- a/vendor/github.com/docker/docker/daemon/health.go +++ b/vendor/github.com/docker/docker/daemon/health.go @@ -80,6 +80,7 @@ func (p *cmdProbe) run(ctx context.Context, d *Daemon, cntr *container.Container execConfig.Tty = false execConfig.Privileged = false execConfig.User = cntr.Config.User + execConfig.WorkingDir = cntr.Config.WorkingDir linkedEnv, err := d.setupLinkedContainers(cntr) if err != nil { @@ -88,7 +89,10 @@ func (p *cmdProbe) run(ctx context.Context, d *Daemon, cntr *container.Container execConfig.Env = container.ReplaceOrAppendEnvValues(cntr.CreateDaemonEnvironment(execConfig.Tty, linkedEnv), execConfig.Env) d.registerExecCommand(cntr, execConfig) - d.LogContainerEvent(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " ")) + attributes := map[string]string{ + "execID": execConfig.ID, + } + d.LogContainerEventWithAttributes(cntr, "exec_create: "+execConfig.Entrypoint+" "+strings.Join(execConfig.Args, " "), attributes) output := &limitedBuffer{} err = d.ContainerExecStart(ctx, execConfig.ID, nil, output, output) @@ -254,6 +258,8 @@ func getProbe(c *container.Container) probe { return &cmdProbe{shell: false} case "CMD-SHELL": return &cmdProbe{shell: true} + case "NONE": + return nil default: logrus.Warnf("Unknown healthcheck type '%s' (expected 'CMD') in container %s", config.Test[0], c.ID) return nil diff --git a/vendor/github.com/docker/docker/daemon/image.go b/vendor/github.com/docker/docker/daemon/image.go index 6e90429d5..c2afa02f1 100644 --- a/vendor/github.com/docker/docker/daemon/image.go +++ b/vendor/github.com/docker/docker/daemon/image.go @@ -2,11 +2,10 @@ package daemon import ( "fmt" - "runtime" "github.com/docker/distribution/reference" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" - "github.com/docker/docker/pkg/stringid" ) // errImageDoesNotExist is error returned when no image can be found for a reference. @@ -29,7 +28,7 @@ func (e errImageDoesNotExist) NotFound() {} func (daemon *Daemon) GetImageIDAndOS(refOrID string) (image.ID, string, error) { ref, err := reference.ParseAnyReference(refOrID) if err != nil { - return "", "", validationError{err} + return "", "", errdefs.InvalidParameter(err) } namedRef, ok := ref.(reference.Named) if !ok { @@ -38,47 +37,27 @@ func (daemon *Daemon) GetImageIDAndOS(refOrID string) (image.ID, string, error) return "", "", errImageDoesNotExist{ref} } id := image.IDFromDigest(digested.Digest()) - for platform := range daemon.stores { - if _, err = daemon.stores[platform].imageStore.Get(id); err == nil { - return id, platform, nil - } + if img, err := daemon.imageStore.Get(id); err == nil { + return id, img.OperatingSystem(), nil } return "", "", errImageDoesNotExist{ref} } if digest, err := daemon.referenceStore.Get(namedRef); err == nil { // Search the image stores to get the operating system, defaulting to host OS. - imageOS := runtime.GOOS id := image.IDFromDigest(digest) - for os := range daemon.stores { - if img, err := daemon.stores[os].imageStore.Get(id); err == nil { - imageOS = img.OperatingSystem() - break - } - } - return id, imageOS, nil - } - - // deprecated: repo:shortid https://github.com/docker/docker/pull/799 - if tagged, ok := namedRef.(reference.Tagged); ok { - if tag := tagged.Tag(); stringid.IsShortID(stringid.TruncateID(tag)) { - for platform := range daemon.stores { - if id, err := daemon.stores[platform].imageStore.Search(tag); err == nil { - for _, storeRef := range daemon.referenceStore.References(id.Digest()) { - if storeRef.Name() == namedRef.Name() { - return id, platform, nil - } - } - } - } + if img, err := daemon.imageStore.Get(id); err == nil { + return id, img.OperatingSystem(), nil } } // Search based on ID - for os := range daemon.stores { - if id, err := daemon.stores[os].imageStore.Search(refOrID); err == nil { - return id, os, nil + if id, err := daemon.imageStore.Search(refOrID); err == nil { + img, err := daemon.imageStore.Get(id) + if err != nil { + return "", "", errImageDoesNotExist{ref} } + return id, img.OperatingSystem(), nil } return "", "", errImageDoesNotExist{ref} @@ -86,9 +65,9 @@ func (daemon *Daemon) GetImageIDAndOS(refOrID string) (image.ID, string, error) // GetImage returns an image corresponding to the image referred to by refOrID. func (daemon *Daemon) GetImage(refOrID string) (*image.Image, error) { - imgID, os, err := daemon.GetImageIDAndOS(refOrID) + imgID, _, err := daemon.GetImageIDAndOS(refOrID) if err != nil { return nil, err } - return daemon.stores[os].imageStore.Get(imgID) + return daemon.imageStore.Get(imgID) } diff --git a/vendor/github.com/docker/docker/daemon/image_delete.go b/vendor/github.com/docker/docker/daemon/image_delete.go index 8e51931cc..c5dc57829 100644 --- a/vendor/github.com/docker/docker/daemon/image_delete.go +++ b/vendor/github.com/docker/docker/daemon/image_delete.go @@ -8,8 +8,10 @@ import ( "github.com/docker/distribution/reference" "github.com/docker/docker/api/types" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/pkg/system" "github.com/pkg/errors" ) @@ -65,10 +67,13 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I start := time.Now() records := []types.ImageDeleteResponseItem{} - imgID, os, err := daemon.GetImageIDAndOS(imageRef) + imgID, operatingSystem, err := daemon.GetImageIDAndOS(imageRef) if err != nil { return nil, err } + if !system.IsOSSupported(operatingSystem) { + return nil, errors.Errorf("unable to delete image: %q", system.ErrNotSupportedOperatingSystem) + } repoRefs := daemon.referenceStore.References(imgID.Digest()) @@ -85,7 +90,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I // we really want to avoid that the client must // explicitly force its removal. err := errors.Errorf("conflict: unable to remove repository reference %q (must force) - container %s is using its referenced image %s", imageRef, stringid.TruncateID(container.ID), stringid.TruncateID(imgID.String())) - return nil, stateConflictError{err} + return nil, errdefs.Conflict(err) } } @@ -94,7 +99,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I return nil, err } - parsedRef, err = daemon.removeImageRef(os, parsedRef) + parsedRef, err = daemon.removeImageRef(parsedRef) if err != nil { return nil, err } @@ -122,7 +127,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I remainingRefs := []reference.Named{} for _, repoRef := range repoRefs { if _, repoRefIsCanonical := repoRef.(reference.Canonical); repoRefIsCanonical && parsedRef.Name() == repoRef.Name() { - if _, err := daemon.removeImageRef(os, repoRef); err != nil { + if _, err := daemon.removeImageRef(repoRef); err != nil { return records, err } @@ -152,12 +157,12 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I if !force { c |= conflictSoft &^ conflictActiveReference } - if conflict := daemon.checkImageDeleteConflict(imgID, os, c); conflict != nil { + if conflict := daemon.checkImageDeleteConflict(imgID, c); conflict != nil { return nil, conflict } for _, repoRef := range repoRefs { - parsedRef, err := daemon.removeImageRef(os, repoRef) + parsedRef, err := daemon.removeImageRef(repoRef) if err != nil { return nil, err } @@ -170,7 +175,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I } } - if err := daemon.imageDeleteHelper(imgID, os, &records, force, prune, removedRepositoryRef); err != nil { + if err := daemon.imageDeleteHelper(imgID, &records, force, prune, removedRepositoryRef); err != nil { return nil, err } @@ -231,7 +236,7 @@ func (daemon *Daemon) getContainerUsingImage(imageID image.ID) *container.Contai // repositoryRef must not be an image ID but a repository name followed by an // optional tag or digest reference. If tag or digest is omitted, the default // tag is used. Returns the resolved image reference and an error. -func (daemon *Daemon) removeImageRef(platform string, ref reference.Named) (reference.Named, error) { +func (daemon *Daemon) removeImageRef(ref reference.Named) (reference.Named, error) { ref = reference.TagNameOnly(ref) // Ignore the boolean value returned, as far as we're concerned, this @@ -247,11 +252,11 @@ func (daemon *Daemon) removeImageRef(platform string, ref reference.Named) (refe // on the first encountered error. Removed references are logged to this // daemon's event service. An "Untagged" types.ImageDeleteResponseItem is added to the // given list of records. -func (daemon *Daemon) removeAllReferencesToImageID(imgID image.ID, platform string, records *[]types.ImageDeleteResponseItem) error { +func (daemon *Daemon) removeAllReferencesToImageID(imgID image.ID, records *[]types.ImageDeleteResponseItem) error { imageRefs := daemon.referenceStore.References(imgID.Digest()) for _, imageRef := range imageRefs { - parsedRef, err := daemon.removeImageRef(platform, imageRef) + parsedRef, err := daemon.removeImageRef(imageRef) if err != nil { return err } @@ -298,15 +303,15 @@ func (idc *imageDeleteConflict) Conflict() {} // conflict is encountered, it will be returned immediately without deleting // the image. If quiet is true, any encountered conflicts will be ignored and // the function will return nil immediately without deleting the image. -func (daemon *Daemon) imageDeleteHelper(imgID image.ID, platform string, records *[]types.ImageDeleteResponseItem, force, prune, quiet bool) error { +func (daemon *Daemon) imageDeleteHelper(imgID image.ID, records *[]types.ImageDeleteResponseItem, force, prune, quiet bool) error { // First, determine if this image has any conflicts. Ignore soft conflicts // if force is true. c := conflictHard if !force { c |= conflictSoft } - if conflict := daemon.checkImageDeleteConflict(imgID, platform, c); conflict != nil { - if quiet && (!daemon.imageIsDangling(imgID, platform) || conflict.used) { + if conflict := daemon.checkImageDeleteConflict(imgID, c); conflict != nil { + if quiet && (!daemon.imageIsDangling(imgID) || conflict.used) { // Ignore conflicts UNLESS the image is "dangling" or not being used in // which case we want the user to know. return nil @@ -317,18 +322,18 @@ func (daemon *Daemon) imageDeleteHelper(imgID image.ID, platform string, records return conflict } - parent, err := daemon.stores[platform].imageStore.GetParent(imgID) + parent, err := daemon.imageStore.GetParent(imgID) if err != nil { // There may be no parent parent = "" } // Delete all repository tag/digest references to this image. - if err := daemon.removeAllReferencesToImageID(imgID, platform, records); err != nil { + if err := daemon.removeAllReferencesToImageID(imgID, records); err != nil { return err } - removedLayers, err := daemon.stores[platform].imageStore.Delete(imgID) + removedLayers, err := daemon.imageStore.Delete(imgID) if err != nil { return err } @@ -348,7 +353,7 @@ func (daemon *Daemon) imageDeleteHelper(imgID image.ID, platform string, records // either running or stopped). // Do not force prunings, but do so quietly (stopping on any encountered // conflicts). - return daemon.imageDeleteHelper(parent, platform, records, false, true, true) + return daemon.imageDeleteHelper(parent, records, false, true, true) } // checkImageDeleteConflict determines whether there are any conflicts @@ -357,9 +362,9 @@ func (daemon *Daemon) imageDeleteHelper(imgID image.ID, platform string, records // using the image. A soft conflict is any tags/digest referencing the given // image or any stopped container using the image. If ignoreSoftConflicts is // true, this function will not check for soft conflict conditions. -func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, platform string, mask conflictType) *imageDeleteConflict { +func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, mask conflictType) *imageDeleteConflict { // Check if the image has any descendant images. - if mask&conflictDependentChild != 0 && len(daemon.stores[platform].imageStore.Children(imgID)) > 0 { + if mask&conflictDependentChild != 0 && len(daemon.imageStore.Children(imgID)) > 0 { return &imageDeleteConflict{ hard: true, imgID: imgID, @@ -410,6 +415,6 @@ func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, platform string, // imageIsDangling returns whether the given image is "dangling" which means // that there are no repository references to the given image and it has no // child images. -func (daemon *Daemon) imageIsDangling(imgID image.ID, platform string) bool { - return !(len(daemon.referenceStore.References(imgID.Digest())) > 0 || len(daemon.stores[platform].imageStore.Children(imgID)) > 0) +func (daemon *Daemon) imageIsDangling(imgID image.ID) bool { + return !(len(daemon.referenceStore.References(imgID.Digest())) > 0 || len(daemon.imageStore.Children(imgID)) > 0) } diff --git a/vendor/github.com/docker/docker/daemon/image_exporter.go b/vendor/github.com/docker/docker/daemon/image_exporter.go index ce9aa7a05..4b85b30e1 100644 --- a/vendor/github.com/docker/docker/daemon/image_exporter.go +++ b/vendor/github.com/docker/docker/daemon/image_exporter.go @@ -2,10 +2,8 @@ package daemon import ( "io" - "runtime" "github.com/docker/docker/image/tarexport" - "github.com/docker/docker/pkg/system" ) // ExportImage exports a list of images to the given output stream. The @@ -14,12 +12,7 @@ import ( // the same tag are exported. names is the set of tags to export, and // outStream is the writer which the images are written to. func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error { - // TODO @jhowardmsft LCOW. This will need revisiting later. - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - imageExporter := tarexport.NewTarExporter(daemon.stores[platform].imageStore, daemon.stores[platform].layerStore, daemon.referenceStore, daemon) + imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStores, daemon.referenceStore, daemon) return imageExporter.Save(names, outStream) } @@ -27,11 +20,6 @@ func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error { // complement of ImageExport. The input stream is an uncompressed tar // ball containing images and metadata. func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error { - // TODO @jhowardmsft LCOW. This will need revisiting later. - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - imageExporter := tarexport.NewTarExporter(daemon.stores[platform].imageStore, daemon.stores[platform].layerStore, daemon.referenceStore, daemon) + imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStores, daemon.referenceStore, daemon) return imageExporter.Load(inTar, outStream, quiet) } diff --git a/vendor/github.com/docker/docker/daemon/image_history.go b/vendor/github.com/docker/docker/daemon/image_history.go index e7dd85cba..9cb9efc3c 100644 --- a/vendor/github.com/docker/docker/daemon/image_history.go +++ b/vendor/github.com/docker/docker/daemon/image_history.go @@ -2,7 +2,6 @@ package daemon import ( "fmt" - "runtime" "time" "github.com/docker/distribution/reference" @@ -19,12 +18,6 @@ func (daemon *Daemon) ImageHistory(name string) ([]*image.HistoryResponseItem, e return nil, err } - // If the image OS isn't set, assume it's the host OS - platform := img.OS - if platform == "" { - platform = runtime.GOOS - } - history := []*image.HistoryResponseItem{} layerCounter := 0 @@ -40,12 +33,12 @@ func (daemon *Daemon) ImageHistory(name string) ([]*image.HistoryResponseItem, e } rootFS.Append(img.RootFS.DiffIDs[layerCounter]) - l, err := daemon.stores[platform].layerStore.Get(rootFS.ChainID()) + l, err := daemon.layerStores[img.OperatingSystem()].Get(rootFS.ChainID()) if err != nil { return nil, err } layerSize, err = l.DiffSize() - layer.ReleaseAndLog(daemon.stores[platform].layerStore, l) + layer.ReleaseAndLog(daemon.layerStores[img.OperatingSystem()], l) if err != nil { return nil, err } diff --git a/vendor/github.com/docker/docker/daemon/image_inspect.go b/vendor/github.com/docker/docker/daemon/image_inspect.go index fefb93c6e..6d76c0a94 100644 --- a/vendor/github.com/docker/docker/daemon/image_inspect.go +++ b/vendor/github.com/docker/docker/daemon/image_inspect.go @@ -1,12 +1,12 @@ package daemon import ( - "runtime" "time" "github.com/docker/distribution/reference" "github.com/docker/docker/api/types" "github.com/docker/docker/layer" + "github.com/docker/docker/pkg/system" "github.com/pkg/errors" ) @@ -17,13 +17,9 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { if err != nil { return nil, errors.Wrapf(err, "no such image: %s", name) } - - // If the image OS isn't set, assume it's the host OS - platform := img.OS - if platform == "" { - platform = runtime.GOOS + if !system.IsOSSupported(img.OperatingSystem()) { + return nil, system.ErrNotSupportedOperatingSystem } - refs := daemon.referenceStore.References(img.ID().Digest()) repoTags := []string{} repoDigests := []string{} @@ -40,11 +36,11 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { var layerMetadata map[string]string layerID := img.RootFS.ChainID() if layerID != "" { - l, err := daemon.stores[platform].layerStore.Get(layerID) + l, err := daemon.layerStores[img.OperatingSystem()].Get(layerID) if err != nil { return nil, err } - defer layer.ReleaseAndLog(daemon.stores[platform].layerStore, l) + defer layer.ReleaseAndLog(daemon.layerStores[img.OperatingSystem()], l) size, err = l.Size() if err != nil { return nil, err @@ -61,7 +57,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { comment = img.History[len(img.History)-1].Comment } - lastUpdated, err := daemon.stores[platform].imageStore.GetLastUpdated(img.ID()) + lastUpdated, err := daemon.imageStore.GetLastUpdated(img.ID()) if err != nil { return nil, err } @@ -79,7 +75,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { Author: img.Author, Config: img.Config, Architecture: img.Architecture, - Os: platform, + Os: img.OperatingSystem(), OsVersion: img.OSVersion, Size: size, VirtualSize: size, // TODO: field unused, deprecate @@ -89,7 +85,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) { }, } - imageInspect.GraphDriver.Name = daemon.GraphDriverName(platform) + imageInspect.GraphDriver.Name = daemon.GraphDriverName(img.OperatingSystem()) imageInspect.GraphDriver.Data = layerMetadata return imageInspect, nil diff --git a/vendor/github.com/docker/docker/daemon/image_pull.go b/vendor/github.com/docker/docker/daemon/image_pull.go index aef1876ba..318e3582d 100644 --- a/vendor/github.com/docker/docker/daemon/image_pull.go +++ b/vendor/github.com/docker/docker/daemon/image_pull.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/distribution" progressutils "github.com/docker/docker/distribution/utils" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/progress" "github.com/docker/docker/registry" "github.com/opencontainers/go-digest" @@ -18,7 +19,7 @@ import ( // PullImage initiates a pull operation. image is the repository name to pull, and // tag may be either empty, or indicate a specific tag to pull. -func (daemon *Daemon) PullImage(ctx context.Context, image, tag, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error { +func (daemon *Daemon) PullImage(ctx context.Context, image, tag, os string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error { // Special case: "pull -a" may send an image name with a // trailing :. This is ugly, but let's not break API // compatibility. @@ -26,7 +27,7 @@ func (daemon *Daemon) PullImage(ctx context.Context, image, tag, platform string ref, err := reference.ParseNormalizedNamed(image) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } if tag != "" { @@ -39,14 +40,14 @@ func (daemon *Daemon) PullImage(ctx context.Context, image, tag, platform string ref, err = reference.WithTag(ref, tag) } if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } } - return daemon.pullImageWithReference(ctx, ref, platform, metaHeaders, authConfig, outStream) + return daemon.pullImageWithReference(ctx, ref, os, metaHeaders, authConfig, outStream) } -func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, platform string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error { +func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, os string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error { // Include a buffer so that slow client connections don't affect // transfer performance. progressChan := make(chan progress.Progress, 100) @@ -61,8 +62,8 @@ func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference. }() // Default to the host OS platform in case it hasn't been populated with an explicit value. - if platform == "" { - platform = runtime.GOOS + if os == "" { + os = runtime.GOOS } imagePullConfig := &distribution.ImagePullConfig{ @@ -72,13 +73,13 @@ func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference. ProgressOutput: progress.ChanOutput(progressChan), RegistryService: daemon.RegistryService, ImageEventLogger: daemon.LogImageEvent, - MetadataStore: daemon.stores[platform].distributionMetadataStore, - ImageStore: distribution.NewImageConfigStoreFromStore(daemon.stores[platform].imageStore), + MetadataStore: daemon.distributionMetadataStore, + ImageStore: distribution.NewImageConfigStoreFromStore(daemon.imageStore), ReferenceStore: daemon.referenceStore, }, DownloadManager: daemon.downloadManager, Schema2Types: distribution.ImageTypes, - Platform: platform, + OS: os, } err := distribution.Pull(ctx, ref, imagePullConfig) @@ -96,7 +97,7 @@ func (daemon *Daemon) GetRepository(ctx context.Context, ref reference.Named, au } // makes sure name is not empty or `scratch` if err := distribution.ValidateRepoName(repoInfo.Name); err != nil { - return nil, false, validationError{err} + return nil, false, errdefs.InvalidParameter(err) } // get endpoints diff --git a/vendor/github.com/docker/docker/daemon/image_push.go b/vendor/github.com/docker/docker/daemon/image_push.go index b55807337..a98fe1fd1 100644 --- a/vendor/github.com/docker/docker/daemon/image_push.go +++ b/vendor/github.com/docker/docker/daemon/image_push.go @@ -2,7 +2,6 @@ package daemon import ( "io" - "runtime" "github.com/docker/distribution/manifest/schema2" "github.com/docker/distribution/reference" @@ -10,7 +9,6 @@ import ( "github.com/docker/docker/distribution" progressutils "github.com/docker/docker/distribution/utils" "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/system" "golang.org/x/net/context" ) @@ -41,12 +39,6 @@ func (daemon *Daemon) PushImage(ctx context.Context, image, tag string, metaHead close(writesDone) }() - // TODO @jhowardmsft LCOW Support. This will require revisiting. For now, hard-code. - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - imagePushConfig := &distribution.ImagePushConfig{ Config: distribution.Config{ MetaHeaders: metaHeaders, @@ -54,12 +46,12 @@ func (daemon *Daemon) PushImage(ctx context.Context, image, tag string, metaHead ProgressOutput: progress.ChanOutput(progressChan), RegistryService: daemon.RegistryService, ImageEventLogger: daemon.LogImageEvent, - MetadataStore: daemon.stores[platform].distributionMetadataStore, - ImageStore: distribution.NewImageConfigStoreFromStore(daemon.stores[platform].imageStore), + MetadataStore: daemon.distributionMetadataStore, + ImageStore: distribution.NewImageConfigStoreFromStore(daemon.imageStore), ReferenceStore: daemon.referenceStore, }, ConfigMediaType: schema2.MediaTypeImageConfig, - LayerStore: distribution.NewLayerProviderFromStore(daemon.stores[platform].layerStore), + LayerStores: distribution.NewLayerProvidersFromStores(daemon.layerStores), TrustKey: daemon.trustKey, UploadManager: daemon.uploadManager, } diff --git a/vendor/github.com/docker/docker/daemon/image_tag.go b/vendor/github.com/docker/docker/daemon/image_tag.go index cfac6d6ac..a955f7d97 100644 --- a/vendor/github.com/docker/docker/daemon/image_tag.go +++ b/vendor/github.com/docker/docker/daemon/image_tag.go @@ -8,7 +8,7 @@ import ( // TagImage creates the tag specified by newTag, pointing to the image named // imageName (alternatively, imageName can also be an image ID). func (daemon *Daemon) TagImage(imageName, repository, tag string) error { - imageID, os, err := daemon.GetImageIDAndOS(imageName) + imageID, _, err := daemon.GetImageIDAndOS(imageName) if err != nil { return err } @@ -23,16 +23,16 @@ func (daemon *Daemon) TagImage(imageName, repository, tag string) error { } } - return daemon.TagImageWithReference(imageID, os, newTag) + return daemon.TagImageWithReference(imageID, newTag) } // TagImageWithReference adds the given reference to the image ID provided. -func (daemon *Daemon) TagImageWithReference(imageID image.ID, os string, newTag reference.Named) error { +func (daemon *Daemon) TagImageWithReference(imageID image.ID, newTag reference.Named) error { if err := daemon.referenceStore.AddTag(newTag, imageID.Digest(), true); err != nil { return err } - if err := daemon.stores[os].imageStore.SetLastUpdated(imageID); err != nil { + if err := daemon.imageStore.SetLastUpdated(imageID); err != nil { return err } daemon.LogImageEvent(imageID.String(), reference.FamiliarString(newTag), "tag") diff --git a/vendor/github.com/docker/docker/daemon/images.go b/vendor/github.com/docker/docker/daemon/images.go index 7cd2c628f..5d388581f 100644 --- a/vendor/github.com/docker/docker/daemon/images.go +++ b/vendor/github.com/docker/docker/daemon/images.go @@ -3,7 +3,6 @@ package daemon import ( "encoding/json" "fmt" - "runtime" "sort" "time" @@ -36,12 +35,7 @@ func (r byCreated) Less(i, j int) bool { return r[i].Created < r[j].Created } // Map returns a map of all images in the ImageStore func (daemon *Daemon) Map() map[image.ID]*image.Image { - // TODO @jhowardmsft LCOW. This can be removed when imagestores are coalesced - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - return daemon.stores[platform].imageStore.Map() + return daemon.imageStore.Map() } // Images returns a filtered list of images. filterArgs is a JSON-encoded set @@ -50,13 +44,6 @@ func (daemon *Daemon) Map() map[image.ID]*image.Image { // named all controls whether all images in the graph are filtered, or just // the heads. func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs bool) ([]*types.ImageSummary, error) { - - // TODO @jhowardmsft LCOW. This can be removed when imagestores are coalesced - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - var ( allImages map[image.ID]*image.Image err error @@ -75,9 +62,9 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs } } if danglingOnly { - allImages = daemon.stores[platform].imageStore.Heads() + allImages = daemon.imageStore.Heads() } else { - allImages = daemon.stores[platform].imageStore.Map() + allImages = daemon.imageStore.Map() } var beforeFilter, sinceFilter *image.Image @@ -127,10 +114,17 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs } } + // Skip any images with an unsupported operating system to avoid a potential + // panic when indexing through the layerstore. Don't error as we want to list + // the other images. This should never happen, but here as a safety precaution. + if !system.IsOSSupported(img.OperatingSystem()) { + continue + } + layerID := img.RootFS.ChainID() var size int64 if layerID != "" { - l, err := daemon.stores[platform].layerStore.Get(layerID) + l, err := daemon.layerStores[img.OperatingSystem()].Get(layerID) if err != nil { // The layer may have been deleted between the call to `Map()` or // `Heads()` and the call to `Get()`, so we just ignore this error @@ -141,7 +135,7 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs } size, err = l.Size() - layer.ReleaseAndLog(daemon.stores[platform].layerStore, l) + layer.ReleaseAndLog(daemon.layerStores[img.OperatingSystem()], l) if err != nil { return nil, err } @@ -171,7 +165,7 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs } } if newImage.RepoDigests == nil && newImage.RepoTags == nil { - if all || len(daemon.stores[platform].imageStore.Children(id)) == 0 { + if all || len(daemon.imageStore.Children(id)) == 0 { if imageFilters.Contains("dangling") && !danglingOnly { //dangling=false case, so dangling image is not needed @@ -193,7 +187,7 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs // lazily init variables if imagesMap == nil { allContainers = daemon.List() - allLayers = daemon.stores[platform].layerStore.Map() + allLayers = daemon.layerStores[img.OperatingSystem()].Map() imagesMap = make(map[*image.Image]*types.ImageSummary) layerRefs = make(map[layer.ChainID]int) } @@ -261,19 +255,14 @@ func (daemon *Daemon) SquashImage(id, parent string) (string, error) { img *image.Image err error ) - for _, ds := range daemon.stores { - if img, err = ds.imageStore.Get(image.ID(id)); err == nil { - break - } - } - if err != nil { + if img, err = daemon.imageStore.Get(image.ID(id)); err != nil { return "", err } var parentImg *image.Image var parentChainID layer.ChainID if len(parent) != 0 { - parentImg, err = daemon.stores[img.OperatingSystem()].imageStore.Get(image.ID(parent)) + parentImg, err = daemon.imageStore.Get(image.ID(parent)) if err != nil { return "", errors.Wrap(err, "error getting specified parent layer") } @@ -283,11 +272,11 @@ func (daemon *Daemon) SquashImage(id, parent string) (string, error) { parentImg = &image.Image{RootFS: rootFS} } - l, err := daemon.stores[img.OperatingSystem()].layerStore.Get(img.RootFS.ChainID()) + l, err := daemon.layerStores[img.OperatingSystem()].Get(img.RootFS.ChainID()) if err != nil { return "", errors.Wrap(err, "error getting image layer") } - defer daemon.stores[img.OperatingSystem()].layerStore.Release(l) + defer daemon.layerStores[img.OperatingSystem()].Release(l) ts, err := l.TarStreamFrom(parentChainID) if err != nil { @@ -295,11 +284,11 @@ func (daemon *Daemon) SquashImage(id, parent string) (string, error) { } defer ts.Close() - newL, err := daemon.stores[img.OperatingSystem()].layerStore.Register(ts, parentChainID, layer.OS(img.OperatingSystem())) + newL, err := daemon.layerStores[img.OperatingSystem()].Register(ts, parentChainID) if err != nil { return "", errors.Wrap(err, "error registering layer") } - defer daemon.stores[img.OperatingSystem()].layerStore.Release(newL) + defer daemon.layerStores[img.OperatingSystem()].Release(newL) newImage := *img newImage.RootFS = nil @@ -334,7 +323,7 @@ func (daemon *Daemon) SquashImage(id, parent string) (string, error) { return "", errors.Wrap(err, "error marshalling image config") } - newImgID, err := daemon.stores[img.OperatingSystem()].imageStore.Create(b) + newImgID, err := daemon.imageStore.Create(b) if err != nil { return "", errors.Wrap(err, "error creating new image after squash") } diff --git a/vendor/github.com/docker/docker/daemon/import.go b/vendor/github.com/docker/docker/daemon/import.go index 3a25bb823..bd4a3fdfc 100644 --- a/vendor/github.com/docker/docker/daemon/import.go +++ b/vendor/github.com/docker/docker/daemon/import.go @@ -14,6 +14,7 @@ import ( "github.com/docker/docker/builder/dockerfile" "github.com/docker/docker/builder/remotecontext" "github.com/docker/docker/dockerversion" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/archive" @@ -42,21 +43,21 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string, var err error newRef, err = reference.ParseNormalizedNamed(repository) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } if _, isCanonical := newRef.(reference.Canonical); isCanonical { - return validationError{errors.New("cannot import digest reference")} + return errdefs.InvalidParameter(errors.New("cannot import digest reference")) } if tag != "" { newRef, err = reference.WithTag(newRef, tag) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } } } - config, err := dockerfile.BuildFromConfig(&container.Config{}, changes) + config, err := dockerfile.BuildFromConfig(&container.Config{}, changes, os) if err != nil { return err } @@ -69,7 +70,7 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string, } u, err := url.Parse(src) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } resp, err = remotecontext.GetWithStatusError(u.String()) @@ -90,11 +91,11 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string, if err != nil { return err } - l, err := daemon.stores[os].layerStore.Register(inflatedLayerData, "", layer.OS(os)) + l, err := daemon.layerStores[os].Register(inflatedLayerData, "") if err != nil { return err } - defer layer.ReleaseAndLog(daemon.stores[os].layerStore, l) + defer layer.ReleaseAndLog(daemon.layerStores[os], l) created := time.Now().UTC() imgConfig, err := json.Marshal(&image.Image{ @@ -119,14 +120,14 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string, return err } - id, err := daemon.stores[os].imageStore.Create(imgConfig) + id, err := daemon.imageStore.Create(imgConfig) if err != nil { return err } // FIXME: connect with commit code and call refstore directly if newRef != nil { - if err := daemon.TagImageWithReference(id, os, newRef); err != nil { + if err := daemon.TagImageWithReference(id, newRef); err != nil { return err } } diff --git a/vendor/github.com/docker/docker/daemon/info.go b/vendor/github.com/docker/docker/daemon/info.go index b14e7ba80..3a2883401 100644 --- a/vendor/github.com/docker/docker/daemon/info.go +++ b/vendor/github.com/docker/docker/daemon/info.go @@ -78,32 +78,26 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) { securityOptions = append(securityOptions, "name=userns") } - imageCount := 0 + var ds [][2]string drivers := "" - for p, ds := range daemon.stores { - imageCount += len(ds.imageStore.Map()) - drivers += daemon.GraphDriverName(p) - if len(daemon.stores) > 1 { - drivers += fmt.Sprintf(" (%s) ", p) + for os, gd := range daemon.graphDrivers { + ds = append(ds, daemon.layerStores[os].DriverStatus()...) + drivers += gd + if len(daemon.graphDrivers) > 1 { + drivers += fmt.Sprintf(" (%s) ", os) } } - - // TODO @jhowardmsft LCOW support. For now, hard-code the platform shown for the driver status - p := runtime.GOOS - if system.LCOWSupported() { - p = "linux" - } - drivers = strings.TrimSpace(drivers) + v := &types.Info{ ID: daemon.ID, Containers: cRunning + cPaused + cStopped, ContainersRunning: cRunning, ContainersPaused: cPaused, ContainersStopped: cStopped, - Images: imageCount, + Images: len(daemon.imageStore.Map()), Driver: drivers, - DriverStatus: daemon.stores[p].layerStore.DriverStatus(), + DriverStatus: ds, Plugins: daemon.showPluginsInfo(), IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled, BridgeNfIptables: !sysInfo.BridgeNFCallIPTablesDisabled, @@ -154,24 +148,46 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) { // SystemVersion returns version information about the daemon. func (daemon *Daemon) SystemVersion() types.Version { - v := types.Version{ - Version: dockerversion.Version, - GitCommit: dockerversion.GitCommit, - MinAPIVersion: api.MinVersion, - GoVersion: runtime.Version(), - Os: runtime.GOOS, - Arch: runtime.GOARCH, - BuildTime: dockerversion.BuildTime, - Experimental: daemon.configStore.Experimental, - } - kernelVersion := "" if kv, err := kernel.GetKernelVersion(); err != nil { logrus.Warnf("Could not get kernel version: %v", err) } else { kernelVersion = kv.String() } - v.KernelVersion = kernelVersion + + v := types.Version{ + Components: []types.ComponentVersion{ + { + Name: "Engine", + Version: dockerversion.Version, + Details: map[string]string{ + "GitCommit": dockerversion.GitCommit, + "ApiVersion": api.DefaultVersion, + "MinAPIVersion": api.MinVersion, + "GoVersion": runtime.Version(), + "Os": runtime.GOOS, + "Arch": runtime.GOARCH, + "BuildTime": dockerversion.BuildTime, + "KernelVersion": kernelVersion, + "Experimental": fmt.Sprintf("%t", daemon.configStore.Experimental), + }, + }, + }, + + // Populate deprecated fields for older clients + Version: dockerversion.Version, + GitCommit: dockerversion.GitCommit, + APIVersion: api.DefaultVersion, + MinAPIVersion: api.MinVersion, + GoVersion: runtime.Version(), + Os: runtime.GOOS, + Arch: runtime.GOARCH, + BuildTime: dockerversion.BuildTime, + KernelVersion: kernelVersion, + Experimental: daemon.configStore.Experimental, + } + + v.Platform.Name = dockerversion.PlatformName return v } diff --git a/vendor/github.com/docker/docker/daemon/initlayer/setup_windows.go b/vendor/github.com/docker/docker/daemon/initlayer/setup_windows.go index b47563ebf..ff78a4d0b 100644 --- a/vendor/github.com/docker/docker/daemon/initlayer/setup_windows.go +++ b/vendor/github.com/docker/docker/daemon/initlayer/setup_windows.go @@ -1,5 +1,3 @@ -// +build windows - package initlayer import ( diff --git a/vendor/github.com/docker/docker/daemon/inspect.go b/vendor/github.com/docker/docker/daemon/inspect.go index 20cfa6ce2..cab4f9279 100644 --- a/vendor/github.com/docker/docker/daemon/inspect.go +++ b/vendor/github.com/docker/docker/daemon/inspect.go @@ -11,6 +11,7 @@ import ( "github.com/docker/docker/api/types/versions/v1p20" "github.com/docker/docker/container" "github.com/docker/docker/daemon/network" + "github.com/docker/docker/errdefs" volumestore "github.com/docker/docker/volume/store" "github.com/docker/go-connections/nat" ) @@ -188,7 +189,7 @@ func (daemon *Daemon) getInspectData(container *container.Container) (*types.Con // could have been removed, it will cause error if we try to get the metadata, // we can ignore the error if the container is dead. if err != nil && !container.Dead { - return nil, systemError{err} + return nil, errdefs.System(err) } contJSONBase.GraphDriver.Data = graphDriverData @@ -232,7 +233,7 @@ func (daemon *Daemon) VolumeInspect(name string) (*types.Volume, error) { if volumestore.IsNotExist(err) { return nil, volumeNotFound(name) } - return nil, systemError{err} + return nil, errdefs.System(err) } apiV := volumeToAPIType(v) apiV.Mountpoint = v.Path() diff --git a/vendor/github.com/docker/docker/daemon/inspect_unix.go b/vendor/github.com/docker/docker/daemon/inspect_linux.go similarity index 99% rename from vendor/github.com/docker/docker/daemon/inspect_unix.go rename to vendor/github.com/docker/docker/daemon/inspect_linux.go index f073695e3..8d334dcf9 100644 --- a/vendor/github.com/docker/docker/daemon/inspect_unix.go +++ b/vendor/github.com/docker/docker/daemon/inspect_linux.go @@ -1,5 +1,3 @@ -// +build !windows - package daemon import ( diff --git a/vendor/github.com/docker/docker/daemon/inspect_solaris.go b/vendor/github.com/docker/docker/daemon/inspect_solaris.go deleted file mode 100644 index 0b275c141..000000000 --- a/vendor/github.com/docker/docker/daemon/inspect_solaris.go +++ /dev/null @@ -1,27 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/backend" - "github.com/docker/docker/api/types/versions/v1p19" - "github.com/docker/docker/container" - "github.com/docker/docker/daemon/exec" -) - -// This sets platform-specific fields -func setPlatformSpecificContainerFields(container *container.Container, contJSONBase *types.ContainerJSONBase) *types.ContainerJSONBase { - return contJSONBase -} - -// containerInspectPre120 get containers for pre 1.20 APIs. -func (daemon *Daemon) containerInspectPre120(name string) (*v1p19.ContainerJSON, error) { - return &v1p19.ContainerJSON{}, nil -} - -func inspectExecProcessConfig(e *exec.Config) *backend.ExecProcessConfig { - return &backend.ExecProcessConfig{ - Tty: e.Tty, - Entrypoint: e.Entrypoint, - Arguments: e.Args, - } -} diff --git a/vendor/github.com/docker/docker/daemon/kill.go b/vendor/github.com/docker/docker/daemon/kill.go index a230eaa76..ad6104bfe 100644 --- a/vendor/github.com/docker/docker/daemon/kill.go +++ b/vendor/github.com/docker/docker/daemon/kill.go @@ -4,11 +4,11 @@ import ( "context" "fmt" "runtime" - "strings" "syscall" "time" containerpkg "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/libcontainerd" "github.com/docker/docker/pkg/signal" "github.com/pkg/errors" @@ -64,6 +64,8 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int) container.Lock() defer container.Unlock() + daemon.stopHealthchecks(container) + if !container.Running { return errNotRunning(container.ID) } @@ -95,15 +97,11 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int) } if err := daemon.kill(container, sig); err != nil { - err = errors.Wrapf(err, "Cannot kill container %s", container.ID) - // if container or process not exists, ignore the error - // TODO: we shouldn't have to parse error strings from containerd - if strings.Contains(err.Error(), "container not found") || - strings.Contains(err.Error(), "no such process") { - logrus.Warnf("container kill failed because of 'container not found' or 'no such process': %s", err.Error()) + if errdefs.IsNotFound(err) { unpause = false + logrus.WithError(err).WithField("container", container.ID).WithField("action", "kill").Debug("container kill failed because of 'container not found' or 'no such process'") } else { - return err + return errors.Wrapf(err, "Cannot kill container %s", container.ID) } } @@ -169,7 +167,7 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error { // killPossibleDeadProcess is a wrapper around killSig() suppressing "no such process" error. func (daemon *Daemon) killPossiblyDeadProcess(container *containerpkg.Container, sig int) error { err := daemon.killWithSignal(container, sig) - if err == syscall.ESRCH { + if errdefs.IsNotFound(err) { e := errNoSuchProcess{container.GetPID(), sig} logrus.Debug(e) return e diff --git a/vendor/github.com/docker/docker/daemon/list.go b/vendor/github.com/docker/docker/daemon/list.go index c87dd6ec1..626de7767 100644 --- a/vendor/github.com/docker/docker/daemon/list.go +++ b/vendor/github.com/docker/docker/daemon/list.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/volume" "github.com/docker/go-connections/nat" @@ -290,7 +291,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis err = psFilters.WalkValues("health", func(value string) error { if !container.IsValidHealthString(value) { - return validationError{errors.Errorf("Unrecognised filter value for health: %s", value)} + return errdefs.InvalidParameter(errors.Errorf("Unrecognised filter value for health: %s", value)) } return nil @@ -322,7 +323,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis if psFilters.Contains("ancestor") { ancestorFilter = true psFilters.WalkValues("ancestor", func(ancestor string) error { - id, os, err := daemon.GetImageIDAndOS(ancestor) + id, _, err := daemon.GetImageIDAndOS(ancestor) if err != nil { logrus.Warnf("Error while looking up for image %v", ancestor) return nil @@ -332,7 +333,7 @@ func (daemon *Daemon) foldFilter(view container.View, config *types.ContainerLis return nil } // Then walk down the graph and put the imageIds in imagesFilter - populateImageFilterByParents(imagesFilter, id, daemon.stores[os].imageStore.Children) + populateImageFilterByParents(imagesFilter, id, daemon.imageStore.Children) return nil }) } diff --git a/vendor/github.com/docker/docker/daemon/listeners/listeners_unix.go b/vendor/github.com/docker/docker/daemon/listeners/listeners_linux.go similarity index 99% rename from vendor/github.com/docker/docker/daemon/listeners/listeners_unix.go rename to vendor/github.com/docker/docker/daemon/listeners/listeners_linux.go index 3a7c0f85b..7e0aaa237 100644 --- a/vendor/github.com/docker/docker/daemon/listeners/listeners_unix.go +++ b/vendor/github.com/docker/docker/daemon/listeners/listeners_linux.go @@ -1,5 +1,3 @@ -// +build !windows - package listeners import ( diff --git a/vendor/github.com/docker/docker/daemon/listeners/listeners_solaris.go b/vendor/github.com/docker/docker/daemon/listeners/listeners_solaris.go deleted file mode 100644 index ee1bd0fcc..000000000 --- a/vendor/github.com/docker/docker/daemon/listeners/listeners_solaris.go +++ /dev/null @@ -1,43 +0,0 @@ -package listeners - -import ( - "crypto/tls" - "fmt" - "net" - "os" - - "github.com/docker/go-connections/sockets" - "github.com/sirupsen/logrus" -) - -// Init creates new listeners for the server. -func Init(proto, addr, socketGroup string, tlsConfig *tls.Config) (ls []net.Listener, err error) { - switch proto { - case "tcp": - l, err := sockets.NewTCPSocket(addr, tlsConfig) - if err != nil { - return nil, err - } - ls = append(ls, l) - case "unix": - gid, err := lookupGID(socketGroup) - if err != nil { - if socketGroup != "" { - if socketGroup != defaultSocketGroup { - return nil, err - } - logrus.Warnf("could not change group %s to %s: %v", addr, defaultSocketGroup, err) - } - gid = os.Getgid() - } - l, err := sockets.NewUnixSocket(addr, gid) - if err != nil { - return nil, fmt.Errorf("can't create unix socket %s: %v", addr, err) - } - ls = append(ls, l) - default: - return nil, fmt.Errorf("Invalid protocol format: %q", proto) - } - - return -} diff --git a/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs.go b/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs.go index 4ea942071..25dd2152f 100644 --- a/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs.go +++ b/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs.go @@ -95,6 +95,17 @@ func init() { } } +// eventBatch holds the events that are batched for submission and the +// associated data about it. +// +// Warning: this type is not threadsafe and must not be used +// concurrently. This type is expected to be consumed in a single go +// routine and never concurrently. +type eventBatch struct { + batch []wrappedEvent + bytes int +} + // New creates an awslogs logger using the configuration passed in on the // context. Supported context configuration variables are awslogs-region, // awslogs-group, awslogs-stream, awslogs-create-group, awslogs-multiline-pattern @@ -389,32 +400,32 @@ var newTicker = func(freq time.Duration) *time.Ticker { // Logs, the processEvents method is called. If a multiline pattern is not // configured, log events are submitted to the processEvents method immediately. func (l *logStream) collectBatch() { - timer := newTicker(batchPublishFrequency) - var events []wrappedEvent + ticker := newTicker(batchPublishFrequency) var eventBuffer []byte var eventBufferTimestamp int64 + var batch = newEventBatch() for { select { - case t := <-timer.C: + case t := <-ticker.C: // If event buffer is older than batch publish frequency flush the event buffer if eventBufferTimestamp > 0 && len(eventBuffer) > 0 { eventBufferAge := t.UnixNano()/int64(time.Millisecond) - eventBufferTimestamp eventBufferExpired := eventBufferAge > int64(batchPublishFrequency)/int64(time.Millisecond) eventBufferNegative := eventBufferAge < 0 if eventBufferExpired || eventBufferNegative { - events = l.processEvent(events, eventBuffer, eventBufferTimestamp) + l.processEvent(batch, eventBuffer, eventBufferTimestamp) eventBuffer = eventBuffer[:0] } } - l.publishBatch(events) - events = events[:0] + l.publishBatch(batch) + batch.reset() case msg, more := <-l.messages: if !more { // Flush event buffer and release resources - events = l.processEvent(events, eventBuffer, eventBufferTimestamp) + l.processEvent(batch, eventBuffer, eventBufferTimestamp) eventBuffer = eventBuffer[:0] - l.publishBatch(events) - events = events[:0] + l.publishBatch(batch) + batch.reset() return } if eventBufferTimestamp == 0 { @@ -425,7 +436,7 @@ func (l *logStream) collectBatch() { if l.multilinePattern.Match(unprocessedLine) || len(eventBuffer)+len(unprocessedLine) > maximumBytesPerEvent { // This is a new log event or we will exceed max bytes per event // so flush the current eventBuffer to events and reset timestamp - events = l.processEvent(events, eventBuffer, eventBufferTimestamp) + l.processEvent(batch, eventBuffer, eventBufferTimestamp) eventBufferTimestamp = msg.Timestamp.UnixNano() / int64(time.Millisecond) eventBuffer = eventBuffer[:0] } @@ -434,7 +445,7 @@ func (l *logStream) collectBatch() { eventBuffer = append(eventBuffer, processedLine...) logger.PutMessage(msg) } else { - events = l.processEvent(events, unprocessedLine, msg.Timestamp.UnixNano()/int64(time.Millisecond)) + l.processEvent(batch, unprocessedLine, msg.Timestamp.UnixNano()/int64(time.Millisecond)) logger.PutMessage(msg) } } @@ -450,8 +461,7 @@ func (l *logStream) collectBatch() { // bytes per event (defined in maximumBytesPerEvent). There is a fixed per-event // byte overhead (defined in perEventBytes) which is accounted for in split- and // batch-calculations. -func (l *logStream) processEvent(events []wrappedEvent, unprocessedLine []byte, timestamp int64) []wrappedEvent { - bytes := 0 +func (l *logStream) processEvent(batch *eventBatch, unprocessedLine []byte, timestamp int64) { for len(unprocessedLine) > 0 { // Split line length so it does not exceed the maximum lineBytes := len(unprocessedLine) @@ -459,38 +469,33 @@ func (l *logStream) processEvent(events []wrappedEvent, unprocessedLine []byte, lineBytes = maximumBytesPerEvent } line := unprocessedLine[:lineBytes] - unprocessedLine = unprocessedLine[lineBytes:] - if (len(events) >= maximumLogEventsPerPut) || (bytes+lineBytes+perEventBytes > maximumBytesPerPut) { - // Publish an existing batch if it's already over the maximum number of events or if adding this - // event would push it over the maximum number of total bytes. - l.publishBatch(events) - events = events[:0] - bytes = 0 - } - events = append(events, wrappedEvent{ + + event := wrappedEvent{ inputLogEvent: &cloudwatchlogs.InputLogEvent{ Message: aws.String(string(line)), Timestamp: aws.Int64(timestamp), }, - insertOrder: len(events), - }) - bytes += (lineBytes + perEventBytes) + insertOrder: batch.count(), + } + + added := batch.add(event, lineBytes) + if added { + unprocessedLine = unprocessedLine[lineBytes:] + } else { + l.publishBatch(batch) + batch.reset() + } } - return events } // publishBatch calls PutLogEvents for a given set of InputLogEvents, // accounting for sequencing requirements (each request must reference the // sequence token returned by the previous request). -func (l *logStream) publishBatch(events []wrappedEvent) { - if len(events) == 0 { +func (l *logStream) publishBatch(batch *eventBatch) { + if batch.isEmpty() { return } - - // events in a batch must be sorted by timestamp - // see http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutLogEvents.html - sort.Sort(byTimestamp(events)) - cwEvents := unwrapEvents(events) + cwEvents := unwrapEvents(batch.events()) nextSequenceToken, err := l.putLogEvents(cwEvents, l.sequenceToken) @@ -615,3 +620,70 @@ func unwrapEvents(events []wrappedEvent) []*cloudwatchlogs.InputLogEvent { } return cwEvents } + +func newEventBatch() *eventBatch { + return &eventBatch{ + batch: make([]wrappedEvent, 0), + bytes: 0, + } +} + +// events returns a slice of wrappedEvents sorted in order of their +// timestamps and then by their insertion order (see `byTimestamp`). +// +// Warning: this method is not threadsafe and must not be used +// concurrently. +func (b *eventBatch) events() []wrappedEvent { + sort.Sort(byTimestamp(b.batch)) + return b.batch +} + +// add adds an event to the batch of events accounting for the +// necessary overhead for an event to be logged. An error will be +// returned if the event cannot be added to the batch due to service +// limits. +// +// Warning: this method is not threadsafe and must not be used +// concurrently. +func (b *eventBatch) add(event wrappedEvent, size int) bool { + addBytes := size + perEventBytes + + // verify we are still within service limits + switch { + case len(b.batch)+1 > maximumLogEventsPerPut: + return false + case b.bytes+addBytes > maximumBytesPerPut: + return false + } + + b.bytes += addBytes + b.batch = append(b.batch, event) + + return true +} + +// count is the number of batched events. Warning: this method +// is not threadsafe and must not be used concurrently. +func (b *eventBatch) count() int { + return len(b.batch) +} + +// size is the total number of bytes that the batch represents. +// +// Warning: this method is not threadsafe and must not be used +// concurrently. +func (b *eventBatch) size() int { + return b.bytes +} + +func (b *eventBatch) isEmpty() bool { + zeroEvents := b.count() == 0 + zeroSize := b.size() == 0 + return zeroEvents && zeroSize +} + +// reset prepares the batch for reuse. +func (b *eventBatch) reset() { + b.bytes = 0 + b.batch = b.batch[:0] +} diff --git a/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs_test.go b/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs_test.go index 7ebc5dede..67ea47476 100644 --- a/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs_test.go +++ b/vendor/github.com/docker/docker/daemon/logger/awslogs/cloudwatchlogs_test.go @@ -49,6 +49,15 @@ func (l *logStream) logGenerator(lineCount int, multilineCount int) { } } +func testEventBatch(events []wrappedEvent) *eventBatch { + batch := newEventBatch() + for _, event := range events { + eventlen := len([]byte(*event.inputLogEvent.Message)) + batch.add(event, eventlen) + } + return batch +} + func TestNewAWSLogsClientUserAgentHandler(t *testing.T) { info := logger.Info{ Config: map[string]string{ @@ -212,7 +221,7 @@ func TestPublishBatchSuccess(t *testing.T) { }, } - stream.publishBatch(events) + stream.publishBatch(testEventBatch(events)) if stream.sequenceToken == nil { t.Fatal("Expected non-nil sequenceToken") } @@ -257,7 +266,7 @@ func TestPublishBatchError(t *testing.T) { }, } - stream.publishBatch(events) + stream.publishBatch(testEventBatch(events)) if stream.sequenceToken == nil { t.Fatal("Expected non-nil sequenceToken") } @@ -291,7 +300,7 @@ func TestPublishBatchInvalidSeqSuccess(t *testing.T) { }, } - stream.publishBatch(events) + stream.publishBatch(testEventBatch(events)) if stream.sequenceToken == nil { t.Fatal("Expected non-nil sequenceToken") } @@ -354,7 +363,7 @@ func TestPublishBatchAlreadyAccepted(t *testing.T) { }, } - stream.publishBatch(events) + stream.publishBatch(testEventBatch(events)) if stream.sequenceToken == nil { t.Fatal("Expected non-nil sequenceToken") } @@ -859,7 +868,8 @@ func TestCollectBatchMaxEvents(t *testing.T) { } func TestCollectBatchMaxTotalBytes(t *testing.T) { - mockClient := newMockClientBuffered(1) + expectedPuts := 2 + mockClient := newMockClientBuffered(expectedPuts) stream := &logStream{ client: mockClient, logGroupName: groupName, @@ -867,11 +877,14 @@ func TestCollectBatchMaxTotalBytes(t *testing.T) { sequenceToken: aws.String(sequenceToken), messages: make(chan *logger.Message), } - mockClient.putLogEventsResult <- &putLogEventsResult{ - successResult: &cloudwatchlogs.PutLogEventsOutput{ - NextSequenceToken: aws.String(nextSequenceToken), - }, + for i := 0; i < expectedPuts; i++ { + mockClient.putLogEventsResult <- &putLogEventsResult{ + successResult: &cloudwatchlogs.PutLogEventsOutput{ + NextSequenceToken: aws.String(nextSequenceToken), + }, + } } + var ticks = make(chan time.Time) newTicker = func(_ time.Duration) *time.Ticker { return &time.Ticker{ @@ -881,32 +894,57 @@ func TestCollectBatchMaxTotalBytes(t *testing.T) { go stream.collectBatch() - longline := strings.Repeat("A", maximumBytesPerPut) + numPayloads := maximumBytesPerPut / (maximumBytesPerEvent + perEventBytes) + // maxline is the maximum line that could be submitted after + // accounting for its overhead. + maxline := strings.Repeat("A", maximumBytesPerPut-(perEventBytes*numPayloads)) + // This will be split and batched up to the `maximumBytesPerPut' + // (+/- `maximumBytesPerEvent'). This /should/ be aligned, but + // should also tolerate an offset within that range. stream.Log(&logger.Message{ - Line: []byte(longline + "B"), + Line: []byte(maxline[:len(maxline)/2]), + Timestamp: time.Time{}, + }) + stream.Log(&logger.Message{ + Line: []byte(maxline[len(maxline)/2:]), + Timestamp: time.Time{}, + }) + stream.Log(&logger.Message{ + Line: []byte("B"), Timestamp: time.Time{}, }) - // no ticks + // no ticks, guarantee batch by size (and chan close) stream.Close() argument := <-mockClient.putLogEventsArgument if argument == nil { t.Fatal("Expected non-nil PutLogEventsInput") } - bytes := 0 + + // Should total to the maximum allowed bytes. + eventBytes := 0 for _, event := range argument.LogEvents { - bytes += len(*event.Message) + eventBytes += len(*event.Message) } - if bytes > maximumBytesPerPut { - t.Errorf("Expected <= %d bytes but was %d", maximumBytesPerPut, bytes) + eventsOverhead := len(argument.LogEvents) * perEventBytes + payloadTotal := eventBytes + eventsOverhead + // lowestMaxBatch allows the payload to be offset if the messages + // don't lend themselves to align with the maximum event size. + lowestMaxBatch := maximumBytesPerPut - maximumBytesPerEvent + + if payloadTotal > maximumBytesPerPut { + t.Errorf("Expected <= %d bytes but was %d", maximumBytesPerPut, payloadTotal) + } + if payloadTotal < lowestMaxBatch { + t.Errorf("Batch to be no less than %d but was %d", lowestMaxBatch, payloadTotal) } argument = <-mockClient.putLogEventsArgument if len(argument.LogEvents) != 1 { t.Errorf("Expected LogEvents to contain 1 elements, but contains %d", len(argument.LogEvents)) } - message := *argument.LogEvents[0].Message + message := *argument.LogEvents[len(argument.LogEvents)-1].Message if message[len(message)-1:] != "B" { t.Errorf("Expected message to be %s but was %s", "B", message[len(message)-1:]) } diff --git a/vendor/github.com/docker/docker/daemon/logger/awslogs/cwlogsiface_mock_test.go b/vendor/github.com/docker/docker/daemon/logger/awslogs/cwlogsiface_mock_test.go index 82bb34b0a..d0a2ebaca 100644 --- a/vendor/github.com/docker/docker/daemon/logger/awslogs/cwlogsiface_mock_test.go +++ b/vendor/github.com/docker/docker/daemon/logger/awslogs/cwlogsiface_mock_test.go @@ -1,6 +1,10 @@ package awslogs -import "github.com/aws/aws-sdk-go/service/cloudwatchlogs" +import ( + "fmt" + + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" +) type mockcwlogsclient struct { createLogGroupArgument chan *cloudwatchlogs.CreateLogGroupInput @@ -67,7 +71,30 @@ func (m *mockcwlogsclient) PutLogEvents(input *cloudwatchlogs.PutLogEventsInput) LogGroupName: input.LogGroupName, LogStreamName: input.LogStreamName, } + + // Intended mock output output := <-m.putLogEventsResult + + // Checked enforced limits in mock + totalBytes := 0 + for _, evt := range events { + if evt.Message == nil { + continue + } + eventBytes := len([]byte(*evt.Message)) + if eventBytes > maximumBytesPerEvent { + // exceeded per event message size limits + return nil, fmt.Errorf("maximum bytes per event exceeded: Event too large %d, max allowed: %d", eventBytes, maximumBytesPerEvent) + } + // total event bytes including overhead + totalBytes += eventBytes + perEventBytes + } + + if totalBytes > maximumBytesPerPut { + // exceeded per put maximum size limit + return nil, fmt.Errorf("maximum bytes per put exceeded: Upload too large %d, max allowed: %d", totalBytes, maximumBytesPerPut) + } + return output.successResult, output.errorResult } diff --git a/vendor/github.com/docker/docker/daemon/logger/fluentd/fluentd.go b/vendor/github.com/docker/docker/daemon/logger/fluentd/fluentd.go index 6a0653ef2..cde36d434 100644 --- a/vendor/github.com/docker/docker/daemon/logger/fluentd/fluentd.go +++ b/vendor/github.com/docker/docker/daemon/logger/fluentd/fluentd.go @@ -48,11 +48,12 @@ const ( defaultRetryWait = 1000 defaultMaxRetries = math.MaxInt32 - addressKey = "fluentd-address" - bufferLimitKey = "fluentd-buffer-limit" - retryWaitKey = "fluentd-retry-wait" - maxRetriesKey = "fluentd-max-retries" - asyncConnectKey = "fluentd-async-connect" + addressKey = "fluentd-address" + bufferLimitKey = "fluentd-buffer-limit" + retryWaitKey = "fluentd-retry-wait" + maxRetriesKey = "fluentd-max-retries" + asyncConnectKey = "fluentd-async-connect" + subSecondPrecisionKey = "fluentd-sub-second-precision" ) func init() { @@ -117,15 +118,23 @@ func New(info logger.Info) (logger.Logger, error) { } } + subSecondPrecision := false + if info.Config[subSecondPrecisionKey] != "" { + if subSecondPrecision, err = strconv.ParseBool(info.Config[subSecondPrecisionKey]); err != nil { + return nil, err + } + } + fluentConfig := fluent.Config{ - FluentPort: loc.port, - FluentHost: loc.host, - FluentNetwork: loc.protocol, - FluentSocketPath: loc.path, - BufferLimit: bufferLimit, - RetryWait: retryWait, - MaxRetry: maxRetries, - AsyncConnect: asyncConnect, + FluentPort: loc.port, + FluentHost: loc.host, + FluentNetwork: loc.protocol, + FluentSocketPath: loc.path, + BufferLimit: bufferLimit, + RetryWait: retryWait, + MaxRetry: maxRetries, + AsyncConnect: asyncConnect, + SubSecondPrecision: subSecondPrecision, } logrus.WithField("container", info.ContainerID).WithField("config", fluentConfig). @@ -183,6 +192,7 @@ func ValidateLogOpt(cfg map[string]string) error { case retryWaitKey: case maxRetriesKey: case asyncConnectKey: + case subSecondPrecisionKey: // Accepted default: return fmt.Errorf("unknown log opt '%s' for fluentd log driver", key) diff --git a/vendor/github.com/docker/docker/daemon/logger/gcplogs/gcplogging_linux.go b/vendor/github.com/docker/docker/daemon/logger/gcplogs/gcplogging_linux.go index 8917bdd4c..41a09362f 100644 --- a/vendor/github.com/docker/docker/daemon/logger/gcplogs/gcplogging_linux.go +++ b/vendor/github.com/docker/docker/daemon/logger/gcplogs/gcplogging_linux.go @@ -1,5 +1,3 @@ -// +build linux - package gcplogs import ( diff --git a/vendor/github.com/docker/docker/daemon/logger/journald/journald.go b/vendor/github.com/docker/docker/daemon/logger/journald/journald.go index 46aac8328..ee6e5b68f 100644 --- a/vendor/github.com/docker/docker/daemon/logger/journald/journald.go +++ b/vendor/github.com/docker/docker/daemon/logger/journald/journald.go @@ -75,6 +75,7 @@ func New(info logger.Info) (logger.Logger, error) { "CONTAINER_ID_FULL": info.ContainerID, "CONTAINER_NAME": info.Name(), "CONTAINER_TAG": tag, + "SYSLOG_IDENTIFIER": tag, } extraAttrs, err := info.ExtraAttributes(sanitizeKeyMod) if err != nil { diff --git a/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog.go b/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog.go index 7aa92f3d3..720a7c3b6 100644 --- a/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog.go +++ b/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog.go @@ -27,6 +27,7 @@ type JSONFileLogger struct { closed bool writer *loggerutils.LogFile readers map[*logger.LogWatcher]struct{} // stores the active log followers + tag string // tag values requested by the user to log } func init() { @@ -61,11 +62,21 @@ func New(info logger.Info) (logger.Logger, error) { } } - var extra []byte attrs, err := info.ExtraAttributes(nil) if err != nil { return nil, err } + + // no default template. only use a tag if the user asked for it + tag, err := loggerutils.ParseLogTag(info, "") + if err != nil { + return nil, err + } + if tag != "" { + attrs["tag"] = tag + } + + var extra []byte if len(attrs) > 0 { var err error extra, err = json.Marshal(attrs) @@ -92,6 +103,7 @@ func New(info logger.Info) (logger.Logger, error) { return &JSONFileLogger{ writer: writer, readers: make(map[*logger.LogWatcher]struct{}), + tag: tag, }, nil } @@ -130,6 +142,7 @@ func ValidateLogOpt(cfg map[string]string) error { case "labels": case "env": case "env-regex": + case "tag": default: return fmt.Errorf("unknown log opt '%s' for json-file log driver", key) } diff --git a/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog_test.go b/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog_test.go index 893c05466..e988e862f 100644 --- a/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog_test.go +++ b/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonfilelog_test.go @@ -14,6 +14,7 @@ import ( "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog" "github.com/gotestyourself/gotestyourself/fs" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -57,6 +58,46 @@ func TestJSONFileLogger(t *testing.T) { } } +func TestJSONFileLoggerWithTags(t *testing.T) { + cid := "a7317399f3f857173c6179d44823594f8294678dea9999662e5c625b5a1c7657" + cname := "test-container" + tmp, err := ioutil.TempDir("", "docker-logger-") + + require.NoError(t, err) + + defer os.RemoveAll(tmp) + filename := filepath.Join(tmp, "container.log") + l, err := New(logger.Info{ + Config: map[string]string{ + "tag": "{{.ID}}/{{.Name}}", // first 12 characters of ContainerID and full ContainerName + }, + ContainerID: cid, + ContainerName: cname, + LogPath: filename, + }) + + require.NoError(t, err) + defer l.Close() + + err = l.Log(&logger.Message{Line: []byte("line1"), Source: "src1"}) + require.NoError(t, err) + + err = l.Log(&logger.Message{Line: []byte("line2"), Source: "src2"}) + require.NoError(t, err) + + err = l.Log(&logger.Message{Line: []byte("line3"), Source: "src3"}) + require.NoError(t, err) + + res, err := ioutil.ReadFile(filename) + require.NoError(t, err) + + expected := `{"log":"line1\n","stream":"src1","attrs":{"tag":"a7317399f3f8/test-container"},"time":"0001-01-01T00:00:00Z"} +{"log":"line2\n","stream":"src2","attrs":{"tag":"a7317399f3f8/test-container"},"time":"0001-01-01T00:00:00Z"} +{"log":"line3\n","stream":"src3","attrs":{"tag":"a7317399f3f8/test-container"},"time":"0001-01-01T00:00:00Z"} +` + assert.Equal(t, expected, string(res)) +} + func BenchmarkJSONFileLoggerLog(b *testing.B) { tmp := fs.NewDir(b, "bench-jsonfilelog") defer tmp.Remove() diff --git a/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog/jsonlogbytes_test.go b/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog/jsonlogbytes_test.go index 4645cd4fa..e52d32c03 100644 --- a/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog/jsonlogbytes_test.go +++ b/vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog/jsonlogbytes_test.go @@ -29,6 +29,8 @@ func TestJSONLogsMarshalJSONBuf(t *testing.T) { {Log: []byte{0x7F}}: `^{\"log\":\"\x7f\",\"time\":`, // with raw attributes {Log: []byte("A log line"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":`, + // with Tag set + {Log: []byte("A log line with tag"), RawAttrs: []byte(`{"hello":"world","value":1234}`)}: `^{\"log\":\"A log line with tag\",\"attrs\":{\"hello\":\"world\",\"value\":1234},\"time\":`, } for jsonLog, expression := range logs { var buf bytes.Buffer diff --git a/vendor/github.com/docker/docker/daemon/logger/logentries/logentries.go b/vendor/github.com/docker/docker/daemon/logger/logentries/logentries.go index e28707c74..255e87d4b 100644 --- a/vendor/github.com/docker/docker/daemon/logger/logentries/logentries.go +++ b/vendor/github.com/docker/docker/daemon/logger/logentries/logentries.go @@ -50,8 +50,10 @@ func New(info logger.Info) (logger.Logger, error) { return nil, errors.Wrap(err, "error connecting to logentries") } var lineOnly bool - if lineOnly, err = strconv.ParseBool(info.Config[lineonly]); err != nil { - return nil, errors.Wrap(err, "error parsing lineonly option") + if info.Config[lineonly] != "" { + if lineOnly, err = strconv.ParseBool(info.Config[lineonly]); err != nil { + return nil, errors.Wrap(err, "error parsing lineonly option") + } } return &logentries{ containerID: info.ContainerID, @@ -76,7 +78,7 @@ func (f *logentries) Log(msg *logger.Message) error { logger.PutMessage(msg) f.writer.Println(f.tag, ts, data) } else { - line := msg.Line + line := string(msg.Line) logger.PutMessage(msg) f.writer.Println(line) } diff --git a/vendor/github.com/docker/docker/daemon/logger/splunk/splunk.go b/vendor/github.com/docker/docker/daemon/logger/splunk/splunk.go index 31a048700..30ab7b741 100644 --- a/vendor/github.com/docker/docker/daemon/logger/splunk/splunk.go +++ b/vendor/github.com/docker/docker/daemon/logger/splunk/splunk.go @@ -5,6 +5,7 @@ package splunk import ( "bytes" "compress/gzip" + "context" "crypto/tls" "crypto/x509" "encoding/json" @@ -21,6 +22,7 @@ import ( "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger/loggerutils" + "github.com/docker/docker/pkg/pools" "github.com/docker/docker/pkg/urlutil" "github.com/sirupsen/logrus" ) @@ -54,6 +56,8 @@ const ( defaultBufferMaximum = 10 * defaultPostMessagesBatchSize // Number of messages allowed to be queued in the channel defaultStreamChannelSize = 4 * defaultPostMessagesBatchSize + // maxResponseSize is the max amount that will be read from an http response + maxResponseSize = 1024 ) const ( @@ -63,6 +67,8 @@ const ( envVarStreamChannelSize = "SPLUNK_LOGGING_DRIVER_CHANNEL_SIZE" ) +var batchSendTimeout = 30 * time.Second + type splunkLoggerInterface interface { logger.Logger worker() @@ -416,13 +422,18 @@ func (l *splunkLogger) worker() { func (l *splunkLogger) postMessages(messages []*splunkMessage, lastChance bool) []*splunkMessage { messagesLen := len(messages) + + ctx, cancel := context.WithTimeout(context.Background(), batchSendTimeout) + defer cancel() + for i := 0; i < messagesLen; i += l.postMessagesBatchSize { upperBound := i + l.postMessagesBatchSize if upperBound > messagesLen { upperBound = messagesLen } - if err := l.tryPostMessages(messages[i:upperBound]); err != nil { - logrus.Error(err) + + if err := l.tryPostMessages(ctx, messages[i:upperBound]); err != nil { + logrus.WithError(err).WithField("module", "logger/splunk").Warn("Error while sending logs") if messagesLen-i >= l.bufferMaximum || lastChance { // If this is last chance - print them all to the daemon log if lastChance { @@ -447,7 +458,7 @@ func (l *splunkLogger) postMessages(messages []*splunkMessage, lastChance bool) return messages[:0] } -func (l *splunkLogger) tryPostMessages(messages []*splunkMessage) error { +func (l *splunkLogger) tryPostMessages(ctx context.Context, messages []*splunkMessage) error { if len(messages) == 0 { return nil } @@ -486,25 +497,28 @@ func (l *splunkLogger) tryPostMessages(messages []*splunkMessage) error { if err != nil { return err } + req = req.WithContext(ctx) req.Header.Set("Authorization", l.auth) // Tell if we are sending gzip compressed body if l.gzipCompression { req.Header.Set("Content-Encoding", "gzip") } - res, err := l.client.Do(req) + resp, err := l.client.Do(req) if err != nil { return err } - defer res.Body.Close() - if res.StatusCode != http.StatusOK { - var body []byte - body, err = ioutil.ReadAll(res.Body) + defer func() { + pools.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() + if resp.StatusCode != http.StatusOK { + rdr := io.LimitReader(resp.Body, maxResponseSize) + body, err := ioutil.ReadAll(rdr) if err != nil { return err } - return fmt.Errorf("%s: failed to send event - %s - %s", driverName, res.Status, body) + return fmt.Errorf("%s: failed to send event - %s - %s", driverName, resp.Status, string(body)) } - io.Copy(ioutil.Discard, res.Body) return nil } @@ -587,20 +601,22 @@ func verifySplunkConnection(l *splunkLogger) error { if err != nil { return err } - res, err := l.client.Do(req) + resp, err := l.client.Do(req) if err != nil { return err } - if res.Body != nil { - defer res.Body.Close() - } - if res.StatusCode != http.StatusOK { - var body []byte - body, err = ioutil.ReadAll(res.Body) + defer func() { + pools.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + }() + + if resp.StatusCode != http.StatusOK { + rdr := io.LimitReader(resp.Body, maxResponseSize) + body, err := ioutil.ReadAll(rdr) if err != nil { return err } - return fmt.Errorf("%s: failed to verify connection - %s - %s", driverName, res.Status, body) + return fmt.Errorf("%s: failed to verify connection - %s - %s", driverName, resp.Status, string(body)) } return nil } diff --git a/vendor/github.com/docker/docker/daemon/logger/splunk/splunk_test.go b/vendor/github.com/docker/docker/daemon/logger/splunk/splunk_test.go index ebf835c58..97613771d 100644 --- a/vendor/github.com/docker/docker/daemon/logger/splunk/splunk_test.go +++ b/vendor/github.com/docker/docker/daemon/logger/splunk/splunk_test.go @@ -2,8 +2,10 @@ package splunk import ( "compress/gzip" + "context" "fmt" "os" + "runtime" "testing" "time" @@ -1062,7 +1064,7 @@ func TestSkipVerify(t *testing.T) { t.Fatal("No messages should be accepted at this point") } - hec.simulateServerError = false + hec.simulateErr(false) for i := defaultStreamChannelSize * 2; i < defaultStreamChannelSize*4; i++ { if err := loggerDriver.Log(&logger.Message{Line: []byte(fmt.Sprintf("%d", i)), Source: "stdout", Timestamp: time.Now()}); err != nil { @@ -1110,7 +1112,7 @@ func TestBufferMaximum(t *testing.T) { } hec := NewHTTPEventCollectorMock(t) - hec.simulateServerError = true + hec.simulateErr(true) go hec.Serve() info := logger.Info{ @@ -1308,3 +1310,48 @@ func TestCannotSendAfterClose(t *testing.T) { t.Fatal(err) } } + +func TestDeadlockOnBlockedEndpoint(t *testing.T) { + hec := NewHTTPEventCollectorMock(t) + go hec.Serve() + info := logger.Info{ + Config: map[string]string{ + splunkURLKey: hec.URL(), + splunkTokenKey: hec.token, + }, + ContainerID: "containeriid", + ContainerName: "/container_name", + ContainerImageID: "contaimageid", + ContainerImageName: "container_image_name", + } + + l, err := New(info) + if err != nil { + t.Fatal(err) + } + + ctx, unblock := context.WithCancel(context.Background()) + hec.withBlock(ctx) + defer unblock() + + batchSendTimeout = 1 * time.Second + + if err := l.Log(&logger.Message{}); err != nil { + t.Fatal(err) + } + + done := make(chan struct{}) + go func() { + l.Close() + close(done) + }() + + select { + case <-time.After(60 * time.Second): + buf := make([]byte, 1e6) + buf = buf[:runtime.Stack(buf, true)] + t.Logf("STACK DUMP: \n\n%s\n\n", string(buf)) + t.Fatal("timeout waiting for close to finish") + case <-done: + } +} diff --git a/vendor/github.com/docker/docker/daemon/logger/splunk/splunkhecmock_test.go b/vendor/github.com/docker/docker/daemon/logger/splunk/splunkhecmock_test.go index e50894828..0135ac7eb 100644 --- a/vendor/github.com/docker/docker/daemon/logger/splunk/splunkhecmock_test.go +++ b/vendor/github.com/docker/docker/daemon/logger/splunk/splunkhecmock_test.go @@ -2,12 +2,14 @@ package splunk import ( "compress/gzip" + "context" "encoding/json" "fmt" "io" "io/ioutil" "net" "net/http" + "sync" "testing" ) @@ -29,8 +31,10 @@ type HTTPEventCollectorMock struct { tcpAddr *net.TCPAddr tcpListener *net.TCPListener + mu sync.Mutex token string simulateServerError bool + blockingCtx context.Context test *testing.T @@ -55,6 +59,18 @@ func NewHTTPEventCollectorMock(t *testing.T) *HTTPEventCollectorMock { connectionVerified: false} } +func (hec *HTTPEventCollectorMock) simulateErr(b bool) { + hec.mu.Lock() + hec.simulateServerError = b + hec.mu.Unlock() +} + +func (hec *HTTPEventCollectorMock) withBlock(ctx context.Context) { + hec.mu.Lock() + hec.blockingCtx = ctx + hec.mu.Unlock() +} + func (hec *HTTPEventCollectorMock) URL() string { return "http://" + hec.tcpListener.Addr().String() } @@ -72,7 +88,16 @@ func (hec *HTTPEventCollectorMock) ServeHTTP(writer http.ResponseWriter, request hec.numOfRequests++ - if hec.simulateServerError { + hec.mu.Lock() + simErr := hec.simulateServerError + ctx := hec.blockingCtx + hec.mu.Unlock() + + if ctx != nil { + <-hec.blockingCtx.Done() + } + + if simErr { if request.Body != nil { defer request.Body.Close() } diff --git a/vendor/github.com/docker/docker/daemon/logs.go b/vendor/github.com/docker/docker/daemon/logs.go index 131360b7b..c819768dc 100644 --- a/vendor/github.com/docker/docker/daemon/logs.go +++ b/vendor/github.com/docker/docker/daemon/logs.go @@ -13,6 +13,7 @@ import ( timetypes "github.com/docker/docker/api/types/time" "github.com/docker/docker/container" "github.com/docker/docker/daemon/logger" + "github.com/docker/docker/errdefs" "github.com/sirupsen/logrus" ) @@ -30,7 +31,7 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c }) if !(config.ShowStdout || config.ShowStderr) { - return nil, false, validationError{errors.New("You must choose at least one stream")} + return nil, false, errdefs.InvalidParameter(errors.New("You must choose at least one stream")) } container, err := daemon.GetContainer(containerName) if err != nil { @@ -38,7 +39,7 @@ func (daemon *Daemon) ContainerLogs(ctx context.Context, containerName string, c } if container.RemovalInProgress || container.Dead { - return nil, false, stateConflictError{errors.New("can not get logs from container which is dead or marked for removal")} + return nil, false, errdefs.Conflict(errors.New("can not get logs from container which is dead or marked for removal")) } if container.HostConfig.LogConfig.Type == "none" { diff --git a/vendor/github.com/docker/docker/daemon/metrics.go b/vendor/github.com/docker/docker/daemon/metrics.go index 44228e7db..92439ad14 100644 --- a/vendor/github.com/docker/docker/daemon/metrics.go +++ b/vendor/github.com/docker/docker/daemon/metrics.go @@ -118,7 +118,8 @@ func (d *Daemon) cleanupMetricsPlugins() { var wg sync.WaitGroup wg.Add(len(ls)) - for _, p := range ls { + for _, plugin := range ls { + p := plugin go func() { defer wg.Done() pluginStopMetricsCollection(p) diff --git a/vendor/github.com/docker/docker/daemon/monitor.go b/vendor/github.com/docker/docker/daemon/monitor.go index c0a265dac..6f6928a4d 100644 --- a/vendor/github.com/docker/docker/daemon/monitor.go +++ b/vendor/github.com/docker/docker/daemon/monitor.go @@ -39,19 +39,23 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc if runtime.GOOS == "windows" { return errors.New("received StateOOM from libcontainerd on Windows. This should never happen") } + + c.Lock() + defer c.Unlock() daemon.updateHealthMonitor(c) if err := c.CheckpointTo(daemon.containersReplica); err != nil { return err } + daemon.LogContainerEvent(c, "oom") case libcontainerd.EventExit: if int(ei.Pid) == c.Pid { + c.Lock() _, _, err := daemon.containerd.DeleteTask(context.Background(), c.ID) if err != nil { logrus.WithError(err).Warnf("failed to delete container %s from containerd", c.ID) } - c.Lock() c.StreamConfig.Wait() c.Reset(false) @@ -68,6 +72,7 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc c.SetStopped(&exitStatus) defer daemon.autoRemove(c) } + defer c.Unlock() // needs to be called before autoRemove // cancel healthcheck here, they will be automatically // restarted if/when the container is started again @@ -91,7 +96,9 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc } } if err != nil { + c.Lock() c.SetStopped(&exitStatus) + c.Unlock() defer daemon.autoRemove(c) if err != restartmanager.ErrRestartCanceled { logrus.Errorf("restartmanger wait error: %+v", err) @@ -101,14 +108,13 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc } daemon.setStateCounter(c) - defer c.Unlock() if err := c.CheckpointTo(daemon.containersReplica); err != nil { return err } return daemon.postRunProcessing(c, ei) } - if execConfig := c.ExecCommands.ByPid(int(ei.Pid)); execConfig != nil { + if execConfig := c.ExecCommands.Get(ei.ProcessID); execConfig != nil { ec := int(ei.ExitCode) execConfig.Lock() defer execConfig.Unlock() @@ -122,9 +128,15 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc // remove the exec command from the container's store only and not the // daemon's store so that the exec command can be inspected. c.ExecCommands.Delete(execConfig.ID, execConfig.Pid) + attributes := map[string]string{ + "execID": execConfig.ID, + "exitCode": strconv.Itoa(ec), + } + daemon.LogContainerEventWithAttributes(c, "exec_die", attributes) } else { logrus.WithFields(logrus.Fields{ "container": c.ID, + "exec-id": ei.ProcessID, "exec-pid": ei.Pid, }).Warnf("Ignoring Exit Event, no such exec command found") } diff --git a/vendor/github.com/docker/docker/daemon/monitor_solaris.go b/vendor/github.com/docker/docker/daemon/monitor_solaris.go deleted file mode 100644 index 099575800..000000000 --- a/vendor/github.com/docker/docker/daemon/monitor_solaris.go +++ /dev/null @@ -1,11 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/container" - "github.com/docker/docker/libcontainerd" -) - -// postRunProcessing perfoms any processing needed on the container after it has stopped. -func (daemon *Daemon) postRunProcessing(_ *container.Container, _ libcontainerd.EventInfo) error { - return nil -} diff --git a/vendor/github.com/docker/docker/daemon/names.go b/vendor/github.com/docker/docker/daemon/names.go index 3ef96b1cd..0e4373884 100644 --- a/vendor/github.com/docker/docker/daemon/names.go +++ b/vendor/github.com/docker/docker/daemon/names.go @@ -6,6 +6,7 @@ import ( "github.com/docker/docker/container" "github.com/docker/docker/daemon/names" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/namesgenerator" "github.com/docker/docker/pkg/stringid" "github.com/pkg/errors" @@ -56,7 +57,7 @@ func (daemon *Daemon) generateIDAndName(name string) (string, string, error) { func (daemon *Daemon) reserveName(id, name string) (string, error) { if !validContainerNamePattern.MatchString(strings.TrimPrefix(name, "/")) { - return "", validationError{errors.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)} + return "", errdefs.InvalidParameter(errors.Errorf("Invalid container name (%s), only %s are allowed", name, validContainerNameChars)) } if name[0] != '/' { name = "/" + name diff --git a/vendor/github.com/docker/docker/daemon/network.go b/vendor/github.com/docker/docker/daemon/network.go index 61548c5b5..1ae69e509 100644 --- a/vendor/github.com/docker/docker/daemon/network.go +++ b/vendor/github.com/docker/docker/daemon/network.go @@ -3,6 +3,7 @@ package daemon import ( "fmt" "net" + "runtime" "sort" "strings" "sync" @@ -10,6 +11,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/network" clustertypes "github.com/docker/docker/daemon/cluster/provider" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/plugingetter" "github.com/docker/docker/runconfig" "github.com/docker/libnetwork" @@ -28,34 +30,40 @@ func (daemon *Daemon) NetworkControllerEnabled() bool { return daemon.netController != nil } -// FindNetwork function finds a network for a given string that can represent network name or id -func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) { - // 1. match by full ID. - n, err := daemon.GetNetworkByID(idName) - if err == nil || !isNoSuchNetworkError(err) { - return n, err +// FindNetwork returns a network based on: +// 1. Full ID +// 2. Full Name +// 3. Partial ID +// as long as there is no ambiguity +func (daemon *Daemon) FindNetwork(term string) (libnetwork.Network, error) { + listByFullName := []libnetwork.Network{} + listByPartialID := []libnetwork.Network{} + for _, nw := range daemon.GetNetworks() { + if nw.ID() == term { + return nw, nil + } + if nw.Name() == term { + listByFullName = append(listByFullName, nw) + } + if strings.HasPrefix(nw.ID(), term) { + listByPartialID = append(listByPartialID, nw) + } + } + switch { + case len(listByFullName) == 1: + return listByFullName[0], nil + case len(listByFullName) > 1: + return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found on name)", term, len(listByFullName))) + case len(listByPartialID) == 1: + return listByPartialID[0], nil + case len(listByPartialID) > 1: + return nil, errdefs.InvalidParameter(errors.Errorf("network %s is ambiguous (%d matches found based on ID prefix)", term, len(listByPartialID))) } - // 2. match by full name - n, err = daemon.GetNetworkByName(idName) - if err == nil || !isNoSuchNetworkError(err) { - return n, err - } - - // 3. match by ID prefix - list := daemon.GetNetworksByIDPrefix(idName) - if len(list) == 0 { - return nil, errors.WithStack(networkNotFound(idName)) - } - if len(list) > 1 { - return nil, errors.WithStack(invalidIdentifier(idName)) - } - return list[0], nil -} - -func isNoSuchNetworkError(err error) bool { - _, ok := err.(libnetwork.ErrNoSuchNetwork) - return ok + // Be very careful to change the error type here, the + // libnetwork.ErrNoSuchNetwork error is used by the controller + // to retry the creation of the network as managed through the swarm manager + return nil, errdefs.NotFound(libnetwork.ErrNoSuchNetwork(term)) } // GetNetworkByID function returns a network whose ID matches the given ID. @@ -101,7 +109,11 @@ func (daemon *Daemon) GetNetworksByIDPrefix(partialID string) []libnetwork.Netwo // getAllNetworks returns a list containing all networks func (daemon *Daemon) getAllNetworks() []libnetwork.Network { - return daemon.netController.Networks() + c := daemon.netController + if c == nil { + return nil + } + return c.Networks() } type ingressJob struct { @@ -181,21 +193,14 @@ func (daemon *Daemon) setupIngress(create *clustertypes.NetworkCreateRequest, ip // Otherwise continue down the call to create or recreate sandbox. } - n, err := daemon.GetNetworkByID(create.ID) + _, err := daemon.GetNetworkByID(create.ID) if err != nil { logrus.Errorf("Failed getting ingress network by id after creating: %v", err) } - - if err = daemon.createLoadBalancerSandbox("ingress", create.ID, ip, n, libnetwork.OptionIngress()); err != nil { - logrus.Errorf("Failed creating load balancer sandbox for ingress network: %v", err) - } } func (daemon *Daemon) releaseIngress(id string) { controller := daemon.netController - if err := controller.SandboxDestroy("ingress-sbox"); err != nil { - logrus.Errorf("Failed to delete ingress sandbox: %v", err) - } if id == "" { return @@ -207,13 +212,6 @@ func (daemon *Daemon) releaseIngress(id string) { return } - for _, ep := range n.Endpoints() { - if err := ep.Delete(true); err != nil { - logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err) - return - } - } - if err := n.Delete(); err != nil { logrus.Errorf("Failed to delete ingress network %s: %v", n.ID(), err) return @@ -268,38 +266,10 @@ func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.N return resp, err } -func (daemon *Daemon) createLoadBalancerSandbox(prefix, id string, ip net.IP, n libnetwork.Network, options ...libnetwork.SandboxOption) error { - c := daemon.netController - sandboxName := prefix + "-sbox" - sb, err := c.NewSandbox(sandboxName, options...) - if err != nil { - if _, ok := err.(networktypes.ForbiddenError); !ok { - return errors.Wrapf(err, "Failed creating %s sandbox", sandboxName) - } - return nil - } - - endpointName := prefix + "-endpoint" - ep, err := n.CreateEndpoint(endpointName, libnetwork.CreateOptionIpam(ip, nil, nil, nil), libnetwork.CreateOptionLoadBalancer()) - if err != nil { - return errors.Wrapf(err, "Failed creating %s in sandbox %s", endpointName, sandboxName) - } - - if err := ep.Join(sb, nil); err != nil { - return errors.Wrapf(err, "Failed joining %s to sandbox %s", endpointName, sandboxName) - } - - if err := sb.EnableService(); err != nil { - return errors.Wrapf(err, "Failed enabling service in %s sandbox", sandboxName) - } - - return nil -} - func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) { if runconfig.IsPreDefinedNetwork(create.Name) && !agent { err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name) - return nil, notAllowedError{err} + return nil, errdefs.Forbidden(err) } var warning string @@ -313,7 +283,9 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string // check if user defined CheckDuplicate, if set true, return err // otherwise prepare a warning message if create.CheckDuplicate { - return nil, libnetwork.NetworkNameError(create.Name) + if !agent || nw.Info().Dynamic() { + return nil, libnetwork.NetworkNameError(create.Name) + } } warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID()) } @@ -358,6 +330,15 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string nwOptions = append(nwOptions, libnetwork.NetworkOptionConfigFrom(create.ConfigFrom.Network)) } + if agent && driver == "overlay" && (create.Ingress || runtime.GOOS == "windows") { + nodeIP, exists := daemon.GetAttachmentStore().GetIPForNetwork(id) + if !exists { + return nil, fmt.Errorf("Failed to find a load balancer IP to use for network: %v", id) + } + + nwOptions = append(nwOptions, libnetwork.NetworkOptionLBEndpoint(nodeIP)) + } + n, err := c.NewNetwork(driver, create.Name, id, nwOptions...) if err != nil { if _, ok := err.(libnetwork.ErrDataStoreNotInitialized); ok { @@ -373,18 +354,6 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string } daemon.LogNetworkEvent(n, "create") - if agent && !n.Info().Ingress() && n.Type() == "overlay" { - nodeIP, exists := daemon.GetAttachmentStore().GetIPForNetwork(id) - if !exists { - return nil, fmt.Errorf("Failed to find a load balancer IP to use for network: %v", id) - } - - if err := daemon.createLoadBalancerSandbox(create.Name, id, nodeIP, n); err != nil { - return nil, err - } - - } - return &types.NetworkCreateResponse{ ID: n.ID(), Warning: warning, @@ -506,13 +475,22 @@ func (daemon *Daemon) GetNetworkDriverList() []string { } // DeleteManagedNetwork deletes an agent network. +// The requirement of networkID is enforced. func (daemon *Daemon) DeleteManagedNetwork(networkID string) error { - return daemon.deleteNetwork(networkID, true) + n, err := daemon.GetNetworkByID(networkID) + if err != nil { + return err + } + return daemon.deleteNetwork(n, true) } // DeleteNetwork destroys a network unless it's one of docker's predefined networks. func (daemon *Daemon) DeleteNetwork(networkID string) error { - return daemon.deleteNetwork(networkID, false) + n, err := daemon.GetNetworkByID(networkID) + if err != nil { + return err + } + return daemon.deleteNetwork(n, false) } func (daemon *Daemon) deleteLoadBalancerSandbox(n libnetwork.Network) { @@ -546,15 +524,10 @@ func (daemon *Daemon) deleteLoadBalancerSandbox(n libnetwork.Network) { } } -func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error { - nw, err := daemon.FindNetwork(networkID) - if err != nil { - return err - } - +func (daemon *Daemon) deleteNetwork(nw libnetwork.Network, dynamic bool) error { if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic { err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name()) - return notAllowedError{err} + return errdefs.Forbidden(err) } if dynamic && !nw.Info().Dynamic() { @@ -564,11 +537,7 @@ func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error { return nil } err := fmt.Errorf("%s is not a dynamic network", nw.Name()) - return notAllowedError{err} - } - - if !nw.Info().Ingress() && nw.Type() == "overlay" { - daemon.deleteLoadBalancerSandbox(nw) + return errdefs.Forbidden(err) } if err := nw.Delete(); err != nil { diff --git a/vendor/github.com/docker/docker/daemon/oci_linux.go b/vendor/github.com/docker/docker/daemon/oci_linux.go index 757de8536..53dc27656 100644 --- a/vendor/github.com/docker/docker/daemon/oci_linux.go +++ b/vendor/github.com/docker/docker/daemon/oci_linux.go @@ -812,6 +812,10 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { return nil, fmt.Errorf("linux seccomp: %v", err) } + if err := daemon.setupContainerMountsRoot(c); err != nil { + return nil, err + } + if err := daemon.setupIpcDirs(c); err != nil { return nil, err } @@ -839,11 +843,17 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { } ms = append(ms, tmpfsMounts...) - if m := c.SecretMounts(); m != nil { - ms = append(ms, m...) + secretMounts, err := c.SecretMounts() + if err != nil { + return nil, err } + ms = append(ms, secretMounts...) - ms = append(ms, c.ConfigMounts()...) + configMounts, err := c.ConfigMounts() + if err != nil { + return nil, err + } + ms = append(ms, configMounts...) sort.Sort(mounts(ms)) if err := setMounts(daemon, &s, c, ms); err != nil { diff --git a/vendor/github.com/docker/docker/daemon/oci_windows.go b/vendor/github.com/docker/docker/daemon/oci_windows.go index c7c94f327..86e0762a9 100644 --- a/vendor/github.com/docker/docker/daemon/oci_windows.go +++ b/vendor/github.com/docker/docker/daemon/oci_windows.go @@ -93,12 +93,20 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { } } - if m := c.SecretMounts(); m != nil { - mounts = append(mounts, m...) + secretMounts, err := c.SecretMounts() + if err != nil { + return nil, err + } + if secretMounts != nil { + mounts = append(mounts, secretMounts...) } - if m := c.ConfigMounts(); m != nil { - mounts = append(mounts, m...) + configMounts, err := c.ConfigMounts() + if err != nil { + return nil, err + } + if configMounts != nil { + mounts = append(mounts, configMounts...) } for _, mount := range mounts { @@ -138,9 +146,12 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { max := len(img.RootFS.DiffIDs) for i := 1; i <= max; i++ { img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i] - layerPath, err := layer.GetLayerPath(daemon.stores[c.OS].layerStore, img.RootFS.ChainID()) + if !system.IsOSSupported(img.OperatingSystem()) { + return nil, fmt.Errorf("cannot get layerpath for ImageID %s: %s ", img.RootFS.ChainID(), system.ErrNotSupportedOperatingSystem) + } + layerPath, err := layer.GetLayerPath(daemon.layerStores[img.OperatingSystem()], img.RootFS.ChainID()) if err != nil { - return nil, fmt.Errorf("failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.stores[c.OS].layerStore, img.RootFS.ChainID(), err) + return nil, fmt.Errorf("failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.layerStores[img.OperatingSystem()], img.RootFS.ChainID(), err) } // Reverse order, expecting parent most first s.Windows.LayerFolders = append([]string{layerPath}, s.Windows.LayerFolders...) @@ -210,15 +221,18 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { NetworkSharedContainerName: networkSharedContainerID, } - if img.OS == "windows" { + switch img.OS { + case "windows": if err := daemon.createSpecWindowsFields(c, &s, isHyperV); err != nil { return nil, err } - } else { - // TODO @jhowardmsft LCOW Support. Modify this check when running in dual-mode - if system.LCOWSupported() && img.OS == "linux" { - daemon.createSpecLinuxFields(c, &s) + case "linux": + if !system.LCOWSupported() { + return nil, fmt.Errorf("Linux containers on Windows are not supported") } + daemon.createSpecLinuxFields(c, &s) + default: + return nil, fmt.Errorf("Unsupported platform %q", img.OS) } return (*specs.Spec)(&s), nil diff --git a/vendor/github.com/docker/docker/daemon/pause.go b/vendor/github.com/docker/docker/daemon/pause.go index b751cc488..0b2ff1d2e 100644 --- a/vendor/github.com/docker/docker/daemon/pause.go +++ b/vendor/github.com/docker/docker/daemon/pause.go @@ -14,12 +14,7 @@ func (daemon *Daemon) ContainerPause(name string) error { if err != nil { return err } - - if err := daemon.containerPause(container); err != nil { - return err - } - - return nil + return daemon.containerPause(container) } // containerPause pauses the container execution without stopping the process. diff --git a/vendor/github.com/docker/docker/daemon/prune.go b/vendor/github.com/docker/docker/daemon/prune.go index 1850752cf..cf42f2872 100644 --- a/vendor/github.com/docker/docker/daemon/prune.go +++ b/vendor/github.com/docker/docker/daemon/prune.go @@ -3,7 +3,6 @@ package daemon import ( "fmt" "regexp" - "runtime" "sync/atomic" "time" @@ -14,7 +13,6 @@ import ( "github.com/docker/docker/image" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/directory" - "github.com/docker/docker/pkg/system" "github.com/docker/docker/runconfig" "github.com/docker/docker/volume" "github.com/docker/libnetwork" @@ -162,12 +160,6 @@ func (daemon *Daemon) VolumesPrune(ctx context.Context, pruneFilters filters.Arg // ImagesPrune removes unused images func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) { - // TODO @jhowardmsft LCOW Support: This will need revisiting later. - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - if !atomic.CompareAndSwapInt32(&daemon.pruneRunning, 0, 1) { return nil, errPruneRunning } @@ -197,9 +189,9 @@ func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args var allImages map[image.ID]*image.Image if danglingOnly { - allImages = daemon.stores[platform].imageStore.Heads() + allImages = daemon.imageStore.Heads() } else { - allImages = daemon.stores[platform].imageStore.Map() + allImages = daemon.imageStore.Map() } allContainers := daemon.List() imageRefs := map[string]bool{} @@ -213,7 +205,12 @@ func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args } // Filter intermediary images and get their unique size - allLayers := daemon.stores[platform].layerStore.Map() + allLayers := make(map[layer.ChainID]layer.Layer) + for _, ls := range daemon.layerStores { + for k, v := range ls.Map() { + allLayers[k] = v + } + } topImages := map[image.ID]*image.Image{} for id, img := range allImages { select { @@ -221,7 +218,7 @@ func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args return nil, ctx.Err() default: dgst := digest.Digest(id) - if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.stores[platform].imageStore.Children(id)) != 0 { + if len(daemon.referenceStore.References(dgst)) == 0 && len(daemon.imageStore.Children(id)) != 0 { continue } if !until.IsZero() && img.Created.After(until) { diff --git a/vendor/github.com/docker/docker/daemon/reload.go b/vendor/github.com/docker/docker/daemon/reload.go index 0d16bc8d0..5a73c9ef9 100644 --- a/vendor/github.com/docker/docker/daemon/reload.go +++ b/vendor/github.com/docker/docker/daemon/reload.go @@ -27,11 +27,14 @@ func (daemon *Daemon) Reload(conf *config.Config) (err error) { attributes := map[string]string{} defer func() { + jsonString, _ := json.Marshal(daemon.configStore) + // we're unlocking here, because // LogDaemonEventWithAttributes() -> SystemInfo() -> GetAllRuntimes() // holds that lock too. daemon.configStore.Unlock() if err == nil { + logrus.Infof("Reloaded configuration: %s", jsonString) daemon.LogDaemonEventWithAttributes("reload", attributes) } }() @@ -61,7 +64,7 @@ func (daemon *Daemon) Reload(conf *config.Config) (err error) { if err := daemon.reloadLiveRestore(conf, attributes); err != nil { return err } - return nil + return daemon.reloadNetworkDiagnosticPort(conf, attributes) } // reloadDebug updates configuration with Debug option @@ -308,3 +311,18 @@ func (daemon *Daemon) reloadLiveRestore(conf *config.Config, attributes map[stri attributes["live-restore"] = fmt.Sprintf("%t", daemon.configStore.LiveRestoreEnabled) return nil } + +// reloadNetworkDiagnosticPort updates the network controller starting the diagnose mode if the config is valid +func (daemon *Daemon) reloadNetworkDiagnosticPort(conf *config.Config, attributes map[string]string) error { + if conf == nil || daemon.netController == nil { + return nil + } + // Enable the network diagnose if the flag is set with a valid port withing the range + if conf.IsValueSet("network-diagnostic-port") && conf.NetworkDiagnosticPort > 0 && conf.NetworkDiagnosticPort < 65536 { + logrus.Warnf("Calling the diagnostic start with %d", conf.NetworkDiagnosticPort) + daemon.netController.StartDiagnose(conf.NetworkDiagnosticPort) + } else { + daemon.netController.StopDiagnose() + } + return nil +} diff --git a/vendor/github.com/docker/docker/daemon/reload_test.go b/vendor/github.com/docker/docker/daemon/reload_test.go index 96b1a2452..03b249bad 100644 --- a/vendor/github.com/docker/docker/daemon/reload_test.go +++ b/vendor/github.com/docker/docker/daemon/reload_test.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/pkg/discovery" _ "github.com/docker/docker/pkg/discovery/memory" "github.com/docker/docker/registry" + "github.com/docker/libnetwork" "github.com/stretchr/testify/assert" ) @@ -479,3 +480,71 @@ func TestDaemonDiscoveryReloadOnlyClusterAdvertise(t *testing.T) { t.Fatal(e) } } + +func TestDaemonReloadNetworkDiagnosticPort(t *testing.T) { + daemon := &Daemon{} + daemon.configStore = &config.Config{} + + valuesSet := make(map[string]interface{}) + valuesSet["network-diagnostic-port"] = 2000 + enableConfig := &config.Config{ + CommonConfig: config.CommonConfig{ + NetworkDiagnosticPort: 2000, + ValuesSet: valuesSet, + }, + } + disableConfig := &config.Config{ + CommonConfig: config.CommonConfig{}, + } + + netOptions, err := daemon.networkOptions(enableConfig, nil, nil) + if err != nil { + t.Fatal(err) + } + controller, err := libnetwork.New(netOptions...) + if err != nil { + t.Fatal(err) + } + daemon.netController = controller + + // Enable/Disable the server for some iterations + for i := 0; i < 10; i++ { + enableConfig.CommonConfig.NetworkDiagnosticPort++ + if err := daemon.Reload(enableConfig); err != nil { + t.Fatal(err) + } + // Check that the diagnose is enabled + if !daemon.netController.IsDiagnoseEnabled() { + t.Fatalf("diagnosed should be enable") + } + + // Reload + if err := daemon.Reload(disableConfig); err != nil { + t.Fatal(err) + } + // Check that the diagnose is disabled + if daemon.netController.IsDiagnoseEnabled() { + t.Fatalf("diagnosed should be disable") + } + } + + enableConfig.CommonConfig.NetworkDiagnosticPort++ + // 2 times the enable should not create problems + if err := daemon.Reload(enableConfig); err != nil { + t.Fatal(err) + } + // Check that the diagnose is enabled + if !daemon.netController.IsDiagnoseEnabled() { + t.Fatalf("diagnosed should be enable") + } + + // Check that another reload does not cause issues + if err := daemon.Reload(enableConfig); err != nil { + t.Fatal(err) + } + // Check that the diagnose is enable + if !daemon.netController.IsDiagnoseEnabled() { + t.Fatalf("diagnosed should be enable") + } + +} diff --git a/vendor/github.com/docker/docker/daemon/reload_unix.go b/vendor/github.com/docker/docker/daemon/reload_unix.go new file mode 100644 index 000000000..cdc17452b --- /dev/null +++ b/vendor/github.com/docker/docker/daemon/reload_unix.go @@ -0,0 +1,56 @@ +// +build linux freebsd + +package daemon + +import ( + "bytes" + "fmt" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/daemon/config" +) + +// reloadPlatform updates configuration with platform specific options +// and updates the passed attributes +func (daemon *Daemon) reloadPlatform(conf *config.Config, attributes map[string]string) error { + if err := conf.ValidatePlatformConfig(); err != nil { + return err + } + + if conf.IsValueSet("runtimes") { + // Always set the default one + conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary} + if err := daemon.initRuntimes(conf.Runtimes); err != nil { + return err + } + daemon.configStore.Runtimes = conf.Runtimes + } + + if conf.DefaultRuntime != "" { + daemon.configStore.DefaultRuntime = conf.DefaultRuntime + } + + if conf.IsValueSet("default-shm-size") { + daemon.configStore.ShmSize = conf.ShmSize + } + + if conf.IpcMode != "" { + daemon.configStore.IpcMode = conf.IpcMode + } + + // Update attributes + var runtimeList bytes.Buffer + for name, rt := range daemon.configStore.Runtimes { + if runtimeList.Len() > 0 { + runtimeList.WriteRune(' ') + } + runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt)) + } + + attributes["runtimes"] = runtimeList.String() + attributes["default-runtime"] = daemon.configStore.DefaultRuntime + attributes["default-shm-size"] = fmt.Sprintf("%d", daemon.configStore.ShmSize) + attributes["default-ipc-mode"] = daemon.configStore.IpcMode + + return nil +} diff --git a/vendor/github.com/docker/docker/daemon/reload_windows.go b/vendor/github.com/docker/docker/daemon/reload_windows.go new file mode 100644 index 000000000..b7a4031ea --- /dev/null +++ b/vendor/github.com/docker/docker/daemon/reload_windows.go @@ -0,0 +1,9 @@ +package daemon + +import "github.com/docker/docker/daemon/config" + +// reloadPlatform updates configuration with platform specific options +// and updates the passed attributes +func (daemon *Daemon) reloadPlatform(config *config.Config, attributes map[string]string) error { + return nil +} diff --git a/vendor/github.com/docker/docker/daemon/rename.go b/vendor/github.com/docker/docker/daemon/rename.go index 26ee9beae..fd13d898e 100644 --- a/vendor/github.com/docker/docker/daemon/rename.go +++ b/vendor/github.com/docker/docker/daemon/rename.go @@ -4,6 +4,7 @@ import ( "strings" dockercontainer "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/libnetwork" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -19,7 +20,7 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error { ) if oldName == "" || newName == "" { - return validationError{errors.New("Neither old nor new names may be empty")} + return errdefs.InvalidParameter(errors.New("Neither old nor new names may be empty")) } if newName[0] != '/' { @@ -38,13 +39,13 @@ func (daemon *Daemon) ContainerRename(oldName, newName string) error { oldIsAnonymousEndpoint := container.NetworkSettings.IsAnonymousEndpoint if oldName == newName { - return validationError{errors.New("Renaming a container with the same name as its current name")} + return errdefs.InvalidParameter(errors.New("Renaming a container with the same name as its current name")) } links := map[string]*dockercontainer.Container{} for k, v := range daemon.linkIndex.children(container) { if !strings.HasPrefix(k, oldName) { - return validationError{errors.Errorf("Linked container %s does not match parent %s", k, oldName)} + return errdefs.InvalidParameter(errors.Errorf("Linked container %s does not match parent %s", k, oldName)) } links[strings.TrimPrefix(k, oldName)] = v } diff --git a/vendor/github.com/docker/docker/daemon/secrets_linux.go b/vendor/github.com/docker/docker/daemon/secrets_linux.go index fca4e1259..6ae0117b7 100644 --- a/vendor/github.com/docker/docker/daemon/secrets_linux.go +++ b/vendor/github.com/docker/docker/daemon/secrets_linux.go @@ -1,5 +1,3 @@ -// +build linux - package daemon func secretsSupported() bool { diff --git a/vendor/github.com/docker/docker/daemon/secrets_windows.go b/vendor/github.com/docker/docker/daemon/secrets_windows.go index 9054354c8..6ae0117b7 100644 --- a/vendor/github.com/docker/docker/daemon/secrets_windows.go +++ b/vendor/github.com/docker/docker/daemon/secrets_windows.go @@ -1,5 +1,3 @@ -// +build windows - package daemon func secretsSupported() bool { diff --git a/vendor/github.com/docker/docker/daemon/selinux_linux.go b/vendor/github.com/docker/docker/daemon/selinux_linux.go index fb2578bf4..46da7f137 100644 --- a/vendor/github.com/docker/docker/daemon/selinux_linux.go +++ b/vendor/github.com/docker/docker/daemon/selinux_linux.go @@ -1,5 +1,3 @@ -// +build linux - package daemon import "github.com/opencontainers/selinux/go-selinux" diff --git a/vendor/github.com/docker/docker/daemon/start.go b/vendor/github.com/docker/docker/daemon/start.go index 3b9f0f9f6..707f40f3a 100644 --- a/vendor/github.com/docker/docker/daemon/start.go +++ b/vendor/github.com/docker/docker/daemon/start.go @@ -8,6 +8,8 @@ import ( "github.com/docker/docker/api/types" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/mount" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -15,7 +17,7 @@ import ( // ContainerStart starts a container. func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error { if checkpoint != "" && !daemon.HasExperimental() { - return validationError{errors.New("checkpoint is only supported in experimental mode")} + return errdefs.InvalidParameter(errors.New("checkpoint is only supported in experimental mode")) } container, err := daemon.GetContainer(name) @@ -28,7 +30,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos defer container.Unlock() if container.Paused { - return stateConflictError{errors.New("cannot start a paused container, try unpause instead")} + return errdefs.Conflict(errors.New("cannot start a paused container, try unpause instead")) } if container.Running { @@ -36,7 +38,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos } if container.RemovalInProgress || container.Dead { - return stateConflictError{errors.New("container is marked for removal and cannot be started")} + return errdefs.Conflict(errors.New("container is marked for removal and cannot be started")) } return nil } @@ -53,13 +55,13 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos logrus.Warn("DEPRECATED: Setting host configuration options when the container starts is deprecated and has been removed in Docker 1.12") oldNetworkMode := container.HostConfig.NetworkMode if err := daemon.setSecurityOptions(container, hostConfig); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } if err := daemon.mergeAndVerifyLogConfig(&hostConfig.LogConfig); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } if err := daemon.setHostConfig(container, hostConfig); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } newNetworkMode := container.HostConfig.NetworkMode if string(oldNetworkMode) != string(newNetworkMode) { @@ -67,34 +69,30 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos // old networks. It is a deprecated feature and has been removed in Docker 1.12 container.NetworkSettings.Networks = nil if err := container.CheckpointTo(daemon.containersReplica); err != nil { - return systemError{err} + return errdefs.System(err) } } container.InitDNSHostConfig() } } else { if hostConfig != nil { - return validationError{errors.New("Supplying a hostconfig on start is not supported. It should be supplied on create")} + return errdefs.InvalidParameter(errors.New("Supplying a hostconfig on start is not supported. It should be supplied on create")) } } // check if hostConfig is in line with the current system settings. // It may happen cgroups are umounted or the like. if _, err = daemon.verifyContainerSettings(container.OS, container.HostConfig, nil, false); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } // Adapt for old containers in case we have updates in this function and // old containers never have chance to call the new function in create stage. if hostConfig != nil { if err := daemon.adaptContainerSettings(container.HostConfig, false); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } } - - if err := daemon.containerStart(container, checkpoint, checkpointDir, true); err != nil { - return err - } - return nil + return daemon.containerStart(container, checkpoint, checkpointDir, true) } // containerStart prepares the container to run by setting up everything the @@ -111,12 +109,12 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint } if container.RemovalInProgress || container.Dead { - return stateConflictError{errors.New("container is marked for removal and cannot be started")} + return errdefs.Conflict(errors.New("container is marked for removal and cannot be started")) } if checkpointDir != "" { // TODO(mlaventure): how would we support that? - return notAllowedError{errors.New("custom checkpointdir is not supported")} + return errdefs.Forbidden(errors.New("custom checkpointdir is not supported")) } // if we encounter an error during start we need to ensure that any other @@ -155,7 +153,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint spec, err := daemon.createSpec(container) if err != nil { - return systemError{err} + return errdefs.System(err) } if resetRestartManager { @@ -225,7 +223,7 @@ func (daemon *Daemon) Cleanup(container *container.Container) { if err := daemon.conditionalUnmountOnCleanup(container); err != nil { // FIXME: remove once reference counting for graphdrivers has been refactored // Ensure that all the mounts are gone - if mountid, err := daemon.stores[container.OS].layerStore.GetMountID(container.ID); err == nil { + if mountid, err := daemon.layerStores[container.OS].GetMountID(container.ID); err == nil { daemon.cleanupMountsByID(mountid) } } @@ -234,6 +232,10 @@ func (daemon *Daemon) Cleanup(container *container.Container) { logrus.Warnf("%s cleanup: failed to unmount secrets: %s", container.ID, err) } + if err := mount.RecursiveUnmount(container.Root); err != nil { + logrus.WithError(err).WithField("container", container.ID).Warn("Error while cleaning up container resource mounts.") + } + for _, eConfig := range container.ExecCommands.Commands() { daemon.unregisterExecCommand(container, eConfig) } diff --git a/vendor/github.com/docker/docker/daemon/start_unix.go b/vendor/github.com/docker/docker/daemon/start_unix.go index a8402bb30..ca0183ec5 100644 --- a/vendor/github.com/docker/docker/daemon/start_unix.go +++ b/vendor/github.com/docker/docker/daemon/start_unix.go @@ -7,8 +7,9 @@ import ( "os/exec" "path/filepath" - "github.com/containerd/containerd/linux/runcopts" + "github.com/containerd/containerd/linux/runctypes" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" ) @@ -16,7 +17,7 @@ func (daemon *Daemon) getRuntimeScript(container *container.Container) (string, name := container.HostConfig.Runtime rt := daemon.configStore.GetRuntime(name) if rt == nil { - return "", validationError{errors.Errorf("no such runtime '%s'", name)} + return "", errdefs.InvalidParameter(errors.Errorf("no such runtime '%s'", name)) } if len(rt.Args) > 0 { @@ -42,7 +43,7 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain if err != nil { return nil, err } - opts := &runcopts.RuncOptions{ + opts := &runctypes.RuncOptions{ Runtime: path, RuntimeRoot: filepath.Join(daemon.configStore.ExecRoot, fmt.Sprintf("runtime-%s", container.HostConfig.Runtime)), diff --git a/vendor/github.com/docker/docker/daemon/stats/collector_windows.go b/vendor/github.com/docker/docker/daemon/stats/collector_windows.go index 5fb27ced6..03109fd8f 100644 --- a/vendor/github.com/docker/docker/daemon/stats/collector_windows.go +++ b/vendor/github.com/docker/docker/daemon/stats/collector_windows.go @@ -1,5 +1,3 @@ -// +build windows - package stats // platformNewStatsCollector performs platform specific initialisation of the diff --git a/vendor/github.com/docker/docker/daemon/stop.go b/vendor/github.com/docker/docker/daemon/stop.go index 7eadba7e2..d3b5297fb 100644 --- a/vendor/github.com/docker/docker/daemon/stop.go +++ b/vendor/github.com/docker/docker/daemon/stop.go @@ -5,6 +5,7 @@ import ( "time" containerpkg "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -28,7 +29,7 @@ func (daemon *Daemon) ContainerStop(name string, seconds *int) error { seconds = &stopTimeout } if err := daemon.containerStop(container, *seconds); err != nil { - return errors.Wrapf(systemError{err}, "cannot stop container: %s", name) + return errdefs.System(errors.Wrapf(err, "cannot stop container: %s", name)) } return nil } @@ -43,8 +44,6 @@ func (daemon *Daemon) containerStop(container *containerpkg.Container, seconds i return nil } - daemon.stopHealthchecks(container) - stopSignal := container.StopSignal() // 1. Send a stop signal if err := daemon.killPossiblyDeadProcess(container, stopSignal); err != nil { diff --git a/vendor/github.com/docker/docker/daemon/unpause.go b/vendor/github.com/docker/docker/daemon/unpause.go index 2e41f2070..b29a1f68d 100644 --- a/vendor/github.com/docker/docker/daemon/unpause.go +++ b/vendor/github.com/docker/docker/daemon/unpause.go @@ -14,12 +14,7 @@ func (daemon *Daemon) ContainerUnpause(name string) error { if err != nil { return err } - - if err := daemon.containerUnpause(container); err != nil { - return err - } - - return nil + return daemon.containerUnpause(container) } // containerUnpause resumes the container execution after the container is paused. diff --git a/vendor/github.com/docker/docker/daemon/update.go b/vendor/github.com/docker/docker/daemon/update.go index 0a79c199f..d2eb33a75 100644 --- a/vendor/github.com/docker/docker/daemon/update.go +++ b/vendor/github.com/docker/docker/daemon/update.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/docker/docker/api/types/container" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" ) @@ -19,7 +20,7 @@ func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostCon warnings, err = daemon.verifyContainerSettings(c.OS, hostConfig, nil, true) if err != nil { - return container.ContainerUpdateOKBody{Warnings: warnings}, validationError{err} + return container.ContainerUpdateOKBody{Warnings: warnings}, errdefs.InvalidParameter(err) } if err := daemon.update(name, hostConfig); err != nil { @@ -80,7 +81,7 @@ func (daemon *Daemon) update(name string, hostConfig *container.HostConfig) erro if err := daemon.containerd.UpdateResources(context.Background(), container.ID, toContainerdResources(hostConfig.Resources)); err != nil { restoreConfig = true // TODO: it would be nice if containerd responded with better errors here so we can classify this better. - return errCannotUpdate(container.ID, systemError{err}) + return errCannotUpdate(container.ID, errdefs.System(err)) } } diff --git a/vendor/github.com/docker/docker/daemon/update_linux.go b/vendor/github.com/docker/docker/daemon/update_linux.go index 41d3b5324..a55d39a56 100644 --- a/vendor/github.com/docker/docker/daemon/update_linux.go +++ b/vendor/github.com/docker/docker/daemon/update_linux.go @@ -1,5 +1,3 @@ -// +build linux - package daemon import ( @@ -32,6 +30,13 @@ func toContainerdResources(resources container.Resources) *libcontainerd.Resourc period = uint64(100 * time.Millisecond / time.Microsecond) quota = resources.NanoCPUs * int64(period) / 1e9 } + if quota == 0 && resources.CPUQuota != 0 { + quota = resources.CPUQuota + } + if period == 0 && resources.CPUPeriod != 0 { + period = uint64(resources.CPUPeriod) + } + r.CPU.Period = &period r.CPU.Quota = "a diff --git a/vendor/github.com/docker/docker/daemon/update_solaris.go b/vendor/github.com/docker/docker/daemon/update_solaris.go deleted file mode 100644 index f3b545c5f..000000000 --- a/vendor/github.com/docker/docker/daemon/update_solaris.go +++ /dev/null @@ -1,11 +0,0 @@ -package daemon - -import ( - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/libcontainerd" -) - -func toContainerdResources(resources container.Resources) libcontainerd.Resources { - var r libcontainerd.Resources - return r -} diff --git a/vendor/github.com/docker/docker/daemon/update_windows.go b/vendor/github.com/docker/docker/daemon/update_windows.go index 4f85f41dd..e60f63d92 100644 --- a/vendor/github.com/docker/docker/daemon/update_windows.go +++ b/vendor/github.com/docker/docker/daemon/update_windows.go @@ -1,5 +1,3 @@ -// +build windows - package daemon import ( diff --git a/vendor/github.com/docker/docker/daemon/volumes.go b/vendor/github.com/docker/docker/daemon/volumes.go index 6a42ec23e..2e75feebd 100644 --- a/vendor/github.com/docker/docker/daemon/volumes.go +++ b/vendor/github.com/docker/docker/daemon/volumes.go @@ -12,6 +12,7 @@ import ( containertypes "github.com/docker/docker/api/types/container" mounttypes "github.com/docker/docker/api/types/mount" "github.com/docker/docker/container" + "github.com/docker/docker/errdefs" "github.com/docker/docker/volume" "github.com/docker/docker/volume/drivers" "github.com/pkg/errors" @@ -175,7 +176,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo for _, cfg := range hostConfig.Mounts { mp, err := parser.ParseMountSpec(cfg) if err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } if binds[mp.Destination] { diff --git a/vendor/github.com/docker/docker/daemon/volumes_windows.go b/vendor/github.com/docker/docker/daemon/volumes_windows.go index 62c9e23ac..bfb5133d3 100644 --- a/vendor/github.com/docker/docker/daemon/volumes_windows.go +++ b/vendor/github.com/docker/docker/daemon/volumes_windows.go @@ -1,5 +1,3 @@ -// +build windows - package daemon import ( diff --git a/vendor/github.com/docker/docker/distribution/config.go b/vendor/github.com/docker/docker/distribution/config.go index 16d729c0e..f42c9670f 100644 --- a/vendor/github.com/docker/docker/distribution/config.go +++ b/vendor/github.com/docker/docker/distribution/config.go @@ -59,9 +59,9 @@ type ImagePullConfig struct { // Schema2Types is the valid schema2 configuration types allowed // by the pull operation. Schema2Types []string - // Platform is the requested platform of the image being pulled to ensure it can be validated - // when the host platform supports multiple image operating systems. - Platform string + // OS is the requested operating system of the image being pulled to ensure it can be validated + // when the host OS supports multiple image operating systems. + OS string } // ImagePushConfig stores push configuration. @@ -71,8 +71,8 @@ type ImagePushConfig struct { // ConfigMediaType is the configuration media type for // schema2 manifests. ConfigMediaType string - // LayerStore manages layers. - LayerStore PushLayerProvider + // LayerStores (indexed by operating system) manages layers. + LayerStores map[string]PushLayerProvider // TrustKey is the private key for legacy signatures. This is typically // an ephemeral key, since these signatures are no longer verified. TrustKey libtrust.PrivateKey @@ -86,7 +86,7 @@ type ImagePushConfig struct { type ImageConfigStore interface { Put([]byte) (digest.Digest, error) Get(digest.Digest) ([]byte, error) - RootFSAndOSFromConfig([]byte) (*image.RootFS, layer.OS, error) + RootFSAndOSFromConfig([]byte) (*image.RootFS, string, error) } // PushLayerProvider provides layers to be pushed by ChainID. @@ -112,7 +112,7 @@ type RootFSDownloadManager interface { // returns the final rootfs. // Given progress output to track download progress // Returns function to release download resources - Download(ctx context.Context, initialRootFS image.RootFS, os layer.OS, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error) + Download(ctx context.Context, initialRootFS image.RootFS, os string, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error) } type imageConfigStore struct { @@ -140,7 +140,7 @@ func (s *imageConfigStore) Get(d digest.Digest) ([]byte, error) { return img.RawJSON(), nil } -func (s *imageConfigStore) RootFSAndOSFromConfig(c []byte) (*image.RootFS, layer.OS, error) { +func (s *imageConfigStore) RootFSAndOSFromConfig(c []byte) (*image.RootFS, string, error) { var unmarshalledConfig image.Image if err := json.Unmarshal(c, &unmarshalledConfig); err != nil { return nil, "", err @@ -154,24 +154,29 @@ func (s *imageConfigStore) RootFSAndOSFromConfig(c []byte) (*image.RootFS, layer return nil, "", fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS) } - os := "" - if runtime.GOOS == "windows" { - os = unmarshalledConfig.OS + os := unmarshalledConfig.OS + if os == "" { + os = runtime.GOOS } - return unmarshalledConfig.RootFS, layer.OS(os), nil + if !system.IsOSSupported(os) { + return nil, "", system.ErrNotSupportedOperatingSystem + } + return unmarshalledConfig.RootFS, os, nil } type storeLayerProvider struct { ls layer.Store } -// NewLayerProviderFromStore returns a layer provider backed by +// NewLayerProvidersFromStores returns layer providers backed by // an instance of LayerStore. Only getting layers as gzipped // tars is supported. -func NewLayerProviderFromStore(ls layer.Store) PushLayerProvider { - return &storeLayerProvider{ - ls: ls, +func NewLayerProvidersFromStores(lss map[string]layer.Store) map[string]PushLayerProvider { + plps := make(map[string]PushLayerProvider) + for os, ls := range lss { + plps[os] = &storeLayerProvider{ls: ls} } + return plps } func (p *storeLayerProvider) Get(lid layer.ChainID) (PushLayer, error) { diff --git a/vendor/github.com/docker/docker/distribution/errors.go b/vendor/github.com/docker/docker/distribution/errors.go index dd6ff0a9a..49e8e5c0c 100644 --- a/vendor/github.com/docker/docker/distribution/errors.go +++ b/vendor/github.com/docker/docker/distribution/errors.go @@ -13,6 +13,7 @@ import ( "github.com/docker/distribution/registry/client" "github.com/docker/distribution/registry/client/auth" "github.com/docker/docker/distribution/xfer" + "github.com/docker/docker/errdefs" "github.com/sirupsen/logrus" ) @@ -85,20 +86,6 @@ func (e notFoundError) Cause() error { return e.cause } -type unknownError struct { - cause error -} - -func (e unknownError) Error() string { - return e.cause.Error() -} - -func (e unknownError) Cause() error { - return e.cause -} - -func (e unknownError) Unknown() {} - // TranslatePullError is used to convert an error from a registry pull // operation to an error representing the entire pull operation. Any error // information which is not used by the returned error gets output to @@ -121,26 +108,30 @@ func TranslatePullError(err error, ref reference.Named) error { return TranslatePullError(v.Err, ref) } - return unknownError{err} + return errdefs.Unknown(err) } // continueOnError returns true if we should fallback to the next endpoint // as a result of this error. -func continueOnError(err error) bool { +func continueOnError(err error, mirrorEndpoint bool) bool { switch v := err.(type) { case errcode.Errors: if len(v) == 0 { return true } - return continueOnError(v[0]) + return continueOnError(v[0], mirrorEndpoint) case ErrNoSupport: - return continueOnError(v.Err) + return continueOnError(v.Err, mirrorEndpoint) case errcode.Error: - return shouldV2Fallback(v) + return mirrorEndpoint || shouldV2Fallback(v) case *client.UnexpectedHTTPResponseError: return true case ImageConfigPullError: - return false + // ImageConfigPullError only happens with v2 images, v1 fallback is + // unnecessary. + // Failures from a mirror endpoint should result in fallback to the + // canonical repo. + return mirrorEndpoint case error: return !strings.Contains(err.Error(), strings.ToLower(syscall.ESRCH.Error())) } diff --git a/vendor/github.com/docker/docker/distribution/errors_test.go b/vendor/github.com/docker/docker/distribution/errors_test.go new file mode 100644 index 000000000..aa9ef4f42 --- /dev/null +++ b/vendor/github.com/docker/docker/distribution/errors_test.go @@ -0,0 +1,85 @@ +package distribution + +import ( + "errors" + "strings" + "syscall" + "testing" + + "github.com/docker/distribution/registry/api/errcode" + "github.com/docker/distribution/registry/api/v2" + "github.com/docker/distribution/registry/client" +) + +var alwaysContinue = []error{ + &client.UnexpectedHTTPResponseError{}, + + // Some errcode.Errors that don't disprove the existence of a V1 image + errcode.Error{Code: errcode.ErrorCodeUnauthorized}, + errcode.Error{Code: v2.ErrorCodeManifestUnknown}, + errcode.Error{Code: v2.ErrorCodeNameUnknown}, + + errors.New("some totally unexpected error"), +} + +var continueFromMirrorEndpoint = []error{ + ImageConfigPullError{}, + + // Some other errcode.Error that doesn't indicate we should search for a V1 image. + errcode.Error{Code: errcode.ErrorCodeTooManyRequests}, +} + +var neverContinue = []error{ + errors.New(strings.ToLower(syscall.ESRCH.Error())), // No such process +} + +func TestContinueOnError_NonMirrorEndpoint(t *testing.T) { + for _, err := range alwaysContinue { + if !continueOnError(err, false) { + t.Errorf("Should continue from non-mirror endpoint: %T: '%s'", err, err.Error()) + } + } + + for _, err := range continueFromMirrorEndpoint { + if continueOnError(err, false) { + t.Errorf("Should only continue from mirror endpoint: %T: '%s'", err, err.Error()) + } + } +} + +func TestContinueOnError_MirrorEndpoint(t *testing.T) { + errs := []error{} + errs = append(errs, alwaysContinue...) + errs = append(errs, continueFromMirrorEndpoint...) + for _, err := range errs { + if !continueOnError(err, true) { + t.Errorf("Should continue from mirror endpoint: %T: '%s'", err, err.Error()) + } + } +} + +func TestContinueOnError_NeverContinue(t *testing.T) { + for _, isMirrorEndpoint := range []bool{true, false} { + for _, err := range neverContinue { + if continueOnError(err, isMirrorEndpoint) { + t.Errorf("Should never continue: %T: '%s'", err, err.Error()) + } + } + } +} + +func TestContinueOnError_UnnestsErrors(t *testing.T) { + // ContinueOnError should evaluate nested errcode.Errors. + + // Assumes that v2.ErrorCodeNameUnknown is a continueable error code. + err := errcode.Errors{errcode.Error{Code: v2.ErrorCodeNameUnknown}} + if !continueOnError(err, false) { + t.Fatal("ContinueOnError should unnest, base return value on errcode.Errors") + } + + // Assumes that errcode.ErrorCodeTooManyRequests is not a V1-fallback indication + err = errcode.Errors{errcode.Error{Code: errcode.ErrorCodeTooManyRequests}} + if continueOnError(err, false) { + t.Fatal("ContinueOnError should unnest, base return value on errcode.Errors") + } +} diff --git a/vendor/github.com/docker/docker/distribution/metadata/metadata.go b/vendor/github.com/docker/docker/distribution/metadata/metadata.go index 3dae79555..05ba4f817 100644 --- a/vendor/github.com/docker/docker/distribution/metadata/metadata.go +++ b/vendor/github.com/docker/docker/distribution/metadata/metadata.go @@ -26,17 +26,15 @@ type Store interface { type FSMetadataStore struct { sync.RWMutex basePath string - platform string } // NewFSMetadataStore creates a new filesystem-based metadata store. -func NewFSMetadataStore(basePath, platform string) (*FSMetadataStore, error) { +func NewFSMetadataStore(basePath string) (*FSMetadataStore, error) { if err := os.MkdirAll(basePath, 0700); err != nil { return nil, err } return &FSMetadataStore{ basePath: basePath, - platform: platform, }, nil } diff --git a/vendor/github.com/docker/docker/distribution/metadata/v1_id_service_test.go b/vendor/github.com/docker/docker/distribution/metadata/v1_id_service_test.go index 385901ec4..337278613 100644 --- a/vendor/github.com/docker/docker/distribution/metadata/v1_id_service_test.go +++ b/vendor/github.com/docker/docker/distribution/metadata/v1_id_service_test.go @@ -3,10 +3,10 @@ package metadata import ( "io/ioutil" "os" - "runtime" "testing" "github.com/docker/docker/layer" + "github.com/stretchr/testify/require" ) func TestV1IDService(t *testing.T) { @@ -16,12 +16,16 @@ func TestV1IDService(t *testing.T) { } defer os.RemoveAll(tmpDir) - metadataStore, err := NewFSMetadataStore(tmpDir, runtime.GOOS) + metadataStore, err := NewFSMetadataStore(tmpDir) if err != nil { t.Fatalf("could not create metadata store: %v", err) } v1IDService := NewV1IDService(metadataStore) + ns := v1IDService.namespace() + + require.Equal(t, "v1id", ns) + testVectors := []struct { registry string v1ID string diff --git a/vendor/github.com/docker/docker/distribution/metadata/v2_metadata_service_test.go b/vendor/github.com/docker/docker/distribution/metadata/v2_metadata_service_test.go index b5d59b229..8e3e4614c 100644 --- a/vendor/github.com/docker/docker/distribution/metadata/v2_metadata_service_test.go +++ b/vendor/github.com/docker/docker/distribution/metadata/v2_metadata_service_test.go @@ -6,7 +6,6 @@ import ( "math/rand" "os" "reflect" - "runtime" "testing" "github.com/docker/docker/layer" @@ -20,7 +19,7 @@ func TestV2MetadataService(t *testing.T) { } defer os.RemoveAll(tmpDir) - metadataStore, err := NewFSMetadataStore(tmpDir, runtime.GOOS) + metadataStore, err := NewFSMetadataStore(tmpDir) if err != nil { t.Fatalf("could not create metadata store: %v", err) } diff --git a/vendor/github.com/docker/docker/distribution/pull.go b/vendor/github.com/docker/docker/distribution/pull.go index 446197cf2..008ccfb5e 100644 --- a/vendor/github.com/docker/docker/distribution/pull.go +++ b/vendor/github.com/docker/docker/distribution/pull.go @@ -21,7 +21,7 @@ type Puller interface { // Pull tries to pull the image referenced by `tag` // Pull returns an error if any, as well as a boolean that determines whether to retry Pull on the next configured endpoint. // - Pull(ctx context.Context, ref reference.Named, platform string) error + Pull(ctx context.Context, ref reference.Named, os string) error } // newPuller returns a Puller interface that will pull from either a v1 or v2 @@ -115,12 +115,12 @@ func Pull(ctx context.Context, ref reference.Named, imagePullConfig *ImagePullCo continue } - // Make sure we default the platform if it hasn't been supplied - if imagePullConfig.Platform == "" { - imagePullConfig.Platform = runtime.GOOS + // Make sure we default the OS if it hasn't been supplied + if imagePullConfig.OS == "" { + imagePullConfig.OS = runtime.GOOS } - if err := puller.Pull(ctx, ref, imagePullConfig.Platform); err != nil { + if err := puller.Pull(ctx, ref, imagePullConfig.OS); err != nil { // Was this pull cancelled? If so, don't try to fall // back. fallback := false diff --git a/vendor/github.com/docker/docker/distribution/pull_v1.go b/vendor/github.com/docker/docker/distribution/pull_v1.go index 6f1c2eee0..17e9a7cce 100644 --- a/vendor/github.com/docker/docker/distribution/pull_v1.go +++ b/vendor/github.com/docker/docker/distribution/pull_v1.go @@ -36,7 +36,7 @@ type v1Puller struct { session *registry.Session } -func (p *v1Puller) Pull(ctx context.Context, ref reference.Named, platform string) error { +func (p *v1Puller) Pull(ctx context.Context, ref reference.Named, os string) error { if _, isCanonical := ref.(reference.Canonical); isCanonical { // Allowing fallback, because HTTPS v1 is before HTTP v2 return fallbackError{err: ErrNoSupport{Err: errors.New("Cannot pull by digest with v1 registry")}} diff --git a/vendor/github.com/docker/docker/distribution/pull_v2.go b/vendor/github.com/docker/docker/distribution/pull_v2.go index c8d784ca6..0b3a3b0cd 100644 --- a/vendor/github.com/docker/docker/distribution/pull_v2.go +++ b/vendor/github.com/docker/docker/distribution/pull_v2.go @@ -62,7 +62,7 @@ type v2Puller struct { confirmedV2 bool } -func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, platform string) (err error) { +func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, os string) (err error) { // TODO(tiborvass): was ReceiveTimeout p.repo, p.confirmedV2, err = NewV2Repository(ctx, p.repoInfo, p.endpoint, p.config.MetaHeaders, p.config.AuthConfig, "pull") if err != nil { @@ -70,11 +70,11 @@ func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, platform strin return err } - if err = p.pullV2Repository(ctx, ref, platform); err != nil { + if err = p.pullV2Repository(ctx, ref, os); err != nil { if _, ok := err.(fallbackError); ok { return err } - if continueOnError(err) { + if continueOnError(err, p.endpoint.Mirror) { return fallbackError{ err: err, confirmedV2: p.confirmedV2, @@ -85,10 +85,10 @@ func (p *v2Puller) Pull(ctx context.Context, ref reference.Named, platform strin return err } -func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named, platform string) (err error) { +func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named, os string) (err error) { var layersDownloaded bool if !reference.IsNameOnly(ref) { - layersDownloaded, err = p.pullV2Tag(ctx, ref, platform) + layersDownloaded, err = p.pullV2Tag(ctx, ref, os) if err != nil { return err } @@ -110,7 +110,7 @@ func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named, pl if err != nil { return err } - pulledNew, err := p.pullV2Tag(ctx, tagRef, platform) + pulledNew, err := p.pullV2Tag(ctx, tagRef, os) if err != nil { // Since this is the pull-all-tags case, don't // allow an error pulling a particular tag to @@ -488,9 +488,9 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Reference, unv descriptors = append(descriptors, layerDescriptor) } - // The v1 manifest itself doesn't directly contain a platform. However, + // The v1 manifest itself doesn't directly contain an OS. However, // the history does, but unfortunately that's a string, so search through - // all the history until hopefully we find one which indicates the os. + // all the history until hopefully we find one which indicates the OS. // supertest2014/nyan is an example of a registry image with schemav1. configOS := runtime.GOOS if system.LCOWSupported() { @@ -514,7 +514,7 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Reference, unv return "", "", fmt.Errorf("cannot download image with operating system %q when requesting %q", configOS, requestedOS) } - resultRootFS, release, err := p.config.DownloadManager.Download(ctx, *rootFS, layer.OS(configOS), descriptors, p.config.ProgressOutput) + resultRootFS, release, err := p.config.DownloadManager.Download(ctx, *rootFS, configOS, descriptors, p.config.ProgressOutput) if err != nil { return "", "", err } @@ -588,7 +588,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s downloadedRootFS *image.RootFS // rootFS from registered layers configRootFS *image.RootFS // rootFS from configuration release func() // release resources from rootFS download - configOS layer.OS // for LCOW when registering downloaded layers + configOS string // for LCOW when registering downloaded layers ) // https://github.com/docker/docker/issues/24766 - Err on the side of caution, @@ -615,7 +615,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s // Early bath if the requested OS doesn't match that of the configuration. // This avoids doing the download, only to potentially fail later. - if !strings.EqualFold(string(configOS), requestedOS) { + if !strings.EqualFold(configOS, requestedOS) { return "", "", fmt.Errorf("cannot download image with operating system %q when requesting %q", configOS, requestedOS) } @@ -633,7 +633,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s rootFS image.RootFS ) downloadRootFS := *image.NewRootFS() - rootFS, release, err = p.config.DownloadManager.Download(ctx, downloadRootFS, layer.OS(requestedOS), descriptors, p.config.ProgressOutput) + rootFS, release, err = p.config.DownloadManager.Download(ctx, downloadRootFS, requestedOS, descriptors, p.config.ProgressOutput) if err != nil { // Intentionally do not cancel the config download here // as the error from config download (if there is one) @@ -698,7 +698,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s return imageID, manifestDigest, nil } -func receiveConfig(s ImageConfigStore, configChan <-chan []byte, errChan <-chan error) ([]byte, *image.RootFS, layer.OS, error) { +func receiveConfig(s ImageConfigStore, configChan <-chan []byte, errChan <-chan error) ([]byte, *image.RootFS, string, error) { select { case configJSON := <-configChan: rootfs, os, err := s.RootFSAndOSFromConfig(configJSON) diff --git a/vendor/github.com/docker/docker/distribution/pull_v2_windows.go b/vendor/github.com/docker/docker/distribution/pull_v2_windows.go index b4573e1ec..08ff4371c 100644 --- a/vendor/github.com/docker/docker/distribution/pull_v2_windows.go +++ b/vendor/github.com/docker/docker/distribution/pull_v2_windows.go @@ -1,5 +1,3 @@ -// +build windows - package distribution import ( diff --git a/vendor/github.com/docker/docker/distribution/push_v1.go b/vendor/github.com/docker/docker/distribution/push_v1.go index dccc7b094..6dbc11011 100644 --- a/vendor/github.com/docker/docker/distribution/push_v1.go +++ b/vendor/github.com/docker/docker/distribution/push_v1.go @@ -14,6 +14,7 @@ import ( "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/progress" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/pkg/system" "github.com/docker/docker/registry" "github.com/opencontainers/go-digest" "github.com/sirupsen/logrus" @@ -210,7 +211,10 @@ func (p *v1Pusher) imageListForTag(imgID image.ID, dependenciesSeen map[layer.Ch topLayerID := img.RootFS.ChainID() - pl, err := p.config.LayerStore.Get(topLayerID) + if !system.IsOSSupported(img.OperatingSystem()) { + return nil, system.ErrNotSupportedOperatingSystem + } + pl, err := p.config.LayerStores[img.OperatingSystem()].Get(topLayerID) *referencedLayers = append(*referencedLayers, pl) if err != nil { return nil, fmt.Errorf("failed to get top layer from image: %v", err) diff --git a/vendor/github.com/docker/docker/distribution/push_v2.go b/vendor/github.com/docker/docker/distribution/push_v2.go index 7ffce5b2a..90b3b6030 100644 --- a/vendor/github.com/docker/docker/distribution/push_v2.go +++ b/vendor/github.com/docker/docker/distribution/push_v2.go @@ -67,7 +67,7 @@ func (p *v2Pusher) Push(ctx context.Context) (err error) { } if err = p.pushV2Repository(ctx); err != nil { - if continueOnError(err) { + if continueOnError(err, p.endpoint.Mirror) { return fallbackError{ err: err, confirmedV2: p.pushState.confirmedV2, @@ -118,12 +118,12 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id return fmt.Errorf("could not find image from tag %s: %v", reference.FamiliarString(ref), err) } - rootfs, _, err := p.config.ImageStore.RootFSAndOSFromConfig(imgConfig) + rootfs, os, err := p.config.ImageStore.RootFSAndOSFromConfig(imgConfig) if err != nil { return fmt.Errorf("unable to get rootfs for image %s: %s", reference.FamiliarString(ref), err) } - l, err := p.config.LayerStore.Get(rootfs.ChainID()) + l, err := p.config.LayerStores[os].Get(rootfs.ChainID()) if err != nil { return fmt.Errorf("failed to get top layer from image: %v", err) } diff --git a/vendor/github.com/docker/docker/distribution/xfer/download.go b/vendor/github.com/docker/docker/distribution/xfer/download.go index 043119e32..1ccb91a14 100644 --- a/vendor/github.com/docker/docker/distribution/xfer/download.go +++ b/vendor/github.com/docker/docker/distribution/xfer/download.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/progress" + "github.com/docker/docker/pkg/system" "github.com/sirupsen/logrus" "golang.org/x/net/context" ) @@ -95,7 +96,7 @@ type DownloadDescriptorWithRegistered interface { // Download method is called to get the layer tar data. Layers are then // registered in the appropriate order. The caller must call the returned // release function once it is done with the returned RootFS object. -func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS image.RootFS, os layer.OS, layers []DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error) { +func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS image.RootFS, os string, layers []DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error) { var ( topLayer layer.Layer topDownload *downloadTransfer @@ -105,9 +106,13 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima downloadsByKey = make(map[string]*downloadTransfer) ) - // Assume that the operating system is the host OS if blank + // Assume that the operating system is the host OS if blank, and validate it + // to ensure we don't cause a panic by an invalid index into the layerstores. if os == "" { - os = layer.OS(runtime.GOOS) + os = runtime.GOOS + } + if !system.IsOSSupported(os) { + return image.RootFS{}, nil, system.ErrNotSupportedOperatingSystem } rootFS := initialRootFS @@ -121,20 +126,20 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima if err == nil { getRootFS := rootFS getRootFS.Append(diffID) - l, err := ldm.layerStores[string(os)].Get(getRootFS.ChainID()) + l, err := ldm.layerStores[os].Get(getRootFS.ChainID()) if err == nil { // Layer already exists. logrus.Debugf("Layer already exists: %s", descriptor.ID()) progress.Update(progressOutput, descriptor.ID(), "Already exists") if topLayer != nil { - layer.ReleaseAndLog(ldm.layerStores[string(os)], topLayer) + layer.ReleaseAndLog(ldm.layerStores[os], topLayer) } topLayer = l missingLayer = false rootFS.Append(diffID) // Register this repository as a source of this layer. withRegistered, hasRegistered := descriptor.(DownloadDescriptorWithRegistered) - if hasRegistered { + if hasRegistered { // As layerstore may set the driver withRegistered.Registered(diffID) } continue @@ -171,7 +176,7 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima if topDownload == nil { return rootFS, func() { if topLayer != nil { - layer.ReleaseAndLog(ldm.layerStores[string(os)], topLayer) + layer.ReleaseAndLog(ldm.layerStores[os], topLayer) } }, nil } @@ -182,7 +187,7 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima defer func() { if topLayer != nil { - layer.ReleaseAndLog(ldm.layerStores[string(os)], topLayer) + layer.ReleaseAndLog(ldm.layerStores[os], topLayer) } }() @@ -218,11 +223,11 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima // complete before the registration step, and registers the downloaded data // on top of parentDownload's resulting layer. Otherwise, it registers the // layer on top of the ChainID given by parentLayer. -func (ldm *LayerDownloadManager) makeDownloadFunc(descriptor DownloadDescriptor, parentLayer layer.ChainID, parentDownload *downloadTransfer, os layer.OS) DoFunc { +func (ldm *LayerDownloadManager) makeDownloadFunc(descriptor DownloadDescriptor, parentLayer layer.ChainID, parentDownload *downloadTransfer, os string) DoFunc { return func(progressChan chan<- progress.Progress, start <-chan struct{}, inactive chan<- struct{}) Transfer { d := &downloadTransfer{ Transfer: NewTransfer(), - layerStore: ldm.layerStores[string(os)], + layerStore: ldm.layerStores[os], } go func() { @@ -341,9 +346,9 @@ func (ldm *LayerDownloadManager) makeDownloadFunc(descriptor DownloadDescriptor, src = fs.Descriptor() } if ds, ok := d.layerStore.(layer.DescribableStore); ok { - d.layer, err = ds.RegisterWithDescriptor(inflatedLayerData, parentLayer, os, src) + d.layer, err = ds.RegisterWithDescriptor(inflatedLayerData, parentLayer, src) } else { - d.layer, err = d.layerStore.Register(inflatedLayerData, parentLayer, os) + d.layer, err = d.layerStore.Register(inflatedLayerData, parentLayer) } if err != nil { select { @@ -382,11 +387,11 @@ func (ldm *LayerDownloadManager) makeDownloadFunc(descriptor DownloadDescriptor, // parentDownload. This function does not log progress output because it would // interfere with the progress reporting for sourceDownload, which has the same // Key. -func (ldm *LayerDownloadManager) makeDownloadFuncFromDownload(descriptor DownloadDescriptor, sourceDownload *downloadTransfer, parentDownload *downloadTransfer, os layer.OS) DoFunc { +func (ldm *LayerDownloadManager) makeDownloadFuncFromDownload(descriptor DownloadDescriptor, sourceDownload *downloadTransfer, parentDownload *downloadTransfer, os string) DoFunc { return func(progressChan chan<- progress.Progress, start <-chan struct{}, inactive chan<- struct{}) Transfer { d := &downloadTransfer{ Transfer: NewTransfer(), - layerStore: ldm.layerStores[string(os)], + layerStore: ldm.layerStores[os], } go func() { @@ -440,9 +445,9 @@ func (ldm *LayerDownloadManager) makeDownloadFuncFromDownload(descriptor Downloa src = fs.Descriptor() } if ds, ok := d.layerStore.(layer.DescribableStore); ok { - d.layer, err = ds.RegisterWithDescriptor(layerReader, parentLayer, os, src) + d.layer, err = ds.RegisterWithDescriptor(layerReader, parentLayer, src) } else { - d.layer, err = d.layerStore.Register(layerReader, parentLayer, os) + d.layer, err = d.layerStore.Register(layerReader, parentLayer) } if err != nil { d.err = fmt.Errorf("failed to register layer: %v", err) diff --git a/vendor/github.com/docker/docker/distribution/xfer/download_test.go b/vendor/github.com/docker/docker/distribution/xfer/download_test.go index 8af27f6e7..0d86b658c 100644 --- a/vendor/github.com/docker/docker/distribution/xfer/download_test.go +++ b/vendor/github.com/docker/docker/distribution/xfer/download_test.go @@ -26,7 +26,7 @@ type mockLayer struct { diffID layer.DiffID chainID layer.ChainID parent layer.Layer - os layer.OS + os string } func (ml *mockLayer) TarStream() (io.ReadCloser, error) { @@ -57,10 +57,6 @@ func (ml *mockLayer) DiffSize() (size int64, err error) { return 0, nil } -func (ml *mockLayer) OS() layer.OS { - return ml.os -} - func (ml *mockLayer) Metadata() (map[string]string, error) { return make(map[string]string), nil } @@ -91,7 +87,7 @@ func (ls *mockLayerStore) Map() map[layer.ChainID]layer.Layer { return layers } -func (ls *mockLayerStore) Register(reader io.Reader, parentID layer.ChainID, os layer.OS) (layer.Layer, error) { +func (ls *mockLayerStore) Register(reader io.Reader, parentID layer.ChainID) (layer.Layer, error) { return ls.RegisterWithDescriptor(reader, parentID, distribution.Descriptor{}) } @@ -293,13 +289,13 @@ func TestSuccessfulDownload(t *testing.T) { firstDescriptor := descriptors[0].(*mockDownloadDescriptor) // Pre-register the first layer to simulate an already-existing layer - l, err := layerStore.Register(firstDescriptor.mockTarStream(), "", layer.OS(runtime.GOOS)) + l, err := layerStore.Register(firstDescriptor.mockTarStream(), "") if err != nil { t.Fatal(err) } firstDescriptor.diffID = l.DiffID() - rootFS, releaseFunc, err := ldm.Download(context.Background(), *image.NewRootFS(), layer.OS(runtime.GOOS), descriptors, progress.ChanOutput(progressChan)) + rootFS, releaseFunc, err := ldm.Download(context.Background(), *image.NewRootFS(), runtime.GOOS, descriptors, progress.ChanOutput(progressChan)) if err != nil { t.Fatalf("download error: %v", err) } @@ -339,7 +335,6 @@ func TestCancelledDownload(t *testing.T) { lsMap := make(map[string]layer.Store) lsMap[runtime.GOOS] = layerStore ldm := NewLayerDownloadManager(lsMap, maxDownloadConcurrency, func(m *LayerDownloadManager) { m.waitDuration = time.Millisecond }) - progressChan := make(chan progress.Progress) progressDone := make(chan struct{}) @@ -357,7 +352,7 @@ func TestCancelledDownload(t *testing.T) { }() descriptors := downloadDescriptors(nil) - _, _, err := ldm.Download(ctx, *image.NewRootFS(), layer.OS(runtime.GOOS), descriptors, progress.ChanOutput(progressChan)) + _, _, err := ldm.Download(ctx, *image.NewRootFS(), runtime.GOOS, descriptors, progress.ChanOutput(progressChan)) if err != context.Canceled { t.Fatal("expected download to be cancelled") } diff --git a/vendor/github.com/docker/docker/dockerversion/version_lib.go b/vendor/github.com/docker/docker/dockerversion/version_lib.go index 33f77d3ce..72f48939d 100644 --- a/vendor/github.com/docker/docker/dockerversion/version_lib.go +++ b/vendor/github.com/docker/docker/dockerversion/version_lib.go @@ -13,4 +13,5 @@ const ( ContainerdCommitID string = "library-import" RuncCommitID string = "library-import" InitCommitID string = "library-import" + PlatformName string = "" ) diff --git a/vendor/github.com/docker/docker/docs/api/version-history.md b/vendor/github.com/docker/docker/docs/api/version-history.md index 5056c0ddb..4eca7fbb1 100644 --- a/vendor/github.com/docker/docker/docs/api/version-history.md +++ b/vendor/github.com/docker/docker/docs/api/version-history.md @@ -13,6 +13,13 @@ keywords: "API, Docker, rcli, REST, documentation" will be rejected. --> +## v1.36 API changes + +[Docker Engine API v1.36](https://docs.docker.com/engine/api/v1.36/) documentation + +* `Get /events` now return `exec_die` event when an exec process terminates. + + ## v1.35 API changes [Docker Engine API v1.35](https://docs.docker.com/engine/api/v1.35/) documentation @@ -23,6 +30,18 @@ keywords: "API, Docker, rcli, REST, documentation" configuration is only used for Windows containers. * `GET /containers/(name)/logs` now supports an additional query parameter: `until`, which returns log lines that occurred before the specified timestamp. +* `POST /containers/{id}/exec` now accepts a `WorkingDir` property to set the + work-dir for the exec process, independent of the container's work-dir. +* `Get /version` now returns a `Platform.Name` field, which can be used by products + using Moby as a foundation to return information about the platform. +* `Get /version` now returns a `Components` field, which can be used to return + information about the components used. Information about the engine itself is + now included as a "Component" version, and contains all information from the + top-level `Version`, `GitCommit`, `APIVersion`, `MinAPIVersion`, `GoVersion`, + `Os`, `Arch`, `BuildTime`, `KernelVersion`, and `Experimental` fields. Going + forward, the information from the `Components` section is preferred over their + top-level counterparts. + ## v1.34 API changes diff --git a/vendor/github.com/docker/docker/docs/contributing/set-up-dev-env.md b/vendor/github.com/docker/docker/docs/contributing/set-up-dev-env.md index acd6888cd..7f8a38119 100644 --- a/vendor/github.com/docker/docker/docs/contributing/set-up-dev-env.md +++ b/vendor/github.com/docker/docker/docs/contributing/set-up-dev-env.md @@ -10,8 +10,7 @@ Moby's development environment is itself, ultimately a Docker container. You use the `moby/moby` repository and its `Dockerfile` to create a Docker image, run a Docker container, and develop code in the container. -If you followed the procedures that -set up Git for contributing, you should have a fork of the `moby/moby` +If you followed the procedures that [set up Git for contributing](./set-up-git.md), you should have a fork of the `moby/moby` repository. You also created a branch called `dry-run-test`. In this section, you continue working with your fork on this branch. @@ -106,8 +105,7 @@ can take over 15 minutes to complete. ``` If you are following along with this guide, you created a `dry-run-test` - branch when you - set up Git for contributing. + branch when you [set up Git for contributing](./set-up-git.md). 3. Ensure you are on your `dry-run-test` branch. @@ -131,15 +129,16 @@ can take over 15 minutes to complete. ```none Successfully built 3d872560918e - docker run --rm -i --privileged -e BUILDFLAGS -e KEEPBUNDLE -e DOCKER_BUILD_GOGC -e DOCKER_BUILD_PKGS -e DOCKER_CLIENTONLY -e DOCKER_DEBUG -e DOCKER_EXPERIMENTAL -e DOCKER_GITCOMMIT -e DOCKER_GRAPHDRIVER=devicemapper -e DOCKER_INCREMENTAL_BINARY -e DOCKER_REMAP_ROOT -e DOCKER_STORAGE_OPTS -e DOCKER_USERLANDPROXY -e TESTDIRS -e TESTFLAGS -e TIMEOUT -v "home/ubuntu/repos/docker/bundles:/go/src/github.com/moby/moby/bundles" -t "docker-dev:dry-run-test" bash - root@f31fa223770f:/go/src/github.com/moby/moby# + Successfully tagged docker-dev:dry-run-test + docker run --rm -i --privileged -e BUILDFLAGS -e KEEPBUNDLE -e DOCKER_BUILD_GOGC -e DOCKER_BUILD_PKGS -e DOCKER_CLIENTONLY -e DOCKER_DEBUG -e DOCKER_EXPERIMENTAL -e DOCKER_GITCOMMIT -e DOCKER_GRAPHDRIVER=devicemapper -e DOCKER_INCREMENTAL_BINARY -e DOCKER_REMAP_ROOT -e DOCKER_STORAGE_OPTS -e DOCKER_USERLANDPROXY -e TESTDIRS -e TESTFLAGS -e TIMEOUT -v "home/ubuntu/repos/docker/bundles:/go/src/github.com/docker/docker/bundles" -t "docker-dev:dry-run-test" bash + root@f31fa223770f:/go/src/github.com/docker/docker# ``` At this point, your prompt reflects the container's BASH shell. -5. List the contents of the current directory (`/go/src/github.com/moby/moby`). +5. List the contents of the current directory (`/go/src/github.com/docker/docker`). - You should see the image's source from the `/go/src/github.com/moby/moby` + You should see the image's source from the `/go/src/github.com/docker/docker` directory. ![List example](images/list_example.png) @@ -147,7 +146,7 @@ can take over 15 minutes to complete. 6. Make a `dockerd` binary. ```none - root@a8b2885ab900:/go/src/github.com/moby/moby# hack/make.sh binary + root@a8b2885ab900:/go/src/github.com/docker/docker# hack/make.sh binary Removing bundles/ ---> Making bundle: binary (in bundles/binary) @@ -161,7 +160,7 @@ can take over 15 minutes to complete. `/usr/local/bin/` directory. ```none - root@a8b2885ab900:/go/src/github.com/moby/moby# make install + root@a8b2885ab900:/go/src/github.com/docker/docker# make install ``` 8. Start the Engine daemon running in the background. @@ -187,13 +186,65 @@ can take over 15 minutes to complete. hack/make.sh binary install-binary run ``` -9. Inside your container, check your Docker version. +9. Inside your container, check your Docker versions: ```none - root@5f8630b873fe:/go/src/github.com/moby/moby# docker --version - Docker version 1.12.0-dev, build 6e728fb + # docker version + Client: + Version: 17.06.0-ce + API version: 1.30 + Go version: go1.8.3 + Git commit: 02c1d87 + Built: Fri Jun 23 21:15:15 2017 + OS/Arch: linux/amd64 + + Server: + Version: dev + API version: 1.35 (minimum version 1.12) + Go version: go1.9.2 + Git commit: 4aa6362da + Built: Sat Dec 2 05:22:42 2017 + OS/Arch: linux/amd64 + Experimental: false ``` + Notice the split versions between client and server, which might be + unexpected. In more recent times the Docker CLI component (which provides the + `docker` command) has split out from the Moby project and is now maintained in: + + * [docker/cli](https://github.com/docker/cli) - The Docker CLI source-code; + * [docker/docker-ce](https://github.com/docker/docker-ce) - The Docker CE + edition project, which assembles engine, CLI and other components. + + The Moby project now defaults to a [fixed + version](https://github.com/docker/docker-ce/commits/v17.06.0-ce) of the + `docker` CLI for integration tests. + + You may have noticed the following message when starting the container with the `shell` command: + + ```none + Makefile:123: The docker client CLI has moved to github.com/docker/cli. For a dev-test cycle involving the CLI, run: + DOCKER_CLI_PATH=/host/path/to/cli/binary make shell + then change the cli and compile into a binary at the same location. + ``` + + By setting `DOCKER_CLI_PATH` you can supply a newer `docker` CLI to the + server development container for testing and for `integration-cli` + test-execution: + + ```none + make DOCKER_CLI_PATH=/home/ubuntu/git/docker-ce/components/packaging/static/build/linux/docker/docker BIND_DIR=. shell + ... + # which docker + /usr/local/cli/docker + # docker --version + Docker version 17.09.0-dev, build + ``` + + This Docker CLI should be built from the [docker-ce + project](https://github.com/docker/docker-ce) and needs to be a Linux + binary. + Inside the container you are running a development version. This is the version on the current branch. It reflects the value of the `VERSION` file at the root of your `docker-fork` repository. @@ -201,13 +252,13 @@ can take over 15 minutes to complete. 10. Run the `hello-world` image. ```none - root@5f8630b873fe:/go/src/github.com/moby/moby# docker run hello-world + root@5f8630b873fe:/go/src/github.com/docker/docker# docker run hello-world ``` 11. List the image you just downloaded. ```none - root@5f8630b873fe:/go/src/github.com/moby/moby# docker images + root@5f8630b873fe:/go/src/github.com/docker/docker# docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest c54a2cc56cbb 3 months ago 1.85 kB ``` @@ -296,7 +347,7 @@ example, you'll edit the help for the `attach` subcommand. 10. To view your change, run the `dockerd --help` command in the docker development container shell. ```bash - root@b0cb4f22715d:/go/src/github.com/moby/moby# dockerd --help + root@b0cb4f22715d:/go/src/github.com/docker/docker# dockerd --help Usage: dockerd COMMAND diff --git a/vendor/github.com/docker/docker/docs/contributing/software-req-win.md b/vendor/github.com/docker/docker/docs/contributing/software-req-win.md index 3be432793..d51861cbe 100644 --- a/vendor/github.com/docker/docker/docs/contributing/software-req-win.md +++ b/vendor/github.com/docker/docker/docs/contributing/software-req-win.md @@ -109,7 +109,7 @@ To test it, stop the system Docker daemon and start the one you just built: .\dockerd.exe -D The other make targets work too, to run unit tests try: -`docker run --rm docker-builder sh -c 'cd /c/go/src/github.com/moby/moby; hack/make.sh test-unit'`. +`docker run --rm docker-builder sh -c 'cd /c/go/src/github.com/docker/docker; hack/make.sh test-unit'`. ### 6. Remove the interim binaries container diff --git a/vendor/github.com/docker/docker/docs/contributing/test.md b/vendor/github.com/docker/docker/docs/contributing/test.md index 9a63a12b8..7e9107d11 100644 --- a/vendor/github.com/docker/docker/docs/contributing/test.md +++ b/vendor/github.com/docker/docker/docs/contributing/test.md @@ -47,7 +47,7 @@ testing: | ---------------------- | ---------------------------------------------- | | `test` | Run the unit, integration, and docker-py tests | | `test-unit` | Run just the unit tests | -| `test-integration-cli` | Run the integration tests for the CLI | +| `test-integration` | Run the integration tests | | `test-docker-py` | Run the tests for the Docker API client | Running the entire test suite on your current repository can take over half an @@ -107,13 +107,13 @@ Try this now. `dry-run-test` image. ```bash - $ docker run --privileged --rm -ti -v `pwd`:/go/src/github.com/moby/moby dry-run-test /bin/bash + $ docker run --privileged --rm -ti -v `pwd`:/go/src/github.com/docker/docker dry-run-test /bin/bash ``` 3. Run the tests using the `hack/make.sh` script. ```bash - root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary cross test-unit test-integration-cli test-docker-py + root@5f8630b873fe:/go/src/github.com/docker/docker# hack/make.sh dynbinary binary cross test-unit test-integration test-docker-py ``` The tests run just as they did within your local host. @@ -122,7 +122,7 @@ Try this now. just the unit tests: ```bash - root@5f8630b873fe:/go/src/github.com/moby/moby# hack/make.sh dynbinary binary cross test-unit + root@5f8630b873fe:/go/src/github.com/docker/docker# hack/make.sh dynbinary binary cross test-unit ``` Most test targets require that you build these precursor targets first: @@ -164,13 +164,13 @@ flag's value is passed as arguments to the `go test` command. For example, from your local host you can run the `TestBuild` test with this command: ```bash -$ TESTFLAGS='-check.f DockerSuite.TestBuild*' make test-integration-cli +$ TESTFLAGS='-check.f DockerSuite.TestBuild*' make test-integration ``` To run the same test inside your Docker development container, you do this: ```bash -root@5f8630b873fe:/go/src/github.com/moby/moby# TESTFLAGS='-check.f TestBuild*' hack/make.sh binary test-integration-cli +root@5f8630b873fe:/go/src/github.com/docker/docker# TESTFLAGS='-check.f TestBuild*' hack/make.sh binary test-integration ``` ## Test the Windows binary against a Linux daemon @@ -188,7 +188,7 @@ run a Bash terminal on Windows. 2. Change to the `moby` source directory. ```bash - $ cd /c/gopath/src/github.com/moby/moby + $ cd /c/gopath/src/github.com/docker/docker ``` 3. Set `DOCKER_REMOTE_DAEMON` as follows: @@ -207,14 +207,14 @@ run a Bash terminal on Windows. 5. Make the binary and run the tests: ```bash - $ hack/make.sh binary test-integration-cli + $ hack/make.sh binary test-integration ``` Some tests are skipped on Windows for various reasons. You can see which tests were skipped by re-running the make and passing in the `TESTFLAGS='-test.v'` value. For example ```bash - $ TESTFLAGS='-test.v' hack/make.sh binary test-integration-cli + $ TESTFLAGS='-test.v' hack/make.sh binary test-integration ``` Should you wish to run a single test such as one with the name @@ -222,7 +222,7 @@ run a Bash terminal on Windows. example ```bash - $ TESTFLAGS='-check.f TestExample' hack/make.sh binary test-integration-cli + $ TESTFLAGS='-check.f TestExample' hack/make.sh binary test-integration ``` You can now choose to make changes to the Moby source or the tests. If you diff --git a/vendor/github.com/docker/docker/api/errdefs/defs.go b/vendor/github.com/docker/docker/errdefs/defs.go similarity index 75% rename from vendor/github.com/docker/docker/api/errdefs/defs.go rename to vendor/github.com/docker/docker/errdefs/defs.go index 4987c623f..29c361960 100644 --- a/vendor/github.com/docker/docker/api/errdefs/defs.go +++ b/vendor/github.com/docker/docker/errdefs/defs.go @@ -43,6 +43,11 @@ type ErrNotModified interface { NotModified() } +// ErrAlreadyExists is a special case of ErrConflict which signals that the desired object already exists +type ErrAlreadyExists interface { + AlreadyExists() +} + // ErrNotImplemented signals that the requested action/feature is not implemented on the system as configured. type ErrNotImplemented interface { NotImplemented() @@ -52,3 +57,18 @@ type ErrNotImplemented interface { type ErrUnknown interface { Unknown() } + +// ErrCancelled signals that the action was cancelled. +type ErrCancelled interface { + Cancelled() +} + +// ErrDeadline signals that the deadline was reached before the action completed. +type ErrDeadline interface { + DeadlineExceeded() +} + +// ErrDataLoss indicates that data was lost or there is data corruption. +type ErrDataLoss interface { + DataLoss() +} diff --git a/vendor/github.com/docker/docker/api/errdefs/doc.go b/vendor/github.com/docker/docker/errdefs/doc.go similarity index 100% rename from vendor/github.com/docker/docker/api/errdefs/doc.go rename to vendor/github.com/docker/docker/errdefs/doc.go diff --git a/vendor/github.com/docker/docker/errdefs/helpers.go b/vendor/github.com/docker/docker/errdefs/helpers.go new file mode 100644 index 000000000..5afa94446 --- /dev/null +++ b/vendor/github.com/docker/docker/errdefs/helpers.go @@ -0,0 +1,240 @@ +package errdefs + +import "context" + +type errNotFound struct{ error } + +func (errNotFound) NotFound() {} + +func (e errNotFound) Cause() error { + return e.error +} + +// NotFound is a helper to create an error of the class with the same name from any error type +func NotFound(err error) error { + if err == nil { + return nil + } + return errNotFound{err} +} + +type errInvalidParameter struct{ error } + +func (errInvalidParameter) InvalidParameter() {} + +func (e errInvalidParameter) Cause() error { + return e.error +} + +// InvalidParameter is a helper to create an error of the class with the same name from any error type +func InvalidParameter(err error) error { + if err == nil { + return nil + } + return errInvalidParameter{err} +} + +type errConflict struct{ error } + +func (errConflict) Conflict() {} + +func (e errConflict) Cause() error { + return e.error +} + +// Conflict is a helper to create an error of the class with the same name from any error type +func Conflict(err error) error { + if err == nil { + return nil + } + return errConflict{err} +} + +type errUnauthorized struct{ error } + +func (errUnauthorized) Unauthorized() {} + +func (e errUnauthorized) Cause() error { + return e.error +} + +// Unauthorized is a helper to create an error of the class with the same name from any error type +func Unauthorized(err error) error { + if err == nil { + return nil + } + return errUnauthorized{err} +} + +type errUnavailable struct{ error } + +func (errUnavailable) Unavailable() {} + +func (e errUnavailable) Cause() error { + return e.error +} + +// Unavailable is a helper to create an error of the class with the same name from any error type +func Unavailable(err error) error { + return errUnavailable{err} +} + +type errForbidden struct{ error } + +func (errForbidden) Forbidden() {} + +func (e errForbidden) Cause() error { + return e.error +} + +// Forbidden is a helper to create an error of the class with the same name from any error type +func Forbidden(err error) error { + if err == nil { + return nil + } + return errForbidden{err} +} + +type errSystem struct{ error } + +func (errSystem) System() {} + +func (e errSystem) Cause() error { + return e.error +} + +// System is a helper to create an error of the class with the same name from any error type +func System(err error) error { + if err == nil { + return nil + } + return errSystem{err} +} + +type errNotModified struct{ error } + +func (errNotModified) NotModified() {} + +func (e errNotModified) Cause() error { + return e.error +} + +// NotModified is a helper to create an error of the class with the same name from any error type +func NotModified(err error) error { + if err == nil { + return nil + } + return errNotModified{err} +} + +type errAlreadyExists struct{ error } + +func (errAlreadyExists) AlreadyExists() {} + +func (e errAlreadyExists) Cause() error { + return e.error +} + +// AlreadyExists is a helper to create an error of the class with the same name from any error type +func AlreadyExists(err error) error { + if err == nil { + return nil + } + return errAlreadyExists{err} +} + +type errNotImplemented struct{ error } + +func (errNotImplemented) NotImplemented() {} + +func (e errNotImplemented) Cause() error { + return e.error +} + +// NotImplemented is a helper to create an error of the class with the same name from any error type +func NotImplemented(err error) error { + if err == nil { + return nil + } + return errNotImplemented{err} +} + +type errUnknown struct{ error } + +func (errUnknown) Unknown() {} + +func (e errUnknown) Cause() error { + return e.error +} + +// Unknown is a helper to create an error of the class with the same name from any error type +func Unknown(err error) error { + if err == nil { + return nil + } + return errUnknown{err} +} + +type errCancelled struct{ error } + +func (errCancelled) Cancelled() {} + +func (e errCancelled) Cause() error { + return e.error +} + +// Cancelled is a helper to create an error of the class with the same name from any error type +func Cancelled(err error) error { + if err == nil { + return nil + } + return errCancelled{err} +} + +type errDeadline struct{ error } + +func (errDeadline) DeadlineExceeded() {} + +func (e errDeadline) Cause() error { + return e.error +} + +// Deadline is a helper to create an error of the class with the same name from any error type +func Deadline(err error) error { + if err == nil { + return nil + } + return errDeadline{err} +} + +type errDataLoss struct{ error } + +func (errDataLoss) DataLoss() {} + +func (e errDataLoss) Cause() error { + return e.error +} + +// DataLoss is a helper to create an error of the class with the same name from any error type +func DataLoss(err error) error { + if err == nil { + return nil + } + return errDataLoss{err} +} + +// FromContext returns the error class from the passed in context +func FromContext(ctx context.Context) error { + e := ctx.Err() + if e == nil { + return nil + } + + if e == context.Canceled { + return Cancelled(e) + } + if e == context.DeadlineExceeded { + return Deadline(e) + } + return Unknown(e) +} diff --git a/vendor/github.com/docker/docker/errdefs/helpers_test.go b/vendor/github.com/docker/docker/errdefs/helpers_test.go new file mode 100644 index 000000000..984f0a77a --- /dev/null +++ b/vendor/github.com/docker/docker/errdefs/helpers_test.go @@ -0,0 +1,132 @@ +package errdefs + +import ( + "errors" + "testing" +) + +var errTest = errors.New("this is a test") + +type causal interface { + Cause() error +} + +func TestNotFound(t *testing.T) { + e := NotFound(errTest) + if !IsNotFound(e) { + t.Fatalf("expected not found error, got: %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestConflict(t *testing.T) { + e := Conflict(errTest) + if !IsConflict(e) { + t.Fatalf("expected conflcit error, got: %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestForbidden(t *testing.T) { + e := Forbidden(errTest) + if !IsForbidden(e) { + t.Fatalf("expected forbidden error, got: %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestInvalidParameter(t *testing.T) { + e := InvalidParameter(errTest) + if !IsInvalidParameter(e) { + t.Fatalf("expected invalid argument error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestNotImplemented(t *testing.T) { + e := NotImplemented(errTest) + if !IsNotImplemented(e) { + t.Fatalf("expected not implemented error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestNotModified(t *testing.T) { + e := NotModified(errTest) + if !IsNotModified(e) { + t.Fatalf("expected not modified error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestAlreadyExists(t *testing.T) { + e := AlreadyExists(errTest) + if !IsAlreadyExists(e) { + t.Fatalf("expected already exists error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestUnauthorized(t *testing.T) { + e := Unauthorized(errTest) + if !IsUnauthorized(e) { + t.Fatalf("expected unauthorized error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestUnknown(t *testing.T) { + e := Unknown(errTest) + if !IsUnknown(e) { + t.Fatalf("expected unknown error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestCancelled(t *testing.T) { + e := Cancelled(errTest) + if !IsCancelled(e) { + t.Fatalf("expected canclled error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestDeadline(t *testing.T) { + e := Deadline(errTest) + if !IsDeadline(e) { + t.Fatalf("expected deadline error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} + +func TestIsDataLoss(t *testing.T) { + e := DataLoss(errTest) + if !IsDataLoss(e) { + t.Fatalf("expected data loss error, got %T", e) + } + if cause := e.(causal).Cause(); cause != errTest { + t.Fatalf("causual should be errTest, got: %v", cause) + } +} diff --git a/vendor/github.com/docker/docker/api/errdefs/is.go b/vendor/github.com/docker/docker/errdefs/is.go similarity index 74% rename from vendor/github.com/docker/docker/api/errdefs/is.go rename to vendor/github.com/docker/docker/errdefs/is.go index b0be0b814..286ffd694 100644 --- a/vendor/github.com/docker/docker/api/errdefs/is.go +++ b/vendor/github.com/docker/docker/errdefs/is.go @@ -15,7 +15,11 @@ func getImplementer(err error) error { ErrForbidden, ErrSystem, ErrNotModified, + ErrAlreadyExists, ErrNotImplemented, + ErrCancelled, + ErrDeadline, + ErrDataLoss, ErrUnknown: return e case causer: @@ -73,6 +77,12 @@ func IsNotModified(err error) bool { return ok } +// IsAlreadyExists returns if the passed in error is a AlreadyExists error +func IsAlreadyExists(err error) bool { + _, ok := getImplementer(err).(ErrAlreadyExists) + return ok +} + // IsNotImplemented returns if the passed in error is an ErrNotImplemented func IsNotImplemented(err error) bool { _, ok := getImplementer(err).(ErrNotImplemented) @@ -84,3 +94,21 @@ func IsUnknown(err error) bool { _, ok := getImplementer(err).(ErrUnknown) return ok } + +// IsCancelled returns if the passed in error is an ErrCancelled +func IsCancelled(err error) bool { + _, ok := getImplementer(err).(ErrCancelled) + return ok +} + +// IsDeadline returns if the passed in error is an ErrDeadline +func IsDeadline(err error) bool { + _, ok := getImplementer(err).(ErrDeadline) + return ok +} + +// IsDataLoss returns if the passed in error is an ErrDataLoss +func IsDataLoss(err error) bool { + _, ok := getImplementer(err).(ErrDataLoss) + return ok +} diff --git a/vendor/github.com/docker/docker/hack/dockerfile/binaries-commits b/vendor/github.com/docker/docker/hack/dockerfile/binaries-commits index 1a20352aa..b2f55b09c 100644 --- a/vendor/github.com/docker/docker/hack/dockerfile/binaries-commits +++ b/vendor/github.com/docker/docker/hack/dockerfile/binaries-commits @@ -3,8 +3,12 @@ TOMLV_COMMIT=9baf8a8a9f2ed20a8e54160840c492f937eeaf9a # When updating RUNC_COMMIT, also update runc in vendor.conf accordingly -RUNC_COMMIT=b2567b37d7b75eb4cf325b77297b140ea686ce8f -CONTAINERD_COMMIT=v1.0.0-beta.3 +RUNC_COMMIT=7f24b40cc5423969b4554ef04ba0b00e2b4ba010 + +# containerd is also pinned in vendor.conf. When updating the binary +# version you may also need to update the vendor version to pick up bug +# fixes or new APIs. +CONTAINERD_COMMIT=9b55aab90508bd389d7654c4baf173a981477d55 # v1.0.1 TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574 LIBNETWORK_COMMIT=7b2b1feb1de4817d522cc372af149ff48d25028e VNDR_COMMIT=a6e196d8b4b0cbbdc29aebdb20c59ac6926bb384 diff --git a/vendor/github.com/docker/docker/hack/dockerfile/install-binaries.sh b/vendor/github.com/docker/docker/hack/dockerfile/install-binaries.sh index e97385ebc..ed97ce58b 100755 --- a/vendor/github.com/docker/docker/hack/dockerfile/install-binaries.sh +++ b/vendor/github.com/docker/docker/hack/dockerfile/install-binaries.sh @@ -48,7 +48,7 @@ install_containerd_static() { git checkout -q "$CONTAINERD_COMMIT" ( export GOPATH - make EXTRA_FLAGS="-buildmode pie" EXTRA_LDFLAGS="-extldflags \\\"-fno-PIC -static\\\"" + make BUILDTAGS='static_build netgo' EXTRA_FLAGS="-buildmode pie" EXTRA_LDFLAGS='-extldflags "-fno-PIC -static"' ) cp bin/containerd /usr/local/bin/docker-containerd cp bin/containerd-shim /usr/local/bin/docker-containerd-shim diff --git a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md index 1cea52526..4f4f67d4f 100644 --- a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md +++ b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/README.md @@ -12,7 +12,7 @@ IT on Swarm allows you to execute integration test in parallel across a Docker S ### Worker service - Works as a funker callee - - Executes an equivalent of `TESTFLAGS=-check.f TestFoo|TestBar|TestBaz ... make test-integration-cli` using the bind-mounted API socket (`docker.sock`) + - Executes an equivalent of `TESTFLAGS=-check.f TestFoo|TestBar|TestBaz ... make test-integration` using the bind-mounted API socket (`docker.sock`) ### Client diff --git a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/worker/executor.go b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/worker/executor.go index 3442b0940..eef80d461 100644 --- a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/worker/executor.go +++ b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/agent/worker/executor.go @@ -43,7 +43,7 @@ func privilegedTestChunkExecutor(autoRemove bool) testChunkExecutor { } graphdriver = info.Driver } - // `daemon_dest` is similar to `$DEST` (e.g. `bundles/VERSION/test-integration-cli`) + // `daemon_dest` is similar to `$DEST` (e.g. `bundles/VERSION/test-integration`) // but it exists outside of `bundles` so as to make `$DOCKER_GRAPHDRIVER` work. // // Without this hack, `$DOCKER_GRAPHDRIVER` fails because of (e.g.) `overlay2 is not supported over overlayfs` @@ -65,7 +65,7 @@ func privilegedTestChunkExecutor(autoRemove bool) testChunkExecutor { "org.dockerproject.integration-cli-on-swarm.comment": "this non-service container is created for running privileged programs on Swarm. you can remove this container manually if the corresponding service is already stopped.", }, Entrypoint: []string{"hack/dind"}, - Cmd: []string{"hack/make.sh", "test-integration-cli"}, + Cmd: []string{"hack/make.sh", "test-integration"}, } hostConfig := container.HostConfig{ AutoRemove: autoRemove, diff --git a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/host/enumerate.go b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/host/enumerate.go index 56c03e38d..3354c23c0 100644 --- a/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/host/enumerate.go +++ b/vendor/github.com/docker/docker/hack/integration-cli-on-swarm/host/enumerate.go @@ -26,7 +26,7 @@ func enumerateTestsForBytes(b []byte) ([]string, error) { // enumerateTests enumerates valid `-check.f` strings for all the test functions. // Note that we use regexp rather than parsing Go files for performance reason. -// (Try `TESTFLAGS=-check.list make test-integration-cli` to see the slowness of parsing) +// (Try `TESTFLAGS=-check.list make test-integration` to see the slowness of parsing) // The files needs to be `gofmt`-ed // // The result will be as follows, but unsorted ('$' is appended because they are regexp for `-check.f`): diff --git a/vendor/github.com/docker/docker/hack/make.ps1 b/vendor/github.com/docker/docker/hack/make.ps1 index 3380a5b69..42a2b319f 100644 --- a/vendor/github.com/docker/docker/hack/make.ps1 +++ b/vendor/github.com/docker/docker/hack/make.ps1 @@ -365,7 +365,7 @@ Try { # Run autogen if building binaries or running unit tests. if ($Client -or $Daemon -or $TestUnit) { Write-Host "INFO: Invoking autogen..." - Try { .\hack\make\.go-autogen.ps1 -CommitString $gitCommit -DockerVersion $dockerVersion } + Try { .\hack\make\.go-autogen.ps1 -CommitString $gitCommit -DockerVersion $dockerVersion -Platform "$env:PLATFORM" } Catch [Exception] { Throw $_ } } diff --git a/vendor/github.com/docker/docker/hack/make/.detect-daemon-osarch b/vendor/github.com/docker/docker/hack/make/.detect-daemon-osarch index 26cb30f4c..c472710d1 100644 --- a/vendor/github.com/docker/docker/hack/make/.detect-daemon-osarch +++ b/vendor/github.com/docker/docker/hack/make/.detect-daemon-osarch @@ -53,7 +53,6 @@ esac export PACKAGE_ARCH DOCKERFILE='Dockerfile' -TEST_IMAGE_NAMESPACE= case "$PACKAGE_ARCH" in amd64) case "${DOCKER_ENGINE_GOOS:-$DOCKER_CLIENT_GOOS}" in @@ -64,7 +63,6 @@ case "$PACKAGE_ARCH" in ;; *) DOCKERFILE="Dockerfile.$PACKAGE_ARCH" - TEST_IMAGE_NAMESPACE="$PACKAGE_ARCH" ;; esac -export DOCKERFILE TEST_IMAGE_NAMESPACE +export DOCKERFILE diff --git a/vendor/github.com/docker/docker/hack/make/.go-autogen b/vendor/github.com/docker/docker/hack/make/.go-autogen index b68e3a753..850c3ec9a 100644 --- a/vendor/github.com/docker/docker/hack/make/.go-autogen +++ b/vendor/github.com/docker/docker/hack/make/.go-autogen @@ -18,6 +18,7 @@ const ( BuildTime string = "$BUILDTIME" IAmStatic string = "${IAMSTATIC:-true}" ContainerdCommitID string = "${CONTAINERD_COMMIT}" + PlatformName string = "${PLATFORM}" ) // AUTOGENERATED FILE; see /go/src/github.com/docker/docker/hack/make/.go-autogen diff --git a/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 b/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 index 768badb6a..cc14e9ee9 100644 --- a/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 +++ b/vendor/github.com/docker/docker/hack/make/.go-autogen.ps1 @@ -14,7 +14,8 @@ param( [Parameter(Mandatory=$true)][string]$CommitString, - [Parameter(Mandatory=$true)][string]$DockerVersion + [Parameter(Mandatory=$true)][string]$DockerVersion, + [Parameter(Mandatory=$false)][string]$Platform ) $ErrorActionPreference = "Stop" @@ -43,6 +44,7 @@ const ( GitCommit string = "'+$CommitString+'" Version string = "'+$DockerVersion+'" BuildTime string = "'+$buildDateTime+'" + PlatformName string = "'+$Platform+'" ) // AUTOGENERATED FILE; see hack\make\.go-autogen.ps1 diff --git a/vendor/github.com/docker/docker/hack/make/.integration-test-helpers b/vendor/github.com/docker/docker/hack/make/.integration-test-helpers index abd1d0f30..3b1326dee 100644 --- a/vendor/github.com/docker/docker/hack/make/.integration-test-helpers +++ b/vendor/github.com/docker/docker/hack/make/.integration-test-helpers @@ -99,7 +99,6 @@ test_env() { HOME="$ABS_DEST/fake-HOME" \ PATH="$PATH" \ TEMP="$TEMP" \ - TEST_IMAGE_NAMESPACE="$TEST_IMAGE_NAMESPACE" \ TEST_CLIENT_BINARY="$TEST_CLIENT_BINARY" \ "$@" ) diff --git a/vendor/github.com/docker/docker/hack/make/test-integration-cli b/vendor/github.com/docker/docker/hack/make/test-integration-cli index 4cc79d095..480851e70 100755 --- a/vendor/github.com/docker/docker/hack/make/test-integration-cli +++ b/vendor/github.com/docker/docker/hack/make/test-integration-cli @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -e -echo "WARNING: test-integration-cli is DEREPCATED. Use test-integration." >&2 +echo "WARNING: test-integration-cli is DEPRECATED. Use test-integration." >&2 # TODO: remove this and exit 1 once CI has changed to use test-integration bundle test-integration diff --git a/vendor/github.com/docker/docker/hack/validate/gometalinter b/vendor/github.com/docker/docker/hack/validate/gometalinter index ae411e864..8f42597fc 100755 --- a/vendor/github.com/docker/docker/hack/validate/gometalinter +++ b/vendor/github.com/docker/docker/hack/validate/gometalinter @@ -6,6 +6,8 @@ SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # CI platforms differ, so per-platform GOMETALINTER_OPTS can be set # from a platform-specific Dockerfile, otherwise let's just set # (somewhat pessimistic) default of 10 minutes. +: ${GOMETALINTER_OPTS=--deadline=10m} + gometalinter \ - ${GOMETALINTER_OPTS:--deadine 10m} \ + ${GOMETALINTER_OPTS} \ --config $SCRIPTDIR/gometalinter.json ./... diff --git a/vendor/github.com/docker/docker/image/fs.go b/vendor/github.com/docker/docker/image/fs.go index 92cdb2662..68e052926 100644 --- a/vendor/github.com/docker/docker/image/fs.go +++ b/vendor/github.com/docker/docker/image/fs.go @@ -133,10 +133,7 @@ func (s *fs) Delete(dgst digest.Digest) error { if err := os.RemoveAll(s.metadataDir(dgst)); err != nil { return err } - if err := os.Remove(s.contentFile(dgst)); err != nil { - return err - } - return nil + return os.Remove(s.contentFile(dgst)) } // SetMetadata sets metadata for a given ID. It fails if there's no base file. diff --git a/vendor/github.com/docker/docker/image/store.go b/vendor/github.com/docker/docker/image/store.go index 04842857a..60f499c9f 100644 --- a/vendor/github.com/docker/docker/image/store.go +++ b/vendor/github.com/docker/docker/image/store.go @@ -3,7 +3,6 @@ package image import ( "encoding/json" "fmt" - "strings" "sync" "time" @@ -43,21 +42,19 @@ type imageMeta struct { type store struct { sync.RWMutex - ls LayerGetReleaser + lss map[string]LayerGetReleaser images map[ID]*imageMeta fs StoreBackend digestSet *digestset.Set - os string } -// NewImageStore returns new store object for given layer store -func NewImageStore(fs StoreBackend, os string, ls LayerGetReleaser) (Store, error) { +// NewImageStore returns new store object for given set of layer stores +func NewImageStore(fs StoreBackend, lss map[string]LayerGetReleaser) (Store, error) { is := &store{ - ls: ls, + lss: lss, images: make(map[ID]*imageMeta), fs: fs, digestSet: digestset.NewSet(), - os: os, } // load all current images and retain layers @@ -77,7 +74,10 @@ func (is *store) restore() error { } var l layer.Layer if chainID := img.RootFS.ChainID(); chainID != "" { - l, err = is.ls.Get(chainID) + if !system.IsOSSupported(img.OperatingSystem()) { + return system.ErrNotSupportedOperatingSystem + } + l, err = is.lss[img.OperatingSystem()].Get(chainID) if err != nil { return err } @@ -118,14 +118,6 @@ func (is *store) Create(config []byte) (ID, error) { return "", err } - // TODO @jhowardmsft - LCOW Support. This will need revisiting when coalescing the image stores. - // Integrity check - ensure we are creating something for the correct platform - if system.LCOWSupported() { - if strings.ToLower(img.OperatingSystem()) != strings.ToLower(is.os) { - return "", fmt.Errorf("cannot create entry for operating system %q in image store for operating system %q", img.OperatingSystem(), is.os) - } - } - // Must reject any config that references diffIDs from the history // which aren't among the rootfs layers. rootFSLayers := make(map[layer.DiffID]struct{}) @@ -160,7 +152,10 @@ func (is *store) Create(config []byte) (ID, error) { var l layer.Layer if layerID != "" { - l, err = is.ls.Get(layerID) + if !system.IsOSSupported(img.OperatingSystem()) { + return "", system.ErrNotSupportedOperatingSystem + } + l, err = is.lss[img.OperatingSystem()].Get(layerID) if err != nil { return "", errors.Wrapf(err, "failed to get layer %s", layerID) } @@ -229,6 +224,13 @@ func (is *store) Delete(id ID) ([]layer.Metadata, error) { if imageMeta == nil { return nil, fmt.Errorf("unrecognized image ID %s", id.String()) } + img, err := is.Get(id) + if err != nil { + return nil, fmt.Errorf("unrecognized image %s, %v", id.String(), err) + } + if !system.IsOSSupported(img.OperatingSystem()) { + return nil, fmt.Errorf("unsupported image operating system %q", img.OperatingSystem()) + } for id := range imageMeta.children { is.fs.DeleteMetadata(id.Digest(), "parent") } @@ -243,7 +245,7 @@ func (is *store) Delete(id ID) ([]layer.Metadata, error) { is.fs.Delete(id.Digest()) if imageMeta.layer != nil { - return is.ls.Release(imageMeta.layer) + return is.lss[img.OperatingSystem()].Release(imageMeta.layer) } return nil, nil } diff --git a/vendor/github.com/docker/docker/image/store_test.go b/vendor/github.com/docker/docker/image/store_test.go index 23a60a98f..4fe366047 100644 --- a/vendor/github.com/docker/docker/image/store_test.go +++ b/vendor/github.com/docker/docker/image/store_test.go @@ -26,7 +26,9 @@ func TestRestore(t *testing.T) { err = fs.SetMetadata(id2, "parent", []byte(id1)) assert.NoError(t, err) - is, err := NewImageStore(fs, runtime.GOOS, &mockLayerGetReleaser{}) + mlgrMap := make(map[string]LayerGetReleaser) + mlgrMap[runtime.GOOS] = &mockLayerGetReleaser{} + is, err := NewImageStore(fs, mlgrMap) assert.NoError(t, err) assert.Len(t, is.Map(), 2) @@ -143,7 +145,9 @@ func TestParentReset(t *testing.T) { func defaultImageStore(t *testing.T) (Store, func()) { fsBackend, cleanup := defaultFSStoreBackend(t) - store, err := NewImageStore(fsBackend, runtime.GOOS, &mockLayerGetReleaser{}) + mlgrMap := make(map[string]LayerGetReleaser) + mlgrMap[runtime.GOOS] = &mockLayerGetReleaser{} + store, err := NewImageStore(fsBackend, mlgrMap) assert.NoError(t, err) return store, cleanup diff --git a/vendor/github.com/docker/docker/image/tarexport/load.go b/vendor/github.com/docker/docker/image/tarexport/load.go index 81beaf4a7..a0cfc6420 100644 --- a/vendor/github.com/docker/docker/image/tarexport/load.go +++ b/vendor/github.com/docker/docker/image/tarexport/load.go @@ -90,11 +90,11 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool) } // On Windows, validate the platform, defaulting to windows if not present. - os := layer.OS(img.OS) + os := img.OS + if os == "" { + os = runtime.GOOS + } if runtime.GOOS == "windows" { - if os == "" { - os = "windows" - } if (os != "windows") && (os != "linux") { return fmt.Errorf("configuration for this image has an unsupported operating system: %s", os) } @@ -107,14 +107,14 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool) } r := rootFS r.Append(diffID) - newLayer, err := l.ls.Get(r.ChainID()) + newLayer, err := l.lss[os].Get(r.ChainID()) if err != nil { newLayer, err = l.loadLayer(layerPath, rootFS, diffID.String(), os, m.LayerSources[diffID], progressOutput) if err != nil { return err } } - defer layer.ReleaseAndLog(l.ls, newLayer) + defer layer.ReleaseAndLog(l.lss[os], newLayer) if expected, actual := diffID, newLayer.DiffID(); expected != actual { return fmt.Errorf("invalid diffID for layer %d: expected %q, got %q", i, expected, actual) } @@ -176,7 +176,7 @@ func (l *tarexporter) setParentID(id, parentID image.ID) error { return l.is.SetParent(id, parentID) } -func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string, os layer.OS, foreignSrc distribution.Descriptor, progressOutput progress.Output) (layer.Layer, error) { +func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string, os string, foreignSrc distribution.Descriptor, progressOutput progress.Output) (layer.Layer, error) { // We use system.OpenSequential to use sequential file access on Windows, avoiding // depleting the standby list. On Linux, this equates to a regular os.Open. rawTar, err := system.OpenSequential(filename) @@ -205,10 +205,10 @@ func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string, } defer inflatedLayerData.Close() - if ds, ok := l.ls.(layer.DescribableStore); ok { - return ds.RegisterWithDescriptor(inflatedLayerData, rootFS.ChainID(), os, foreignSrc) + if ds, ok := l.lss[os].(layer.DescribableStore); ok { + return ds.RegisterWithDescriptor(inflatedLayerData, rootFS.ChainID(), foreignSrc) } - return l.ls.Register(inflatedLayerData, rootFS.ChainID(), os) + return l.lss[os].Register(inflatedLayerData, rootFS.ChainID()) } func (l *tarexporter) setLoadedTag(ref reference.Named, imgID digest.Digest, outStream io.Writer) error { @@ -302,6 +302,9 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str if err := checkCompatibleOS(img.OS); err != nil { return err } + if img.OS == "" { + img.OS = runtime.GOOS + } var parentID image.ID if img.Parent != "" { @@ -335,7 +338,7 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str if err != nil { return err } - newLayer, err := l.loadLayer(layerPath, *rootFS, oldID, "", distribution.Descriptor{}, progressOutput) + newLayer, err := l.loadLayer(layerPath, *rootFS, oldID, img.OS, distribution.Descriptor{}, progressOutput) if err != nil { return err } @@ -356,7 +359,7 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str return err } - metadata, err := l.ls.Release(newLayer) + metadata, err := l.lss[img.OS].Release(newLayer) layer.LogReleaseMetadata(metadata) if err != nil { return err @@ -409,19 +412,18 @@ func checkValidParent(img, parent *image.Image) bool { return true } -func checkCompatibleOS(os string) error { - // TODO @jhowardmsft LCOW - revisit for simultaneous platforms - platform := runtime.GOOS - if system.LCOWSupported() { - platform = "linux" - } - // always compatible if the OS matches; also match an empty OS - if os == platform || os == "" { +func checkCompatibleOS(imageOS string) error { + // always compatible if the images OS matches the host OS; also match an empty image OS + if imageOS == runtime.GOOS || imageOS == "" { return nil } - // for compatibility, only fail if the image or runtime OS is Windows - if os == "windows" || platform == "windows" { - return fmt.Errorf("cannot load %s image on %s", os, platform) + // On non-Windows hosts, for compatibility, fail if the image is Windows. + if runtime.GOOS != "windows" && imageOS == "windows" { + return fmt.Errorf("cannot load %s image on %s", imageOS, runtime.GOOS) + } + // Finally, check the image OS is supported for the platform. + if err := system.ValidatePlatform(system.ParsePlatform(imageOS)); err != nil { + return fmt.Errorf("cannot load %s image on %s: %s", imageOS, runtime.GOOS, err) } return nil } diff --git a/vendor/github.com/docker/docker/image/tarexport/save.go b/vendor/github.com/docker/docker/image/tarexport/save.go index d304a54c3..15f12304a 100644 --- a/vendor/github.com/docker/docker/image/tarexport/save.go +++ b/vendor/github.com/docker/docker/image/tarexport/save.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "time" "github.com/docker/distribution" @@ -153,7 +154,11 @@ func (l *tarexporter) takeLayerReference(id image.ID, imgDescr *imageDescriptor) if topLayerID == "" { return nil } - layer, err := l.ls.Get(topLayerID) + os := img.OS + if os == "" { + os = runtime.GOOS + } + layer, err := l.lss[os].Get(topLayerID) if err != nil { return err } @@ -165,7 +170,11 @@ func (l *tarexporter) takeLayerReference(id image.ID, imgDescr *imageDescriptor) func (l *tarexporter) releaseLayerReferences(imgDescr map[image.ID]*imageDescriptor) error { for _, descr := range imgDescr { if descr.layerRef != nil { - l.ls.Release(descr.layerRef) + os := descr.image.OS + if os == "" { + os = runtime.GOOS + } + l.lss[os].Release(descr.layerRef) } } return nil @@ -356,11 +365,15 @@ func (s *saveSession) saveLayer(id layer.ChainID, legacyImg image.V1Image, creat // serialize filesystem layerPath := filepath.Join(outDir, legacyLayerFileName) - l, err := s.ls.Get(id) + operatingSystem := legacyImg.OS + if operatingSystem == "" { + operatingSystem = runtime.GOOS + } + l, err := s.lss[operatingSystem].Get(id) if err != nil { return distribution.Descriptor{}, err } - defer layer.ReleaseAndLog(s.ls, l) + defer layer.ReleaseAndLog(s.lss[operatingSystem], l) if oldPath, exists := s.diffIDPaths[l.DiffID()]; exists { relPath, err := filepath.Rel(outDir, oldPath) diff --git a/vendor/github.com/docker/docker/image/tarexport/tarexport.go b/vendor/github.com/docker/docker/image/tarexport/tarexport.go index f7fab74f5..f12259dd1 100644 --- a/vendor/github.com/docker/docker/image/tarexport/tarexport.go +++ b/vendor/github.com/docker/docker/image/tarexport/tarexport.go @@ -25,7 +25,7 @@ type manifestItem struct { type tarexporter struct { is image.Store - ls layer.Store + lss map[string]layer.Store rs refstore.Store loggerImgEvent LogImageEvent } @@ -37,10 +37,10 @@ type LogImageEvent interface { } // NewTarExporter returns new Exporter for tar packages -func NewTarExporter(is image.Store, ls layer.Store, rs refstore.Store, loggerImgEvent LogImageEvent) image.Exporter { +func NewTarExporter(is image.Store, lss map[string]layer.Store, rs refstore.Store, loggerImgEvent LogImageEvent) image.Exporter { return &tarexporter{ is: is, - ls: ls, + lss: lss, rs: rs, loggerImgEvent: loggerImgEvent, } diff --git a/vendor/github.com/docker/docker/integration-cli/check_test.go b/vendor/github.com/docker/docker/integration-cli/check_test.go index 49504c630..dd802fbc1 100644 --- a/vendor/github.com/docker/docker/integration-cli/check_test.go +++ b/vendor/github.com/docker/docker/integration-cli/check_test.go @@ -129,7 +129,7 @@ func (s *DockerRegistrySuite) SetUpTest(c *check.C) { testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon) s.reg = setupRegistry(c, false, "", "") s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) } @@ -163,7 +163,7 @@ func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) { testRequires(c, DaemonIsLinux, registry.Hosting, NotArm64, SameHostDaemon) s.reg = setupRegistry(c, true, "", "") s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) } @@ -197,7 +197,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) SetUpTest(c *check.C) { testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon) s.reg = setupRegistry(c, false, "htpasswd", "") s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) } @@ -232,7 +232,7 @@ func (s *DockerRegistryAuthTokenSuite) OnTimeout(c *check.C) { func (s *DockerRegistryAuthTokenSuite) SetUpTest(c *check.C) { testRequires(c, DaemonIsLinux, registry.Hosting, SameHostDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) } @@ -273,7 +273,7 @@ func (s *DockerDaemonSuite) OnTimeout(c *check.C) { func (s *DockerDaemonSuite) SetUpTest(c *check.C) { testRequires(c, DaemonIsLinux, SameHostDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) } @@ -331,7 +331,7 @@ func (s *DockerSwarmSuite) SetUpTest(c *check.C) { func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *daemon.Swarm { d := &daemon.Swarm{ Daemon: daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }), Port: defaultSwarmPort + s.portIndex, } diff --git a/vendor/github.com/docker/docker/integration-cli/daemon/daemon.go b/vendor/github.com/docker/docker/integration-cli/daemon/daemon.go index f6ad6559b..62150a1d2 100644 --- a/vendor/github.com/docker/docker/integration-cli/daemon/daemon.go +++ b/vendor/github.com/docker/docker/integration-cli/daemon/daemon.go @@ -348,11 +348,7 @@ func (d *Daemon) Kill() error { return err } - if err := os.Remove(fmt.Sprintf("%s/docker.pid", d.Folder)); err != nil { - return err - } - - return nil + return os.Remove(fmt.Sprintf("%s/docker.pid", d.Folder)) } // Pid returns the pid of the daemon @@ -459,11 +455,7 @@ out2: d.cmd.Wait() - if err := os.Remove(fmt.Sprintf("%s/docker.pid", d.Folder)); err != nil { - return err - } - - return nil + return os.Remove(fmt.Sprintf("%s/docker.pid", d.Folder)) } // Restart will restart the daemon by first stopping it and the starting it. diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_build_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_build_test.go index 3f43c9543..6da8e5bb8 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_build_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_build_test.go @@ -30,7 +30,7 @@ func (s *DockerSuite) TestBuildAPIDockerFileRemote(c *check.C) { testRequires(c, NotUserNamespace) var testD string - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { testD = `FROM busybox RUN find / -name ba* RUN find /tmp/` @@ -460,6 +460,7 @@ COPY file /file` assert.Equal(c, http.StatusOK, res.StatusCode) out, err := request.ReadBody(body) + require.NoError(c, err) ids := getImageIDsFromBuild(c, out) return ids[len(ids)-1] @@ -498,6 +499,7 @@ ADD file /file` assert.Equal(c, http.StatusOK, res.StatusCode) out, err := request.ReadBody(body) + require.NoError(c, err) ids := getImageIDsFromBuild(c, out) return ids[len(ids)-1] diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go index cd3566f4b..02e8e9f7d 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_containers_test.go @@ -1016,7 +1016,7 @@ func (s *DockerSuite) TestContainerAPIWait(c *check.C) { name := "test-api-wait" sleepCmd := "/bin/sleep" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { sleepCmd = "sleep" } dockerCmd(c, "run", "--name", name, "busybox", sleepCmd, "2") @@ -1216,7 +1216,7 @@ func (s *DockerSuite) TestContainerAPIDeleteRemoveVolume(c *check.C) { testRequires(c, SameHostDaemon) vol := "/testvolume" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { vol = `c:\testvolume` } @@ -1890,7 +1890,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) { var ( testImg string ) - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { testImg = "test-mount-config" buildImageSuccessfully(c, testImg, build.WithDockerfile(` FROM busybox @@ -1987,7 +1987,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) { } } - if testEnv.DaemonPlatform() != "windows" { // Windows does not support volume populate + if testEnv.OSType != "windows" { // Windows does not support volume populate cases = append(cases, []testCase{ { spec: mounttypes.Mount{Type: "volume", Target: destPath, VolumeOptions: &mounttypes.VolumeOptions{NoCopy: true}}, diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_containers_windows_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_containers_windows_test.go index 4cbe067cd..ae60cfec0 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_containers_windows_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_containers_windows_test.go @@ -47,7 +47,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsBindNamedPipe(c *check.C) { name := "test-bind-npipe" data := map[string]interface{}{ - "Image": testEnv.MinimalBaseImage(), + "Image": testEnv.PlatformDefaults.BaseImage, "Cmd": []string{"cmd", "/c", cmd}, "HostConfig": map[string]interface{}{"Mounts": []map[string]interface{}{{"Type": "npipe", "Source": hostPipeName, "Target": containerPipeName}}}, } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_images_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_images_test.go index fba69dc68..10cb52eeb 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_images_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_images_test.go @@ -80,7 +80,7 @@ func (s *DockerSuite) TestAPIImagesDelete(c *check.C) { c.Assert(err, checker.IsNil) defer cli.Close() - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { testRequires(c, Network) } name := "test-api-images-delete" @@ -104,7 +104,7 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) { c.Assert(err, checker.IsNil) defer cli.Close() - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { testRequires(c, Network) } name := "test-api-images-history" diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_info_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_info_test.go index 60ca4b928..e7d77f098 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_info_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_info_test.go @@ -1,13 +1,10 @@ package main import ( - "encoding/json" "net/http" "fmt" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" "github.com/docker/docker/integration-cli/checker" "github.com/docker/docker/integration-cli/request" @@ -48,25 +45,6 @@ func (s *DockerSuite) TestInfoAPI(c *check.C) { } } -// TestInfoAPIRuncCommit tests that dockerd is able to obtain RunC version -// information, and that the version matches the expected version -func (s *DockerSuite) TestInfoAPIRuncCommit(c *check.C) { - testRequires(c, DaemonIsLinux) // Windows does not have RunC version information - - res, body, err := request.Get("/v1.30/info") - c.Assert(res.StatusCode, checker.Equals, http.StatusOK) - c.Assert(err, checker.IsNil) - - b, err := request.ReadBody(body) - c.Assert(err, checker.IsNil) - - var i types.Info - - c.Assert(json.Unmarshal(b, &i), checker.IsNil) - c.Assert(i.RuncCommit.ID, checker.Not(checker.Equals), "N/A") - c.Assert(i.RuncCommit.ID, checker.Equals, i.RuncCommit.Expected) -} - func (s *DockerSuite) TestInfoAPIVersioned(c *check.C) { testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_inspect_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_inspect_test.go index 38f3f4dd8..52a889f08 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_inspect_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_inspect_test.go @@ -28,7 +28,7 @@ func (s *DockerSuite) TestInspectAPIContainerResponse(c *check.C) { var cases []acase - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { cases = []acase{ {"v1.25", append(keysBase, "Mounts")}, } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_logs_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_logs_test.go index 0672e328d..89c2865fc 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_logs_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_logs_test.go @@ -151,7 +151,7 @@ func (s *DockerSuite) TestLogsAPIUntilFutureFollow(c *check.C) { func (s *DockerSuite) TestLogsAPIUntil(c *check.C) { name := "logsuntil" - dockerCmd(c, "run", "--name", name, "busybox", "/bin/sh", "-c", "for i in $(seq 1 3); do echo log$i; sleep 0.5; done") + dockerCmd(c, "run", "--name", name, "busybox", "/bin/sh", "-c", "for i in $(seq 1 3); do echo log$i; sleep 1; done") client, err := request.NewClient() if err != nil { @@ -172,6 +172,8 @@ func (s *DockerSuite) TestLogsAPIUntil(c *check.C) { // Get timestamp of second log line allLogs := extractBody(c, types.ContainerLogsOptions{Timestamps: true, ShowStdout: true}) + c.Assert(len(allLogs), checker.GreaterOrEqualThan, 3) + t, err := time.Parse(time.RFC3339Nano, strings.Split(allLogs[1], " ")[0]) c.Assert(err, checker.IsNil) until := t.Format(time.RFC3339Nano) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_network_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_network_test.go index 2cdd2627a..f0c26e2d9 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_network_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_network_test.go @@ -328,9 +328,8 @@ func createNetwork(c *check.C, config types.NetworkCreateRequest, expectedStatus c.Assert(err, checker.IsNil) return nr.ID - } else { - return "" } + return "" } func connectNetwork(c *check.C, nid, cid string) { diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_stats_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_stats_test.go index 7c9de1c08..1818c3b4e 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_stats_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_stats_test.go @@ -39,7 +39,7 @@ func (s *DockerSuite) TestAPIStatsNoStreamGetCpu(c *check.C) { var cpuPercent = 0.0 - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { cpuDelta := float64(v.CPUStats.CPUUsage.TotalUsage - v.PreCPUStats.CPUUsage.TotalUsage) systemDelta := float64(v.CPUStats.SystemUsage - v.PreCPUStats.SystemUsage) cpuPercent = (cpuDelta / systemDelta) * float64(len(v.CPUStats.CPUUsage.PercpuUsage)) * 100.0 @@ -105,7 +105,7 @@ func (s *DockerSuite) TestAPIStatsNetworkStats(c *check.C) { // Retrieve the container address net := "bridge" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { net = "nat" } contIP := findContainerIP(c, id, net) @@ -153,7 +153,7 @@ func (s *DockerSuite) TestAPIStatsNetworkStats(c *check.C) { // On Linux, account for ARP. expRxPkts := preRxPackets + uint64(numPings) expTxPkts := preTxPackets + uint64(numPings) - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { expRxPkts++ expTxPkts++ } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_swarm_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_swarm_test.go index adb3885f3..a9b045803 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_swarm_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_swarm_test.go @@ -1031,7 +1031,7 @@ func (s *DockerSwarmSuite) TestAPINetworkInspectWithScope(c *check.C) { v := url.Values{} v.Set("scope", "local") - status, body, err = d.SockRequest("GET", "/networks/"+name+"?"+v.Encode(), nil) + status, _, err = d.SockRequest("GET", "/networks/"+name+"?"+v.Encode(), nil) c.Assert(err, checker.IsNil, check.Commentf(string(out))) c.Assert(status, checker.Equals, http.StatusNotFound, check.Commentf(string(out))) } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_api_test.go b/vendor/github.com/docker/docker/integration-cli/docker_api_test.go index af189b9d0..e5b454fbf 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_api_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_api_test.go @@ -33,7 +33,7 @@ func (s *DockerSuite) TestAPIGetEnabledCORS(c *check.C) { } func (s *DockerSuite) TestAPIClientVersionOldNotSupported(c *check.C) { - if testEnv.DaemonPlatform() != runtime.GOOS { + if testEnv.OSType != runtime.GOOS { c.Skip("Daemon platform doesn't match test platform") } if api.MinVersion == api.DefaultVersion { diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go index 89e62c14e..dda77c94a 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_build_test.go @@ -40,7 +40,7 @@ func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) { func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) { name := "testbuildshcmdjsonentrypoint" expected := "/bin/sh -c echo test" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = "cmd /S /C echo test" } @@ -78,7 +78,7 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) { var volumePath string - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { volumePath = "c:/quux" } else { volumePath = "/quux" @@ -135,7 +135,7 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementWorkdir(c *check.C) { res := inspectFieldJSON(c, name, "Config.WorkingDir") expected := `"/work"` - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = `"C:\\work"` } if res != expected { @@ -400,20 +400,27 @@ func (s *DockerSuite) TestBuildLastModified(c *check.C) { defer server.Close() var out, out2 string + var args []string + // Temopray workaround for #35963. Will remove this when that issue fixed + if runtime.GOARCH == "amd64" { + args = []string{"run", name, "ls", "-le", "/file"} + } else { + args = []string{"run", name, "ls", "-l", "--full-time", "/file"} + } dFmt := `FROM busybox ADD %s/file /` dockerfile := fmt.Sprintf(dFmt, server.URL()) cli.BuildCmd(c, name, build.WithoutCache, build.WithDockerfile(dockerfile)) - out = cli.DockerCmd(c, "run", name, "ls", "-le", "/file").Combined() + out = cli.DockerCmd(c, args...).Combined() // Build it again and make sure the mtime of the file didn't change. // Wait a few seconds to make sure the time changed enough to notice time.Sleep(2 * time.Second) cli.BuildCmd(c, name, build.WithoutCache, build.WithDockerfile(dockerfile)) - out2 = cli.DockerCmd(c, "run", name, "ls", "-le", "/file").Combined() + out2 = cli.DockerCmd(c, args...).Combined() if out != out2 { c.Fatalf("MTime changed:\nOrigin:%s\nNew:%s", out, out2) @@ -428,7 +435,7 @@ ADD %s/file /` dockerfile = fmt.Sprintf(dFmt, server.URL()) cli.BuildCmd(c, name, build.WithoutCache, build.WithDockerfile(dockerfile)) - out2 = cli.DockerCmd(c, "run", name, "ls", "-le", "/file").Combined() + out2 = cli.DockerCmd(c, args...).Combined() if out == out2 { c.Fatalf("MTime didn't change:\nOrigin:%s\nNew:%s", out, out2) @@ -603,7 +610,7 @@ RUN [ $(cat "/test dir/test_file6") = 'test6' ]`, command, command, command, com func (s *DockerSuite) TestBuildCopyFileWithWhitespaceOnWindows(c *check.C) { testRequires(c, DaemonIsWindows) - dockerfile := `FROM ` + testEnv.MinimalBaseImage() + ` + dockerfile := `FROM ` + testEnv.PlatformDefaults.BaseImage + ` RUN mkdir "C:/test dir" RUN mkdir "C:/test_dir" COPY [ "test file1", "/test_file1" ] @@ -1304,7 +1311,7 @@ func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) { expectedFinal string ) - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected1 = `C:/` expected2 = `C:/test1` expected3 = `C:/test2` @@ -1383,7 +1390,7 @@ func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) { name := "testbuildworkdirwithenvvariables" var expected string - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = `C:\test1\test2` } else { expected = `/test1/test2` @@ -1405,7 +1412,7 @@ func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) { testRequires(c, NotUserNamespace) var expected string - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = `C:/test1/test2` } else { expected = `/test1/test2` @@ -1514,7 +1521,7 @@ func (s *DockerSuite) TestBuildContextCleanup(c *check.C) { testRequires(c, SameHostDaemon) name := "testbuildcontextcleanup" - entries, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp")) + entries, err := ioutil.ReadDir(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "tmp")) if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) } @@ -1522,7 +1529,7 @@ func (s *DockerSuite) TestBuildContextCleanup(c *check.C) { buildImageSuccessfully(c, name, build.WithDockerfile(`FROM `+minimalBaseImage()+` ENTRYPOINT ["/bin/echo"]`)) - entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp")) + entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "tmp")) if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) } @@ -1536,7 +1543,7 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) { testRequires(c, SameHostDaemon) name := "testbuildcontextcleanup" - entries, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp")) + entries, err := ioutil.ReadDir(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "tmp")) if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) } @@ -1546,7 +1553,7 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) { ExitCode: 1, }) - entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp")) + entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "tmp")) if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) } @@ -2189,7 +2196,7 @@ func (s *DockerSuite) TestBuildAddFileNotFound(c *check.C) { name := "testbuildaddnotfound" expected := "foo: no such file or directory" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = "foo: The system cannot find the file specified" } @@ -2243,7 +2250,7 @@ func (s *DockerSuite) TestBuildOnBuild(c *check.C) { // gh #2446 func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) { makeLink := `ln -s /foo /bar` - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { makeLink = `mklink /D C:\bar C:\foo` } name := "testbuildaddtosymlinkdest" @@ -3198,7 +3205,7 @@ func (s *DockerSuite) TestBuildCmdShDashC(c *check.C) { res := inspectFieldJSON(c, name, "Config.Cmd") expected := `["/bin/sh","-c","echo cmd"]` - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = `["cmd","/S","/C","echo cmd"]` } if res != expected { @@ -3271,7 +3278,7 @@ func (s *DockerSuite) TestBuildEntrypointCanBeOverriddenByChildInspect(c *check. expected = `["/bin/sh","-c","echo quux"]` ) - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = `["cmd","/S","/C","echo quux"]` } @@ -3328,7 +3335,7 @@ func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) { // it should barf on it. name := "testbuildsinglequotefails" expectedExitCode := 2 - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expectedExitCode = 127 } @@ -3344,7 +3351,7 @@ func (s *DockerSuite) TestBuildVerboseOut(c *check.C) { name := "testbuildverboseout" expected := "\n123\n" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = "\n123\r\n" } @@ -3360,7 +3367,7 @@ func (s *DockerSuite) TestBuildWithTabs(c *check.C) { res := inspectFieldJSON(c, name, "ContainerConfig.Cmd") expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]` expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected1 = `["cmd","/S","/C","echo\tone\t\ttwo"]` expected2 = `["cmd","/S","/C","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates } @@ -3532,7 +3539,17 @@ func (s *DockerSuite) TestBuildNotVerboseFailureRemote(c *check.C) { result.Assert(c, icmd.Expected{ ExitCode: 1, }) - if strings.TrimSpace(quietResult.Stderr()) != strings.TrimSpace(result.Combined()) { + + // An error message should contain name server IP and port, like this: + // "dial tcp: lookup something.invalid on 172.29.128.11:53: no such host" + // The IP:port need to be removed in order to not trigger a test failur + // when more than one nameserver is configured. + // While at it, also strip excessive newlines. + normalize := func(msg string) string { + return strings.TrimSpace(regexp.MustCompile("[1-9][0-9.]+:[0-9]+").ReplaceAllLiteralString(msg, "")) + } + + if normalize(quietResult.Stderr()) != normalize(result.Combined()) { c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", name, quietResult.Stderr(), result.Combined())) } } @@ -3545,7 +3562,7 @@ func (s *DockerSuite) TestBuildStderr(c *check.C) { result.Assert(c, icmd.Success) // Windows to non-Windows should have a security warning - if runtime.GOOS == "windows" && testEnv.DaemonPlatform() != "windows" && !strings.Contains(result.Stdout(), "SECURITY WARNING:") { + if runtime.GOOS == "windows" && testEnv.OSType != "windows" && !strings.Contains(result.Stdout(), "SECURITY WARNING:") { c.Fatalf("Stdout contains unexpected output: %q", result.Stdout()) } @@ -3657,7 +3674,7 @@ func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) { volName = "/foo" ) - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { volName = "C:/foo" } @@ -3958,7 +3975,7 @@ RUN echo " \ expected := "\n foo \n" // Windows uses the builtin echo, which preserves quotes - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = "\" foo \"" } @@ -3992,7 +4009,7 @@ func (s *DockerSuite) TestBuildMissingArgs(c *check.C) { "INSERT": {}, } - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { skipCmds = map[string]struct{}{ "CMD": {}, "RUN": {}, @@ -4125,7 +4142,7 @@ func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) { name := "testbuildbadrunerrmsg" shell := "/bin/sh -c" exitCode := 127 - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { shell = "cmd /S /C" // architectural - Windows has to start the container to determine the exe is bad, Linux does not exitCode = 1 @@ -4277,7 +4294,7 @@ func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *che func (s *DockerSuite) TestBuildNullStringInAddCopyVolume(c *check.C) { name := "testbuildnullstringinaddcopyvolume" volName := "nullvolume" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { volName = `C:\\nullvolume` } @@ -4317,7 +4334,7 @@ func (s *DockerSuite) TestBuildBuildTimeArg(c *check.C) { envKey := "foo" envVal := "bar" var dockerfile string - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { // Bugs in Windows busybox port - use the default base image and native cmd stuff dockerfile = fmt.Sprintf(`FROM `+minimalBaseImage()+` ARG %s @@ -4860,7 +4877,7 @@ func (s *DockerSuite) TestBuildBuildTimeArgDefinitionWithNoEnvInjection(c *check } } -func (s *DockerSuite) TestBuildBuildTimeArgMultipleFrom(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageArg(c *check.C) { imgName := "multifrombldargtest" dockerfile := `FROM busybox ARG foo=abc @@ -4884,7 +4901,7 @@ func (s *DockerSuite) TestBuildBuildTimeArgMultipleFrom(c *check.C) { c.Assert(result.Stdout(), checker.Contains, "bar=def") } -func (s *DockerSuite) TestBuildBuildTimeFromArgMultipleFrom(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageGlobalArg(c *check.C) { imgName := "multifrombldargtest" dockerfile := `ARG tag=nosuchtag FROM busybox:${tag} @@ -4909,7 +4926,7 @@ func (s *DockerSuite) TestBuildBuildTimeFromArgMultipleFrom(c *check.C) { c.Assert(result.Stdout(), checker.Contains, "tag=latest") } -func (s *DockerSuite) TestBuildBuildTimeUnusedArgMultipleFrom(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageUnusedArg(c *check.C) { imgName := "multifromunusedarg" dockerfile := `FROM busybox ARG foo @@ -4932,7 +4949,7 @@ func (s *DockerSuite) TestBuildBuildTimeUnusedArgMultipleFrom(c *check.C) { func (s *DockerSuite) TestBuildNoNamedVolume(c *check.C) { volName := "testname:/foo" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { volName = "testname:C:\\foo" } dockerCmd(c, "run", "-v", volName, "busybox", "sh", "-c", "touch /foo/oops") @@ -5138,7 +5155,7 @@ func (s *DockerSuite) TestBuildWorkdirWindowsPath(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildworkdirwindowspath" buildImageSuccessfully(c, name, build.WithDockerfile(` - FROM `+testEnv.MinimalBaseImage()+` + FROM `+testEnv.PlatformDefaults.BaseImage+` RUN mkdir C:\\work WORKDIR C:\\work RUN if "%CD%" NEQ "C:\work" exit -1 @@ -5727,7 +5744,7 @@ func (s *DockerSuite) TestBuildCacheFrom(c *check.C) { c.Assert(layers1[len(layers1)-1], checker.Not(checker.Equals), layers2[len(layers1)-1]) } -func (s *DockerSuite) TestBuildCacheMultipleFrom(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageCache(c *check.C) { testRequires(c, DaemonIsLinux) // All tests that do save are skipped in windows dockerfile := ` FROM busybox @@ -5888,7 +5905,7 @@ func (s *DockerSuite) TestBuildContChar(c *check.C) { c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi \\\\\n") } -func (s *DockerSuite) TestBuildCopyFromPreviousRootFS(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageCopyFromSyntax(c *check.C) { dockerfile := ` FROM busybox AS first COPY foo bar @@ -5946,7 +5963,7 @@ func (s *DockerSuite) TestBuildCopyFromPreviousRootFS(c *check.C) { cli.DockerCmd(c, "run", "build4", "cat", "baz").Assert(c, icmd.Expected{Out: "pqr"}) } -func (s *DockerSuite) TestBuildCopyFromPreviousRootFSErrors(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageCopyFromErrors(c *check.C) { testCases := []struct { dockerfile string expectedError string @@ -5993,7 +6010,7 @@ func (s *DockerSuite) TestBuildCopyFromPreviousRootFSErrors(c *check.C) { } } -func (s *DockerSuite) TestBuildCopyFromPreviousFrom(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageMultipleBuilds(c *check.C) { dockerfile := ` FROM busybox COPY foo bar` @@ -6026,7 +6043,7 @@ func (s *DockerSuite) TestBuildCopyFromPreviousFrom(c *check.C) { c.Assert(strings.TrimSpace(out), check.Equals, "def") } -func (s *DockerSuite) TestBuildCopyFromImplicitFrom(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageImplicitFrom(c *check.C) { dockerfile := ` FROM busybox COPY --from=busybox /etc/passwd /mypasswd @@ -6053,7 +6070,7 @@ func (s *DockerSuite) TestBuildCopyFromImplicitFrom(c *check.C) { } } -func (s *DockerRegistrySuite) TestBuildCopyFromImplicitPullingFrom(c *check.C) { +func (s *DockerRegistrySuite) TestBuildMultiStageImplicitPull(c *check.C) { repoName := fmt.Sprintf("%v/dockercli/testf", privateRegistryURL) dockerfile := ` @@ -6083,7 +6100,7 @@ func (s *DockerRegistrySuite) TestBuildCopyFromImplicitPullingFrom(c *check.C) { cli.Docker(cli.Args("run", "build1", "cat", "baz")).Assert(c, icmd.Expected{Out: "abc"}) } -func (s *DockerSuite) TestBuildFromPreviousBlock(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageNameVariants(c *check.C) { dockerfile := ` FROM busybox as foo COPY foo / @@ -6094,7 +6111,7 @@ func (s *DockerSuite) TestBuildFromPreviousBlock(c *check.C) { FROM foo COPY --from=foo1 foo f1 COPY --from=FOo2 foo f2 - ` // foo2 case also tests that names are canse insensitive + ` // foo2 case also tests that names are case insensitive ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), fakecontext.WithFiles(map[string]string{ @@ -6108,7 +6125,7 @@ func (s *DockerSuite) TestBuildFromPreviousBlock(c *check.C) { cli.Docker(cli.Args("run", "build1", "cat", "f2")).Assert(c, icmd.Expected{Out: "bar2"}) } -func (s *DockerTrustSuite) TestCopyFromTrustedBuild(c *check.C) { +func (s *DockerTrustSuite) TestBuildMultiStageTrusted(c *check.C) { img1 := s.setupTrustedImage(c, "trusted-build1") img2 := s.setupTrustedImage(c, "trusted-build2") dockerFile := fmt.Sprintf(` @@ -6130,10 +6147,10 @@ func (s *DockerTrustSuite) TestCopyFromTrustedBuild(c *check.C) { dockerCmdWithResult("run", name, "cat", "bar").Assert(c, icmd.Expected{Out: "ok"}) } -func (s *DockerSuite) TestBuildCopyFromPreviousFromWindows(c *check.C) { +func (s *DockerSuite) TestBuildMultiStageMultipleBuildsWindows(c *check.C) { testRequires(c, DaemonIsWindows) dockerfile := ` - FROM ` + testEnv.MinimalBaseImage() + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` COPY foo c:\\bar` ctx := fakecontext.New(c, "", fakecontext.WithDockerfile(dockerfile), @@ -6146,7 +6163,7 @@ func (s *DockerSuite) TestBuildCopyFromPreviousFromWindows(c *check.C) { dockerfile = ` FROM build1:latest - FROM ` + testEnv.MinimalBaseImage() + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` COPY --from=0 c:\\bar / COPY foo /` ctx = fakecontext.New(c, "", @@ -6167,8 +6184,8 @@ func (s *DockerSuite) TestBuildCopyFromPreviousFromWindows(c *check.C) { func (s *DockerSuite) TestBuildCopyFromForbidWindowsSystemPaths(c *check.C) { testRequires(c, DaemonIsWindows) dockerfile := ` - FROM ` + testEnv.MinimalBaseImage() + ` - FROM ` + testEnv.MinimalBaseImage() + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` COPY --from=0 %s c:\\oscopy ` exp := icmd.Expected{ @@ -6184,8 +6201,8 @@ func (s *DockerSuite) TestBuildCopyFromForbidWindowsSystemPaths(c *check.C) { func (s *DockerSuite) TestBuildCopyFromForbidWindowsRelativePaths(c *check.C) { testRequires(c, DaemonIsWindows) dockerfile := ` - FROM ` + testEnv.MinimalBaseImage() + ` - FROM ` + testEnv.MinimalBaseImage() + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` COPY --from=0 %s c:\\oscopy ` exp := icmd.Expected{ @@ -6202,9 +6219,9 @@ func (s *DockerSuite) TestBuildCopyFromForbidWindowsRelativePaths(c *check.C) { func (s *DockerSuite) TestBuildCopyFromWindowsIsCaseInsensitive(c *check.C) { testRequires(c, DaemonIsWindows) dockerfile := ` - FROM ` + testEnv.MinimalBaseImage() + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` COPY foo / - FROM ` + testEnv.MinimalBaseImage() + ` + FROM ` + testEnv.PlatformDefaults.BaseImage + ` COPY --from=0 c:\\fOo c:\\copied RUN type c:\\copied ` @@ -6218,7 +6235,7 @@ func (s *DockerSuite) TestBuildCopyFromWindowsIsCaseInsensitive(c *check.C) { } // #33176 -func (s *DockerSuite) TestBuildCopyFromResetScratch(c *check.C) { +func (s *DockerSuite) TestBuildMulitStageResetScratch(c *check.C) { testRequires(c, DaemonIsLinux) dockerfile := ` @@ -6284,7 +6301,7 @@ func (s *DockerSuite) TestBuildOpaqueDirectory(c *check.C) { func (s *DockerSuite) TestBuildWindowsUser(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildwindowsuser" - buildImage(name, build.WithDockerfile(`FROM `+testEnv.MinimalBaseImage()+` + buildImage(name, build.WithDockerfile(`FROM `+testEnv.PlatformDefaults.BaseImage+` RUN net user user /add USER user RUN set username @@ -6315,7 +6332,7 @@ func (s *DockerSuite) TestBuildWindowsEnvCaseInsensitive(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildwindowsenvcaseinsensitive" buildImageSuccessfully(c, name, build.WithDockerfile(` - FROM `+testEnv.MinimalBaseImage()+` + FROM `+testEnv.PlatformDefaults.BaseImage+` ENV FOO=bar foo=baz `)) res := inspectFieldJSON(c, name, "Config.Env") @@ -6335,7 +6352,7 @@ WORKDIR /foo/bar // The Windows busybox image has a blank `cmd` lookingFor := `["sh"]` - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { lookingFor = "null" } c.Assert(strings.TrimSpace(out), checker.Equals, lookingFor) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_by_digest_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_by_digest_test.go index 3a974cfad..2d5dd486e 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_by_digest_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_by_digest_test.go @@ -635,7 +635,7 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) { // digest verification for the target layer digest. // Remove distribution cache to force a re-pull of the blobs - if err := os.RemoveAll(filepath.Join(testEnv.DockerBasePath(), "image", s.d.StorageDriver(), "distribution")); err != nil { + if err := os.RemoveAll(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "image", s.d.StorageDriver(), "distribution")); err != nil { c.Fatalf("error clearing distribution cache: %v", err) } @@ -678,7 +678,7 @@ func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) { // digest verification for the target layer digest. // Remove distribution cache to force a re-pull of the blobs - if err := os.RemoveAll(filepath.Join(testEnv.DockerBasePath(), "image", s.d.StorageDriver(), "distribution")); err != nil { + if err := os.RemoveAll(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "image", s.d.StorageDriver(), "distribution")); err != nil { c.Fatalf("error clearing distribution cache: %v", err) } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_commit_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_commit_test.go index 58a50ce0b..b0f21cef5 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_commit_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_commit_test.go @@ -121,11 +121,19 @@ func (s *DockerSuite) TestCommitChange(c *check.C) { "test", "test-commit") imageID = strings.TrimSpace(imageID) + // The ordering here is due to `PATH` being overridden from the container's + // ENV. On windows, the container doesn't have a `PATH` ENV variable so + // the ordering is the same as the cli. + expectedEnv := "[PATH=/foo DEBUG=true test=1]" + if testEnv.OSType == "windows" { + expectedEnv = "[DEBUG=true test=1 PATH=/foo]" + } + prefix, slash := getPrefixAndSlashFromDaemonPlatform() prefix = strings.ToUpper(prefix) // Force C: as that's how WORKDIR is normalized on Windows expected := map[string]string{ "Config.ExposedPorts": "map[8080/tcp:{}]", - "Config.Env": "[DEBUG=true test=1 PATH=/foo]", + "Config.Env": expectedEnv, "Config.Labels": "map[foo:bar]", "Config.Cmd": "[/bin/sh]", "Config.WorkingDir": prefix + slash + "opt", diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_test.go index 57a850c42..24c1fe228 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_test.go @@ -2,6 +2,7 @@ package main import ( "os" + "runtime" "strings" "github.com/docker/docker/integration-cli/checker" @@ -35,7 +36,22 @@ func (s *DockerSuite) TestCpToErrSrcNotExists(c *check.C) { c.Assert(os.IsNotExist(srcStatErr), checker.True) err := runDockerCp(c, srcPath, dstPath, nil) - c.Assert(strings.ToLower(err.Error()), checker.Contains, strings.ToLower(srcStatErr.Error())) + if runtime.GOOS == "windows" { + // Go 1.9+ on Windows returns a different error for `os.Stat()`, see + // https://github.com/golang/go/commit/6144c7270e5812d9de8fb97456ee4e5ae657fcbb#diff-f63e1a4b4377b2fe0b05011db3df9599 + // + // Go 1.8: CreateFile C:\not-exist: The system cannot find the file specified. + // Go 1.9: GetFileAttributesEx C:\not-exist: The system cannot find the file specified. + // + // Due to the CLI using a different version than the daemon, comparing the + // error message won't work, so just hard-code the common part here. + // + // TODO this should probably be a test in the CLI repository instead + c.Assert(strings.ToLower(err.Error()), checker.Contains, "cannot find the file specified") + c.Assert(strings.ToLower(err.Error()), checker.Contains, strings.ToLower(tmpDir)) + } else { + c.Assert(strings.ToLower(err.Error()), checker.Contains, strings.ToLower(srcStatErr.Error())) + } } // Test for error when SRC ends in a trailing diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_unix_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_unix_test.go index fa55b6ee2..8f830dcf9 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_unix_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_cp_to_container_unix_test.go @@ -64,7 +64,7 @@ func (s *DockerSuite) TestCpCheckDestOwnership(c *check.C) { } func getRootUIDGID() (int, int, error) { - uidgid := strings.Split(filepath.Base(testEnv.DockerBasePath()), ".") + uidgid := strings.Split(filepath.Base(testEnv.DaemonInfo.DockerRootDir), ".") if len(uidgid) == 1 { //user namespace remapping is not turned on; return 0 return 0, 0, nil diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_create_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_create_test.go index f5fe0da7f..448af9f19 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_create_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_create_test.go @@ -60,7 +60,7 @@ func (s *DockerSuite) TestCreateArgs(c *check.C) { // Make sure we can grow the container's rootfs at creation time. func (s *DockerSuite) TestCreateGrowRootfs(c *check.C) { // Windows and Devicemapper support growing the rootfs - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { testRequires(c, Devicemapper) } out, _ := dockerCmd(c, "create", "--storage-opt", "size=120G", "busybox") @@ -224,8 +224,8 @@ func (s *DockerSuite) TestCreateLabelFromImage(c *check.C) { func (s *DockerSuite) TestCreateHostnameWithNumber(c *check.C) { image := "busybox" // Busybox on Windows does not implement hostname command - if testEnv.DaemonPlatform() == "windows" { - image = testEnv.MinimalBaseImage() + if testEnv.OSType == "windows" { + image = testEnv.PlatformDefaults.BaseImage } out, _ := dockerCmd(c, "run", "-h", "web.0", image, "hostname") c.Assert(strings.TrimSpace(out), checker.Equals, "web.0", check.Commentf("hostname not set, expected `web.0`, got: %s", out)) @@ -268,7 +268,6 @@ func (s *DockerSuite) TestCreateByImageID(c *check.C) { dockerCmd(c, "create", imageID) dockerCmd(c, "create", truncatedImageID) - dockerCmd(c, "create", fmt.Sprintf("%s:%s", imageName, truncatedImageID)) // Ensure this fails out, exit, _ := dockerCmdWithError("create", fmt.Sprintf("%s:%s", imageName, imageID)) @@ -280,7 +279,10 @@ func (s *DockerSuite) TestCreateByImageID(c *check.C) { c.Fatalf(`Expected %q in output; got: %s`, expected, out) } - out, exit, _ = dockerCmdWithError("create", fmt.Sprintf("%s:%s", "wrongimage", truncatedImageID)) + if i := strings.IndexRune(imageID, ':'); i >= 0 { + imageID = imageID[i+1:] + } + out, exit, _ = dockerCmdWithError("create", fmt.Sprintf("%s:%s", "wrongimage", imageID)) if exit == 0 { c.Fatalf("expected non-zero exit code; received %d", exit) } @@ -376,7 +378,7 @@ func (s *DockerSuite) TestCreateWithWorkdir(c *check.C) { dockerCmd(c, "create", "--name", name, "-w", dir, "busybox") // Windows does not create the workdir until the container is started - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { dockerCmd(c, "start", name) } dockerCmd(c, "cp", fmt.Sprintf("%s:%s", name, dir), prefix+slash+"tmp") diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_daemon_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_daemon_test.go index 6865b9280..d6d2ef7ed 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_daemon_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_daemon_test.go @@ -467,9 +467,8 @@ func (s *DockerDaemonSuite) TestDaemonIPv6HostMode(c *check.C) { c.Assert(err, checker.IsNil, check.Commentf("Could not run container: %s, %v", out, err)) out, err = s.d.Cmd("exec", "hostcnt", "ip", "-6", "addr", "show", "docker0") - out = strings.Trim(out, " \r\n'") - - c.Assert(out, checker.Contains, "2001:db8:2::1") + c.Assert(err, checker.IsNil) + c.Assert(strings.Trim(out, " \r\n'"), checker.Contains, "2001:db8:2::1") } func (s *DockerDaemonSuite) TestDaemonLogLevelWrong(c *check.C) { @@ -1434,24 +1433,30 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithSocketAsVolume(c *check.C) { // A subsequent daemon restart should clean up said mounts. func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *check.C) { d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) d.StartWithBusybox(c) out, err := d.Cmd("run", "-d", "busybox", "top") c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) id := strings.TrimSpace(out) - c.Assert(d.Signal(os.Kill), check.IsNil) + + // If there are no mounts with container id visible from the host + // (as those are in container's own mount ns), there is nothing + // to check here and the test should be skipped. mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) + if !strings.Contains(string(mountOut), id) { + d.Stop(c) + c.Skip("no container mounts visible in host ns") + } - // container mounts should exist even after daemon has crashed. - comment := check.Commentf("%s should stay mounted from older daemon start:\nDaemon root repository %s\n%s", id, d.Root, mountOut) - c.Assert(strings.Contains(string(mountOut), id), check.Equals, true, comment) + // kill the daemon + c.Assert(d.Kill(), check.IsNil) // kill the container icmd.RunCommand(ctrBinary, "--address", "/var/run/docker/containerd/docker-containerd.sock", - "--namespace", moby_daemon.MainNamespace, "tasks", "kill", id).Assert(c, icmd.Success) + "--namespace", moby_daemon.ContainersNamespace, "tasks", "kill", id).Assert(c, icmd.Success) // restart daemon. d.Restart(c) @@ -1459,7 +1464,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *chec // Now, container mounts should be gone. mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) - comment = check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, d.Root, mountOut) + comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, d.Root, mountOut) c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) d.Stop(c) @@ -1468,7 +1473,7 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonAndContainerKill(c *chec // os.Interrupt should perform a graceful daemon shutdown and hence cleanup mounts. func (s *DockerDaemonSuite) TestCleanupMountsAfterGracefulShutdown(c *check.C) { d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) d.StartWithBusybox(c) @@ -1689,7 +1694,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartLocalVolumes(c *check.C) { // FIXME(vdemeester) should be a unit test func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) { d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) c.Assert(d.StartWithError("--log-driver=syslog", "--log-opt", "syslog-address=corrupted:42"), check.NotNil) expected := "Failed to set log opts: syslog-address should be in form proto://address" @@ -1699,7 +1704,7 @@ func (s *DockerDaemonSuite) TestDaemonCorruptedLogDriverAddress(c *check.C) { // FIXME(vdemeester) should be a unit test func (s *DockerDaemonSuite) TestDaemonCorruptedFluentdAddress(c *check.C) { d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) c.Assert(d.StartWithError("--log-driver=fluentd", "--log-opt", "fluentd-address=corrupted:c"), check.NotNil) expected := "Failed to set log opts: invalid fluentd-address corrupted:c: " @@ -2011,7 +2016,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithKilledRunningContainer(t *check // kill the container icmd.RunCommand(ctrBinary, "--address", "/var/run/docker/containerd/docker-containerd.sock", - "--namespace", moby_daemon.MainNamespace, "tasks", "kill", cid).Assert(t, icmd.Success) + "--namespace", moby_daemon.ContainersNamespace, "tasks", "kill", cid).Assert(t, icmd.Success) // Give time to containerd to process the command if we don't // the exit event might be received after we do the inspect @@ -2047,13 +2052,18 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *check.C) { c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) id := strings.TrimSpace(out) - c.Assert(s.d.Signal(os.Kill), check.IsNil) + // kill the daemon + c.Assert(s.d.Kill(), check.IsNil) + + // Check if there are mounts with container id visible from the host. + // If not, those mounts exist in container's own mount ns, and so + // the following check for mounts being cleared is pointless. + skipMountCheck := false mountOut, err := ioutil.ReadFile("/proc/self/mountinfo") c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) - - // container mounts should exist even after daemon has crashed. - comment := check.Commentf("%s should stay mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.Root, mountOut) - c.Assert(strings.Contains(string(mountOut), id), check.Equals, true, comment) + if !strings.Contains(string(mountOut), id) { + skipMountCheck = true + } // restart daemon. s.d.Start(c, "--live-restore") @@ -2070,10 +2080,13 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *check.C) { out, err = s.d.Cmd("stop", id) c.Assert(err, check.IsNil, check.Commentf("Output: %s", out)) + if skipMountCheck { + return + } // Now, container mounts should be gone. mountOut, err = ioutil.ReadFile("/proc/self/mountinfo") c.Assert(err, check.IsNil, check.Commentf("Output: %s", mountOut)) - comment = check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.Root, mountOut) + comment := check.Commentf("%s is still mounted from older daemon start:\nDaemon root repository %s\n%s", id, s.d.Root, mountOut) c.Assert(strings.Contains(string(mountOut), id), check.Equals, false, comment) } @@ -2106,7 +2119,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *che result := icmd.RunCommand( ctrBinary, "--address", "/var/run/docker/containerd/docker-containerd.sock", - "--namespace", moby_daemon.MainNamespace, + "--namespace", moby_daemon.ContainersNamespace, "tasks", "resume", cid) result.Assert(t, icmd.Success) @@ -3068,7 +3081,7 @@ func (s *DockerDaemonSuite) TestDaemonIpcModeShareableFromConfig(c *check.C) { func testDaemonStartIpcMode(c *check.C, from, mode string, valid bool) { d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) c.Logf("Checking IpcMode %s set from %s\n", mode, from) var serr error diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_diff_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_diff_test.go index 3e95a7378..614beee43 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_diff_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_diff_test.go @@ -20,7 +20,7 @@ func (s *DockerSuite) TestDiffFilenameShownInOutput(c *check.C) { // a "Files/" prefix. containerID := strings.TrimSpace(out) lookingFor := "A /foo/bar" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { cli.WaitExited(c, containerID, 60*time.Second) lookingFor = "C Files/foo/bar" } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_events_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_events_test.go index dff54a446..be91087b6 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_events_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_events_test.go @@ -81,50 +81,6 @@ func (s *DockerSuite) TestEventsUntag(c *check.C) { } } -func (s *DockerSuite) TestEventsLimit(c *check.C) { - // Windows: Limit to 4 goroutines creating containers in order to prevent - // timeouts creating so many containers simultaneously. This is a due to - // a bug in the Windows platform. It will be fixed in a Windows Update. - numContainers := 17 - eventPerContainer := 7 // create, attach, network connect, start, die, network disconnect, destroy - numConcurrentContainers := numContainers - if testEnv.DaemonPlatform() == "windows" { - numConcurrentContainers = 4 - } - sem := make(chan bool, numConcurrentContainers) - errChan := make(chan error, numContainers) - - startTime := daemonUnixTime(c) - - args := []string{"run", "--rm", "busybox", "true"} - for i := 0; i < numContainers; i++ { - sem <- true - go func(i int) { - defer func() { <-sem }() - out, err := exec.Command(dockerBinary, args...).CombinedOutput() - if err != nil { - err = fmt.Errorf("%v: %s", err, string(out)) - } - errChan <- err - }(i) - } - - // Wait for all goroutines to finish - for i := 0; i < cap(sem); i++ { - sem <- true - } - close(errChan) - - for err := range errChan { - c.Assert(err, checker.IsNil, check.Commentf("%q failed with error", strings.Join(args, " "))) - } - - out, _ := dockerCmd(c, "events", "--since="+startTime, "--until", daemonUnixTime(c)) - events := strings.Split(out, "\n") - nEvents := len(events) - 1 - c.Assert(nEvents, checker.Equals, numContainers*eventPerContainer, check.Commentf("events should be limited to 256, but received %d", nEvents)) -} - func (s *DockerSuite) TestEventsContainerEvents(c *check.C) { dockerCmd(c, "run", "--rm", "--name", "container-events-test", "busybox", "true") @@ -703,7 +659,7 @@ func (s *DockerSuite) TestEventsContainerRestart(c *check.C) { // wait until test2 is auto removed. waitTime := 10 * time.Second - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { // Windows takes longer... waitTime = 90 * time.Second } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_external_graphdriver_unix_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_external_graphdriver_unix_test.go index 8e766bcc3..3265336d6 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_external_graphdriver_unix_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_external_graphdriver_unix_test.go @@ -53,7 +53,7 @@ type graphEventsCounter struct { func (s *DockerExternalGraphdriverSuite) SetUpTest(c *check.C) { s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go index 2e2de972d..ff3d50fb0 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_external_volume_driver_unix_test.go @@ -52,7 +52,7 @@ type DockerExternalVolumeSuite struct { func (s *DockerExternalVolumeSuite) SetUpTest(c *check.C) { testRequires(c, SameHostDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) s.ec = &eventCounter{} } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_info_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_info_test.go index d7ce238bf..35a253219 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_info_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_info_test.go @@ -36,7 +36,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) { "Live Restore Enabled:", } - if testEnv.DaemonPlatform() == "linux" { + if testEnv.OSType == "linux" { stringsToCheck = append(stringsToCheck, "Init Binary:", "Security Options:", "containerd version:", "runc version:", "init version:") } @@ -44,7 +44,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) { stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: runc") } - if testEnv.ExperimentalDaemon() { + if testEnv.DaemonInfo.ExperimentalBuild { stringsToCheck = append(stringsToCheck, "Experimental: true") } else { stringsToCheck = append(stringsToCheck, "Experimental: false") @@ -72,7 +72,7 @@ func (s *DockerSuite) TestInfoDiscoveryBackend(c *check.C) { testRequires(c, SameHostDaemon, DaemonIsLinux) d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) discoveryBackend := "consul://consuladdr:consulport/some/path" discoveryAdvertise := "1.1.1.1:2375" @@ -91,7 +91,7 @@ func (s *DockerSuite) TestInfoDiscoveryInvalidAdvertise(c *check.C) { testRequires(c, SameHostDaemon, DaemonIsLinux) d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) discoveryBackend := "consul://consuladdr:consulport/some/path" @@ -110,7 +110,7 @@ func (s *DockerSuite) TestInfoDiscoveryAdvertiseInterfaceName(c *check.C) { testRequires(c, SameHostDaemon, Network, DaemonIsLinux) d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) discoveryBackend := "consul://consuladdr:consulport/some/path" discoveryAdvertise := "eth0" @@ -183,7 +183,7 @@ func (s *DockerSuite) TestInfoDebug(c *check.C) { testRequires(c, SameHostDaemon, DaemonIsLinux) d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) d.Start(c, "--debug") defer d.Stop(c) @@ -206,7 +206,7 @@ func (s *DockerSuite) TestInsecureRegistries(c *check.C) { registryHost := "insecurehost.com:5000" d := daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) d.Start(c, "--insecure-registry="+registryCIDR, "--insecure-registry="+registryHost) defer d.Stop(c) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go index 13eb2d38a..bf2ee71e9 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_inspect_test.go @@ -61,7 +61,7 @@ func (s *DockerSuite) TestInspectStatus(c *check.C) { // Windows does not support pause/unpause on Windows Server Containers. // (RS1 does for Hyper-V Containers, but production CI is not setup for that) - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { dockerCmd(c, "pause", out) inspectOut = inspectField(c, out, "State.Status") c.Assert(inspectOut, checker.Equals, "paused") @@ -206,7 +206,7 @@ func (s *DockerSuite) TestInspectContainerGraphDriver(c *check.C) { func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) { modifier := ",z" prefix, slash := getPrefixAndSlashFromDaemonPlatform() - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { modifier = "" // Linux creates the host directory if it doesn't exist. Windows does not. os.Mkdir(`c:\data`, os.ModeDir) @@ -229,7 +229,7 @@ func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) { c.Assert(m.Driver, checker.Equals, "") c.Assert(m.Source, checker.Equals, prefix+slash+"data") c.Assert(m.Destination, checker.Equals, prefix+slash+"data") - if testEnv.DaemonPlatform() != "windows" { // Windows does not set mode + if testEnv.OSType != "windows" { // Windows does not set mode c.Assert(m.Mode, checker.Equals, "ro"+modifier) } c.Assert(m.RW, checker.Equals, false) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_logout_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_logout_test.go index 5076ceba0..e0752f489 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_logout_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_logout_test.go @@ -13,9 +13,7 @@ import ( ) func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C) { - - // @TODO TestLogoutWithExternalAuth expects docker to fall back to a v1 registry, so has to be updated for v17.12, when v1 registries are no longer supported - s.d.StartWithBusybox(c, "--disable-legacy-registry=false") + s.d.StartWithBusybox(c) osPath := os.Getenv("PATH") defer os.Setenv("PATH", osPath) @@ -62,7 +60,7 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestLogoutWithExternalAuth(c *check.C) // check I cannot pull anymore out, err := s.d.Cmd("--config", tmp, "pull", repoName) c.Assert(err, check.NotNil, check.Commentf(out)) - c.Assert(out, checker.Contains, "Error: image dockercli/busybox:authtest not found") + c.Assert(out, checker.Contains, "no basic auth credentials") } // #23100 diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_netmode_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_netmode_test.go index abf1ff2cf..2b134d4de 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_netmode_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_netmode_test.go @@ -49,7 +49,7 @@ func (s *DockerSuite) TestNetHostname(c *check.C) { c.Assert(out, checker.Contains, "Invalid network mode: invalid container format container:") out, _ = dockerCmdWithFail(c, "run", "--net=weird", "busybox", "ps") - c.Assert(strings.ToLower(out), checker.Contains, "no such network") + c.Assert(strings.ToLower(out), checker.Contains, "not found") } func (s *DockerSuite) TestConflictContainerNetworkAndLinks(c *check.C) { diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_network_unix_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_network_unix_test.go index 4bb542386..90e4f6c1f 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_network_unix_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_network_unix_test.go @@ -50,7 +50,7 @@ type DockerNetworkSuite struct { func (s *DockerNetworkSuite) SetUpTest(c *check.C) { s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go index 13ae2b0eb..e49c42849 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_plugins_test.go @@ -55,7 +55,7 @@ func (ps *DockerPluginSuite) TestPluginBasicOps(c *check.C) { c.Assert(err, checker.IsNil) c.Assert(out, checker.Contains, plugin) - _, err = os.Stat(filepath.Join(testEnv.DockerBasePath(), "plugins", id)) + _, err = os.Stat(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "plugins", id)) if !os.IsNotExist(err) { c.Fatal(err) } @@ -168,8 +168,19 @@ func (ps *DockerPluginSuite) TestPluginSet(c *check.C) { defer cancel() initialValue := "0" + mntSrc := "foo" + devPath := "/dev/bar" + err = plugin.Create(ctx, client, name, func(cfg *plugin.Config) { cfg.Env = []types.PluginEnv{{Name: "DEBUG", Value: &initialValue, Settable: []string{"value"}}} + cfg.Mounts = []types.PluginMount{ + {Name: "pmount1", Settable: []string{"source"}, Type: "none", Source: &mntSrc}, + {Name: "pmount2", Settable: []string{"source"}, Type: "none"}, // Mount without source is invalid. + } + cfg.Linux.Devices = []types.PluginDevice{ + {Name: "pdev1", Path: &devPath, Settable: []string{"path"}}, + {Name: "pdev2", Settable: []string{"path"}}, // Device without Path is invalid. + } }) c.Assert(err, checker.IsNil, check.Commentf("failed to create test plugin")) @@ -180,6 +191,23 @@ func (ps *DockerPluginSuite) TestPluginSet(c *check.C) { env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{.Settings.Env}}", name) c.Assert(strings.TrimSpace(env), checker.Equals, "[DEBUG=1]") + + env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{with $mount := index .Settings.Mounts 0}}{{$mount.Source}}{{end}}", name) + c.Assert(strings.TrimSpace(env), checker.Contains, mntSrc) + + dockerCmd(c, "plugin", "set", name, "pmount1.source=bar") + + env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{with $mount := index .Settings.Mounts 0}}{{$mount.Source}}{{end}}", name) + c.Assert(strings.TrimSpace(env), checker.Contains, "bar") + + out, _, err := dockerCmdWithError("plugin", "set", name, "pmount2.source=bar2") + c.Assert(err, checker.NotNil) + c.Assert(out, checker.Contains, "Plugin config has no mount source") + + out, _, err = dockerCmdWithError("plugin", "set", name, "pdev2.path=/dev/bar2") + c.Assert(err, checker.NotNil) + c.Assert(out, checker.Contains, "Plugin config has no device path") + } func (ps *DockerPluginSuite) TestPluginInstallArgs(c *check.C) { @@ -478,14 +506,14 @@ func (s *DockerSuite) TestPluginUpgrade(c *check.C) { id := strings.TrimSpace(out) // make sure "v2" does not exists - _, err = os.Stat(filepath.Join(testEnv.DockerBasePath(), "plugins", id, "rootfs", "v2")) + _, err = os.Stat(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "plugins", id, "rootfs", "v2")) c.Assert(os.IsNotExist(err), checker.True, check.Commentf(out)) dockerCmd(c, "plugin", "disable", "-f", plugin) dockerCmd(c, "plugin", "upgrade", "--grant-all-permissions", "--skip-remote-check", plugin, pluginV2) // make sure "v2" file exists - _, err = os.Stat(filepath.Join(testEnv.DockerBasePath(), "plugins", id, "rootfs", "v2")) + _, err = os.Stat(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "plugins", id, "rootfs", "v2")) c.Assert(err, checker.IsNil) dockerCmd(c, "plugin", "enable", plugin) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_ps_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_ps_test.go index bea126120..6fe91f656 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_ps_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_ps_test.go @@ -216,7 +216,7 @@ func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) { }) // Windows doesn't support pausing of containers - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { // pause running container out = cli.DockerCmd(c, "run", "-itd", "busybox").Combined() pausedID := strings.TrimSpace(out) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_pull_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_pull_test.go index 613cdb311..0e88b1e56 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_pull_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_pull_test.go @@ -259,18 +259,6 @@ func (s *DockerHubPullSuite) TestPullClientDisconnect(c *check.C) { c.Assert(err, checker.NotNil, check.Commentf("image was pulled after client disconnected")) } -func (s *DockerRegistryAuthHtpasswdSuite) TestPullNoCredentialsNotFound(c *check.C) { - // @TODO TestPullNoCredentialsNotFound expects docker to fall back to a v1 registry, so has to be updated for v17.12, when v1 registries are no longer supported - s.d.StartWithBusybox(c, "--disable-legacy-registry=false") - - // we don't care about the actual image, we just want to see image not found - // because that means v2 call returned 401 and we fell back to v1 which usually - // gives a 404 (in this case the test registry doesn't handle v1 at all) - out, err := s.d.Cmd("pull", privateRegistryURL+"/busybox") - c.Assert(err, check.NotNil, check.Commentf(out)) - c.Assert(out, checker.Contains, "Error: image busybox:latest not found") -} - // Regression test for https://github.com/docker/docker/issues/26429 func (s *DockerSuite) TestPullLinuxImageFailsOnWindows(c *check.C) { testRequires(c, DaemonIsWindows, Network) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go index de277596f..e9d63684c 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_rename_test.go @@ -93,7 +93,7 @@ func (s *DockerSuite) TestRenameAnonymousContainer(c *check.C) { dockerCmd(c, "start", "container1") count := "-c" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { count = "-n" } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go index cf6b135ed..1b4c928b9 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_restart_test.go @@ -269,7 +269,7 @@ func (s *DockerSuite) TestRestartContainerwithRestartPolicy(c *check.C) { id1 := strings.TrimSpace(string(out1)) id2 := strings.TrimSpace(string(out2)) waitTimeout := 15 * time.Second - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { waitTimeout = 150 * time.Second } err := waitInspect(id1, "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTimeout) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_rmi_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_rmi_test.go index 52c8837d2..aedfa13a8 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_rmi_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_rmi_test.go @@ -68,7 +68,7 @@ func (s *DockerSuite) TestRmiImgIDMultipleTag(c *check.C) { // Wait for it to exit as cannot commit a running container on Windows, and // it will take a few seconds to exit - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { cli.WaitExited(c, containerID, 60*time.Second) } @@ -109,7 +109,7 @@ func (s *DockerSuite) TestRmiImgIDForce(c *check.C) { // Wait for it to exit as cannot commit a running container on Windows, and // it will take a few seconds to exit - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { cli.WaitExited(c, containerID, 60*time.Second) } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go index 6dbbb67ac..bf0cb0ddf 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_run_test.go @@ -36,7 +36,6 @@ import ( "github.com/docker/libnetwork/types" "github.com/go-check/check" "github.com/gotestyourself/gotestyourself/icmd" - libcontainerUser "github.com/opencontainers/runc/libcontainer/user" "golang.org/x/net/context" ) @@ -72,10 +71,10 @@ func (s *DockerSuite) TestRunLeakyFileDescriptors(c *check.C) { // this will fail when Internet access is unavailable func (s *DockerSuite) TestRunLookupGoogleDNS(c *check.C) { testRequires(c, Network, NotArm) - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { // nslookup isn't present in Windows busybox. Is built-in. Further, // nslookup isn't present in nanoserver. Hence just use PowerShell... - dockerCmd(c, "run", testEnv.MinimalBaseImage(), "powershell", "Resolve-DNSName", "google.com") + dockerCmd(c, "run", testEnv.PlatformDefaults.BaseImage, "powershell", "Resolve-DNSName", "google.com") } else { dockerCmd(c, "run", "busybox", "nslookup", "google.com") } @@ -137,7 +136,7 @@ func (s *DockerSuite) TestRunDetachedContainerIDPrinting(c *check.C) { func (s *DockerSuite) TestRunWorkingDirectory(c *check.C) { dir := "/root" image := "busybox" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { dir = `C:/Windows` } @@ -160,9 +159,9 @@ func (s *DockerSuite) TestRunWorkingDirectory(c *check.C) { func (s *DockerSuite) TestRunWithoutNetworking(c *check.C) { count := "-c" image := "busybox" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { count = "-n" - image = testEnv.MinimalBaseImage() + image = testEnv.PlatformDefaults.BaseImage } // First using the long form --net @@ -354,8 +353,8 @@ func (s *DockerSuite) TestRunWithVolumesFromExited(c *check.C) { ) // Create a file in a volume - if testEnv.DaemonPlatform() == "windows" { - out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", `c:\some\dir`, testEnv.MinimalBaseImage(), "cmd", "/c", `echo hello > c:\some\dir\file`) + if testEnv.OSType == "windows" { + out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", `c:\some\dir`, testEnv.PlatformDefaults.BaseImage, "cmd", "/c", `echo hello > c:\some\dir\file`) } else { out, exitCode = dockerCmd(c, "run", "--name", "test-data", "--volume", "/some/dir", "busybox", "touch", "/some/dir/file") } @@ -364,8 +363,8 @@ func (s *DockerSuite) TestRunWithVolumesFromExited(c *check.C) { } // Read the file from another container using --volumes-from to access the volume in the second container - if testEnv.DaemonPlatform() == "windows" { - out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", testEnv.MinimalBaseImage(), "cmd", "/c", `type c:\some\dir\file`) + if testEnv.OSType == "windows" { + out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", testEnv.PlatformDefaults.BaseImage, "cmd", "/c", `type c:\some\dir\file`) } else { out, exitCode = dockerCmd(c, "run", "--volumes-from", "test-data", "busybox", "cat", "/some/dir/file") } @@ -396,7 +395,7 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) { // In the case of Windows to Windows CI, if the machine is setup so that // the temp directory is not the C: drive, this test is invalid and will // not work. - if testEnv.DaemonPlatform() == "windows" && strings.ToLower(dir[:1]) != "c" { + if testEnv.OSType == "windows" && strings.ToLower(dir[:1]) != "c" { c.Skip("Requires TEMP to point to C: drive") } @@ -406,8 +405,8 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir(c *check.C) { } f.Close() - if testEnv.DaemonPlatform() == "windows" { - dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir %s\nRUN mklink /D c:\\test %s", testEnv.MinimalBaseImage(), dir, dir) + if testEnv.OSType == "windows" { + dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir %s\nRUN mklink /D c:\\test %s", testEnv.PlatformDefaults.BaseImage, dir, dir) containerPath = `c:\test\test` cmd = "tasklist" } else { @@ -431,8 +430,8 @@ func (s *DockerSuite) TestRunCreateVolumesInSymlinkDir2(c *check.C) { testRequires(c, SameHostDaemon, DaemonIsLinux) name := "test-volume-symlink2" - if testEnv.DaemonPlatform() == "windows" { - dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir c:\\%s\nRUN mklink /D c:\\test c:\\%s", testEnv.MinimalBaseImage(), name, name) + if testEnv.OSType == "windows" { + dockerFile = fmt.Sprintf("FROM %s\nRUN mkdir c:\\%s\nRUN mklink /D c:\\test c:\\%s", testEnv.PlatformDefaults.BaseImage, name, name) containerPath = `c:\test\test` cmd = "tasklist" } else { @@ -455,7 +454,7 @@ func (s *DockerSuite) TestRunVolumesFromInReadonlyModeFails(c *check.C) { volumeDir string fileInVol string ) - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { volumeDir = `c:/test` // Forward-slash as using busybox fileInVol = `c:/test/file` } else { @@ -476,7 +475,7 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) { volumeDir string fileInVol string ) - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { volumeDir = `c:/test` // Forward-slash as using busybox fileInVol = `c:/test/file` } else { @@ -497,7 +496,7 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) { func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) { testRequires(c, SameHostDaemon) prefix, slash := getPrefixAndSlashFromDaemonPlatform() - hostpath := RandomTmpDirPath("test", testEnv.DaemonPlatform()) + hostpath := RandomTmpDirPath("test", testEnv.OSType) if err := os.MkdirAll(hostpath, 0755); err != nil { c.Fatalf("Failed to create %s: %q", hostpath, err) } @@ -520,11 +519,11 @@ func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) { // Test for GH#10618 func (s *DockerSuite) TestRunNoDupVolumes(c *check.C) { - path1 := RandomTmpDirPath("test1", testEnv.DaemonPlatform()) - path2 := RandomTmpDirPath("test2", testEnv.DaemonPlatform()) + path1 := RandomTmpDirPath("test1", testEnv.OSType) + path2 := RandomTmpDirPath("test2", testEnv.OSType) someplace := ":/someplace" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { // Windows requires that the source directory exists before calling HCS testRequires(c, SameHostDaemon) someplace = `:c:\someplace` @@ -573,7 +572,7 @@ func (s *DockerSuite) TestRunNoDupVolumes(c *check.C) { // Test for #1351 func (s *DockerSuite) TestRunApplyVolumesFromBeforeVolumes(c *check.C) { prefix := "" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { prefix = `c:` } dockerCmd(c, "run", "--name", "parent", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo") @@ -582,7 +581,7 @@ func (s *DockerSuite) TestRunApplyVolumesFromBeforeVolumes(c *check.C) { func (s *DockerSuite) TestRunMultipleVolumesFrom(c *check.C) { prefix := "" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { prefix = `c:` } dockerCmd(c, "run", "--name", "parent1", "-v", prefix+"/test", "busybox", "touch", prefix+"/test/foo") @@ -612,7 +611,7 @@ func (s *DockerSuite) TestRunVerifyContainerID(c *check.C) { // Test that creating a container with a volume doesn't crash. Regression test for #995. func (s *DockerSuite) TestRunCreateVolume(c *check.C) { prefix := "" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { prefix = `c:` } dockerCmd(c, "run", "-v", prefix+"/var/lib/data", "busybox", "true") @@ -668,9 +667,9 @@ func (s *DockerSuite) TestRunVolumesFromSymlinkPath(c *check.C) { RUN ln -s home /foo VOLUME ["/foo/bar"]` - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { prefix = `c:` - dfContents = `FROM ` + testEnv.MinimalBaseImage() + ` + dfContents = `FROM ` + testEnv.PlatformDefaults.BaseImage + ` RUN mkdir c:\home RUN mklink /D c:\foo c:\home VOLUME ["c:/foo/bar"] @@ -714,7 +713,7 @@ func (s *DockerSuite) TestRunExitCode(c *check.C) { func (s *DockerSuite) TestRunUserDefaults(c *check.C) { expected := "uid=0(root) gid=0(root)" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = "uid=1000(ContainerAdministrator) gid=1000(ContainerAdministrator)" } out, _ := dockerCmd(c, "run", "busybox", "id") @@ -751,7 +750,7 @@ func (s *DockerSuite) TestRunUserByIDBig(c *check.C) { if err == nil { c.Fatal("No error, but must be.", out) } - if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) { + if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") { c.Fatalf("expected error about uids range, got %s", out) } } @@ -764,7 +763,7 @@ func (s *DockerSuite) TestRunUserByIDNegative(c *check.C) { if err == nil { c.Fatal("No error, but must be.", out) } - if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) { + if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") { c.Fatalf("expected error about uids range, got %s", out) } } @@ -920,9 +919,9 @@ func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) { } func (s *DockerSuite) TestRunContainerNetwork(c *check.C) { - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { // Windows busybox does not have ping. Use built in ping instead. - dockerCmd(c, "run", testEnv.MinimalBaseImage(), "ping", "-n", "1", "127.0.0.1") + dockerCmd(c, "run", testEnv.PlatformDefaults.BaseImage, "ping", "-n", "1", "127.0.0.1") } else { dockerCmd(c, "run", "busybox", "ping", "-c", "1", "127.0.0.1") } @@ -1220,7 +1219,7 @@ func (s *DockerSuite) TestRunModeHostname(c *check.C) { func (s *DockerSuite) TestRunRootWorkdir(c *check.C) { out, _ := dockerCmd(c, "run", "--workdir", "/", "busybox", "pwd") expected := "/\n" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = "C:" + expected } if out != expected { @@ -1229,9 +1228,9 @@ func (s *DockerSuite) TestRunRootWorkdir(c *check.C) { } func (s *DockerSuite) TestRunAllowBindMountingRoot(c *check.C) { - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { // Windows busybox will fail with Permission Denied on items such as pagefile.sys - dockerCmd(c, "run", "-v", `c:\:c:\host`, testEnv.MinimalBaseImage(), "cmd", "-c", "dir", `c:\host`) + dockerCmd(c, "run", "-v", `c:\:c:\host`, testEnv.PlatformDefaults.BaseImage, "cmd", "-c", "dir", `c:\host`) } else { dockerCmd(c, "run", "-v", "/:/host", "busybox", "ls", "/host") } @@ -1240,7 +1239,7 @@ func (s *DockerSuite) TestRunAllowBindMountingRoot(c *check.C) { func (s *DockerSuite) TestRunDisallowBindMountingRootToRoot(c *check.C) { mount := "/:/" targetDir := "/host" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { mount = `c:\:c\` targetDir = "c:/host" // Forward slash as using busybox } @@ -1704,15 +1703,15 @@ func (s *DockerSuite) TestRunCleanupCmdOnEntrypoint(c *check.C) { } out = strings.TrimSpace(out) expected := "root" - if testEnv.DaemonPlatform() == "windows" { - if strings.Contains(testEnv.MinimalBaseImage(), "windowsservercore") { + if testEnv.OSType == "windows" { + if strings.Contains(testEnv.PlatformDefaults.BaseImage, "windowsservercore") { expected = `user manager\containeradministrator` } else { expected = `ContainerAdministrator` // nanoserver } } if out != expected { - c.Fatalf("Expected output %s, got %q. %s", expected, out, testEnv.MinimalBaseImage()) + c.Fatalf("Expected output %s, got %q. %s", expected, out, testEnv.PlatformDefaults.BaseImage) } } @@ -1720,7 +1719,7 @@ func (s *DockerSuite) TestRunCleanupCmdOnEntrypoint(c *check.C) { func (s *DockerSuite) TestRunWorkdirExistsAndIsFile(c *check.C) { existingFile := "/bin/cat" expected := "not a directory" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { existingFile = `\windows\system32\ntdll.dll` expected = `The directory name is invalid.` } @@ -1736,7 +1735,7 @@ func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) { meow := "/bin/cat" delay := 60 - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { meow = "cat" } runCmd := exec.Command(dockerBinary, "run", "--name", name, "-i", "busybox", meow) @@ -1881,7 +1880,7 @@ func (s *DockerSuite) TestRunEntrypoint(c *check.C) { func (s *DockerSuite) TestRunBindMounts(c *check.C) { testRequires(c, SameHostDaemon) - if testEnv.DaemonPlatform() == "linux" { + if testEnv.OSType == "linux" { testRequires(c, DaemonIsLinux, NotUserNamespace) } @@ -1902,7 +1901,7 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) { } // test writing to bind mount - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { dockerCmd(c, "run", "-v", fmt.Sprintf(`%s:c:\tmp:rw`, tmpDir), "busybox", "touch", "c:/tmp/holla") } else { dockerCmd(c, "run", "-v", fmt.Sprintf("%s:/tmp:rw", tmpDir), "busybox", "touch", "/tmp/holla") @@ -1917,7 +1916,7 @@ func (s *DockerSuite) TestRunBindMounts(c *check.C) { } // Windows does not (and likely never will) support mounting a single file - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { // test mount a file dockerCmd(c, "run", "-v", fmt.Sprintf("%s/holla:/tmp/holla:rw", tmpDir), "busybox", "sh", "-c", "echo -n 'yotta' > /tmp/holla") content := readFile(path.Join(tmpDir, "holla"), c) // Will fail if the file doesn't exist @@ -1942,9 +1941,9 @@ func (s *DockerSuite) TestRunCidFileCleanupIfEmpty(c *check.C) { tmpCidFile := path.Join(tmpDir, "cid") image := "emptyfs" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { // Windows can't support an emptyfs image. Just use the regular Windows image - image = testEnv.MinimalBaseImage() + image = testEnv.PlatformDefaults.BaseImage } out, _, err := dockerCmdWithError("run", "--cidfile", tmpCidFile, image) if err == nil { @@ -1988,7 +1987,7 @@ func (s *DockerSuite) TestRunCidFileCheckIDLength(c *check.C) { func (s *DockerSuite) TestRunSetMacAddress(c *check.C) { mac := "12:34:56:78:9a:bc" var out string - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { out, _ = dockerCmd(c, "run", "-i", "--rm", fmt.Sprintf("--mac-address=%s", mac), "busybox", "sh", "-c", "ipconfig /all | grep 'Physical Address' | awk '{print $12}'") mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1) // To Windows-style MACs } else { @@ -2185,7 +2184,7 @@ func (s *DockerSuite) TestVolumesNoCopyData(c *check.C) { c.Fatalf("Data was copied on volumes-from but shouldn't be:\n%q", out) } - tmpDir := RandomTmpDirPath("docker_test_bind_mount_copy_data", testEnv.DaemonPlatform()) + tmpDir := RandomTmpDirPath("docker_test_bind_mount_copy_data", testEnv.OSType) if out, _, err := dockerCmdWithError("run", "-v", tmpDir+":/foo", "dataimage", "ls", "-lh", "/foo/bar"); err == nil || !strings.Contains(out, "No such file or directory") { c.Fatalf("Data was copied on bind mount but shouldn't be:\n%q", out) } @@ -2239,7 +2238,16 @@ func (s *DockerSuite) TestRunSlowStdoutConsumer(c *check.C) { // TODO Windows: This should be able to run on Windows if can find an // alternate to /dev/zero and /dev/stdout. testRequires(c, DaemonIsLinux) - cont := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | catv") + + // TODO will remove this if issue #35963 fixed + var args []string + if runtime.GOARCH == "amd64" { + args = []string{"run", "--rm", "busybox", "/bin/sh", "-c", "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | catv"} + } else { + args = []string{"run", "--rm", "busybox", "/bin/sh", "-c", "dd if=/dev/zero of=/dev/stdout bs=1024 count=2000 | cat -v"} + } + + cont := exec.Command(dockerBinary, args...) stdout, err := cont.StdoutPipe() if err != nil { @@ -2312,48 +2320,6 @@ func (s *DockerSuite) TestRunModeIpcHost(c *check.C) { } } -func (s *DockerSuite) TestRunModeIpcContainer(c *check.C) { - // Not applicable on Windows as uses Unix-specific capabilities - testRequires(c, SameHostDaemon, DaemonIsLinux) - - out, _ := dockerCmd(c, "run", "-d", "busybox", "sh", "-c", "echo -n test > /dev/shm/test && touch /dev/mqueue/toto && top") - - id := strings.TrimSpace(out) - state := inspectField(c, id, "State.Running") - if state != "true" { - c.Fatal("Container state is 'not running'") - } - pid1 := inspectField(c, id, "State.Pid") - - parentContainerIpc, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/ipc", pid1)) - if err != nil { - c.Fatal(err) - } - - out, _ = dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "readlink", "/proc/self/ns/ipc") - out = strings.Trim(out, "\n") - if parentContainerIpc != out { - c.Fatalf("IPC different with --ipc=container:%s %s != %s\n", id, parentContainerIpc, out) - } - - catOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "cat", "/dev/shm/test") - if catOutput != "test" { - c.Fatalf("Output of /dev/shm/test expected test but found: %s", catOutput) - } - - // check that /dev/mqueue is actually of mqueue type - grepOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "grep", "/dev/mqueue", "/proc/mounts") - if !strings.HasPrefix(grepOutput, "mqueue /dev/mqueue mqueue rw") { - c.Fatalf("Output of 'grep /proc/mounts' expected 'mqueue /dev/mqueue mqueue rw' but found: %s", grepOutput) - } - - lsOutput, _ := dockerCmd(c, "run", fmt.Sprintf("--ipc=container:%s", id), "busybox", "ls", "/dev/mqueue") - lsOutput = strings.Trim(lsOutput, "\n") - if lsOutput != "toto" { - c.Fatalf("Output of 'ls /dev/mqueue' expected 'toto' but found: %s", lsOutput) - } -} - func (s *DockerSuite) TestRunModeIpcContainerNotExists(c *check.C) { // Not applicable on Windows as uses Unix-specific capabilities testRequires(c, DaemonIsLinux) @@ -2600,10 +2566,10 @@ func (s *DockerSuite) TestRunNonLocalMacAddress(c *check.C) { args := []string{"run", "--mac-address", addr} expected := addr - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { args = append(args, "busybox", "ifconfig") } else { - args = append(args, testEnv.MinimalBaseImage(), "ipconfig", "/all") + args = append(args, testEnv.PlatformDefaults.BaseImage, "ipconfig", "/all") expected = strings.Replace(strings.ToUpper(addr), ":", "-", -1) } @@ -2696,7 +2662,7 @@ func (s *DockerSuite) TestRunSetDefaultRestartPolicy(c *check.C) { func (s *DockerSuite) TestRunRestartMaxRetries(c *check.C) { out, _ := dockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "false") timeout := 10 * time.Second - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { timeout = 120 * time.Second } @@ -3064,7 +3030,7 @@ func (s *DockerSuite) TestVolumeFromMixedRWOptions(c *check.C) { dockerCmd(c, "run", "--volumes-from", "parent:ro", "--name", "test-volumes-1", "busybox", "true") dockerCmd(c, "run", "--volumes-from", "parent:rw", "--name", "test-volumes-2", "busybox", "true") - if testEnv.DaemonPlatform() != "windows" { + if testEnv.OSType != "windows" { mRO, err := inspectMountPoint("test-volumes-1", prefix+slash+"test") c.Assert(err, checker.IsNil, check.Commentf("failed to inspect mount point")) if mRO.RW { @@ -3524,8 +3490,8 @@ func (s *DockerSuite) TestRunLoopbackOnlyExistsWhenNetworkingDisabled(c *check.C // Issue #4681 func (s *DockerSuite) TestRunLoopbackWhenNetworkDisabled(c *check.C) { - if testEnv.DaemonPlatform() == "windows" { - dockerCmd(c, "run", "--net=none", testEnv.MinimalBaseImage(), "ping", "-n", "1", "127.0.0.1") + if testEnv.OSType == "windows" { + dockerCmd(c, "run", "--net=none", testEnv.PlatformDefaults.BaseImage, "ping", "-n", "1", "127.0.0.1") } else { dockerCmd(c, "run", "--net=none", "busybox", "ping", "-c", "1", "127.0.0.1") } @@ -3791,7 +3757,7 @@ func (s *DockerSuite) TestRunNonExistingCmd(c *check.C) { // as that's when the check is made (and yes, by its design...) func (s *DockerSuite) TestCmdCannotBeInvoked(c *check.C) { expected := 126 - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { expected = 127 } name := "testCmdCannotBeInvoked" @@ -4274,7 +4240,7 @@ func (s *DockerSuite) TestRunCredentialSpecFailures(c *check.C) { func (s *DockerSuite) TestRunCredentialSpecWellFormed(c *check.C) { testRequires(c, DaemonIsWindows, SameHostDaemon) validCS := readFile(`fixtures\credentialspecs\valid.json`, c) - writeFile(filepath.Join(testEnv.DockerBasePath(), `credentialspecs\valid.json`), validCS, c) + writeFile(filepath.Join(testEnv.DaemonInfo.DockerRootDir, `credentialspecs\valid.json`), validCS, c) dockerCmd(c, "run", `--security-opt=credentialspec=file://valid.json`, "busybox", "true") } @@ -4284,7 +4250,18 @@ func (s *DockerSuite) TestRunCredentialSpecWellFormed(c *check.C) { func (s *DockerSuite) TestRunServicingContainer(c *check.C) { testRequires(c, DaemonIsWindows, SameHostDaemon) - out := cli.DockerCmd(c, "run", "-d", testEnv.MinimalBaseImage(), "cmd", "/c", "mkdir c:\\programdata\\Microsoft\\Windows\\ContainerUpdates\\000_000_d99f45d0-ffc8-4af7-bd9c-ea6a62e035c9_200 && sc control cexecsvc 255").Combined() + // This functionality does not exist in post-RS3 builds. + // Note we get the version number from the full build string, as Windows + // reports Windows 8 version 6.2 build 9200 from non-manifested binaries. + // Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx + v, err := kernel.GetKernelVersion() + c.Assert(err, checker.IsNil) + build, _ := strconv.Atoi(strings.Split(strings.SplitN(v.String(), " ", 3)[2][1:], ".")[0]) + if build > 16299 { + c.Skip("Disabled on post-RS3 builds") + } + + out := cli.DockerCmd(c, "run", "-d", testEnv.PlatformDefaults.BaseImage, "cmd", "/c", "mkdir c:\\programdata\\Microsoft\\Windows\\ContainerUpdates\\000_000_d99f45d0-ffc8-4af7-bd9c-ea6a62e035c9_200 && sc control cexecsvc 255").Combined() containerID := strings.TrimSpace(out) cli.WaitExited(c, containerID, 60*time.Second) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go index 9488fff45..283f576f5 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_swarm_test.go @@ -849,7 +849,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *check.C) { waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1) // We need to get the container id. - out, err = d.Cmd("ps", "-a", "-q", "--no-trunc") + out, err = d.Cmd("ps", "-q", "--no-trunc") c.Assert(err, checker.IsNil) id := strings.TrimSpace(out) @@ -872,7 +872,7 @@ func (s *DockerSwarmSuite) TestSwarmServiceTTY(c *check.C) { waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1) // We need to get the container id. - out, err = d.Cmd("ps", "-a", "-q", "--no-trunc") + out, err = d.Cmd("ps", "-q", "--no-trunc") c.Assert(err, checker.IsNil) id = strings.TrimSpace(out) diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_tag_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_tag_test.go index ee94a9b14..278e348f4 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_tag_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_tag_test.go @@ -1,13 +1,10 @@ package main import ( - "fmt" "strings" "github.com/docker/docker/integration-cli/checker" - "github.com/docker/docker/integration-cli/cli/build" "github.com/docker/docker/internal/testutil" - "github.com/docker/docker/pkg/stringid" "github.com/go-check/check" ) @@ -140,29 +137,3 @@ func (s *DockerSuite) TestTagInvalidRepoName(c *check.C) { c.Fatal("tagging with image named \"sha256\" should have failed") } } - -// ensure tags cannot create ambiguity with image ids -func (s *DockerSuite) TestTagTruncationAmbiguity(c *check.C) { - buildImageSuccessfully(c, "notbusybox:latest", build.WithDockerfile(`FROM busybox - MAINTAINER dockerio`)) - imageID := getIDByName(c, "notbusybox:latest") - truncatedImageID := stringid.TruncateID(imageID) - truncatedTag := fmt.Sprintf("notbusybox:%s", truncatedImageID) - - id := inspectField(c, truncatedTag, "Id") - - // Ensure inspect by image id returns image for image id - c.Assert(id, checker.Equals, imageID) - c.Logf("Built image: %s", imageID) - - // test setting tag fails - _, _, err := dockerCmdWithError("tag", "busybox:latest", truncatedTag) - if err != nil { - c.Fatalf("Error tagging with an image id: %s", err) - } - - id = inspectField(c, truncatedTag, "Id") - - // Ensure id is imageID and not busybox:latest - c.Assert(id, checker.Not(checker.Equals), imageID) -} diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_top_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_top_test.go index f52f24014..b8924d3b5 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_top_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_top_test.go @@ -13,7 +13,7 @@ func (s *DockerSuite) TestTopMultipleArgs(c *check.C) { cleanedContainerID := strings.TrimSpace(out) var expected icmd.Expected - switch testEnv.DaemonPlatform() { + switch testEnv.OSType { case "windows": expected = icmd.Expected{ExitCode: 1, Err: "Windows does not support arguments to top"} default: @@ -34,7 +34,7 @@ func (s *DockerSuite) TestTopNonPrivileged(c *check.C) { // Windows will list the name of the launched executable which in this case is busybox.exe, without the parameters. // Linux will display the command executed in the container var lookingFor string - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { lookingFor = "busybox.exe" } else { lookingFor = "top" diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_update_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_update_test.go index 5b9b7304c..dce137ebf 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_update_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_update_test.go @@ -13,7 +13,7 @@ import ( func (s *DockerSuite) TestUpdateRestartPolicy(c *check.C) { out := cli.DockerCmd(c, "run", "-d", "--restart=on-failure:3", "busybox", "sh", "-c", "sleep 1 && false").Combined() timeout := 60 * time.Second - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { timeout = 180 * time.Second } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_cli_v2_only_test.go b/vendor/github.com/docker/docker/integration-cli/docker_cli_v2_only_test.go index b82cdbde1..375734102 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_cli_v2_only_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_cli_v2_only_test.go @@ -22,7 +22,7 @@ func makefile(path string, contents string) (string, error) { return f.Name(), nil } -// TestV2Only ensures that a daemon by default does not +// TestV2Only ensures that a daemon does not // attempt to contact any v1 registry endpoints. func (s *DockerRegistrySuite) TestV2Only(c *check.C) { reg, err := registry.NewMock(c) @@ -56,65 +56,3 @@ func (s *DockerRegistrySuite) TestV2Only(c *check.C) { s.d.Cmd("push", repoName) s.d.Cmd("pull", repoName) } - -// TestV1 starts a daemon with legacy registries enabled -// and ensure v1 endpoints are hit for the following operations: -// login, push, pull, build & run -func (s *DockerRegistrySuite) TestV1(c *check.C) { - reg, err := registry.NewMock(c) - defer reg.Close() - c.Assert(err, check.IsNil) - - v2Pings := 0 - reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) { - v2Pings++ - // V2 ping 404 causes fallback to v1 - w.WriteHeader(404) - }) - - v1Pings := 0 - reg.RegisterHandler("/v1/_ping", func(w http.ResponseWriter, r *http.Request) { - v1Pings++ - }) - - v1Logins := 0 - reg.RegisterHandler("/v1/users/", func(w http.ResponseWriter, r *http.Request) { - v1Logins++ - }) - - v1Repo := 0 - reg.RegisterHandler("/v1/repositories/busybox/", func(w http.ResponseWriter, r *http.Request) { - v1Repo++ - }) - - reg.RegisterHandler("/v1/repositories/busybox/images", func(w http.ResponseWriter, r *http.Request) { - v1Repo++ - }) - - s.d.Start(c, "--insecure-registry", reg.URL(), "--disable-legacy-registry=false") - - tmp, err := ioutil.TempDir("", "integration-cli-") - c.Assert(err, check.IsNil) - defer os.RemoveAll(tmp) - - dockerfileName, err := makefile(tmp, fmt.Sprintf("FROM %s/busybox", reg.URL())) - c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile")) - - s.d.Cmd("build", "--file", dockerfileName, tmp) - c.Assert(v1Repo, check.Equals, 1, check.Commentf("Expected v1 repository access after build")) - - repoName := fmt.Sprintf("%s/busybox", reg.URL()) - s.d.Cmd("run", repoName) - c.Assert(v1Repo, check.Equals, 2, check.Commentf("Expected v1 repository access after run")) - - s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL()) - c.Assert(v1Logins, check.Equals, 1, check.Commentf("Expected v1 login attempt")) - - s.d.Cmd("tag", "busybox", repoName) - s.d.Cmd("push", repoName) - - c.Assert(v1Repo, check.Equals, 2) - - s.d.Cmd("pull", repoName) - c.Assert(v1Repo, check.Equals, 3, check.Commentf("Expected v1 repository access after pull")) -} diff --git a/vendor/github.com/docker/docker/integration-cli/docker_deprecated_api_v124_test.go b/vendor/github.com/docker/docker/integration-cli/docker_deprecated_api_v124_test.go index 214ae0866..279efddd8 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_deprecated_api_v124_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_deprecated_api_v124_test.go @@ -36,7 +36,7 @@ func (s *DockerSuite) TestDeprecatedContainerAPIStartVolumeBinds(c *check.C) { // TODO Windows CI: Investigate further why this fails on Windows to Windows CI. testRequires(c, DaemonIsLinux) path := "/foo" - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { path = `c:\foo` } name := "testing" @@ -49,7 +49,7 @@ func (s *DockerSuite) TestDeprecatedContainerAPIStartVolumeBinds(c *check.C) { c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusCreated) - bindPath := RandomTmpDirPath("test", testEnv.DaemonPlatform()) + bindPath := RandomTmpDirPath("test", testEnv.OSType) config = map[string]interface{}{ "Binds": []string{bindPath + ":" + path}, } @@ -76,8 +76,8 @@ func (s *DockerSuite) TestDeprecatedContainerAPIStartDupVolumeBinds(c *check.C) c.Assert(err, checker.IsNil) c.Assert(res.StatusCode, checker.Equals, http.StatusCreated) - bindPath1 := RandomTmpDirPath("test1", testEnv.DaemonPlatform()) - bindPath2 := RandomTmpDirPath("test2", testEnv.DaemonPlatform()) + bindPath1 := RandomTmpDirPath("test1", testEnv.OSType) + bindPath2 := RandomTmpDirPath("test2", testEnv.OSType) config = map[string]interface{}{ "Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"}, diff --git a/vendor/github.com/docker/docker/integration-cli/docker_hub_pull_suite_test.go b/vendor/github.com/docker/docker/integration-cli/docker_hub_pull_suite_test.go index 286a3913c..a8d6aedad 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_hub_pull_suite_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_hub_pull_suite_test.go @@ -41,7 +41,7 @@ func newDockerHubPullSuite() *DockerHubPullSuite { func (s *DockerHubPullSuite) SetUpSuite(c *check.C) { testRequires(c, DaemonIsLinux, SameHostDaemon) s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{ - Experimental: testEnv.ExperimentalDaemon(), + Experimental: testEnv.DaemonInfo.ExperimentalBuild, }) s.d.Start(c) } diff --git a/vendor/github.com/docker/docker/integration-cli/docker_utils_test.go b/vendor/github.com/docker/docker/integration-cli/docker_utils_test.go index 1bda2c723..6eda88c68 100644 --- a/vendor/github.com/docker/docker/integration-cli/docker_utils_test.go +++ b/vendor/github.com/docker/docker/integration-cli/docker_utils_test.go @@ -399,7 +399,7 @@ func runSleepingContainerInImage(c *check.C, image string, extraArgs ...string) // minimalBaseImage returns the name of the minimal base image for the current // daemon platform. func minimalBaseImage() string { - return testEnv.MinimalBaseImage() + return testEnv.PlatformDefaults.BaseImage } func getGoroutineNumber() (int, error) { diff --git a/vendor/github.com/docker/docker/integration-cli/environment/environment.go b/vendor/github.com/docker/docker/integration-cli/environment/environment.go index 0decc0698..7fd6743c7 100644 --- a/vendor/github.com/docker/docker/integration-cli/environment/environment.go +++ b/vendor/github.com/docker/docker/integration-cli/environment/environment.go @@ -48,32 +48,3 @@ func New() (*Execution, error) { dockerBinary: dockerBinary, }, nil } - -// DockerBasePath is the base path of the docker folder (by default it is -/var/run/docker) -// TODO: remove -// Deprecated: use Execution.DaemonInfo.DockerRootDir -func (e *Execution) DockerBasePath() string { - return e.DaemonInfo.DockerRootDir -} - -// ExperimentalDaemon tell whether the main daemon has -// experimental features enabled or not -// Deprecated: use DaemonInfo.ExperimentalBuild -func (e *Execution) ExperimentalDaemon() bool { - return e.DaemonInfo.ExperimentalBuild -} - -// DaemonPlatform is held globally so that tests can make intelligent -// decisions on how to configure themselves according to the platform -// of the daemon. This is initialized in docker_utils by sending -// a version call to the daemon and examining the response header. -// Deprecated: use Execution.OSType -func (e *Execution) DaemonPlatform() string { - return e.OSType -} - -// MinimalBaseImage is the image used for minimal builds (it depends on the platform) -// Deprecated: use Execution.PlatformDefaults.BaseImage -func (e *Execution) MinimalBaseImage() string { - return e.PlatformDefaults.BaseImage -} diff --git a/vendor/github.com/docker/docker/integration-cli/fixtures/load/frozen.go b/vendor/github.com/docker/docker/integration-cli/fixtures/load/frozen.go index 4bec323b5..7b91fecd9 100644 --- a/vendor/github.com/docker/docker/integration-cli/fixtures/load/frozen.go +++ b/vendor/github.com/docker/docker/integration-cli/fixtures/load/frozen.go @@ -26,7 +26,6 @@ const frozenImgDir = "/docker-frozen-images" // images were passed in. If the images need to be downloaded, then it will respect // the passed in images func FrozenImagesLinux(client client.APIClient, images ...string) error { - imgNS := os.Getenv("TEST_IMAGE_NAMESPACE") var loadImages []struct{ srcName, destName string } for _, img := range images { if !imageExists(client, img) { @@ -38,9 +37,6 @@ func FrozenImagesLinux(client client.APIClient, images ...string) error { if img == "hello-world:frozen" { srcName = "hello-world:latest" } - if imgNS != "" { - srcName = imgNS + "/" + srcName - } loadImages = append(loadImages, struct{ srcName, destName string }{ srcName: srcName, destName: img, diff --git a/vendor/github.com/docker/docker/integration-cli/fixtures_linux_daemon_test.go b/vendor/github.com/docker/docker/integration-cli/fixtures_linux_daemon_test.go index 6ac451121..e1cad449f 100644 --- a/vendor/github.com/docker/docker/integration-cli/fixtures_linux_daemon_test.go +++ b/vendor/github.com/docker/docker/integration-cli/fixtures_linux_daemon_test.go @@ -38,7 +38,7 @@ func ensureSyscallTest(c *check.C) { // if no match, must build in docker, which is significantly slower // (slower mostly because of the vfs graphdriver) - if testEnv.DaemonPlatform() != runtime.GOOS { + if testEnv.OSType != runtime.GOOS { ensureSyscallTestBuild(c) return } @@ -93,7 +93,7 @@ func ensureSyscallTestBuild(c *check.C) { func ensureNNPTest(c *check.C) { defer testEnv.ProtectImage(c, "nnp-test:latest") - if testEnv.DaemonPlatform() != runtime.GOOS { + if testEnv.OSType != runtime.GOOS { ensureNNPTestBuild(c) return } diff --git a/vendor/github.com/docker/docker/integration-cli/test_vars_test.go b/vendor/github.com/docker/docker/integration-cli/test_vars_test.go index 139279ccd..82ec58e9e 100644 --- a/vendor/github.com/docker/docker/integration-cli/test_vars_test.go +++ b/vendor/github.com/docker/docker/integration-cli/test_vars_test.go @@ -4,7 +4,7 @@ package main // the command is for a sleeping container based on the daemon platform. // The Windows busybox image does not have a `top` command. func sleepCommandForDaemonPlatform() []string { - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { return []string{"sleep", "240"} } return []string{"top"} diff --git a/vendor/github.com/docker/docker/integration-cli/utils_test.go b/vendor/github.com/docker/docker/integration-cli/utils_test.go index 1146e1b2f..6c18c222d 100644 --- a/vendor/github.com/docker/docker/integration-cli/utils_test.go +++ b/vendor/github.com/docker/docker/integration-cli/utils_test.go @@ -14,7 +14,7 @@ import ( ) func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) { - if testEnv.DaemonPlatform() == "windows" { + if testEnv.OSType == "windows" { return "c:", `\` } return "", "/" diff --git a/vendor/github.com/docker/docker/integration/build/build_test.go b/vendor/github.com/docker/docker/integration/build/build_test.go index cbaa7dc9b..1271daea9 100644 --- a/vendor/github.com/docker/docker/integration/build/build_test.go +++ b/vendor/github.com/docker/docker/integration/build/build_test.go @@ -169,3 +169,101 @@ func TestBuildMultiStageParentConfig(t *testing.T) { assert.Equal(t, "/foo/sub2", image.Config.WorkingDir) assert.Contains(t, image.Config.Env, "WHO=parent") } + +func TestBuildWithEmptyLayers(t *testing.T) { + dockerfile := ` + FROM busybox + COPY 1/ /target/ + COPY 2/ /target/ + COPY 3/ /target/ + ` + ctx := context.Background() + source := fakecontext.New(t, "", + fakecontext.WithDockerfile(dockerfile), + fakecontext.WithFile("1/a", "asdf"), + fakecontext.WithFile("2/a", "asdf"), + fakecontext.WithFile("3/a", "asdf")) + defer source.Close() + + apiclient := testEnv.APIClient() + resp, err := apiclient.ImageBuild(ctx, + source.AsTarReader(t), + types.ImageBuildOptions{ + Remove: true, + ForceRemove: true, + }) + require.NoError(t, err) + _, err = io.Copy(ioutil.Discard, resp.Body) + resp.Body.Close() + require.NoError(t, err) +} + +// TestBuildMultiStageOnBuild checks that ONBUILD commands are applied to +// multiple subsequent stages +// #35652 +func TestBuildMultiStageOnBuild(t *testing.T) { + defer setupTest(t)() + // test both metadata and layer based commands as they may be implemented differently + dockerfile := `FROM busybox AS stage1 +ONBUILD RUN echo 'foo' >somefile +ONBUILD ENV bar=baz + +FROM stage1 +RUN cat somefile # fails if ONBUILD RUN fails + +FROM stage1 +RUN cat somefile` + + ctx := context.Background() + source := fakecontext.New(t, "", + fakecontext.WithDockerfile(dockerfile)) + defer source.Close() + + apiclient := testEnv.APIClient() + resp, err := apiclient.ImageBuild(ctx, + source.AsTarReader(t), + types.ImageBuildOptions{ + Remove: true, + ForceRemove: true, + }) + + out := bytes.NewBuffer(nil) + require.NoError(t, err) + _, err = io.Copy(out, resp.Body) + resp.Body.Close() + require.NoError(t, err) + + assert.Contains(t, out.String(), "Successfully built") + + imageIDs, err := getImageIDsFromBuild(out.Bytes()) + require.NoError(t, err) + assert.Equal(t, 3, len(imageIDs)) + + image, _, err := apiclient.ImageInspectWithRaw(context.Background(), imageIDs[2]) + require.NoError(t, err) + assert.Contains(t, image.Config.Env, "bar=baz") +} + +type buildLine struct { + Stream string + Aux struct { + ID string + } +} + +func getImageIDsFromBuild(output []byte) ([]string, error) { + ids := []string{} + for _, line := range bytes.Split(output, []byte("\n")) { + if len(line) == 0 { + continue + } + entry := buildLine{} + if err := json.Unmarshal(line, &entry); err != nil { + return nil, err + } + if entry.Aux.ID != "" { + ids = append(ids, entry.Aux.ID) + } + } + return ids, nil +} diff --git a/vendor/github.com/docker/docker/integration/container/exec_test.go b/vendor/github.com/docker/docker/integration/container/exec_test.go new file mode 100644 index 000000000..22d7ec01c --- /dev/null +++ b/vendor/github.com/docker/docker/integration/container/exec_test.go @@ -0,0 +1,60 @@ +package container + +import ( + "context" + "io/ioutil" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/strslice" + "github.com/docker/docker/integration/util/request" + "github.com/stretchr/testify/require" +) + +func TestExec(t *testing.T) { + defer setupTest(t)() + ctx := context.Background() + client := request.NewAPIClient(t) + + container, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Tty: true, + WorkingDir: "/root", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "foo", + ) + require.NoError(t, err) + err = client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + + id, err := client.ContainerExecCreate(ctx, container.ID, + types.ExecConfig{ + WorkingDir: "/tmp", + Env: strslice.StrSlice([]string{"FOO=BAR"}), + AttachStdout: true, + Cmd: strslice.StrSlice([]string{"sh", "-c", "env"}), + }, + ) + require.NoError(t, err) + + resp, err := client.ContainerExecAttach(ctx, id.ID, + types.ExecStartCheck{ + Detach: false, + Tty: false, + }, + ) + require.NoError(t, err) + defer resp.Close() + r, err := ioutil.ReadAll(resp.Reader) + require.NoError(t, err) + out := string(r) + require.NoError(t, err) + require.Contains(t, out, "PWD=/tmp", "exec command not running in expected /tmp working directory") + require.Contains(t, out, "FOO=BAR", "exec command not running with expected environment variable FOO") +} diff --git a/vendor/github.com/docker/docker/integration/container/health_test.go b/vendor/github.com/docker/docker/integration/container/health_test.go new file mode 100644 index 000000000..8ed86a86e --- /dev/null +++ b/vendor/github.com/docker/docker/integration/container/health_test.go @@ -0,0 +1,61 @@ +package container + +import ( + "context" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/strslice" + "github.com/docker/docker/client" + "github.com/docker/docker/integration/util/request" + "github.com/gotestyourself/gotestyourself/poll" + "github.com/stretchr/testify/require" +) + +// TestHealthCheckWorkdir verifies that health-checks inherit the containers' +// working-dir. +func TestHealthCheckWorkdir(t *testing.T) { + defer setupTest(t)() + ctx := context.Background() + client := request.NewAPIClient(t) + + c, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Tty: true, + WorkingDir: "/foo", + Cmd: strslice.StrSlice([]string{"top"}), + Healthcheck: &container.HealthConfig{ + Test: []string{"CMD-SHELL", "if [ \"$PWD\" = \"/foo\" ]; then exit 0; else exit 1; fi;"}, + Interval: 50 * time.Millisecond, + Retries: 3, + }, + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "healthtest", + ) + require.NoError(t, err) + err = client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + + poll.WaitOn(t, pollForHealthStatus(ctx, client, c.ID, types.Healthy), poll.WithDelay(100*time.Millisecond)) +} + +func pollForHealthStatus(ctx context.Context, client client.APIClient, containerID string, healthStatus string) func(log poll.LogT) poll.Result { + return func(log poll.LogT) poll.Result { + inspect, err := client.ContainerInspect(ctx, containerID) + + switch { + case err != nil: + return poll.Error(err) + case inspect.State.Health.Status == healthStatus: + return poll.Success() + default: + return poll.Continue("waiting for container to become %s", healthStatus) + } + } +} diff --git a/vendor/github.com/docker/docker/integration/container/mounts_linux_test.go b/vendor/github.com/docker/docker/integration/container/mounts_linux_test.go new file mode 100644 index 000000000..8c13258c3 --- /dev/null +++ b/vendor/github.com/docker/docker/integration/container/mounts_linux_test.go @@ -0,0 +1,84 @@ +package container + +import ( + "bytes" + "context" + "fmt" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/mount" + "github.com/docker/docker/integration-cli/daemon" + "github.com/docker/docker/pkg/stdcopy" +) + +func TestContainerShmNoLeak(t *testing.T) { + t.Parallel() + d := daemon.New(t, "docker", "dockerd", daemon.Config{}) + client, err := d.NewClient() + if err != nil { + t.Fatal(err) + } + d.StartWithBusybox(t) + defer d.Stop(t) + + ctx := context.Background() + cfg := container.Config{ + Image: "busybox", + Cmd: []string{"top"}, + } + + ctr, err := client.ContainerCreate(ctx, &cfg, nil, nil, "") + if err != nil { + t.Fatal(err) + } + defer client.ContainerRemove(ctx, ctr.ID, types.ContainerRemoveOptions{Force: true}) + + if err := client.ContainerStart(ctx, ctr.ID, types.ContainerStartOptions{}); err != nil { + t.Fatal(err) + } + + // this should recursively bind mount everything in the test daemons root + // except of course we are hoping that the previous containers /dev/shm mount did not leak into this new container + hc := container.HostConfig{ + Mounts: []mount.Mount{ + { + Type: mount.TypeBind, + Source: d.Root, + Target: "/testdaemonroot", + BindOptions: &mount.BindOptions{Propagation: mount.PropagationRPrivate}}, + }, + } + cfg.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("mount | grep testdaemonroot | grep containers | grep %s", ctr.ID)} + cfg.AttachStdout = true + cfg.AttachStderr = true + ctrLeak, err := client.ContainerCreate(ctx, &cfg, &hc, nil, "") + if err != nil { + t.Fatal(err) + } + + attach, err := client.ContainerAttach(ctx, ctrLeak.ID, types.ContainerAttachOptions{ + Stream: true, + Stdout: true, + Stderr: true, + }) + if err != nil { + t.Fatal(err) + } + + if err := client.ContainerStart(ctx, ctrLeak.ID, types.ContainerStartOptions{}); err != nil { + t.Fatal(err) + } + + buf := bytes.NewBuffer(nil) + + if _, err := stdcopy.StdCopy(buf, buf, attach.Reader); err != nil { + t.Fatal(err) + } + + out := bytes.TrimSpace(buf.Bytes()) + if !bytes.Equal(out, []byte{}) { + t.Fatalf("mount leaked: %s", string(out)) + } +} diff --git a/vendor/github.com/docker/docker/integration/container/restart_test.go b/vendor/github.com/docker/docker/integration/container/restart_test.go new file mode 100644 index 000000000..cf014b591 --- /dev/null +++ b/vendor/github.com/docker/docker/integration/container/restart_test.go @@ -0,0 +1,112 @@ +package container + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/integration-cli/daemon" +) + +func TestDaemonRestartKillContainers(t *testing.T) { + type testCase struct { + desc string + config *container.Config + hostConfig *container.HostConfig + + xRunning bool + xRunningLiveRestore bool + } + + for _, c := range []testCase{ + { + desc: "container without restart policy", + config: &container.Config{Image: "busybox", Cmd: []string{"top"}}, + xRunningLiveRestore: true, + }, + { + desc: "container with restart=always", + config: &container.Config{Image: "busybox", Cmd: []string{"top"}}, + hostConfig: &container.HostConfig{RestartPolicy: container.RestartPolicy{Name: "always"}}, + xRunning: true, + xRunningLiveRestore: true, + }, + } { + for _, liveRestoreEnabled := range []bool{false, true} { + for fnName, stopDaemon := range map[string]func(*testing.T, *daemon.Daemon){ + "kill-daemon": func(t *testing.T, d *daemon.Daemon) { + if err := d.Kill(); err != nil { + t.Fatal(err) + } + }, + "stop-daemon": func(t *testing.T, d *daemon.Daemon) { + d.Stop(t) + }, + } { + t.Run(fmt.Sprintf("live-restore=%v/%s/%s", liveRestoreEnabled, c.desc, fnName), func(t *testing.T) { + c := c + liveRestoreEnabled := liveRestoreEnabled + stopDaemon := stopDaemon + + t.Parallel() + + d := daemon.New(t, "", "dockerd", daemon.Config{}) + client, err := d.NewClient() + if err != nil { + t.Fatal(err) + } + + args := []string{"--iptables=false"} + if liveRestoreEnabled { + args = append(args, "--live-restore") + } + + d.StartWithBusybox(t, args...) + defer d.Stop(t) + ctx := context.Background() + + resp, err := client.ContainerCreate(ctx, c.config, c.hostConfig, nil, "") + if err != nil { + t.Fatal(err) + } + defer client.ContainerRemove(ctx, resp.ID, types.ContainerRemoveOptions{Force: true}) + + if err := client.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { + t.Fatal(err) + } + + stopDaemon(t, d) + d.Start(t, args...) + + expected := c.xRunning + if liveRestoreEnabled { + expected = c.xRunningLiveRestore + } + + var running bool + for i := 0; i < 30; i++ { + inspect, err := client.ContainerInspect(ctx, resp.ID) + if err != nil { + t.Fatal(err) + } + + running = inspect.State.Running + if running == expected { + break + } + time.Sleep(2 * time.Second) + + } + + if running != expected { + t.Fatalf("got unexpected running state, expected %v, got: %v", expected, running) + } + // TODO(cpuguy83): test pause states... this seems to be rather undefined currently + }) + } + } + } +} diff --git a/vendor/github.com/docker/docker/integration/container/stop_test.go b/vendor/github.com/docker/docker/integration/container/stop_test.go new file mode 100644 index 000000000..feecc6901 --- /dev/null +++ b/vendor/github.com/docker/docker/integration/container/stop_test.go @@ -0,0 +1,74 @@ +package container + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + "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" + "github.com/docker/docker/integration/util/request" + "github.com/gotestyourself/gotestyourself/icmd" + "github.com/gotestyourself/gotestyourself/poll" + "github.com/gotestyourself/gotestyourself/skip" + "github.com/stretchr/testify/require" +) + +func TestDeleteDevicemapper(t *testing.T) { + skip.IfCondition(t, testEnv.DaemonInfo.Driver != "devicemapper") + + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + foo, err := client.ContainerCreate(ctx, + &container.Config{ + Cmd: []string{"echo"}, + Image: "busybox", + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "foo", + ) + require.NoError(t, err) + + err = client.ContainerStart(ctx, foo.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + + inspect, err := client.ContainerInspect(ctx, foo.ID) + require.NoError(t, err) + + poll.WaitOn(t, containerIsStopped(ctx, client, foo.ID), poll.WithDelay(100*time.Millisecond)) + + deviceID := inspect.GraphDriver.Data["DeviceId"] + + // Find pool name from device name + deviceName := inspect.GraphDriver.Data["DeviceName"] + devicePrefix := deviceName[:strings.LastIndex(deviceName, "-")] + devicePool := fmt.Sprintf("/dev/mapper/%s-pool", devicePrefix) + + result := icmd.RunCommand("dmsetup", "message", devicePool, "0", fmt.Sprintf("delete %s", deviceID)) + result.Assert(t, icmd.Success) + + err = client.ContainerRemove(ctx, foo.ID, types.ContainerRemoveOptions{}) + require.NoError(t, err) +} + +func containerIsStopped(ctx context.Context, client client.APIClient, containerID string) func(log poll.LogT) poll.Result { + return func(log poll.LogT) poll.Result { + inspect, err := client.ContainerInspect(ctx, containerID) + + switch { + case err != nil: + return poll.Error(err) + case !inspect.State.Running: + return poll.Success() + default: + return poll.Continue("waiting for container to be stopped") + } + } +} diff --git a/vendor/github.com/docker/docker/integration/container/update_linux_test.go b/vendor/github.com/docker/docker/integration/container/update_linux_test.go new file mode 100644 index 000000000..bb9906ac7 --- /dev/null +++ b/vendor/github.com/docker/docker/integration/container/update_linux_test.go @@ -0,0 +1,108 @@ +package container + +import ( + "bytes" + "context" + "fmt" + "strconv" + "strings" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/integration/util/request" + "github.com/docker/docker/pkg/stdcopy" +) + +func TestUpdateCPUQUota(t *testing.T) { + t.Parallel() + + client := request.NewAPIClient(t) + ctx := context.Background() + + c, err := client.ContainerCreate(ctx, &container.Config{ + Image: "busybox", + Cmd: []string{"top"}, + }, nil, nil, "") + if err != nil { + t.Fatal(err) + } + defer func() { + if err := client.ContainerRemove(ctx, c.ID, types.ContainerRemoveOptions{Force: true}); err != nil { + panic(fmt.Sprintf("failed to clean up after test: %v", err)) + } + }() + + if err := client.ContainerStart(ctx, c.ID, types.ContainerStartOptions{}); err != nil { + t.Fatal(err) + } + + for _, test := range []struct { + desc string + update int64 + }{ + {desc: "some random value", update: 15000}, + {desc: "a higher value", update: 20000}, + {desc: "a lower value", update: 10000}, + {desc: "unset value", update: -1}, + } { + if _, err := client.ContainerUpdate(ctx, c.ID, container.UpdateConfig{ + Resources: container.Resources{ + CPUQuota: test.update, + }, + }); err != nil { + t.Fatal(err) + } + + inspect, err := client.ContainerInspect(ctx, c.ID) + if err != nil { + t.Fatal(err) + } + + if inspect.HostConfig.CPUQuota != test.update { + t.Fatalf("quota not updated in the API, expected %d, got: %d", test.update, inspect.HostConfig.CPUQuota) + } + + execCreate, err := client.ContainerExecCreate(ctx, c.ID, types.ExecConfig{ + Cmd: []string{"/bin/cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"}, + AttachStdout: true, + AttachStderr: true, + }) + if err != nil { + t.Fatal(err) + } + + attach, err := client.ContainerExecAttach(ctx, execCreate.ID, types.ExecStartCheck{}) + if err != nil { + t.Fatal(err) + } + + if err := client.ContainerExecStart(ctx, execCreate.ID, types.ExecStartCheck{}); err != nil { + t.Fatal(err) + } + + buf := bytes.NewBuffer(nil) + ready := make(chan error) + + go func() { + _, err := stdcopy.StdCopy(buf, buf, attach.Reader) + ready <- err + }() + + select { + case <-time.After(60 * time.Second): + t.Fatal("timeout waiting for exec to complete") + case err := <-ready: + if err != nil { + t.Fatal(err) + } + } + + actual := strings.TrimSpace(buf.String()) + if actual != strconv.Itoa(int(test.update)) { + t.Fatalf("expected cgroup value %d, got: %s", test.update, actual) + } + } + +} diff --git a/vendor/github.com/docker/docker/integration/image/commit_test.go b/vendor/github.com/docker/docker/integration/image/commit_test.go new file mode 100644 index 000000000..13edbe117 --- /dev/null +++ b/vendor/github.com/docker/docker/integration/image/commit_test.go @@ -0,0 +1,47 @@ +package image + +import ( + "context" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/integration/util/request" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCommitInheritsEnv(t *testing.T) { + defer setupTest(t)() + client := request.NewAPIClient(t) + ctx := context.Background() + + createResp1, err := client.ContainerCreate(ctx, &container.Config{Image: "busybox"}, nil, nil, "") + require.NoError(t, err) + + commitResp1, err := client.ContainerCommit(ctx, createResp1.ID, types.ContainerCommitOptions{ + Changes: []string{"ENV PATH=/bin"}, + Reference: "test-commit-image", + }) + require.NoError(t, err) + + image1, _, err := client.ImageInspectWithRaw(ctx, commitResp1.ID) + require.NoError(t, err) + + expectedEnv1 := []string{"PATH=/bin"} + assert.Equal(t, expectedEnv1, image1.Config.Env) + + createResp2, err := client.ContainerCreate(ctx, &container.Config{Image: image1.ID}, nil, nil, "") + require.NoError(t, err) + + commitResp2, err := client.ContainerCommit(ctx, createResp2.ID, types.ContainerCommitOptions{ + Changes: []string{"ENV PATH=/usr/bin:$PATH"}, + Reference: "test-commit-image", + }) + require.NoError(t, err) + + image2, _, err := client.ImageInspectWithRaw(ctx, commitResp2.ID) + require.NoError(t, err) + expectedEnv2 := []string{"PATH=/usr/bin:/bin"} + assert.Equal(t, expectedEnv2, image2.Config.Env) +} diff --git a/vendor/github.com/docker/docker/integration/image/import_test.go b/vendor/github.com/docker/docker/integration/image/import_test.go index 955891f28..2bb7ffbdc 100644 --- a/vendor/github.com/docker/docker/integration/image/import_test.go +++ b/vendor/github.com/docker/docker/integration/image/import_test.go @@ -5,6 +5,7 @@ import ( "bytes" "context" "io" + "runtime" "testing" "github.com/docker/docker/api/types" @@ -14,12 +15,17 @@ import ( // Ensure we don't regress on CVE-2017-14992. func TestImportExtremelyLargeImageWorks(t *testing.T) { + if runtime.GOARCH == "arm64" { + t.Skip("effective test will be time out") + } + client := request.NewAPIClient(t) // Construct an empty tar archive with about 8GB of junk padding at the // end. This should not cause any crashes (the padding should be mostly // ignored). var tarBuffer bytes.Buffer + tw := tar.NewWriter(&tarBuffer) if err := tw.Close(); err != nil { t.Fatal(err) diff --git a/vendor/github.com/docker/docker/integration/service/create_test.go b/vendor/github.com/docker/docker/integration/service/create_test.go index e94185a54..7e78b9499 100644 --- a/vendor/github.com/docker/docker/integration/service/create_test.go +++ b/vendor/github.com/docker/docker/integration/service/create_test.go @@ -16,7 +16,7 @@ import ( "golang.org/x/net/context" ) -func TestCreateWithLBSandbox(t *testing.T) { +func TestCreateServiceMultipleTimes(t *testing.T) { defer setupTest(t)() d := newSwarm(t) defer d.Stop(t) @@ -33,9 +33,8 @@ func TestCreateWithLBSandbox(t *testing.T) { require.NoError(t, err) overlayID := netResp.ID - var instances uint64 = 1 + var instances uint64 = 4 serviceSpec := swarmServiceSpec("TestService", instances) - serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: overlayName}) serviceResp, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{ @@ -44,7 +43,8 @@ func TestCreateWithLBSandbox(t *testing.T) { require.NoError(t, err) pollSettings := func(config *poll.Settings) { - if runtime.GOARCH == "arm" { + // It takes about ~25s to finish the multi services creation in this case per the pratical observation on arm64/arm platform + if runtime.GOARCH == "arm64" || runtime.GOARCH == "arm" { config.Timeout = 30 * time.Second config.Delay = 100 * time.Millisecond } @@ -56,20 +56,94 @@ func TestCreateWithLBSandbox(t *testing.T) { _, _, err = client.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) require.NoError(t, err) - network, err := client.NetworkInspect(context.Background(), overlayID, types.NetworkInspectOptions{}) - require.NoError(t, err) - assert.Contains(t, network.Containers, overlayName+"-sbox") - err = client.ServiceRemove(context.Background(), serviceID) require.NoError(t, err) poll.WaitOn(t, serviceIsRemoved(client, serviceID), pollSettings) + poll.WaitOn(t, noTasks(client), pollSettings) + + serviceResp, err = client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{ + QueryRegistry: false, + }) + require.NoError(t, err) + + serviceID2 := serviceResp.ID + poll.WaitOn(t, serviceRunningTasksCount(client, serviceID2, instances), pollSettings) + + err = client.ServiceRemove(context.Background(), serviceID2) + require.NoError(t, err) + + poll.WaitOn(t, serviceIsRemoved(client, serviceID2), pollSettings) + poll.WaitOn(t, noTasks(client), pollSettings) + err = client.NetworkRemove(context.Background(), overlayID) require.NoError(t, err) poll.WaitOn(t, networkIsRemoved(client, overlayID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) } +func TestCreateWithDuplicateNetworkNames(t *testing.T) { + defer setupTest(t)() + d := newSwarm(t) + defer d.Stop(t) + client, err := request.NewClientForHost(d.Sock()) + require.NoError(t, err) + + name := "foo" + networkCreate := types.NetworkCreate{ + CheckDuplicate: false, + Driver: "bridge", + } + + n1, err := client.NetworkCreate(context.Background(), name, networkCreate) + require.NoError(t, err) + + n2, err := client.NetworkCreate(context.Background(), name, networkCreate) + require.NoError(t, err) + + // Dupliates with name but with different driver + networkCreate.Driver = "overlay" + n3, err := client.NetworkCreate(context.Background(), name, networkCreate) + require.NoError(t, err) + + // Create Service with the same name + var instances uint64 = 1 + serviceSpec := swarmServiceSpec("top", instances) + + serviceSpec.TaskTemplate.Networks = append(serviceSpec.TaskTemplate.Networks, swarm.NetworkAttachmentConfig{Target: name}) + + service, err := client.ServiceCreate(context.Background(), serviceSpec, types.ServiceCreateOptions{}) + require.NoError(t, err) + + poll.WaitOn(t, serviceRunningTasksCount(client, service.ID, instances)) + + resp, _, err := client.ServiceInspectWithRaw(context.Background(), service.ID, types.ServiceInspectOptions{}) + require.NoError(t, err) + assert.Equal(t, n3.ID, resp.Spec.TaskTemplate.Networks[0].Target) + + // Remove Service + err = client.ServiceRemove(context.Background(), service.ID) + require.NoError(t, err) + + // Make sure task has been destroyed. + poll.WaitOn(t, serviceIsRemoved(client, service.ID)) + + // Remove networks + err = client.NetworkRemove(context.Background(), n3.ID) + require.NoError(t, err) + + err = client.NetworkRemove(context.Background(), n2.ID) + require.NoError(t, err) + + err = client.NetworkRemove(context.Background(), n1.ID) + require.NoError(t, err) + + // Make sure networks have been destroyed. + poll.WaitOn(t, networkIsRemoved(client, n3.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) + poll.WaitOn(t, networkIsRemoved(client, n2.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) + poll.WaitOn(t, networkIsRemoved(client, n1.ID), poll.WithTimeout(1*time.Minute), poll.WithDelay(10*time.Second)) +} + func swarmServiceSpec(name string, replicas uint64) swarm.ServiceSpec { return swarm.ServiceSpec{ Annotations: swarm.Annotations{ @@ -112,6 +186,23 @@ func serviceRunningTasksCount(client client.ServiceAPIClient, serviceID string, } } +func noTasks(client client.ServiceAPIClient) func(log poll.LogT) poll.Result { + return func(log poll.LogT) poll.Result { + filter := filters.NewArgs() + tasks, err := client.TaskList(context.Background(), types.TaskListOptions{ + Filters: filter, + }) + switch { + case err != nil: + return poll.Error(err) + case len(tasks) == 0: + return poll.Success() + default: + return poll.Continue("task count at %d waiting for 0", len(tasks)) + } + } +} + func serviceIsRemoved(client client.ServiceAPIClient, serviceID string) func(log poll.LogT) poll.Result { return func(log poll.LogT) poll.Result { filter := filters.NewArgs() diff --git a/vendor/github.com/docker/docker/integration/system/event_test.go b/vendor/github.com/docker/docker/integration/system/event_test.go new file mode 100644 index 000000000..ef7eb1ff5 --- /dev/null +++ b/vendor/github.com/docker/docker/integration/system/event_test.go @@ -0,0 +1,74 @@ +package system + +import ( + "context" + "testing" + + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/strslice" + "github.com/docker/docker/integration/util/request" + "github.com/stretchr/testify/require" +) + +func TestEvents(t *testing.T) { + defer setupTest(t)() + ctx := context.Background() + client := request.NewAPIClient(t) + + container, err := client.ContainerCreate(ctx, + &container.Config{ + Image: "busybox", + Tty: true, + WorkingDir: "/root", + Cmd: strslice.StrSlice([]string{"top"}), + }, + &container.HostConfig{}, + &network.NetworkingConfig{}, + "foo", + ) + require.NoError(t, err) + err = client.ContainerStart(ctx, container.ID, types.ContainerStartOptions{}) + require.NoError(t, err) + + id, err := client.ContainerExecCreate(ctx, container.ID, + types.ExecConfig{ + Cmd: strslice.StrSlice([]string{"echo", "hello"}), + }, + ) + require.NoError(t, err) + + filters := filters.NewArgs( + filters.Arg("container", container.ID), + filters.Arg("event", "exec_die"), + ) + msg, errors := client.Events(ctx, types.EventsOptions{ + Filters: filters, + }) + + err = client.ContainerExecStart(ctx, id.ID, + types.ExecStartCheck{ + Detach: true, + Tty: false, + }, + ) + require.NoError(t, err) + + select { + case m := <-msg: + require.Equal(t, m.Type, "container") + require.Equal(t, m.Actor.ID, container.ID) + require.Equal(t, m.Action, "exec_die") + require.Equal(t, m.Actor.Attributes["execID"], id.ID) + require.Equal(t, m.Actor.Attributes["exitCode"], "0") + case err = <-errors: + t.Fatal(err) + case <-time.After(time.Second * 3): + t.Fatal("timeout hit") + } + +} diff --git a/vendor/github.com/docker/docker/integration/system/info_linux_test.go b/vendor/github.com/docker/docker/integration/system/info_linux_test.go new file mode 100644 index 000000000..bea14eadd --- /dev/null +++ b/vendor/github.com/docker/docker/integration/system/info_linux_test.go @@ -0,0 +1,34 @@ +// +build !windows + +package system + +import ( + "testing" + + "github.com/docker/docker/integration/util/request" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/net/context" +) + +func TestInfo_BinaryCommits(t *testing.T) { + client := request.NewAPIClient(t) + + info, err := client.Info(context.Background()) + require.NoError(t, err) + + assert.NotNil(t, info.ContainerdCommit) + assert.NotEqual(t, "N/A", info.ContainerdCommit.ID) + assert.Equal(t, testEnv.DaemonInfo.ContainerdCommit.Expected, info.ContainerdCommit.Expected) + assert.Equal(t, info.ContainerdCommit.Expected, info.ContainerdCommit.ID) + + assert.NotNil(t, info.InitCommit) + assert.NotEqual(t, "N/A", info.InitCommit.ID) + assert.Equal(t, testEnv.DaemonInfo.InitCommit.Expected, info.InitCommit.Expected) + assert.Equal(t, info.InitCommit.Expected, info.InitCommit.ID) + + assert.NotNil(t, info.RuncCommit) + assert.NotEqual(t, "N/A", info.RuncCommit.ID) + assert.Equal(t, testEnv.DaemonInfo.RuncCommit.Expected, info.RuncCommit.Expected) + assert.Equal(t, info.RuncCommit.Expected, info.RuncCommit.ID) +} diff --git a/vendor/github.com/docker/docker/internal/testutil/helpers.go b/vendor/github.com/docker/docker/internal/testutil/helpers.go index 287b3cb48..bb36322a8 100644 --- a/vendor/github.com/docker/docker/internal/testutil/helpers.go +++ b/vendor/github.com/docker/docker/internal/testutil/helpers.go @@ -20,8 +20,8 @@ var DevZero io.Reader = devZero{} type devZero struct{} func (d devZero) Read(p []byte) (n int, err error) { - for i := 0; i < len(p); i++ { - p[i] = '\x00' + for i := range p { + p[i] = 0 } return len(p), nil } diff --git a/vendor/github.com/docker/docker/layer/empty.go b/vendor/github.com/docker/docker/layer/empty.go index 7924a56e3..80f2c1243 100644 --- a/vendor/github.com/docker/docker/layer/empty.go +++ b/vendor/github.com/docker/docker/layer/empty.go @@ -55,10 +55,6 @@ func (el *emptyLayer) Metadata() (map[string]string, error) { return make(map[string]string), nil } -func (el *emptyLayer) OS() OS { - return "" -} - // IsEmpty returns true if the layer is an EmptyLayer func IsEmpty(diffID DiffID) bool { return diffID == DigestSHA256EmptyTar diff --git a/vendor/github.com/docker/docker/layer/filestore_unix.go b/vendor/github.com/docker/docker/layer/filestore_unix.go index 35e282ee4..898774bdc 100644 --- a/vendor/github.com/docker/docker/layer/filestore_unix.go +++ b/vendor/github.com/docker/docker/layer/filestore_unix.go @@ -2,12 +2,14 @@ package layer -// SetOS writes the "os" file to the layer filestore -func (fm *fileMetadataTransaction) SetOS(os OS) error { +import "runtime" + +// setOS writes the "os" file to the layer filestore +func (fm *fileMetadataTransaction) setOS(os string) error { return nil } -// GetOS reads the "os" file from the layer filestore -func (fms *fileMetadataStore) GetOS(layer ChainID) (OS, error) { - return "", nil +// getOS reads the "os" file from the layer filestore +func (fms *fileMetadataStore) getOS(layer ChainID) (string, error) { + return runtime.GOOS, nil } diff --git a/vendor/github.com/docker/docker/layer/filestore_windows.go b/vendor/github.com/docker/docker/layer/filestore_windows.go index 25daa2104..199b0b7a5 100644 --- a/vendor/github.com/docker/docker/layer/filestore_windows.go +++ b/vendor/github.com/docker/docker/layer/filestore_windows.go @@ -7,16 +7,16 @@ import ( "strings" ) -// SetOS writes the "os" file to the layer filestore -func (fm *fileMetadataTransaction) SetOS(os OS) error { +// setOS writes the "os" file to the layer filestore +func (fm *fileMetadataTransaction) setOS(os string) error { if os == "" { return nil } return fm.ws.WriteFile("os", []byte(os), 0644) } -// GetOS reads the "os" file from the layer filestore -func (fms *fileMetadataStore) GetOS(layer ChainID) (OS, error) { +// getOS reads the "os" file from the layer filestore +func (fms *fileMetadataStore) getOS(layer ChainID) (string, error) { contentBytes, err := ioutil.ReadFile(fms.getLayerFilename(layer, "os")) if err != nil { // For backwards compatibility, the os file may not exist. Default to "windows" if missing. @@ -31,5 +31,5 @@ func (fms *fileMetadataStore) GetOS(layer ChainID) (OS, error) { return "", fmt.Errorf("invalid operating system value: %s", content) } - return OS(content), nil + return content, nil } diff --git a/vendor/github.com/docker/docker/layer/layer.go b/vendor/github.com/docker/docker/layer/layer.go index 08fc789d9..2603ac592 100644 --- a/vendor/github.com/docker/docker/layer/layer.go +++ b/vendor/github.com/docker/docker/layer/layer.go @@ -65,14 +65,6 @@ func (id ChainID) String() string { return string(id) } -// OS is the operating system of a layer -type OS string - -// String returns a string rendition of layers target operating system -func (id OS) String() string { - return string(id) -} - // DiffID is the hash of an individual layer tar. type DiffID digest.Digest @@ -108,9 +100,6 @@ type Layer interface { // Parent returns the next layer in the layer chain. Parent() Layer - // OS returns the operating system of the layer - OS() OS - // Size returns the size of the entire layer chain. The size // is calculated from the total size of all files in the layers. Size() (int64, error) @@ -191,7 +180,7 @@ type CreateRWLayerOpts struct { // Store represents a backend for managing both // read-only and read-write layers. type Store interface { - Register(io.Reader, ChainID, OS) (Layer, error) + Register(io.Reader, ChainID) (Layer, error) Get(ChainID) (Layer, error) Map() map[ChainID]Layer Release(Layer) ([]Metadata, error) @@ -209,7 +198,7 @@ type Store interface { // DescribableStore represents a layer store capable of storing // descriptors for layers. type DescribableStore interface { - RegisterWithDescriptor(io.Reader, ChainID, OS, distribution.Descriptor) (Layer, error) + RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error) } // MetadataTransaction represents functions for setting layer metadata @@ -220,7 +209,7 @@ type MetadataTransaction interface { SetDiffID(DiffID) error SetCacheID(string) error SetDescriptor(distribution.Descriptor) error - SetOS(OS) error + setOS(string) error TarSplitWriter(compressInput bool) (io.WriteCloser, error) Commit(ChainID) error @@ -241,7 +230,7 @@ type MetadataStore interface { GetDiffID(ChainID) (DiffID, error) GetCacheID(ChainID) (string, error) GetDescriptor(ChainID) (distribution.Descriptor, error) - GetOS(ChainID) (OS, error) + getOS(ChainID) (string, error) TarSplitReader(ChainID) (io.ReadCloser, error) SetMountID(string, string) error diff --git a/vendor/github.com/docker/docker/layer/layer_store.go b/vendor/github.com/docker/docker/layer/layer_store.go index 27abcdeec..c6225386d 100644 --- a/vendor/github.com/docker/docker/layer/layer_store.go +++ b/vendor/github.com/docker/docker/layer/layer_store.go @@ -5,7 +5,6 @@ import ( "fmt" "io" "io/ioutil" - "strings" "sync" "github.com/docker/distribution" @@ -28,23 +27,21 @@ import ( const maxLayerDepth = 125 type layerStore struct { - store MetadataStore - driver graphdriver.Driver + store MetadataStore + driver graphdriver.Driver + useTarSplit bool layerMap map[ChainID]*roLayer layerL sync.Mutex mounts map[string]*mountedLayer mountL sync.Mutex - - useTarSplit bool - - os string + os string } // StoreOptions are the options used to create a new Store instance type StoreOptions struct { - StorePath string + Root string MetadataStorePathTemplate string GraphDriver string GraphDriverOptions []string @@ -57,7 +54,7 @@ type StoreOptions struct { // NewStoreFromOptions creates a new Store instance func NewStoreFromOptions(options StoreOptions) (Store, error) { driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{ - Root: options.StorePath, + Root: options.Root, DriverOptions: options.GraphDriverOptions, UIDMaps: options.IDMappings.UIDs(), GIDMaps: options.IDMappings.GIDs(), @@ -66,7 +63,7 @@ func NewStoreFromOptions(options StoreOptions) (Store, error) { if err != nil { return nil, fmt.Errorf("error initializing graphdriver: %v", err) } - logrus.Debugf("Using graph driver %s", driver) + logrus.Debugf("Initialized graph driver %s", driver) fms, err := NewFSMetadataStore(fmt.Sprintf(options.MetadataStorePathTemplate, driver)) if err != nil { @@ -80,6 +77,9 @@ func NewStoreFromOptions(options StoreOptions) (Store, error) { // metadata store and graph driver. The metadata store will be used to restore // the Store. func NewStoreFromGraphDriver(store MetadataStore, driver graphdriver.Driver, os string) (Store, error) { + if !system.IsOSSupported(os) { + return nil, fmt.Errorf("failed to initialize layer store as operating system '%s' is not supported", os) + } caps := graphdriver.Capabilities{} if capDriver, ok := driver.(graphdriver.CapabilityDriver); ok { caps = capDriver.Capabilities() @@ -150,11 +150,15 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) { return nil, fmt.Errorf("failed to get descriptor for %s: %s", layer, err) } - os, err := ls.store.GetOS(layer) + os, err := ls.store.getOS(layer) if err != nil { return nil, fmt.Errorf("failed to get operating system for %s: %s", layer, err) } + if os != ls.os { + return nil, fmt.Errorf("failed to load layer with os %s into layerstore for %s", os, ls.os) + } + cl = &roLayer{ chainID: layer, diffID: diff, @@ -163,7 +167,6 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) { layerStore: ls, references: map[Layer]struct{}{}, descriptor: descriptor, - os: os, } if parent != "" { @@ -259,11 +262,11 @@ func (ls *layerStore) applyTar(tx MetadataTransaction, ts io.Reader, parent stri return nil } -func (ls *layerStore) Register(ts io.Reader, parent ChainID, os OS) (Layer, error) { - return ls.registerWithDescriptor(ts, parent, os, distribution.Descriptor{}) +func (ls *layerStore) Register(ts io.Reader, parent ChainID) (Layer, error) { + return ls.registerWithDescriptor(ts, parent, distribution.Descriptor{}) } -func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, os OS, descriptor distribution.Descriptor) (Layer, error) { +func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) { // err is used to hold the error which will always trigger // cleanup of creates sources but may not be an error returned // to the caller (already exists). @@ -271,13 +274,6 @@ func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, os OS var pid string var p *roLayer - // Integrity check - ensure we are creating something for the correct operating system - if system.LCOWSupported() { - if strings.ToLower(ls.os) != strings.ToLower(string(os)) { - return nil, fmt.Errorf("cannot create entry for operating system %q in layer store for operating system %q", os, ls.os) - } - } - if string(parent) != "" { p = ls.get(parent) if p == nil { @@ -306,7 +302,6 @@ func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, os OS layerStore: ls, references: map[Layer]struct{}{}, descriptor: descriptor, - os: os, } if err = ls.driver.Create(layer.cacheID, pid, nil); err != nil { diff --git a/vendor/github.com/docker/docker/layer/layer_store_windows.go b/vendor/github.com/docker/docker/layer/layer_store_windows.go index 8e93119fd..1276a912c 100644 --- a/vendor/github.com/docker/docker/layer/layer_store_windows.go +++ b/vendor/github.com/docker/docker/layer/layer_store_windows.go @@ -6,6 +6,6 @@ import ( "github.com/docker/distribution" ) -func (ls *layerStore) RegisterWithDescriptor(ts io.Reader, parent ChainID, os OS, descriptor distribution.Descriptor) (Layer, error) { - return ls.registerWithDescriptor(ts, parent, os, descriptor) +func (ls *layerStore) RegisterWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) { + return ls.registerWithDescriptor(ts, parent, descriptor) } diff --git a/vendor/github.com/docker/docker/layer/layer_test.go b/vendor/github.com/docker/docker/layer/layer_test.go index 6936faeb2..edd9c9f4c 100644 --- a/vendor/github.com/docker/docker/layer/layer_test.go +++ b/vendor/github.com/docker/docker/layer/layer_test.go @@ -23,7 +23,7 @@ import ( func init() { graphdriver.ApplyUncompressedLayer = archive.UnpackLayer defaultArchiver := archive.NewDefaultArchiver() - vfs.CopyWithTar = defaultArchiver.CopyWithTar + vfs.CopyDir = defaultArchiver.CopyWithTar } func newVFSGraphDriver(td string) (graphdriver.Driver, error) { @@ -108,7 +108,7 @@ func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) { } defer ts.Close() - layer, err := ls.Register(ts, parent, OS(runtime.GOOS)) + layer, err := ls.Register(ts, parent) if err != nil { return nil, err } @@ -153,10 +153,7 @@ func (tf *testFile) ApplyFile(root containerfs.ContainerFS) error { return err } } - if err := driver.WriteFile(root, fullPath, tf.content, tf.permission); err != nil { - return err - } - return nil + return driver.WriteFile(root, fullPath, tf.content, tf.permission) } func initWithFiles(files ...FileApplier) layerInit { @@ -501,7 +498,7 @@ func TestTarStreamStability(t *testing.T) { t.Fatal(err) } - layer1, err := ls.Register(bytes.NewReader(tar1), "", OS(runtime.GOOS)) + layer1, err := ls.Register(bytes.NewReader(tar1), "") if err != nil { t.Fatal(err) } @@ -520,7 +517,7 @@ func TestTarStreamStability(t *testing.T) { t.Fatal(err) } - layer2, err := ls.Register(bytes.NewReader(tar2), layer1.ChainID(), OS(runtime.GOOS)) + layer2, err := ls.Register(bytes.NewReader(tar2), layer1.ChainID()) if err != nil { t.Fatal(err) } @@ -688,12 +685,12 @@ func TestRegisterExistingLayer(t *testing.T) { t.Fatal(err) } - layer2a, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID(), OS(runtime.GOOS)) + layer2a, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID()) if err != nil { t.Fatal(err) } - layer2b, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID(), OS(runtime.GOOS)) + layer2b, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID()) if err != nil { t.Fatal(err) } @@ -728,12 +725,12 @@ func TestTarStreamVerification(t *testing.T) { t.Fatal(err) } - layer1, err := ls.Register(bytes.NewReader(tar1), "", OS(runtime.GOOS)) + layer1, err := ls.Register(bytes.NewReader(tar1), "") if err != nil { t.Fatal(err) } - layer2, err := ls.Register(bytes.NewReader(tar2), "", OS(runtime.GOOS)) + layer2, err := ls.Register(bytes.NewReader(tar2), "") if err != nil { t.Fatal(err) } diff --git a/vendor/github.com/docker/docker/layer/layer_unix_test.go b/vendor/github.com/docker/docker/layer/layer_unix_test.go index 9aa1afd59..c11f3bece 100644 --- a/vendor/github.com/docker/docker/layer/layer_unix_test.go +++ b/vendor/github.com/docker/docker/layer/layer_unix_test.go @@ -2,7 +2,9 @@ package layer -import "testing" +import ( + "testing" +) func graphDiffSize(ls Store, l Layer) (int64, error) { cl := getCachedLayer(l) diff --git a/vendor/github.com/docker/docker/layer/layer_windows.go b/vendor/github.com/docker/docker/layer/layer_windows.go index d02d4d0dd..c379c1b86 100644 --- a/vendor/github.com/docker/docker/layer/layer_windows.go +++ b/vendor/github.com/docker/docker/layer/layer_windows.go @@ -28,7 +28,6 @@ func GetLayerPath(s Store, layer ChainID) (string, error) { if layerGetter, ok := ls.driver.(Getter); ok { return layerGetter.GetLayerPath(rl.cacheID) } - path, err := ls.driver.Get(rl.cacheID, "") if err != nil { return "", err diff --git a/vendor/github.com/docker/docker/layer/migration.go b/vendor/github.com/docker/docker/layer/migration.go index f4c4adec4..21b43b73e 100644 --- a/vendor/github.com/docker/docker/layer/migration.go +++ b/vendor/github.com/docker/docker/layer/migration.go @@ -16,7 +16,7 @@ import ( // CreateRWLayerByGraphID creates a RWLayer in the layer store using // the provided name with the given graphID. To get the RWLayer // after migration the layer may be retrieved by the given name. -func (ls *layerStore) CreateRWLayerByGraphID(name string, graphID string, parent ChainID) (err error) { +func (ls *layerStore) CreateRWLayerByGraphID(name, graphID string, parent ChainID) (err error) { ls.mountL.Lock() defer ls.mountL.Unlock() m, ok := ls.mounts[name] @@ -68,11 +68,7 @@ func (ls *layerStore) CreateRWLayerByGraphID(name string, graphID string, parent m.initID = initID } - if err = ls.saveMount(m); err != nil { - return err - } - - return nil + return ls.saveMount(m) } func (ls *layerStore) ChecksumForGraphID(id, parent, oldTarDataPath, newTarDataPath string) (diffID DiffID, size int64, err error) { diff --git a/vendor/github.com/docker/docker/layer/migration_test.go b/vendor/github.com/docker/docker/layer/migration_test.go index cc63a014d..e2acd19c2 100644 --- a/vendor/github.com/docker/docker/layer/migration_test.go +++ b/vendor/github.com/docker/docker/layer/migration_test.go @@ -110,14 +110,14 @@ func TestLayerMigration(t *testing.T) { t.Fatal(err) } - layer1b, err := ls.Register(bytes.NewReader(tar1), "", OS(runtime.GOOS)) + layer1b, err := ls.Register(bytes.NewReader(tar1), "") if err != nil { t.Fatal(err) } assertReferences(t, layer1a, layer1b) // Attempt register, should be same - layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID(), OS(runtime.GOOS)) + layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID()) if err != nil { t.Fatal(err) } @@ -238,7 +238,7 @@ func TestLayerMigrationNoTarsplit(t *testing.T) { t.Fatal(err) } - layer1b, err := ls.Register(bytes.NewReader(tar1), "", OS(runtime.GOOS)) + layer1b, err := ls.Register(bytes.NewReader(tar1), "") if err != nil { t.Fatal(err) } @@ -246,7 +246,7 @@ func TestLayerMigrationNoTarsplit(t *testing.T) { assertReferences(t, layer1a, layer1b) // Attempt register, should be same - layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID(), OS(runtime.GOOS)) + layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID()) if err != nil { t.Fatal(err) } diff --git a/vendor/github.com/docker/docker/layer/ro_layer.go b/vendor/github.com/docker/docker/layer/ro_layer.go index f634194b8..29fa85362 100644 --- a/vendor/github.com/docker/docker/layer/ro_layer.go +++ b/vendor/github.com/docker/docker/layer/ro_layer.go @@ -16,7 +16,6 @@ type roLayer struct { size int64 layerStore *layerStore descriptor distribution.Descriptor - os OS referenceCount int references map[Layer]struct{} @@ -143,7 +142,7 @@ func storeLayer(tx MetadataTransaction, layer *roLayer) error { return err } } - if err := tx.SetOS(layer.os); err != nil { + if err := tx.setOS(layer.layerStore.os); err != nil { return err } diff --git a/vendor/github.com/docker/docker/layer/ro_layer_unix.go b/vendor/github.com/docker/docker/layer/ro_layer_unix.go deleted file mode 100644 index f0c2003f3..000000000 --- a/vendor/github.com/docker/docker/layer/ro_layer_unix.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build !windows - -package layer - -func (rl *roLayer) OS() OS { - return "" -} diff --git a/vendor/github.com/docker/docker/layer/ro_layer_windows.go b/vendor/github.com/docker/docker/layer/ro_layer_windows.go index 1210f1028..32bd7182a 100644 --- a/vendor/github.com/docker/docker/layer/ro_layer_windows.go +++ b/vendor/github.com/docker/docker/layer/ro_layer_windows.go @@ -7,10 +7,3 @@ var _ distribution.Describable = &roLayer{} func (rl *roLayer) Descriptor() distribution.Descriptor { return rl.descriptor } - -func (rl *roLayer) OS() OS { - if rl.os == "" { - return "windows" - } - return rl.os -} diff --git a/vendor/github.com/docker/docker/libcontainerd/client_daemon.go b/vendor/github.com/docker/docker/libcontainerd/client_daemon.go index f1b5f011f..9e66d224c 100644 --- a/vendor/github.com/docker/docker/libcontainerd/client_daemon.go +++ b/vendor/github.com/docker/docker/libcontainerd/client_daemon.go @@ -21,13 +21,17 @@ import ( "google.golang.org/grpc/status" "github.com/containerd/containerd" + "github.com/containerd/containerd/api/events" eventsapi "github.com/containerd/containerd/api/services/events/v1" "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/archive" + "github.com/containerd/containerd/cio" "github.com/containerd/containerd/content" + containerderrors "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" - "github.com/containerd/containerd/linux/runcopts" + "github.com/containerd/containerd/linux/runctypes" "github.com/containerd/typeurl" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/ioutils" "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/runtime-spec/specs-go" @@ -40,7 +44,7 @@ import ( const InitProcessName = "init" type container struct { - sync.Mutex + mu sync.Mutex bundleDir string ctr containerd.Container @@ -49,6 +53,54 @@ type container struct { oomKilled bool } +func (c *container) setTask(t containerd.Task) { + c.mu.Lock() + c.task = t + c.mu.Unlock() +} + +func (c *container) getTask() containerd.Task { + c.mu.Lock() + t := c.task + c.mu.Unlock() + return t +} + +func (c *container) addProcess(id string, p containerd.Process) { + c.mu.Lock() + if c.execs == nil { + c.execs = make(map[string]containerd.Process) + } + c.execs[id] = p + c.mu.Unlock() +} + +func (c *container) deleteProcess(id string) { + c.mu.Lock() + delete(c.execs, id) + c.mu.Unlock() +} + +func (c *container) getProcess(id string) containerd.Process { + c.mu.Lock() + p := c.execs[id] + c.mu.Unlock() + return p +} + +func (c *container) setOOMKilled(killed bool) { + c.mu.Lock() + c.oomKilled = killed + c.mu.Unlock() +} + +func (c *container) getOOMKilled() bool { + c.mu.Lock() + killed := c.oomKilled + c.mu.Unlock() + return killed +} + type client struct { sync.RWMutex // protects containers map @@ -70,8 +122,12 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallba c.Lock() defer c.Unlock() - var cio containerd.IO + var dio *cio.DirectIO defer func() { + if err != nil && dio != nil { + dio.Cancel() + dio.Close() + } err = wrapError(err) }() @@ -80,23 +136,17 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallba return false, -1, errors.WithStack(err) } - defer func() { - if err != nil && cio != nil { - cio.Cancel() - cio.Close() - } - }() - - t, err := ctr.Task(ctx, func(fifos *containerd.FIFOSet) (containerd.IO, error) { - io, err := newIOPipe(fifos) + attachIO := func(fifos *cio.FIFOSet) (cio.IO, error) { + // dio must be assigned to the previously defined dio for the defer above + // to handle cleanup + dio, err = cio.NewDirectIO(ctx, fifos) if err != nil { return nil, err } - - cio, err = attachStdio(io) - return cio, err - }) - if err != nil && !strings.Contains(err.Error(), "no running task found") { + return attachStdio(dio) + } + t, err := ctr.Task(ctx, attachIO) + if err != nil && !errdefs.IsNotFound(errors.Cause(err)) { return false, -1, err } @@ -132,7 +182,7 @@ func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, run bdir, err := prepareBundleDir(filepath.Join(c.stateDir, id), ociSpec) if err != nil { - return wrapSystemError(errors.Wrap(err, "prepare bundle dir failed")) + return errdefs.System(errors.Wrap(err, "prepare bundle dir failed")) } c.logger.WithField("bundle", bdir).WithField("root", ociSpec.Root.Path).Debug("bundle dir created") @@ -158,17 +208,17 @@ func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, run // Start create and start a task for the specified containerd id func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin bool, attachStdio StdioCallback) (int, error) { ctr := c.getContainer(id) - switch { - case ctr == nil: + if ctr == nil { return -1, errors.WithStack(newNotFoundError("no such container")) - case ctr.task != nil: + } + if t := ctr.getTask(); t != nil { return -1, errors.WithStack(newConflictError("container already started")) } var ( cp *types.Descriptor t containerd.Task - cio containerd.IO + rio cio.IO err error stdinCloseSync = make(chan struct{}) ) @@ -203,31 +253,30 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin } uid, gid := getSpecUser(spec) t, err = ctr.ctr.NewTask(ctx, - func(id string) (containerd.IO, error) { - fifos := newFIFOSet(ctr.bundleDir, id, InitProcessName, withStdin, spec.Process.Terminal) - cio, err = c.createIO(fifos, id, InitProcessName, stdinCloseSync, attachStdio) - return cio, err + func(id string) (cio.IO, error) { + fifos := newFIFOSet(ctr.bundleDir, InitProcessName, withStdin, spec.Process.Terminal) + rio, err = c.createIO(fifos, id, InitProcessName, stdinCloseSync, attachStdio) + return rio, err }, func(_ context.Context, _ *containerd.Client, info *containerd.TaskInfo) error { info.Checkpoint = cp - info.Options = &runcopts.CreateOptions{ - IoUid: uint32(uid), - IoGid: uint32(gid), + info.Options = &runctypes.CreateOptions{ + IoUid: uint32(uid), + IoGid: uint32(gid), + NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "", } return nil }) if err != nil { close(stdinCloseSync) - if cio != nil { - cio.Cancel() - cio.Close() + if rio != nil { + rio.Cancel() + rio.Close() } return -1, err } - c.Lock() - c.containers[id].task = t - c.Unlock() + ctr.setTask(t) // Signal c.createIO that it can call CloseIO close(stdinCloseSync) @@ -237,9 +286,7 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin c.logger.WithError(err).WithField("container", id). Error("failed to delete task after fail start") } - c.Lock() - c.containers[id].task = nil - c.Unlock() + ctr.setTask(nil) return -1, err } @@ -248,62 +295,53 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin func (c *client) Exec(ctx context.Context, containerID, processID string, spec *specs.Process, withStdin bool, attachStdio StdioCallback) (int, error) { ctr := c.getContainer(containerID) - switch { - case ctr == nil: + if ctr == nil { return -1, errors.WithStack(newNotFoundError("no such container")) - case ctr.task == nil: + } + t := ctr.getTask() + if t == nil { return -1, errors.WithStack(newInvalidParameterError("container is not running")) - case ctr.execs != nil && ctr.execs[processID] != nil: + } + + if p := ctr.getProcess(processID); p != nil { return -1, errors.WithStack(newConflictError("id already in use")) } var ( p containerd.Process - cio containerd.IO + rio cio.IO err error stdinCloseSync = make(chan struct{}) ) - fifos := newFIFOSet(ctr.bundleDir, containerID, processID, withStdin, spec.Terminal) + fifos := newFIFOSet(ctr.bundleDir, processID, withStdin, spec.Terminal) defer func() { if err != nil { - if cio != nil { - cio.Cancel() - cio.Close() + if rio != nil { + rio.Cancel() + rio.Close() } - rmFIFOSet(fifos) } }() - p, err = ctr.task.Exec(ctx, processID, spec, func(id string) (containerd.IO, error) { - cio, err = c.createIO(fifos, containerID, processID, stdinCloseSync, attachStdio) - return cio, err + p, err = t.Exec(ctx, processID, spec, func(id string) (cio.IO, error) { + rio, err = c.createIO(fifos, containerID, processID, stdinCloseSync, attachStdio) + return rio, err }) if err != nil { close(stdinCloseSync) - if cio != nil { - cio.Cancel() - cio.Close() - } return -1, err } - ctr.Lock() - if ctr.execs == nil { - ctr.execs = make(map[string]containerd.Process) - } - ctr.execs[processID] = p - ctr.Unlock() + ctr.addProcess(processID, p) // Signal c.createIO that it can call CloseIO close(stdinCloseSync) if err = p.Start(ctx); err != nil { p.Delete(context.Background()) - ctr.Lock() - delete(ctr.execs, processID) - ctr.Unlock() + ctr.deleteProcess(processID) return -1, err } @@ -315,7 +353,7 @@ func (c *client) SignalProcess(ctx context.Context, containerID, processID strin if err != nil { return err } - return p.Kill(ctx, syscall.Signal(signal)) + return wrapError(p.Kill(ctx, syscall.Signal(signal))) } func (c *client) ResizeTerminal(ctx context.Context, containerID, processID string, width, height int) error { @@ -429,12 +467,9 @@ func (c *client) DeleteTask(ctx context.Context, containerID string) (uint32, ti return 255, time.Now(), nil } - c.Lock() - if ctr, ok := c.containers[containerID]; ok { - ctr.task = nil + if ctr := c.getContainer(containerID); ctr != nil { + ctr.setTask(nil) } - c.Unlock() - return status.ExitCode(), status.ExitTime(), nil } @@ -468,7 +503,12 @@ func (c *client) Status(ctx context.Context, containerID string) (Status, error) return StatusUnknown, errors.WithStack(newNotFoundError("no such container")) } - s, err := ctr.task.Status(ctx) + t := ctr.getTask() + if t == nil { + return StatusUnknown, errors.WithStack(newNotFoundError("no such task")) + } + + s, err := t.Status(ctx) if err != nil { return StatusUnknown, err } @@ -497,11 +537,11 @@ func (c *client) CreateCheckpoint(ctx context.Context, containerID, checkpointDi b, err := content.ReadBlob(ctx, c.remote.ContentStore(), img.Target().Digest) if err != nil { - return wrapSystemError(errors.Wrapf(err, "failed to retrieve checkpoint data")) + return errdefs.System(errors.Wrapf(err, "failed to retrieve checkpoint data")) } var index v1.Index if err := json.Unmarshal(b, &index); err != nil { - return wrapSystemError(errors.Wrapf(err, "failed to decode checkpoint data")) + return errdefs.System(errors.Wrapf(err, "failed to decode checkpoint data")) } var cpDesc *v1.Descriptor @@ -512,17 +552,17 @@ func (c *client) CreateCheckpoint(ctx context.Context, containerID, checkpointDi } } if cpDesc == nil { - return wrapSystemError(errors.Wrapf(err, "invalid checkpoint")) + return errdefs.System(errors.Wrapf(err, "invalid checkpoint")) } rat, err := c.remote.ContentStore().ReaderAt(ctx, cpDesc.Digest) if err != nil { - return wrapSystemError(errors.Wrapf(err, "failed to get checkpoint reader")) + return errdefs.System(errors.Wrapf(err, "failed to get checkpoint reader")) } defer rat.Close() _, err = archive.Apply(ctx, checkpointDir, content.NewReader(rat)) if err != nil { - return wrapSystemError(errors.Wrapf(err, "failed to read checkpoint reader")) + return errdefs.System(errors.Wrapf(err, "failed to read checkpoint reader")) } return err @@ -544,33 +584,29 @@ func (c *client) removeContainer(id string) { func (c *client) getProcess(containerID, processID string) (containerd.Process, error) { ctr := c.getContainer(containerID) - switch { - case ctr == nil: + if ctr == nil { return nil, errors.WithStack(newNotFoundError("no such container")) - case ctr.task == nil: - return nil, errors.WithStack(newNotFoundError("container is not running")) - case processID == InitProcessName: - return ctr.task, nil - default: - ctr.Lock() - defer ctr.Unlock() - if ctr.execs == nil { - return nil, errors.WithStack(newNotFoundError("no execs")) - } } - p := ctr.execs[processID] + t := ctr.getTask() + if t == nil { + return nil, errors.WithStack(newNotFoundError("container is not running")) + } + if processID == InitProcessName { + return t, nil + } + + p := ctr.getProcess(processID) if p == nil { return nil, errors.WithStack(newNotFoundError("no such exec")) } - return p, nil } // createIO creates the io to be used by a process // This needs to get a pointer to interface as upon closure the process may not have yet been registered -func (c *client) createIO(fifos *containerd.FIFOSet, containerID, processID string, stdinCloseSync chan struct{}, attachStdio StdioCallback) (containerd.IO, error) { - io, err := newIOPipe(fifos) +func (c *client) createIO(fifos *cio.FIFOSet, containerID, processID string, stdinCloseSync chan struct{}, attachStdio StdioCallback) (cio.IO, error) { + io, err := cio.NewDirectIO(context.Background(), fifos) if err != nil { return nil, err } @@ -601,12 +637,12 @@ func (c *client) createIO(fifos *containerd.FIFOSet, containerID, processID stri }) } - cio, err := attachStdio(io) + rio, err := attachStdio(io) if err != nil { io.Cancel() io.Close() } - return cio, err + return rio, err } func (c *client) processEvent(ctr *container, et EventType, ei EventInfo) { @@ -621,12 +657,7 @@ func (c *client) processEvent(ctr *container, et EventType, ei EventInfo) { } if et == EventExit && ei.ProcessID != ei.ContainerID { - var p containerd.Process - ctr.Lock() - if ctr.execs != nil { - p = ctr.execs[ei.ProcessID] - } - ctr.Unlock() + p := ctr.getProcess(ei.ProcessID) if p == nil { c.logger.WithError(errors.New("no such process")). WithFields(logrus.Fields{ @@ -642,16 +673,15 @@ func (c *client) processEvent(ctr *container, et EventType, ei EventInfo) { "process": ei.ProcessID, }).Warn("failed to delete process") } - c.Lock() - delete(ctr.execs, ei.ProcessID) - c.Unlock() + ctr.deleteProcess(ei.ProcessID) + ctr := c.getContainer(ei.ContainerID) if ctr == nil { c.logger.WithFields(logrus.Fields{ "container": ei.ContainerID, }).Error("failed to find container") } else { - rmFIFOSet(newFIFOSet(ctr.bundleDir, ei.ContainerID, ei.ProcessID, true, false)) + newFIFOSet(ctr.bundleDir, ei.ProcessID, true, false).Close() } } }) @@ -679,7 +709,11 @@ func (c *client) processEventStream(ctx context.Context) { }() eventStream, err = c.remote.EventService().Subscribe(ctx, &eventsapi.SubscribeRequest{ - Filters: []string{"namespace==" + c.namespace + ",topic~=/tasks/.+"}, + Filters: []string{ + // Filter on both namespace *and* topic. To create an "and" filter, + // this must be a single, comma-separated string + "namespace==" + c.namespace + ",topic~=|^/tasks/|", + }, }, grpc.FailFast(false)) if err != nil { return @@ -710,21 +744,21 @@ func (c *client) processEventStream(ctx context.Context) { c.logger.WithField("topic", ev.Topic).Debug("event") switch t := v.(type) { - case *eventsapi.TaskCreate: + case *events.TaskCreate: et = EventCreate ei = EventInfo{ ContainerID: t.ContainerID, ProcessID: t.ContainerID, Pid: t.Pid, } - case *eventsapi.TaskStart: + case *events.TaskStart: et = EventStart ei = EventInfo{ ContainerID: t.ContainerID, ProcessID: t.ContainerID, Pid: t.Pid, } - case *eventsapi.TaskExit: + case *events.TaskExit: et = EventExit ei = EventInfo{ ContainerID: t.ContainerID, @@ -733,32 +767,32 @@ func (c *client) processEventStream(ctx context.Context) { ExitCode: t.ExitStatus, ExitedAt: t.ExitedAt, } - case *eventsapi.TaskOOM: + case *events.TaskOOM: et = EventOOM ei = EventInfo{ ContainerID: t.ContainerID, OOMKilled: true, } oomKilled = true - case *eventsapi.TaskExecAdded: + case *events.TaskExecAdded: et = EventExecAdded ei = EventInfo{ ContainerID: t.ContainerID, ProcessID: t.ExecID, } - case *eventsapi.TaskExecStarted: + case *events.TaskExecStarted: et = EventExecStarted ei = EventInfo{ ContainerID: t.ContainerID, ProcessID: t.ExecID, Pid: t.Pid, } - case *eventsapi.TaskPaused: + case *events.TaskPaused: et = EventPaused ei = EventInfo{ ContainerID: t.ContainerID, } - case *eventsapi.TaskResumed: + case *events.TaskResumed: et = EventResumed ei = EventInfo{ ContainerID: t.ContainerID, @@ -778,10 +812,10 @@ func (c *client) processEventStream(ctx context.Context) { } if oomKilled { - ctr.oomKilled = true + ctr.setOOMKilled(true) oomKilled = false } - ei.OOMKilled = ctr.oomKilled + ei.OOMKilled = ctr.getOOMKilled() c.processEvent(ctr, et, ei) } @@ -811,12 +845,17 @@ func (c *client) writeContent(ctx context.Context, mediaType, ref string, r io.R } func wrapError(err error) error { - if err != nil { - msg := err.Error() - for _, s := range []string{"container does not exist", "not found", "no such container"} { - if strings.Contains(msg, s) { - return wrapNotFoundError(err) - } + switch { + case err == nil: + return nil + case containerderrors.IsNotFound(err): + return errdefs.NotFound(err) + } + + msg := err.Error() + for _, s := range []string{"container does not exist", "not found", "no such container"} { + if strings.Contains(msg, s) { + return errdefs.NotFound(err) } } return err diff --git a/vendor/github.com/docker/docker/libcontainerd/client_daemon_linux.go b/vendor/github.com/docker/docker/libcontainerd/client_daemon_linux.go index 14966f00b..d34420ac2 100644 --- a/vendor/github.com/docker/docker/libcontainerd/client_daemon_linux.go +++ b/vendor/github.com/docker/docker/libcontainerd/client_daemon_linux.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" "github.com/docker/docker/pkg/idtools" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" @@ -79,29 +80,29 @@ func prepareBundleDir(bundleDir string, ociSpec *specs.Spec) (string, error) { return p, nil } -func newFIFOSet(bundleDir, containerID, processID string, withStdin, withTerminal bool) *containerd.FIFOSet { - fifos := &containerd.FIFOSet{ +func newFIFOSet(bundleDir, processID string, withStdin, withTerminal bool) *cio.FIFOSet { + config := cio.Config{ Terminal: withTerminal, - Out: filepath.Join(bundleDir, processID+"-stdout"), + Stdout: filepath.Join(bundleDir, processID+"-stdout"), } + paths := []string{config.Stdout} if withStdin { - fifos.In = filepath.Join(bundleDir, processID+"-stdin") + config.Stdin = filepath.Join(bundleDir, processID+"-stdin") + paths = append(paths, config.Stdin) } - - if !fifos.Terminal { - fifos.Err = filepath.Join(bundleDir, processID+"-stderr") + if !withTerminal { + config.Stderr = filepath.Join(bundleDir, processID+"-stderr") + paths = append(paths, config.Stderr) } - - return fifos -} - -func rmFIFOSet(fset *containerd.FIFOSet) { - for _, fn := range []string{fset.Out, fset.In, fset.Err} { - if fn != "" { - if err := os.RemoveAll(fn); err != nil { - logrus.Warnf("libcontainerd: failed to remove fifo %v: %v", fn, err) + closer := func() error { + for _, path := range paths { + if err := os.RemoveAll(path); err != nil { + logrus.Warnf("libcontainerd: failed to remove fifo %v: %v", path, err) } } + return nil } + + return cio.NewFIFOSet(config, closer) } diff --git a/vendor/github.com/docker/docker/libcontainerd/client_daemon_windows.go b/vendor/github.com/docker/docker/libcontainerd/client_daemon_windows.go index 9bb5d86f4..6215346e7 100644 --- a/vendor/github.com/docker/docker/libcontainerd/client_daemon_windows.go +++ b/vendor/github.com/docker/docker/libcontainerd/client_daemon_windows.go @@ -2,8 +2,9 @@ package libcontainerd import ( "fmt" + "path/filepath" - "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" "github.com/containerd/containerd/windows/hcsshimtypes" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -35,19 +36,20 @@ func pipeName(containerID, processID, name string) string { return fmt.Sprintf(`\\.\pipe\containerd-%s-%s-%s`, containerID, processID, name) } -func newFIFOSet(bundleDir, containerID, processID string, withStdin, withTerminal bool) *containerd.FIFOSet { - fifos := &containerd.FIFOSet{ +func newFIFOSet(bundleDir, processID string, withStdin, withTerminal bool) *cio.FIFOSet { + containerID := filepath.Base(bundleDir) + config := cio.Config{ Terminal: withTerminal, - Out: pipeName(containerID, processID, "stdout"), + Stdout: pipeName(containerID, processID, "stdout"), } if withStdin { - fifos.In = pipeName(containerID, processID, "stdin") + config.Stdin = pipeName(containerID, processID, "stdin") } - if !fifos.Terminal { - fifos.Err = pipeName(containerID, processID, "stderr") + if !config.Terminal { + config.Stderr = pipeName(containerID, processID, "stderr") } - return fifos + return cio.NewFIFOSet(config, nil) } diff --git a/vendor/github.com/docker/docker/libcontainerd/client_local_windows.go b/vendor/github.com/docker/docker/libcontainerd/client_local_windows.go index 8ce9dfeda..75329b25f 100644 --- a/vendor/github.com/docker/docker/libcontainerd/client_local_windows.go +++ b/vendor/github.com/docker/docker/libcontainerd/client_local_windows.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "io" "io/ioutil" "os" "path" @@ -18,6 +17,7 @@ import ( "github.com/Microsoft/hcsshim" opengcs "github.com/Microsoft/opengcs/client" "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" "github.com/docker/docker/pkg/sysinfo" "github.com/docker/docker/pkg/system" specs "github.com/opencontainers/runtime-spec/specs-go" @@ -670,28 +670,12 @@ func (c *client) Start(_ context.Context, id, _ string, withStdin bool, attachSt return p.pid, nil } - var ( - stdout, stderr io.ReadCloser - stdin io.WriteCloser - ) - stdin, stdout, stderr, err = newProcess.Stdio() + dio, err := newIOFromProcess(newProcess, ctr.ociSpec.Process.Terminal) if err != nil { logger.WithError(err).Error("failed to get stdio pipes") return -1, err } - - iopipe := &IOPipe{Terminal: ctr.ociSpec.Process.Terminal} - iopipe.Stdin = createStdInCloser(stdin, newProcess) - - // Convert io.ReadClosers to io.Readers - if stdout != nil { - iopipe.Stdout = ioutil.NopCloser(&autoClosingReader{ReadCloser: stdout}) - } - if stderr != nil { - iopipe.Stderr = ioutil.NopCloser(&autoClosingReader{ReadCloser: stderr}) - } - - _, err = attachStdio(iopipe) + _, err = attachStdio(dio) if err != nil { logger.WithError(err).Error("failed to attache stdio") return -1, err @@ -727,6 +711,24 @@ func (c *client) Start(_ context.Context, id, _ string, withStdin bool, attachSt return p.pid, nil } +func newIOFromProcess(newProcess hcsshim.Process, terminal bool) (*cio.DirectIO, error) { + stdin, stdout, stderr, err := newProcess.Stdio() + if err != nil { + return nil, err + } + + dio := cio.NewDirectIO(createStdInCloser(stdin, newProcess), nil, nil, terminal) + + // Convert io.ReadClosers to io.Readers + if stdout != nil { + dio.Stdout = ioutil.NopCloser(&autoClosingReader{ReadCloser: stdout}) + } + if stderr != nil { + dio.Stderr = ioutil.NopCloser(&autoClosingReader{ReadCloser: stderr}) + } + return dio, nil +} + // Exec adds a process in an running container func (c *client) Exec(ctx context.Context, containerID, processID string, spec *specs.Process, withStdin bool, attachStdio StdioCallback) (int, error) { ctr := c.getContainer(containerID) @@ -781,10 +783,6 @@ func (c *client) Exec(ctx context.Context, containerID, processID string, spec * logger.Debugf("exec commandLine: %s", createProcessParms.CommandLine) // Start the command running in the container. - var ( - stdout, stderr io.ReadCloser - stdin io.WriteCloser - ) newProcess, err := ctr.hcsContainer.CreateProcess(&createProcessParms) if err != nil { logger.WithError(err).Errorf("exec's CreateProcess() failed") @@ -807,25 +805,13 @@ func (c *client) Exec(ctx context.Context, containerID, processID string, spec * } }() - stdin, stdout, stderr, err = newProcess.Stdio() + dio, err := newIOFromProcess(newProcess, spec.Terminal) if err != nil { - logger.WithError(err).Error("getting std pipes failed") + logger.WithError(err).Error("failed to get stdio pipes") return -1, err } - - iopipe := &IOPipe{Terminal: spec.Terminal} - iopipe.Stdin = createStdInCloser(stdin, newProcess) - - // Convert io.ReadClosers to io.Readers - if stdout != nil { - iopipe.Stdout = ioutil.NopCloser(&autoClosingReader{ReadCloser: stdout}) - } - if stderr != nil { - iopipe.Stderr = ioutil.NopCloser(&autoClosingReader{ReadCloser: stderr}) - } - // Tell the engine to attach streams back to the client - _, err = attachStdio(iopipe) + _, err = attachStdio(dio) if err != nil { return -1, err } @@ -934,7 +920,7 @@ func (c *client) ResizeTerminal(_ context.Context, containerID, processID string "width": width, "pid": p.pid, }).Debug("resizing") - return p.hcsProcess.ResizeConsole(uint16(height), uint16(width)) + return p.hcsProcess.ResizeConsole(uint16(width), uint16(height)) } func (c *client) CloseStdin(_ context.Context, containerID, processID string) error { diff --git a/vendor/github.com/docker/docker/libcontainerd/errors.go b/vendor/github.com/docker/docker/libcontainerd/errors.go index db59ea878..dcd252531 100644 --- a/vendor/github.com/docker/docker/libcontainerd/errors.go +++ b/vendor/github.com/docker/docker/libcontainerd/errors.go @@ -1,46 +1,13 @@ package libcontainerd -import "errors" +import ( + "errors" -type liberr struct { - err error -} + "github.com/docker/docker/errdefs" +) -func (e liberr) Error() string { - return e.err.Error() -} +func newNotFoundError(err string) error { return errdefs.NotFound(errors.New(err)) } -func (e liberr) Cause() error { - return e.err -} +func newInvalidParameterError(err string) error { return errdefs.InvalidParameter(errors.New(err)) } -type notFoundErr struct { - liberr -} - -func (notFoundErr) NotFound() {} - -func newNotFoundError(err string) error { return notFoundErr{liberr{errors.New(err)}} } -func wrapNotFoundError(err error) error { return notFoundErr{liberr{err}} } - -type invalidParamErr struct { - liberr -} - -func (invalidParamErr) InvalidParameter() {} - -func newInvalidParameterError(err string) error { return invalidParamErr{liberr{errors.New(err)}} } - -type conflictErr struct { - liberr -} - -func (conflictErr) ConflictErr() {} - -func newConflictError(err string) error { return conflictErr{liberr{errors.New(err)}} } - -type sysErr struct { - liberr -} - -func wrapSystemError(err error) error { return sysErr{liberr{err}} } +func newConflictError(err string) error { return errdefs.Conflict(errors.New(err)) } diff --git a/vendor/github.com/docker/docker/libcontainerd/io.go b/vendor/github.com/docker/docker/libcontainerd/io.go deleted file mode 100644 index 2c4af58ce..000000000 --- a/vendor/github.com/docker/docker/libcontainerd/io.go +++ /dev/null @@ -1,36 +0,0 @@ -package libcontainerd - -import "github.com/containerd/containerd" - -// Config returns the containerd.IOConfig of this pipe set -func (p *IOPipe) Config() containerd.IOConfig { - return p.config -} - -// Cancel aborts ongoing operations if they have not completed yet -func (p *IOPipe) Cancel() { - p.cancel() -} - -// Wait waits for io operations to finish -func (p *IOPipe) Wait() { -} - -// Close closes the underlying pipes -func (p *IOPipe) Close() error { - p.cancel() - - if p.Stdin != nil { - p.Stdin.Close() - } - - if p.Stdout != nil { - p.Stdout.Close() - } - - if p.Stderr != nil { - p.Stderr.Close() - } - - return nil -} diff --git a/vendor/github.com/docker/docker/libcontainerd/io_unix.go b/vendor/github.com/docker/docker/libcontainerd/io_unix.go deleted file mode 100644 index 0c08b2013..000000000 --- a/vendor/github.com/docker/docker/libcontainerd/io_unix.go +++ /dev/null @@ -1,60 +0,0 @@ -// +build !windows - -package libcontainerd - -import ( - "context" - "io" - "syscall" - - "github.com/containerd/containerd" - "github.com/containerd/fifo" - "github.com/pkg/errors" -) - -func newIOPipe(fifos *containerd.FIFOSet) (*IOPipe, error) { - var ( - err error - ctx, cancel = context.WithCancel(context.Background()) - f io.ReadWriteCloser - iop = &IOPipe{ - Terminal: fifos.Terminal, - cancel: cancel, - config: containerd.IOConfig{ - Terminal: fifos.Terminal, - Stdin: fifos.In, - Stdout: fifos.Out, - Stderr: fifos.Err, - }, - } - ) - defer func() { - if err != nil { - cancel() - iop.Close() - } - }() - - if fifos.In != "" { - if f, err = fifo.OpenFifo(ctx, fifos.In, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, errors.WithStack(err) - } - iop.Stdin = f - } - - if fifos.Out != "" { - if f, err = fifo.OpenFifo(ctx, fifos.Out, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, errors.WithStack(err) - } - iop.Stdout = f - } - - if fifos.Err != "" { - if f, err = fifo.OpenFifo(ctx, fifos.Err, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil { - return nil, errors.WithStack(err) - } - iop.Stderr = f - } - - return iop, nil -} diff --git a/vendor/github.com/docker/docker/libcontainerd/io_windows.go b/vendor/github.com/docker/docker/libcontainerd/io_windows.go deleted file mode 100644 index 312bdbd8c..000000000 --- a/vendor/github.com/docker/docker/libcontainerd/io_windows.go +++ /dev/null @@ -1,138 +0,0 @@ -package libcontainerd - -import ( - "context" - "io" - "net" - "sync" - - winio "github.com/Microsoft/go-winio" - "github.com/containerd/containerd" - "github.com/pkg/errors" -) - -type winpipe struct { - sync.Mutex - - ctx context.Context - listener net.Listener - readyCh chan struct{} - readyErr error - - client net.Conn -} - -func newWinpipe(ctx context.Context, pipe string) (*winpipe, error) { - l, err := winio.ListenPipe(pipe, nil) - if err != nil { - return nil, errors.Wrapf(err, "%q pipe creation failed", pipe) - } - wp := &winpipe{ - ctx: ctx, - listener: l, - readyCh: make(chan struct{}), - } - go func() { - go func() { - defer close(wp.readyCh) - defer wp.listener.Close() - c, err := wp.listener.Accept() - if err != nil { - wp.Lock() - if wp.readyErr == nil { - wp.readyErr = err - } - wp.Unlock() - return - } - wp.client = c - }() - - select { - case <-wp.readyCh: - case <-ctx.Done(): - wp.Lock() - if wp.readyErr == nil { - wp.listener.Close() - wp.readyErr = ctx.Err() - } - wp.Unlock() - } - }() - - return wp, nil -} - -func (wp *winpipe) Read(b []byte) (int, error) { - select { - case <-wp.ctx.Done(): - return 0, wp.ctx.Err() - case <-wp.readyCh: - return wp.client.Read(b) - } -} - -func (wp *winpipe) Write(b []byte) (int, error) { - select { - case <-wp.ctx.Done(): - return 0, wp.ctx.Err() - case <-wp.readyCh: - return wp.client.Write(b) - } -} - -func (wp *winpipe) Close() error { - select { - case <-wp.readyCh: - return wp.client.Close() - default: - return nil - } -} - -func newIOPipe(fifos *containerd.FIFOSet) (*IOPipe, error) { - var ( - err error - ctx, cancel = context.WithCancel(context.Background()) - p io.ReadWriteCloser - iop = &IOPipe{ - Terminal: fifos.Terminal, - cancel: cancel, - config: containerd.IOConfig{ - Terminal: fifos.Terminal, - Stdin: fifos.In, - Stdout: fifos.Out, - Stderr: fifos.Err, - }, - } - ) - defer func() { - if err != nil { - cancel() - iop.Close() - } - }() - - if fifos.In != "" { - if p, err = newWinpipe(ctx, fifos.In); err != nil { - return nil, err - } - iop.Stdin = p - } - - if fifos.Out != "" { - if p, err = newWinpipe(ctx, fifos.Out); err != nil { - return nil, err - } - iop.Stdout = p - } - - if fifos.Err != "" { - if p, err = newWinpipe(ctx, fifos.Err); err != nil { - return nil, err - } - iop.Stderr = p - } - - return iop, nil -} diff --git a/vendor/github.com/docker/docker/libcontainerd/remote_daemon.go b/vendor/github.com/docker/docker/libcontainerd/remote_daemon.go index e6fd05f08..609bcfba7 100644 --- a/vendor/github.com/docker/docker/libcontainerd/remote_daemon.go +++ b/vendor/github.com/docker/docker/libcontainerd/remote_daemon.go @@ -278,7 +278,7 @@ func (r *remote) monitorConnection(client *containerd.Client) { select { case <-r.shutdownContext.Done(): - r.logger.Info("stopping healtcheck following graceful shutdown") + r.logger.Info("stopping healthcheck following graceful shutdown") client.Close() return default: diff --git a/vendor/github.com/docker/docker/libcontainerd/remote_daemon_options_linux.go b/vendor/github.com/docker/docker/libcontainerd/remote_daemon_options_linux.go index 1e5a98124..7376c0611 100644 --- a/vendor/github.com/docker/docker/libcontainerd/remote_daemon_options_linux.go +++ b/vendor/github.com/docker/docker/libcontainerd/remote_daemon_options_linux.go @@ -27,7 +27,7 @@ type subreaper bool func (s subreaper) Apply(r Remote) error { if remote, ok := r.(*remote); ok { - remote.Subreaper = bool(s) + remote.NoSubreaper = !bool(s) return nil } return fmt.Errorf("WithSubreaper option not supported for this remote") diff --git a/vendor/github.com/docker/docker/libcontainerd/remote_daemon_process.go b/vendor/github.com/docker/docker/libcontainerd/remote_daemon_process.go deleted file mode 100644 index a00406e15..000000000 --- a/vendor/github.com/docker/docker/libcontainerd/remote_daemon_process.go +++ /dev/null @@ -1,56 +0,0 @@ -// +build !windows - -package libcontainerd - -import "github.com/pkg/errors" - -// process represents the state for the main container process or an exec. -type process struct { - // id is the logical name of the process - id string - - // cid is the container id to which this process belongs - cid string - - // pid is the identifier of the process - pid uint32 - - // io holds the io reader/writer associated with the process - io *IOPipe - - // root is the state directory for the process - root string -} - -func (p *process) ID() string { - return p.id -} - -func (p *process) Pid() uint32 { - return p.pid -} - -func (p *process) SetPid(pid uint32) error { - if p.pid != 0 { - return errors.Errorf("pid is already set to %d", pid) - } - - p.pid = pid - return nil -} - -func (p *process) IOPipe() *IOPipe { - return p.io -} - -func (p *process) CloseIO() { - if p.io.Stdin != nil { - p.io.Stdin.Close() - } - if p.io.Stdout != nil { - p.io.Stdout.Close() - } - if p.io.Stderr != nil { - p.io.Stderr.Close() - } -} diff --git a/vendor/github.com/docker/docker/libcontainerd/remote_daemon_process_linux.go b/vendor/github.com/docker/docker/libcontainerd/remote_daemon_process_linux.go deleted file mode 100644 index fd54d0198..000000000 --- a/vendor/github.com/docker/docker/libcontainerd/remote_daemon_process_linux.go +++ /dev/null @@ -1,59 +0,0 @@ -package libcontainerd - -import ( - "os" - "path/filepath" - - "github.com/pkg/errors" - "golang.org/x/sys/unix" -) - -var fdNames = map[int]string{ - unix.Stdin: "stdin", - unix.Stdout: "stdout", - unix.Stderr: "stderr", -} - -func (p *process) pipeName(index int) string { - return filepath.Join(p.root, p.id+"-"+fdNames[index]) -} - -func (p *process) IOPaths() (string, string, string) { - var ( - stdin = p.pipeName(unix.Stdin) - stdout = p.pipeName(unix.Stdout) - stderr = p.pipeName(unix.Stderr) - ) - // TODO: debug why we're having zombies when I don't unset those - if p.io.Stdin == nil { - stdin = "" - } - if p.io.Stderr == nil { - stderr = "" - } - return stdin, stdout, stderr -} - -func (p *process) Cleanup() error { - var retErr error - - // Ensure everything was closed - p.CloseIO() - - for _, i := range [3]string{ - p.pipeName(unix.Stdin), - p.pipeName(unix.Stdout), - p.pipeName(unix.Stderr), - } { - err := os.Remove(i) - if err != nil { - if retErr == nil { - retErr = errors.Wrapf(err, "failed to remove %s", i) - } else { - retErr = errors.Wrapf(retErr, "failed to remove %s", i) - } - } - } - - return retErr -} diff --git a/vendor/github.com/docker/docker/libcontainerd/types.go b/vendor/github.com/docker/docker/libcontainerd/types.go index 9eede43a4..4286415ea 100644 --- a/vendor/github.com/docker/docker/libcontainerd/types.go +++ b/vendor/github.com/docker/docker/libcontainerd/types.go @@ -2,10 +2,10 @@ package libcontainerd import ( "context" - "io" "time" "github.com/containerd/containerd" + "github.com/containerd/containerd/cio" "github.com/opencontainers/runtime-spec/specs-go" ) @@ -106,20 +106,4 @@ type Client interface { } // StdioCallback is called to connect a container or process stdio. -type StdioCallback func(*IOPipe) (containerd.IO, error) - -// IOPipe contains the stdio streams. -type IOPipe struct { - Stdin io.WriteCloser - Stdout io.ReadCloser - Stderr io.ReadCloser - Terminal bool // Whether stderr is connected on Windows - - cancel context.CancelFunc - config containerd.IOConfig -} - -// ServerVersion contains version information as retrieved from the -// server -type ServerVersion struct { -} +type StdioCallback func(io *cio.DirectIO) (cio.IO, error) diff --git a/vendor/github.com/docker/docker/migrate/v1/migratev1.go b/vendor/github.com/docker/docker/migrate/v1/migratev1.go index 60dbfe078..02fcd2c2c 100644 --- a/vendor/github.com/docker/docker/migrate/v1/migratev1.go +++ b/vendor/github.com/docker/docker/migrate/v1/migratev1.go @@ -89,11 +89,7 @@ func Migrate(root, driverName string, ls layer.Store, is image.Store, rs refstor return err } - if err := migrateRefs(root, driverName, rs, mappings); err != nil { - return err - } - - return nil + return migrateRefs(root, driverName, rs, mappings) } // CalculateLayerChecksums walks an old graph directory and calculates checksums diff --git a/vendor/github.com/docker/docker/migrate/v1/migratev1_test.go b/vendor/github.com/docker/docker/migrate/v1/migratev1_test.go index 122a0805a..28b7df3f3 100644 --- a/vendor/github.com/docker/docker/migrate/v1/migratev1_test.go +++ b/vendor/github.com/docker/docker/migrate/v1/migratev1_test.go @@ -87,14 +87,15 @@ func TestMigrateContainers(t *testing.T) { t.Fatal(err) } - ls := &mockMounter{} - ifs, err := image.NewFSStoreBackend(filepath.Join(tmpdir, "imagedb")) if err != nil { t.Fatal(err) } - is, err := image.NewImageStore(ifs, runtime.GOOS, ls) + ls := &mockMounter{} + mmMap := make(map[string]image.LayerGetReleaser) + mmMap[runtime.GOOS] = ls + is, err := image.NewImageStore(ifs, mmMap) if err != nil { t.Fatal(err) } @@ -165,19 +166,20 @@ func TestMigrateImages(t *testing.T) { t.Fatal(err) } - ls := &mockRegistrar{} - ifs, err := image.NewFSStoreBackend(filepath.Join(tmpdir, "imagedb")) if err != nil { t.Fatal(err) } - is, err := image.NewImageStore(ifs, runtime.GOOS, ls) + ls := &mockRegistrar{} + mrMap := make(map[string]image.LayerGetReleaser) + mrMap[runtime.GOOS] = ls + is, err := image.NewImageStore(ifs, mrMap) if err != nil { t.Fatal(err) } - ms, err := metadata.NewFSMetadataStore(filepath.Join(tmpdir, "distribution"), runtime.GOOS) + ms, err := metadata.NewFSMetadataStore(filepath.Join(tmpdir, "distribution")) if err != nil { t.Fatal(err) } @@ -323,10 +325,7 @@ func addContainer(dest, jsonConfig string) error { if err := os.MkdirAll(contDir, 0700); err != nil { return err } - if err := ioutil.WriteFile(filepath.Join(contDir, "config.json"), []byte(jsonConfig), 0600); err != nil { - return err - } - return nil + return ioutil.WriteFile(filepath.Join(contDir, "config.json"), []byte(jsonConfig), 0600) } type mockTagAdder struct { @@ -433,10 +432,6 @@ func (l *mockLayer) DiffSize() (int64, error) { return 0, nil } -func (l *mockLayer) OS() layer.OS { - return "" -} - func (l *mockLayer) Metadata() (map[string]string, error) { return nil, nil } diff --git a/vendor/github.com/docker/docker/opts/hosts_windows.go b/vendor/github.com/docker/docker/opts/hosts_windows.go index 7c239e00f..684f0e128 100644 --- a/vendor/github.com/docker/docker/opts/hosts_windows.go +++ b/vendor/github.com/docker/docker/opts/hosts_windows.go @@ -1,5 +1,3 @@ -// +build windows - package opts // DefaultHost constant defines the default host string used by docker on Windows diff --git a/vendor/github.com/docker/docker/pkg/archive/archive.go b/vendor/github.com/docker/docker/pkg/archive/archive.go index aa5563756..5f7f56267 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive.go @@ -6,6 +6,7 @@ import ( "bytes" "compress/bzip2" "compress/gzip" + "context" "fmt" "io" "io/ioutil" @@ -13,6 +14,7 @@ import ( "os/exec" "path/filepath" "runtime" + "strconv" "strings" "syscall" @@ -24,6 +26,17 @@ import ( "github.com/sirupsen/logrus" ) +var unpigzPath string + +func init() { + if path, err := exec.LookPath("unpigz"); err != nil { + logrus.Debug("unpigz binary not found in PATH, falling back to go gzip library") + } else { + logrus.Debugf("Using unpigz binary found at path %s", path) + unpigzPath = path + } +} + type ( // Compression is the state represents if compressed or not. Compression int @@ -136,10 +149,34 @@ func DetectCompression(source []byte) Compression { return Uncompressed } -func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) { +func xzDecompress(ctx context.Context, archive io.Reader) (io.ReadCloser, error) { args := []string{"xz", "-d", "-c", "-q"} - return cmdStream(exec.Command(args[0], args[1:]...), archive) + return cmdStream(exec.CommandContext(ctx, args[0], args[1:]...), archive) +} + +func gzDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) { + if unpigzPath == "" { + return gzip.NewReader(buf) + } + + disablePigzEnv := os.Getenv("MOBY_DISABLE_PIGZ") + if disablePigzEnv != "" { + if disablePigz, err := strconv.ParseBool(disablePigzEnv); err != nil { + return nil, err + } else if disablePigz { + return gzip.NewReader(buf) + } + } + + return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf) +} + +func wrapReadCloser(readBuf io.ReadCloser, cancel context.CancelFunc) io.ReadCloser { + return ioutils.NewReadCloserWrapper(readBuf, func() error { + cancel() + return readBuf.Close() + }) } // DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive. @@ -163,26 +200,29 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) { readBufWrapper := p.NewReadCloserWrapper(buf, buf) return readBufWrapper, nil case Gzip: - gzReader, err := gzip.NewReader(buf) + ctx, cancel := context.WithCancel(context.Background()) + + gzReader, err := gzDecompress(ctx, buf) if err != nil { + cancel() return nil, err } readBufWrapper := p.NewReadCloserWrapper(buf, gzReader) - return readBufWrapper, nil + return wrapReadCloser(readBufWrapper, cancel), nil case Bzip2: bz2Reader := bzip2.NewReader(buf) readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader) return readBufWrapper, nil case Xz: - xzReader, chdone, err := xzDecompress(buf) + ctx, cancel := context.WithCancel(context.Background()) + + xzReader, err := xzDecompress(ctx, buf) if err != nil { + cancel() return nil, err } readBufWrapper := p.NewReadCloserWrapper(buf, xzReader) - return ioutils.NewReadCloserWrapper(readBufWrapper, func() error { - <-chdone - return readBufWrapper.Close() - }), nil + return wrapReadCloser(readBufWrapper, cancel), nil default: return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) } @@ -456,10 +496,16 @@ func (ta *tarAppender) addTarFile(path, name string) error { } } + //check whether the file is overlayfs whiteout + //if yes, skip re-mapping container ID mappings. + isOverlayWhiteout := fi.Mode()&os.ModeCharDevice != 0 && hdr.Devmajor == 0 && hdr.Devminor == 0 + //handle re-mapping container ID mappings back to host ID mappings before //writing tar headers/files. We skip whiteout files because they were written //by the kernel and already have proper ownership relative to the host - if !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IDMappings.Empty() { + if !isOverlayWhiteout && + !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && + !ta.IDMappings.Empty() { fileIDPair, err := getFileUIDGID(fi.Sys()) if err != nil { return err @@ -1157,8 +1203,7 @@ func remapIDs(idMappings *idtools.IDMappings, hdr *tar.Header) error { // cmdStream executes a command, and returns its stdout as a stream. // If the command fails to run or doesn't complete successfully, an error // will be returned, including anything written on stderr. -func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, error) { - chdone := make(chan struct{}) +func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, error) { cmd.Stdin = input pipeR, pipeW := io.Pipe() cmd.Stdout = pipeW @@ -1167,7 +1212,7 @@ func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, // Run the command and return the pipe if err := cmd.Start(); err != nil { - return nil, nil, err + return nil, err } // Copy stdout to the returned pipe @@ -1177,10 +1222,9 @@ func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, <-chan struct{}, } else { pipeW.Close() } - close(chdone) }() - return pipeR, chdone, nil + return pipeR, nil } // NewTempArchive reads the content of src into a temporary file, and returns the contents diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_test.go b/vendor/github.com/docker/docker/pkg/archive/archive_test.go index 989557c53..0e94f41c6 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_test.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_test.go @@ -3,6 +3,7 @@ package archive import ( "archive/tar" "bytes" + "compress/gzip" "fmt" "io" "io/ioutil" @@ -15,6 +16,7 @@ import ( "time" "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/ioutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -87,7 +89,7 @@ func TestIsArchivePathTar(t *testing.T) { } } -func testDecompressStream(t *testing.T, ext, compressCommand string) { +func testDecompressStream(t *testing.T, ext, compressCommand string) io.Reader { cmd := exec.Command("sh", "-c", fmt.Sprintf("touch /tmp/archive && %s /tmp/archive", compressCommand)) output, err := cmd.CombinedOutput() @@ -111,6 +113,8 @@ func testDecompressStream(t *testing.T, ext, compressCommand string) { if err = r.Close(); err != nil { t.Fatalf("Failed to close the decompressed stream: %v ", err) } + + return r } func TestDecompressStreamGzip(t *testing.T) { @@ -206,7 +210,7 @@ func TestExtensionXz(t *testing.T) { func TestCmdStreamLargeStderr(t *testing.T) { cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1k count=1000 of=/dev/stderr; echo hello") - out, _, err := cmdStream(cmd, nil) + out, err := cmdStream(cmd, nil) if err != nil { t.Fatalf("Failed to start command: %s", err) } @@ -231,7 +235,7 @@ func TestCmdStreamBad(t *testing.T) { t.Skip("Failing on Windows CI machines") } badCmd := exec.Command("sh", "-c", "echo hello; echo >&2 error couldn\\'t reverse the phase pulser; exit 1") - out, _, err := cmdStream(badCmd, nil) + out, err := cmdStream(badCmd, nil) if err != nil { t.Fatalf("Failed to start command: %s", err) } @@ -246,7 +250,7 @@ func TestCmdStreamBad(t *testing.T) { func TestCmdStreamGood(t *testing.T) { cmd := exec.Command("sh", "-c", "echo hello; exit 0") - out, _, err := cmdStream(cmd, nil) + out, err := cmdStream(cmd, nil) if err != nil { t.Fatal(err) } @@ -1318,3 +1322,38 @@ func readFileFromArchive(t *testing.T, archive io.ReadCloser, name string, expec assert.NoError(t, err) return string(content) } + +func TestDisablePigz(t *testing.T) { + _, err := exec.LookPath("unpigz") + if err != nil { + t.Log("Test will not check full path when Pigz not installed") + } + + os.Setenv("MOBY_DISABLE_PIGZ", "true") + defer os.Unsetenv("MOBY_DISABLE_PIGZ") + + r := testDecompressStream(t, "gz", "gzip -f") + // For the bufio pool + outsideReaderCloserWrapper := r.(*ioutils.ReadCloserWrapper) + // For the context canceller + contextReaderCloserWrapper := outsideReaderCloserWrapper.Reader.(*ioutils.ReadCloserWrapper) + + assert.IsType(t, &gzip.Reader{}, contextReaderCloserWrapper.Reader) +} + +func TestPigz(t *testing.T) { + r := testDecompressStream(t, "gz", "gzip -f") + // For the bufio pool + outsideReaderCloserWrapper := r.(*ioutils.ReadCloserWrapper) + // For the context canceller + contextReaderCloserWrapper := outsideReaderCloserWrapper.Reader.(*ioutils.ReadCloserWrapper) + + _, err := exec.LookPath("unpigz") + if err == nil { + t.Log("Tested whether Pigz is used, as it installed") + assert.IsType(t, &io.PipeReader{}, contextReaderCloserWrapper.Reader) + } else { + t.Log("Tested whether Pigz is not used, as it not installed") + assert.IsType(t, &gzip.Reader{}, contextReaderCloserWrapper.Reader) + } +} diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go b/vendor/github.com/docker/docker/pkg/archive/archive_windows.go index a22410c03..66243a64a 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_windows.go @@ -1,5 +1,3 @@ -// +build windows - package archive import ( diff --git a/vendor/github.com/docker/docker/pkg/chrootarchive/archive_unix.go b/vendor/github.com/docker/docker/pkg/chrootarchive/archive_unix.go index f2325abd7..75c010e98 100644 --- a/vendor/github.com/docker/docker/pkg/chrootarchive/archive_unix.go +++ b/vendor/github.com/docker/docker/pkg/chrootarchive/archive_unix.go @@ -66,10 +66,12 @@ func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.T cmd.Stderr = output if err := cmd.Start(); err != nil { + w.Close() return fmt.Errorf("Untar error on re-exec cmd: %v", err) } //write the options to the pipe for the untar exec to read if err := json.NewEncoder(w).Encode(options); err != nil { + w.Close() return fmt.Errorf("Untar json encode to pipe failed: %v", err) } w.Close() diff --git a/vendor/github.com/docker/docker/pkg/devicemapper/devmapper.go b/vendor/github.com/docker/docker/pkg/devicemapper/devmapper.go index 48618765f..c72992f7a 100644 --- a/vendor/github.com/docker/docker/pkg/devicemapper/devmapper.go +++ b/vendor/github.com/docker/docker/pkg/devicemapper/devmapper.go @@ -67,12 +67,14 @@ var ( ErrBusy = errors.New("Device is Busy") ErrDeviceIDExists = errors.New("Device Id Exists") ErrEnxio = errors.New("No such device or address") + ErrEnoData = errors.New("No data available") ) var ( - dmSawBusy bool - dmSawExist bool - dmSawEnxio bool // No Such Device or Address + dmSawBusy bool + dmSawExist bool + dmSawEnxio bool // No Such Device or Address + dmSawEnoData bool // No data available ) type ( @@ -708,10 +710,15 @@ func DeleteDevice(poolName string, deviceID int) error { } dmSawBusy = false + dmSawEnoData = false if err := task.run(); err != nil { if dmSawBusy { return ErrBusy } + if dmSawEnoData { + logrus.Debugf("devicemapper: Device(id: %d) from pool(%s) does not exist", deviceID, poolName) + return nil + } return fmt.Errorf("devicemapper: Error running DeleteDevice %s", err) } return nil diff --git a/vendor/github.com/docker/docker/pkg/devicemapper/devmapper_log.go b/vendor/github.com/docker/docker/pkg/devicemapper/devmapper_log.go index f2ac7da87..1da75101c 100644 --- a/vendor/github.com/docker/docker/pkg/devicemapper/devmapper_log.go +++ b/vendor/github.com/docker/docker/pkg/devicemapper/devmapper_log.go @@ -55,6 +55,9 @@ func DevmapperLogCallback(level C.int, file *C.char, line, dmErrnoOrClass C.int, if strings.Contains(msg, "No such device or address") { dmSawEnxio = true } + if strings.Contains(msg, "No data available") { + dmSawEnoData = true + } } if dmLogger != nil { diff --git a/vendor/github.com/docker/docker/pkg/directory/directory_windows.go b/vendor/github.com/docker/docker/pkg/directory/directory_windows.go index 6fb0917c4..efe05cece 100644 --- a/vendor/github.com/docker/docker/pkg/directory/directory_windows.go +++ b/vendor/github.com/docker/docker/pkg/directory/directory_windows.go @@ -1,5 +1,3 @@ -// +build windows - package directory import ( diff --git a/vendor/github.com/docker/docker/pkg/dmesg/dmesg_linux.go b/vendor/github.com/docker/docker/pkg/dmesg/dmesg_linux.go index 7df7f3d43..2fb494e1b 100644 --- a/vendor/github.com/docker/docker/pkg/dmesg/dmesg_linux.go +++ b/vendor/github.com/docker/docker/pkg/dmesg/dmesg_linux.go @@ -1,5 +1,3 @@ -// +build linux - package dmesg import ( diff --git a/vendor/github.com/docker/docker/pkg/fsutils/fsutils_linux.go b/vendor/github.com/docker/docker/pkg/fsutils/fsutils_linux.go index e6094b55b..759625945 100644 --- a/vendor/github.com/docker/docker/pkg/fsutils/fsutils_linux.go +++ b/vendor/github.com/docker/docker/pkg/fsutils/fsutils_linux.go @@ -1,5 +1,3 @@ -// +build linux - package fsutils import ( diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go index 012fe52a2..a7cd2e103 100644 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go +++ b/vendor/github.com/docker/docker/pkg/homedir/homedir_linux.go @@ -1,5 +1,3 @@ -// +build linux - package homedir import ( diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools.go b/vendor/github.com/docker/docker/pkg/idtools/idtools.go index 49cc97c3d..6108ae3f4 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools.go @@ -42,7 +42,9 @@ func MkdirAllAndChown(path string, mode os.FileMode, owner IDPair) error { } // MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid. -// If the directory already exists, this function still changes ownership +// If the directory already exists, this function still changes ownership. +// Note that unlike os.Mkdir(), this function does not return IsExist error +// in case path already exists. func MkdirAndChown(path string, mode os.FileMode, owner IDPair) error { return mkdirAs(path, mode, owner.UID, owner.GID, false, true) } diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go index ff7968f85..aedf8ad34 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strings" "sync" + "syscall" "github.com/docker/docker/pkg/system" "github.com/opencontainers/runc/libcontainer/user" @@ -29,6 +30,9 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown stat, err := system.Stat(path) if err == nil { + if !stat.IsDir() { + return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} + } if !chownExisting { return nil } @@ -54,7 +58,7 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown paths = append(paths, dirPath) } } - if err := system.MkdirAll(path, mode, ""); err != nil && !os.IsExist(err) { + if err := system.MkdirAll(path, mode, ""); err != nil { return err } } else { diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix_test.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix_test.go index afefdb34d..396ff202d 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix_test.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix_test.go @@ -378,6 +378,20 @@ func TestLookupUserAndGroupThatDoesNotExist(t *testing.T) { assert.Error(t, err) } +// TestMkdirIsNotDir checks that mkdirAs() function (used by MkdirAll...) +// returns a correct error in case a directory which it is about to create +// already exists but is a file (rather than a directory). +func TestMkdirIsNotDir(t *testing.T) { + file, err := ioutil.TempFile("", t.Name()) + if err != nil { + t.Fatalf("Couldn't create temp dir: %v", err) + } + defer os.Remove(file.Name()) + + err = mkdirAs(file.Name(), 0755, 0, 0, false, false) + assert.EqualError(t, err, "mkdir "+file.Name()+": not a directory") +} + func RequiresRoot(t *testing.T) { skip.IfCondition(t, os.Getuid() != 0, "skipping test that requires root") } diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go index 45d2878e3..ec4917770 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go @@ -1,5 +1,3 @@ -// +build windows - package idtools import ( @@ -11,7 +9,7 @@ import ( // Platforms such as Windows do not support the UID/GID concept. So make this // just a wrapper around system.MkdirAll. func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error { - if err := system.MkdirAll(path, mode, ""); err != nil && !os.IsExist(err) { + if err := system.MkdirAll(path, mode, ""); err != nil { return err } return nil diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers.go b/vendor/github.com/docker/docker/pkg/ioutils/readers.go index 63f3c07f4..168fa1d2d 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/readers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/readers.go @@ -8,18 +8,22 @@ import ( "golang.org/x/net/context" ) -type readCloserWrapper struct { +// ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser +// It calls the given callback function when closed. It should be constructed +// with NewReadCloserWrapper +type ReadCloserWrapper struct { io.Reader closer func() error } -func (r *readCloserWrapper) Close() error { +// Close calls back the passed closer function +func (r *ReadCloserWrapper) Close() error { return r.closer() } // NewReadCloserWrapper returns a new io.ReadCloser. func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { - return &readCloserWrapper{ + return &ReadCloserWrapper{ Reader: r, closer: closer, } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go b/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go index c258e5fdd..fb14c9548 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go @@ -1,5 +1,3 @@ -// +build windows - package ioutils import ( diff --git a/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go b/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go index be69fee1d..dde889e7b 100644 --- a/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go +++ b/vendor/github.com/docker/docker/pkg/mount/mountinfo_linux.go @@ -1,5 +1,3 @@ -// +build linux - package mount import ( diff --git a/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go b/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go index 8ceec84bc..f3c13e5a1 100644 --- a/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go +++ b/vendor/github.com/docker/docker/pkg/mount/sharedsubtree_linux.go @@ -1,5 +1,3 @@ -// +build linux - package mount // MakeShared ensures a mounted filesystem has the SHARED mount option enabled. diff --git a/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go b/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go index 6352bc7ce..8c4851cc4 100644 --- a/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go +++ b/vendor/github.com/docker/docker/pkg/namesgenerator/names-generator.go @@ -192,6 +192,9 @@ var ( // Subrahmanyan Chandrasekhar - Astrophysicist known for his mathematical theory on different stages and evolution in structures of the stars. He has won nobel prize for physics - https://en.wikipedia.org/wiki/Subrahmanyan_Chandrasekhar "chandrasekhar", + // Asima Chatterjee was an indian organic chemist noted for her research on vinca alkaloids, development of drugs for treatment of epilepsy and malaria - https://en.wikipedia.org/wiki/Asima_Chatterjee + "chatterjee", + //Claude Shannon - The father of information theory and founder of digital circuit design theory. (https://en.wikipedia.org/wiki/Claude_Shannon) "shannon", @@ -557,6 +560,9 @@ var ( // Varahamihira - Ancient Indian mathematician who discovered trigonometric formulae during 505-587 CE - https://en.wikipedia.org/wiki/Var%C4%81hamihira#Contributions "varahamihira", + // Dorothy Vaughan was a NASA mathematician and computer programmer on the SCOUT launch vehicle program that put America's first satellites into space - https://en.wikipedia.org/wiki/Dorothy_Vaughan + "vaughan", + // Sir Mokshagundam Visvesvaraya - is a notable Indian engineer. He is a recipient of the Indian Republic's highest honour, the Bharat Ratna, in 1955. On his birthday, 15 September is celebrated as Engineer's Day in India in his memory - https://en.wikipedia.org/wiki/Visvesvaraya "visvesvaraya", diff --git a/vendor/github.com/docker/docker/pkg/parsers/kernel/kernel_windows.go b/vendor/github.com/docker/docker/pkg/parsers/kernel/kernel_windows.go index e59867277..93620eeff 100644 --- a/vendor/github.com/docker/docker/pkg/parsers/kernel/kernel_windows.go +++ b/vendor/github.com/docker/docker/pkg/parsers/kernel/kernel_windows.go @@ -1,5 +1,3 @@ -// +build windows - package kernel import ( diff --git a/vendor/github.com/docker/docker/pkg/plugins/client.go b/vendor/github.com/docker/docker/pkg/plugins/client.go index 9ee1f8997..63bdc81ea 100644 --- a/vendor/github.com/docker/docker/pkg/plugins/client.go +++ b/vendor/github.com/docker/docker/pkg/plugins/client.go @@ -2,6 +2,7 @@ package plugins import ( "bytes" + "context" "encoding/json" "io" "io/ioutil" @@ -9,6 +10,7 @@ import ( "net/url" "time" + "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/plugins/transport" "github.com/docker/go-connections/sockets" "github.com/docker/go-connections/tlsconfig" @@ -82,16 +84,33 @@ type Client struct { requestFactory transport.RequestFactory } +// RequestOpts is the set of options that can be passed into a request +type RequestOpts struct { + Timeout time.Duration +} + +// WithRequestTimeout sets a timeout duration for plugin requests +func WithRequestTimeout(t time.Duration) func(*RequestOpts) { + return func(o *RequestOpts) { + o.Timeout = t + } +} + // Call calls the specified method with the specified arguments for the plugin. // It will retry for 30 seconds if a failure occurs when calling. -func (c *Client) Call(serviceMethod string, args interface{}, ret interface{}) error { +func (c *Client) Call(serviceMethod string, args, ret interface{}) error { + return c.CallWithOptions(serviceMethod, args, ret) +} + +// CallWithOptions is just like call except it takes options +func (c *Client) CallWithOptions(serviceMethod string, args interface{}, ret interface{}, opts ...func(*RequestOpts)) error { var buf bytes.Buffer if args != nil { if err := json.NewEncoder(&buf).Encode(args); err != nil { return err } } - body, err := c.callWithRetry(serviceMethod, &buf, true) + body, err := c.callWithRetry(serviceMethod, &buf, true, opts...) if err != nil { return err } @@ -128,18 +147,31 @@ func (c *Client) SendFile(serviceMethod string, data io.Reader, ret interface{}) return nil } -func (c *Client) callWithRetry(serviceMethod string, data io.Reader, retry bool) (io.ReadCloser, error) { +func (c *Client) callWithRetry(serviceMethod string, data io.Reader, retry bool, reqOpts ...func(*RequestOpts)) (io.ReadCloser, error) { var retries int start := time.Now() + var opts RequestOpts + for _, o := range reqOpts { + o(&opts) + } + for { req, err := c.requestFactory.NewRequest(serviceMethod, data) if err != nil { return nil, err } + cancelRequest := func() {} + if opts.Timeout > 0 { + var ctx context.Context + ctx, cancelRequest = context.WithTimeout(req.Context(), opts.Timeout) + req = req.WithContext(ctx) + } + resp, err := c.http.Do(req) if err != nil { + cancelRequest() if !retry { return nil, err } @@ -157,6 +189,7 @@ func (c *Client) callWithRetry(serviceMethod string, data io.Reader, retry bool) if resp.StatusCode != http.StatusOK { b, err := ioutil.ReadAll(resp.Body) resp.Body.Close() + cancelRequest() if err != nil { return nil, &statusError{resp.StatusCode, serviceMethod, err.Error()} } @@ -176,7 +209,11 @@ func (c *Client) callWithRetry(serviceMethod string, data io.Reader, retry bool) // old way... return nil, &statusError{resp.StatusCode, serviceMethod, string(b)} } - return resp.Body, nil + return ioutils.NewReadCloserWrapper(resp.Body, func() error { + err := resp.Body.Close() + cancelRequest() + return err + }), nil } } diff --git a/vendor/github.com/docker/docker/pkg/reexec/command_linux.go b/vendor/github.com/docker/docker/pkg/reexec/command_linux.go index 05319eacc..d3f10615f 100644 --- a/vendor/github.com/docker/docker/pkg/reexec/command_linux.go +++ b/vendor/github.com/docker/docker/pkg/reexec/command_linux.go @@ -1,5 +1,3 @@ -// +build linux - package reexec import ( diff --git a/vendor/github.com/docker/docker/pkg/reexec/command_windows.go b/vendor/github.com/docker/docker/pkg/reexec/command_windows.go index ca871c422..c320876b7 100644 --- a/vendor/github.com/docker/docker/pkg/reexec/command_windows.go +++ b/vendor/github.com/docker/docker/pkg/reexec/command_windows.go @@ -1,5 +1,3 @@ -// +build windows - package reexec import ( diff --git a/vendor/github.com/docker/docker/pkg/signal/signal_windows.go b/vendor/github.com/docker/docker/pkg/signal/signal_windows.go index 440f2700e..c84a63e82 100644 --- a/vendor/github.com/docker/docker/pkg/signal/signal_windows.go +++ b/vendor/github.com/docker/docker/pkg/signal/signal_windows.go @@ -1,5 +1,3 @@ -// +build windows - package signal import ( diff --git a/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_linux.go b/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_linux.go index f1d2d9db3..5739b33ac 100644 --- a/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_linux.go +++ b/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_linux.go @@ -1,5 +1,3 @@ -// +build linux - package sysinfo import ( diff --git a/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_windows.go b/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_windows.go index 1d89dd550..3516182ff 100644 --- a/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_windows.go +++ b/vendor/github.com/docker/docker/pkg/sysinfo/numcpu_windows.go @@ -1,5 +1,3 @@ -// +build windows - package sysinfo import ( diff --git a/vendor/github.com/docker/docker/pkg/sysinfo/sysinfo_windows.go b/vendor/github.com/docker/docker/pkg/sysinfo/sysinfo_windows.go index 4e6255bc5..8889318c3 100644 --- a/vendor/github.com/docker/docker/pkg/sysinfo/sysinfo_windows.go +++ b/vendor/github.com/docker/docker/pkg/sysinfo/sysinfo_windows.go @@ -1,5 +1,3 @@ -// +build windows - package sysinfo // New returns an empty SysInfo for windows for now. diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes.go b/vendor/github.com/docker/docker/pkg/system/chtimes.go index 056d19954..18378f1ca 100644 --- a/vendor/github.com/docker/docker/pkg/system/chtimes.go +++ b/vendor/github.com/docker/docker/pkg/system/chtimes.go @@ -27,9 +27,5 @@ func Chtimes(name string, atime time.Time, mtime time.Time) error { } // Take platform specific action for setting create time. - if err := setCTime(name, mtime); err != nil { - return err - } - - return nil + return setCTime(name, mtime) } diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go b/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go index 45428c141..a1f4fd53b 100644 --- a/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go @@ -1,5 +1,3 @@ -// +build windows - package system import ( diff --git a/vendor/github.com/docker/docker/pkg/system/errors.go b/vendor/github.com/docker/docker/pkg/system/errors.go index 288318985..1b5bc2c03 100644 --- a/vendor/github.com/docker/docker/pkg/system/errors.go +++ b/vendor/github.com/docker/docker/pkg/system/errors.go @@ -7,4 +7,7 @@ import ( var ( // ErrNotSupportedPlatform means the platform is not supported. ErrNotSupportedPlatform = errors.New("platform and architecture is not supported") + + // ErrNotSupportedOperatingSystem means the operating system is not supported. + ErrNotSupportedOperatingSystem = errors.New("operating system is not supported") ) diff --git a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go index a61b53d0b..b1e46d9e8 100644 --- a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go @@ -1,5 +1,3 @@ -// +build windows - package system import ( diff --git a/vendor/github.com/docker/docker/pkg/system/init_windows.go b/vendor/github.com/docker/docker/pkg/system/init_windows.go index 75f8f2c06..948794736 100644 --- a/vendor/github.com/docker/docker/pkg/system/init_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/init_windows.go @@ -1,17 +1,12 @@ package system -import "os" - // lcowSupported determines if Linux Containers on Windows are supported. var lcowSupported = false // InitLCOW sets whether LCOW is supported or not -// TODO @jhowardmsft. -// 1. Replace with RS3 RTM build number. -// 2. Remove the getenv check when image-store is coalesced as shouldn't be needed anymore. func InitLCOW(experimental bool) { v := GetOSVersion() - if experimental && v.Build > 16270 && os.Getenv("LCOW_SUPPORTED") != "" { + if experimental && v.Build >= 16299 { lcowSupported = true } } diff --git a/vendor/github.com/docker/docker/pkg/system/lcow.go b/vendor/github.com/docker/docker/pkg/system/lcow.go index b88c11e31..95958b2c8 100644 --- a/vendor/github.com/docker/docker/pkg/system/lcow.go +++ b/vendor/github.com/docker/docker/pkg/system/lcow.go @@ -56,3 +56,14 @@ func ParsePlatform(in string) *specs.Platform { } return p } + +// IsOSSupported determines if an operating system is supported by the host +func IsOSSupported(os string) bool { + if runtime.GOOS == os { + return true + } + if LCOWSupported() && os == "linux" { + return true + } + return false +} diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_windows.go b/vendor/github.com/docker/docker/pkg/system/mknod_windows.go index 2e863c021..ba2692aed 100644 --- a/vendor/github.com/docker/docker/pkg/system/mknod_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/mknod_windows.go @@ -1,5 +1,3 @@ -// +build windows - package system // Mknod is not implemented on Windows. diff --git a/vendor/github.com/docker/docker/pkg/system/stat_unix.go b/vendor/github.com/docker/docker/pkg/system/stat_unix.go index 91c7d121c..9dcec6afb 100644 --- a/vendor/github.com/docker/docker/pkg/system/stat_unix.go +++ b/vendor/github.com/docker/docker/pkg/system/stat_unix.go @@ -47,6 +47,11 @@ func (s StatT) Mtim() syscall.Timespec { return s.mtim } +// IsDir reports whether s describes a directory. +func (s StatT) IsDir() bool { + return s.mode&syscall.S_IFDIR != 0 +} + // Stat takes a path to a file and returns // a system.StatT type pertaining to that file. // diff --git a/vendor/github.com/docker/docker/pkg/system/umask_windows.go b/vendor/github.com/docker/docker/pkg/system/umask_windows.go index 13f1de176..71fc0f1ba 100644 --- a/vendor/github.com/docker/docker/pkg/system/umask_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/umask_windows.go @@ -1,5 +1,3 @@ -// +build windows - package system // Umask is not supported on the windows platform. diff --git a/vendor/github.com/docker/docker/pkg/tarsum/fileinfosums.go b/vendor/github.com/docker/docker/pkg/tarsum/fileinfosums.go index 5abf5e7ba..908131ebc 100644 --- a/vendor/github.com/docker/docker/pkg/tarsum/fileinfosums.go +++ b/vendor/github.com/docker/docker/pkg/tarsum/fileinfosums.go @@ -1,6 +1,10 @@ package tarsum -import "sort" +import ( + "runtime" + "sort" + "strings" +) // FileInfoSumInterface provides an interface for accessing file checksum // information within a tar file. This info is accessed through interface @@ -35,8 +39,11 @@ type FileInfoSums []FileInfoSumInterface // GetFile returns the first FileInfoSumInterface with a matching name. func (fis FileInfoSums) GetFile(name string) FileInfoSumInterface { + // We do case insensitive matching on Windows as c:\APP and c:\app are + // the same. See issue #33107. for i := range fis { - if fis[i].Name() == name { + if (runtime.GOOS == "windows" && strings.EqualFold(fis[i].Name(), name)) || + (runtime.GOOS != "windows" && fis[i].Name() == name) { return fis[i] } } diff --git a/vendor/github.com/docker/docker/pkg/term/term_windows.go b/vendor/github.com/docker/docker/pkg/term/term_windows.go index b6819b342..284ac6301 100644 --- a/vendor/github.com/docker/docker/pkg/term/term_windows.go +++ b/vendor/github.com/docker/docker/pkg/term/term_windows.go @@ -1,5 +1,3 @@ -// +build windows - package term import ( diff --git a/vendor/github.com/docker/docker/plugin/backend_linux.go b/vendor/github.com/docker/docker/plugin/backend_linux.go index 28a6c18ab..7d71808e3 100644 --- a/vendor/github.com/docker/docker/plugin/backend_linux.go +++ b/vendor/github.com/docker/docker/plugin/backend_linux.go @@ -1,5 +1,3 @@ -// +build linux - package plugin import ( @@ -12,6 +10,7 @@ import ( "os" "path" "path/filepath" + "runtime" "strings" "github.com/docker/distribution/manifest/schema2" @@ -22,6 +21,7 @@ import ( progressutils "github.com/docker/docker/distribution/utils" "github.com/docker/docker/distribution/xfer" "github.com/docker/docker/dockerversion" + "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/docker/docker/layer" "github.com/docker/docker/pkg/authorization" @@ -146,7 +146,7 @@ func (s *tempConfigStore) Get(d digest.Digest) ([]byte, error) { return s.config, nil } -func (s *tempConfigStore) RootFSAndOSFromConfig(c []byte) (*image.RootFS, layer.OS, error) { +func (s *tempConfigStore) RootFSAndOSFromConfig(c []byte) (*image.RootFS, string, error) { return configToRootFS(c) } @@ -235,7 +235,7 @@ func (pm *Manager) Privileges(ctx context.Context, ref reference.Named, metaHead } var config types.PluginConfig if err := json.Unmarshal(cs.config, &config); err != nil { - return nil, systemError{err} + return nil, errdefs.System(err) } return computePrivileges(config), nil @@ -257,12 +257,12 @@ func (pm *Manager) Upgrade(ctx context.Context, ref reference.Named, name string // revalidate because Pull is public if _, err := reference.ParseNormalizedNamed(name); err != nil { - return errors.Wrapf(validationError{err}, "failed to parse %q", name) + return errors.Wrapf(errdefs.InvalidParameter(err), "failed to parse %q", name) } tmpRootFSDir, err := ioutil.TempDir(pm.tmpDir(), ".rootfs") if err != nil { - return errors.Wrap(systemError{err}, "error preparing upgrade") + return errors.Wrap(errdefs.System(err), "error preparing upgrade") } defer os.RemoveAll(tmpRootFSDir) @@ -304,17 +304,17 @@ func (pm *Manager) Pull(ctx context.Context, ref reference.Named, name string, m // revalidate because Pull is public nameref, err := reference.ParseNormalizedNamed(name) if err != nil { - return errors.Wrapf(validationError{err}, "failed to parse %q", name) + return errors.Wrapf(errdefs.InvalidParameter(err), "failed to parse %q", name) } name = reference.FamiliarString(reference.TagNameOnly(nameref)) if err := pm.config.Store.validateName(name); err != nil { - return validationError{err} + return errdefs.InvalidParameter(err) } tmpRootFSDir, err := ioutil.TempDir(pm.tmpDir(), ".rootfs") if err != nil { - return errors.Wrap(systemError{err}, "error preparing pull") + return errors.Wrap(errdefs.System(err), "error preparing pull") } defer os.RemoveAll(tmpRootFSDir) @@ -441,7 +441,8 @@ func (pm *Manager) Push(ctx context.Context, name string, metaHeader http.Header pm: pm, plugin: p, } - ls := &pluginLayerProvider{ + lss := make(map[string]distribution.PushLayerProvider) + lss[runtime.GOOS] = &pluginLayerProvider{ pm: pm, plugin: p, } @@ -464,7 +465,7 @@ func (pm *Manager) Push(ctx context.Context, name string, metaHeader http.Header RequireSchema2: true, }, ConfigMediaType: schema2.MediaTypePluginConfig, - LayerStore: ls, + LayerStores: lss, UploadManager: uploadManager, } @@ -533,7 +534,7 @@ func (s *pluginConfigStore) Get(d digest.Digest) ([]byte, error) { return ioutil.ReadAll(rwc) } -func (s *pluginConfigStore) RootFSAndOSFromConfig(c []byte) (*image.RootFS, layer.OS, error) { +func (s *pluginConfigStore) RootFSAndOSFromConfig(c []byte) (*image.RootFS, string, error) { return configToRootFS(c) } diff --git a/vendor/github.com/docker/docker/plugin/blobstore.go b/vendor/github.com/docker/docker/plugin/blobstore.go index 1f358e6c4..157831182 100644 --- a/vendor/github.com/docker/docker/plugin/blobstore.go +++ b/vendor/github.com/docker/docker/plugin/blobstore.go @@ -126,8 +126,7 @@ type downloadManager struct { configDigest digest.Digest } -func (dm *downloadManager) Download(ctx context.Context, initialRootFS image.RootFS, os layer.OS, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error) { - // TODO @jhowardmsft LCOW: May need revisiting. +func (dm *downloadManager) Download(ctx context.Context, initialRootFS image.RootFS, os string, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error) { for _, l := range layers { b, err := dm.blobStore.New() if err != nil { @@ -179,6 +178,6 @@ func (dm *downloadManager) Put(dt []byte) (digest.Digest, error) { func (dm *downloadManager) Get(d digest.Digest) ([]byte, error) { return nil, fmt.Errorf("digest not found") } -func (dm *downloadManager) RootFSAndOSFromConfig(c []byte) (*image.RootFS, layer.OS, error) { +func (dm *downloadManager) RootFSAndOSFromConfig(c []byte) (*image.RootFS, string, error) { return configToRootFS(c) } diff --git a/vendor/github.com/docker/docker/plugin/errors.go b/vendor/github.com/docker/docker/plugin/errors.go index 0a101d4dc..a4f6fa810 100644 --- a/vendor/github.com/docker/docker/plugin/errors.go +++ b/vendor/github.com/docker/docker/plugin/errors.go @@ -26,34 +26,6 @@ func (name errDisabled) Error() string { func (name errDisabled) Conflict() {} -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (validationError) Conflict() {} - -func (e validationError) Cause() error { - return e.cause -} - -type systemError struct { - cause error -} - -func (e systemError) Error() string { - return e.cause.Error() -} - -func (systemError) SystemError() {} - -func (e systemError) Cause() error { - return e.cause -} - type invalidFilter struct { filter string value []string diff --git a/vendor/github.com/docker/docker/plugin/executor/containerd/containerd.go b/vendor/github.com/docker/docker/plugin/executor/containerd/containerd.go index d93b8b75e..7b35136a1 100644 --- a/vendor/github.com/docker/docker/plugin/executor/containerd/containerd.go +++ b/vendor/github.com/docker/docker/plugin/executor/containerd/containerd.go @@ -6,9 +6,9 @@ import ( "path/filepath" "sync" - "github.com/containerd/containerd" - "github.com/containerd/containerd/linux/runcopts" - "github.com/docker/docker/api/errdefs" + "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/linux/runctypes" + "github.com/docker/docker/errdefs" "github.com/docker/docker/libcontainerd" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" @@ -16,7 +16,7 @@ import ( ) // PluginNamespace is the name used for the plugins namespace -var PluginNamespace = "moby-plugins" +var PluginNamespace = "plugins.moby" // ExitHandler represents an object that is called when the exit event is received from containerd type ExitHandler interface { @@ -46,7 +46,7 @@ type Executor struct { // Create creates a new container func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteCloser) error { - opts := runcopts.RuncOptions{ + opts := runctypes.RuncOptions{ RuntimeRoot: filepath.Join(e.rootDir, "runtime-root"), } ctx := context.Background() @@ -110,37 +110,37 @@ func (e *Executor) ProcessEvent(id string, et libcontainerd.EventType, ei libcon return nil } -type cio struct { - containerd.IO +type rio struct { + cio.IO wg sync.WaitGroup } -func (c *cio) Wait() { +func (c *rio) Wait() { c.wg.Wait() c.IO.Wait() } func attachStreamsFunc(stdout, stderr io.WriteCloser) libcontainerd.StdioCallback { - return func(iop *libcontainerd.IOPipe) (containerd.IO, error) { + return func(iop *cio.DirectIO) (cio.IO, error) { if iop.Stdin != nil { iop.Stdin.Close() // closing stdin shouldn't be needed here, it should never be open panic("plugin stdin shouldn't have been created!") } - cio := &cio{IO: iop} - cio.wg.Add(2) + rio := &rio{IO: iop} + rio.wg.Add(2) go func() { io.Copy(stdout, iop.Stdout) stdout.Close() - cio.wg.Done() + rio.wg.Done() }() go func() { io.Copy(stderr, iop.Stderr) stderr.Close() - cio.wg.Done() + rio.wg.Done() }() - return cio, nil + return rio, nil } } diff --git a/vendor/github.com/docker/docker/plugin/manager.go b/vendor/github.com/docker/docker/plugin/manager.go index f144e8208..d686443c6 100644 --- a/vendor/github.com/docker/docker/plugin/manager.go +++ b/vendor/github.com/docker/docker/plugin/manager.go @@ -375,12 +375,9 @@ func isEqualPrivilege(a, b types.PluginPrivilege) bool { return reflect.DeepEqual(a.Value, b.Value) } -func configToRootFS(c []byte) (*image.RootFS, layer.OS, error) { - // TODO @jhowardmsft LCOW - Will need to revisit this. For now, calculate the operating system. - os := layer.OS(runtime.GOOS) - if system.LCOWSupported() { - os = "linux" - } +func configToRootFS(c []byte) (*image.RootFS, string, error) { + // TODO @jhowardmsft LCOW - Will need to revisit this. + os := runtime.GOOS var pluginConfig types.PluginConfig if err := json.Unmarshal(c, &pluginConfig); err != nil { return nil, "", err diff --git a/vendor/github.com/docker/docker/plugin/manager_linux.go b/vendor/github.com/docker/docker/plugin/manager_linux.go index eff21e1d0..65380af06 100644 --- a/vendor/github.com/docker/docker/plugin/manager_linux.go +++ b/vendor/github.com/docker/docker/plugin/manager_linux.go @@ -1,5 +1,3 @@ -// +build linux - package plugin import ( @@ -11,6 +9,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/daemon/initlayer" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/containerfs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/mount" @@ -219,12 +218,12 @@ func (pm *Manager) upgradePlugin(p *v2.Plugin, configDigest digest.Digest, blobs // This could happen if the plugin was disabled with `-f` with active mounts. // If there is anything in `orig` is still mounted, this should error out. if err := mount.RecursiveUnmount(orig); err != nil { - return systemError{err} + return errdefs.System(err) } backup := orig + "-old" if err := os.Rename(orig, backup); err != nil { - return errors.Wrap(systemError{err}, "error backing up plugin data before upgrade") + return errors.Wrap(errdefs.System(err), "error backing up plugin data before upgrade") } defer func() { @@ -250,7 +249,7 @@ func (pm *Manager) upgradePlugin(p *v2.Plugin, configDigest digest.Digest, blobs }() if err := os.Rename(tmpRootFSDir, orig); err != nil { - return errors.Wrap(systemError{err}, "error upgrading") + return errors.Wrap(errdefs.System(err), "error upgrading") } p.PluginObj.Config = config @@ -290,7 +289,7 @@ func (pm *Manager) setupNewPlugin(configDigest digest.Digest, blobsums []digest. // createPlugin creates a new plugin. take lock before calling. func (pm *Manager) createPlugin(name string, configDigest digest.Digest, blobsums []digest.Digest, rootFSDir string, privileges *types.PluginPrivileges, opts ...CreateOpt) (p *v2.Plugin, err error) { if err := pm.config.Store.validateName(name); err != nil { // todo: this check is wrong. remove store - return nil, validationError{err} + return nil, errdefs.InvalidParameter(err) } config, err := pm.setupNewPlugin(configDigest, blobsums, privileges) diff --git a/vendor/github.com/docker/docker/plugin/manager_linux_test.go b/vendor/github.com/docker/docker/plugin/manager_linux_test.go new file mode 100644 index 000000000..3259ca8cf --- /dev/null +++ b/vendor/github.com/docker/docker/plugin/manager_linux_test.go @@ -0,0 +1,79 @@ +package plugin + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/pkg/mount" + "github.com/docker/docker/pkg/system" + "github.com/docker/docker/plugin/v2" +) + +func TestManagerWithPluginMounts(t *testing.T) { + root, err := ioutil.TempDir("", "test-store-with-plugin-mounts") + if err != nil { + t.Fatal(err) + } + defer system.EnsureRemoveAll(root) + + s := NewStore() + managerRoot := filepath.Join(root, "manager") + p1 := newTestPlugin(t, "test1", "testcap", managerRoot) + + p2 := newTestPlugin(t, "test2", "testcap", managerRoot) + p2.PluginObj.Enabled = true + + m, err := NewManager( + ManagerConfig{ + Store: s, + Root: managerRoot, + ExecRoot: filepath.Join(root, "exec"), + CreateExecutor: func(*Manager) (Executor, error) { return nil, nil }, + LogPluginEvent: func(_, _, _ string) {}, + }) + if err != nil { + t.Fatal(err) + } + + if err := s.Add(p1); err != nil { + t.Fatal(err) + } + if err := s.Add(p2); err != nil { + t.Fatal(err) + } + + // Create a mount to simulate a plugin that has created it's own mounts + p2Mount := filepath.Join(p2.Rootfs, "testmount") + if err := os.MkdirAll(p2Mount, 0755); err != nil { + t.Fatal(err) + } + if err := mount.Mount("tmpfs", p2Mount, "tmpfs", ""); err != nil { + t.Fatal(err) + } + + if err := m.Remove(p1.Name(), &types.PluginRmConfig{ForceRemove: true}); err != nil { + t.Fatal(err) + } + if mounted, err := mount.Mounted(p2Mount); !mounted || err != nil { + t.Fatalf("expected %s to be mounted, err: %v", p2Mount, err) + } +} + +func newTestPlugin(t *testing.T, name, cap, root string) *v2.Plugin { + rootfs := filepath.Join(root, name) + if err := os.MkdirAll(rootfs, 0755); err != nil { + t.Fatal(err) + } + + p := v2.Plugin{PluginObj: types.Plugin{Name: name}} + p.Rootfs = rootfs + iType := types.PluginInterfaceType{Capability: cap, Prefix: "docker", Version: "1.0"} + i := types.PluginConfigInterface{Socket: "plugins.sock", Types: []types.PluginInterfaceType{iType}} + p.PluginObj.Config.Interface = i + p.PluginObj.ID = name + + return &p +} diff --git a/vendor/github.com/docker/docker/plugin/manager_solaris.go b/vendor/github.com/docker/docker/plugin/manager_solaris.go deleted file mode 100644 index ac03d6e63..000000000 --- a/vendor/github.com/docker/docker/plugin/manager_solaris.go +++ /dev/null @@ -1,30 +0,0 @@ -package plugin - -import ( - "fmt" - - "github.com/docker/docker/plugin/v2" - specs "github.com/opencontainers/runtime-spec/specs-go" -) - -func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error { - return fmt.Errorf("Not implemented") -} - -func (pm *Manager) initSpec(p *v2.Plugin) (*specs.Spec, error) { - return nil, fmt.Errorf("Not implemented") -} - -func (pm *Manager) disable(p *v2.Plugin, c *controller) error { - return fmt.Errorf("Not implemented") -} - -func (pm *Manager) restore(p *v2.Plugin) error { - return fmt.Errorf("Not implemented") -} - -// Shutdown plugins -func (pm *Manager) Shutdown() { -} - -func setupRoot(root string) error { return nil } diff --git a/vendor/github.com/docker/docker/plugin/manager_windows.go b/vendor/github.com/docker/docker/plugin/manager_windows.go index 56a7ee3ec..ac03d6e63 100644 --- a/vendor/github.com/docker/docker/plugin/manager_windows.go +++ b/vendor/github.com/docker/docker/plugin/manager_windows.go @@ -1,5 +1,3 @@ -// +build windows - package plugin import ( diff --git a/vendor/github.com/docker/docker/plugin/store.go b/vendor/github.com/docker/docker/plugin/store.go index b3398145d..9768c2506 100644 --- a/vendor/github.com/docker/docker/plugin/store.go +++ b/vendor/github.com/docker/docker/plugin/store.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/docker/distribution/reference" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/plugingetter" "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/plugin/v2" @@ -144,7 +145,7 @@ func (ps *Store) Get(name, capability string, mode int) (plugingetter.CompatPlug if errors.Cause(err) == plugins.ErrNotFound { return nil, errNotFound(name) } - return nil, errors.Wrap(systemError{err}, "legacy plugin") + return nil, errors.Wrap(errdefs.System(err), "legacy plugin") } // GetAllManagedPluginsByCap returns a list of managed plugins matching the given capability. @@ -172,7 +173,7 @@ func (ps *Store) GetAllByCap(capability string) ([]plugingetter.CompatPlugin, er if allowV1PluginsFallback { pl, err := plugins.GetAll(capability) if err != nil { - return nil, errors.Wrap(systemError{err}, "legacy plugin") + return nil, errors.Wrap(errdefs.System(err), "legacy plugin") } for _, p := range pl { result = append(result, p) diff --git a/vendor/github.com/docker/docker/plugin/v2/plugin.go b/vendor/github.com/docker/docker/plugin/v2/plugin.go index b77536c98..ce3257c0c 100644 --- a/vendor/github.com/docker/docker/plugin/v2/plugin.go +++ b/vendor/github.com/docker/docker/plugin/v2/plugin.go @@ -142,6 +142,9 @@ next: } // it is, so lets update the settings in memory + if mount.Source == nil { + return fmt.Errorf("Plugin config has no mount source") + } *mount.Source = s.value continue next } @@ -159,6 +162,9 @@ next: } // it is, so lets update the settings in memory + if device.Path == nil { + return fmt.Errorf("Plugin config has no device path") + } *device.Path = s.value continue next } diff --git a/vendor/github.com/docker/docker/plugin/v2/plugin_linux.go b/vendor/github.com/docker/docker/plugin/v2/plugin_linux.go index be8236324..9590df4f7 100644 --- a/vendor/github.com/docker/docker/plugin/v2/plugin_linux.go +++ b/vendor/github.com/docker/docker/plugin/v2/plugin_linux.go @@ -1,5 +1,3 @@ -// +build linux - package v2 import ( diff --git a/vendor/github.com/docker/docker/project/GOVERNANCE.md b/vendor/github.com/docker/docker/project/GOVERNANCE.md index 6ae7baf74..4b52989a6 100644 --- a/vendor/github.com/docker/docker/project/GOVERNANCE.md +++ b/vendor/github.com/docker/docker/project/GOVERNANCE.md @@ -1,17 +1,120 @@ -# Docker Governance Advisory Board Meetings +# Moby project governance -In the spirit of openness, Docker created a Governance Advisory Board, and committed to make all materials and notes from the meetings of this group public. -All output from the meetings should be considered proposals only, and are subject to the review and approval of the community and the project leadership. +Moby projects are governed by the [Moby Technical Steering Committee (TSC)](https://github.com/moby/tsc). +See the Moby TSC [charter](https://github.com/moby/tsc/blob/master/README.md) for +further information on the role of the TSC and procedures for escalation +of technical issues or concerns. -The materials from the first Docker Governance Advisory Board meeting, held on October 28, 2014, are available at -[Google Docs Folder](https://goo.gl/Alfj8r) +Contact [any Moby TSC member](https://github.com/moby/tsc/blob/master/MEMBERS.md) with your questions/concerns about the governance or a specific technical +issue that you feel requires escalation. -These include: +## Project maintainers -* First Meeting Notes -* DGAB Charter -* Presentation 1: Introductory Presentation, including State of The Project -* Presentation 2: Overall Contribution Structure/Docker Project Core Proposal -* Presentation 3: Long Term Roadmap/Statement of Direction - +The current maintainers of the moby/moby repository are listed in the +[MAINTAINERS](/MAINTAINERS) file. +There are different types of maintainers, with different responsibilities, but +all maintainers have 3 things in common: + + 1. They share responsibility in the project's success. + 2. They have made a long-term, recurring time investment to improve the project. + 3. They spend that time doing whatever needs to be done, not necessarily what is the most interesting or fun. + +Maintainers are often under-appreciated, because their work is less visible. +It's easy to recognize a really cool and technically advanced feature. It's harder +to appreciate the absence of bugs, the slow but steady improvement in stability, +or the reliability of a release process. But those things distinguish a good +project from a great one. + +### Adding maintainers + +Maintainers are first and foremost contributors who have shown their +commitment to the long term success of a project. Contributors who want to +become maintainers first demonstrate commitment to the project by contributing +code, reviewing others' work, and triaging issues on a regular basis for at +least three months. + +The contributions alone don't make you a maintainer. You need to earn the +trust of the current maintainers and other project contributors, that your +decisions and actions are in the best interest of the project. + +Periodically, the existing maintainers curate a list of contributors who have +shown regular activity on the project over the prior months. From this +list, maintainer candidates are selected and proposed on the maintainers +mailing list. + +After a candidate is announced on the maintainers mailing list, the +existing maintainers discuss the candidate over the next 5 business days, +provide feedback, and vote. At least 66% of the current maintainers must +vote in the affirmative. + +If a candidate is approved, a maintainer contacts the candidate to +invite them to open a pull request that adds the contributor to +the MAINTAINERS file. The candidate becomes a maintainer once the pull +request is merged. + +### Removing maintainers + +Maintainers can be removed from the project, either at their own request +or due to [project inactivity](#inactive-maintainer-policy). + +#### How to step down + +Life priorities, interests, and passions can change. If you're a maintainer but +feel you must remove yourself from the list, inform other maintainers that you +intend to step down, and if possible, help find someone to pick up your work. +At the very least, ensure your work can be continued where you left off. + +After you've informed other maintainers, create a pull request to remove +yourself from the MAINTAINERS file. + +#### Inactive maintainer policy + +An existing maintainer can be removed if they do not show significant activity +on the project. Periodically, the maintainers review the list of maintainers +and their activity over the last three months. + +If a maintainer has shown insufficient activity over this period, a project +representative will contact the maintainer to ask if they want to continue +being a maintainer. If the maintainer decides to step down as a maintainer, +they open a pull request to be removed from the MAINTAINERS file. + +If the maintainer wants to continue in this role, but is unable to perform the +required duties, they can be removed with a vote by at least 66% of the current +maintainers. The maintainer under discussion will not be allowed to vote. An +e-mail is sent to the mailing list, inviting maintainers of the project to +vote. The voting period is five business days. Issues related to a maintainer's +performance should be discussed with them among the other maintainers so that +they are not surprised by a pull request removing them. This discussion should +be handled objectively with no ad hominem attacks. + +## Project decision making + +Short answer: **Everything is a pull request**. + +The Moby core engine project is an open-source project with an open design +philosophy. This means that the repository is the source of truth for **every** +aspect of the project, including its philosophy, design, road map, and APIs. +*If it's part of the project, it's in the repo. If it's in the repo, it's part +of the project.* + +As a result, each decision can be expressed as a change to the repository. An +implementation change is expressed as a change to the source code. An API +change is a change to the API specification. A philosophy change is a change +to the philosophy manifesto, and so on. + +All decisions affecting the moby/moby repository, both big and small, follow +the same steps: + + * **Step 1**: Open a pull request. Anyone can do this. + + * **Step 2**: Discuss the pull request. Anyone can do this. + + * **Step 3**: Maintainers merge, close or reject the pull request. + +Pull requests are reviewed by the current maintainers of the moby/moby +repository. Weekly meetings are organized to are organized to synchronously +discuss tricky PRs, as well as design and architecture decisions.. When +technical agreement cannot be reached among the maintainers of the project, +escalation or concerns can be raised by opening an issue to be handled +by the [Moby Technical Steering Committee](https://github.com/moby/tsc). diff --git a/vendor/github.com/docker/docker/registry/auth.go b/vendor/github.com/docker/docker/registry/auth.go index 11937d801..56b9c8829 100644 --- a/vendor/github.com/docker/docker/registry/auth.go +++ b/vendor/github.com/docker/docker/registry/auth.go @@ -12,6 +12,7 @@ import ( "github.com/docker/distribution/registry/client/transport" "github.com/docker/docker/api/types" registrytypes "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -29,7 +30,7 @@ func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent st logrus.Debugf("attempting v1 login to registry endpoint %s", serverAddress) if serverAddress == "" { - return "", "", systemError{errors.New("server Error: Server Address not set")} + return "", "", errdefs.System(errors.New("server Error: Server Address not set")) } req, err := http.NewRequest("GET", serverAddress+"users/", nil) @@ -47,23 +48,23 @@ func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent st defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { - return "", "", systemError{err} + return "", "", errdefs.System(err) } switch resp.StatusCode { case http.StatusOK: return "Login Succeeded", "", nil case http.StatusUnauthorized: - return "", "", unauthorizedError{errors.New("Wrong login/password, please try again")} + return "", "", errdefs.Unauthorized(errors.New("Wrong login/password, please try again")) case http.StatusForbidden: // *TODO: Use registry configuration to determine what this says, if anything? - return "", "", notActivatedError{errors.Errorf("Login: Account is not active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress)} + return "", "", errdefs.Forbidden(errors.Errorf("Login: Account is not active. Please see the documentation of the registry %s for instructions how to activate it.", serverAddress)) case http.StatusInternalServerError: logrus.Errorf("%s returned status code %d. Response Body :\n%s", req.URL.String(), resp.StatusCode, body) - return "", "", systemError{errors.New("Internal Server Error")} + return "", "", errdefs.System(errors.New("Internal Server Error")) } - return "", "", systemError{errors.Errorf("Login: %s (Code: %d; Headers: %s)", body, - resp.StatusCode, resp.Header)} + return "", "", errdefs.System(errors.Errorf("Login: %s (Code: %d; Headers: %s)", body, + resp.StatusCode, resp.Header)) } type loginCredentialStore struct { diff --git a/vendor/github.com/docker/docker/registry/errors.go b/vendor/github.com/docker/docker/registry/errors.go index b388efca7..55f74d97e 100644 --- a/vendor/github.com/docker/docker/registry/errors.go +++ b/vendor/github.com/docker/docker/registry/errors.go @@ -4,6 +4,7 @@ import ( "net/url" "github.com/docker/distribution/registry/api/errcode" + "github.com/docker/docker/errdefs" ) type notFoundError string @@ -14,62 +15,6 @@ func (e notFoundError) Error() string { func (notFoundError) NotFound() {} -type validationError struct { - cause error -} - -func (e validationError) Error() string { - return e.cause.Error() -} - -func (e validationError) InvalidParameter() {} - -func (e validationError) Cause() error { - return e.cause -} - -type unauthorizedError struct { - cause error -} - -func (e unauthorizedError) Error() string { - return e.cause.Error() -} - -func (e unauthorizedError) Unauthorized() {} - -func (e unauthorizedError) Cause() error { - return e.cause -} - -type systemError struct { - cause error -} - -func (e systemError) Error() string { - return e.cause.Error() -} - -func (e systemError) SystemError() {} - -func (e systemError) Cause() error { - return e.cause -} - -type notActivatedError struct { - cause error -} - -func (e notActivatedError) Error() string { - return e.cause.Error() -} - -func (e notActivatedError) Forbidden() {} - -func (e notActivatedError) Cause() error { - return e.cause -} - func translateV2AuthError(err error) error { switch e := err.(type) { case *url.Error: @@ -77,7 +22,7 @@ func translateV2AuthError(err error) error { case errcode.Error: switch e2.Code { case errcode.ErrorCodeUnauthorized: - return unauthorizedError{err} + return errdefs.Unauthorized(err) } } } diff --git a/vendor/github.com/docker/docker/registry/service.go b/vendor/github.com/docker/docker/registry/service.go index f3f1b4a56..bf4ab94d9 100644 --- a/vendor/github.com/docker/docker/registry/service.go +++ b/vendor/github.com/docker/docker/registry/service.go @@ -13,6 +13,7 @@ import ( "github.com/docker/distribution/registry/client/auth" "github.com/docker/docker/api/types" registrytypes "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/errdefs" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -117,12 +118,12 @@ func (s *DefaultService) Auth(ctx context.Context, authConfig *types.AuthConfig, } u, err := url.Parse(serverAddress) if err != nil { - return "", "", validationError{errors.Errorf("unable to parse server address: %v", err)} + return "", "", errdefs.InvalidParameter(errors.Errorf("unable to parse server address: %v", err)) } endpoints, err := s.LookupPushEndpoints(u.Host) if err != nil { - return "", "", validationError{err} + return "", "", errdefs.InvalidParameter(err) } for _, endpoint := range endpoints { diff --git a/vendor/github.com/docker/docker/registry/session.go b/vendor/github.com/docker/docker/registry/session.go index e619d9f64..ae0ec1b4b 100644 --- a/vendor/github.com/docker/docker/registry/session.go +++ b/vendor/github.com/docker/docker/registry/session.go @@ -21,6 +21,7 @@ import ( "github.com/docker/distribution/registry/api/errcode" "github.com/docker/docker/api/types" registrytypes "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/ioutils" "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/stringid" @@ -734,20 +735,20 @@ func shouldRedirect(response *http.Response) bool { // SearchRepositories performs a search against the remote repository func (r *Session) SearchRepositories(term string, limit int) (*registrytypes.SearchResults, error) { if limit < 1 || limit > 100 { - return nil, validationError{errors.Errorf("Limit %d is outside the range of [1, 100]", limit)} + return nil, errdefs.InvalidParameter(errors.Errorf("Limit %d is outside the range of [1, 100]", limit)) } logrus.Debugf("Index server: %s", r.indexEndpoint) u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit)) req, err := http.NewRequest("GET", u, nil) if err != nil { - return nil, errors.Wrap(validationError{err}, "Error building request") + return nil, errors.Wrap(errdefs.InvalidParameter(err), "Error building request") } // Have the AuthTransport send authentication, when logged in. req.Header.Set("X-Docker-Token", "true") res, err := r.client.Do(req) if err != nil { - return nil, systemError{err} + return nil, errdefs.System(err) } defer res.Body.Close() if res.StatusCode != 200 { diff --git a/vendor/github.com/docker/docker/vendor.conf b/vendor/github.com/docker/docker/vendor.conf index 448792524..04c31aa9a 100644 --- a/vendor/github.com/docker/docker/vendor.conf +++ b/vendor/github.com/docker/docker/vendor.conf @@ -1,7 +1,7 @@ # the following lines are in sorted order, FYI github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109 -github.com/Microsoft/hcsshim v0.6.7 -github.com/Microsoft/go-winio v0.4.5 +github.com/Microsoft/hcsshim v0.6.8 +github.com/Microsoft/go-winio v0.4.6 github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git @@ -20,7 +20,8 @@ github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756 github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987 github.com/pmezard/go-difflib v1.0.0 -github.com/gotestyourself/gotestyourself v1.1.0 +github.com/gotestyourself/gotestyourself 511344eed30e4384f010579a593dfb442033a692 +github.com/google/go-cmp v0.1.0 github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 github.com/imdario/mergo 0.2.1 @@ -30,7 +31,7 @@ github.com/moby/buildkit aaff9d591ef128560018433fe61beb802e149de8 github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 #get libnetwork packages -github.com/docker/libnetwork 72fd7e5495eba86e28012e39b5ed63ef9ca9a97b +github.com/docker/libnetwork 315a076a4e9ded2abc950318c71d5f1637547977 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec @@ -42,7 +43,7 @@ github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 -github.com/vishvananda/netlink bd6d5de5ccef2d66b0a26177928d0d8895d7f969 +github.com/vishvananda/netlink b2de5d10e38ecce8607e6b438b6d174f389a004e github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060 github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374 github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d @@ -65,9 +66,9 @@ github.com/pborman/uuid v1.0 google.golang.org/grpc v1.3.0 # When updating, also update RUNC_COMMIT in hack/dockerfile/binaries-commits accordingly -github.com/opencontainers/runc b2567b37d7b75eb4cf325b77297b140ea686ce8f -github.com/opencontainers/runtime-spec v1.0.0 -github.com/opencontainers/image-spec v1.0.0 +github.com/opencontainers/runc 7f24b40cc5423969b4554ef04ba0b00e2b4ba010 +github.com/opencontainers/runtime-spec v1.0.1 +github.com/opencontainers/image-spec v1.0.1 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json) @@ -77,12 +78,12 @@ github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 github.com/golang/protobuf 7a211bcf3bce0e3f1d74f9894916e6f116ae83b4 # gelf logging driver deps -github.com/Graylog2/go-gelf v2 +github.com/Graylog2/go-gelf 4143646226541087117ff2f83334ea48b3201841 -github.com/fluent/fluent-logger-golang v1.2.1 +github.com/fluent/fluent-logger-golang v1.3.0 # fluent-logger-golang deps github.com/philhofer/fwd 98c11a7a6ec829d672b03833c3d69a7fae1ca972 -github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c +github.com/tinylib/msgp 3b556c64540842d4f82967be066a7f7fffc3adad # fsnotify github.com/fsnotify/fsnotify 4da3e2cfbabc9f751898f250b49f2439785783a1 @@ -103,17 +104,18 @@ github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7 google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 # containerd -github.com/containerd/containerd v1.0.0-beta.3 +github.com/containerd/containerd 3fa104f843ec92328912e042b767d26825f202aa github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6 github.com/containerd/continuity 35d55c5e8dd23b32037d56cf97174aff3efdfa83 -github.com/containerd/cgroups f7dd103d3e4e696aa67152f6b4ddd1779a3455a9 +github.com/containerd/cgroups 29da22c6171a4316169f9205ab6c49f59b5b852f github.com/containerd/console 84eeaae905fa414d03e07bcd6c8d3f19e7cf180e github.com/containerd/go-runc ed1cbe1fc31f5fb2359d3a54b6330d1a097858b7 github.com/containerd/typeurl f6943554a7e7e88b3c14aad190bf05932da84788 -github.com/dmcgowan/go-tar 2e2c51242e8993c50445dab7c03c8e7febddd0cf +github.com/dmcgowan/go-tar go1.10 +github.com/stevvooe/ttrpc 76e68349ad9ab4d03d764c713826d31216715e4f # cluster -github.com/docker/swarmkit de950a7ed842c7b7e47e9451cde9bf8f96031894 +github.com/docker/swarmkit 713d79dc8799b33465c58ed120b870c52eb5eb4f github.com/gogo/protobuf v0.4 github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e @@ -147,7 +149,7 @@ github.com/opencontainers/selinux b29023b86e4a69d1b46b7e7b4e2b6fda03f0b9cd # archive/tar # mkdir -p ./vendor/archive # git clone git://github.com/tonistiigi/go-1.git ./go -# git --git-dir ./go/.git --work-tree ./go checkout revert-prefix-ignore +# git --git-dir ./go/.git --work-tree ./go checkout revert-prefix-ignore-1.9 # cp -a go/src/archive/tar ./vendor/archive/tar # rm -rf ./go # vndr diff --git a/vendor/github.com/docker/docker/volume/drivers/proxy.go b/vendor/github.com/docker/docker/volume/drivers/proxy.go index b23db6258..f4020d600 100644 --- a/vendor/github.com/docker/docker/volume/drivers/proxy.go +++ b/vendor/github.com/docker/docker/volume/drivers/proxy.go @@ -4,12 +4,19 @@ package volumedrivers import ( "errors" + "time" + "github.com/docker/docker/pkg/plugins" "github.com/docker/docker/volume" ) +const ( + longTimeout = 2 * time.Minute + shortTimeout = 1 * time.Minute +) + type client interface { - Call(string, interface{}, interface{}) error + CallWithOptions(string, interface{}, interface{}, ...func(*plugins.RequestOpts)) error } type volumeDriverProxy struct { @@ -33,7 +40,8 @@ func (pp *volumeDriverProxy) Create(name string, opts map[string]string) (err er req.Name = name req.Opts = opts - if err = pp.Call("VolumeDriver.Create", req, &ret); err != nil { + + if err = pp.CallWithOptions("VolumeDriver.Create", req, &ret, plugins.WithRequestTimeout(longTimeout)); err != nil { return } @@ -59,7 +67,8 @@ func (pp *volumeDriverProxy) Remove(name string) (err error) { ) req.Name = name - if err = pp.Call("VolumeDriver.Remove", req, &ret); err != nil { + + if err = pp.CallWithOptions("VolumeDriver.Remove", req, &ret, plugins.WithRequestTimeout(shortTimeout)); err != nil { return } @@ -86,7 +95,8 @@ func (pp *volumeDriverProxy) Path(name string) (mountpoint string, err error) { ) req.Name = name - if err = pp.Call("VolumeDriver.Path", req, &ret); err != nil { + + if err = pp.CallWithOptions("VolumeDriver.Path", req, &ret, plugins.WithRequestTimeout(shortTimeout)); err != nil { return } @@ -117,7 +127,8 @@ func (pp *volumeDriverProxy) Mount(name string, id string) (mountpoint string, e req.Name = name req.ID = id - if err = pp.Call("VolumeDriver.Mount", req, &ret); err != nil { + + if err = pp.CallWithOptions("VolumeDriver.Mount", req, &ret, plugins.WithRequestTimeout(longTimeout)); err != nil { return } @@ -147,7 +158,8 @@ func (pp *volumeDriverProxy) Unmount(name string, id string) (err error) { req.Name = name req.ID = id - if err = pp.Call("VolumeDriver.Unmount", req, &ret); err != nil { + + if err = pp.CallWithOptions("VolumeDriver.Unmount", req, &ret, plugins.WithRequestTimeout(shortTimeout)); err != nil { return } @@ -172,7 +184,7 @@ func (pp *volumeDriverProxy) List() (volumes []*proxyVolume, err error) { ret volumeDriverProxyListResponse ) - if err = pp.Call("VolumeDriver.List", req, &ret); err != nil { + if err = pp.CallWithOptions("VolumeDriver.List", req, &ret, plugins.WithRequestTimeout(shortTimeout)); err != nil { return } @@ -201,7 +213,8 @@ func (pp *volumeDriverProxy) Get(name string) (volume *proxyVolume, err error) { ) req.Name = name - if err = pp.Call("VolumeDriver.Get", req, &ret); err != nil { + + if err = pp.CallWithOptions("VolumeDriver.Get", req, &ret, plugins.WithRequestTimeout(shortTimeout)); err != nil { return } @@ -228,7 +241,7 @@ func (pp *volumeDriverProxy) Capabilities() (capabilities volume.Capability, err ret volumeDriverProxyCapabilitiesResponse ) - if err = pp.Call("VolumeDriver.Capabilities", req, &ret); err != nil { + if err = pp.CallWithOptions("VolumeDriver.Capabilities", req, &ret, plugins.WithRequestTimeout(shortTimeout)); err != nil { return } diff --git a/vendor/github.com/docker/docker/volume/lcow_parser.go b/vendor/github.com/docker/docker/volume/lcow_parser.go index aeb81a420..b6a49d84d 100644 --- a/vendor/github.com/docker/docker/volume/lcow_parser.go +++ b/vendor/github.com/docker/docker/volume/lcow_parser.go @@ -2,7 +2,6 @@ package volume import ( "errors" - "fmt" "path" "github.com/docker/docker/api/types/mount" @@ -10,7 +9,7 @@ import ( var lcowSpecificValidators mountValidator = func(m *mount.Mount) error { if path.Clean(m.Target) == "/" { - return fmt.Errorf("invalid specification: destination can't be '/'") + return ErrVolumeTargetIsRoot } if m.Type == mount.TypeNamedPipe { return errors.New("Linux containers on Windows do not support named pipe mounts") @@ -22,7 +21,7 @@ type lcowParser struct { windowsParser } -func (p *lcowParser) validateMountConfig(mnt *mount.Mount) error { +func (p *lcowParser) ValidateMountConfig(mnt *mount.Mount) error { return p.validateMountConfigReg(mnt, rxLCOWDestination, lcowSpecificValidators) } diff --git a/vendor/github.com/docker/docker/volume/linux_parser.go b/vendor/github.com/docker/docker/volume/linux_parser.go index 59605fe67..43f191538 100644 --- a/vendor/github.com/docker/docker/volume/linux_parser.go +++ b/vendor/github.com/docker/docker/volume/linux_parser.go @@ -29,7 +29,7 @@ func linuxSplitRawSpec(raw string) ([]string, error) { func linuxValidateNotRoot(p string) error { p = path.Clean(strings.Replace(p, `\`, `/`, -1)) if p == "/" { - return fmt.Errorf("invalid specification: destination can't be '/'") + return ErrVolumeTargetIsRoot } return nil } @@ -40,7 +40,7 @@ func linuxValidateAbsolute(p string) error { } return fmt.Errorf("invalid mount path: '%s' mount path must be absolute", p) } -func (p *linuxParser) validateMountConfig(mnt *mount.Mount) error { +func (p *linuxParser) ValidateMountConfig(mnt *mount.Mount) error { // there was something looking like a bug in existing codebase: // - validateMountConfig on linux was called with options skipping bind source existence when calling ParseMountRaw // - but not when calling ParseMountSpec directly... nor when the unit test called it directly diff --git a/vendor/github.com/docker/docker/volume/local/local.go b/vendor/github.com/docker/docker/volume/local/local.go index b37c45e61..206d96506 100644 --- a/vendor/github.com/docker/docker/volume/local/local.go +++ b/vendor/github.com/docker/docker/volume/local/local.go @@ -14,6 +14,7 @@ import ( "sync" "github.com/docker/docker/daemon/names" + "github.com/docker/docker/errdefs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/volume" @@ -139,30 +140,6 @@ func (r *Root) Name() string { return volume.DefaultDriverName } -type alreadyExistsError struct { - path string -} - -func (e alreadyExistsError) Error() string { - return "local volume already exists under " + e.path -} - -func (e alreadyExistsError) Conflict() {} - -type systemError struct { - err error -} - -func (e systemError) Error() string { - return e.err.Error() -} - -func (e systemError) SystemError() {} - -func (e systemError) Cause() error { - return e.err -} - // Create creates a new volume.Volume with the provided name, creating // the underlying directory tree required for this volume in the // process. @@ -181,10 +158,7 @@ func (r *Root) Create(name string, opts map[string]string) (volume.Volume, error path := r.DataPath(name) if err := idtools.MkdirAllAndChown(path, 0755, r.rootIDs); err != nil { - if os.IsExist(err) { - return nil, alreadyExistsError{filepath.Dir(path)} - } - return nil, errors.Wrapf(systemError{err}, "error while creating volume path '%s'", path) + return nil, errors.Wrapf(errdefs.System(err), "error while creating volume path '%s'", path) } var err error @@ -210,7 +184,7 @@ func (r *Root) Create(name string, opts map[string]string) (volume.Volume, error return nil, err } if err = ioutil.WriteFile(filepath.Join(filepath.Dir(path), "opts.json"), b, 600); err != nil { - return nil, errors.Wrap(systemError{err}, "error while persisting volume options") + return nil, errdefs.System(errors.Wrap(err, "error while persisting volume options")) } } @@ -228,11 +202,11 @@ func (r *Root) Remove(v volume.Volume) error { lv, ok := v.(*localVolume) if !ok { - return systemError{errors.Errorf("unknown volume type %T", v)} + return errdefs.System(errors.Errorf("unknown volume type %T", v)) } if lv.active.count > 0 { - return systemError{errors.Errorf("volume has active mounts")} + return errdefs.System(errors.Errorf("volume has active mounts")) } if err := lv.unmount(); err != nil { @@ -248,7 +222,7 @@ func (r *Root) Remove(v volume.Volume) error { } if !r.scopedPath(realPath) { - return systemError{errors.Errorf("Unable to remove a directory of out the Docker root %s: %s", r.scope, realPath)} + return errdefs.System(errors.Errorf("Unable to remove a directory of out the Docker root %s: %s", r.scope, realPath)) } if err := removePath(realPath); err != nil { @@ -264,7 +238,7 @@ func removePath(path string) error { if os.IsNotExist(err) { return nil } - return errors.Wrapf(systemError{err}, "error removing volume path '%s'", path) + return errdefs.System(errors.Wrapf(err, "error removing volume path '%s'", path)) } return nil } @@ -347,7 +321,7 @@ func (v *localVolume) Mount(id string) (string, error) { if v.opts != nil { if !v.active.mounted { if err := v.mount(); err != nil { - return "", systemError{err} + return "", errdefs.System(err) } v.active.mounted = true } @@ -381,7 +355,7 @@ func (v *localVolume) unmount() error { if v.opts != nil { if err := mount.Unmount(v.path); err != nil { if mounted, mErr := mount.Mounted(v.path); mounted || mErr != nil { - return errors.Wrapf(systemError{err}, "error while unmounting volume path '%s'", v.path) + return errdefs.System(errors.Wrapf(err, "error while unmounting volume path '%s'", v.path)) } } v.active.mounted = false diff --git a/vendor/github.com/docker/docker/volume/parser.go b/vendor/github.com/docker/docker/volume/parser.go index 1f48b60e2..0b720313c 100644 --- a/vendor/github.com/docker/docker/volume/parser.go +++ b/vendor/github.com/docker/docker/volume/parser.go @@ -1,6 +1,7 @@ package volume import ( + "errors" "runtime" "github.com/docker/docker/api/types/mount" @@ -13,6 +14,10 @@ const ( OSWindows = "windows" ) +// ErrVolumeTargetIsRoot is returned when the target destination is root. +// It's used by both LCOW and Linux parsers. +var ErrVolumeTargetIsRoot = errors.New("invalid specification: destination can't be '/'") + // Parser represents a platform specific parser for mount expressions type Parser interface { ParseMountRaw(raw, volumeDriver string) (*MountPoint, error) @@ -26,8 +31,7 @@ type Parser interface { IsBackwardCompatible(m *MountPoint) bool HasResource(m *MountPoint, absPath string) bool ValidateTmpfsMountDestination(dest string) error - - validateMountConfig(mt *mount.Mount) error + ValidateMountConfig(mt *mount.Mount) error } // NewParser creates a parser for a given container OS, depending on the current host OS (linux on a windows host will resolve to an lcowParser) diff --git a/vendor/github.com/docker/docker/volume/store/store.go b/vendor/github.com/docker/docker/volume/store/store.go index fd1ca616c..9a511a5df 100644 --- a/vendor/github.com/docker/docker/volume/store/store.go +++ b/vendor/github.com/docker/docker/volume/store/store.go @@ -145,8 +145,9 @@ func (s *VolumeStore) Purge(name string) { s.globalLock.Lock() v, exists := s.names[name] if exists { - if _, err := volumedrivers.ReleaseDriver(v.DriverName()); err != nil { - logrus.Errorf("Error dereferencing volume driver: %v", err) + driverName := v.DriverName() + if _, err := volumedrivers.ReleaseDriver(driverName); err != nil { + logrus.WithError(err).WithField("driver", driverName).Error("Error releasing reference to volume driver") } } if err := s.removeMeta(name); err != nil { diff --git a/vendor/github.com/docker/docker/volume/validate_test.go b/vendor/github.com/docker/docker/volume/validate_test.go index 6a8e28682..eac343f50 100644 --- a/vendor/github.com/docker/docker/volume/validate_test.go +++ b/vendor/github.com/docker/docker/volume/validate_test.go @@ -31,13 +31,9 @@ func TestValidateMount(t *testing.T) { {mount.Mount{Type: mount.TypeBind, Source: testDir, Target: testDestinationPath}, nil}, {mount.Mount{Type: "invalid", Target: testDestinationPath}, errors.New("mount type unknown")}, + {mount.Mount{Type: mount.TypeBind, Source: testSourcePath, Target: testDestinationPath}, errBindNotExist}, } - if runtime.GOOS == "windows" { - cases = append(cases, struct { - input mount.Mount - expected error - }{mount.Mount{Type: mount.TypeBind, Source: testSourcePath, Target: testDestinationPath}, errBindNotExist}) // bind source existance is not checked on linux - } + lcowCases := []struct { input mount.Mount expected error @@ -54,7 +50,7 @@ func TestValidateMount(t *testing.T) { } parser := NewParser(runtime.GOOS) for i, x := range cases { - err := parser.validateMountConfig(&x.input) + err := parser.ValidateMountConfig(&x.input) if err == nil && x.expected == nil { continue } @@ -65,7 +61,7 @@ func TestValidateMount(t *testing.T) { if runtime.GOOS == "windows" { parser = &lcowParser{} for i, x := range lcowCases { - err := parser.validateMountConfig(&x.input) + err := parser.ValidateMountConfig(&x.input) if err == nil && x.expected == nil { continue } diff --git a/vendor/github.com/docker/docker/volume/volume.go b/vendor/github.com/docker/docker/volume/volume.go index b8ec1e5a0..207dc560c 100644 --- a/vendor/github.com/docker/docker/volume/volume.go +++ b/vendor/github.com/docker/docker/volume/volume.go @@ -192,7 +192,6 @@ func (m *MountPoint) Setup(mountLabel string, rootIDs idtools.IDPair, checkFun f return "", fmt.Errorf("Unable to setup mount point, neither source nor volume defined") } - // system.MkdirAll() produces an error if m.Source exists and is a file (not a directory), if m.Type == mounttypes.TypeBind { // Before creating the source directory on the host, invoke checkFun if it's not nil. One of // the use case is to forbid creating the daemon socket as a directory if the daemon is in diff --git a/vendor/github.com/docker/docker/volume/windows_parser.go b/vendor/github.com/docker/docker/volume/windows_parser.go index 172610dbd..5cf1a8da7 100644 --- a/vendor/github.com/docker/docker/volume/windows_parser.go +++ b/vendor/github.com/docker/docker/volume/windows_parser.go @@ -189,7 +189,7 @@ func (p *windowsParser) ValidateVolumeName(name string) error { } return nil } -func (p *windowsParser) validateMountConfig(mnt *mount.Mount) error { +func (p *windowsParser) ValidateMountConfig(mnt *mount.Mount) error { return p.validateMountConfigReg(mnt, rxDestination, windowsSpecificValidators) } diff --git a/vendor/github.com/go-openapi/runtime/client/runtime.go b/vendor/github.com/go-openapi/runtime/client/runtime.go index 126f6559d..c5c36e050 100644 --- a/vendor/github.com/go-openapi/runtime/client/runtime.go +++ b/vendor/github.com/go-openapi/runtime/client/runtime.go @@ -15,8 +15,12 @@ package client import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" "crypto/tls" "crypto/x509" + "encoding/pem" "fmt" "io/ioutil" "mime" @@ -37,9 +41,26 @@ import ( // TLSClientOptions to configure client authentication with mutual TLS type TLSClientOptions struct { - Certificate string - Key string - CA string + // Certificate is the path to a PEM-encoded certificate to be used for + // client authentication. If set then Key must also be set. + Certificate string + + // LoadedCertificate is the certificate to be used for client authentication. + // This field is ignored if Certificate is set. If this field is set, LoadedKey + // is also required. + LoadedCertificate *x509.Certificate + + // Key is the path to an unencrypted PEM-encoded private key for client + // authentication. This field is required if Certificate is set. + Key string + + // LoadedKey is the key for client authentication. This field is required if + // LoadedCertificate is set. + LoadedKey crypto.PrivateKey + + // CA is a path to a PEM-encoded certificate. + CA string + ServerName string InsecureSkipVerify bool _ struct{} @@ -57,6 +78,32 @@ func TLSClientAuth(opts TLSClientOptions) (*tls.Config, error) { return nil, fmt.Errorf("tls client cert: %v", err) } cfg.Certificates = []tls.Certificate{cert} + } else if opts.LoadedCertificate != nil { + block := pem.Block{Type: "CERTIFICATE", Bytes: opts.LoadedCertificate.Raw} + certPem := pem.EncodeToMemory(&block) + + var keyBytes []byte + switch k := opts.LoadedKey.(type) { + case *rsa.PrivateKey: + keyBytes = x509.MarshalPKCS1PrivateKey(k) + case *ecdsa.PrivateKey: + var err error + keyBytes, err = x509.MarshalECPrivateKey(k) + if err != nil { + return nil, fmt.Errorf("tls client priv key: %v", err) + } + default: + return nil, fmt.Errorf("tls client priv key: unsupported key type") + } + + block = pem.Block{Type: "PRIVATE KEY", Bytes: keyBytes} + keyPem := pem.EncodeToMemory(&block) + + cert, err := tls.X509KeyPair(certPem, keyPem) + if err != nil { + return nil, fmt.Errorf("tls client cert: %v", err) + } + cfg.Certificates = []tls.Certificate{cert} } cfg.InsecureSkipVerify = opts.InsecureSkipVerify diff --git a/vendor/github.com/go-openapi/runtime/client/runtime_test.go b/vendor/github.com/go-openapi/runtime/client/runtime_test.go index 1d878f22f..5deddb4fa 100644 --- a/vendor/github.com/go-openapi/runtime/client/runtime_test.go +++ b/vendor/github.com/go-openapi/runtime/client/runtime_test.go @@ -30,9 +30,13 @@ import ( "golang.org/x/net/context" + "crypto/x509" + "encoding/pem" + "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // task This describes a task. Tasks require a content property to be set. @@ -65,6 +69,69 @@ func TestRuntime_TLSAuthConfig(t *testing.T) { } } +func TestRuntime_TLSAuthConfigWithRSAKey(t *testing.T) { + + keyPem, err := ioutil.ReadFile("../fixtures/certs/myclient.key") + require.NoError(t, err) + + keyDer, _ := pem.Decode(keyPem) + require.NotNil(t, keyDer) + + key, err := x509.ParsePKCS1PrivateKey(keyDer.Bytes) + require.NoError(t, err) + + certPem, err := ioutil.ReadFile("../fixtures/certs/myclient.crt") + require.NoError(t, err) + + certDer, _ := pem.Decode(certPem) + require.NotNil(t, certDer) + + cert, err := x509.ParseCertificate(certDer.Bytes) + + var opts TLSClientOptions + opts.LoadedKey = key + opts.LoadedCertificate = cert + + cfg, err := TLSClientAuth(opts) + if assert.NoError(t, err) { + if assert.NotNil(t, cfg) { + assert.Len(t, cfg.Certificates, 1) + } + } +} + +func TestRuntime_TLSAuthConfigWithECKey(t *testing.T) { + + keyPem, err := ioutil.ReadFile("../fixtures/certs/myclient-ecc.key") + require.NoError(t, err) + + _, remainder := pem.Decode(keyPem) + keyDer, _ := pem.Decode(remainder) + require.NotNil(t, keyDer) + + key, err := x509.ParseECPrivateKey(keyDer.Bytes) + require.NoError(t, err) + + certPem, err := ioutil.ReadFile("../fixtures/certs/myclient-ecc.crt") + require.NoError(t, err) + + certDer, _ := pem.Decode(certPem) + require.NotNil(t, certDer) + + cert, err := x509.ParseCertificate(certDer.Bytes) + + var opts TLSClientOptions + opts.LoadedKey = key + opts.LoadedCertificate = cert + + cfg, err := TLSClientAuth(opts) + if assert.NoError(t, err) { + if assert.NotNil(t, cfg) { + assert.Len(t, cfg.Certificates, 1) + } + } +} + func TestRuntime_Concurrent(t *testing.T) { // test that it can make a simple request // and get the response for it. diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.crt b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.crt new file mode 100644 index 000000000..3bd5545b7 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC3TCBxgIJAKElkR1J2tCUMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNVBAMMCkdv +IFN3YWdnZXIwHhcNMTgwMTIyMTUyODA3WhcNMTkwMTIyMTUyODA3WjAYMRYwFAYD +VQQDDA1UZXN0IEVDQyBDZXJ0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENlON +9ojzKxcMlsAIFcsc+JoMSOd1bREjEHAPaj77L0NjO6p605jT2TTLbj1lpDGD9XRc +vw5iiHvhF41Sl454wjANBgkqhkiG9w0BAQsFAAOCAgEAyYwVGVG/Jzei9zxmWT+k +LeK7OpGzOIyfBdEvQDFSfmyHoVJsR2LdicMJAI0gnVl5V0LdfBpu1MRz6Jdsto+u +RKL1WdygESzWQ/LtqvT4rb5vLhkpCBY6Ua+SoTpY/93iOZpf1ArKOtHzL4Xop2Lb +6/0hHYU73vaBjd9YnA3T0jVFsI/otpfJhSY8FGdKSYKMf6rob9+iv2Tyjm1svkV0 +IBL0D0v/LlGeM8UqXC3ZLaHsTxWi2v6PNfRyFnSNoRX4+I9ejjYvjIKQ9giVcPFQ +SfhR5xm0C0xxYVqoIb6gX6owlmX2duIaV6qjU5YSzwEZqkv0Ze9i+zztBVqBRA7q +fC/AMSxtqo4+Faj+hxX9T4D15hysx76uS7LxCi8GkypSZTGkjhHdMRKa2jIEvW3A +9nKW4nnC5sEBDrOTwaH4Mn6zFik3r9LTfh1gljLu9Ieqizb1gXloFhWJYvC2UwXO +ins3tX2VYBF7p6yIXRmc5nZlpFErGqu2MR/lwJKD6zGIJOzCza/4DP+Mppw+DSPN +XkNJG05uymsaEZceupeBH0uCgVSuVaZ3nfA73RM+0evxsscii/Kw/VFNvNDy5fLg +OQWRm6RlBTK2dRqpsfo9irjdd6NVC0EfqZceYIte/eWn9aPU5uTy/TzRG24ouKtY +Ixs1usnXCabNN/n0AMI+xVc= +-----END CERTIFICATE----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.csr b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.csr new file mode 100644 index 000000000..3f698e073 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.csr @@ -0,0 +1,7 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHSMHoCAQAwGDEWMBQGA1UEAwwNVGVzdCBFQ0MgQ2VydDBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABDZTjfaI8ysXDJbACBXLHPiaDEjndW0RIxBwD2o++y9DYzuq +etOY09k0y249ZaQxg/V0XL8OYoh74ReNUpeOeMKgADAKBggqhkjOPQQDAgNIADBF +AiEAsqdXJEIuedKkuiavgfc0YXssFWBORAC37F5w+Z0kGEMCIDRGiCaZG4Z/Gutm +id7N5T0Uxah0p5i6OzvCpYPN8f3Y +-----END CERTIFICATE REQUEST----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.key b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.key new file mode 100644 index 000000000..c123550d6 --- /dev/null +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/myclient-ecc.key @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJyZvFqw3os7TVGOSvK8XM1qysN32jG6G0AQ2mDxcRaaoAoGCCqGSM49 +AwEHoUQDQgAENlON9ojzKxcMlsAIFcsc+JoMSOd1bREjEHAPaj77L0NjO6p605jT +2TTLbj1lpDGD9XRcvw5iiHvhF41Sl454wg== +-----END EC PRIVATE KEY----- diff --git a/vendor/github.com/go-openapi/runtime/fixtures/certs/serial b/vendor/github.com/go-openapi/runtime/fixtures/certs/serial index 0de78375e..3e1d186dd 100644 --- a/vendor/github.com/go-openapi/runtime/fixtures/certs/serial +++ b/vendor/github.com/go-openapi/runtime/fixtures/certs/serial @@ -1 +1 @@ -A125911D49DAD093 +A125911D49DAD094 diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go index dfdfc5b30..110ae1384 100644 --- a/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb.go @@ -193,7 +193,8 @@ func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeU // "Generated output always contains 3, 6, or 9 fractional digits, // depending on required precision." s, ns := s.Field(0).Int(), s.Field(1).Int() - x := fmt.Sprintf("%d.%09d", s, ns) + d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond + x := fmt.Sprintf("%.9f", d.Seconds()) x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") out.write(`"`) diff --git a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go index 4fdbde15a..2428d0566 100644 --- a/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go +++ b/vendor/github.com/golang/protobuf/jsonpb/jsonpb_test.go @@ -407,7 +407,6 @@ var marshalingTests = []struct { {"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON}, {"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON}, {"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3.000s"}`}, - {"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`}, {"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{ Fields: map[string]*stpb.Value{ "one": {Kind: &stpb.Value_StringValue{"loneliest number"}}, diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go index fadb88e5e..de6e5c17c 100644 --- a/vendor/github.com/lib/pq/conn.go +++ b/vendor/github.com/lib/pq/conn.go @@ -339,6 +339,15 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { if err != nil { return nil, err } + + // cn.ssl and cn.startup panic on error. Make sure we don't leak cn.c. + panicking := true + defer func() { + if panicking { + cn.c.Close() + } + }() + cn.ssl(o) cn.buf = bufio.NewReader(cn.c) cn.startup(o) @@ -347,6 +356,7 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { if timeout, ok := o["connect_timeout"]; ok && timeout != "0" { err = cn.c.SetDeadline(time.Time{}) } + panicking = false return cn, err } diff --git a/vendor/github.com/lib/pq/conn_test.go b/vendor/github.com/lib/pq/conn_test.go index 030a798c9..7c0f30eb7 100644 --- a/vendor/github.com/lib/pq/conn_test.go +++ b/vendor/github.com/lib/pq/conn_test.go @@ -28,7 +28,7 @@ func forceBinaryParameters() bool { } } -func openTestConnConninfo(conninfo string) (*sql.DB, error) { +func testConninfo(conninfo string) string { defaultTo := func(envvar string, value string) { if os.Getenv(envvar) == "" { os.Setenv(envvar, value) @@ -43,8 +43,11 @@ func openTestConnConninfo(conninfo string) (*sql.DB, error) { !strings.HasPrefix(conninfo, "postgresql://") { conninfo = conninfo + " binary_parameters=yes" } + return conninfo +} - return sql.Open("postgres", conninfo) +func openTestConnConninfo(conninfo string) (*sql.DB, error) { + return sql.Open("postgres", testConninfo(conninfo)) } func openTestConn(t Fatalistic) *sql.DB { @@ -637,6 +640,57 @@ func TestErrorDuringStartup(t *testing.T) { } } +type testConn struct { + closed bool + net.Conn +} + +func (c *testConn) Close() error { + c.closed = true + return c.Conn.Close() +} + +type testDialer struct { + conns []*testConn +} + +func (d *testDialer) Dial(ntw, addr string) (net.Conn, error) { + c, err := net.Dial(ntw, addr) + if err != nil { + return nil, err + } + tc := &testConn{Conn: c} + d.conns = append(d.conns, tc) + return tc, nil +} + +func (d *testDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) { + c, err := net.DialTimeout(ntw, addr, timeout) + if err != nil { + return nil, err + } + tc := &testConn{Conn: c} + d.conns = append(d.conns, tc) + return tc, nil +} + +func TestErrorDuringStartupClosesConn(t *testing.T) { + // Don't use the normal connection setup, this is intended to + // blow up in the startup packet from a non-existent user. + var d testDialer + c, err := DialOpen(&d, testConninfo("user=thisuserreallydoesntexist")) + if err == nil { + c.Close() + t.Fatal("expected dial error") + } + if len(d.conns) != 1 { + t.Fatalf("got len(d.conns) = %d, want = %d", len(d.conns), 1) + } + if !d.conns[0].closed { + t.Error("connection leaked") + } +} + func TestBadConn(t *testing.T) { var err error diff --git a/vendor/github.com/prometheus/procfs/fixtures/net/rpc/nfsd b/vendor/github.com/prometheus/procfs/fixtures/net/rpc/nfsd new file mode 100644 index 000000000..4e8565f41 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/fixtures/net/rpc/nfsd @@ -0,0 +1,11 @@ +rc 0 6 18622 +fh 0 0 0 0 0 +io 157286400 0 +th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 +ra 32 0 0 0 0 0 0 0 0 0 0 0 +net 18628 0 18628 6 +rpc 18628 0 0 0 0 +proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 +proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 +proc4 2 2 10853 +proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go index 17546756b..d0bcb78b1 100644 --- a/vendor/github.com/prometheus/procfs/fs.go +++ b/vendor/github.com/prometheus/procfs/fs.go @@ -5,6 +5,7 @@ import ( "os" "path" + "github.com/prometheus/procfs/nfsd" "github.com/prometheus/procfs/xfs" ) @@ -44,3 +45,14 @@ func (fs FS) XFSStats() (*xfs.Stats, error) { return xfs.ParseStats(f) } + +// NFSdRPCStats retrieves NFS daemon RPC statistics. +func (fs FS) NFSdRPCStats() (*nfsd.RPCStats, error) { + f, err := os.Open(fs.Path("net/rpc/nfsd")) + if err != nil { + return nil, err + } + defer f.Close() + + return nfsd.ParseRPCStats(f) +} diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go new file mode 100644 index 000000000..1ad21c91a --- /dev/null +++ b/vendor/github.com/prometheus/procfs/internal/util/parse.go @@ -0,0 +1,46 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import "strconv" + +// ParseUint32s parses a slice of strings into a slice of uint32s. +func ParseUint32s(ss []string) ([]uint32, error) { + us := make([]uint32, 0, len(ss)) + for _, s := range ss { + u, err := strconv.ParseUint(s, 10, 32) + if err != nil { + return nil, err + } + + us = append(us, uint32(u)) + } + + return us, nil +} + +// ParseUint64s parses a slice of strings into a slice of uint64s. +func ParseUint64s(ss []string) ([]uint64, error) { + us := make([]uint64, 0, len(ss)) + for _, s := range ss { + u, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return nil, err + } + + us = append(us, u) + } + + return us, nil +} diff --git a/vendor/github.com/prometheus/procfs/nfsd/nfsd.go b/vendor/github.com/prometheus/procfs/nfsd/nfsd.go new file mode 100644 index 000000000..7b5ec11cf --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfsd/nfsd.go @@ -0,0 +1,184 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package nfsd implements parsing of /proc/net/rpc/nfsd. +// Fields are documented in https://www.svennd.be/nfsd-stats-explained-procnetrpcnfsd/ +package nfsd + +// ReplyCache models the "rc" line. +type ReplyCache struct { + Hits uint64 + Misses uint64 + NoCache uint64 +} + +// FileHandles models the "fh" line. +type FileHandles struct { + Stale uint64 + TotalLookups uint64 + AnonLookups uint64 + DirNoCache uint64 + NoDirNoCache uint64 +} + +// InputOutput models the "io" line. +type InputOutput struct { + Read uint64 + Write uint64 +} + +// Threads models the "th" line. +type Threads struct { + Threads uint64 + FullCnt uint64 +} + +// ReadAheadCache models the "ra" line. +type ReadAheadCache struct { + CacheSize uint64 + CacheHistogram []uint64 + NotFound uint64 +} + +// Network models the "net" line. +type Network struct { + NetCount uint64 + UDPCount uint64 + TCPCount uint64 + TCPConnect uint64 +} + +// RPC models the "rpc" line. +type RPC struct { + RPCCount uint64 + BadCnt uint64 + BadFmt uint64 + BadAuth uint64 + BadcInt uint64 +} + +// V2Stats models the "proc2" line. +type V2Stats struct { + Null uint64 + GetAttr uint64 + SetAttr uint64 + Root uint64 + Lookup uint64 + ReadLink uint64 + Read uint64 + WrCache uint64 + Write uint64 + Create uint64 + Remove uint64 + Rename uint64 + Link uint64 + SymLink uint64 + MkDir uint64 + RmDir uint64 + ReadDir uint64 + FsStat uint64 +} + +// V3Stats models the "proc3" line. +type V3Stats struct { + Null uint64 + GetAttr uint64 + SetAttr uint64 + Lookup uint64 + Access uint64 + ReadLink uint64 + Read uint64 + Write uint64 + Create uint64 + MkDir uint64 + SymLink uint64 + MkNod uint64 + Remove uint64 + RmDir uint64 + Rename uint64 + Link uint64 + ReadDir uint64 + ReadDirPlus uint64 + FsStat uint64 + FsInfo uint64 + PathConf uint64 + Commit uint64 +} + +// V4Stats models the "proc4" line. +type V4Stats struct { + Null uint64 + Compound uint64 +} + +// V4Ops models the "proc4ops" line: NFSv4 operations +// Variable list, see: +// v4.0 https://tools.ietf.org/html/rfc3010 (38 operations) +// v4.1 https://tools.ietf.org/html/rfc5661 (58 operations) +// v4.2 https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41 (71 operations) +type V4Ops struct { + //Values uint64 // Variable depending on v4.x sub-version. TODO: Will this always at least include the fields in this struct? + Op0Unused uint64 + Op1Unused uint64 + Op2Future uint64 + Access uint64 + Close uint64 + Commit uint64 + Create uint64 + DelegPurge uint64 + DelegReturn uint64 + GetAttr uint64 + GetFH uint64 + Link uint64 + Lock uint64 + Lockt uint64 + Locku uint64 + Lookup uint64 + LookupRoot uint64 + Nverify uint64 + Open uint64 + OpenAttr uint64 + OpenConfirm uint64 + OpenDgrd uint64 + PutFH uint64 + PutPubFH uint64 + PutRootFH uint64 + Read uint64 + ReadDir uint64 + ReadLink uint64 + Remove uint64 + Rename uint64 + Renew uint64 + RestoreFH uint64 + SaveFH uint64 + SecInfo uint64 + SetAttr uint64 + Verify uint64 + Write uint64 + RelLockOwner uint64 +} + +// RPCStats models all stats from /proc/net/rpc/nfsd. +type RPCStats struct { + ReplyCache ReplyCache + FileHandles FileHandles + InputOutput InputOutput + Threads Threads + ReadAheadCache ReadAheadCache + Network Network + RPC RPC + V2Stats V2Stats + V3Stats V3Stats + V4Stats V4Stats + V4Ops V4Ops +} diff --git a/vendor/github.com/prometheus/procfs/nfsd/parse_nfsd.go b/vendor/github.com/prometheus/procfs/nfsd/parse_nfsd.go new file mode 100644 index 000000000..991d7cedb --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfsd/parse_nfsd.go @@ -0,0 +1,298 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nfsd + +import ( + "bufio" + "fmt" + "io" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ParseRPCStats returns stats read from /proc/net/rpc/nfsd +func ParseRPCStats(r io.Reader) (*RPCStats, error) { + stats := &RPCStats{} + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + parts := strings.Fields(scanner.Text()) + // require at least + if len(parts) < 2 { + return nil, fmt.Errorf("invalid NFSd metric line %q", line) + } + label := parts[0] + + var values []uint64 + var err error + if label == "th" { + if len(parts) < 3 { + return nil, fmt.Errorf("invalid NFSd th metric line %q", line) + } + values, err = util.ParseUint64s(parts[1:3]) + } else { + values, err = util.ParseUint64s(parts[1:]) + } + if err != nil { + return nil, fmt.Errorf("error parsing NFSd metric line: %s", err) + } + + switch metricLine := parts[0]; metricLine { + case "rc": + stats.ReplyCache, err = parseReplyCache(values) + case "fh": + stats.FileHandles, err = parseFileHandles(values) + case "io": + stats.InputOutput, err = parseInputOutput(values) + case "th": + stats.Threads, err = parseThreads(values) + case "ra": + stats.ReadAheadCache, err = parseReadAheadCache(values) + case "net": + stats.Network, err = parseNetwork(values) + case "rpc": + stats.RPC, err = parseRPC(values) + case "proc2": + stats.V2Stats, err = parseV2Stats(values) + case "proc3": + stats.V3Stats, err = parseV3Stats(values) + case "proc4": + stats.V4Stats, err = parseV4Stats(values) + case "proc4ops": + stats.V4Ops, err = parseV4Ops(values) + default: + return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine) + } + if err != nil { + return nil, fmt.Errorf("errors parsing NFSd metric line: %s", err) + } + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error scanning NFSd file: %s", err) + } + + return stats, nil +} + +func parseReplyCache(v []uint64) (ReplyCache, error) { + if len(v) != 3 { + return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v) + } + + return ReplyCache{ + Hits: v[0], + Misses: v[1], + NoCache: v[2], + }, nil +} + +func parseFileHandles(v []uint64) (FileHandles, error) { + if len(v) != 5 { + return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v) + } + + return FileHandles{ + Stale: v[0], + TotalLookups: v[1], + AnonLookups: v[2], + DirNoCache: v[3], + NoDirNoCache: v[4], + }, nil +} + +func parseInputOutput(v []uint64) (InputOutput, error) { + if len(v) != 2 { + return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v) + } + + return InputOutput{ + Read: v[0], + Write: v[1], + }, nil +} + +func parseThreads(v []uint64) (Threads, error) { + if len(v) != 2 { + return Threads{}, fmt.Errorf("invalid Threads line %q", v) + } + + return Threads{ + Threads: v[0], + FullCnt: v[1], + }, nil +} + +func parseReadAheadCache(v []uint64) (ReadAheadCache, error) { + if len(v) != 12 { + return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v) + } + + return ReadAheadCache{ + CacheSize: v[0], + CacheHistogram: v[1:11], + NotFound: v[11], + }, nil +} + +func parseNetwork(v []uint64) (Network, error) { + if len(v) != 4 { + return Network{}, fmt.Errorf("invalid Network line %q", v) + } + + return Network{ + NetCount: v[0], + UDPCount: v[1], + TCPCount: v[2], + TCPConnect: v[3], + }, nil +} + +func parseRPC(v []uint64) (RPC, error) { + if len(v) != 5 { + return RPC{}, fmt.Errorf("invalid RPC line %q", v) + } + + return RPC{ + RPCCount: v[0], + BadCnt: v[1], + BadFmt: v[2], + BadAuth: v[3], + BadcInt: v[4], + }, nil +} + +func parseV2Stats(v []uint64) (V2Stats, error) { + values := int(v[0]) + if len(v[1:]) != values || values != 18 { + return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v) + } + + return V2Stats{ + Null: v[1], + GetAttr: v[2], + SetAttr: v[3], + Root: v[4], + Lookup: v[5], + ReadLink: v[6], + Read: v[7], + WrCache: v[8], + Write: v[9], + Create: v[10], + Remove: v[11], + Rename: v[12], + Link: v[13], + SymLink: v[14], + MkDir: v[15], + RmDir: v[16], + ReadDir: v[17], + FsStat: v[18], + }, nil +} + +func parseV3Stats(v []uint64) (V3Stats, error) { + values := int(v[0]) + if len(v[1:]) != values || values != 22 { + return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v) + } + + return V3Stats{ + Null: v[1], + GetAttr: v[2], + SetAttr: v[3], + Lookup: v[4], + Access: v[5], + ReadLink: v[6], + Read: v[7], + Write: v[8], + Create: v[9], + MkDir: v[10], + SymLink: v[11], + MkNod: v[12], + Remove: v[13], + RmDir: v[14], + Rename: v[15], + Link: v[16], + ReadDir: v[17], + ReadDirPlus: v[18], + FsStat: v[19], + FsInfo: v[20], + PathConf: v[21], + Commit: v[22], + }, nil +} + +func parseV4Stats(v []uint64) (V4Stats, error) { + values := int(v[0]) + if len(v[1:]) != values || values != 2 { + return V4Stats{}, fmt.Errorf("invalid V4Stats line %q", v) + } + + return V4Stats{ + Null: v[1], + Compound: v[2], + }, nil +} + +func parseV4Ops(v []uint64) (V4Ops, error) { + values := int(v[0]) + if len(v[1:]) != values || values < 39 { + return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v) + } + + stats := V4Ops{ + Op0Unused: v[1], + Op1Unused: v[2], + Op2Future: v[3], + Access: v[4], + Close: v[5], + Commit: v[6], + Create: v[7], + DelegPurge: v[8], + DelegReturn: v[9], + GetAttr: v[10], + GetFH: v[11], + Link: v[12], + Lock: v[13], + Lockt: v[14], + Locku: v[15], + Lookup: v[16], + LookupRoot: v[17], + Nverify: v[18], + Open: v[19], + OpenAttr: v[20], + OpenConfirm: v[21], + OpenDgrd: v[22], + PutFH: v[23], + PutPubFH: v[24], + PutRootFH: v[25], + Read: v[26], + ReadDir: v[27], + ReadLink: v[28], + Remove: v[29], + Rename: v[30], + Renew: v[31], + RestoreFH: v[32], + SaveFH: v[33], + SecInfo: v[34], + SetAttr: v[35], + Verify: v[36], + Write: v[37], + RelLockOwner: v[38], + } + + return stats, nil +} diff --git a/vendor/github.com/prometheus/procfs/nfsd/parse_test.go b/vendor/github.com/prometheus/procfs/nfsd/parse_test.go new file mode 100644 index 000000000..0fe25cdd6 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfsd/parse_test.go @@ -0,0 +1,196 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package nfsd_test + +import ( + "reflect" + "strings" + "testing" + + "github.com/prometheus/procfs/nfsd" +) + +func TestNewNFSdRPCStats(t *testing.T) { + tests := []struct { + name string + content string + stats *nfsd.RPCStats + invalid bool + }{ + { + name: "invalid file", + content: "invalid", + invalid: true, + }, { + name: "good file", + content: `rc 0 6 18622 +fh 0 0 0 0 0 +io 157286400 0 +th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 +ra 32 0 0 0 0 0 0 0 0 0 0 0 +net 18628 0 18628 6 +rpc 18628 0 0 0 0 +proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 +proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 +proc4 2 2 10853 +proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +`, + stats: &nfsd.RPCStats{ + ReplyCache: nfsd.ReplyCache{ + Hits: 0, + Misses: 6, + NoCache: 18622, + }, + FileHandles: nfsd.FileHandles{ + Stale: 0, + TotalLookups: 0, + AnonLookups: 0, + DirNoCache: 0, + NoDirNoCache: 0, + }, + InputOutput: nfsd.InputOutput{ + Read: 157286400, + Write: 0, + }, + Threads: nfsd.Threads{ + Threads: 8, + FullCnt: 0, + }, + ReadAheadCache: nfsd.ReadAheadCache{ + CacheSize: 32, + CacheHistogram: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + NotFound: 0, + }, + Network: nfsd.Network{ + NetCount: 18628, + UDPCount: 0, + TCPCount: 18628, + TCPConnect: 6, + }, + RPC: nfsd.RPC{ + RPCCount: 18628, + BadCnt: 0, + BadFmt: 0, + BadAuth: 0, + BadcInt: 0, + }, + V2Stats: nfsd.V2Stats{ + Null: 2, + GetAttr: 69, + SetAttr: 0, + Root: 0, + Lookup: 4410, + ReadLink: 0, + Read: 0, + WrCache: 0, + Write: 0, + Create: 0, + Remove: 0, + Rename: 0, + Link: 0, + SymLink: 0, + MkDir: 0, + RmDir: 0, + ReadDir: 99, + FsStat: 2, + }, + V3Stats: nfsd.V3Stats{ + Null: 2, + GetAttr: 112, + SetAttr: 0, + Lookup: 2719, + Access: 111, + ReadLink: 0, + Read: 0, + Write: 0, + Create: 0, + MkDir: 0, + SymLink: 0, + MkNod: 0, + Remove: 0, + RmDir: 0, + Rename: 0, + Link: 0, + ReadDir: 27, + ReadDirPlus: 216, + FsStat: 0, + FsInfo: 2, + PathConf: 1, + Commit: 0, + }, + V4Stats: nfsd.V4Stats{ + Null: 2, + Compound: 10853, + }, + V4Ops: nfsd.V4Ops{ + Op0Unused: 0, + Op1Unused: 0, + Op2Future: 0, + Access: 1098, + Close: 2, + Commit: 0, + Create: 0, + DelegPurge: 0, + DelegReturn: 0, + GetAttr: 8179, + GetFH: 5896, + Link: 0, + Lock: 0, + Lockt: 0, + Locku: 0, + Lookup: 5900, + LookupRoot: 0, + Nverify: 0, + Open: 2, + OpenAttr: 0, + OpenConfirm: 2, + OpenDgrd: 0, + PutFH: 9609, + PutPubFH: 0, + PutRootFH: 2, + Read: 150, + ReadDir: 1272, + ReadLink: 0, + Remove: 0, + Rename: 0, + Renew: 1236, + RestoreFH: 0, + SaveFH: 0, + SecInfo: 0, + SetAttr: 0, + Verify: 3, + Write: 3, + RelLockOwner: 0, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + stats, err := nfsd.ParseRPCStats(strings.NewReader(tt.content)) + + if tt.invalid && err == nil { + t.Fatal("expected an error, but none occurred") + } + if !tt.invalid && err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if want, have := tt.stats, stats; !reflect.DeepEqual(want, have) { + t.Fatalf("unexpected NFS stats:\nwant:\n%v\nhave:\n%v", want, have) + } + }) + } +} diff --git a/vendor/github.com/prometheus/procfs/xfs/parse.go b/vendor/github.com/prometheus/procfs/xfs/parse.go index c8f6279f3..2bc0ef342 100644 --- a/vendor/github.com/prometheus/procfs/xfs/parse.go +++ b/vendor/github.com/prometheus/procfs/xfs/parse.go @@ -17,8 +17,9 @@ import ( "bufio" "fmt" "io" - "strconv" "strings" + + "github.com/prometheus/procfs/internal/util" ) // ParseStats parses a Stats from an input io.Reader, using the format @@ -68,7 +69,7 @@ func ParseStats(r io.Reader) (*Stats, error) { // Extended precision counters are uint64 values. if label == fieldXpc { - us, err := parseUint64s(ss[1:]) + us, err := util.ParseUint64s(ss[1:]) if err != nil { return nil, err } @@ -82,7 +83,7 @@ func ParseStats(r io.Reader) (*Stats, error) { } // All other counters are uint32 values. - us, err := parseUint32s(ss[1:]) + us, err := util.ParseUint32s(ss[1:]) if err != nil { return nil, err } @@ -327,33 +328,3 @@ func extendedPrecisionStats(us []uint64) (ExtendedPrecisionStats, error) { ReadBytes: us[2], }, nil } - -// parseUint32s parses a slice of strings into a slice of uint32s. -func parseUint32s(ss []string) ([]uint32, error) { - us := make([]uint32, 0, len(ss)) - for _, s := range ss { - u, err := strconv.ParseUint(s, 10, 32) - if err != nil { - return nil, err - } - - us = append(us, uint32(u)) - } - - return us, nil -} - -// parseUint64s parses a slice of strings into a slice of uint64s. -func parseUint64s(ss []string) ([]uint64, error) { - us := make([]uint64, 0, len(ss)) - for _, s := range ss { - u, err := strconv.ParseUint(s, 10, 64) - if err != nil { - return nil, err - } - - us = append(us, u) - } - - return us, nil -} diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go index 99441395b..30a49fdf2 100644 --- a/vendor/golang.org/x/crypto/ssh/cipher.go +++ b/vendor/golang.org/x/crypto/ssh/cipher.go @@ -56,78 +56,78 @@ func newRC4(key, iv []byte) (cipher.Stream, error) { return rc4.NewCipher(key) } -type streamCipherMode struct { - keySize int - ivSize int - skip int - createFunc func(key, iv []byte) (cipher.Stream, error) +type cipherMode struct { + keySize int + ivSize int + create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) } -func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) { - if len(key) < c.keySize { - panic("ssh: key length too small for cipher") - } - if len(iv) < c.ivSize { - panic("ssh: iv too small for cipher") - } - - stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize]) - if err != nil { - return nil, err - } - - var streamDump []byte - if c.skip > 0 { - streamDump = make([]byte, 512) - } - - for remainingToDump := c.skip; remainingToDump > 0; { - dumpThisTime := remainingToDump - if dumpThisTime > len(streamDump) { - dumpThisTime = len(streamDump) +func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { + stream, err := createFunc(key, iv) + if err != nil { + return nil, err } - stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) - remainingToDump -= dumpThisTime - } - return stream, nil + var streamDump []byte + if skip > 0 { + streamDump = make([]byte, 512) + } + + for remainingToDump := skip; remainingToDump > 0; { + dumpThisTime := remainingToDump + if dumpThisTime > len(streamDump) { + dumpThisTime = len(streamDump) + } + stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) + remainingToDump -= dumpThisTime + } + + mac := macModes[algs.MAC].new(macKey) + return &streamPacketCipher{ + mac: mac, + etm: macModes[algs.MAC].etm, + macResult: make([]byte, mac.Size()), + cipher: stream, + }, nil + } } // cipherModes documents properties of supported ciphers. Ciphers not included // are not supported and will not be negotiated, even if explicitly requested in // ClientConfig.Crypto.Ciphers. -var cipherModes = map[string]*streamCipherMode{ +var cipherModes = map[string]*cipherMode{ // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms // are defined in the order specified in the RFC. - "aes128-ctr": {16, aes.BlockSize, 0, newAESCTR}, - "aes192-ctr": {24, aes.BlockSize, 0, newAESCTR}, - "aes256-ctr": {32, aes.BlockSize, 0, newAESCTR}, + "aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, + "aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)}, // Ciphers from RFC4345, which introduces security-improved arcfour ciphers. // They are defined in the order specified in the RFC. - "arcfour128": {16, 0, 1536, newRC4}, - "arcfour256": {32, 0, 1536, newRC4}, + "arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, + "arcfour256": {32, 0, streamCipherMode(1536, newRC4)}, // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol. // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and // RC4) has problems with weak keys, and should be used with caution." // RFC4345 introduces improved versions of Arcfour. - "arcfour": {16, 0, 0, newRC4}, + "arcfour": {16, 0, streamCipherMode(0, newRC4)}, - // AEAD ciphers are special cased. If we add any more non-stream - // ciphers, we should create a cleaner way to do this. - gcmCipherID: {16, 12, 0, nil}, - chacha20Poly1305ID: {64, 0, 0, nil}, + // AEAD ciphers + gcmCipherID: {16, 12, newGCMCipher}, + chacha20Poly1305ID: {64, 0, newChaCha20Cipher}, // CBC mode is insecure and so is not included in the default config. // (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely // needed, it's possible to specify a custom Config to enable it. // You should expect that an active attacker can recover plaintext if // you do. - aes128cbcID: {16, aes.BlockSize, 0, nil}, + aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, - // 3des-cbc is insecure and is disabled by default. - tripledescbcID: {24, des.BlockSize, 0, nil}, + // 3des-cbc is insecure and is not included in the default + // config. + tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher}, } // prefixLen is the length of the packet prefix that contains the packet length @@ -307,7 +307,7 @@ type gcmCipher struct { buf []byte } -func newGCMCipher(iv, key []byte) (packetCipher, error) { +func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err @@ -425,7 +425,7 @@ type cbcCipher struct { oracleCamouflage uint32 } -func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { cbc := &cbcCipher{ mac: macModes[algs.MAC].new(macKey), decrypter: cipher.NewCBCDecrypter(c, iv), @@ -439,13 +439,13 @@ func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorith return cbc, nil } -func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err } - cbc, err := newCBCCipher(c, iv, key, macKey, algs) + cbc, err := newCBCCipher(c, key, iv, macKey, algs) if err != nil { return nil, err } @@ -453,13 +453,13 @@ func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCi return cbc, nil } -func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { c, err := des.NewTripleDESCipher(key) if err != nil { return nil, err } - cbc, err := newCBCCipher(c, iv, key, macKey, algs) + cbc, err := newCBCCipher(c, key, iv, macKey, algs) if err != nil { return nil, err } @@ -646,9 +646,9 @@ type chacha20Poly1305Cipher struct { buf []byte } -func newChaCha20Cipher(key []byte) (packetCipher, error) { +func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { if len(key) != 64 { - panic("key length") + panic(len(key)) } c := &chacha20Poly1305Cipher{ @@ -671,7 +671,7 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, chacha20.XORKeyStream(polyKey[:], chacha20PolyKeyInput[:], &counter, &c.contentKey) encryptedLength := c.buf[:4] - if _, err := r.Read(encryptedLength); err != nil { + if _, err := io.ReadFull(r, encryptedLength); err != nil { return nil, err } @@ -692,13 +692,12 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, c.buf = c.buf[:packetEnd] } - if _, err := r.Read(c.buf[4:packetEnd]); err != nil { + if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil { return nil, err } var mac [poly1305.TagSize]byte copy(mac[:], c.buf[contentEnd:packetEnd]) - if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) { return nil, errors.New("ssh: MAC failure") } @@ -720,6 +719,7 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, } plain = plain[1 : len(plain)-int(padding)] + return plain, nil } diff --git a/vendor/golang.org/x/crypto/ssh/cipher_test.go b/vendor/golang.org/x/crypto/ssh/cipher_test.go index 6a35d8708..a52d6e486 100644 --- a/vendor/golang.org/x/crypto/ssh/cipher_test.go +++ b/vendor/golang.org/x/crypto/ssh/cipher_test.go @@ -7,7 +7,6 @@ package ssh import ( "bytes" "crypto" - "crypto/aes" "crypto/rand" "testing" ) @@ -15,7 +14,12 @@ import ( func TestDefaultCiphersExist(t *testing.T) { for _, cipherAlgo := range supportedCiphers { if _, ok := cipherModes[cipherAlgo]; !ok { - t.Errorf("default cipher %q is unknown", cipherAlgo) + t.Errorf("supported cipher %q is unknown", cipherAlgo) + } + } + for _, cipherAlgo := range preferredCiphers { + if _, ok := cipherModes[cipherAlgo]; !ok { + t.Errorf("preferred cipher %q is unknown", cipherAlgo) } } } @@ -67,9 +71,6 @@ func testPacketCipher(t *testing.T, cipher, mac string) { } func TestCBCOracleCounterMeasure(t *testing.T) { - cipherModes[aes128cbcID] = &streamCipherMode{16, aes.BlockSize, 0, nil} - defer delete(cipherModes, aes128cbcID) - kr := &kexResult{Hash: crypto.SHA1} algs := directionAlgorithms{ Cipher: aes128cbcID, diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go index 77f9c5bbe..04f3620b3 100644 --- a/vendor/golang.org/x/crypto/ssh/common.go +++ b/vendor/golang.org/x/crypto/ssh/common.go @@ -24,12 +24,21 @@ const ( serviceSSH = "ssh-connection" ) -// supportedCiphers specifies the supported ciphers in preference order. +// supportedCiphers lists ciphers we support but might not recommend. var supportedCiphers = []string{ "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", chacha20Poly1305ID, - "arcfour256", "arcfour128", + "arcfour256", "arcfour128", "arcfour", + aes128cbcID, + tripledescbcID, +} + +// preferredCiphers specifies the default preference for ciphers. +var preferredCiphers = []string{ + "aes128-gcm@openssh.com", + chacha20Poly1305ID, + "aes128-ctr", "aes192-ctr", "aes256-ctr", } // supportedKexAlgos specifies the supported key-exchange algorithms in @@ -212,7 +221,7 @@ func (c *Config) SetDefaults() { c.Rand = rand.Reader } if c.Ciphers == nil { - c.Ciphers = supportedCiphers + c.Ciphers = preferredCiphers } var ciphers []string for _, c := range c.Ciphers { diff --git a/vendor/golang.org/x/crypto/ssh/test/session_test.go b/vendor/golang.org/x/crypto/ssh/test/session_test.go index 9e702effa..4eb7afde8 100644 --- a/vendor/golang.org/x/crypto/ssh/test/session_test.go +++ b/vendor/golang.org/x/crypto/ssh/test/session_test.go @@ -11,6 +11,7 @@ package test import ( "bytes" "errors" + "fmt" "io" "strings" "testing" @@ -324,31 +325,59 @@ func TestWindowChange(t *testing.T) { } } +func testOneCipher(t *testing.T, cipher string, cipherOrder []string) { + server := newServer(t) + defer server.Shutdown() + conf := clientConfig() + conf.Ciphers = []string{cipher} + // Don't fail if sshd doesn't have the cipher. + conf.Ciphers = append(conf.Ciphers, cipherOrder...) + conn, err := server.TryDial(conf) + if err != nil { + t.Fatalf("TryDial: %v", err) + } + defer conn.Close() + + numBytes := 4096 + + // Exercise sending data to the server + if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil { + t.Fatalf("SendRequest: %v", err) + } + + // Exercise receiving data from the server + session, err := conn.NewSession() + if err != nil { + t.Fatalf("NewSession: %v", err) + } + + out, err := session.Output(fmt.Sprintf("dd if=/dev/zero of=/dev/stdout bs=%d count=1", numBytes)) + if err != nil { + t.Fatalf("Output: %v", err) + } + + if len(out) != numBytes { + t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes) + } +} + +var deprecatedCiphers = []string{ + "aes128-cbc", "3des-cbc", + "arcfour128", "arcfour256", +} + func TestCiphers(t *testing.T) { var config ssh.Config config.SetDefaults() - cipherOrder := config.Ciphers - // These ciphers will not be tested when commented out in cipher.go it will - // fallback to the next available as per line 292. - cipherOrder = append(cipherOrder, "aes128-cbc", "3des-cbc") + cipherOrder := append(config.Ciphers, deprecatedCiphers...) for _, ciph := range cipherOrder { t.Run(ciph, func(t *testing.T) { - server := newServer(t) - defer server.Shutdown() - conf := clientConfig() - conf.Ciphers = []string{ciph} - // Don't fail if sshd doesn't have the cipher. - conf.Ciphers = append(conf.Ciphers, cipherOrder...) - conn, err := server.TryDial(conf) - if err == nil { - conn.Close() - } else { - t.Fatalf("failed for cipher %q", ciph) - } + testOneCipher(t, ciph, cipherOrder) }) } } + func TestMACs(t *testing.T) { var config ssh.Config config.SetDefaults() diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go index 5a567539c..f6fae1db4 100644 --- a/vendor/golang.org/x/crypto/ssh/transport.go +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -233,51 +233,22 @@ var ( clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}} ) -// generateKeys generates key material for IV, MAC and encryption. -func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { - cipherMode := cipherModes[algs.Cipher] - macMode := macModes[algs.MAC] - - iv = make([]byte, cipherMode.ivSize) - key = make([]byte, cipherMode.keySize) - macKey = make([]byte, macMode.keySize) - - generateKeyMaterial(iv, d.ivTag, kex) - generateKeyMaterial(key, d.keyTag, kex) - generateKeyMaterial(macKey, d.macKeyTag, kex) - return -} - // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as // described in RFC 4253, section 6.4. direction should either be serverKeys // (to setup server->client keys) or clientKeys (for client->server keys). func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { - iv, key, macKey := generateKeys(d, algs, kex) + cipherMode := cipherModes[algs.Cipher] + macMode := macModes[algs.MAC] - switch algs.Cipher { - case chacha20Poly1305ID: - return newChaCha20Cipher(key) - case gcmCipherID: - return newGCMCipher(iv, key) - case aes128cbcID: - return newAESCBCCipher(iv, key, macKey, algs) - case tripledescbcID: - return newTripleDESCBCCipher(iv, key, macKey, algs) - } + iv := make([]byte, cipherMode.ivSize) + key := make([]byte, cipherMode.keySize) + macKey := make([]byte, macMode.keySize) - c := &streamPacketCipher{ - mac: macModes[algs.MAC].new(macKey), - etm: macModes[algs.MAC].etm, - } - c.macResult = make([]byte, c.mac.Size()) + generateKeyMaterial(iv, d.ivTag, kex) + generateKeyMaterial(key, d.keyTag, kex) + generateKeyMaterial(macKey, d.macKeyTag, kex) - var err error - c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv) - if err != nil { - return nil, err - } - - return c, nil + return cipherModes[algs.Cipher].create(key, iv, macKey, algs) } // generateKeyMaterial fills out with key material generated from tag, K, H diff --git a/vendor/golang.org/x/sys/unix/dirent.go b/vendor/golang.org/x/sys/unix/dirent.go index bd475812b..95fd35317 100644 --- a/vendor/golang.org/x/sys/unix/dirent.go +++ b/vendor/golang.org/x/sys/unix/dirent.go @@ -6,97 +6,12 @@ package unix -import "unsafe" - -// readInt returns the size-bytes unsigned integer in native byte order at offset off. -func readInt(b []byte, off, size uintptr) (u uint64, ok bool) { - if len(b) < int(off+size) { - return 0, false - } - if isBigEndian { - return readIntBE(b[off:], size), true - } - return readIntLE(b[off:], size), true -} - -func readIntBE(b []byte, size uintptr) uint64 { - switch size { - case 1: - return uint64(b[0]) - case 2: - _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[1]) | uint64(b[0])<<8 - case 4: - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24 - case 8: - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | - uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 - default: - panic("syscall: readInt with unsupported size") - } -} - -func readIntLE(b []byte, size uintptr) uint64 { - switch size { - case 1: - return uint64(b[0]) - case 2: - _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[0]) | uint64(b[1])<<8 - case 4: - _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 - case 8: - _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 - return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | - uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 - default: - panic("syscall: readInt with unsupported size") - } -} +import "syscall" // ParseDirent parses up to max directory entries in buf, // appending the names to names. It returns the number of // bytes consumed from buf, the number of entries added // to names, and the new names slice. func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { - origlen := len(buf) - count = 0 - for max != 0 && len(buf) > 0 { - reclen, ok := direntReclen(buf) - if !ok || reclen > uint64(len(buf)) { - return origlen, count, names - } - rec := buf[:reclen] - buf = buf[reclen:] - ino, ok := direntIno(rec) - if !ok { - break - } - if ino == 0 { // File absent in directory. - continue - } - const namoff = uint64(unsafe.Offsetof(Dirent{}.Name)) - namlen, ok := direntNamlen(rec) - if !ok || namoff+namlen > uint64(len(rec)) { - break - } - name := rec[namoff : namoff+namlen] - for i, c := range name { - if c == 0 { - name = name[:i] - break - } - } - // Check for useless names before allocating a string. - if string(name) == "." || string(name) == ".." { - continue - } - max-- - count++ - names = append(names, string(name)) - } - return origlen - len(buf), count, names + return syscall.ParseDirent(buf, max, names) } diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index d6c472a75..1eea35675 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -76,18 +76,6 @@ func nametomib(name string) (mib []_C_int, err error) { return buf[0 : n/siz], nil } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) -} - -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) -} - -func direntNamlen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) -} - //sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 6dfc89a7e..17256ec9f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -56,22 +56,6 @@ func nametomib(name string) (mib []_C_int, err error) { return buf[0 : n/siz], nil } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno)) -} - -func direntReclen(buf []byte) (uint64, bool) { - namlen, ok := direntNamlen(buf) - if !ok { - return 0, false - } - return (16 + namlen + 1 + 7) &^ 7, true -} - -func direntNamlen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) -} - //sysnb pipe() (r int, w int, err error) func Pipe(p []int) (err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index b8ecf6c78..444627579 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -54,18 +54,6 @@ func nametomib(name string) (mib []_C_int, err error) { return buf[0 : n/siz], nil } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno)) -} - -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) -} - -func direntNamlen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) -} - //sysnb pipe() (r int, w int, err error) func Pipe(p []int) (err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 71c58e11f..839f1d5c1 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -1197,22 +1197,6 @@ func ReadDirent(fd int, buf []byte) (n int, err error) { return Getdents(fd, buf) } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) -} - -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) -} - -func direntNamlen(buf []byte) (uint64, bool) { - reclen, ok := direntReclen(buf) - if !ok { - return 0, false - } - return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true -} - //sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go index d81106d10..060e5e610 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -92,18 +92,6 @@ func nametomib(name string) (mib []_C_int, err error) { return mib, nil } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno)) -} - -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) -} - -func direntNamlen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) -} - //sysnb pipe() (fd1 int, fd2 int, err error) func Pipe(p []int) (err error) { if len(p) != 2 { diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 553c2fb85..407d119ec 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -42,18 +42,6 @@ func nametomib(name string) (mib []_C_int, err error) { return nil, EINVAL } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno)) -} - -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) -} - -func direntNamlen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen)) -} - //sysnb pipe(p *[2]_C_int) (err error) func Pipe(p []int) (err error) { if len(p) != 2 { diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index 9dc01e742..a87aebfe6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -34,22 +34,6 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) -} - -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) -} - -func direntNamlen(buf []byte) (uint64, bool) { - reclen, ok := direntReclen(buf) - if !ok { - return 0, false - } - return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true -} - //sysnb pipe(p *[2]_C_int) (n int, err error) func Pipe(p []int) (err error) {