Commit 5c113cf4 authored by Alok Kumar Singh's avatar Alok Kumar Singh

Docker dependency updated to 18.09.4 i.e be7ac8be2ae072032a4005e8f232be3fc57e4127

parent a93f803f
...@@ -5058,7 +5058,7 @@ Apache License ...@@ -5058,7 +5058,7 @@ Apache License
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Copyright 2013-2017 Docker, Inc. Copyright 2013-2018 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
...@@ -5072,7 +5072,7 @@ Apache License ...@@ -5072,7 +5072,7 @@ Apache License
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
= vendor/github.com/docker/docker/LICENSE 9740d093a080530b5c5c6573df9af45a = vendor/github.com/docker/docker/LICENSE 4859e97a9c7780e77972d989f0823f28
================================================================================ ================================================================================
...@@ -14840,6 +14840,35 @@ SOFTWARE. ...@@ -14840,6 +14840,35 @@ SOFTWARE.
================================================================================ ================================================================================
= vendor/github.com/morikuni/aec licensed under: =
The MIT License (MIT)
Copyright (c) 2016 Taihei Morikuni
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/morikuni/aec/LICENSE 86852eb2df591157c788f3ba889c8aec
================================================================================
================================================================================
= vendor/github.com/mrunalp/fileutils licensed under: = = vendor/github.com/mrunalp/fileutils licensed under: =
...@@ -15186,40 +15215,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -15186,40 +15215,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================ ================================================================================
= vendor/github.com/Nvveen/Gotty licensed under: =
Copyright (c) 2012, Neal van Veen (nealvanveen@gmail.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
= vendor/github.com/Nvveen/Gotty/LICENSE ab11220c6af5f3758ccae7bf525f8dec
================================================================================
================================================================================
= vendor/github.com/NYTimes/gziphandler licensed under: = = vendor/github.com/NYTimes/gziphandler licensed under: =
Copyright (c) 2015 The New York Times Company Copyright (c) 2015 The New York Times Company
...@@ -17,7 +17,6 @@ require ( ...@@ -17,7 +17,6 @@ require (
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd
github.com/Microsoft/go-winio v0.4.11 github.com/Microsoft/go-winio v0.4.11
github.com/Microsoft/hcsshim v0.0.0-20190110205307-69ac8d3f7fc1 github.com/Microsoft/hcsshim v0.0.0-20190110205307-69ac8d3f7fc1
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/PuerkitoBio/purell v1.1.0 github.com/PuerkitoBio/purell v1.1.0
github.com/Rican7/retry v0.0.0-20160712041035-272ad122d6e5 // indirect github.com/Rican7/retry v0.0.0-20160712041035-272ad122d6e5 // indirect
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e
...@@ -53,7 +52,7 @@ require ( ...@@ -53,7 +52,7 @@ require (
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd
github.com/dnaeon/go-vcr v1.0.1 // indirect github.com/dnaeon/go-vcr v1.0.1 // indirect
github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/go-connections v0.3.0 github.com/docker/go-connections v0.3.0
github.com/docker/go-units v0.3.3 github.com/docker/go-units v0.3.3
github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789 github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789
...@@ -120,6 +119,7 @@ require ( ...@@ -120,6 +119,7 @@ require (
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7
github.com/mitchellh/mapstructure v1.1.2 github.com/mitchellh/mapstructure v1.1.2
github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb // indirect github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb // indirect
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 // indirect github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 // indirect
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d
github.com/mvdan/xurls v0.0.0-20160110113200-1b768d7c393a github.com/mvdan/xurls v0.0.0-20160110113200-1b768d7c393a
...@@ -267,7 +267,7 @@ replace ( ...@@ -267,7 +267,7 @@ replace (
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda
github.com/dnaeon/go-vcr => github.com/dnaeon/go-vcr v1.0.1 github.com/dnaeon/go-vcr => github.com/dnaeon/go-vcr v1.0.1
github.com/docker/distribution => github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff github.com/docker/distribution => github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff
github.com/docker/docker => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/go-connections => github.com/docker/go-connections v0.3.0 github.com/docker/go-connections => github.com/docker/go-connections v0.3.0
github.com/docker/go-units => github.com/docker/go-units v0.3.3 github.com/docker/go-units => github.com/docker/go-units v0.3.3
github.com/docker/libnetwork => github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789 github.com/docker/libnetwork => github.com/docker/libnetwork v0.0.0-20180830151422-a9cd636e3789
...@@ -369,6 +369,7 @@ replace ( ...@@ -369,6 +369,7 @@ replace (
github.com/modern-go/concurrent => github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd github.com/modern-go/concurrent => github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/modern-go/reflect2 => github.com/modern-go/reflect2 v1.0.1 github.com/modern-go/reflect2 => github.com/modern-go/reflect2 v1.0.1
github.com/mohae/deepcopy => github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb github.com/mohae/deepcopy => github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb
github.com/morikuni/aec => github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c
github.com/mrunalp/fileutils => github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 github.com/mrunalp/fileutils => github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058
github.com/munnerz/goautoneg => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d github.com/munnerz/goautoneg => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d
github.com/mvdan/xurls => github.com/mvdan/xurls v0.0.0-20160110113200-1b768d7c393a github.com/mvdan/xurls => github.com/mvdan/xurls v0.0.0-20160110113200-1b768d7c393a
......
...@@ -25,8 +25,6 @@ github.com/Microsoft/hcsshim v0.0.0-20190110205307-69ac8d3f7fc1 h1:QOfYwlBe/tzoR ...@@ -25,8 +25,6 @@ github.com/Microsoft/hcsshim v0.0.0-20190110205307-69ac8d3f7fc1 h1:QOfYwlBe/tzoR
github.com/Microsoft/hcsshim v0.0.0-20190110205307-69ac8d3f7fc1/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.0.0-20190110205307-69ac8d3f7fc1/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 h1:lsxEuwrXEAokXB9qhlbKWPpo3KMLZQ5WB5WLQRW1uq0=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4= github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
...@@ -111,8 +109,8 @@ github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= ...@@ -111,8 +109,8 @@ github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff h1:FKH02LHYqSmeWd3GBh0KIkM8JBpw3RrShgtcWShdWJg= github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff h1:FKH02LHYqSmeWd3GBh0KIkM8JBpw3RrShgtcWShdWJg=
github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 h1:a9PI9K38c+lqsMzO5itpsaXd9BhUYWTC9GM7TN5Vn0U= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 h1:w3NnFcKR5241cfmQU5ZZAsf0xcpId6mWOupTvJlUX2U=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o= github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
...@@ -208,8 +206,6 @@ github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U= ...@@ -208,8 +206,6 @@ github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE=
...@@ -309,6 +305,8 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9 ...@@ -309,6 +305,8 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb h1:e+l77LJOEqXTIQihQJVkA6ZxPOUmfPM5e4H7rcpgtSk= github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb h1:e+l77LJOEqXTIQihQJVkA6ZxPOUmfPM5e4H7rcpgtSk=
github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 h1:A4y2IxU1GcIzlcmUlQ6yr/mrvYZhqo+HakAPwgwaa6s= github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 h1:A4y2IxU1GcIzlcmUlQ6yr/mrvYZhqo+HakAPwgwaa6s=
github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d h1:7PxY7LVfSZm7PEeBTyK1rj1gABdCO2mbri6GKO1cMDs= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d h1:7PxY7LVfSZm7PEeBTyK1rj1gABdCO2mbri6GKO1cMDs=
......
...@@ -58,7 +58,7 @@ replace ( ...@@ -58,7 +58,7 @@ replace (
github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda
github.com/docker/docker => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/go-units => github.com/docker/go-units v0.3.3 github.com/docker/go-units => github.com/docker/go-units v0.3.3
github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e
...@@ -91,7 +91,6 @@ replace ( ...@@ -91,7 +91,6 @@ replace (
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c
github.com/gotestyourself/gotestyourself => github.com/gotestyourself/gotestyourself v2.2.0+incompatible
github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79
github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611 github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611
......
...@@ -31,7 +31,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c ...@@ -31,7 +31,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
...@@ -87,7 +87,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC ...@@ -87,7 +87,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
......
...@@ -14,7 +14,7 @@ require ( ...@@ -14,7 +14,7 @@ require (
github.com/coreos/go-semver v0.0.0-20180108230905-e214231b295a // indirect github.com/coreos/go-semver v0.0.0-20180108230905-e214231b295a // indirect
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550 github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550
github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4 // indirect github.com/ghodss/yaml v0.0.0-20180820084758-c7ce16629ff4 // indirect
...@@ -28,7 +28,6 @@ require ( ...@@ -28,7 +28,6 @@ require (
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c // indirect github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c // indirect
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611 github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611
github.com/grpc-ecosystem/grpc-gateway v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.3.0 // indirect
...@@ -92,7 +91,7 @@ replace ( ...@@ -92,7 +91,7 @@ replace (
github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda
github.com/docker/docker => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e
github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633
...@@ -117,7 +116,6 @@ replace ( ...@@ -117,7 +116,6 @@ replace (
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c
github.com/gotestyourself/gotestyourself => github.com/gotestyourself/gotestyourself v2.2.0+incompatible
github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79
github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611 github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611
......
...@@ -30,8 +30,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c ...@@ -30,8 +30,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 h1:a9PI9K38c+lqsMzO5itpsaXd9BhUYWTC9GM7TN5Vn0U= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 h1:w3NnFcKR5241cfmQU5ZZAsf0xcpId6mWOupTvJlUX2U=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
...@@ -73,8 +73,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC ...@@ -73,8 +73,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
......
...@@ -32,7 +32,7 @@ replace ( ...@@ -32,7 +32,7 @@ replace (
github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda
github.com/docker/docker => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e
github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633
...@@ -57,7 +57,6 @@ replace ( ...@@ -57,7 +57,6 @@ replace (
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c
github.com/gotestyourself/gotestyourself => github.com/gotestyourself/gotestyourself v2.2.0+incompatible
github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79
github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611 github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611
......
...@@ -17,7 +17,7 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc ...@@ -17,7 +17,7 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
...@@ -47,7 +47,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1 ...@@ -47,7 +47,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
......
...@@ -29,7 +29,7 @@ replace ( ...@@ -29,7 +29,7 @@ replace (
github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda
github.com/docker/docker => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e
github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633
...@@ -54,7 +54,6 @@ replace ( ...@@ -54,7 +54,6 @@ replace (
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c
github.com/gotestyourself/gotestyourself => github.com/gotestyourself/gotestyourself v2.2.0+incompatible
github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79
github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611 github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611
......
...@@ -17,7 +17,7 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc ...@@ -17,7 +17,7 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfc
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
...@@ -44,7 +44,6 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ ...@@ -44,7 +44,6 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
......
...@@ -46,7 +46,7 @@ replace ( ...@@ -46,7 +46,7 @@ replace (
github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda
github.com/docker/docker => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e
github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633
...@@ -71,7 +71,6 @@ replace ( ...@@ -71,7 +71,6 @@ replace (
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c
github.com/gotestyourself/gotestyourself => github.com/gotestyourself/gotestyourself v2.2.0+incompatible
github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79
github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611 github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611
......
...@@ -29,7 +29,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c ...@@ -29,7 +29,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e h1:p1yVGRW3nmb85p1Sh1ZJSDm4A4iKLS5QNbvUHMgGu/M= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e h1:p1yVGRW3nmb85p1Sh1ZJSDm4A4iKLS5QNbvUHMgGu/M=
...@@ -72,7 +72,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC ...@@ -72,7 +72,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
......
...@@ -36,7 +36,7 @@ replace ( ...@@ -36,7 +36,7 @@ replace (
github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg => github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda github.com/dgrijalva/jwt-go => github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda
github.com/docker/docker => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/docker => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 github.com/docker/spdystream => github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96
github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e github.com/elazarl/goproxy => github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e
github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 github.com/emicklei/go-restful => github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633
...@@ -61,7 +61,6 @@ replace ( ...@@ -61,7 +61,6 @@ replace (
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 github.com/gophercloud/gophercloud => github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c github.com/gorilla/websocket => github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c
github.com/gotestyourself/gotestyourself => github.com/gotestyourself/gotestyourself v2.2.0+incompatible
github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 github.com/gregjones/httpcache => github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 github.com/grpc-ecosystem/go-grpc-middleware => github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79
github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611 github.com/grpc-ecosystem/go-grpc-prometheus => github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20170330212424-2500245aa611
......
...@@ -29,7 +29,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c ...@@ -29,7 +29,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw=
...@@ -70,7 +70,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC ...@@ -70,7 +70,6 @@ github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsC
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c h1:Lh2aW+HnU2Nbe1gqD9SOJLJxW1jBMmQOktN2acDyJk8=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
......
...@@ -29,7 +29,6 @@ filegroup( ...@@ -29,7 +29,6 @@ filegroup(
"//vendor/github.com/Microsoft/go-winio:all-srcs", "//vendor/github.com/Microsoft/go-winio:all-srcs",
"//vendor/github.com/Microsoft/hcsshim:all-srcs", "//vendor/github.com/Microsoft/hcsshim:all-srcs",
"//vendor/github.com/NYTimes/gziphandler:all-srcs", "//vendor/github.com/NYTimes/gziphandler:all-srcs",
"//vendor/github.com/Nvveen/Gotty:all-srcs",
"//vendor/github.com/PuerkitoBio/purell:all-srcs", "//vendor/github.com/PuerkitoBio/purell:all-srcs",
"//vendor/github.com/PuerkitoBio/urlesc:all-srcs", "//vendor/github.com/PuerkitoBio/urlesc:all-srcs",
"//vendor/github.com/Rican7/retry:all-srcs", "//vendor/github.com/Rican7/retry:all-srcs",
...@@ -176,9 +175,11 @@ filegroup( ...@@ -176,9 +175,11 @@ filegroup(
"//vendor/github.com/dgrijalva/jwt-go:all-srcs", "//vendor/github.com/dgrijalva/jwt-go:all-srcs",
"//vendor/github.com/docker/distribution/digestset:all-srcs", "//vendor/github.com/docker/distribution/digestset:all-srcs",
"//vendor/github.com/docker/distribution/reference:all-srcs", "//vendor/github.com/docker/distribution/reference:all-srcs",
"//vendor/github.com/docker/distribution/registry/api/errcode:all-srcs",
"//vendor/github.com/docker/docker/api:all-srcs", "//vendor/github.com/docker/docker/api:all-srcs",
"//vendor/github.com/docker/docker/client:all-srcs", "//vendor/github.com/docker/docker/client:all-srcs",
"//vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog:all-srcs", "//vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog:all-srcs",
"//vendor/github.com/docker/docker/errdefs:all-srcs",
"//vendor/github.com/docker/docker/pkg/jsonmessage:all-srcs", "//vendor/github.com/docker/docker/pkg/jsonmessage:all-srcs",
"//vendor/github.com/docker/docker/pkg/mount:all-srcs", "//vendor/github.com/docker/docker/pkg/mount:all-srcs",
"//vendor/github.com/docker/docker/pkg/parsers:all-srcs", "//vendor/github.com/docker/docker/pkg/parsers:all-srcs",
...@@ -321,6 +322,7 @@ filegroup( ...@@ -321,6 +322,7 @@ filegroup(
"//vendor/github.com/modern-go/concurrent:all-srcs", "//vendor/github.com/modern-go/concurrent:all-srcs",
"//vendor/github.com/modern-go/reflect2:all-srcs", "//vendor/github.com/modern-go/reflect2:all-srcs",
"//vendor/github.com/mohae/deepcopy:all-srcs", "//vendor/github.com/mohae/deepcopy:all-srcs",
"//vendor/github.com/morikuni/aec:all-srcs",
"//vendor/github.com/mrunalp/fileutils:all-srcs", "//vendor/github.com/mrunalp/fileutils:all-srcs",
"//vendor/github.com/munnerz/goautoneg:all-srcs", "//vendor/github.com/munnerz/goautoneg:all-srcs",
"//vendor/github.com/mvdan/xurls:all-srcs", "//vendor/github.com/mvdan/xurls:all-srcs",
......
Copyright (c) 2012, Neal van Veen (nealvanveen@gmail.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
Gotty is a library written in Go that determines and reads termcap database
files to produce an interface for interacting with the capabilities of a
terminal.
See the godoc documentation or the source code for more information about
function usage.
gotty.go:// TODO add more concurrency to name lookup, look for more opportunities.
all:// TODO add more documentation, with function usage in a doc.go file.
all:// TODO add more testing/benchmarking with go test.
// Copyright 2012 Neal van Veen. All rights reserved.
// Usage of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package gotty
// Boolean capabilities
var BoolAttr = [...]string{
"auto_left_margin", "bw",
"auto_right_margin", "am",
"no_esc_ctlc", "xsb",
"ceol_standout_glitch", "xhp",
"eat_newline_glitch", "xenl",
"erase_overstrike", "eo",
"generic_type", "gn",
"hard_copy", "hc",
"has_meta_key", "km",
"has_status_line", "hs",
"insert_null_glitch", "in",
"memory_above", "da",
"memory_below", "db",
"move_insert_mode", "mir",
"move_standout_mode", "msgr",
"over_strike", "os",
"status_line_esc_ok", "eslok",
"dest_tabs_magic_smso", "xt",
"tilde_glitch", "hz",
"transparent_underline", "ul",
"xon_xoff", "nxon",
"needs_xon_xoff", "nxon",
"prtr_silent", "mc5i",
"hard_cursor", "chts",
"non_rev_rmcup", "nrrmc",
"no_pad_char", "npc",
"non_dest_scroll_region", "ndscr",
"can_change", "ccc",
"back_color_erase", "bce",
"hue_lightness_saturation", "hls",
"col_addr_glitch", "xhpa",
"cr_cancels_micro_mode", "crxm",
"has_print_wheel", "daisy",
"row_addr_glitch", "xvpa",
"semi_auto_right_margin", "sam",
"cpi_changes_res", "cpix",
"lpi_changes_res", "lpix",
"backspaces_with_bs", "",
"crt_no_scrolling", "",
"no_correctly_working_cr", "",
"gnu_has_meta_key", "",
"linefeed_is_newline", "",
"has_hardware_tabs", "",
"return_does_clr_eol", "",
}
// Numerical capabilities
var NumAttr = [...]string{
"columns", "cols",
"init_tabs", "it",
"lines", "lines",
"lines_of_memory", "lm",
"magic_cookie_glitch", "xmc",
"padding_baud_rate", "pb",
"virtual_terminal", "vt",
"width_status_line", "wsl",
"num_labels", "nlab",
"label_height", "lh",
"label_width", "lw",
"max_attributes", "ma",
"maximum_windows", "wnum",
"max_colors", "colors",
"max_pairs", "pairs",
"no_color_video", "ncv",
"buffer_capacity", "bufsz",
"dot_vert_spacing", "spinv",
"dot_horz_spacing", "spinh",
"max_micro_address", "maddr",
"max_micro_jump", "mjump",
"micro_col_size", "mcs",
"micro_line_size", "mls",
"number_of_pins", "npins",
"output_res_char", "orc",
"output_res_line", "orl",
"output_res_horz_inch", "orhi",
"output_res_vert_inch", "orvi",
"print_rate", "cps",
"wide_char_size", "widcs",
"buttons", "btns",
"bit_image_entwining", "bitwin",
"bit_image_type", "bitype",
"magic_cookie_glitch_ul", "",
"carriage_return_delay", "",
"new_line_delay", "",
"backspace_delay", "",
"horizontal_tab_delay", "",
"number_of_function_keys", "",
}
// String capabilities
var StrAttr = [...]string{
"back_tab", "cbt",
"bell", "bel",
"carriage_return", "cr",
"change_scroll_region", "csr",
"clear_all_tabs", "tbc",
"clear_screen", "clear",
"clr_eol", "el",
"clr_eos", "ed",
"column_address", "hpa",
"command_character", "cmdch",
"cursor_address", "cup",
"cursor_down", "cud1",
"cursor_home", "home",
"cursor_invisible", "civis",
"cursor_left", "cub1",
"cursor_mem_address", "mrcup",
"cursor_normal", "cnorm",
"cursor_right", "cuf1",
"cursor_to_ll", "ll",
"cursor_up", "cuu1",
"cursor_visible", "cvvis",
"delete_character", "dch1",
"delete_line", "dl1",
"dis_status_line", "dsl",
"down_half_line", "hd",
"enter_alt_charset_mode", "smacs",
"enter_blink_mode", "blink",
"enter_bold_mode", "bold",
"enter_ca_mode", "smcup",
"enter_delete_mode", "smdc",
"enter_dim_mode", "dim",
"enter_insert_mode", "smir",
"enter_secure_mode", "invis",
"enter_protected_mode", "prot",
"enter_reverse_mode", "rev",
"enter_standout_mode", "smso",
"enter_underline_mode", "smul",
"erase_chars", "ech",
"exit_alt_charset_mode", "rmacs",
"exit_attribute_mode", "sgr0",
"exit_ca_mode", "rmcup",
"exit_delete_mode", "rmdc",
"exit_insert_mode", "rmir",
"exit_standout_mode", "rmso",
"exit_underline_mode", "rmul",
"flash_screen", "flash",
"form_feed", "ff",
"from_status_line", "fsl",
"init_1string", "is1",
"init_2string", "is2",
"init_3string", "is3",
"init_file", "if",
"insert_character", "ich1",
"insert_line", "il1",
"insert_padding", "ip",
"key_backspace", "kbs",
"key_catab", "ktbc",
"key_clear", "kclr",
"key_ctab", "kctab",
"key_dc", "kdch1",
"key_dl", "kdl1",
"key_down", "kcud1",
"key_eic", "krmir",
"key_eol", "kel",
"key_eos", "ked",
"key_f0", "kf0",
"key_f1", "kf1",
"key_f10", "kf10",
"key_f2", "kf2",
"key_f3", "kf3",
"key_f4", "kf4",
"key_f5", "kf5",
"key_f6", "kf6",
"key_f7", "kf7",
"key_f8", "kf8",
"key_f9", "kf9",
"key_home", "khome",
"key_ic", "kich1",
"key_il", "kil1",
"key_left", "kcub1",
"key_ll", "kll",
"key_npage", "knp",
"key_ppage", "kpp",
"key_right", "kcuf1",
"key_sf", "kind",
"key_sr", "kri",
"key_stab", "khts",
"key_up", "kcuu1",
"keypad_local", "rmkx",
"keypad_xmit", "smkx",
"lab_f0", "lf0",
"lab_f1", "lf1",
"lab_f10", "lf10",
"lab_f2", "lf2",
"lab_f3", "lf3",
"lab_f4", "lf4",
"lab_f5", "lf5",
"lab_f6", "lf6",
"lab_f7", "lf7",
"lab_f8", "lf8",
"lab_f9", "lf9",
"meta_off", "rmm",
"meta_on", "smm",
"newline", "_glitch",
"pad_char", "npc",
"parm_dch", "dch",
"parm_delete_line", "dl",
"parm_down_cursor", "cud",
"parm_ich", "ich",
"parm_index", "indn",
"parm_insert_line", "il",
"parm_left_cursor", "cub",
"parm_right_cursor", "cuf",
"parm_rindex", "rin",
"parm_up_cursor", "cuu",
"pkey_key", "pfkey",
"pkey_local", "pfloc",
"pkey_xmit", "pfx",
"print_screen", "mc0",
"prtr_off", "mc4",
"prtr_on", "mc5",
"repeat_char", "rep",
"reset_1string", "rs1",
"reset_2string", "rs2",
"reset_3string", "rs3",
"reset_file", "rf",
"restore_cursor", "rc",
"row_address", "mvpa",
"save_cursor", "row_address",
"scroll_forward", "ind",
"scroll_reverse", "ri",
"set_attributes", "sgr",
"set_tab", "hts",
"set_window", "wind",
"tab", "s_magic_smso",
"to_status_line", "tsl",
"underline_char", "uc",
"up_half_line", "hu",
"init_prog", "iprog",
"key_a1", "ka1",
"key_a3", "ka3",
"key_b2", "kb2",
"key_c1", "kc1",
"key_c3", "kc3",
"prtr_non", "mc5p",
"char_padding", "rmp",
"acs_chars", "acsc",
"plab_norm", "pln",
"key_btab", "kcbt",
"enter_xon_mode", "smxon",
"exit_xon_mode", "rmxon",
"enter_am_mode", "smam",
"exit_am_mode", "rmam",
"xon_character", "xonc",
"xoff_character", "xoffc",
"ena_acs", "enacs",
"label_on", "smln",
"label_off", "rmln",
"key_beg", "kbeg",
"key_cancel", "kcan",
"key_close", "kclo",
"key_command", "kcmd",
"key_copy", "kcpy",
"key_create", "kcrt",
"key_end", "kend",
"key_enter", "kent",
"key_exit", "kext",
"key_find", "kfnd",
"key_help", "khlp",
"key_mark", "kmrk",
"key_message", "kmsg",
"key_move", "kmov",
"key_next", "knxt",
"key_open", "kopn",
"key_options", "kopt",
"key_previous", "kprv",
"key_print", "kprt",
"key_redo", "krdo",
"key_reference", "kref",
"key_refresh", "krfr",
"key_replace", "krpl",
"key_restart", "krst",
"key_resume", "kres",
"key_save", "ksav",
"key_suspend", "kspd",
"key_undo", "kund",
"key_sbeg", "kBEG",
"key_scancel", "kCAN",
"key_scommand", "kCMD",
"key_scopy", "kCPY",
"key_screate", "kCRT",
"key_sdc", "kDC",
"key_sdl", "kDL",
"key_select", "kslt",
"key_send", "kEND",
"key_seol", "kEOL",
"key_sexit", "kEXT",
"key_sfind", "kFND",
"key_shelp", "kHLP",
"key_shome", "kHOM",
"key_sic", "kIC",
"key_sleft", "kLFT",
"key_smessage", "kMSG",
"key_smove", "kMOV",
"key_snext", "kNXT",
"key_soptions", "kOPT",
"key_sprevious", "kPRV",
"key_sprint", "kPRT",
"key_sredo", "kRDO",
"key_sreplace", "kRPL",
"key_sright", "kRIT",
"key_srsume", "kRES",
"key_ssave", "kSAV",
"key_ssuspend", "kSPD",
"key_sundo", "kUND",
"req_for_input", "rfi",
"key_f11", "kf11",
"key_f12", "kf12",
"key_f13", "kf13",
"key_f14", "kf14",
"key_f15", "kf15",
"key_f16", "kf16",
"key_f17", "kf17",
"key_f18", "kf18",
"key_f19", "kf19",
"key_f20", "kf20",
"key_f21", "kf21",
"key_f22", "kf22",
"key_f23", "kf23",
"key_f24", "kf24",
"key_f25", "kf25",
"key_f26", "kf26",
"key_f27", "kf27",
"key_f28", "kf28",
"key_f29", "kf29",
"key_f30", "kf30",
"key_f31", "kf31",
"key_f32", "kf32",
"key_f33", "kf33",
"key_f34", "kf34",
"key_f35", "kf35",
"key_f36", "kf36",
"key_f37", "kf37",
"key_f38", "kf38",
"key_f39", "kf39",
"key_f40", "kf40",
"key_f41", "kf41",
"key_f42", "kf42",
"key_f43", "kf43",
"key_f44", "kf44",
"key_f45", "kf45",
"key_f46", "kf46",
"key_f47", "kf47",
"key_f48", "kf48",
"key_f49", "kf49",
"key_f50", "kf50",
"key_f51", "kf51",
"key_f52", "kf52",
"key_f53", "kf53",
"key_f54", "kf54",
"key_f55", "kf55",
"key_f56", "kf56",
"key_f57", "kf57",
"key_f58", "kf58",
"key_f59", "kf59",
"key_f60", "kf60",
"key_f61", "kf61",
"key_f62", "kf62",
"key_f63", "kf63",
"clr_bol", "el1",
"clear_margins", "mgc",
"set_left_margin", "smgl",
"set_right_margin", "smgr",
"label_format", "fln",
"set_clock", "sclk",
"display_clock", "dclk",
"remove_clock", "rmclk",
"create_window", "cwin",
"goto_window", "wingo",
"hangup", "hup",
"dial_phone", "dial",
"quick_dial", "qdial",
"tone", "tone",
"pulse", "pulse",
"flash_hook", "hook",
"fixed_pause", "pause",
"wait_tone", "wait",
"user0", "u0",
"user1", "u1",
"user2", "u2",
"user3", "u3",
"user4", "u4",
"user5", "u5",
"user6", "u6",
"user7", "u7",
"user8", "u8",
"user9", "u9",
"orig_pair", "op",
"orig_colors", "oc",
"initialize_color", "initc",
"initialize_pair", "initp",
"set_color_pair", "scp",
"set_foreground", "setf",
"set_background", "setb",
"change_char_pitch", "cpi",
"change_line_pitch", "lpi",
"change_res_horz", "chr",
"change_res_vert", "cvr",
"define_char", "defc",
"enter_doublewide_mode", "swidm",
"enter_draft_quality", "sdrfq",
"enter_italics_mode", "sitm",
"enter_leftward_mode", "slm",
"enter_micro_mode", "smicm",
"enter_near_letter_quality", "snlq",
"enter_normal_quality", "snrmq",
"enter_shadow_mode", "sshm",
"enter_subscript_mode", "ssubm",
"enter_superscript_mode", "ssupm",
"enter_upward_mode", "sum",
"exit_doublewide_mode", "rwidm",
"exit_italics_mode", "ritm",
"exit_leftward_mode", "rlm",
"exit_micro_mode", "rmicm",
"exit_shadow_mode", "rshm",
"exit_subscript_mode", "rsubm",
"exit_superscript_mode", "rsupm",
"exit_upward_mode", "rum",
"micro_column_address", "mhpa",
"micro_down", "mcud1",
"micro_left", "mcub1",
"micro_right", "mcuf1",
"micro_row_address", "mvpa",
"micro_up", "mcuu1",
"order_of_pins", "porder",
"parm_down_micro", "mcud",
"parm_left_micro", "mcub",
"parm_right_micro", "mcuf",
"parm_up_micro", "mcuu",
"select_char_set", "scs",
"set_bottom_margin", "smgb",
"set_bottom_margin_parm", "smgbp",
"set_left_margin_parm", "smglp",
"set_right_margin_parm", "smgrp",
"set_top_margin", "smgt",
"set_top_margin_parm", "smgtp",
"start_bit_image", "sbim",
"start_char_set_def", "scsd",
"stop_bit_image", "rbim",
"stop_char_set_def", "rcsd",
"subscript_characters", "subcs",
"superscript_characters", "supcs",
"these_cause_cr", "docr",
"zero_motion", "zerom",
"char_set_names", "csnm",
"key_mouse", "kmous",
"mouse_info", "minfo",
"req_mouse_pos", "reqmp",
"get_mouse", "getm",
"set_a_foreground", "setaf",
"set_a_background", "setab",
"pkey_plab", "pfxl",
"device_type", "devt",
"code_set_init", "csin",
"set0_des_seq", "s0ds",
"set1_des_seq", "s1ds",
"set2_des_seq", "s2ds",
"set3_des_seq", "s3ds",
"set_lr_margin", "smglr",
"set_tb_margin", "smgtb",
"bit_image_repeat", "birep",
"bit_image_newline", "binel",
"bit_image_carriage_return", "bicr",
"color_names", "colornm",
"define_bit_image_region", "defbi",
"end_bit_image_region", "endbi",
"set_color_band", "setcolor",
"set_page_length", "slines",
"display_pc_char", "dispc",
"enter_pc_charset_mode", "smpch",
"exit_pc_charset_mode", "rmpch",
"enter_scancode_mode", "smsc",
"exit_scancode_mode", "rmsc",
"pc_term_options", "pctrm",
"scancode_escape", "scesc",
"alt_scancode_esc", "scesa",
"enter_horizontal_hl_mode", "ehhlm",
"enter_left_hl_mode", "elhlm",
"enter_low_hl_mode", "elohlm",
"enter_right_hl_mode", "erhlm",
"enter_top_hl_mode", "ethlm",
"enter_vertical_hl_mode", "evhlm",
"set_a_attributes", "sgr1",
"set_pglen_inch", "slength",
"termcap_init2", "",
"termcap_reset", "",
"linefeed_if_not_lf", "",
"backspace_if_not_bs", "",
"other_non_function_keys", "",
"arrow_key_map", "",
"acs_ulcorner", "",
"acs_llcorner", "",
"acs_urcorner", "",
"acs_lrcorner", "",
"acs_ltee", "",
"acs_rtee", "",
"acs_btee", "",
"acs_ttee", "",
"acs_hline", "",
"acs_vline", "",
"acs_plus", "",
"memory_lock", "",
"memory_unlock", "",
"box_chars_1", "",
}
// Copyright 2012 Neal van Veen. All rights reserved.
// Usage of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Gotty is a Go-package for reading and parsing the terminfo database
package gotty
// TODO add more concurrency to name lookup, look for more opportunities.
import (
"encoding/binary"
"errors"
"fmt"
"os"
"reflect"
"strings"
"sync"
)
// Open a terminfo file by the name given and construct a TermInfo object.
// If something went wrong reading the terminfo database file, an error is
// returned.
func OpenTermInfo(termName string) (*TermInfo, error) {
var term *TermInfo
var err error
// Find the environment variables
termloc := os.Getenv("TERMINFO")
if len(termloc) == 0 {
// Search like ncurses
locations := []string{os.Getenv("HOME") + "/.terminfo/", "/etc/terminfo/",
"/lib/terminfo/", "/usr/share/terminfo/"}
var path string
for _, str := range locations {
// Construct path
path = str + string(termName[0]) + "/" + termName
// Check if path can be opened
file, _ := os.Open(path)
if file != nil {
// Path can open, fall out and use current path
file.Close()
break
}
}
if len(path) > 0 {
term, err = readTermInfo(path)
} else {
err = errors.New(fmt.Sprintf("No terminfo file(-location) found"))
}
}
return term, err
}
// Open a terminfo file from the environment variable containing the current
// terminal name and construct a TermInfo object. If something went wrong
// reading the terminfo database file, an error is returned.
func OpenTermInfoEnv() (*TermInfo, error) {
termenv := os.Getenv("TERM")
return OpenTermInfo(termenv)
}
// Return an attribute by the name attr provided. If none can be found,
// an error is returned.
func (term *TermInfo) GetAttribute(attr string) (stacker, error) {
// Channel to store the main value in.
var value stacker
// Add a blocking WaitGroup
var block sync.WaitGroup
// Keep track of variable being written.
written := false
// Function to put into goroutine.
f := func(ats interface{}) {
var ok bool
var v stacker
// Switch on type of map to use and assign value to it.
switch reflect.TypeOf(ats).Elem().Kind() {
case reflect.Bool:
v, ok = ats.(map[string]bool)[attr]
case reflect.Int16:
v, ok = ats.(map[string]int16)[attr]
case reflect.String:
v, ok = ats.(map[string]string)[attr]
}
// If ok, a value is found, so we can write.
if ok {
value = v
written = true
}
// Goroutine is done
block.Done()
}
block.Add(3)
// Go for all 3 attribute lists.
go f(term.boolAttributes)
go f(term.numAttributes)
go f(term.strAttributes)
// Wait until every goroutine is done.
block.Wait()
// If a value has been written, return it.
if written {
return value, nil
}
// Otherwise, error.
return nil, fmt.Errorf("Erorr finding attribute")
}
// Return an attribute by the name attr provided. If none can be found,
// an error is returned. A name is first converted to its termcap value.
func (term *TermInfo) GetAttributeName(name string) (stacker, error) {
tc := GetTermcapName(name)
return term.GetAttribute(tc)
}
// A utility function that finds and returns the termcap equivalent of a
// variable name.
func GetTermcapName(name string) string {
// Termcap name
var tc string
// Blocking group
var wait sync.WaitGroup
// Function to put into a goroutine
f := func(attrs []string) {
// Find the string corresponding to the name
for i, s := range attrs {
if s == name {
tc = attrs[i+1]
}
}
// Goroutine is finished
wait.Done()
}
wait.Add(3)
// Go for all 3 attribute lists
go f(BoolAttr[:])
go f(NumAttr[:])
go f(StrAttr[:])
// Wait until every goroutine is done
wait.Wait()
// Return the termcap name
return tc
}
// This function takes a path to a terminfo file and reads it in binary
// form to construct the actual TermInfo file.
func readTermInfo(path string) (*TermInfo, error) {
// Open the terminfo file
file, err := os.Open(path)
defer file.Close()
if err != nil {
return nil, err
}
// magic, nameSize, boolSize, nrSNum, nrOffsetsStr, strSize
// Header is composed of the magic 0432 octal number, size of the name
// section, size of the boolean section, the amount of number values,
// the number of offsets of strings, and the size of the string section.
var header [6]int16
// Byte array is used to read in byte values
var byteArray []byte
// Short array is used to read in short values
var shArray []int16
// TermInfo object to store values
var term TermInfo
// Read in the header
err = binary.Read(file, binary.LittleEndian, &header)
if err != nil {
return nil, err
}
// If magic number isn't there or isn't correct, we have the wrong filetype
if header[0] != 0432 {
return nil, errors.New(fmt.Sprintf("Wrong filetype"))
}
// Read in the names
byteArray = make([]byte, header[1])
err = binary.Read(file, binary.LittleEndian, &byteArray)
if err != nil {
return nil, err
}
term.Names = strings.Split(string(byteArray), "|")
// Read in the booleans
byteArray = make([]byte, header[2])
err = binary.Read(file, binary.LittleEndian, &byteArray)
if err != nil {
return nil, err
}
term.boolAttributes = make(map[string]bool)
for i, b := range byteArray {
if b == 1 {
term.boolAttributes[BoolAttr[i*2+1]] = true
}
}
// If the number of bytes read is not even, a byte for alignment is added
if len(byteArray)%2 != 0 {
err = binary.Read(file, binary.LittleEndian, make([]byte, 1))
if err != nil {
return nil, err
}
}
// Read in shorts
shArray = make([]int16, header[3])
err = binary.Read(file, binary.LittleEndian, &shArray)
if err != nil {
return nil, err
}
term.numAttributes = make(map[string]int16)
for i, n := range shArray {
if n != 0377 && n > -1 {
term.numAttributes[NumAttr[i*2+1]] = n
}
}
// Read the offsets into the short array
shArray = make([]int16, header[4])
err = binary.Read(file, binary.LittleEndian, &shArray)
if err != nil {
return nil, err
}
// Read the actual strings in the byte array
byteArray = make([]byte, header[5])
err = binary.Read(file, binary.LittleEndian, &byteArray)
if err != nil {
return nil, err
}
term.strAttributes = make(map[string]string)
// We get an offset, and then iterate until the string is null-terminated
for i, offset := range shArray {
if offset > -1 {
r := offset
for ; byteArray[r] != 0; r++ {
}
term.strAttributes[StrAttr[i*2+1]] = string(byteArray[offset:r])
}
}
return &term, nil
}
// Copyright 2012 Neal van Veen. All rights reserved.
// Usage of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package gotty
import (
"bytes"
"errors"
"fmt"
"regexp"
"strconv"
"strings"
)
var exp = [...]string{
"%%",
"%c",
"%s",
"%p(\\d)",
"%P([A-z])",
"%g([A-z])",
"%'(.)'",
"%{([0-9]+)}",
"%l",
"%\\+|%-|%\\*|%/|%m",
"%&|%\\||%\\^",
"%=|%>|%<",
"%A|%O",
"%!|%~",
"%i",
"%(:[\\ #\\-\\+]{0,4})?(\\d+\\.\\d+|\\d+)?[doxXs]",
"%\\?(.*?);",
}
var regex *regexp.Regexp
var staticVar map[byte]stacker
// Parses the attribute that is received with name attr and parameters params.
func (term *TermInfo) Parse(attr string, params ...interface{}) (string, error) {
// Get the attribute name first.
iface, err := term.GetAttribute(attr)
str, ok := iface.(string)
if err != nil {
return "", err
}
if !ok {
return str, errors.New("Only string capabilities can be parsed.")
}
// Construct the hidden parser struct so we can use a recursive stack based
// parser.
ps := &parser{}
// Dynamic variables only exist in this context.
ps.dynamicVar = make(map[byte]stacker, 26)
ps.parameters = make([]stacker, len(params))
// Convert the parameters to insert them into the parser struct.
for i, x := range params {
ps.parameters[i] = x
}
// Recursively walk and return.
result, err := ps.walk(str)
return result, err
}
// Parses the attribute that is received with name attr and parameters params.
// Only works on full name of a capability that is given, which it uses to
// search for the termcap name.
func (term *TermInfo) ParseName(attr string, params ...interface{}) (string, error) {
tc := GetTermcapName(attr)
return term.Parse(tc, params)
}
// Identify each token in a stack based manner and do the actual parsing.
func (ps *parser) walk(attr string) (string, error) {
// We use a buffer to get the modified string.
var buf bytes.Buffer
// Next, find and identify all tokens by their indices and strings.
tokens := regex.FindAllStringSubmatch(attr, -1)
if len(tokens) == 0 {
return attr, nil
}
indices := regex.FindAllStringIndex(attr, -1)
q := 0 // q counts the matches of one token
// Iterate through the string per character.
for i := 0; i < len(attr); i++ {
// If the current position is an identified token, execute the following
// steps.
if q < len(indices) && i >= indices[q][0] && i < indices[q][1] {
// Switch on token.
switch {
case tokens[q][0][:2] == "%%":
// Literal percentage character.
buf.WriteByte('%')
case tokens[q][0][:2] == "%c":
// Pop a character.
c, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
buf.WriteByte(c.(byte))
case tokens[q][0][:2] == "%s":
// Pop a string.
str, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
if _, ok := str.(string); !ok {
return buf.String(), errors.New("Stack head is not a string")
}
buf.WriteString(str.(string))
case tokens[q][0][:2] == "%p":
// Push a parameter on the stack.
index, err := strconv.ParseInt(tokens[q][1], 10, 8)
index--
if err != nil {
return buf.String(), err
}
if int(index) >= len(ps.parameters) {
return buf.String(), errors.New("Parameters index out of bound")
}
ps.st.push(ps.parameters[index])
case tokens[q][0][:2] == "%P":
// Pop a variable from the stack as a dynamic or static variable.
val, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
index := tokens[q][2]
if len(index) > 1 {
errorStr := fmt.Sprintf("%s is not a valid dynamic variables index",
index)
return buf.String(), errors.New(errorStr)
}
// Specify either dynamic or static.
if index[0] >= 'a' && index[0] <= 'z' {
ps.dynamicVar[index[0]] = val
} else if index[0] >= 'A' && index[0] <= 'Z' {
staticVar[index[0]] = val
}
case tokens[q][0][:2] == "%g":
// Push a variable from the stack as a dynamic or static variable.
index := tokens[q][3]
if len(index) > 1 {
errorStr := fmt.Sprintf("%s is not a valid static variables index",
index)
return buf.String(), errors.New(errorStr)
}
var val stacker
if index[0] >= 'a' && index[0] <= 'z' {
val = ps.dynamicVar[index[0]]
} else if index[0] >= 'A' && index[0] <= 'Z' {
val = staticVar[index[0]]
}
ps.st.push(val)
case tokens[q][0][:2] == "%'":
// Push a character constant.
con := tokens[q][4]
if len(con) > 1 {
errorStr := fmt.Sprintf("%s is not a valid character constant", con)
return buf.String(), errors.New(errorStr)
}
ps.st.push(con[0])
case tokens[q][0][:2] == "%{":
// Push an integer constant.
con, err := strconv.ParseInt(tokens[q][5], 10, 32)
if err != nil {
return buf.String(), err
}
ps.st.push(con)
case tokens[q][0][:2] == "%l":
// Push the length of the string that is popped from the stack.
popStr, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
if _, ok := popStr.(string); !ok {
errStr := fmt.Sprintf("Stack head is not a string")
return buf.String(), errors.New(errStr)
}
ps.st.push(len(popStr.(string)))
case tokens[q][0][:2] == "%?":
// If-then-else construct. First, the whole string is identified and
// then inside this substring, we can specify which parts to switch on.
ifReg, _ := regexp.Compile("%\\?(.*)%t(.*)%e(.*);|%\\?(.*)%t(.*);")
ifTokens := ifReg.FindStringSubmatch(tokens[q][0])
var (
ifStr string
err error
)
// Parse the if-part to determine if-else.
if len(ifTokens[1]) > 0 {
ifStr, err = ps.walk(ifTokens[1])
} else { // else
ifStr, err = ps.walk(ifTokens[4])
}
// Return any errors
if err != nil {
return buf.String(), err
} else if len(ifStr) > 0 {
// Self-defined limitation, not sure if this is correct, but didn't
// seem like it.
return buf.String(), errors.New("If-clause cannot print statements")
}
var thenStr string
// Pop the first value that is set by parsing the if-clause.
choose, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
// Switch to if or else.
if choose.(int) == 0 && len(ifTokens[1]) > 0 {
thenStr, err = ps.walk(ifTokens[3])
} else if choose.(int) != 0 {
if len(ifTokens[1]) > 0 {
thenStr, err = ps.walk(ifTokens[2])
} else {
thenStr, err = ps.walk(ifTokens[5])
}
}
if err != nil {
return buf.String(), err
}
buf.WriteString(thenStr)
case tokens[q][0][len(tokens[q][0])-1] == 'd': // Fallthrough for printing
fallthrough
case tokens[q][0][len(tokens[q][0])-1] == 'o': // digits.
fallthrough
case tokens[q][0][len(tokens[q][0])-1] == 'x':
fallthrough
case tokens[q][0][len(tokens[q][0])-1] == 'X':
fallthrough
case tokens[q][0][len(tokens[q][0])-1] == 's':
token := tokens[q][0]
// Remove the : that comes before a flag.
if token[1] == ':' {
token = token[:1] + token[2:]
}
digit, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
// The rest is determined like the normal formatted prints.
digitStr := fmt.Sprintf(token, digit.(int))
buf.WriteString(digitStr)
case tokens[q][0][:2] == "%i":
// Increment the parameters by one.
if len(ps.parameters) < 2 {
return buf.String(), errors.New("Not enough parameters to increment.")
}
val1, val2 := ps.parameters[0].(int), ps.parameters[1].(int)
val1++
val2++
ps.parameters[0], ps.parameters[1] = val1, val2
default:
// The rest of the tokens is a special case, where two values are
// popped and then operated on by the token that comes after them.
op1, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
op2, err := ps.st.pop()
if err != nil {
return buf.String(), err
}
var result stacker
switch tokens[q][0][:2] {
case "%+":
// Addition
result = op2.(int) + op1.(int)
case "%-":
// Subtraction
result = op2.(int) - op1.(int)
case "%*":
// Multiplication
result = op2.(int) * op1.(int)
case "%/":
// Division
result = op2.(int) / op1.(int)
case "%m":
// Modulo
result = op2.(int) % op1.(int)
case "%&":
// Bitwise AND
result = op2.(int) & op1.(int)
case "%|":
// Bitwise OR
result = op2.(int) | op1.(int)
case "%^":
// Bitwise XOR
result = op2.(int) ^ op1.(int)
case "%=":
// Equals
result = op2 == op1
case "%>":
// Greater-than
result = op2.(int) > op1.(int)
case "%<":
// Lesser-than
result = op2.(int) < op1.(int)
case "%A":
// Logical AND
result = op2.(bool) && op1.(bool)
case "%O":
// Logical OR
result = op2.(bool) || op1.(bool)
case "%!":
// Logical complement
result = !op1.(bool)
case "%~":
// Bitwise complement
result = ^(op1.(int))
}
ps.st.push(result)
}
i = indices[q][1] - 1
q++
} else {
// We are not "inside" a token, so just skip until the end or the next
// token, and add all characters to the buffer.
j := i
if q != len(indices) {
for !(j >= indices[q][0] && j < indices[q][1]) {
j++
}
} else {
j = len(attr)
}
buf.WriteString(string(attr[i:j]))
i = j
}
}
// Return the buffer as a string.
return buf.String(), nil
}
// Push a stacker-value onto the stack.
func (st *stack) push(s stacker) {
*st = append(*st, s)
}
// Pop a stacker-value from the stack.
func (st *stack) pop() (stacker, error) {
if len(*st) == 0 {
return nil, errors.New("Stack is empty.")
}
newStack := make(stack, len(*st)-1)
val := (*st)[len(*st)-1]
copy(newStack, (*st)[:len(*st)-1])
*st = newStack
return val, nil
}
// Initialize regexes and the static vars (that don't get changed between
// calls.
func init() {
// Initialize the main regex.
expStr := strings.Join(exp[:], "|")
regex, _ = regexp.Compile(expStr)
// Initialize the static variables.
staticVar = make(map[byte]stacker, 26)
}
// Copyright 2012 Neal van Veen. All rights reserved.
// Usage of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package gotty
type TermInfo struct {
boolAttributes map[string]bool
numAttributes map[string]int16
strAttributes map[string]string
// The various names of the TermInfo file.
Names []string
}
type stacker interface {
}
type stack []stacker
type parser struct {
st stack
parameters []stacker
dynamicVar map[byte]stacker
}
...@@ -3,13 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") ...@@ -3,13 +3,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"attributes.go", "errors.go",
"gotty.go", "handler.go",
"parser.go", "register.go",
"types.go",
], ],
importmap = "k8s.io/kubernetes/vendor/github.com/Nvveen/Gotty", importmap = "k8s.io/kubernetes/vendor/github.com/docker/distribution/registry/api/errcode",
importpath = "github.com/Nvveen/Gotty", importpath = "github.com/docker/distribution/registry/api/errcode",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
......
package errcode
import (
"encoding/json"
"fmt"
"strings"
)
// ErrorCoder is the base interface for ErrorCode and Error allowing
// users of each to just call ErrorCode to get the real ID of each
type ErrorCoder interface {
ErrorCode() ErrorCode
}
// ErrorCode represents the error type. The errors are serialized via strings
// and the integer format may change and should *never* be exported.
type ErrorCode int
var _ error = ErrorCode(0)
// ErrorCode just returns itself
func (ec ErrorCode) ErrorCode() ErrorCode {
return ec
}
// Error returns the ID/Value
func (ec ErrorCode) Error() string {
// NOTE(stevvooe): Cannot use message here since it may have unpopulated args.
return strings.ToLower(strings.Replace(ec.String(), "_", " ", -1))
}
// Descriptor returns the descriptor for the error code.
func (ec ErrorCode) Descriptor() ErrorDescriptor {
d, ok := errorCodeToDescriptors[ec]
if !ok {
return ErrorCodeUnknown.Descriptor()
}
return d
}
// String returns the canonical identifier for this error code.
func (ec ErrorCode) String() string {
return ec.Descriptor().Value
}
// Message returned the human-readable error message for this error code.
func (ec ErrorCode) Message() string {
return ec.Descriptor().Message
}
// MarshalText encodes the receiver into UTF-8-encoded text and returns the
// result.
func (ec ErrorCode) MarshalText() (text []byte, err error) {
return []byte(ec.String()), nil
}
// UnmarshalText decodes the form generated by MarshalText.
func (ec *ErrorCode) UnmarshalText(text []byte) error {
desc, ok := idToDescriptors[string(text)]
if !ok {
desc = ErrorCodeUnknown.Descriptor()
}
*ec = desc.Code
return nil
}
// WithMessage creates a new Error struct based on the passed-in info and
// overrides the Message property.
func (ec ErrorCode) WithMessage(message string) Error {
return Error{
Code: ec,
Message: message,
}
}
// WithDetail creates a new Error struct based on the passed-in info and
// set the Detail property appropriately
func (ec ErrorCode) WithDetail(detail interface{}) Error {
return Error{
Code: ec,
Message: ec.Message(),
}.WithDetail(detail)
}
// WithArgs creates a new Error struct and sets the Args slice
func (ec ErrorCode) WithArgs(args ...interface{}) Error {
return Error{
Code: ec,
Message: ec.Message(),
}.WithArgs(args...)
}
// Error provides a wrapper around ErrorCode with extra Details provided.
type Error struct {
Code ErrorCode `json:"code"`
Message string `json:"message"`
Detail interface{} `json:"detail,omitempty"`
// TODO(duglin): See if we need an "args" property so we can do the
// variable substitution right before showing the message to the user
}
var _ error = Error{}
// ErrorCode returns the ID/Value of this Error
func (e Error) ErrorCode() ErrorCode {
return e.Code
}
// Error returns a human readable representation of the error.
func (e Error) Error() string {
return fmt.Sprintf("%s: %s", e.Code.Error(), e.Message)
}
// WithDetail will return a new Error, based on the current one, but with
// some Detail info added
func (e Error) WithDetail(detail interface{}) Error {
return Error{
Code: e.Code,
Message: e.Message,
Detail: detail,
}
}
// WithArgs uses the passed-in list of interface{} as the substitution
// variables in the Error's Message string, but returns a new Error
func (e Error) WithArgs(args ...interface{}) Error {
return Error{
Code: e.Code,
Message: fmt.Sprintf(e.Code.Message(), args...),
Detail: e.Detail,
}
}
// ErrorDescriptor provides relevant information about a given error code.
type ErrorDescriptor struct {
// Code is the error code that this descriptor describes.
Code ErrorCode
// Value provides a unique, string key, often captilized with
// underscores, to identify the error code. This value is used as the
// keyed value when serializing api errors.
Value string
// Message is a short, human readable decription of the error condition
// included in API responses.
Message string
// Description provides a complete account of the errors purpose, suitable
// for use in documentation.
Description string
// HTTPStatusCode provides the http status code that is associated with
// this error condition.
HTTPStatusCode int
}
// ParseErrorCode returns the value by the string error code.
// `ErrorCodeUnknown` will be returned if the error is not known.
func ParseErrorCode(value string) ErrorCode {
ed, ok := idToDescriptors[value]
if ok {
return ed.Code
}
return ErrorCodeUnknown
}
// Errors provides the envelope for multiple errors and a few sugar methods
// for use within the application.
type Errors []error
var _ error = Errors{}
func (errs Errors) Error() string {
switch len(errs) {
case 0:
return "<nil>"
case 1:
return errs[0].Error()
default:
msg := "errors:\n"
for _, err := range errs {
msg += err.Error() + "\n"
}
return msg
}
}
// Len returns the current number of errors.
func (errs Errors) Len() int {
return len(errs)
}
// MarshalJSON converts slice of error, ErrorCode or Error into a
// slice of Error - then serializes
func (errs Errors) MarshalJSON() ([]byte, error) {
var tmpErrs struct {
Errors []Error `json:"errors,omitempty"`
}
for _, daErr := range errs {
var err Error
switch daErr.(type) {
case ErrorCode:
err = daErr.(ErrorCode).WithDetail(nil)
case Error:
err = daErr.(Error)
default:
err = ErrorCodeUnknown.WithDetail(daErr)
}
// If the Error struct was setup and they forgot to set the
// Message field (meaning its "") then grab it from the ErrCode
msg := err.Message
if msg == "" {
msg = err.Code.Message()
}
tmpErrs.Errors = append(tmpErrs.Errors, Error{
Code: err.Code,
Message: msg,
Detail: err.Detail,
})
}
return json.Marshal(tmpErrs)
}
// UnmarshalJSON deserializes []Error and then converts it into slice of
// Error or ErrorCode
func (errs *Errors) UnmarshalJSON(data []byte) error {
var tmpErrs struct {
Errors []Error
}
if err := json.Unmarshal(data, &tmpErrs); err != nil {
return err
}
var newErrs Errors
for _, daErr := range tmpErrs.Errors {
// If Message is empty or exactly matches the Code's message string
// then just use the Code, no need for a full Error struct
if daErr.Detail == nil && (daErr.Message == "" || daErr.Message == daErr.Code.Message()) {
// Error's w/o details get converted to ErrorCode
newErrs = append(newErrs, daErr.Code)
} else {
// Error's w/ details are untouched
newErrs = append(newErrs, Error{
Code: daErr.Code,
Message: daErr.Message,
Detail: daErr.Detail,
})
}
}
*errs = newErrs
return nil
}
package errcode
import (
"encoding/json"
"net/http"
)
// ServeJSON attempts to serve the errcode in a JSON envelope. It marshals err
// and sets the content-type header to 'application/json'. It will handle
// ErrorCoder and Errors, and if necessary will create an envelope.
func ServeJSON(w http.ResponseWriter, err error) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
var sc int
switch errs := err.(type) {
case Errors:
if len(errs) < 1 {
break
}
if err, ok := errs[0].(ErrorCoder); ok {
sc = err.ErrorCode().Descriptor().HTTPStatusCode
}
case ErrorCoder:
sc = errs.ErrorCode().Descriptor().HTTPStatusCode
err = Errors{err} // create an envelope.
default:
// We just have an unhandled error type, so just place in an envelope
// and move along.
err = Errors{err}
}
if sc == 0 {
sc = http.StatusInternalServerError
}
w.WriteHeader(sc)
if err := json.NewEncoder(w).Encode(err); err != nil {
return err
}
return nil
}
package errcode
import (
"fmt"
"net/http"
"sort"
"sync"
)
var (
errorCodeToDescriptors = map[ErrorCode]ErrorDescriptor{}
idToDescriptors = map[string]ErrorDescriptor{}
groupToDescriptors = map[string][]ErrorDescriptor{}
)
var (
// ErrorCodeUnknown is a generic error that can be used as a last
// resort if there is no situation-specific error message that can be used
ErrorCodeUnknown = Register("errcode", ErrorDescriptor{
Value: "UNKNOWN",
Message: "unknown error",
Description: `Generic error returned when the error does not have an
API classification.`,
HTTPStatusCode: http.StatusInternalServerError,
})
// ErrorCodeUnsupported is returned when an operation is not supported.
ErrorCodeUnsupported = Register("errcode", ErrorDescriptor{
Value: "UNSUPPORTED",
Message: "The operation is unsupported.",
Description: `The operation was unsupported due to a missing
implementation or invalid set of parameters.`,
HTTPStatusCode: http.StatusMethodNotAllowed,
})
// ErrorCodeUnauthorized is returned if a request requires
// authentication.
ErrorCodeUnauthorized = Register("errcode", ErrorDescriptor{
Value: "UNAUTHORIZED",
Message: "authentication required",
Description: `The access controller was unable to authenticate
the client. Often this will be accompanied by a
Www-Authenticate HTTP response header indicating how to
authenticate.`,
HTTPStatusCode: http.StatusUnauthorized,
})
// ErrorCodeDenied is returned if a client does not have sufficient
// permission to perform an action.
ErrorCodeDenied = Register("errcode", ErrorDescriptor{
Value: "DENIED",
Message: "requested access to the resource is denied",
Description: `The access controller denied access for the
operation on a resource.`,
HTTPStatusCode: http.StatusForbidden,
})
// ErrorCodeUnavailable provides a common error to report unavailability
// of a service or endpoint.
ErrorCodeUnavailable = Register("errcode", ErrorDescriptor{
Value: "UNAVAILABLE",
Message: "service unavailable",
Description: "Returned when a service is not available",
HTTPStatusCode: http.StatusServiceUnavailable,
})
// ErrorCodeTooManyRequests is returned if a client attempts too many
// times to contact a service endpoint.
ErrorCodeTooManyRequests = Register("errcode", ErrorDescriptor{
Value: "TOOMANYREQUESTS",
Message: "too many requests",
Description: `Returned when a client attempts to contact a
service too many times`,
HTTPStatusCode: http.StatusTooManyRequests,
})
)
var nextCode = 1000
var registerLock sync.Mutex
// Register will make the passed-in error known to the environment and
// return a new ErrorCode
func Register(group string, descriptor ErrorDescriptor) ErrorCode {
registerLock.Lock()
defer registerLock.Unlock()
descriptor.Code = ErrorCode(nextCode)
if _, ok := idToDescriptors[descriptor.Value]; ok {
panic(fmt.Sprintf("ErrorValue %q is already registered", descriptor.Value))
}
if _, ok := errorCodeToDescriptors[descriptor.Code]; ok {
panic(fmt.Sprintf("ErrorCode %v is already registered", descriptor.Code))
}
groupToDescriptors[group] = append(groupToDescriptors[group], descriptor)
errorCodeToDescriptors[descriptor.Code] = descriptor
idToDescriptors[descriptor.Value] = descriptor
nextCode++
return descriptor.Code
}
type byValue []ErrorDescriptor
func (a byValue) Len() int { return len(a) }
func (a byValue) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byValue) Less(i, j int) bool { return a[i].Value < a[j].Value }
// GetGroupNames returns the list of Error group names that are registered
func GetGroupNames() []string {
keys := []string{}
for k := range groupToDescriptors {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
// GetErrorCodeGroup returns the named group of error descriptors
func GetErrorCodeGroup(name string) []ErrorDescriptor {
desc := groupToDescriptors[name]
sort.Sort(byValue(desc))
return desc
}
// GetErrorAllDescriptors returns a slice of all ErrorDescriptors that are
// registered, irrespective of what group they're in
func GetErrorAllDescriptors() []ErrorDescriptor {
result := []ErrorDescriptor{}
for _, group := range GetGroupNames() {
result = append(result, GetErrorCodeGroup(group)...)
}
sort.Sort(byValue(result))
return result
}
...@@ -118,6 +118,7 @@ Andreas Köhler <andi5.py@gmx.net> ...@@ -118,6 +118,7 @@ Andreas Köhler <andi5.py@gmx.net>
Andreas Savvides <andreas@editd.com> Andreas Savvides <andreas@editd.com>
Andreas Tiefenthaler <at@an-ti.eu> Andreas Tiefenthaler <at@an-ti.eu>
Andrei Gherzan <andrei@resin.io> Andrei Gherzan <andrei@resin.io>
Andrei Vagin <avagin@gmail.com>
Andrew C. Bodine <acbodine@us.ibm.com> Andrew C. Bodine <acbodine@us.ibm.com>
Andrew Clay Shafer <andrewcshafer@gmail.com> Andrew Clay Shafer <andrewcshafer@gmail.com>
Andrew Duckworth <grillopress@gmail.com> Andrew Duckworth <grillopress@gmail.com>
...@@ -137,6 +138,7 @@ Andrew Po <absourd.noise@gmail.com> ...@@ -137,6 +138,7 @@ Andrew Po <absourd.noise@gmail.com>
Andrew Weiss <andrew.weiss@docker.com> Andrew Weiss <andrew.weiss@docker.com>
Andrew Williams <williams.andrew@gmail.com> Andrew Williams <williams.andrew@gmail.com>
Andrews Medina <andrewsmedina@gmail.com> Andrews Medina <andrewsmedina@gmail.com>
Andrey Kolomentsev <andrey.kolomentsev@docker.com>
Andrey Petrov <andrey.petrov@shazow.net> Andrey Petrov <andrey.petrov@shazow.net>
Andrey Stolbovsky <andrey.stolbovsky@gmail.com> Andrey Stolbovsky <andrey.stolbovsky@gmail.com>
André Martins <aanm90@gmail.com> André Martins <aanm90@gmail.com>
...@@ -195,23 +197,27 @@ bdevloed <boris.de.vloed@gmail.com> ...@@ -195,23 +197,27 @@ bdevloed <boris.de.vloed@gmail.com>
Ben Bonnefoy <frenchben@docker.com> Ben Bonnefoy <frenchben@docker.com>
Ben Firshman <ben@firshman.co.uk> Ben Firshman <ben@firshman.co.uk>
Ben Golub <ben.golub@dotcloud.com> Ben Golub <ben.golub@dotcloud.com>
Ben Gould <ben@bengould.co.uk>
Ben Hall <ben@benhall.me.uk> Ben Hall <ben@benhall.me.uk>
Ben Sargent <ben@brokendigits.com> Ben Sargent <ben@brokendigits.com>
Ben Severson <BenSeverson@users.noreply.github.com> Ben Severson <BenSeverson@users.noreply.github.com>
Ben Toews <mastahyeti@gmail.com> Ben Toews <mastahyeti@gmail.com>
Ben Wiklund <ben@daisyowl.com> Ben Wiklund <ben@daisyowl.com>
Benjamin Atkin <ben@benatkin.com> Benjamin Atkin <ben@benatkin.com>
Benjamin Baker <Benjamin.baker@utexas.edu>
Benjamin Boudreau <boudreau.benjamin@gmail.com> Benjamin Boudreau <boudreau.benjamin@gmail.com>
Benjamin Yolken <yolken@stripe.com> Benjamin Yolken <yolken@stripe.com>
Benoit Chesneau <bchesneau@gmail.com> Benoit Chesneau <bchesneau@gmail.com>
Bernerd Schaefer <bj.schaefer@gmail.com> Bernerd Schaefer <bj.schaefer@gmail.com>
Bernhard M. Wiedemann <bwiedemann@suse.de> Bernhard M. Wiedemann <bwiedemann@suse.de>
Bert Goethals <bert@bertg.be> Bert Goethals <bert@bertg.be>
Bevisy Zhang <binbin36520@gmail.com>
Bharath Thiruveedula <bharath_ves@hotmail.com> Bharath Thiruveedula <bharath_ves@hotmail.com>
Bhiraj Butala <abhiraj.butala@gmail.com> Bhiraj Butala <abhiraj.butala@gmail.com>
Bhumika Bayani <bhumikabayani@gmail.com> Bhumika Bayani <bhumikabayani@gmail.com>
Bilal Amarni <bilal.amarni@gmail.com> Bilal Amarni <bilal.amarni@gmail.com>
Bill Wang <ozbillwang@gmail.com> Bill Wang <ozbillwang@gmail.com>
Bily Zhang <xcoder@tenxcloud.com>
Bin Liu <liubin0329@gmail.com> Bin Liu <liubin0329@gmail.com>
Bingshen Wang <bingshen.wbs@alibaba-inc.com> Bingshen Wang <bingshen.wbs@alibaba-inc.com>
Blake Geno <blakegeno@gmail.com> Blake Geno <blakegeno@gmail.com>
...@@ -246,6 +252,7 @@ Brian Torres-Gil <brian@dralth.com> ...@@ -246,6 +252,7 @@ Brian Torres-Gil <brian@dralth.com>
Brian Trump <btrump@yelp.com> Brian Trump <btrump@yelp.com>
Brice Jaglin <bjaglin@teads.tv> Brice Jaglin <bjaglin@teads.tv>
Briehan Lombaard <briehan.lombaard@gmail.com> Briehan Lombaard <briehan.lombaard@gmail.com>
Brielle Broder <bbroder@google.com>
Bruno Bigras <bigras.bruno@gmail.com> Bruno Bigras <bigras.bruno@gmail.com>
Bruno Binet <bruno.binet@gmail.com> Bruno Binet <bruno.binet@gmail.com>
Bruno Gazzera <bgazzera@paginar.com> Bruno Gazzera <bgazzera@paginar.com>
...@@ -300,6 +307,7 @@ Chen Min <chenmin46@huawei.com> ...@@ -300,6 +307,7 @@ Chen Min <chenmin46@huawei.com>
Chen Mingjie <chenmingjie0828@163.com> Chen Mingjie <chenmingjie0828@163.com>
Chen Qiu <cheney-90@hotmail.com> Chen Qiu <cheney-90@hotmail.com>
Cheng-mean Liu <soccerl@microsoft.com> Cheng-mean Liu <soccerl@microsoft.com>
Chengfei Shang <cfshang@alauda.io>
Chengguang Xu <cgxu519@gmx.com> Chengguang Xu <cgxu519@gmx.com>
chenyuzhu <chenyuzhi@oschina.cn> chenyuzhu <chenyuzhi@oschina.cn>
Chetan Birajdar <birajdar.chetan@gmail.com> Chetan Birajdar <birajdar.chetan@gmail.com>
...@@ -325,9 +333,11 @@ Chris Swan <chris.swan@iee.org> ...@@ -325,9 +333,11 @@ Chris Swan <chris.swan@iee.org>
Chris Telfer <ctelfer@docker.com> Chris Telfer <ctelfer@docker.com>
Chris Wahl <github@wahlnetwork.com> Chris Wahl <github@wahlnetwork.com>
Chris Weyl <cweyl@alumni.drew.edu> Chris Weyl <cweyl@alumni.drew.edu>
Chris White <me@cwprogram.com>
Christian Berendt <berendt@b1-systems.de> Christian Berendt <berendt@b1-systems.de>
Christian Brauner <christian.brauner@ubuntu.com> Christian Brauner <christian.brauner@ubuntu.com>
Christian Böhme <developement@boehme3d.de> Christian Böhme <developement@boehme3d.de>
Christian Muehlhaeuser <muesli@gmail.com>
Christian Persson <saser@live.se> Christian Persson <saser@live.se>
Christian Rotzoll <ch.rotzoll@gmail.com> Christian Rotzoll <ch.rotzoll@gmail.com>
Christian Simon <simon@swine.de> Christian Simon <simon@swine.de>
...@@ -350,6 +360,7 @@ Cody Roseborough <crrosebo@amazon.com> ...@@ -350,6 +360,7 @@ Cody Roseborough <crrosebo@amazon.com>
Coenraad Loubser <coenraad@wish.org.za> Coenraad Loubser <coenraad@wish.org.za>
Colin Dunklau <colin.dunklau@gmail.com> Colin Dunklau <colin.dunklau@gmail.com>
Colin Hebert <hebert.colin@gmail.com> Colin Hebert <hebert.colin@gmail.com>
Colin Panisset <github@clabber.com>
Colin Rice <colin@daedrum.net> Colin Rice <colin@daedrum.net>
Colin Walters <walters@verbum.org> Colin Walters <walters@verbum.org>
Collin Guarino <collin.guarino@gmail.com> Collin Guarino <collin.guarino@gmail.com>
...@@ -385,6 +396,7 @@ Dan Levy <dan@danlevy.net> ...@@ -385,6 +396,7 @@ Dan Levy <dan@danlevy.net>
Dan McPherson <dmcphers@redhat.com> Dan McPherson <dmcphers@redhat.com>
Dan Stine <sw@stinemail.com> Dan Stine <sw@stinemail.com>
Dan Williams <me@deedubs.com> Dan Williams <me@deedubs.com>
Dani Hodovic <dani.hodovic@gmail.com>
Dani Louca <dani.louca@docker.com> Dani Louca <dani.louca@docker.com>
Daniel Antlinger <d.antlinger@gmx.at> Daniel Antlinger <d.antlinger@gmx.at>
Daniel Dao <dqminh@cloudflare.com> Daniel Dao <dqminh@cloudflare.com>
...@@ -438,12 +450,14 @@ David Mackey <tdmackey@booleanhaiku.com> ...@@ -438,12 +450,14 @@ David Mackey <tdmackey@booleanhaiku.com>
David Mat <david@davidmat.com> David Mat <david@davidmat.com>
David Mcanulty <github@hellspark.com> David Mcanulty <github@hellspark.com>
David McKay <david@rawkode.com> David McKay <david@rawkode.com>
David P Hilton <david.hilton.p@gmail.com>
David Pelaez <pelaez89@gmail.com> David Pelaez <pelaez89@gmail.com>
David R. Jenni <david.r.jenni@gmail.com> David R. Jenni <david.r.jenni@gmail.com>
David Röthlisberger <david@rothlis.net> David Röthlisberger <david@rothlis.net>
David Sheets <dsheets@docker.com> David Sheets <dsheets@docker.com>
David Sissitka <me@dsissitka.com> David Sissitka <me@dsissitka.com>
David Trott <github@davidtrott.com> David Trott <github@davidtrott.com>
David Wang <00107082@163.com>
David Williamson <david.williamson@docker.com> David Williamson <david.williamson@docker.com>
David Xia <dxia@spotify.com> David Xia <dxia@spotify.com>
David Young <yangboh@cn.ibm.com> David Young <yangboh@cn.ibm.com>
...@@ -451,8 +465,10 @@ Davide Ceretti <davide.ceretti@hogarthww.com> ...@@ -451,8 +465,10 @@ Davide Ceretti <davide.ceretti@hogarthww.com>
Dawn Chen <dawnchen@google.com> Dawn Chen <dawnchen@google.com>
dbdd <wangtong2712@gmail.com> dbdd <wangtong2712@gmail.com>
dcylabs <dcylabs@gmail.com> dcylabs <dcylabs@gmail.com>
Debayan De <debayande@users.noreply.github.com>
Deborah Gertrude Digges <deborah.gertrude.digges@gmail.com> Deborah Gertrude Digges <deborah.gertrude.digges@gmail.com>
deed02392 <georgehafiz@gmail.com> deed02392 <georgehafiz@gmail.com>
Deep Debroy <ddebroy@docker.com>
Deng Guangxing <dengguangxing@huawei.com> Deng Guangxing <dengguangxing@huawei.com>
Deni Bertovic <deni@kset.org> Deni Bertovic <deni@kset.org>
Denis Defreyne <denis@soundcloud.com> Denis Defreyne <denis@soundcloud.com>
...@@ -477,6 +493,7 @@ Dieter Reuter <dieter.reuter@me.com> ...@@ -477,6 +493,7 @@ Dieter Reuter <dieter.reuter@me.com>
Dillon Dixon <dillondixon@gmail.com> Dillon Dixon <dillondixon@gmail.com>
Dima Stopel <dima@twistlock.com> Dima Stopel <dima@twistlock.com>
Dimitri John Ledkov <dimitri.j.ledkov@intel.com> Dimitri John Ledkov <dimitri.j.ledkov@intel.com>
Dimitris Mandalidis <dimitris.mandalidis@gmail.com>
Dimitris Rozakis <dimrozakis@gmail.com> Dimitris Rozakis <dimrozakis@gmail.com>
Dimitry Andric <d.andric@activevideo.com> Dimitry Andric <d.andric@activevideo.com>
Dinesh Subhraveti <dineshs@altiscale.com> Dinesh Subhraveti <dineshs@altiscale.com>
...@@ -503,6 +520,7 @@ Don Kjer <don.kjer@gmail.com> ...@@ -503,6 +520,7 @@ Don Kjer <don.kjer@gmail.com>
Don Spaulding <donspauldingii@gmail.com> Don Spaulding <donspauldingii@gmail.com>
Donald Huang <don.hcd@gmail.com> Donald Huang <don.hcd@gmail.com>
Dong Chen <dongluo.chen@docker.com> Dong Chen <dongluo.chen@docker.com>
Donghwa Kim <shanytt@gmail.com>
Donovan Jones <git@gamma.net.nz> Donovan Jones <git@gamma.net.nz>
Doron Podoleanu <doronp@il.ibm.com> Doron Podoleanu <doronp@il.ibm.com>
Doug Davis <dug@us.ibm.com> Doug Davis <dug@us.ibm.com>
...@@ -579,7 +597,9 @@ Ewa Czechowska <ewa@ai-traders.com> ...@@ -579,7 +597,9 @@ Ewa Czechowska <ewa@ai-traders.com>
Eystein Måløy Stenberg <eystein.maloy.stenberg@cfengine.com> Eystein Måløy Stenberg <eystein.maloy.stenberg@cfengine.com>
ezbercih <cem.ezberci@gmail.com> ezbercih <cem.ezberci@gmail.com>
Ezra Silvera <ezra@il.ibm.com> Ezra Silvera <ezra@il.ibm.com>
Fabian Kramm <kramm@covexo.com>
Fabian Lauer <kontakt@softwareschmiede-saar.de> Fabian Lauer <kontakt@softwareschmiede-saar.de>
Fabian Raetz <fabian.raetz@gmail.com>
Fabiano Rosas <farosas@br.ibm.com> Fabiano Rosas <farosas@br.ibm.com>
Fabio Falci <fabiofalci@gmail.com> Fabio Falci <fabiofalci@gmail.com>
Fabio Kung <fabio.kung@gmail.com> Fabio Kung <fabio.kung@gmail.com>
...@@ -591,6 +611,7 @@ Faiz Khan <faizkhan00@gmail.com> ...@@ -591,6 +611,7 @@ Faiz Khan <faizkhan00@gmail.com>
falmp <chico.lopes@gmail.com> falmp <chico.lopes@gmail.com>
Fangming Fang <fangming.fang@arm.com> Fangming Fang <fangming.fang@arm.com>
Fangyuan Gao <21551127@zju.edu.cn> Fangyuan Gao <21551127@zju.edu.cn>
fanjiyun <fan.jiyun@zte.com.cn>
Fareed Dudhia <fareeddudhia@googlemail.com> Fareed Dudhia <fareeddudhia@googlemail.com>
Fathi Boudra <fathi.boudra@linaro.org> Fathi Boudra <fathi.boudra@linaro.org>
Federico Gimenez <fgimenez@coit.es> Federico Gimenez <fgimenez@coit.es>
...@@ -621,6 +642,7 @@ Florin Patan <florinpatan@gmail.com> ...@@ -621,6 +642,7 @@ Florin Patan <florinpatan@gmail.com>
fonglh <fonglh@gmail.com> fonglh <fonglh@gmail.com>
Foysal Iqbal <foysal.iqbal.fb@gmail.com> Foysal Iqbal <foysal.iqbal.fb@gmail.com>
Francesc Campoy <campoy@google.com> Francesc Campoy <campoy@google.com>
Francesco Mari <mari.francesco@gmail.com>
Francis Chuang <francis.chuang@boostport.com> Francis Chuang <francis.chuang@boostport.com>
Francisco Carriedo <fcarriedo@gmail.com> Francisco Carriedo <fcarriedo@gmail.com>
Francisco Souza <f@souza.cc> Francisco Souza <f@souza.cc>
...@@ -653,6 +675,7 @@ Gaël PORTAY <gael.portay@savoirfairelinux.com> ...@@ -653,6 +675,7 @@ Gaël PORTAY <gael.portay@savoirfairelinux.com>
Genki Takiuchi <genki@s21g.com> Genki Takiuchi <genki@s21g.com>
GennadySpb <lipenkov@gmail.com> GennadySpb <lipenkov@gmail.com>
Geoffrey Bachelet <grosfrais@gmail.com> Geoffrey Bachelet <grosfrais@gmail.com>
Geon Kim <geon0250@gmail.com>
George Kontridze <george@bugsnag.com> George Kontridze <george@bugsnag.com>
George MacRorie <gmacr31@gmail.com> George MacRorie <gmacr31@gmail.com>
George Xie <georgexsh@gmail.com> George Xie <georgexsh@gmail.com>
...@@ -676,6 +699,7 @@ Gopikannan Venugopalsamy <gopikannan.venugopalsamy@gmail.com> ...@@ -676,6 +699,7 @@ Gopikannan Venugopalsamy <gopikannan.venugopalsamy@gmail.com>
Gosuke Miyashita <gosukenator@gmail.com> Gosuke Miyashita <gosukenator@gmail.com>
Gou Rao <gou@portworx.com> Gou Rao <gou@portworx.com>
Govinda Fichtner <govinda.fichtner@googlemail.com> Govinda Fichtner <govinda.fichtner@googlemail.com>
Grant Millar <grant@cylo.io>
Grant Reaber <grant.reaber@gmail.com> Grant Reaber <grant.reaber@gmail.com>
Graydon Hoare <graydon@pobox.com> Graydon Hoare <graydon@pobox.com>
Greg Fausak <greg@tacodata.com> Greg Fausak <greg@tacodata.com>
...@@ -694,7 +718,9 @@ Guruprasad <lgp171188@gmail.com> ...@@ -694,7 +718,9 @@ Guruprasad <lgp171188@gmail.com>
Gustav Sinder <gustav.sinder@gmail.com> Gustav Sinder <gustav.sinder@gmail.com>
gwx296173 <gaojing3@huawei.com> gwx296173 <gaojing3@huawei.com>
Günter Zöchbauer <guenter@gzoechbauer.com> Günter Zöchbauer <guenter@gzoechbauer.com>
haikuoliu <haikuo@amazon.com>
Hakan Özler <hakan.ozler@kodcu.com> Hakan Özler <hakan.ozler@kodcu.com>
Hamish Hutchings <moredhel@aoeu.me>
Hans Kristian Flaatten <hans@starefossen.com> Hans Kristian Flaatten <hans@starefossen.com>
Hans Rødtang <hansrodtang@gmail.com> Hans Rødtang <hansrodtang@gmail.com>
Hao Shu Wei <haosw@cn.ibm.com> Hao Shu Wei <haosw@cn.ibm.com>
...@@ -702,6 +728,7 @@ Hao Zhang <21521210@zju.edu.cn> ...@@ -702,6 +728,7 @@ Hao Zhang <21521210@zju.edu.cn>
Harald Albers <github@albersweb.de> Harald Albers <github@albersweb.de>
Harley Laue <losinggeneration@gmail.com> Harley Laue <losinggeneration@gmail.com>
Harold Cooper <hrldcpr@gmail.com> Harold Cooper <hrldcpr@gmail.com>
Harrison Turton <harrisonturton@gmail.com>
Harry Zhang <harryz@hyper.sh> Harry Zhang <harryz@hyper.sh>
Harshal Patil <harshal.patil@in.ibm.com> Harshal Patil <harshal.patil@in.ibm.com>
Harshal Patil <harshalp@linux.vnet.ibm.com> Harshal Patil <harshalp@linux.vnet.ibm.com>
...@@ -713,6 +740,7 @@ Hector Castro <hectcastro@gmail.com> ...@@ -713,6 +740,7 @@ Hector Castro <hectcastro@gmail.com>
Helen Xie <chenjg@harmonycloud.cn> Helen Xie <chenjg@harmonycloud.cn>
Henning Sprang <henning.sprang@gmail.com> Henning Sprang <henning.sprang@gmail.com>
Hiroshi Hatake <hatake@clear-code.com> Hiroshi Hatake <hatake@clear-code.com>
Hiroyuki Sasagawa <hs19870702@gmail.com>
Hobofan <goisser94@gmail.com> Hobofan <goisser94@gmail.com>
Hollie Teal <hollie@docker.com> Hollie Teal <hollie@docker.com>
Hong Xu <hong@topbug.net> Hong Xu <hong@topbug.net>
...@@ -735,6 +763,7 @@ Ian Bishop <ianbishop@pace7.com> ...@@ -735,6 +763,7 @@ Ian Bishop <ianbishop@pace7.com>
Ian Bull <irbull@gmail.com> Ian Bull <irbull@gmail.com>
Ian Calvert <ianjcalvert@gmail.com> Ian Calvert <ianjcalvert@gmail.com>
Ian Campbell <ian.campbell@docker.com> Ian Campbell <ian.campbell@docker.com>
Ian Chen <ianre657@gmail.com>
Ian Lee <IanLee1521@gmail.com> Ian Lee <IanLee1521@gmail.com>
Ian Main <imain@redhat.com> Ian Main <imain@redhat.com>
Ian Philpot <ian.philpot@microsoft.com> Ian Philpot <ian.philpot@microsoft.com>
...@@ -752,9 +781,11 @@ Ilya Khlopotov <ilya.khlopotov@gmail.com> ...@@ -752,9 +781,11 @@ Ilya Khlopotov <ilya.khlopotov@gmail.com>
imre Fitos <imre.fitos+github@gmail.com> imre Fitos <imre.fitos+github@gmail.com>
inglesp <peter.inglesby@gmail.com> inglesp <peter.inglesby@gmail.com>
Ingo Gottwald <in.gottwald@gmail.com> Ingo Gottwald <in.gottwald@gmail.com>
Innovimax <innovimax@gmail.com>
Isaac Dupree <antispam@idupree.com> Isaac Dupree <antispam@idupree.com>
Isabel Jimenez <contact.isabeljimenez@gmail.com> Isabel Jimenez <contact.isabeljimenez@gmail.com>
Isao Jonas <isao.jonas@gmail.com> Isao Jonas <isao.jonas@gmail.com>
Iskander Sharipov <quasilyte@gmail.com>
Ivan Babrou <ibobrik@gmail.com> Ivan Babrou <ibobrik@gmail.com>
Ivan Fraixedes <ifcdev@gmail.com> Ivan Fraixedes <ifcdev@gmail.com>
Ivan Grcic <igrcic@gmail.com> Ivan Grcic <igrcic@gmail.com>
...@@ -785,6 +816,7 @@ James Mills <prologic@shortcircuit.net.au> ...@@ -785,6 +816,7 @@ James Mills <prologic@shortcircuit.net.au>
James Nesbitt <james.nesbitt@wunderkraut.com> James Nesbitt <james.nesbitt@wunderkraut.com>
James Nugent <james@jen20.com> James Nugent <james@jen20.com>
James Turnbull <james@lovedthanlost.net> James Turnbull <james@lovedthanlost.net>
James Watkins-Harvey <jwatkins@progi-media.com>
Jamie Hannaford <jamie@limetree.org> Jamie Hannaford <jamie@limetree.org>
Jamshid Afshar <jafshar@yahoo.com> Jamshid Afshar <jafshar@yahoo.com>
Jan Keromnes <janx@linux.com> Jan Keromnes <janx@linux.com>
...@@ -817,6 +849,7 @@ jaxgeller <jacksongeller@gmail.com> ...@@ -817,6 +849,7 @@ jaxgeller <jacksongeller@gmail.com>
Jay <imjching@hotmail.com> Jay <imjching@hotmail.com>
Jay <teguhwpurwanto@gmail.com> Jay <teguhwpurwanto@gmail.com>
Jay Kamat <github@jgkamat.33mail.com> Jay Kamat <github@jgkamat.33mail.com>
Jean Rouge <rougej+github@gmail.com>
Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com> Jean-Baptiste Barth <jeanbaptiste.barth@gmail.com>
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com> Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
Jean-Christophe Berthon <huygens@berthon.eu> Jean-Christophe Berthon <huygens@berthon.eu>
...@@ -847,11 +880,13 @@ Jeroen Franse <jeroenfranse@gmail.com> ...@@ -847,11 +880,13 @@ Jeroen Franse <jeroenfranse@gmail.com>
Jeroen Jacobs <github@jeroenj.be> Jeroen Jacobs <github@jeroenj.be>
Jesse Dearing <jesse.dearing@gmail.com> Jesse Dearing <jesse.dearing@gmail.com>
Jesse Dubay <jesse@thefortytwo.net> Jesse Dubay <jesse@thefortytwo.net>
Jessica Frazelle <jessfraz@google.com> Jessica Frazelle <acidburn@microsoft.com>
Jezeniel Zapanta <jpzapanta22@gmail.com> Jezeniel Zapanta <jpzapanta22@gmail.com>
Jhon Honce <jhonce@redhat.com> Jhon Honce <jhonce@redhat.com>
Ji.Zhilong <zhilongji@gmail.com> Ji.Zhilong <zhilongji@gmail.com>
Jian Liao <jliao@alauda.io>
Jian Zhang <zhangjian.fnst@cn.fujitsu.com> Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
Jiang Jinyang <jjyruby@gmail.com>
Jie Luo <luo612@zju.edu.cn> Jie Luo <luo612@zju.edu.cn>
Jihyun Hwang <jhhwang@telcoware.com> Jihyun Hwang <jhhwang@telcoware.com>
Jilles Oldenbeuving <ojilles@gmail.com> Jilles Oldenbeuving <ojilles@gmail.com>
...@@ -862,14 +897,13 @@ Jim Perrin <jperrin@centos.org> ...@@ -862,14 +897,13 @@ Jim Perrin <jperrin@centos.org>
Jimmy Cuadra <jimmy@jimmycuadra.com> Jimmy Cuadra <jimmy@jimmycuadra.com>
Jimmy Puckett <jimmy.puckett@spinen.com> Jimmy Puckett <jimmy.puckett@spinen.com>
Jimmy Song <rootsongjc@gmail.com> Jimmy Song <rootsongjc@gmail.com>
jimmyxian <jimmyxian2004@yahoo.com.cn>
Jinsoo Park <cellpjs@gmail.com> Jinsoo Park <cellpjs@gmail.com>
Jiri Appl <jiria@microsoft.com>
Jiri Popelka <jpopelka@redhat.com> Jiri Popelka <jpopelka@redhat.com>
Jiuyue Ma <majiuyue@huawei.com> Jiuyue Ma <majiuyue@huawei.com>
Jiří Župka <jzupka@redhat.com> Jiří Župka <jzupka@redhat.com>
jjy <jiangjinyang@outlook.com>
jmzwcn <jmzwcn@gmail.com>
Joao Fernandes <joao.fernandes@docker.com> Joao Fernandes <joao.fernandes@docker.com>
Joao Trindade <trindade.joao@gmail.com>
Joe Beda <joe.github@bedafamily.com> Joe Beda <joe.github@bedafamily.com>
Joe Doliner <jdoliner@pachyderm.io> Joe Doliner <jdoliner@pachyderm.io>
Joe Ferguson <joe@infosiftr.com> Joe Ferguson <joe@infosiftr.com>
...@@ -908,6 +942,7 @@ Jon Johnson <jonjohnson@google.com> ...@@ -908,6 +942,7 @@ Jon Johnson <jonjohnson@google.com>
Jon Surrell <jon.surrell@gmail.com> Jon Surrell <jon.surrell@gmail.com>
Jon Wedaman <jweede@gmail.com> Jon Wedaman <jweede@gmail.com>
Jonas Pfenniger <jonas@pfenniger.name> Jonas Pfenniger <jonas@pfenniger.name>
Jonathan A. Schweder <jonathanschweder@gmail.com>
Jonathan A. Sternberg <jonathansternberg@gmail.com> Jonathan A. Sternberg <jonathansternberg@gmail.com>
Jonathan Boulle <jonathanboulle@gmail.com> Jonathan Boulle <jonathanboulle@gmail.com>
Jonathan Camp <jonathan@irondojo.com> Jonathan Camp <jonathan@irondojo.com>
...@@ -928,7 +963,7 @@ Jordan Jennings <jjn2009@gmail.com> ...@@ -928,7 +963,7 @@ Jordan Jennings <jjn2009@gmail.com>
Jordan Sissel <jls@semicomplete.com> Jordan Sissel <jls@semicomplete.com>
Jorge Marin <chipironcin@users.noreply.github.com> Jorge Marin <chipironcin@users.noreply.github.com>
Jorit Kleine-Möllhoff <joppich@bricknet.de> Jorit Kleine-Möllhoff <joppich@bricknet.de>
Jose Diaz-Gonzalez <jose@seatgeek.com> Jose Diaz-Gonzalez <email@josediazgonzalez.com>
Joseph Anthony Pasquale Holsten <joseph@josephholsten.com> Joseph Anthony Pasquale Holsten <joseph@josephholsten.com>
Joseph Hager <ajhager@gmail.com> Joseph Hager <ajhager@gmail.com>
Joseph Kern <jkern@semafour.net> Joseph Kern <jkern@semafour.net>
...@@ -982,7 +1017,8 @@ kargakis <kargakis@users.noreply.github.com> ...@@ -982,7 +1017,8 @@ kargakis <kargakis@users.noreply.github.com>
Karl Grzeszczak <karlgrz@gmail.com> Karl Grzeszczak <karlgrz@gmail.com>
Karol Duleba <mr.fuxi@gmail.com> Karol Duleba <mr.fuxi@gmail.com>
Karthik Karanth <karanth.karthik@gmail.com> Karthik Karanth <karanth.karthik@gmail.com>
Karthik Nayak <Karthik.188@gmail.com> Karthik Nayak <karthik.188@gmail.com>
Kasper Fabæch Brandt <poizan@poizan.dk>
Kate Heddleston <kate.heddleston@gmail.com> Kate Heddleston <kate.heddleston@gmail.com>
Katie McLaughlin <katie@glasnt.com> Katie McLaughlin <katie@glasnt.com>
Kato Kazuyoshi <kato.kazuyoshi@gmail.com> Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
...@@ -990,6 +1026,7 @@ Katrina Owen <katrina.owen@gmail.com> ...@@ -990,6 +1026,7 @@ Katrina Owen <katrina.owen@gmail.com>
Kawsar Saiyeed <kawsar.saiyeed@projiris.com> Kawsar Saiyeed <kawsar.saiyeed@projiris.com>
Kay Yan <kay.yan@daocloud.io> Kay Yan <kay.yan@daocloud.io>
kayrus <kay.diam@gmail.com> kayrus <kay.diam@gmail.com>
Kazuhiro Sera <seratch@gmail.com>
Ke Li <kel@splunk.com> Ke Li <kel@splunk.com>
Ke Xu <leonhartx.k@gmail.com> Ke Xu <leonhartx.k@gmail.com>
Kei Ohmura <ohmura.kei@gmail.com> Kei Ohmura <ohmura.kei@gmail.com>
...@@ -998,6 +1035,7 @@ Keli Hu <dev@keli.hu> ...@@ -998,6 +1035,7 @@ Keli Hu <dev@keli.hu>
Ken Cochrane <kencochrane@gmail.com> Ken Cochrane <kencochrane@gmail.com>
Ken Herner <kherner@progress.com> Ken Herner <kherner@progress.com>
Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com> Ken ICHIKAWA <ichikawa.ken@jp.fujitsu.com>
Ken Reese <krrgithub@gmail.com>
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com> Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
Kenjiro Nakayama <nakayamakenjiro@gmail.com> Kenjiro Nakayama <nakayamakenjiro@gmail.com>
Kent Johnson <kentoj@gmail.com> Kent Johnson <kentoj@gmail.com>
...@@ -1035,9 +1073,10 @@ Krasimir Georgiev <support@vip-consult.co.uk> ...@@ -1035,9 +1073,10 @@ Krasimir Georgiev <support@vip-consult.co.uk>
Kris-Mikael Krister <krismikael@protonmail.com> Kris-Mikael Krister <krismikael@protonmail.com>
Kristian Haugene <kristian.haugene@capgemini.com> Kristian Haugene <kristian.haugene@capgemini.com>
Kristina Zabunova <triara.xiii@gmail.com> Kristina Zabunova <triara.xiii@gmail.com>
krrg <krrgithub@gmail.com> Krystian Wojcicki <kwojcicki@sympatico.ca>
Kun Zhang <zkazure@gmail.com> Kun Zhang <zkazure@gmail.com>
Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp> Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp>
Kunal Tyagi <tyagi.kunal@live.com>
Kyle Conroy <kyle.j.conroy@gmail.com> Kyle Conroy <kyle.j.conroy@gmail.com>
Kyle Linden <linden.kyle@gmail.com> Kyle Linden <linden.kyle@gmail.com>
kyu <leehk1227@gmail.com> kyu <leehk1227@gmail.com>
...@@ -1060,6 +1099,7 @@ Leandro Siqueira <leandro.siqueira@gmail.com> ...@@ -1060,6 +1099,7 @@ Leandro Siqueira <leandro.siqueira@gmail.com>
Lee Chao <932819864@qq.com> Lee Chao <932819864@qq.com>
Lee, Meng-Han <sunrisedm4@gmail.com> Lee, Meng-Han <sunrisedm4@gmail.com>
leeplay <hyeongkyu.lee@navercorp.com> leeplay <hyeongkyu.lee@navercorp.com>
Lei Gong <lgong@alauda.io>
Lei Jitang <leijitang@huawei.com> Lei Jitang <leijitang@huawei.com>
Len Weincier <len@cloudafrica.net> Len Weincier <len@cloudafrica.net>
Lennie <github@consolejunkie.net> Lennie <github@consolejunkie.net>
...@@ -1076,6 +1116,8 @@ Liana Lo <liana.lixia@gmail.com> ...@@ -1076,6 +1116,8 @@ Liana Lo <liana.lixia@gmail.com>
Liang Mingqiang <mqliang.zju@gmail.com> Liang Mingqiang <mqliang.zju@gmail.com>
Liang-Chi Hsieh <viirya@gmail.com> Liang-Chi Hsieh <viirya@gmail.com>
Liao Qingwei <liaoqingwei@huawei.com> Liao Qingwei <liaoqingwei@huawei.com>
Lifubang <lifubang@acmcoder.com>
Lihua Tang <lhtang@alauda.io>
Lily Guo <lily.guo@docker.com> Lily Guo <lily.guo@docker.com>
limsy <seongyeol37@gmail.com> limsy <seongyeol37@gmail.com>
Lin Lu <doraalin@163.com> Lin Lu <doraalin@163.com>
...@@ -1094,7 +1136,8 @@ Lloyd Dewolf <foolswisdom@gmail.com> ...@@ -1094,7 +1136,8 @@ Lloyd Dewolf <foolswisdom@gmail.com>
Lokesh Mandvekar <lsm5@fedoraproject.org> Lokesh Mandvekar <lsm5@fedoraproject.org>
longliqiang88 <394564827@qq.com> longliqiang88 <394564827@qq.com>
Lorenz Leutgeb <lorenz.leutgeb@gmail.com> Lorenz Leutgeb <lorenz.leutgeb@gmail.com>
Lorenzo Fontana <lo@linux.com> Lorenzo Fontana <fontanalorenz@gmail.com>
Lotus Fenn <fenn.lotus@gmail.com>
Louis Opter <kalessin@kalessin.fr> Louis Opter <kalessin@kalessin.fr>
Luca Favatella <luca.favatella@erlang-solutions.com> Luca Favatella <luca.favatella@erlang-solutions.com>
Luca Marturana <lucamarturana@gmail.com> Luca Marturana <lucamarturana@gmail.com>
...@@ -1151,6 +1194,7 @@ Marius Gundersen <me@mariusgundersen.net> ...@@ -1151,6 +1194,7 @@ Marius Gundersen <me@mariusgundersen.net>
Marius Sturm <marius@graylog.com> Marius Sturm <marius@graylog.com>
Marius Voila <marius.voila@gmail.com> Marius Voila <marius.voila@gmail.com>
Mark Allen <mrallen1@yahoo.com> Mark Allen <mrallen1@yahoo.com>
Mark Jeromin <mark.jeromin@sysfrog.net>
Mark McGranaghan <mmcgrana@gmail.com> Mark McGranaghan <mmcgrana@gmail.com>
Mark McKinstry <mmckinst@umich.edu> Mark McKinstry <mmckinst@umich.edu>
Mark Milstein <mark@epiloque.com> Mark Milstein <mark@epiloque.com>
...@@ -1167,6 +1211,7 @@ Martijn van Oosterhout <kleptog@svana.org> ...@@ -1167,6 +1211,7 @@ Martijn van Oosterhout <kleptog@svana.org>
Martin Honermeyer <maze@strahlungsfrei.de> Martin Honermeyer <maze@strahlungsfrei.de>
Martin Kelly <martin@surround.io> Martin Kelly <martin@surround.io>
Martin Mosegaard Amdisen <martin.amdisen@praqma.com> Martin Mosegaard Amdisen <martin.amdisen@praqma.com>
Martin Muzatko <martin@happy-css.com>
Martin Redmond <redmond.martin@gmail.com> Martin Redmond <redmond.martin@gmail.com>
Mary Anthony <mary.anthony@docker.com> Mary Anthony <mary.anthony@docker.com>
Masahito Zembutsu <zembutsu@users.noreply.github.com> Masahito Zembutsu <zembutsu@users.noreply.github.com>
...@@ -1200,6 +1245,7 @@ Matthias Klumpp <matthias@tenstral.net> ...@@ -1200,6 +1245,7 @@ Matthias Klumpp <matthias@tenstral.net>
Matthias Kühnle <git.nivoc@neverbox.com> Matthias Kühnle <git.nivoc@neverbox.com>
Matthias Rampke <mr@soundcloud.com> Matthias Rampke <mr@soundcloud.com>
Matthieu Hauglustaine <matt.hauglustaine@gmail.com> Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
Mattias Jernberg <nostrad@gmail.com>
Mauricio Garavaglia <mauricio@medallia.com> Mauricio Garavaglia <mauricio@medallia.com>
mauriyouth <mauriyouth@gmail.com> mauriyouth <mauriyouth@gmail.com>
Max Shytikov <mshytikov@gmail.com> Max Shytikov <mshytikov@gmail.com>
...@@ -1208,6 +1254,7 @@ Maxim Ivanov <ivanov.maxim@gmail.com> ...@@ -1208,6 +1254,7 @@ Maxim Ivanov <ivanov.maxim@gmail.com>
Maxim Kulkin <mkulkin@mirantis.com> Maxim Kulkin <mkulkin@mirantis.com>
Maxim Treskin <zerthurd@gmail.com> Maxim Treskin <zerthurd@gmail.com>
Maxime Petazzoni <max@signalfuse.com> Maxime Petazzoni <max@signalfuse.com>
Maximiliano Maccanti <maccanti@amazon.com>
Meaglith Ma <genedna@gmail.com> Meaglith Ma <genedna@gmail.com>
meejah <meejah@meejah.ca> meejah <meejah@meejah.ca>
Megan Kostick <mkostick@us.ibm.com> Megan Kostick <mkostick@us.ibm.com>
...@@ -1248,8 +1295,9 @@ Michal Wieczorek <wieczorek-michal@wp.pl> ...@@ -1248,8 +1295,9 @@ Michal Wieczorek <wieczorek-michal@wp.pl>
Michaël Pailloncy <mpapo.dev@gmail.com> Michaël Pailloncy <mpapo.dev@gmail.com>
Michał Czeraszkiewicz <czerasz@gmail.com> Michał Czeraszkiewicz <czerasz@gmail.com>
Michał Gryko <github@odkurzacz.org> Michał Gryko <github@odkurzacz.org>
Michiel@unhosted <michiel@unhosted.org> Michiel de Jong <michiel@unhosted.org>
Mickaël FORTUNATO <morsi.morsicus@gmail.com> Mickaël Fortunato <morsi.morsicus@gmail.com>
Mickaël Remars <mickael@remars.com>
Miguel Angel Fernández <elmendalerenda@gmail.com> Miguel Angel Fernández <elmendalerenda@gmail.com>
Miguel Morales <mimoralea@gmail.com> Miguel Morales <mimoralea@gmail.com>
Mihai Borobocea <MihaiBorob@gmail.com> Mihai Borobocea <MihaiBorob@gmail.com>
...@@ -1280,6 +1328,7 @@ Mitch Capper <mitch.capper@gmail.com> ...@@ -1280,6 +1328,7 @@ Mitch Capper <mitch.capper@gmail.com>
Mizuki Urushida <z11111001011@gmail.com> Mizuki Urushida <z11111001011@gmail.com>
mlarcher <github@ringabell.org> mlarcher <github@ringabell.org>
Mohammad Banikazemi <mb@us.ibm.com> Mohammad Banikazemi <mb@us.ibm.com>
Mohammad Nasirifar <farnasirim@gmail.com>
Mohammed Aaqib Ansari <maaquib@gmail.com> Mohammed Aaqib Ansari <maaquib@gmail.com>
Mohit Soni <mosoni@ebay.com> Mohit Soni <mosoni@ebay.com>
Moorthy RS <rsmoorthy@gmail.com> Moorthy RS <rsmoorthy@gmail.com>
...@@ -1304,6 +1353,7 @@ Nan Monnand Deng <monnand@gmail.com> ...@@ -1304,6 +1353,7 @@ Nan Monnand Deng <monnand@gmail.com>
Naoki Orii <norii@cs.cmu.edu> Naoki Orii <norii@cs.cmu.edu>
Natalie Parker <nparker@omnifone.com> Natalie Parker <nparker@omnifone.com>
Natanael Copa <natanael.copa@docker.com> Natanael Copa <natanael.copa@docker.com>
Natasha Jarus <linuxmercedes@gmail.com>
Nate Brennand <nate.brennand@clever.com> Nate Brennand <nate.brennand@clever.com>
Nate Eagleson <nate@nateeag.com> Nate Eagleson <nate@nateeag.com>
Nate Jones <nate@endot.org> Nate Jones <nate@endot.org>
...@@ -1337,6 +1387,7 @@ Nicolas Dudebout <nicolas.dudebout@gatech.edu> ...@@ -1337,6 +1387,7 @@ Nicolas Dudebout <nicolas.dudebout@gatech.edu>
Nicolas Goy <kuon@goyman.com> Nicolas Goy <kuon@goyman.com>
Nicolas Kaiser <nikai@nikai.net> Nicolas Kaiser <nikai@nikai.net>
Nicolas Sterchele <sterchele.nicolas@gmail.com> Nicolas Sterchele <sterchele.nicolas@gmail.com>
Nicolas V Castet <nvcastet@us.ibm.com>
Nicolás Hock Isaza <nhocki@gmail.com> Nicolás Hock Isaza <nhocki@gmail.com>
Nigel Poulton <nigelpoulton@hotmail.com> Nigel Poulton <nigelpoulton@hotmail.com>
Nik Nyby <nikolas@gnu.org> Nik Nyby <nikolas@gnu.org>
...@@ -1352,6 +1403,7 @@ Noah Treuhaft <noah.treuhaft@docker.com> ...@@ -1352,6 +1403,7 @@ Noah Treuhaft <noah.treuhaft@docker.com>
NobodyOnSE <ich@sektor.selfip.com> NobodyOnSE <ich@sektor.selfip.com>
noducks <onemannoducks@gmail.com> noducks <onemannoducks@gmail.com>
Nolan Darilek <nolan@thewordnerd.info> Nolan Darilek <nolan@thewordnerd.info>
Noriki Nakamura <noriki.nakamura@miraclelinux.com>
nponeccop <andy.melnikov@gmail.com> nponeccop <andy.melnikov@gmail.com>
Nuutti Kotivuori <naked@iki.fi> Nuutti Kotivuori <naked@iki.fi>
nzwsch <hi@nzwsch.com> nzwsch <hi@nzwsch.com>
...@@ -1363,8 +1415,11 @@ Ohad Schneider <ohadschn@users.noreply.github.com> ...@@ -1363,8 +1415,11 @@ Ohad Schneider <ohadschn@users.noreply.github.com>
ohmystack <jun.jiang02@ele.me> ohmystack <jun.jiang02@ele.me>
Ole Reifschneider <mail@ole-reifschneider.de> Ole Reifschneider <mail@ole-reifschneider.de>
Oliver Neal <ItsVeryWindy@users.noreply.github.com> Oliver Neal <ItsVeryWindy@users.noreply.github.com>
Oliver Reason <oli@overrateddev.co>
Olivier Gambier <dmp42@users.noreply.github.com> Olivier Gambier <dmp42@users.noreply.github.com>
Olle Jonsson <olle.jonsson@gmail.com> Olle Jonsson <olle.jonsson@gmail.com>
Olli Janatuinen <olli.janatuinen@gmail.com>
Omri Shiv <Omri.Shiv@teradata.com>
Oriol Francès <oriolfa@gmail.com> Oriol Francès <oriolfa@gmail.com>
Oskar Niburski <oskarniburski@gmail.com> Oskar Niburski <oskarniburski@gmail.com>
Otto Kekäläinen <otto@seravo.fi> Otto Kekäläinen <otto@seravo.fi>
...@@ -1420,6 +1475,7 @@ Peter Edge <peter.edge@gmail.com> ...@@ -1420,6 +1475,7 @@ Peter Edge <peter.edge@gmail.com>
Peter Ericson <pdericson@gmail.com> Peter Ericson <pdericson@gmail.com>
Peter Esbensen <pkesbensen@gmail.com> Peter Esbensen <pkesbensen@gmail.com>
Peter Jaffe <pjaffe@nevo.com> Peter Jaffe <pjaffe@nevo.com>
Peter Kang <peter@spell.run>
Peter Malmgren <ptmalmgren@gmail.com> Peter Malmgren <ptmalmgren@gmail.com>
Peter Salvatore <peter@psftw.com> Peter Salvatore <peter@psftw.com>
Peter Volpe <petervo@redhat.com> Peter Volpe <petervo@redhat.com>
...@@ -1452,6 +1508,7 @@ Prasanna Gautam <prasannagautam@gmail.com> ...@@ -1452,6 +1508,7 @@ Prasanna Gautam <prasannagautam@gmail.com>
Pratik Karki <prertik@outlook.com> Pratik Karki <prertik@outlook.com>
Prayag Verma <prayag.verma@gmail.com> Prayag Verma <prayag.verma@gmail.com>
Priya Wadhwa <priyawadhwa@google.com> Priya Wadhwa <priyawadhwa@google.com>
Projjol Banerji <probaner23@gmail.com>
Przemek Hejman <przemyslaw.hejman@gmail.com> Przemek Hejman <przemyslaw.hejman@gmail.com>
Pure White <daniel48@126.com> Pure White <daniel48@126.com>
pysqz <randomq@126.com> pysqz <randomq@126.com>
...@@ -1475,6 +1532,7 @@ Ralph Bean <rbean@redhat.com> ...@@ -1475,6 +1532,7 @@ Ralph Bean <rbean@redhat.com>
Ramkumar Ramachandra <artagnon@gmail.com> Ramkumar Ramachandra <artagnon@gmail.com>
Ramon Brooker <rbrooker@aetherealmind.com> Ramon Brooker <rbrooker@aetherealmind.com>
Ramon van Alteren <ramon@vanalteren.nl> Ramon van Alteren <ramon@vanalteren.nl>
RaviTeja Pothana <ravi-teja@live.com>
Ray Tsang <rayt@google.com> Ray Tsang <rayt@google.com>
ReadmeCritic <frankensteinbot@gmail.com> ReadmeCritic <frankensteinbot@gmail.com>
Recursive Madman <recursive.madman@gmx.de> Recursive Madman <recursive.madman@gmx.de>
...@@ -1524,6 +1582,7 @@ Roel Van Nyen <roel.vannyen@gmail.com> ...@@ -1524,6 +1582,7 @@ Roel Van Nyen <roel.vannyen@gmail.com>
Roger Peppe <rogpeppe@gmail.com> Roger Peppe <rogpeppe@gmail.com>
Rohit Jnagal <jnagal@google.com> Rohit Jnagal <jnagal@google.com>
Rohit Kadam <rohit.d.kadam@gmail.com> Rohit Kadam <rohit.d.kadam@gmail.com>
Rohit Kapur <rkapur@flatiron.com>
Rojin George <rojingeorge@huawei.com> Rojin George <rojingeorge@huawei.com>
Roland Huß <roland@jolokia.org> Roland Huß <roland@jolokia.org>
Roland Kammerer <roland.kammerer@linbit.com> Roland Kammerer <roland.kammerer@linbit.com>
...@@ -1533,6 +1592,9 @@ Roman Dudin <katrmr@gmail.com> ...@@ -1533,6 +1592,9 @@ Roman Dudin <katrmr@gmail.com>
Roman Strashkin <roman.strashkin@gmail.com> Roman Strashkin <roman.strashkin@gmail.com>
Ron Smits <ron.smits@gmail.com> Ron Smits <ron.smits@gmail.com>
Ron Williams <ron.a.williams@gmail.com> Ron Williams <ron.a.williams@gmail.com>
Rong Gao <gaoronggood@163.com>
Rong Zhang <rongzhang@alauda.io>
Rongxiang Song <tinysong1226@gmail.com>
root <docker-dummy@example.com> root <docker-dummy@example.com>
root <root@lxdebmas.marist.edu> root <root@lxdebmas.marist.edu>
root <root@ubuntu-14.04-amd64-vbox> root <root@ubuntu-14.04-amd64-vbox>
...@@ -1544,8 +1606,10 @@ Rovanion Luckey <rovanion.luckey@gmail.com> ...@@ -1544,8 +1606,10 @@ Rovanion Luckey <rovanion.luckey@gmail.com>
Royce Remer <royceremer@gmail.com> Royce Remer <royceremer@gmail.com>
Rozhnov Alexandr <nox73@ya.ru> Rozhnov Alexandr <nox73@ya.ru>
Rudolph Gottesheim <r.gottesheim@loot.at> Rudolph Gottesheim <r.gottesheim@loot.at>
Rui Cao <ruicao@alauda.io>
Rui Lopes <rgl@ruilopes.com> Rui Lopes <rgl@ruilopes.com>
Runshen Zhu <runshen.zhu@gmail.com> Runshen Zhu <runshen.zhu@gmail.com>
Russ Magee <rmagee@gmail.com>
Ryan Abrams <rdabrams@gmail.com> Ryan Abrams <rdabrams@gmail.com>
Ryan Anderson <anderson.ryanc@gmail.com> Ryan Anderson <anderson.ryanc@gmail.com>
Ryan Aslett <github@mixologic.com> Ryan Aslett <github@mixologic.com>
...@@ -1564,6 +1628,7 @@ Ryan Wallner <ryan.wallner@clusterhq.com> ...@@ -1564,6 +1628,7 @@ Ryan Wallner <ryan.wallner@clusterhq.com>
Ryan Zhang <ryan.zhang@docker.com> Ryan Zhang <ryan.zhang@docker.com>
ryancooper7 <ryan.cooper7@gmail.com> ryancooper7 <ryan.cooper7@gmail.com>
RyanDeng <sheldon.d1018@gmail.com> RyanDeng <sheldon.d1018@gmail.com>
Ryo Nakao <nakabonne@gmail.com>
Rémy Greinhofer <remy.greinhofer@livelovely.com> Rémy Greinhofer <remy.greinhofer@livelovely.com>
s. rannou <mxs@sbrk.org> s. rannou <mxs@sbrk.org>
s00318865 <sunyuan3@huawei.com> s00318865 <sunyuan3@huawei.com>
...@@ -1572,6 +1637,7 @@ Sachin Joshi <sachin_jayant_joshi@hotmail.com> ...@@ -1572,6 +1637,7 @@ Sachin Joshi <sachin_jayant_joshi@hotmail.com>
Sagar Hani <sagarhani33@gmail.com> Sagar Hani <sagarhani33@gmail.com>
Sainath Grandhi <sainath.grandhi@intel.com> Sainath Grandhi <sainath.grandhi@intel.com>
Sakeven Jiang <jc5930@sina.cn> Sakeven Jiang <jc5930@sina.cn>
Salahuddin Khan <salah@docker.com>
Sally O'Malley <somalley@redhat.com> Sally O'Malley <somalley@redhat.com>
Sam Abed <sam.abed@gmail.com> Sam Abed <sam.abed@gmail.com>
Sam Alba <sam.alba@gmail.com> Sam Alba <sam.alba@gmail.com>
...@@ -1593,6 +1659,7 @@ Santhosh Manohar <santhosh@docker.com> ...@@ -1593,6 +1659,7 @@ Santhosh Manohar <santhosh@docker.com>
sapphiredev <se.imas.kr@gmail.com> sapphiredev <se.imas.kr@gmail.com>
Sargun Dhillon <sargun@netflix.com> Sargun Dhillon <sargun@netflix.com>
Sascha Andres <sascha.andres@outlook.com> Sascha Andres <sascha.andres@outlook.com>
Sascha Grunert <sgrunert@suse.com>
Satnam Singh <satnam@raintown.org> Satnam Singh <satnam@raintown.org>
Satoshi Amemiya <satoshi_amemiya@voyagegroup.com> Satoshi Amemiya <satoshi_amemiya@voyagegroup.com>
Satoshi Tagomori <tagomoris@gmail.com> Satoshi Tagomori <tagomoris@gmail.com>
...@@ -1619,7 +1686,9 @@ Serge Hallyn <serge.hallyn@ubuntu.com> ...@@ -1619,7 +1686,9 @@ Serge Hallyn <serge.hallyn@ubuntu.com>
Sergey Alekseev <sergey.alekseev.minsk@gmail.com> Sergey Alekseev <sergey.alekseev.minsk@gmail.com>
Sergey Evstifeev <sergey.evstifeev@gmail.com> Sergey Evstifeev <sergey.evstifeev@gmail.com>
Sergii Kabashniuk <skabashnyuk@codenvy.com> Sergii Kabashniuk <skabashnyuk@codenvy.com>
Sergio Lopez <slp@redhat.com>
Serhat Gülçiçek <serhat25@gmail.com> Serhat Gülçiçek <serhat25@gmail.com>
SeungUkLee <lsy931106@gmail.com>
Sevki Hasirci <s@sevki.org> Sevki Hasirci <s@sevki.org>
Shane Canon <scanon@lbl.gov> Shane Canon <scanon@lbl.gov>
Shane da Silva <shane@dasilva.io> Shane da Silva <shane@dasilva.io>
...@@ -1647,6 +1716,7 @@ Sidhartha Mani <sidharthamn@gmail.com> ...@@ -1647,6 +1716,7 @@ Sidhartha Mani <sidharthamn@gmail.com>
sidharthamani <sid@rancher.com> sidharthamani <sid@rancher.com>
Silas Sewell <silas@sewell.org> Silas Sewell <silas@sewell.org>
Silvan Jegen <s.jegen@gmail.com> Silvan Jegen <s.jegen@gmail.com>
Simão Reis <smnrsti@gmail.com>
Simei He <hesimei@zju.edu.cn> Simei He <hesimei@zju.edu.cn>
Simon Eskildsen <sirup@sirupsen.com> Simon Eskildsen <sirup@sirupsen.com>
Simon Ferquel <simon.ferquel@docker.com> Simon Ferquel <simon.ferquel@docker.com>
...@@ -1714,10 +1784,11 @@ tang0th <tang0th@gmx.com> ...@@ -1714,10 +1784,11 @@ tang0th <tang0th@gmx.com>
Tangi Colin <tangicolin@gmail.com> Tangi Colin <tangicolin@gmail.com>
Tatsuki Sugiura <sugi@nemui.org> Tatsuki Sugiura <sugi@nemui.org>
Tatsushi Inagaki <e29253@jp.ibm.com> Tatsushi Inagaki <e29253@jp.ibm.com>
Taylan Isikdemir <taylani@google.com>
Taylor Jones <monitorjbl@gmail.com> Taylor Jones <monitorjbl@gmail.com>
tbonza <tylers.pile@gmail.com>
Ted M. Young <tedyoung@gmail.com> Ted M. Young <tedyoung@gmail.com>
Tehmasp Chaudhri <tehmasp@gmail.com> Tehmasp Chaudhri <tehmasp@gmail.com>
Tejaswini Duggaraju <naduggar@microsoft.com>
Tejesh Mehta <tejesh.mehta@gmail.com> Tejesh Mehta <tejesh.mehta@gmail.com>
terryding77 <550147740@qq.com> terryding77 <550147740@qq.com>
tgic <farmer1992@gmail.com> tgic <farmer1992@gmail.com>
...@@ -1811,6 +1882,7 @@ Tristan Carel <tristan@cogniteev.com> ...@@ -1811,6 +1882,7 @@ Tristan Carel <tristan@cogniteev.com>
Troy Denton <trdenton@gmail.com> Troy Denton <trdenton@gmail.com>
Tycho Andersen <tycho@docker.com> Tycho Andersen <tycho@docker.com>
Tyler Brock <tyler.brock@gmail.com> Tyler Brock <tyler.brock@gmail.com>
Tyler Brown <tylers.pile@gmail.com>
Tzu-Jung Lee <roylee17@gmail.com> Tzu-Jung Lee <roylee17@gmail.com>
uhayate <uhayate.gong@daocloud.io> uhayate <uhayate.gong@daocloud.io>
Ulysse Carion <ulyssecarion@gmail.com> Ulysse Carion <ulyssecarion@gmail.com>
...@@ -1871,6 +1943,7 @@ Wassim Dhif <wassimdhif@gmail.com> ...@@ -1871,6 +1943,7 @@ Wassim Dhif <wassimdhif@gmail.com>
Wayne Chang <wayne@neverfear.org> Wayne Chang <wayne@neverfear.org>
Wayne Song <wsong@docker.com> Wayne Song <wsong@docker.com>
Weerasak Chongnguluam <singpor@gmail.com> Weerasak Chongnguluam <singpor@gmail.com>
Wei Fu <fuweid89@gmail.com>
Wei Wu <wuwei4455@gmail.com> Wei Wu <wuwei4455@gmail.com>
Wei-Ting Kuo <waitingkuo0527@gmail.com> Wei-Ting Kuo <waitingkuo0527@gmail.com>
weipeng <weipeng@tuscloud.io> weipeng <weipeng@tuscloud.io>
...@@ -1900,17 +1973,23 @@ WiseTrem <shepelyov.g@gmail.com> ...@@ -1900,17 +1973,23 @@ WiseTrem <shepelyov.g@gmail.com>
Wolfgang Powisch <powo@powo.priv.at> Wolfgang Powisch <powo@powo.priv.at>
Wonjun Kim <wonjun.kim@navercorp.com> Wonjun Kim <wonjun.kim@navercorp.com>
xamyzhao <x.amy.zhao@gmail.com> xamyzhao <x.amy.zhao@gmail.com>
Xian Chaobo <xianchaobo@huawei.com>
Xianglin Gao <xlgao@zju.edu.cn> Xianglin Gao <xlgao@zju.edu.cn>
Xianlu Bird <xianlubird@gmail.com> Xianlu Bird <xianlubird@gmail.com>
XiaoBing Jiang <s7v7nislands@gmail.com> XiaoBing Jiang <s7v7nislands@gmail.com>
Xiaodong Zhang <a4012017@sina.com>
Xiaoxi He <xxhe@alauda.io>
Xiaoxu Chen <chenxiaoxu14@otcaix.iscas.ac.cn> Xiaoxu Chen <chenxiaoxu14@otcaix.iscas.ac.cn>
Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn> Xiaoyu Zhang <zhang.xiaoyu33@zte.com.cn>
xichengliudui <1693291525@qq.com>
xiekeyang <xiekeyang@huawei.com> xiekeyang <xiekeyang@huawei.com>
Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com>
Xinbo Weng <xihuanbo_0521@zju.edu.cn> Xinbo Weng <xihuanbo_0521@zju.edu.cn>
Xinzi Zhou <imdreamrunner@gmail.com> Xinzi Zhou <imdreamrunner@gmail.com>
Xiuming Chen <cc@cxm.cc> Xiuming Chen <cc@cxm.cc>
Xuecong Liao <satorulogic@gmail.com> Xuecong Liao <satorulogic@gmail.com>
xuzhaokui <cynicholas@gmail.com> xuzhaokui <cynicholas@gmail.com>
Yadnyawalkya Tale <ytale@redhat.com>
Yahya <ya7yaz@gmail.com> Yahya <ya7yaz@gmail.com>
YAMADA Tsuyoshi <tyamada@minimum2scp.org> YAMADA Tsuyoshi <tyamada@minimum2scp.org>
Yamasaki Masahide <masahide.y@gmail.com> Yamasaki Masahide <masahide.y@gmail.com>
...@@ -1930,6 +2009,7 @@ Yihang Ho <hoyihang5@gmail.com> ...@@ -1930,6 +2009,7 @@ Yihang Ho <hoyihang5@gmail.com>
Ying Li <ying.li@docker.com> Ying Li <ying.li@docker.com>
Yohei Ueda <yohei@jp.ibm.com> Yohei Ueda <yohei@jp.ibm.com>
Yong Tang <yong.tang.github@outlook.com> Yong Tang <yong.tang.github@outlook.com>
Yongxin Li <yxli@alauda.io>
Yongzhi Pan <panyongzhi@gmail.com> Yongzhi Pan <panyongzhi@gmail.com>
Yosef Fertel <yfertel@gmail.com> Yosef Fertel <yfertel@gmail.com>
You-Sheng Yang (楊有勝) <vicamo@gmail.com> You-Sheng Yang (楊有勝) <vicamo@gmail.com>
...@@ -1940,9 +2020,12 @@ Yu Peng <yu.peng36@zte.com.cn> ...@@ -1940,9 +2020,12 @@ Yu Peng <yu.peng36@zte.com.cn>
Yu-Ju Hong <yjhong@google.com> Yu-Ju Hong <yjhong@google.com>
Yuan Sun <sunyuan3@huawei.com> Yuan Sun <sunyuan3@huawei.com>
Yuanhong Peng <pengyuanhong@huawei.com> Yuanhong Peng <pengyuanhong@huawei.com>
Yue Zhang <zy675793960@yeah.net>
Yuhao Fang <fangyuhao@gmail.com> Yuhao Fang <fangyuhao@gmail.com>
Yuichiro Kaneko <spiketeika@gmail.com>
Yunxiang Huang <hyxqshk@vip.qq.com> Yunxiang Huang <hyxqshk@vip.qq.com>
Yurii Rashkovskii <yrashk@gmail.com> Yurii Rashkovskii <yrashk@gmail.com>
Yusuf Tarık Günaydın <yusuf_tarik@hotmail.com>
Yves Junqueira <yves.junqueira@gmail.com> Yves Junqueira <yves.junqueira@gmail.com>
Zac Dover <zdover@redhat.com> Zac Dover <zdover@redhat.com>
Zach Borboa <zachborboa@gmail.com> Zach Borboa <zachborboa@gmail.com>
...@@ -1959,8 +2042,10 @@ ZhangHang <stevezhang2014@gmail.com> ...@@ -1959,8 +2042,10 @@ ZhangHang <stevezhang2014@gmail.com>
zhangxianwei <xianwei.zw@alibaba-inc.com> zhangxianwei <xianwei.zw@alibaba-inc.com>
Zhenan Ye <21551168@zju.edu.cn> Zhenan Ye <21551168@zju.edu.cn>
zhenghenghuo <zhenghenghuo@zju.edu.cn> zhenghenghuo <zhenghenghuo@zju.edu.cn>
Zhenhai Gao <gaozh1988@live.com>
Zhenkun Bi <bi.zhenkun@zte.com.cn> Zhenkun Bi <bi.zhenkun@zte.com.cn>
Zhou Hao <zhouhao@cn.fujitsu.com> Zhou Hao <zhouhao@cn.fujitsu.com>
Zhoulin Xie <zhoulin.xie@daocloud.io>
Zhu Guihua <zhugh.fnst@cn.fujitsu.com> Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
Zhu Kunjia <zhu.kunjia@zte.com.cn> Zhu Kunjia <zhu.kunjia@zte.com.cn>
Zhuoyun Wei <wzyboy@wzyboy.org> Zhuoyun Wei <wzyboy@wzyboy.org>
......
...@@ -176,7 +176,7 @@ ...@@ -176,7 +176,7 @@
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Copyright 2013-2017 Docker, Inc. Copyright 2013-2018 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
......
...@@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api" ...@@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
// Common constants for daemon and client. // Common constants for daemon and client.
const ( const (
// DefaultVersion of Current REST API // DefaultVersion of Current REST API
DefaultVersion = "1.38" DefaultVersion = "1.40"
// NoBaseImageSpecifier is the symbol used by the FROM // NoBaseImageSpecifier is the symbol used by the FROM
// command to specify that no base image is to be used. // command to specify that no base image is to be used.
......
...@@ -19,10 +19,10 @@ produces: ...@@ -19,10 +19,10 @@ produces:
consumes: consumes:
- "application/json" - "application/json"
- "text/plain" - "text/plain"
basePath: "/v1.38" basePath: "/v1.40"
info: info:
title: "Docker Engine API" title: "Docker Engine API"
version: "1.38" version: "1.40"
x-logo: x-logo:
url: "https://docs.docker.com/images/logo-docker-main.png" url: "https://docs.docker.com/images/logo-docker-main.png"
description: | description: |
...@@ -49,8 +49,8 @@ info: ...@@ -49,8 +49,8 @@ info:
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
is returned. is returned.
If you omit the version-prefix, the current version of the API (v1.38) is used. If you omit the version-prefix, the current version of the API (v1.40) is used.
For example, calling `/info` is the same as calling `/v1.38/info`. Using the For example, calling `/info` is the same as calling `/v1.40/info`. Using the
API without a version-prefix is deprecated and will be removed in a future release. 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, Engine releases in the near future should support this version of the API,
...@@ -210,6 +210,43 @@ definitions: ...@@ -210,6 +210,43 @@ definitions:
PathInContainer: "/dev/deviceName" PathInContainer: "/dev/deviceName"
CgroupPermissions: "mrw" CgroupPermissions: "mrw"
DeviceRequest:
type: "object"
description: "A request for devices to be sent to device drivers"
properties:
Driver:
type: "string"
example: "nvidia"
Count:
type: "integer"
example: -1
DeviceIDs:
type: "array"
items:
type: "string"
example:
- "0"
- "1"
- "GPU-fef8089b-4820-abfc-e83e-94318197576e"
Capabilities:
description: |
A list of capabilities; an OR list of AND lists of capabilities.
type: "array"
items:
type: "array"
items:
type: "string"
example:
# gpu AND nvidia AND compute
- ["gpu", "nvidia", "compute"]
Options:
description: |
Driver-specific options, specified as a key/value pairs. These options
are passed directly to the driver.
type: "object"
additionalProperties:
type: "string"
ThrottleDevice: ThrottleDevice:
type: "object" type: "object"
properties: properties:
...@@ -238,11 +275,13 @@ definitions: ...@@ -238,11 +275,13 @@ definitions:
- `bind` Mounts a file or directory from the host into the container. Must exist prior to creating the container. - `bind` Mounts a file or directory from the host into the container. Must exist prior to creating the container.
- `volume` Creates a volume with the given name and options (or uses a pre-existing volume with the same name and options). These are **not** removed when the container is removed. - `volume` Creates a volume with the given name and options (or uses a pre-existing volume with the same name and options). These are **not** removed when the container is removed.
- `tmpfs` Create a tmpfs with the given options. The mount source cannot be specified for tmpfs. - `tmpfs` Create a tmpfs with the given options. The mount source cannot be specified for tmpfs.
- `npipe` Mounts a named pipe from the host into the container. Must exist prior to creating the container.
type: "string" type: "string"
enum: enum:
- "bind" - "bind"
- "volume" - "volume"
- "tmpfs" - "tmpfs"
- "npipe"
ReadOnly: ReadOnly:
description: "Whether the mount should be read-only." description: "Whether the mount should be read-only."
type: "boolean" type: "boolean"
...@@ -263,6 +302,10 @@ definitions: ...@@ -263,6 +302,10 @@ definitions:
- "rshared" - "rshared"
- "slave" - "slave"
- "rslave" - "rslave"
NonRecursive:
description: "Disable recursive bind mount."
type: "boolean"
default: false
VolumeOptions: VolumeOptions:
description: "Optional configuration for the `volume` type." description: "Optional configuration for the `volume` type."
type: "object" type: "object"
...@@ -415,6 +458,11 @@ definitions: ...@@ -415,6 +458,11 @@ definitions:
items: items:
type: "string" type: "string"
example: "c 13:* rwm" example: "c 13:* rwm"
DeviceRequests:
description: "a list of requests for devices to be sent to device drivers"
type: "array"
items:
$ref: "#/definitions/DeviceRequest"
DiskQuota: DiskQuota:
description: "Disk limit (in bytes)." description: "Disk limit (in bytes)."
type: "integer" type: "integer"
...@@ -423,6 +471,11 @@ definitions: ...@@ -423,6 +471,11 @@ definitions:
description: "Kernel memory limit in bytes." description: "Kernel memory limit in bytes."
type: "integer" type: "integer"
format: "int64" format: "int64"
example: 209715200
KernelMemoryTCP:
description: "Hard limit for kernel TCP buffer memory (in bytes)."
type: "integer"
format: "int64"
MemoryReservation: MemoryReservation:
description: "Memory soft limit in bytes." description: "Memory soft limit in bytes."
type: "integer" type: "integer"
...@@ -449,9 +502,11 @@ definitions: ...@@ -449,9 +502,11 @@ definitions:
type: "boolean" type: "boolean"
x-nullable: true x-nullable: true
PidsLimit: PidsLimit:
description: "Tune a container's pids limit. Set -1 for unlimited." description: |
Tune a container's PIDs limit. Set `0` or `-1` for unlimited, or `null` to not change.
type: "integer" type: "integer"
format: "int64" format: "int64"
x-nullable: true
Ulimits: Ulimits:
description: | description: |
A list of resource limits to set in the container. For example: `{"Name": "nofile", "Soft": 1024, "Hard": 2048}`" A list of resource limits to set in the container. For example: `{"Name": "nofile", "Soft": 1024, "Hard": 2048}`"
...@@ -634,14 +689,22 @@ definitions: ...@@ -634,14 +689,22 @@ definitions:
$ref: "#/definitions/Mount" $ref: "#/definitions/Mount"
# Applicable to UNIX platforms # Applicable to UNIX platforms
Capabilities:
type: "array"
description: |
A list of kernel capabilities to be available for container (this overrides the default set).
Conflicts with options 'CapAdd' and 'CapDrop'"
items:
type: "string"
CapAdd: CapAdd:
type: "array" type: "array"
description: "A list of kernel capabilities to add to the container." description: "A list of kernel capabilities to add to the container. Conflicts with option 'Capabilities'"
items: items:
type: "string" type: "string"
CapDrop: CapDrop:
type: "array" type: "array"
description: "A list of kernel capabilities to drop from the container." description: "A list of kernel capabilities to drop from the container. Conflicts with option 'Capabilities'"
items: items:
type: "string" type: "string"
Dns: Dns:
...@@ -1473,11 +1536,9 @@ definitions: ...@@ -1473,11 +1536,9 @@ definitions:
type: "string" type: "string"
Options: Options:
description: "Driver-specific options, specified as a map." description: "Driver-specific options, specified as a map."
type: "array" type: "object"
items: additionalProperties:
type: "object" type: "string"
additionalProperties:
type: "string"
NetworkContainer: NetworkContainer:
type: "object" type: "object"
...@@ -1513,6 +1574,31 @@ definitions: ...@@ -1513,6 +1574,31 @@ definitions:
aux: aux:
$ref: "#/definitions/ImageID" $ref: "#/definitions/ImageID"
BuildCache:
type: "object"
properties:
ID:
type: "string"
Parent:
type: "string"
Type:
type: "string"
Description:
type: "string"
InUse:
type: "boolean"
Shared:
type: "boolean"
Size:
type: "integer"
CreatedAt:
type: "integer"
LastUsedAt:
type: "integer"
x-nullable: true
UsageCount:
type: "integer"
ImageID: ImageID:
type: "object" type: "object"
description: "Image ID or Digest" description: "Image ID or Digest"
...@@ -2434,6 +2520,31 @@ definitions: ...@@ -2434,6 +2520,31 @@ definitions:
description: "Whether there is currently a root CA rotation in progress for the swarm" description: "Whether there is currently a root CA rotation in progress for the swarm"
type: "boolean" type: "boolean"
example: false example: false
DataPathPort:
description: |
DataPathPort specifies the data path port number for data traffic.
Acceptable port range is 1024 to 49151.
If no port is set or is set to 0, the default port (4789) is used.
type: "integer"
format: "uint32"
default: 4789
example: 4789
DefaultAddrPool:
description: |
Default Address Pool specifies default subnet pools for global scope networks.
type: "array"
items:
type: "string"
format: "CIDR"
example: ["10.10.0.0/16", "20.20.0.0/16"]
SubnetSize:
description: |
SubnetSize specifies the subnet size of the networks created from the default subnet pool
type: "integer"
format: "uint32"
maximum: 29
default: 24
example: 24
JoinTokens: JoinTokens:
description: | description: |
...@@ -2556,8 +2667,20 @@ definitions: ...@@ -2556,8 +2667,20 @@ definitions:
type: "object" type: "object"
description: "CredentialSpec for managed service account (Windows only)" description: "CredentialSpec for managed service account (Windows only)"
properties: properties:
Config:
type: "string"
example: "0bt9dmxjvjiqermk6xrop3ekq"
description: |
Load credential spec from a Swarm Config with the given ID.
The specified config must also be present in the Configs field with the Runtime property set.
<p><br /></p>
> **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, and `CredentialSpec.Config` are mutually exclusive.
File: File:
type: "string" type: "string"
example: "spec.json"
description: | description: |
Load credential spec from this file. The file is read by the daemon, and must be present in the Load credential spec from this file. The file is read by the daemon, and must be present in the
`CredentialSpecs` subdirectory in the docker data directory, which defaults to `CredentialSpecs` subdirectory in the docker data directory, which defaults to
...@@ -2567,7 +2690,7 @@ definitions: ...@@ -2567,7 +2690,7 @@ definitions:
<p><br /></p> <p><br /></p>
> **Note**: `CredentialSpec.File` and `CredentialSpec.Registry` are mutually exclusive. > **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, and `CredentialSpec.Config` are mutually exclusive.
Registry: Registry:
type: "string" type: "string"
description: | description: |
...@@ -2579,7 +2702,7 @@ definitions: ...@@ -2579,7 +2702,7 @@ definitions:
<p><br /></p> <p><br /></p>
> **Note**: `CredentialSpec.File` and `CredentialSpec.Registry` are mutually exclusive. > **Note**: `CredentialSpec.File`, `CredentialSpec.Registry`, and `CredentialSpec.Config` are mutually exclusive.
SELinuxContext: SELinuxContext:
type: "object" type: "object"
description: "SELinux labels of the container" description: "SELinux labels of the container"
...@@ -2690,7 +2813,12 @@ definitions: ...@@ -2690,7 +2813,12 @@ definitions:
type: "object" type: "object"
properties: properties:
File: File:
description: "File represents a specific target that is backed by a file." description: |
File represents a specific target that is backed by a file.
<p><br /><p>
> **Note**: `Configs.File` and `Configs.Runtime` are mutually exclusive
type: "object" type: "object"
properties: properties:
Name: Name:
...@@ -2706,6 +2834,14 @@ definitions: ...@@ -2706,6 +2834,14 @@ definitions:
description: "Mode represents the FileMode of the file." description: "Mode represents the FileMode of the file."
type: "integer" type: "integer"
format: "uint32" format: "uint32"
Runtime:
description: |
Runtime represents a target that is not mounted into the container but is used by the task
<p><br /><p>
> **Note**: `Configs.File` and `Configs.Runtime` are mutually exclusive
type: "object"
ConfigID: ConfigID:
description: "ConfigID represents the ID of the specific config that we're referencing." description: "ConfigID represents the ID of the specific config that we're referencing."
type: "string" type: "string"
...@@ -2725,6 +2861,18 @@ definitions: ...@@ -2725,6 +2861,18 @@ definitions:
description: "Run an init inside the container that forwards signals and reaps processes. This field is omitted if empty, and the default (as configured on the daemon) is used." description: "Run an init inside the container that forwards signals and reaps processes. This field is omitted if empty, and the default (as configured on the daemon) is used."
type: "boolean" type: "boolean"
x-nullable: true x-nullable: true
Sysctls:
description: |
Set kernel namedspaced parameters (sysctls) in the container.
The Sysctls option on services accepts the same sysctls as the
are supported on containers. Note that while the same sysctls are
supported, no guarantees or checks are made about their
suitability for a clustered environment, and it's up to the user
to determine whether a given sysctl will work properly in a
Service.
type: "object"
additionalProperties:
type: "string"
NetworkAttachmentSpec: NetworkAttachmentSpec:
description: | description: |
Read-only spec type for non-swarm containers attached to swarm overlay Read-only spec type for non-swarm containers attached to swarm overlay
...@@ -2805,6 +2953,11 @@ definitions: ...@@ -2805,6 +2953,11 @@ definitions:
SpreadDescriptor: "node.labels.datacenter" SpreadDescriptor: "node.labels.datacenter"
- Spread: - Spread:
SpreadDescriptor: "node.labels.rack" SpreadDescriptor: "node.labels.rack"
MaxReplicas:
description: "Maximum number of replicas for per node (default value is 0, which is unlimited)"
type: "integer"
format: "int64"
default: 0
Platforms: Platforms:
description: | description: |
Platforms stores all the platforms that the service's image can Platforms stores all the platforms that the service's image can
...@@ -3605,6 +3758,10 @@ definitions: ...@@ -3605,6 +3758,10 @@ definitions:
See [cpuset(7)](https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt) See [cpuset(7)](https://www.kernel.org/doc/Documentation/cgroup-v1/cpusets.txt)
type: "boolean" type: "boolean"
example: true example: true
PidsLimit:
description: "Indicates if the host kernel has PID limit support enabled."
type: "boolean"
example: true
OomKillDisable: OomKillDisable:
description: "Indicates if OOM killer disable is supported on the host." description: "Indicates if OOM killer disable is supported on the host."
type: "boolean" type: "boolean"
...@@ -3722,18 +3879,22 @@ definitions: ...@@ -3722,18 +3879,22 @@ definitions:
description: | description: |
HTTP-proxy configured for the daemon. This value is obtained from the HTTP-proxy configured for the daemon. This value is obtained from the
[`HTTP_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable. [`HTTP_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable.
Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL
are masked in the API response.
Containers do not automatically inherit this configuration. Containers do not automatically inherit this configuration.
type: "string" type: "string"
example: "http://user:pass@proxy.corp.example.com:8080" example: "http://xxxxx:xxxxx@proxy.corp.example.com:8080"
HttpsProxy: HttpsProxy:
description: | description: |
HTTPS-proxy configured for the daemon. This value is obtained from the HTTPS-proxy configured for the daemon. This value is obtained from the
[`HTTPS_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable. [`HTTPS_PROXY`](https://www.gnu.org/software/wget/manual/html_node/Proxies.html) environment variable.
Credentials ([user info component](https://tools.ietf.org/html/rfc3986#section-3.2.1)) in the proxy URL
are masked in the API response.
Containers do not automatically inherit this configuration. Containers do not automatically inherit this configuration.
type: "string" type: "string"
example: "https://user:pass@proxy.corp.example.com:4443" example: "https://xxxxx:xxxxx@proxy.corp.example.com:4443"
NoProxy: NoProxy:
description: | description: |
Comma-separated list of domain extensions for which no proxy should be Comma-separated list of domain extensions for which no proxy should be
...@@ -3823,10 +3984,10 @@ definitions: ...@@ -3823,10 +3984,10 @@ definitions:
$ref: "#/definitions/Runtime" $ref: "#/definitions/Runtime"
default: default:
runc: runc:
path: "docker-runc" path: "runc"
example: example:
runc: runc:
path: "docker-runc" path: "runc"
runc-master: runc-master:
path: "/go/bin/runc" path: "/go/bin/runc"
custom: custom:
...@@ -3896,6 +4057,27 @@ definitions: ...@@ -3896,6 +4057,27 @@ definitions:
- "name=seccomp,profile=default" - "name=seccomp,profile=default"
- "name=selinux" - "name=selinux"
- "name=userns" - "name=userns"
ProductLicense:
description: |
Reports a summary of the product license on the daemon.
If a commercial license has been applied to the daemon, information
such as number of nodes, and expiration are included.
type: "string"
example: "Community Engine"
Warnings:
description: |
List of warnings / informational messages about missing features, or
issues related to the daemon configuration.
These messages can be printed by the client as information to the user.
type: "array"
items:
type: "string"
example:
- "WARNING: No memory limit support"
- "WARNING: bridge-nf-call-iptables is disabled"
- "WARNING: bridge-nf-call-ip6tables is disabled"
# PluginsInfo is a temp struct holding Plugins name # PluginsInfo is a temp struct holding Plugins name
...@@ -4516,7 +4698,7 @@ paths: ...@@ -4516,7 +4698,7 @@ paths:
OomKillDisable: false OomKillDisable: false
OomScoreAdj: 500 OomScoreAdj: 500
PidMode: "" PidMode: ""
PidsLimit: -1 PidsLimit: 0
PortBindings: PortBindings:
22/tcp: 22/tcp:
- HostPort: "11022" - HostPort: "11022"
...@@ -5922,7 +6104,7 @@ paths: ...@@ -5922,7 +6104,7 @@ paths:
headers: headers:
X-Docker-Container-Path-Stat: X-Docker-Container-Path-Stat:
type: "string" type: "string"
description: "TODO" description: "A base64 - encoded JSON object with some filesystem header information about the path"
400: 400:
description: "Bad parameter" description: "Bad parameter"
schema: schema:
...@@ -6319,6 +6501,11 @@ paths: ...@@ -6319,6 +6501,11 @@ paths:
description: "Target build stage" description: "Target build stage"
type: "string" type: "string"
default: "" default: ""
- name: "outputs"
in: "query"
description: "BuildKit output configuration"
type: "string"
default: ""
responses: responses:
200: 200:
description: "no error" description: "no error"
...@@ -6337,6 +6524,29 @@ paths: ...@@ -6337,6 +6524,29 @@ paths:
produces: produces:
- "application/json" - "application/json"
operationId: "BuildPrune" operationId: "BuildPrune"
parameters:
- name: "keep-storage"
in: "query"
description: "Amount of disk space in bytes to keep for cache"
type: "integer"
format: "int64"
- name: "all"
in: "query"
type: "boolean"
description: "Remove all types of build cache"
- name: "filters"
in: "query"
type: "string"
description: |
A JSON encoded value of the filters (a `map[string][]string`) to process on the list of build cache objects. Available filters:
- `until=<duration>`: duration relative to daemon's time, during which build cache was not used, in Go's duration format (e.g., '24h')
- `id=<id>`
- `parent=<id>`
- `type=<string>`
- `description=<string>`
- `inuse`
- `shared`
- `private`
responses: responses:
200: 200:
description: "No error" description: "No error"
...@@ -6344,6 +6554,11 @@ paths: ...@@ -6344,6 +6554,11 @@ paths:
type: "object" type: "object"
title: "BuildPruneResponse" title: "BuildPruneResponse"
properties: properties:
CachesDeleted:
type: "array"
items:
description: "ID of build cache object"
type: "string"
SpaceReclaimed: SpaceReclaimed:
description: "Disk space reclaimed in bytes" description: "Disk space reclaimed in bytes"
type: "integer" type: "integer"
...@@ -6972,9 +7187,57 @@ paths: ...@@ -6972,9 +7187,57 @@ paths:
API-Version: API-Version:
type: "string" type: "string"
description: "Max API Version the server supports" description: "Max API Version the server supports"
BuildKit-Version:
type: "string"
description: "Default version of docker image builder"
Docker-Experimental:
type: "boolean"
description: "If the server is running with experimental mode enabled"
Cache-Control:
type: "string"
default: "no-cache, no-store, must-revalidate"
Pragma:
type: "string"
default: "no-cache"
500:
description: "server error"
schema:
$ref: "#/definitions/ErrorResponse"
headers:
Cache-Control:
type: "string"
default: "no-cache, no-store, must-revalidate"
Pragma:
type: "string"
default: "no-cache"
tags: ["System"]
head:
summary: "Ping"
description: "This is a dummy endpoint you can use to test if the server is accessible."
operationId: "SystemPingHead"
produces: ["text/plain"]
responses:
200:
description: "no error"
schema:
type: "string"
example: "(empty)"
headers:
API-Version:
type: "string"
description: "Max API Version the server supports"
BuildKit-Version:
type: "string"
description: "Default version of docker image builder"
Docker-Experimental: Docker-Experimental:
type: "boolean" type: "boolean"
description: "If the server is running with experimental mode enabled" description: "If the server is running with experimental mode enabled"
Cache-Control:
type: "string"
default: "no-cache, no-store, must-revalidate"
Pragma:
type: "string"
default: "no-cache"
500: 500:
description: "server error" description: "server error"
schema: schema:
...@@ -7175,6 +7438,10 @@ paths: ...@@ -7175,6 +7438,10 @@ paths:
type: "array" type: "array"
items: items:
$ref: "#/definitions/Volume" $ref: "#/definitions/Volume"
BuildCache:
type: "array"
items:
$ref: "#/definitions/BuildCache"
example: example:
LayersSize: 1092588 LayersSize: 1092588
Images: Images:
...@@ -7589,6 +7856,7 @@ paths: ...@@ -7589,6 +7856,7 @@ paths:
schema: schema:
type: "object" type: "object"
title: "VolumeListResponse" title: "VolumeListResponse"
description: "Volume list response"
required: [Volumes, Warnings] required: [Volumes, Warnings]
properties: properties:
Volumes: Volumes:
...@@ -7665,6 +7933,8 @@ paths: ...@@ -7665,6 +7933,8 @@ paths:
description: "Volume configuration" description: "Volume configuration"
schema: schema:
type: "object" type: "object"
description: "Volume configuration"
title: "VolumeConfig"
properties: properties:
Name: Name:
description: "The new volume's name. If not specified, Docker generates a name." description: "The new volume's name. If not specified, Docker generates a name."
...@@ -7865,6 +8135,10 @@ paths: ...@@ -7865,6 +8135,10 @@ paths:
description: | description: |
JSON encoded value of the filters (a `map[string][]string`) to process on the networks list. Available filters: JSON encoded value of the filters (a `map[string][]string`) to process on the networks list. Available filters:
- `dangling=<boolean>` When set to `true` (or `1`), returns all
networks that are not in use by a container. When set to `false`
(or `0`), only networks that are in use by one or more
containers are returned.
- `driver=<driver-name>` Matches a network's driver. - `driver=<driver-name>` Matches a network's driver.
- `id=<network-id>` Matches all or part of a network ID. - `id=<network-id>` Matches all or part of a network ID.
- `label=<key>` or `label=<key>=<value>` of a network label. - `label=<key>` or `label=<key>=<value>` of a network label.
...@@ -8582,6 +8856,7 @@ paths: ...@@ -8582,6 +8856,7 @@ paths:
- `label=<engine label>` - `label=<engine label>`
- `membership=`(`accepted`|`pending`)` - `membership=`(`accepted`|`pending`)`
- `name=<node name>` - `name=<node name>`
- `node.label=<node label>`
- `role=`(`manager`|`worker`)` - `role=`(`manager`|`worker`)`
type: "string" type: "string"
tags: ["Node"] tags: ["Node"]
...@@ -8754,14 +9029,36 @@ paths: ...@@ -8754,14 +9029,36 @@ paths:
nodes in order to reach the containers running on this node. Using this parameter it is possible to nodes in order to reach the containers running on this node. Using this parameter it is possible to
separate the container data traffic from the management traffic of the cluster. separate the container data traffic from the management traffic of the cluster.
type: "string" type: "string"
DataPathPort:
description: |
DataPathPort specifies the data path port number for data traffic.
Acceptable port range is 1024 to 49151.
if no port is set or is set to 0, default port 4789 will be used.
type: "integer"
format: "uint32"
DefaultAddrPool:
description: |
Default Address Pool specifies default subnet pools for global scope networks.
type: "array"
items:
type: "string"
example: ["10.10.0.0/16", "20.20.0.0/16"]
ForceNewCluster: ForceNewCluster:
description: "Force creation of a new swarm." description: "Force creation of a new swarm."
type: "boolean" type: "boolean"
SubnetSize:
description: |
SubnetSize specifies the subnet size of the networks created from the default subnet pool
type: "integer"
format: "uint32"
Spec: Spec:
$ref: "#/definitions/SwarmSpec" $ref: "#/definitions/SwarmSpec"
example: example:
ListenAddr: "0.0.0.0:2377" ListenAddr: "0.0.0.0:2377"
AdvertiseAddr: "192.168.1.1:2377" AdvertiseAddr: "192.168.1.1:2377"
DataPathPort: 4789
DefaultAddrPool: ["10.10.0.0/8", "20.20.0.0/8"]
SubnetSize: 24
ForceNewCluster: false ForceNewCluster: false
Spec: Spec:
Orchestration: {} Orchestration: {}
...@@ -9243,7 +9540,10 @@ paths: ...@@ -9243,7 +9540,10 @@ paths:
- name: "version" - name: "version"
in: "query" in: "query"
description: "The version number of the service object being updated. This is required to avoid conflicting writes." description: "The version number of the service object being updated.
This is required to avoid conflicting writes.
This version number should be the value as currently set on the service *before* the update.
You can find the current version by calling `GET /services/{id}`"
required: true required: true
type: "integer" type: "integer"
- name: "registryAuthFrom" - name: "registryAuthFrom"
...@@ -9602,6 +9902,7 @@ paths: ...@@ -9602,6 +9902,7 @@ paths:
description: "Only return this number of log lines from the end of the logs. Specify as an integer or `all` to output all log lines." description: "Only return this number of log lines from the end of the logs. Specify as an integer or `all` to output all log lines."
type: "string" type: "string"
default: "all" default: "all"
tags: ["Task"]
/secrets: /secrets:
get: get:
summary: "List secrets" summary: "List secrets"
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/go-units" units "github.com/docker/go-units"
) )
// CheckpointCreateOptions holds parameters to create a checkpoint from a container // CheckpointCreateOptions holds parameters to create a checkpoint from a container
...@@ -181,8 +181,33 @@ type ImageBuildOptions struct { ...@@ -181,8 +181,33 @@ type ImageBuildOptions struct {
Target string Target string
SessionID string SessionID string
Platform string Platform string
// Version specifies the version of the unerlying builder to use
Version BuilderVersion
// BuildID is an optional identifier that can be passed together with the
// build request. The same identifier can be used to gracefully cancel the
// build with the cancel request.
BuildID string
// Outputs defines configurations for exporting build results. Only supported
// in BuildKit mode
Outputs []ImageBuildOutput
} }
// ImageBuildOutput defines configuration for exporting a build result
type ImageBuildOutput struct {
Type string
Attrs map[string]string
}
// BuilderVersion sets the version of underlying builder to use
type BuilderVersion string
const (
// BuilderV1 is the first generation builder in docker daemon
BuilderV1 BuilderVersion = "1"
// BuilderBuildKit is builder based on moby/buildkit project
BuilderBuildKit = "2"
)
// ImageBuildResponse holds information // ImageBuildResponse holds information
// returned by a server after building // returned by a server after building
// an image. // an image.
......
...@@ -55,3 +55,10 @@ type PluginEnableConfig struct { ...@@ -55,3 +55,10 @@ type PluginEnableConfig struct {
type PluginDisableConfig struct { type PluginDisableConfig struct {
ForceDisable bool ForceDisable bool
} }
// NetworkListConfig stores the options available for listing networks
type NetworkListConfig struct {
// TODO(@cpuguy83): naming is hard, this is pulled from what was being used in the router before moving here
Detailed bool
Verbose bool
}
...@@ -54,7 +54,7 @@ type Config struct { ...@@ -54,7 +54,7 @@ type Config struct {
Env []string // List of environment variable to set in the container Env []string // List of environment variable to set in the container
Cmd strslice.StrSlice // Command to run when starting the container Cmd strslice.StrSlice // Command to run when starting the container
Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific) ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (meaning treat as a command line) (Windows specific).
Image string // Name of the image as it was passed by the operator (e.g. could be symbolic) Image string // Name of the image as it was passed by the operator (e.g. could be symbolic)
Volumes map[string]struct{} // List of volumes (mounts) used for the container Volumes map[string]struct{} // List of volumes (mounts) used for the container
WorkingDir string // Current directory (PWD) in the command will be launched WorkingDir string // Current directory (PWD) in the command will be launched
......
...@@ -244,6 +244,16 @@ func (n PidMode) Container() string { ...@@ -244,6 +244,16 @@ func (n PidMode) Container() string {
return "" return ""
} }
// DeviceRequest represents a request for devices from a device driver.
// Used by GPU device drivers.
type DeviceRequest struct {
Driver string // Name of device driver
Count int // Number of devices to request (-1 = All)
DeviceIDs []string // List of device IDs as recognizable by the device driver
Capabilities [][]string // An OR list of AND lists of device capabilities (e.g. "gpu")
Options map[string]string // Options to pass onto the device driver
}
// DeviceMapping represents the device mapping between the host and the container. // DeviceMapping represents the device mapping between the host and the container.
type DeviceMapping struct { type DeviceMapping struct {
PathOnHost string PathOnHost string
...@@ -327,13 +337,15 @@ type Resources struct { ...@@ -327,13 +337,15 @@ type Resources struct {
CpusetMems string // CpusetMems 0-2, 0,1 CpusetMems string // CpusetMems 0-2, 0,1
Devices []DeviceMapping // List of devices to map inside the container Devices []DeviceMapping // List of devices to map inside the container
DeviceCgroupRules []string // List of rule to be added to the device cgroup DeviceCgroupRules []string // List of rule to be added to the device cgroup
DeviceRequests []DeviceRequest // List of device requests for device drivers
DiskQuota int64 // Disk limit (in bytes) DiskQuota int64 // Disk limit (in bytes)
KernelMemory int64 // Kernel memory limit (in bytes) KernelMemory int64 // Kernel memory limit (in bytes)
KernelMemoryTCP int64 // Hard limit for kernel TCP buffer memory (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes) MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
MemorySwappiness *int64 // Tuning container memory swappiness behaviour MemorySwappiness *int64 // Tuning container memory swappiness behaviour
OomKillDisable *bool // Whether to disable OOM Killer or not OomKillDisable *bool // Whether to disable OOM Killer or not
PidsLimit int64 // Setting pids limit for a container PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change.
Ulimits []*units.Ulimit // List of ulimits to be set in the container Ulimits []*units.Ulimit // List of ulimits to be set in the container
// Applicable to Windows // Applicable to Windows
...@@ -369,9 +381,10 @@ type HostConfig struct { ...@@ -369,9 +381,10 @@ type HostConfig struct {
// Applicable to UNIX platforms // Applicable to UNIX platforms
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
DNS []string `json:"Dns"` // List of DNS server to lookup Capabilities []string `json:"Capabilities"` // List of kernel capabilities to be available for container (this overrides the default set)
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for DNS []string `json:"Dns"` // List of DNS server to lookup
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
ExtraHosts []string // List of extra hosts ExtraHosts []string // List of extra hosts
GroupAdd []string // List of additional groups that the container process will run as GroupAdd []string // List of additional groups that the container process will run as
IpcMode IpcMode // IPC namespace to use for the container IpcMode IpcMode // IPC namespace to use for the container
......
...@@ -323,6 +323,22 @@ func (args Args) WalkValues(field string, op func(value string) error) error { ...@@ -323,6 +323,22 @@ func (args Args) WalkValues(field string, op func(value string) error) error {
return nil return nil
} }
// Clone returns a copy of args.
func (args Args) Clone() (newArgs Args) {
newArgs.fields = make(map[string]map[string]bool, len(args.fields))
for k, m := range args.fields {
var mm map[string]bool
if m != nil {
mm = make(map[string]bool, len(m))
for kk, v := range m {
mm[kk] = v
}
}
newArgs.fields[k] = mm
}
return newArgs
}
func deprecatedArgs(d map[string][]string) map[string]map[string]bool { func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
m := map[string]map[string]bool{} m := map[string]map[string]bool{}
for k, v := range d { for k, v := range d {
......
...@@ -79,7 +79,8 @@ const ( ...@@ -79,7 +79,8 @@ const (
// BindOptions defines options specific to mounts of type "bind". // BindOptions defines options specific to mounts of type "bind".
type BindOptions struct { type BindOptions struct {
Propagation Propagation `json:",omitempty"` Propagation Propagation `json:",omitempty"`
NonRecursive bool `json:",omitempty"`
} }
// VolumeOptions represents the options for a mount of type volume. // VolumeOptions represents the options for a mount of type volume.
......
...@@ -6,6 +6,10 @@ go_library( ...@@ -6,6 +6,10 @@ go_library(
importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api/types/network", importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api/types/network",
importpath = "github.com/docker/docker/api/types/network", importpath = "github.com/docker/docker/api/types/network",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/docker/docker/api/types/filters:go_default_library",
"//vendor/github.com/docker/docker/errdefs:go_default_library",
],
) )
filegroup( filegroup(
......
package network // import "github.com/docker/docker/api/types/network" package network // import "github.com/docker/docker/api/types/network"
import (
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/errdefs"
)
// Address represents an IP address // Address represents an IP address
type Address struct { type Address struct {
...@@ -106,3 +110,18 @@ type NetworkingConfig struct { ...@@ -106,3 +110,18 @@ type NetworkingConfig struct {
type ConfigReference struct { type ConfigReference struct {
Network string Network string
} }
var acceptedFilters = map[string]bool{
"dangling": true,
"driver": true,
"id": true,
"label": true,
"name": true,
"scope": true,
"type": true,
}
// ValidateFilters validates the list of filter args with the available filters.
func ValidateFilters(filter filters.Args) error {
return errdefs.InvalidParameter(filter.Validate(acceptedFilters))
}
...@@ -77,8 +77,9 @@ type Arg struct { ...@@ -77,8 +77,9 @@ type Arg struct {
// Filter is used to conditionally apply Seccomp rules // Filter is used to conditionally apply Seccomp rules
type Filter struct { type Filter struct {
Caps []string `json:"caps,omitempty"` Caps []string `json:"caps,omitempty"`
Arches []string `json:"arches,omitempty"` Arches []string `json:"arches,omitempty"`
MinKernel string `json:"minKernel,omitempty"`
} }
// Syscall is used to match a group of syscalls in Seccomp // Syscall is used to match a group of syscalls in Seccomp
......
...@@ -120,7 +120,7 @@ type NetworkStats struct { ...@@ -120,7 +120,7 @@ type NetworkStats struct {
RxBytes uint64 `json:"rx_bytes"` RxBytes uint64 `json:"rx_bytes"`
// Packets received. Windows and Linux. // Packets received. Windows and Linux.
RxPackets uint64 `json:"rx_packets"` RxPackets uint64 `json:"rx_packets"`
// Received errors. Not used on Windows. Note that we dont `omitempty` this // Received errors. Not used on Windows. Note that we don't `omitempty` this
// field as it is expected in the >=v1.21 API stats structure. // field as it is expected in the >=v1.21 API stats structure.
RxErrors uint64 `json:"rx_errors"` RxErrors uint64 `json:"rx_errors"`
// Incoming packets dropped. Windows and Linux. // Incoming packets dropped. Windows and Linux.
...@@ -129,7 +129,7 @@ type NetworkStats struct { ...@@ -129,7 +129,7 @@ type NetworkStats struct {
TxBytes uint64 `json:"tx_bytes"` TxBytes uint64 `json:"tx_bytes"`
// Packets sent. Windows and Linux. // Packets sent. Windows and Linux.
TxPackets uint64 `json:"tx_packets"` TxPackets uint64 `json:"tx_packets"`
// Sent errors. Not used on Windows. Note that we dont `omitempty` this // Sent errors. Not used on Windows. Note that we don't `omitempty` this
// field as it is expected in the >=v1.21 API stats structure. // field as it is expected in the >=v1.21 API stats structure.
TxErrors uint64 `json:"tx_errors"` TxErrors uint64 `json:"tx_errors"`
// Outgoing packets dropped. Windows and Linux. // Outgoing packets dropped. Windows and Linux.
......
...@@ -27,9 +27,14 @@ type ConfigReferenceFileTarget struct { ...@@ -27,9 +27,14 @@ type ConfigReferenceFileTarget struct {
Mode os.FileMode Mode os.FileMode
} }
// ConfigReferenceRuntimeTarget is a target for a config specifying that it
// isn't mounted into the container but instead has some other purpose.
type ConfigReferenceRuntimeTarget struct{}
// ConfigReference is a reference to a config in swarm // ConfigReference is a reference to a config in swarm
type ConfigReference struct { type ConfigReference struct {
File *ConfigReferenceFileTarget File *ConfigReferenceFileTarget `json:",omitempty"`
Runtime *ConfigReferenceRuntimeTarget `json:",omitempty"`
ConfigID string ConfigID string
ConfigName string ConfigName string
} }
...@@ -33,6 +33,7 @@ type SELinuxContext struct { ...@@ -33,6 +33,7 @@ type SELinuxContext struct {
// CredentialSpec for managed service account (Windows only) // CredentialSpec for managed service account (Windows only)
type CredentialSpec struct { type CredentialSpec struct {
Config string
File string File string
Registry string Registry string
} }
...@@ -71,4 +72,5 @@ type ContainerSpec struct { ...@@ -71,4 +72,5 @@ type ContainerSpec struct {
Secrets []*SecretReference `json:",omitempty"` Secrets []*SecretReference `json:",omitempty"`
Configs []*ConfigReference `json:",omitempty"` Configs []*ConfigReference `json:",omitempty"`
Isolation container.Isolation `json:",omitempty"` Isolation container.Isolation `json:",omitempty"`
Sysctls map[string]string `json:",omitempty"`
} }
package swarm // import "github.com/docker/docker/api/types/swarm" package swarm // import "github.com/docker/docker/api/types/swarm"
import "time" import (
"time"
)
// ClusterInfo represents info about the cluster for outputting in "info" // ClusterInfo represents info about the cluster for outputting in "info"
// it contains the same information as "Swarm", but without the JoinTokens // it contains the same information as "Swarm", but without the JoinTokens
...@@ -10,6 +12,9 @@ type ClusterInfo struct { ...@@ -10,6 +12,9 @@ type ClusterInfo struct {
Spec Spec Spec Spec
TLSInfo TLSInfo TLSInfo TLSInfo
RootRotationInProgress bool RootRotationInProgress bool
DefaultAddrPool []string
SubnetSize uint32
DataPathPort uint32
} }
// Swarm represents a swarm. // Swarm represents a swarm.
...@@ -149,10 +154,13 @@ type InitRequest struct { ...@@ -149,10 +154,13 @@ type InitRequest struct {
ListenAddr string ListenAddr string
AdvertiseAddr string AdvertiseAddr string
DataPathAddr string DataPathAddr string
DataPathPort uint32
ForceNewCluster bool ForceNewCluster bool
Spec Spec Spec Spec
AutoLockManagers bool AutoLockManagers bool
Availability NodeAvailability Availability NodeAvailability
DefaultAddrPool []string
SubnetSize uint32
} }
// JoinRequest is the request used to join a swarm. // JoinRequest is the request used to join a swarm.
...@@ -201,6 +209,8 @@ type Info struct { ...@@ -201,6 +209,8 @@ type Info struct {
Managers int `json:",omitempty"` Managers int `json:",omitempty"`
Cluster *ClusterInfo `json:",omitempty"` Cluster *ClusterInfo `json:",omitempty"`
Warnings []string `json:",omitempty"`
} }
// Peer represents a peer. // Peer represents a peer.
......
...@@ -127,6 +127,7 @@ type ResourceRequirements struct { ...@@ -127,6 +127,7 @@ type ResourceRequirements struct {
type Placement struct { type Placement struct {
Constraints []string `json:",omitempty"` Constraints []string `json:",omitempty"`
Preferences []PlacementPreference `json:",omitempty"` Preferences []PlacementPreference `json:",omitempty"`
MaxReplicas uint64 `json:",omitempty"`
// Platforms stores all the platforms that the image can run on. // Platforms stores all the platforms that the image can run on.
// This field is used in the platform filter for scheduling. If empty, // This field is used in the platform filter for scheduling. If empty,
......
...@@ -102,9 +102,10 @@ type ContainerStats struct { ...@@ -102,9 +102,10 @@ type ContainerStats struct {
// Ping contains response of Engine API: // Ping contains response of Engine API:
// GET "/_ping" // GET "/_ping"
type Ping struct { type Ping struct {
APIVersion string APIVersion string
OSType string OSType string
Experimental bool Experimental bool
BuilderVersion BuilderVersion
} }
// ComponentVersion describes the version information for a specific component. // ComponentVersion describes the version information for a specific component.
...@@ -157,10 +158,12 @@ type Info struct { ...@@ -157,10 +158,12 @@ type Info struct {
MemoryLimit bool MemoryLimit bool
SwapLimit bool SwapLimit bool
KernelMemory bool KernelMemory bool
KernelMemoryTCP bool
CPUCfsPeriod bool `json:"CpuCfsPeriod"` CPUCfsPeriod bool `json:"CpuCfsPeriod"`
CPUCfsQuota bool `json:"CpuCfsQuota"` CPUCfsQuota bool `json:"CpuCfsQuota"`
CPUShares bool CPUShares bool
CPUSet bool CPUSet bool
PidsLimit bool
IPv4Forwarding bool IPv4Forwarding bool
BridgeNfIptables bool BridgeNfIptables bool
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` BridgeNfIP6tables bool `json:"BridgeNfIp6tables"`
...@@ -204,6 +207,8 @@ type Info struct { ...@@ -204,6 +207,8 @@ type Info struct {
RuncCommit Commit RuncCommit Commit
InitCommit Commit InitCommit Commit
SecurityOptions []string SecurityOptions []string
ProductLicense string `json:",omitempty"`
Warnings []string
} }
// KeyValue holds a key/value pair // KeyValue holds a key/value pair
...@@ -512,7 +517,8 @@ type DiskUsage struct { ...@@ -512,7 +517,8 @@ type DiskUsage struct {
Images []*ImageSummary Images []*ImageSummary
Containers []*Container Containers []*Container
Volumes []*Volume Volumes []*Volume
BuilderSize int64 BuildCache []*BuildCache
BuilderSize int64 // deprecated
} }
// ContainersPruneReport contains the response for Engine API: // ContainersPruneReport contains the response for Engine API:
...@@ -539,6 +545,7 @@ type ImagesPruneReport struct { ...@@ -539,6 +545,7 @@ type ImagesPruneReport struct {
// BuildCachePruneReport contains the response for Engine API: // BuildCachePruneReport contains the response for Engine API:
// POST "/build/prune" // POST "/build/prune"
type BuildCachePruneReport struct { type BuildCachePruneReport struct {
CachesDeleted []string
SpaceReclaimed uint64 SpaceReclaimed uint64
} }
...@@ -585,3 +592,24 @@ type PushResult struct { ...@@ -585,3 +592,24 @@ type PushResult struct {
type BuildResult struct { type BuildResult struct {
ID string ID string
} }
// BuildCache contains information about a build cache record
type BuildCache struct {
ID string
Parent string
Type string
Description string
InUse bool
Shared bool
Size int64
CreatedAt time.Time
LastUsedAt *time.Time
UsageCount int
}
// BuildCachePruneOptions hold parameters to prune the build cache
type BuildCachePruneOptions struct {
All bool
KeepStorage int64
Filters filters.Args
}
...@@ -7,7 +7,7 @@ package volume ...@@ -7,7 +7,7 @@ package volume
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// VolumeCreateBody // VolumeCreateBody Volume configuration
// swagger:model VolumeCreateBody // swagger:model VolumeCreateBody
type VolumeCreateBody struct { type VolumeCreateBody struct {
......
...@@ -9,7 +9,7 @@ package volume ...@@ -9,7 +9,7 @@ package volume
import "github.com/docker/docker/api/types" import "github.com/docker/docker/api/types"
// VolumeListOKBody // VolumeListOKBody Volume list response
// swagger:model VolumeListOKBody // swagger:model VolumeListOKBody
type VolumeListOKBody struct { type VolumeListOKBody struct {
......
...@@ -3,11 +3,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") ...@@ -3,11 +3,13 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"build_cancel.go",
"build_prune.go", "build_prune.go",
"checkpoint_create.go", "checkpoint_create.go",
"checkpoint_delete.go", "checkpoint_delete.go",
"checkpoint_list.go", "checkpoint_list.go",
"client.go", "client.go",
"client_deprecated.go",
"client_unix.go", "client_unix.go",
"client_windows.go", "client_windows.go",
"config_create.go", "config_create.go",
...@@ -74,6 +76,7 @@ go_library( ...@@ -74,6 +76,7 @@ go_library(
"node_list.go", "node_list.go",
"node_remove.go", "node_remove.go",
"node_update.go", "node_update.go",
"options.go",
"ping.go", "ping.go",
"plugin_create.go", "plugin_create.go",
"plugin_disable.go", "plugin_disable.go",
...@@ -134,11 +137,11 @@ go_library( ...@@ -134,11 +137,11 @@ go_library(
"//vendor/github.com/docker/docker/api/types/time:go_default_library", "//vendor/github.com/docker/docker/api/types/time:go_default_library",
"//vendor/github.com/docker/docker/api/types/versions:go_default_library", "//vendor/github.com/docker/docker/api/types/versions:go_default_library",
"//vendor/github.com/docker/docker/api/types/volume:go_default_library", "//vendor/github.com/docker/docker/api/types/volume:go_default_library",
"//vendor/github.com/docker/docker/errdefs:go_default_library",
"//vendor/github.com/docker/go-connections/sockets:go_default_library", "//vendor/github.com/docker/go-connections/sockets:go_default_library",
"//vendor/github.com/docker/go-connections/tlsconfig:go_default_library", "//vendor/github.com/docker/go-connections/tlsconfig:go_default_library",
"//vendor/github.com/opencontainers/go-digest:go_default_library", "//vendor/github.com/opencontainers/go-digest:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/golang.org/x/net/context/ctxhttp:go_default_library",
], ],
) )
......
...@@ -16,7 +16,7 @@ import ( ...@@ -16,7 +16,7 @@ import (
) )
func main() { func main() {
cli, err := client.NewEnvClient() cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil { if err != nil {
panic(err) panic(err)
} }
......
package client // import "github.com/docker/docker/client"
import (
"context"
"net/url"
)
// BuildCancel requests the daemon to cancel ongoing build request
func (cli *Client) BuildCancel(ctx context.Context, id string) error {
query := url.Values{}
query.Set("id", id)
serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil)
ensureReaderClosed(serverResp)
return err
}
...@@ -4,24 +4,39 @@ import ( ...@@ -4,24 +4,39 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/pkg/errors"
) )
// BuildCachePrune requests the daemon to delete unused cache data // BuildCachePrune requests the daemon to delete unused cache data
func (cli *Client) BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error) { func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) {
if err := cli.NewVersionError("1.31", "build prune"); err != nil { if err := cli.NewVersionError("1.31", "build prune"); err != nil {
return nil, err return nil, err
} }
report := types.BuildCachePruneReport{} report := types.BuildCachePruneReport{}
serverResp, err := cli.post(ctx, "/build/prune", nil, nil, nil) query := url.Values{}
if opts.All {
query.Set("all", "1")
}
query.Set("keep-storage", fmt.Sprintf("%d", opts.KeepStorage))
filters, err := filters.ToJSON(opts.Filters)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "prune could not marshal filters option")
} }
query.Set("filters", filters)
serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil)
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)
if err != nil {
return nil, err
}
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return nil, fmt.Errorf("Error retrieving disk usage: %v", err) return nil, fmt.Errorf("Error retrieving disk usage: %v", err)
} }
......
...@@ -18,11 +18,11 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options ...@@ -18,11 +18,11 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options
} }
resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return checkpoints, wrapResponseError(err, resp, "container", container) return checkpoints, wrapResponseError(err, resp, "container", container)
} }
err = json.NewDecoder(resp.body).Decode(&checkpoints) err = json.NewDecoder(resp.body).Decode(&checkpoints)
ensureReaderClosed(resp)
return checkpoints, err return checkpoints, err
} }
...@@ -23,7 +23,7 @@ For example, to list running containers (the equivalent of "docker ps"): ...@@ -23,7 +23,7 @@ For example, to list running containers (the equivalent of "docker ps"):
) )
func main() { func main() {
cli, err := client.NewEnvClient() cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil { if err != nil {
panic(err) panic(err)
} }
...@@ -47,16 +47,13 @@ import ( ...@@ -47,16 +47,13 @@ import (
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"os"
"path" "path"
"path/filepath"
"strings" "strings"
"github.com/docker/docker/api" "github.com/docker/docker/api"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/go-connections/sockets" "github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -90,7 +87,7 @@ type Client struct { ...@@ -90,7 +87,7 @@ type Client struct {
// If the request is non-GET return `ErrRedirect`. Otherwise use the last response. // If the request is non-GET return `ErrRedirect`. Otherwise use the last response.
// //
// Go 1.8 changes behavior for HTTP redirects (specifically 301, 307, and 308) in the client . // Go 1.8 changes behavior for HTTP redirects (specifically 301, 307, and 308) in the client .
// The Docker client (and by extension docker API client) can be made to to send a request // The Docker client (and by extension docker API client) can be made to send a request
// like POST /containers//start where what would normally be in the name section of the URL is empty. // like POST /containers//start where what would normally be in the name section of the URL is empty.
// This triggers an HTTP 301 from the daemon. // This triggers an HTTP 301 from the daemon.
// In go 1.8 this 301 will be converted to a GET request, and ends up getting a 404 from the daemon. // In go 1.8 this 301 will be converted to a GET request, and ends up getting a 404 from the daemon.
...@@ -103,130 +100,6 @@ func CheckRedirect(req *http.Request, via []*http.Request) error { ...@@ -103,130 +100,6 @@ func CheckRedirect(req *http.Request, via []*http.Request) error {
return ErrRedirect return ErrRedirect
} }
// NewEnvClient initializes a new API client based on environment variables.
// See FromEnv for a list of support environment variables.
//
// Deprecated: use NewClientWithOpts(FromEnv)
func NewEnvClient() (*Client, error) {
return NewClientWithOpts(FromEnv)
}
// FromEnv configures the client with values from environment variables.
//
// Supported environment variables:
// DOCKER_HOST to set the url to the docker server.
// DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
// DOCKER_CERT_PATH to load the TLS certificates from.
// DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func FromEnv(c *Client) error {
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
options := tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
}
tlsc, err := tlsconfig.Client(options)
if err != nil {
return err
}
c.client = &http.Client{
Transport: &http.Transport{TLSClientConfig: tlsc},
CheckRedirect: CheckRedirect,
}
}
if host := os.Getenv("DOCKER_HOST"); host != "" {
if err := WithHost(host)(c); err != nil {
return err
}
}
if version := os.Getenv("DOCKER_API_VERSION"); version != "" {
c.version = version
c.manualOverride = true
}
return nil
}
// WithTLSClientConfig applies a tls config to the client transport.
func WithTLSClientConfig(cacertPath, certPath, keyPath string) func(*Client) error {
return func(c *Client) error {
opts := tlsconfig.Options{
CAFile: cacertPath,
CertFile: certPath,
KeyFile: keyPath,
ExclusiveRootPools: true,
}
config, err := tlsconfig.Client(opts)
if err != nil {
return errors.Wrap(err, "failed to create tls config")
}
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.TLSClientConfig = config
return nil
}
return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport)
}
}
// WithDialer applies the dialer.DialContext to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
func WithDialer(dialer *net.Dialer) func(*Client) error {
return func(c *Client) error {
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.DialContext = dialer.DialContext
return nil
}
return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport)
}
}
// WithVersion overrides the client version with the specified one
func WithVersion(version string) func(*Client) error {
return func(c *Client) error {
c.version = version
return nil
}
}
// WithHost overrides the client host with the specified one.
func WithHost(host string) func(*Client) error {
return func(c *Client) error {
hostURL, err := ParseHostURL(host)
if err != nil {
return err
}
c.host = host
c.proto = hostURL.Scheme
c.addr = hostURL.Host
c.basePath = hostURL.Path
if transport, ok := c.client.Transport.(*http.Transport); ok {
return sockets.ConfigureTransport(transport, c.proto, c.addr)
}
return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
}
}
// WithHTTPClient overrides the client http client with the specified one
func WithHTTPClient(client *http.Client) func(*Client) error {
return func(c *Client) error {
if client != nil {
c.client = client
}
return nil
}
}
// WithHTTPHeaders overrides the client default http headers
func WithHTTPHeaders(headers map[string]string) func(*Client) error {
return func(c *Client) error {
c.customHTTPHeaders = headers
return nil
}
}
// NewClientWithOpts initializes a new API client with default values. It takes functors // NewClientWithOpts initializes a new API client with default values. It takes functors
// to modify values when creating it, like `NewClientWithOpts(WithVersion(…))` // to modify values when creating it, like `NewClientWithOpts(WithVersion(…))`
// It also initializes the custom http headers to add to each request. // It also initializes the custom http headers to add to each request.
...@@ -242,7 +115,6 @@ func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) { ...@@ -242,7 +115,6 @@ func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) {
c := &Client{ c := &Client{
host: DefaultDockerHost, host: DefaultDockerHost,
version: api.DefaultVersion, version: api.DefaultVersion,
scheme: "http",
client: client, client: client,
proto: defaultProto, proto: defaultProto,
addr: defaultAddr, addr: defaultAddr,
...@@ -257,14 +129,18 @@ func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) { ...@@ -257,14 +129,18 @@ func NewClientWithOpts(ops ...func(*Client) error) (*Client, error) {
if _, ok := c.client.Transport.(http.RoundTripper); !ok { if _, ok := c.client.Transport.(http.RoundTripper); !ok {
return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", c.client.Transport) return nil, fmt.Errorf("unable to verify TLS configuration, invalid transport %v", c.client.Transport)
} }
tlsConfig := resolveTLSConfig(c.client.Transport) if c.scheme == "" {
if tlsConfig != nil { c.scheme = "http"
// TODO(stevvooe): This isn't really the right way to write clients in Go.
// `NewClient` should probably only take an `*http.Client` and work from there. tlsConfig := resolveTLSConfig(c.client.Transport)
// Unfortunately, the model of having a host-ish/url-thingy as the connection if tlsConfig != nil {
// string has us confusing protocol and transport layers. We continue doing // TODO(stevvooe): This isn't really the right way to write clients in Go.
// this to avoid breaking existing clients but this should be addressed. // `NewClient` should probably only take an `*http.Client` and work from there.
c.scheme = "https" // Unfortunately, the model of having a host-ish/url-thingy as the connection
// string has us confusing protocol and transport layers. We continue doing
// this to avoid breaking existing clients but this should be addressed.
c.scheme = "https"
}
} }
return c, nil return c, nil
...@@ -283,18 +159,6 @@ func defaultHTTPClient(host string) (*http.Client, error) { ...@@ -283,18 +159,6 @@ func defaultHTTPClient(host string) (*http.Client, error) {
}, nil }, nil
} }
// NewClient initializes a new API client for the given host and API version.
// It uses the given http client as transport.
// It also initializes the custom http headers to add to each request.
//
// It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the
// server is upgraded.
// Deprecated: use NewClientWithOpts
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))
}
// Close the transport used by the client // Close the transport used by the client
func (cli *Client) Close() error { func (cli *Client) Close() error {
if t, ok := cli.client.Transport.(*http.Transport); ok { if t, ok := cli.client.Transport.(*http.Transport); ok {
...@@ -400,3 +264,16 @@ func (cli *Client) CustomHTTPHeaders() map[string]string { ...@@ -400,3 +264,16 @@ func (cli *Client) CustomHTTPHeaders() map[string]string {
func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) { func (cli *Client) SetCustomHTTPHeaders(headers map[string]string) {
cli.customHTTPHeaders = headers cli.customHTTPHeaders = headers
} }
// Dialer returns a dialer for a raw stream connection, with HTTP/1.1 header, that can be used for proxying the daemon connection.
// Used by `docker dial-stdio` (docker/cli#889).
func (cli *Client) Dialer() func(context.Context) (net.Conn, error) {
return func(ctx context.Context) (net.Conn, error) {
if transport, ok := cli.client.Transport.(*http.Transport); ok {
if transport.DialContext != nil && transport.TLSClientConfig == nil {
return transport.DialContext(ctx, cli.proto, cli.addr)
}
}
return fallbackDial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport))
}
}
package client
import "net/http"
// NewClient initializes a new API client for the given host and API version.
// It uses the given http client as transport.
// It also initializes the custom http headers to add to each request.
//
// It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the
// server is upgraded.
// Deprecated: use NewClientWithOpts
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))
}
// NewEnvClient initializes a new API client based on environment variables.
// See FromEnv for a list of support environment variables.
//
// Deprecated: use NewClientWithOpts(FromEnv)
func NewEnvClient() (*Client, error) {
return NewClientWithOpts(FromEnv)
}
...@@ -15,11 +15,11 @@ func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (t ...@@ -15,11 +15,11 @@ func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (t
return response, err return response, err
} }
resp, err := cli.post(ctx, "/configs/create", nil, config, nil) resp, err := cli.post(ctx, "/configs/create", nil, config, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -18,10 +18,10 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C ...@@ -18,10 +18,10 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C
return swarm.Config{}, nil, err return swarm.Config{}, nil, err
} }
resp, err := cli.get(ctx, "/configs/"+id, nil, nil) resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id) return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
......
...@@ -27,12 +27,12 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio ...@@ -27,12 +27,12 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio
} }
resp, err := cli.get(ctx, "/configs", query, nil) resp, err := cli.get(ctx, "/configs", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var configs []swarm.Config var configs []swarm.Config
err = json.NewDecoder(resp.body).Decode(&configs) err = json.NewDecoder(resp.body).Decode(&configs)
ensureReaderClosed(resp)
return configs, err return configs, err
} }
...@@ -8,6 +8,6 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error { ...@@ -8,6 +8,6 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
return err return err
} }
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "config", id) return wrapResponseError(err, resp, "config", id)
} }
...@@ -45,11 +45,11 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option ...@@ -45,11 +45,11 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option
var response types.IDResponse var response types.IDResponse
resp, err := cli.post(ctx, "/commit", query, options.Config, nil) resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -21,10 +21,10 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri ...@@ -21,10 +21,10 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri
urlStr := "/containers/" + containerID + "/archive" urlStr := "/containers/" + containerID + "/archive"
response, err := cli.head(ctx, urlStr, query, nil) response, err := cli.head(ctx, urlStr, query, nil)
defer ensureReaderClosed(response)
if err != nil { if err != nil {
return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path) return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path)
} }
defer ensureReaderClosed(response)
return getContainerPathStatFromHeader(response.header) return getContainerPathStatFromHeader(response.header)
} }
...@@ -45,11 +45,12 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str ...@@ -45,11 +45,12 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str
apiPath := "/containers/" + containerID + "/archive" apiPath := "/containers/" + containerID + "/archive"
response, err := cli.putRaw(ctx, apiPath, query, content, nil) response, err := cli.putRaw(ctx, apiPath, query, content, nil)
defer ensureReaderClosed(response)
if err != nil { if err != nil {
return wrapResponseError(err, response, "container:path", containerID+":"+dstPath) return wrapResponseError(err, response, "container:path", containerID+":"+dstPath)
} }
defer ensureReaderClosed(response)
// TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior
if response.statusCode != http.StatusOK { if response.statusCode != http.StatusOK {
return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
} }
...@@ -69,6 +70,7 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s ...@@ -69,6 +70,7 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s
return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath) return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath)
} }
// TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior
if response.statusCode != http.StatusOK { if response.statusCode != http.StatusOK {
return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
} }
......
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strings"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
...@@ -43,14 +42,11 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config ...@@ -43,14 +42,11 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
} }
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
return response, objectNotFoundError{object: "image", id: config.Image}
}
return response, err return response, err
} }
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -13,11 +13,11 @@ func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]con ...@@ -13,11 +13,11 @@ func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]con
var changes []container.ContainerChangeResponseItem var changes []container.ContainerChangeResponseItem
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return changes, err return changes, err
} }
err = json.NewDecoder(serverResp.body).Decode(&changes) err = json.NewDecoder(serverResp.body).Decode(&changes)
ensureReaderClosed(serverResp)
return changes, err return changes, err
} }
...@@ -16,11 +16,11 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co ...@@ -16,11 +16,11 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co
} }
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil) resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
......
...@@ -16,13 +16,13 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty ...@@ -16,13 +16,13 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty
return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID} return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID}
} }
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID) return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
} }
var response types.ContainerJSON var response types.ContainerJSON
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -36,10 +36,10 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri ...@@ -36,10 +36,10 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri
query.Set("size", "1") query.Set("size", "1")
} }
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID) return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -45,12 +45,12 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis ...@@ -45,12 +45,12 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis
} }
resp, err := cli.get(ctx, "/containers/json", query, nil) resp, err := cli.get(ctx, "/containers/json", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var containers []types.Container var containers []types.Container
err = json.NewDecoder(resp.body).Decode(&containers) err = json.NewDecoder(resp.body).Decode(&containers)
ensureReaderClosed(resp)
return containers, err return containers, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Arg ...@@ -23,10 +23,10 @@ func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Arg
} }
serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return report, err return report, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return report, fmt.Errorf("Error retrieving disk usage: %v", err) return report, fmt.Errorf("Error retrieving disk usage: %v", err)
......
...@@ -22,6 +22,6 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti ...@@ -22,6 +22,6 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti
} }
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "container", containerID) return wrapResponseError(err, resp, "container", containerID)
} }
...@@ -18,11 +18,11 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen ...@@ -18,11 +18,11 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen
} }
resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -11,12 +11,11 @@ import ( ...@@ -11,12 +11,11 @@ import (
func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) { func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) {
var response container.ContainerUpdateOKBody var response container.ContainerUpdateOKBody
serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -13,10 +13,10 @@ func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) { ...@@ -13,10 +13,10 @@ func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) {
var du types.DiskUsage var du types.DiskUsage
serverResp, err := cli.get(ctx, "/system/df", nil, nil) serverResp, err := cli.get(ctx, "/system/df", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return du, err return du, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil {
return du, fmt.Errorf("Error retrieving disk usage: %v", err) return du, fmt.Errorf("Error retrieving disk usage: %v", err)
......
...@@ -28,11 +28,11 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist ...@@ -28,11 +28,11 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
} }
resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers) resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return distributionInspect, err return distributionInspect, err
} }
err = json.NewDecoder(resp.body).Decode(&distributionInspect) err = json.NewDecoder(resp.body).Decode(&distributionInspect)
ensureReaderClosed(resp)
return distributionInspect, err return distributionInspect, err
} }
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -32,16 +33,19 @@ func ErrorConnectionFailed(host string) error { ...@@ -32,16 +33,19 @@ func ErrorConnectionFailed(host string) error {
return errConnectionFailed{host: host} return errConnectionFailed{host: host}
} }
// Deprecated: use the errdefs.NotFound() interface instead. Kept for backward compatibility
type notFound interface { type notFound interface {
error error
NotFound() bool // Is the error a NotFound error NotFound() bool
} }
// IsErrNotFound returns true if the error is a NotFound error, which is returned // IsErrNotFound returns true if the error is a NotFound error, which is returned
// by the API when some object is not found. // by the API when some object is not found.
func IsErrNotFound(err error) bool { func IsErrNotFound(err error) bool {
te, ok := err.(notFound) if _, ok := err.(notFound); ok {
return ok && te.NotFound() return ok
}
return errdefs.IsNotFound(err)
} }
type objectNotFoundError struct { type objectNotFoundError struct {
...@@ -49,9 +53,7 @@ type objectNotFoundError struct { ...@@ -49,9 +53,7 @@ type objectNotFoundError struct {
id string id string
} }
func (e objectNotFoundError) NotFound() bool { func (e objectNotFoundError) NotFound() {}
return true
}
func (e objectNotFoundError) Error() string { func (e objectNotFoundError) Error() string {
return fmt.Sprintf("Error: No such %s: %s", e.object, e.id) return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
...@@ -64,7 +66,7 @@ func wrapResponseError(err error, resp serverResponse, object, id string) error ...@@ -64,7 +66,7 @@ func wrapResponseError(err error, resp serverResponse, object, id string) error
case resp.statusCode == http.StatusNotFound: case resp.statusCode == http.StatusNotFound:
return objectNotFoundError{object: object, id: id} return objectNotFoundError{object: object, id: id}
case resp.statusCode == http.StatusNotImplemented: case resp.statusCode == http.StatusNotImplemented:
return notImplementedError{message: err.Error()} return errdefs.NotImplemented(err)
default: default:
return err return err
} }
...@@ -83,8 +85,10 @@ func (u unauthorizedError) Error() string { ...@@ -83,8 +85,10 @@ func (u unauthorizedError) Error() string {
// IsErrUnauthorized returns true if the error is caused // IsErrUnauthorized returns true if the error is caused
// when a remote registry authentication fails // when a remote registry authentication fails
func IsErrUnauthorized(err error) bool { func IsErrUnauthorized(err error) bool {
_, ok := err.(unauthorizedError) if _, ok := err.(unauthorizedError); ok {
return ok return ok
}
return errdefs.IsUnauthorized(err)
} }
type pluginPermissionDenied struct { type pluginPermissionDenied struct {
...@@ -118,8 +122,10 @@ func (e notImplementedError) NotImplemented() bool { ...@@ -118,8 +122,10 @@ func (e notImplementedError) NotImplemented() bool {
// This is returned by the API when a requested feature has not been // This is returned by the API when a requested feature has not been
// implemented. // implemented.
func IsErrNotImplemented(err error) bool { func IsErrNotImplemented(err error) bool {
te, ok := err.(notImplementedError) if _, ok := err.(notImplementedError); ok {
return ok && te.NotImplemented() return ok
}
return errdefs.IsNotImplemented(err)
} }
// NewVersionError returns an error if the APIVersion required // NewVersionError returns an error if the APIVersion required
......
...@@ -30,7 +30,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu ...@@ -30,7 +30,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
} }
req = cli.addHeaders(req, headers) req = cli.addHeaders(req, headers)
conn, err := cli.setupHijackConn(req, "tcp") conn, err := cli.setupHijackConn(ctx, req, "tcp")
if err != nil { if err != nil {
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
} }
...@@ -38,7 +38,9 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu ...@@ -38,7 +38,9 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err
} }
func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { // fallbackDial is used when WithDialer() was not called.
// See cli.Dialer().
func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
if tlsConfig != nil && proto != "unix" && proto != "npipe" { if tlsConfig != nil && proto != "unix" && proto != "npipe" {
return tls.Dial(proto, addr, tlsConfig) return tls.Dial(proto, addr, tlsConfig)
} }
...@@ -48,12 +50,13 @@ func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { ...@@ -48,12 +50,13 @@ func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
return net.Dial(proto, addr) return net.Dial(proto, addr)
} }
func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, error) { func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, error) {
req.Host = cli.addr req.Host = cli.addr
req.Header.Set("Connection", "Upgrade") req.Header.Set("Connection", "Upgrade")
req.Header.Set("Upgrade", proto) req.Header.Set("Upgrade", proto)
conn, err := dial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport)) dialer := cli.Dialer()
conn, err := dialer(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") return nil, errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
} }
......
...@@ -30,12 +30,6 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio ...@@ -30,12 +30,6 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
} }
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf)) headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
if options.Platform != "" {
if err := cli.NewVersionError("1.32", "platform"); err != nil {
return types.ImageBuildResponse{}, err
}
query.Set("platform", options.Platform)
}
headers.Set("Content-Type", "application/x-tar") headers.Set("Content-Type", "application/x-tar")
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers) serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
...@@ -131,7 +125,22 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur ...@@ -131,7 +125,22 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
query.Set("session", options.SessionID) query.Set("session", options.SessionID)
} }
if options.Platform != "" { if options.Platform != "" {
if err := cli.NewVersionError("1.32", "platform"); err != nil {
return query, err
}
query.Set("platform", strings.ToLower(options.Platform)) query.Set("platform", strings.ToLower(options.Platform))
} }
if options.BuildID != "" {
query.Set("buildid", options.BuildID)
}
query.Set("version", string(options.Version))
if options.Outputs != nil {
outputsJSON, err := json.Marshal(options.Outputs)
if err != nil {
return query, err
}
query.Set("outputs", string(outputsJSON))
}
return query, nil return query, nil
} }
...@@ -12,11 +12,11 @@ import ( ...@@ -12,11 +12,11 @@ import (
func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) { func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) {
var history []image.HistoryResponseItem var history []image.HistoryResponseItem
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil) serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return history, err return history, err
} }
err = json.NewDecoder(serverResp.body).Decode(&history) err = json.NewDecoder(serverResp.body).Decode(&history)
ensureReaderClosed(serverResp)
return history, err return history, err
} }
...@@ -15,10 +15,10 @@ func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (typ ...@@ -15,10 +15,10 @@ func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (typ
return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID} return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID}
} }
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID) return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -35,11 +35,11 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions ...@@ -35,11 +35,11 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
} }
serverResp, err := cli.get(ctx, "/images/json", query, nil) serverResp, err := cli.get(ctx, "/images/json", query, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return images, err return images, err
} }
err = json.NewDecoder(serverResp.body).Decode(&images) err = json.NewDecoder(serverResp.body).Decode(&images)
ensureReaderClosed(serverResp)
return images, err return images, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) ( ...@@ -23,10 +23,10 @@ func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (
} }
serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return report, err return report, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return report, fmt.Errorf("Error retrieving disk usage: %v", err) return report, fmt.Errorf("Error retrieving disk usage: %v", err)
......
...@@ -3,12 +3,12 @@ package client // import "github.com/docker/docker/client" ...@@ -3,12 +3,12 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"io" "io"
"net/http"
"net/url" "net/url"
"strings" "strings"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
) )
// ImagePull requests the docker host to pull an image from a remote registry. // ImagePull requests the docker host to pull an image from a remote registry.
...@@ -35,7 +35,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.I ...@@ -35,7 +35,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.I
} }
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
return nil, privilegeErr return nil, privilegeErr
......
...@@ -4,11 +4,11 @@ import ( ...@@ -4,11 +4,11 @@ import (
"context" "context"
"errors" "errors"
"io" "io"
"net/http"
"net/url" "net/url"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
) )
// ImagePush requests the docker host to push an image to a remote registry. // ImagePush requests the docker host to push an image to a remote registry.
...@@ -36,7 +36,7 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options types.Im ...@@ -36,7 +36,7 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options types.Im
query.Set("tag", tag) query.Set("tag", tag)
resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth) resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
return nil, privilegeErr return nil, privilegeErr
......
...@@ -21,11 +21,11 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type ...@@ -21,11 +21,11 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type
var dels []types.ImageDeleteResponseItem var dels []types.ImageDeleteResponseItem
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return dels, wrapResponseError(err, resp, "image", imageID) return dels, wrapResponseError(err, resp, "image", imageID)
} }
err = json.NewDecoder(resp.body).Decode(&dels) err = json.NewDecoder(resp.body).Decode(&dels)
ensureReaderClosed(resp)
return dels, err return dels, err
} }
...@@ -4,12 +4,12 @@ import ( ...@@ -4,12 +4,12 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/errdefs"
) )
// ImageSearch makes the docker host to search by a term in a remote registry. // ImageSearch makes the docker host to search by a term in a remote registry.
...@@ -29,7 +29,8 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I ...@@ -29,7 +29,8 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I
} }
resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth) resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { defer ensureReaderClosed(resp)
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
return results, privilegeErr return results, privilegeErr
...@@ -41,7 +42,6 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I ...@@ -41,7 +42,6 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I
} }
err = json.NewDecoder(resp.body).Decode(&results) err = json.NewDecoder(resp.body).Decode(&results)
ensureReaderClosed(resp)
return results, err return results, err
} }
......
...@@ -13,10 +13,10 @@ import ( ...@@ -13,10 +13,10 @@ import (
func (cli *Client) Info(ctx context.Context) (types.Info, error) { func (cli *Client) Info(ctx context.Context) (types.Info, error) {
var info types.Info var info types.Info
serverResp, err := cli.get(ctx, "/info", url.Values{}, nil) serverResp, err := cli.get(ctx, "/info", url.Values{}, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return info, err return info, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil {
return info, fmt.Errorf("Error reading remote info: %v", err) return info, fmt.Errorf("Error reading remote info: %v", err)
......
...@@ -39,6 +39,7 @@ type CommonAPIClient interface { ...@@ -39,6 +39,7 @@ type CommonAPIClient interface {
NegotiateAPIVersion(ctx context.Context) NegotiateAPIVersion(ctx context.Context)
NegotiateAPIVersionPing(types.Ping) NegotiateAPIVersionPing(types.Ping)
DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error) DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error)
Dialer() func(context.Context) (net.Conn, error)
Close() error Close() error
} }
...@@ -85,7 +86,8 @@ type DistributionAPIClient interface { ...@@ -85,7 +86,8 @@ type DistributionAPIClient interface {
// ImageAPIClient defines API client methods for the images // ImageAPIClient defines API client methods for the images
type ImageAPIClient interface { type ImageAPIClient interface {
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error)
BuildCancel(ctx context.Context, id string) error
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error) ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error)
ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error) ImageImport(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) (io.ReadCloser, error)
......
...@@ -3,7 +3,6 @@ package client // import "github.com/docker/docker/client" ...@@ -3,7 +3,6 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
...@@ -14,16 +13,13 @@ import ( ...@@ -14,16 +13,13 @@ import (
// It returns unauthorizedError when the authentication fails. // It returns unauthorizedError when the authentication fails.
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) { func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) {
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil) resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
defer ensureReaderClosed(resp)
if resp.statusCode == http.StatusUnauthorized {
return registry.AuthenticateOKBody{}, unauthorizedError{err}
}
if err != nil { if err != nil {
return registry.AuthenticateOKBody{}, err return registry.AuthenticateOKBody{}, err
} }
var response registry.AuthenticateOKBody var response registry.AuthenticateOKBody
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -15,11 +15,11 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options types ...@@ -15,11 +15,11 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options types
} }
var response types.NetworkCreateResponse var response types.NetworkCreateResponse
serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return response, err return response, err
} }
json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -34,10 +34,10 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, ...@@ -34,10 +34,10 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string,
query.Set("scope", options.Scope) query.Set("scope", options.Scope)
} }
resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) resp, err = cli.get(ctx, "/networks/"+networkID, query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return networkResource, nil, wrapResponseError(err, resp, "network", networkID) return networkResource, nil, wrapResponseError(err, resp, "network", networkID)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
......
...@@ -22,10 +22,10 @@ func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOpt ...@@ -22,10 +22,10 @@ func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOpt
} }
var networkResources []types.NetworkResource var networkResources []types.NetworkResource
resp, err := cli.get(ctx, "/networks", query, nil) resp, err := cli.get(ctx, "/networks", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return networkResources, err return networkResources, err
} }
err = json.NewDecoder(resp.body).Decode(&networkResources) err = json.NewDecoder(resp.body).Decode(&networkResources)
ensureReaderClosed(resp)
return networkResources, err return networkResources, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) ...@@ -23,10 +23,10 @@ func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args)
} }
serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return report, err return report, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return report, fmt.Errorf("Error retrieving network prune report: %v", err) return report, fmt.Errorf("Error retrieving network prune report: %v", err)
......
...@@ -5,6 +5,6 @@ import "context" ...@@ -5,6 +5,6 @@ import "context"
// NetworkRemove removes an existent network from the docker host. // NetworkRemove removes an existent network from the docker host.
func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "network", networkID) return wrapResponseError(err, resp, "network", networkID)
} }
...@@ -15,10 +15,10 @@ func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm ...@@ -15,10 +15,10 @@ func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm
return swarm.Node{}, nil, objectNotFoundError{object: "node", id: nodeID} return swarm.Node{}, nil, objectNotFoundError{object: "node", id: nodeID}
} }
serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID) return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -25,12 +25,12 @@ func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions) ...@@ -25,12 +25,12 @@ func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions)
} }
resp, err := cli.get(ctx, "/nodes", query, nil) resp, err := cli.get(ctx, "/nodes", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var nodes []swarm.Node var nodes []swarm.Node
err = json.NewDecoder(resp.body).Decode(&nodes) err = json.NewDecoder(resp.body).Decode(&nodes)
ensureReaderClosed(resp)
return nodes, err return nodes, err
} }
...@@ -15,6 +15,6 @@ func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types. ...@@ -15,6 +15,6 @@ func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types.
} }
resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil) resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "node", nodeID) return wrapResponseError(err, resp, "node", nodeID)
} }
package client
import (
"context"
"net"
"net/http"
"os"
"path/filepath"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
)
// FromEnv configures the client with values from environment variables.
//
// Supported environment variables:
// DOCKER_HOST to set the url to the docker server.
// DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
// DOCKER_CERT_PATH to load the TLS certificates from.
// DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func FromEnv(c *Client) error {
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
options := tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
}
tlsc, err := tlsconfig.Client(options)
if err != nil {
return err
}
c.client = &http.Client{
Transport: &http.Transport{TLSClientConfig: tlsc},
CheckRedirect: CheckRedirect,
}
}
if host := os.Getenv("DOCKER_HOST"); host != "" {
if err := WithHost(host)(c); err != nil {
return err
}
}
if version := os.Getenv("DOCKER_API_VERSION"); version != "" {
if err := WithVersion(version)(c); err != nil {
return err
}
}
return nil
}
// WithDialer applies the dialer.DialContext to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
// Deprecated: use WithDialContext
func WithDialer(dialer *net.Dialer) func(*Client) error {
return WithDialContext(dialer.DialContext)
}
// WithDialContext applies the dialer to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) func(*Client) error {
return func(c *Client) error {
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.DialContext = dialContext
return nil
}
return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport)
}
}
// WithHost overrides the client host with the specified one.
func WithHost(host string) func(*Client) error {
return func(c *Client) error {
hostURL, err := ParseHostURL(host)
if err != nil {
return err
}
c.host = host
c.proto = hostURL.Scheme
c.addr = hostURL.Host
c.basePath = hostURL.Path
if transport, ok := c.client.Transport.(*http.Transport); ok {
return sockets.ConfigureTransport(transport, c.proto, c.addr)
}
return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
}
}
// WithHTTPClient overrides the client http client with the specified one
func WithHTTPClient(client *http.Client) func(*Client) error {
return func(c *Client) error {
if client != nil {
c.client = client
}
return nil
}
}
// WithHTTPHeaders overrides the client default http headers
func WithHTTPHeaders(headers map[string]string) func(*Client) error {
return func(c *Client) error {
c.customHTTPHeaders = headers
return nil
}
}
// WithScheme overrides the client scheme with the specified one
func WithScheme(scheme string) func(*Client) error {
return func(c *Client) error {
c.scheme = scheme
return nil
}
}
// WithTLSClientConfig applies a tls config to the client transport.
func WithTLSClientConfig(cacertPath, certPath, keyPath string) func(*Client) error {
return func(c *Client) error {
opts := tlsconfig.Options{
CAFile: cacertPath,
CertFile: certPath,
KeyFile: keyPath,
ExclusiveRootPools: true,
}
config, err := tlsconfig.Client(opts)
if err != nil {
return errors.Wrap(err, "failed to create tls config")
}
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.TLSClientConfig = config
return nil
}
return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport)
}
}
// WithVersion overrides the client version with the specified one
func WithVersion(version string) func(*Client) error {
return func(c *Client) error {
c.version = version
c.manualOverride = true
return nil
}
}
...@@ -2,31 +2,63 @@ package client // import "github.com/docker/docker/client" ...@@ -2,31 +2,63 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"net/http"
"path" "path"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
) )
// Ping pings the server and returns the value of the "Docker-Experimental", "OS-Type" & "API-Version" headers // Ping pings the server and returns the value of the "Docker-Experimental",
// "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use
// a HEAD request on the endpoint, but falls back to GET if HEAD is not supported
// by the daemon.
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
var ping types.Ping var ping types.Ping
req, err := cli.buildRequest("GET", path.Join(cli.basePath, "/_ping"), nil, nil)
// Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest()
// because ping requests are used during API version negotiation, so we want
// to hit the non-versioned /_ping endpoint, not /v1.xx/_ping
req, err := cli.buildRequest("HEAD", path.Join(cli.basePath, "/_ping"), nil, nil)
if err != nil { if err != nil {
return ping, err return ping, err
} }
serverResp, err := cli.doRequest(ctx, req) serverResp, err := cli.doRequest(ctx, req)
if err == nil {
defer ensureReaderClosed(serverResp)
switch serverResp.statusCode {
case http.StatusOK, http.StatusInternalServerError:
// Server handled the request, so parse the response
return parsePingResponse(cli, serverResp)
}
}
req, err = cli.buildRequest("GET", path.Join(cli.basePath, "/_ping"), nil, nil)
if err != nil { if err != nil {
return ping, err return ping, err
} }
serverResp, err = cli.doRequest(ctx, req)
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)
if err != nil {
return ping, err
}
return parsePingResponse(cli, serverResp)
}
if serverResp.header != nil { func parsePingResponse(cli *Client, resp serverResponse) (types.Ping, error) {
ping.APIVersion = serverResp.header.Get("API-Version") var ping types.Ping
if resp.header == nil {
if serverResp.header.Get("Docker-Experimental") == "true" { err := cli.checkResponseErr(resp)
ping.Experimental = true return ping, errdefs.FromStatusCode(err, resp.statusCode)
} }
ping.OSType = serverResp.header.Get("OSType") ping.APIVersion = resp.header.Get("API-Version")
ping.OSType = resp.header.Get("OSType")
if resp.header.Get("Docker-Experimental") == "true" {
ping.Experimental = true
}
if bv := resp.header.Get("Builder-Version"); bv != "" {
ping.BuilderVersion = types.BuilderVersion(bv)
} }
return ping, cli.checkResponseErr(serverResp) err := cli.checkResponseErr(resp)
return ping, errdefs.FromStatusCode(err, resp.statusCode)
} }
...@@ -18,9 +18,6 @@ func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, cr ...@@ -18,9 +18,6 @@ func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, cr
query.Set("name", createOptions.RepoName) query.Set("name", createOptions.RepoName)
resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers) resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers)
if err != nil {
return err
}
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return err
} }
...@@ -15,11 +15,11 @@ func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*type ...@@ -15,11 +15,11 @@ func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*type
return nil, nil, objectNotFoundError{object: "plugin", id: name} return nil, nil, objectNotFoundError{object: "plugin", id: name}
} }
resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, nil, wrapResponseError(err, resp, "plugin", name) return nil, nil, wrapResponseError(err, resp, "plugin", name)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
......
...@@ -4,11 +4,11 @@ import ( ...@@ -4,11 +4,11 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"io" "io"
"net/http"
"net/url" "net/url"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -78,7 +78,7 @@ func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileg ...@@ -78,7 +78,7 @@ func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileg
func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options types.PluginInstallOptions) (types.PluginPrivileges, error) { func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options types.PluginInstallOptions) (types.PluginPrivileges, error) {
resp, err := cli.tryPluginPrivileges(ctx, query, options.RegistryAuth) resp, err := cli.tryPluginPrivileges(ctx, query, options.RegistryAuth)
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil { if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
// todo: do inspect before to check existing name before checking privileges // todo: do inspect before to check existing name before checking privileges
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
......
...@@ -22,11 +22,11 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P ...@@ -22,11 +22,11 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P
query.Set("filters", filterJSON) query.Set("filters", filterJSON)
} }
resp, err := cli.get(ctx, "/plugins", query, nil) resp, err := cli.get(ctx, "/plugins", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return plugins, wrapResponseError(err, resp, "plugin", "") return plugins, wrapResponseError(err, resp, "plugin", "")
} }
err = json.NewDecoder(resp.body).Decode(&plugins) err = json.NewDecoder(resp.body).Decode(&plugins)
ensureReaderClosed(resp)
return plugins, err return plugins, err
} }
...@@ -15,6 +15,6 @@ func (cli *Client) PluginRemove(ctx context.Context, name string, options types. ...@@ -15,6 +15,6 @@ func (cli *Client) PluginRemove(ctx context.Context, name string, options types.
} }
resp, err := cli.delete(ctx, "/plugins/"+name, query, nil) resp, err := cli.delete(ctx, "/plugins/"+name, query, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "plugin", name) return wrapResponseError(err, resp, "plugin", name)
} }
...@@ -15,8 +15,8 @@ import ( ...@@ -15,8 +15,8 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/net/context/ctxhttp"
) )
// serverResponse is a wrapper for http API responses. // serverResponse is a wrapper for http API responses.
...@@ -121,22 +121,24 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u ...@@ -121,22 +121,24 @@ func (cli *Client) sendRequest(ctx context.Context, method, path string, query u
} }
resp, err := cli.doRequest(ctx, req) resp, err := cli.doRequest(ctx, req)
if err != nil { if err != nil {
return resp, err return resp, errdefs.FromStatusCode(err, resp.statusCode)
} }
return resp, cli.checkResponseErr(resp) err = cli.checkResponseErr(resp)
return resp, errdefs.FromStatusCode(err, resp.statusCode)
} }
func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) { func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) {
serverResp := serverResponse{statusCode: -1, reqURL: req.URL} serverResp := serverResponse{statusCode: -1, reqURL: req.URL}
resp, err := ctxhttp.Do(ctx, cli.client, req) req = req.WithContext(ctx)
resp, err := cli.client.Do(req)
if err != nil { if err != nil {
if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") { if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err) return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
} }
if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") { if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err) return serverResp, errors.Wrap(err, "The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings")
} }
// Don't decorate context sentinel errors; users may be comparing to // Don't decorate context sentinel errors; users may be comparing to
...@@ -195,9 +197,21 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error { ...@@ -195,9 +197,21 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error {
return nil return nil
} }
body, err := ioutil.ReadAll(serverResp.body) var body []byte
if err != nil { var err error
return err if serverResp.body != nil {
bodyMax := 1 * 1024 * 1024 // 1 MiB
bodyR := &io.LimitedReader{
R: serverResp.body,
N: int64(bodyMax),
}
body, err = ioutil.ReadAll(bodyR)
if err != nil {
return err
}
if bodyR.N == 0 {
return fmt.Errorf("request returned %s with a message (> %d bytes) for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), bodyMax, serverResp.reqURL)
}
} }
if len(body) == 0 { if len(body) == 0 {
return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL) return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL)
...@@ -212,14 +226,14 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error { ...@@ -212,14 +226,14 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error {
if (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) && ct == "application/json" { if (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) && ct == "application/json" {
var errorResponse types.ErrorResponse var errorResponse types.ErrorResponse
if err := json.Unmarshal(body, &errorResponse); err != nil { if err := json.Unmarshal(body, &errorResponse); err != nil {
return fmt.Errorf("Error reading JSON: %v", err) return errors.Wrap(err, "Error reading JSON")
} }
errorMessage = errorResponse.Message errorMessage = strings.TrimSpace(errorResponse.Message)
} else { } else {
errorMessage = string(body) errorMessage = strings.TrimSpace(string(body))
} }
return fmt.Errorf("Error response from daemon: %s", strings.TrimSpace(errorMessage)) return errors.Wrap(errors.New(errorMessage), "Error response from daemon")
} }
func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request { func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request {
......
...@@ -15,11 +15,11 @@ func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (t ...@@ -15,11 +15,11 @@ func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (t
return response, err return response, err
} }
resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil) resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -18,10 +18,10 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S ...@@ -18,10 +18,10 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S
return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id} return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id}
} }
resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) resp, err := cli.get(ctx, "/secrets/"+id, nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id) return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
......
...@@ -27,12 +27,12 @@ func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptio ...@@ -27,12 +27,12 @@ func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptio
} }
resp, err := cli.get(ctx, "/secrets", query, nil) resp, err := cli.get(ctx, "/secrets", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var secrets []swarm.Secret var secrets []swarm.Secret
err = json.NewDecoder(resp.body).Decode(&secrets) err = json.NewDecoder(resp.body).Decode(&secrets)
ensureReaderClosed(resp)
return secrets, err return secrets, err
} }
...@@ -8,6 +8,6 @@ func (cli *Client) SecretRemove(ctx context.Context, id string) error { ...@@ -8,6 +8,6 @@ func (cli *Client) SecretRemove(ctx context.Context, id string) error {
return err return err
} }
resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil) resp, err := cli.delete(ctx, "/secrets/"+id, nil, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "secret", id) return wrapResponseError(err, resp, "secret", id)
} }
...@@ -72,6 +72,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, ...@@ -72,6 +72,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
var response types.ServiceCreateResponse var response types.ServiceCreateResponse
resp, err := cli.post(ctx, "/services/create", nil, service, headers) resp, err := cli.post(ctx, "/services/create", nil, service, headers)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
...@@ -82,7 +83,6 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, ...@@ -82,7 +83,6 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image)) response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image))
} }
ensureReaderClosed(resp)
return response, err return response, err
} }
......
...@@ -20,10 +20,10 @@ func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, ...@@ -20,10 +20,10 @@ func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string,
query := url.Values{} query := url.Values{}
query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults)) query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults))
serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID) return swarm.Service{}, nil, wrapResponseError(err, serverResp, "service", serviceID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -24,12 +24,12 @@ func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOpt ...@@ -24,12 +24,12 @@ func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOpt
} }
resp, err := cli.get(ctx, "/services", query, nil) resp, err := cli.get(ctx, "/services", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var services []swarm.Service var services []swarm.Service
err = json.NewDecoder(resp.body).Decode(&services) err = json.NewDecoder(resp.body).Decode(&services)
ensureReaderClosed(resp)
return services, err return services, err
} }
...@@ -5,6 +5,6 @@ import "context" ...@@ -5,6 +5,6 @@ import "context"
// ServiceRemove kills and removes a service. // ServiceRemove kills and removes a service.
func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error { func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error {
resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "service", serviceID) return wrapResponseError(err, resp, "service", serviceID)
} }
...@@ -10,7 +10,9 @@ import ( ...@@ -10,7 +10,9 @@ import (
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
) )
// ServiceUpdate updates a Service. // ServiceUpdate updates a Service. The version number is required to avoid conflicting writes.
// It should be the value as set *before* the update. You can find this value in the Meta field
// of swarm.Service, which can be found using ServiceInspectWithRaw.
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) { func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
var ( var (
query = url.Values{} query = url.Values{}
...@@ -77,6 +79,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version ...@@ -77,6 +79,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
var response types.ServiceUpdateResponse var response types.ServiceUpdateResponse
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
...@@ -87,6 +90,5 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version ...@@ -87,6 +90,5 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image)) response.Warnings = append(response.Warnings, digestWarning(service.TaskTemplate.ContainerSpec.Image))
} }
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -14,5 +14,5 @@ func (cli *Client) DialSession(ctx context.Context, proto string, meta map[strin ...@@ -14,5 +14,5 @@ func (cli *Client) DialSession(ctx context.Context, proto string, meta map[strin
} }
req = cli.addHeaders(req, meta) req = cli.addHeaders(req, meta)
return cli.setupHijackConn(req, proto) return cli.setupHijackConn(ctx, req, proto)
} }
...@@ -10,12 +10,12 @@ import ( ...@@ -10,12 +10,12 @@ import (
// SwarmGetUnlockKey retrieves the swarm's unlock key. // SwarmGetUnlockKey retrieves the swarm's unlock key.
func (cli *Client) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) { func (cli *Client) SwarmGetUnlockKey(ctx context.Context) (types.SwarmUnlockKeyResponse, error) {
serverResp, err := cli.get(ctx, "/swarm/unlockkey", nil, nil) serverResp, err := cli.get(ctx, "/swarm/unlockkey", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return types.SwarmUnlockKeyResponse{}, err return types.SwarmUnlockKeyResponse{}, err
} }
var response types.SwarmUnlockKeyResponse var response types.SwarmUnlockKeyResponse
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -10,12 +10,12 @@ import ( ...@@ -10,12 +10,12 @@ import (
// SwarmInit initializes the swarm. // SwarmInit initializes the swarm.
func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) { func (cli *Client) SwarmInit(ctx context.Context, req swarm.InitRequest) (string, error) {
serverResp, err := cli.post(ctx, "/swarm/init", nil, req, nil) serverResp, err := cli.post(ctx, "/swarm/init", nil, req, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return "", err return "", err
} }
var response string var response string
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -10,12 +10,12 @@ import ( ...@@ -10,12 +10,12 @@ import (
// SwarmInspect inspects the swarm. // SwarmInspect inspects the swarm.
func (cli *Client) SwarmInspect(ctx context.Context) (swarm.Swarm, error) { func (cli *Client) SwarmInspect(ctx context.Context) (swarm.Swarm, error) {
serverResp, err := cli.get(ctx, "/swarm", nil, nil) serverResp, err := cli.get(ctx, "/swarm", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return swarm.Swarm{}, err return swarm.Swarm{}, err
} }
var response swarm.Swarm var response swarm.Swarm
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -15,10 +15,10 @@ func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm ...@@ -15,10 +15,10 @@ func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm
return swarm.Task{}, nil, objectNotFoundError{object: "task", id: taskID} return swarm.Task{}, nil, objectNotFoundError{object: "task", id: taskID}
} }
serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID) return swarm.Task{}, nil, wrapResponseError(err, serverResp, "task", taskID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -24,12 +24,12 @@ func (cli *Client) TaskList(ctx context.Context, options types.TaskListOptions) ...@@ -24,12 +24,12 @@ func (cli *Client) TaskList(ctx context.Context, options types.TaskListOptions)
} }
resp, err := cli.get(ctx, "/tasks", query, nil) resp, err := cli.get(ctx, "/tasks", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var tasks []swarm.Task var tasks []swarm.Task
err = json.NewDecoder(resp.body).Decode(&tasks) err = json.NewDecoder(resp.body).Decode(&tasks)
ensureReaderClosed(resp)
return tasks, err return tasks, err
} }
...@@ -10,12 +10,12 @@ import ( ...@@ -10,12 +10,12 @@ import (
// ServerVersion returns information of the docker client and server host. // ServerVersion returns information of the docker client and server host.
func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) { func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
resp, err := cli.get(ctx, "/version", nil, nil) resp, err := cli.get(ctx, "/version", nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return types.Version{}, err return types.Version{}, err
} }
var server types.Version var server types.Version
err = json.NewDecoder(resp.body).Decode(&server) err = json.NewDecoder(resp.body).Decode(&server)
ensureReaderClosed(resp)
return server, err return server, err
} }
...@@ -12,10 +12,10 @@ import ( ...@@ -12,10 +12,10 @@ import (
func (cli *Client) VolumeCreate(ctx context.Context, options volumetypes.VolumeCreateBody) (types.Volume, error) { func (cli *Client) VolumeCreate(ctx context.Context, options volumetypes.VolumeCreateBody) (types.Volume, error) {
var volume types.Volume var volume types.Volume
resp, err := cli.post(ctx, "/volumes/create", nil, options, nil) resp, err := cli.post(ctx, "/volumes/create", nil, options, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return volume, err return volume, err
} }
err = json.NewDecoder(resp.body).Decode(&volume) err = json.NewDecoder(resp.body).Decode(&volume)
ensureReaderClosed(resp)
return volume, err return volume, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (t ...@@ -23,10 +23,10 @@ func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (t
var volume types.Volume var volume types.Volume
resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil) resp, err := cli.get(ctx, "/volumes/"+volumeID, nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return volume, nil, wrapResponseError(err, resp, "volume", volumeID) return volume, nil, wrapResponseError(err, resp, "volume", volumeID)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
......
...@@ -22,11 +22,11 @@ func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (volumet ...@@ -22,11 +22,11 @@ func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (volumet
query.Set("filters", filterJSON) query.Set("filters", filterJSON)
} }
resp, err := cli.get(ctx, "/volumes", query, nil) resp, err := cli.get(ctx, "/volumes", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return volumes, err return volumes, err
} }
err = json.NewDecoder(resp.body).Decode(&volumes) err = json.NewDecoder(resp.body).Decode(&volumes)
ensureReaderClosed(resp)
return volumes, err return volumes, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) ...@@ -23,10 +23,10 @@ func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args)
} }
serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return report, err return report, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return report, fmt.Errorf("Error retrieving volume prune report: %v", err) return report, fmt.Errorf("Error retrieving volume prune report: %v", err)
......
...@@ -16,6 +16,6 @@ func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool ...@@ -16,6 +16,6 @@ func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool
} }
} }
resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil) resp, err := cli.delete(ctx, "/volumes/"+volumeID, query, nil)
ensureReaderClosed(resp) defer ensureReaderClosed(resp)
return wrapResponseError(err, resp, "volume", volumeID) return wrapResponseError(err, resp, "volume", volumeID)
} }
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"defs.go",
"doc.go",
"helpers.go",
"http_helpers.go",
"is.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/errdefs",
importpath = "github.com/docker/docker/errdefs",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/docker/distribution/registry/api/errcode:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
"//vendor/google.golang.org/grpc/codes:go_default_library",
"//vendor/google.golang.org/grpc/status:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
package errdefs // import "github.com/docker/docker/errdefs"
// ErrNotFound signals that the requested object doesn't exist
type ErrNotFound interface {
NotFound()
}
// ErrInvalidParameter signals that the user input is invalid
type ErrInvalidParameter interface {
InvalidParameter()
}
// ErrConflict signals that some internal state conflicts with the requested action and can't be performed.
// A change in state should be able to clear this error.
type ErrConflict interface {
Conflict()
}
// ErrUnauthorized is used to signify that the user is not authorized to perform a specific action
type ErrUnauthorized interface {
Unauthorized()
}
// ErrUnavailable signals that the requested action/subsystem is not available.
type ErrUnavailable interface {
Unavailable()
}
// ErrForbidden signals that the requested action cannot be performed under any circumstances.
// When a ErrForbidden is returned, the caller should never retry the action.
type ErrForbidden interface {
Forbidden()
}
// ErrSystem signals that some internal error occurred.
// An example of this would be a failed mount request.
type ErrSystem interface {
System()
}
// ErrNotModified signals that an action can't be performed because it's already in the desired state
type ErrNotModified interface {
NotModified()
}
// ErrNotImplemented signals that the requested action/feature is not implemented on the system as configured.
type ErrNotImplemented interface {
NotImplemented()
}
// ErrUnknown signals that the kind of error that occurred is not known.
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()
}
// Package errdefs defines a set of error interfaces that packages should use for communicating classes of errors.
// Errors that cross the package boundary should implement one (and only one) of these interfaces.
//
// Packages should not reference these interfaces directly, only implement them.
// To check if a particular error implements one of these interfaces, there are helper
// functions provided (e.g. `Is<SomeError>`) which can be used rather than asserting the interfaces directly.
// If you must assert on these interfaces, be sure to check the causal chain (`err.Cause()`).
package errdefs // import "github.com/docker/docker/errdefs"
package errdefs // import "github.com/docker/docker/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 || IsNotFound(err) {
return err
}
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 || IsInvalidParameter(err) {
return err
}
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 || IsConflict(err) {
return err
}
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 || IsUnauthorized(err) {
return err
}
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 {
if err == nil || IsUnavailable(err) {
return err
}
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 || IsForbidden(err) {
return err
}
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 || IsSystem(err) {
return err
}
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 || IsNotModified(err) {
return err
}
return errNotModified{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 || IsNotImplemented(err) {
return err
}
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 || IsUnknown(err) {
return err
}
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 || IsCancelled(err) {
return err
}
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 || IsDeadline(err) {
return err
}
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 || IsDataLoss(err) {
return err
}
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)
}
package errdefs // import "github.com/docker/docker/errdefs"
import (
"fmt"
"net/http"
"github.com/docker/distribution/registry/api/errcode"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// GetHTTPErrorStatusCode retrieves status code from error message.
func GetHTTPErrorStatusCode(err error) int {
if err == nil {
logrus.WithFields(logrus.Fields{"error": err}).Error("unexpected HTTP error handling")
return http.StatusInternalServerError
}
var statusCode int
// Stop right there
// Are you sure you should be adding a new error class here? Do one of the existing ones work?
// Note that the below functions are already checking the error causal chain for matches.
switch {
case IsNotFound(err):
statusCode = http.StatusNotFound
case IsInvalidParameter(err):
statusCode = http.StatusBadRequest
case IsConflict(err):
statusCode = http.StatusConflict
case IsUnauthorized(err):
statusCode = http.StatusUnauthorized
case IsUnavailable(err):
statusCode = http.StatusServiceUnavailable
case IsForbidden(err):
statusCode = http.StatusForbidden
case IsNotModified(err):
statusCode = http.StatusNotModified
case IsNotImplemented(err):
statusCode = http.StatusNotImplemented
case IsSystem(err) || IsUnknown(err) || IsDataLoss(err) || IsDeadline(err) || IsCancelled(err):
statusCode = http.StatusInternalServerError
default:
statusCode = statusCodeFromGRPCError(err)
if statusCode != http.StatusInternalServerError {
return statusCode
}
statusCode = statusCodeFromDistributionError(err)
if statusCode != http.StatusInternalServerError {
return statusCode
}
if e, ok := err.(causer); ok {
return GetHTTPErrorStatusCode(e.Cause())
}
logrus.WithFields(logrus.Fields{
"module": "api",
"error_type": fmt.Sprintf("%T", err),
}).Debugf("FIXME: Got an API for which error does not match any expected type!!!: %+v", err)
}
if statusCode == 0 {
statusCode = http.StatusInternalServerError
}
return statusCode
}
// FromStatusCode creates an errdef error, based on the provided HTTP status-code
func FromStatusCode(err error, statusCode int) error {
if err == nil {
return err
}
switch statusCode {
case http.StatusNotFound:
err = NotFound(err)
case http.StatusBadRequest:
err = InvalidParameter(err)
case http.StatusConflict:
err = Conflict(err)
case http.StatusUnauthorized:
err = Unauthorized(err)
case http.StatusServiceUnavailable:
err = Unavailable(err)
case http.StatusForbidden:
err = Forbidden(err)
case http.StatusNotModified:
err = NotModified(err)
case http.StatusNotImplemented:
err = NotImplemented(err)
case http.StatusInternalServerError:
if !IsSystem(err) && !IsUnknown(err) && !IsDataLoss(err) && !IsDeadline(err) && !IsCancelled(err) {
err = System(err)
}
default:
logrus.WithFields(logrus.Fields{
"module": "api",
"status_code": fmt.Sprintf("%d", statusCode),
}).Debugf("FIXME: Got an status-code for which error does not match any expected type!!!: %d", statusCode)
switch {
case statusCode >= 200 && statusCode < 400:
// it's a client error
case statusCode >= 400 && statusCode < 500:
err = InvalidParameter(err)
case statusCode >= 500 && statusCode < 600:
err = System(err)
default:
err = Unknown(err)
}
}
return err
}
// statusCodeFromGRPCError returns status code according to gRPC error
func statusCodeFromGRPCError(err error) int {
switch status.Code(err) {
case codes.InvalidArgument: // code 3
return http.StatusBadRequest
case codes.NotFound: // code 5
return http.StatusNotFound
case codes.AlreadyExists: // code 6
return http.StatusConflict
case codes.PermissionDenied: // code 7
return http.StatusForbidden
case codes.FailedPrecondition: // code 9
return http.StatusBadRequest
case codes.Unauthenticated: // code 16
return http.StatusUnauthorized
case codes.OutOfRange: // code 11
return http.StatusBadRequest
case codes.Unimplemented: // code 12
return http.StatusNotImplemented
case codes.Unavailable: // code 14
return http.StatusServiceUnavailable
default:
if e, ok := err.(causer); ok {
return statusCodeFromGRPCError(e.Cause())
}
// codes.Canceled(1)
// codes.Unknown(2)
// codes.DeadlineExceeded(4)
// codes.ResourceExhausted(8)
// codes.Aborted(10)
// codes.Internal(13)
// codes.DataLoss(15)
return http.StatusInternalServerError
}
}
// statusCodeFromDistributionError returns status code according to registry errcode
// code is loosely based on errcode.ServeJSON() in docker/distribution
func statusCodeFromDistributionError(err error) int {
switch errs := err.(type) {
case errcode.Errors:
if len(errs) < 1 {
return http.StatusInternalServerError
}
if _, ok := errs[0].(errcode.ErrorCoder); ok {
return statusCodeFromDistributionError(errs[0])
}
case errcode.ErrorCoder:
return errs.ErrorCode().Descriptor().HTTPStatusCode
default:
if e, ok := err.(causer); ok {
return statusCodeFromDistributionError(e.Cause())
}
}
return http.StatusInternalServerError
}
package errdefs // import "github.com/docker/docker/errdefs"
type causer interface {
Cause() error
}
func getImplementer(err error) error {
switch e := err.(type) {
case
ErrNotFound,
ErrInvalidParameter,
ErrConflict,
ErrUnauthorized,
ErrUnavailable,
ErrForbidden,
ErrSystem,
ErrNotModified,
ErrNotImplemented,
ErrCancelled,
ErrDeadline,
ErrDataLoss,
ErrUnknown:
return err
case causer:
return getImplementer(e.Cause())
default:
return err
}
}
// IsNotFound returns if the passed in error is an ErrNotFound
func IsNotFound(err error) bool {
_, ok := getImplementer(err).(ErrNotFound)
return ok
}
// IsInvalidParameter returns if the passed in error is an ErrInvalidParameter
func IsInvalidParameter(err error) bool {
_, ok := getImplementer(err).(ErrInvalidParameter)
return ok
}
// IsConflict returns if the passed in error is an ErrConflict
func IsConflict(err error) bool {
_, ok := getImplementer(err).(ErrConflict)
return ok
}
// IsUnauthorized returns if the passed in error is an ErrUnauthorized
func IsUnauthorized(err error) bool {
_, ok := getImplementer(err).(ErrUnauthorized)
return ok
}
// IsUnavailable returns if the passed in error is an ErrUnavailable
func IsUnavailable(err error) bool {
_, ok := getImplementer(err).(ErrUnavailable)
return ok
}
// IsForbidden returns if the passed in error is an ErrForbidden
func IsForbidden(err error) bool {
_, ok := getImplementer(err).(ErrForbidden)
return ok
}
// IsSystem returns if the passed in error is an ErrSystem
func IsSystem(err error) bool {
_, ok := getImplementer(err).(ErrSystem)
return ok
}
// IsNotModified returns if the passed in error is a NotModified error
func IsNotModified(err error) bool {
_, ok := getImplementer(err).(ErrNotModified)
return ok
}
// IsNotImplemented returns if the passed in error is an ErrNotImplemented
func IsNotImplemented(err error) bool {
_, ok := getImplementer(err).(ErrNotImplemented)
return ok
}
// IsUnknown returns if the passed in error is an ErrUnknown
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
}
...@@ -7,9 +7,9 @@ go_library( ...@@ -7,9 +7,9 @@ go_library(
importpath = "github.com/docker/docker/pkg/jsonmessage", importpath = "github.com/docker/docker/pkg/jsonmessage",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//vendor/github.com/Nvveen/Gotty:go_default_library",
"//vendor/github.com/docker/docker/pkg/term:go_default_library", "//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/github.com/docker/go-units:go_default_library", "//vendor/github.com/docker/go-units:go_default_library",
"//vendor/github.com/morikuni/aec:go_default_library",
], ],
) )
......
...@@ -4,13 +4,12 @@ import ( ...@@ -4,13 +4,12 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"os"
"strings" "strings"
"time" "time"
"github.com/Nvveen/Gotty"
"github.com/docker/docker/pkg/term" "github.com/docker/docker/pkg/term"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/morikuni/aec"
) )
// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to // RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to
...@@ -151,60 +150,23 @@ type JSONMessage struct { ...@@ -151,60 +150,23 @@ type JSONMessage struct {
Aux *json.RawMessage `json:"aux,omitempty"` Aux *json.RawMessage `json:"aux,omitempty"`
} }
/* Satisfied by gotty.TermInfo as well as noTermInfo from below */ func clearLine(out io.Writer) {
type termInfo interface { eraseMode := aec.EraseModes.All
Parse(attr string, params ...interface{}) (string, error) cl := aec.EraseLine(eraseMode)
fmt.Fprint(out, cl)
} }
type noTermInfo struct{} // canary used when no terminfo. func cursorUp(out io.Writer, l uint) {
fmt.Fprint(out, aec.Up(l))
func (ti *noTermInfo) Parse(attr string, params ...interface{}) (string, error) {
return "", fmt.Errorf("noTermInfo")
}
func clearLine(out io.Writer, ti termInfo) {
// el2 (clear whole line) is not exposed by terminfo.
// First clear line from beginning to cursor
if attr, err := ti.Parse("el1"); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[1K")
}
// Then clear line from cursor to end
if attr, err := ti.Parse("el"); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[K")
}
}
func cursorUp(out io.Writer, ti termInfo, l int) {
if l == 0 { // Should never be the case, but be tolerant
return
}
if attr, err := ti.Parse("cuu", l); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[%dA", l)
}
} }
func cursorDown(out io.Writer, ti termInfo, l int) { func cursorDown(out io.Writer, l uint) {
if l == 0 { // Should never be the case, but be tolerant fmt.Fprint(out, aec.Down(l))
return
}
if attr, err := ti.Parse("cud", l); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[%dB", l)
}
} }
// Display displays the JSONMessage to `out`. `termInfo` is non-nil if `out` // Display displays the JSONMessage to `out`. If `isTerminal` is true, it will erase the
// is a terminal. If this is the case, it will erase the entire current line // entire current line when displaying the progressbar.
// when displaying the progressbar. func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error {
if jm.Error != nil { if jm.Error != nil {
if jm.Error.Code == 401 { if jm.Error.Code == 401 {
return fmt.Errorf("authentication is required") return fmt.Errorf("authentication is required")
...@@ -212,8 +174,8 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error { ...@@ -212,8 +174,8 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error {
return jm.Error return jm.Error
} }
var endl string var endl string
if termInfo != nil && jm.Stream == "" && jm.Progress != nil { if isTerminal && jm.Stream == "" && jm.Progress != nil {
clearLine(out, termInfo) clearLine(out)
endl = "\r" endl = "\r"
fmt.Fprintf(out, endl) fmt.Fprintf(out, endl)
} else if jm.Progress != nil && jm.Progress.String() != "" { //disable progressbar in non-terminal } else if jm.Progress != nil && jm.Progress.String() != "" { //disable progressbar in non-terminal
...@@ -230,7 +192,7 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error { ...@@ -230,7 +192,7 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error {
if jm.From != "" { if jm.From != "" {
fmt.Fprintf(out, "(from %s) ", jm.From) fmt.Fprintf(out, "(from %s) ", jm.From)
} }
if jm.Progress != nil && termInfo != nil { if jm.Progress != nil && isTerminal {
fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl) fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl)
} else if jm.ProgressMessage != "" { //deprecated } else if jm.ProgressMessage != "" { //deprecated
fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl) fmt.Fprintf(out, "%s %s%s", jm.Status, jm.ProgressMessage, endl)
...@@ -248,25 +210,11 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error { ...@@ -248,25 +210,11 @@ func (jm *JSONMessage) Display(out io.Writer, termInfo termInfo) error {
func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error { func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error {
var ( var (
dec = json.NewDecoder(in) dec = json.NewDecoder(in)
ids = make(map[string]int) ids = make(map[string]uint)
) )
var termInfo termInfo
if isTerminal {
term := os.Getenv("TERM")
if term == "" {
term = "vt102"
}
var err error
if termInfo, err = gotty.OpenTermInfo(term); err != nil {
termInfo = &noTermInfo{}
}
}
for { for {
diff := 0 var diff uint
var jm JSONMessage var jm JSONMessage
if err := dec.Decode(&jm); err != nil { if err := dec.Decode(&jm); err != nil {
if err == io.EOF { if err == io.EOF {
...@@ -294,15 +242,15 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, ...@@ -294,15 +242,15 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr,
// when we output something that's not // when we output something that's not
// accounted for in the map, such as a line // accounted for in the map, such as a line
// with no ID. // with no ID.
line = len(ids) line = uint(len(ids))
ids[jm.ID] = line ids[jm.ID] = line
if termInfo != nil { if isTerminal {
fmt.Fprintf(out, "\n") fmt.Fprintf(out, "\n")
} }
} }
diff = len(ids) - line diff = uint(len(ids)) - line
if termInfo != nil { if isTerminal {
cursorUp(out, termInfo, diff) cursorUp(out, diff)
} }
} else { } else {
// When outputting something that isn't progress // When outputting something that isn't progress
...@@ -310,11 +258,11 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, ...@@ -310,11 +258,11 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr,
// don't want progress entries from some previous // don't want progress entries from some previous
// operation to be updated (for example, pull -a // operation to be updated (for example, pull -a
// with multiple tags). // with multiple tags).
ids = make(map[string]int) ids = make(map[string]uint)
} }
err := jm.Display(out, termInfo) err := jm.Display(out, isTerminal)
if jm.ID != "" && termInfo != nil { if jm.ID != "" && isTerminal {
cursorDown(out, termInfo, diff) cursorDown(out, diff)
} }
if err != nil { if err != nil {
return err return err
......
...@@ -17,6 +17,8 @@ go_library( ...@@ -17,6 +17,8 @@ go_library(
"mountinfo_unsupported.go", "mountinfo_unsupported.go",
"mountinfo_windows.go", "mountinfo_windows.go",
"sharedsubtree_linux.go", "sharedsubtree_linux.go",
"unmount_unix.go",
"unmount_unsupported.go",
], ],
cgo = True, cgo = True,
importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/pkg/mount", importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/pkg/mount",
...@@ -25,12 +27,36 @@ go_library( ...@@ -25,12 +27,36 @@ go_library(
deps = [ deps = [
"//vendor/github.com/sirupsen/logrus:go_default_library", "//vendor/github.com/sirupsen/logrus:go_default_library",
] + select({ ] + select({
"@io_bazel_rules_go//go/platform:android": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [ "@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:linux": [ "@io_bazel_rules_go//go/platform:linux": [
"//vendor/golang.org/x/sys/unix:go_default_library", "//vendor/golang.org/x/sys/unix:go_default_library",
], ],
"@io_bazel_rules_go//go/platform:nacl": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"//conditions:default": [], "//conditions:default": [],
}), }),
) )
......
...@@ -135,15 +135,3 @@ func parseOptions(options string) (int, string) { ...@@ -135,15 +135,3 @@ func parseOptions(options string) (int, string) {
} }
return flag, strings.Join(data, ",") return flag, strings.Join(data, ",")
} }
// ParseTmpfsOptions parse fstab type mount options into flags and data
func ParseTmpfsOptions(options string) (int, string, error) {
flags, data := parseOptions(options)
for _, o := range strings.Split(data, ",") {
opt := strings.SplitN(o, "=", 2)
if !validFlags[opt[0]] {
return 0, "", fmt.Errorf("Invalid tmpfs option %q", opt)
}
}
return flags, data, nil
}
...@@ -2,12 +2,46 @@ package mount // import "github.com/docker/docker/pkg/mount" ...@@ -2,12 +2,46 @@ package mount // import "github.com/docker/docker/pkg/mount"
import ( import (
"sort" "sort"
"strconv"
"strings" "strings"
"syscall"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// mountError records an error from mount or unmount operation
type mountError struct {
op string
source, target string
flags uintptr
data string
err error
}
func (e *mountError) Error() string {
out := e.op + " "
if e.source != "" {
out += e.source + ":" + e.target
} else {
out += e.target
}
if e.flags != uintptr(0) {
out += ", flags: 0x" + strconv.FormatUint(uint64(e.flags), 16)
}
if e.data != "" {
out += ", data: " + e.data
}
out += ": " + e.err.Error()
return out
}
// Cause returns the underlying cause of the error
func (e *mountError) Cause() error {
return e.err
}
// FilterFunc is a type defining a callback function // FilterFunc is a type defining a callback function
// to filter out unwanted entries. It takes a pointer // to filter out unwanted entries. It takes a pointer
// to an Info struct (not fully populated, currently // to an Info struct (not fully populated, currently
...@@ -89,12 +123,7 @@ func ForceMount(device, target, mType, options string) error { ...@@ -89,12 +123,7 @@ func ForceMount(device, target, mType, options string) error {
// Unmount lazily unmounts a filesystem on supported platforms, otherwise // Unmount lazily unmounts a filesystem on supported platforms, otherwise
// does a normal unmount. // does a normal unmount.
func Unmount(target string) error { func Unmount(target string) error {
err := unmount(target, mntDetach) return unmount(target, mntDetach)
if err == syscall.EINVAL {
// ignore "not mounted" error
err = nil
}
return err
} }
// RecursiveUnmount unmounts the target and all mounts underneath, starting with // RecursiveUnmount unmounts the target and all mounts underneath, starting with
...@@ -114,25 +143,14 @@ func RecursiveUnmount(target string) error { ...@@ -114,25 +143,14 @@ func RecursiveUnmount(target string) error {
logrus.Debugf("Trying to unmount %s", m.Mountpoint) logrus.Debugf("Trying to unmount %s", m.Mountpoint)
err = unmount(m.Mountpoint, mntDetach) err = unmount(m.Mountpoint, mntDetach)
if err != nil { if err != nil {
// If the error is EINVAL either this whole package is wrong (invalid flags passed to unmount(2)) or this is if i == len(mounts)-1 { // last mount
// not a mountpoint (which is ok in this case).
// Meanwhile calling `Mounted()` is very expensive.
//
// We've purposefully used `syscall.EINVAL` here instead of `unix.EINVAL` to avoid platform branching
// Since `EINVAL` is defined for both Windows and Linux in the `syscall` package (and other platforms),
// this is nicer than defining a custom value that we can refer to in each platform file.
if err == syscall.EINVAL {
continue
}
if i == len(mounts)-1 {
if mounted, e := Mounted(m.Mountpoint); e != nil || mounted { if mounted, e := Mounted(m.Mountpoint); e != nil || mounted {
return err return err
} }
continue } else {
// This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem
logrus.WithError(err).Warnf("Failed to unmount submount %s", m.Mountpoint)
} }
// This is some submount, we can ignore this error for now, the final unmount will fail if this is a real problem
logrus.WithError(err).Warnf("Failed to unmount submount %s", m.Mountpoint)
continue
} }
logrus.Debugf("Unmounted %s", m.Mountpoint) logrus.Debugf("Unmounted %s", m.Mountpoint)
......
...@@ -11,11 +11,9 @@ package mount // import "github.com/docker/docker/pkg/mount" ...@@ -11,11 +11,9 @@ package mount // import "github.com/docker/docker/pkg/mount"
import "C" import "C"
import ( import (
"fmt"
"strings" "strings"
"syscall"
"unsafe" "unsafe"
"golang.org/x/sys/unix"
) )
func allocateIOVecs(options []string) []C.struct_iovec { func allocateIOVecs(options []string) []C.struct_iovec {
...@@ -49,12 +47,13 @@ func mount(device, target, mType string, flag uintptr, data string) error { ...@@ -49,12 +47,13 @@ func mount(device, target, mType string, flag uintptr, data string) error {
} }
if errno := C.nmount(&rawOptions[0], C.uint(len(options)), C.int(flag)); errno != 0 { if errno := C.nmount(&rawOptions[0], C.uint(len(options)), C.int(flag)); errno != 0 {
reason := C.GoString(C.strerror(*C.__error())) return &mountError{
return fmt.Errorf("Failed to call nmount: %s", reason) op: "mount",
source: device,
target: target,
flags: flag,
err: syscall.Errno(errno),
}
} }
return nil return nil
} }
func unmount(target string, flag int) error {
return unix.Unmount(target, flag)
}
...@@ -33,25 +33,41 @@ func mount(device, target, mType string, flags uintptr, data string) error { ...@@ -33,25 +33,41 @@ func mount(device, target, mType string, flags uintptr, data string) error {
// Initial call applying all non-propagation flags for mount // Initial call applying all non-propagation flags for mount
// or remount with changed data // or remount with changed data
if err := unix.Mount(device, target, mType, oflags, data); err != nil { if err := unix.Mount(device, target, mType, oflags, data); err != nil {
return err return &mountError{
op: "mount",
source: device,
target: target,
flags: oflags,
data: data,
err: err,
}
} }
} }
if flags&ptypes != 0 { if flags&ptypes != 0 {
// Change the propagation type. // Change the propagation type.
if err := unix.Mount("", target, "", flags&pflags, ""); err != nil { if err := unix.Mount("", target, "", flags&pflags, ""); err != nil {
return err return &mountError{
op: "remount",
target: target,
flags: flags & pflags,
err: err,
}
} }
} }
if oflags&broflags == broflags { if oflags&broflags == broflags {
// Remount the bind to apply read only. // Remount the bind to apply read only.
return unix.Mount("", target, "", oflags|unix.MS_REMOUNT, "") if err := unix.Mount("", target, "", oflags|unix.MS_REMOUNT, ""); err != nil {
return &mountError{
op: "remount-ro",
target: target,
flags: oflags | unix.MS_REMOUNT,
err: err,
}
}
} }
return nil return nil
} }
func unmount(target string, flag int) error {
return unix.Unmount(target, flag)
}
...@@ -5,7 +5,3 @@ package mount // import "github.com/docker/docker/pkg/mount" ...@@ -5,7 +5,3 @@ package mount // import "github.com/docker/docker/pkg/mount"
func mount(device, target, mType string, flag uintptr, data string) error { func mount(device, target, mType string, flag uintptr, data string) error {
panic("Not implemented") panic("Not implemented")
} }
func unmount(target string, flag int) error {
panic("Not implemented")
}
...@@ -48,18 +48,22 @@ func MakeRUnbindable(mountPoint string) error { ...@@ -48,18 +48,22 @@ func MakeRUnbindable(mountPoint string) error {
return ensureMountedAs(mountPoint, "runbindable") return ensureMountedAs(mountPoint, "runbindable")
} }
func ensureMountedAs(mountPoint, options string) error { // MakeMount ensures that the file or directory given is a mount point,
mounted, err := Mounted(mountPoint) // bind mounting it to itself it case it is not.
func MakeMount(mnt string) error {
mounted, err := Mounted(mnt)
if err != nil { if err != nil {
return err return err
} }
if mounted {
if !mounted { return nil
if err := Mount(mountPoint, mountPoint, "none", "bind,rw"); err != nil {
return err
}
} }
if _, err = Mounted(mountPoint); err != nil {
return Mount(mnt, mnt, "none", "bind")
}
func ensureMountedAs(mountPoint, options string) error {
if err := MakeMount(mountPoint); err != nil {
return err return err
} }
......
// +build !windows
package mount // import "github.com/docker/docker/pkg/mount"
import "golang.org/x/sys/unix"
func unmount(target string, flags int) error {
err := unix.Unmount(target, flags)
if err == nil || err == unix.EINVAL {
// Ignore "not mounted" error here. Note the same error
// can be returned if flags are invalid, so this code
// assumes that the flags value is always correct.
return nil
}
return &mountError{
op: "umount",
target: target,
flags: uintptr(flags),
err: err,
}
}
// +build windows
package mount // import "github.com/docker/docker/pkg/mount"
func unmount(target string, flag int) error {
panic("Not implemented")
}
...@@ -18,6 +18,24 @@ func ParseKeyValueOpt(opt string) (string, string, error) { ...@@ -18,6 +18,24 @@ func ParseKeyValueOpt(opt string) (string, string, error) {
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
} }
// ParseUintListMaximum parses and validates the specified string as the value
// found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
// one of the formats below. Note that duplicates are actually allowed in the
// input string. It returns a `map[int]bool` with available elements from `val`
// set to `true`. Values larger than `maximum` cause an error if max is non zero,
// in order to stop the map becoming excessively large.
// Supported formats:
// 7
// 1-6
// 0,3-4,7,8-10
// 0-0,0,1-7
// 03,1-3 <- this is gonna get parsed as [1,2,3]
// 3,2,1
// 0-2,3,1
func ParseUintListMaximum(val string, maximum int) (map[int]bool, error) {
return parseUintList(val, maximum)
}
// ParseUintList parses and validates the specified string as the value // ParseUintList parses and validates the specified string as the value
// found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be // found in some cgroup file (e.g. `cpuset.cpus`, `cpuset.mems`), which could be
// one of the formats below. Note that duplicates are actually allowed in the // one of the formats below. Note that duplicates are actually allowed in the
...@@ -32,6 +50,10 @@ func ParseKeyValueOpt(opt string) (string, string, error) { ...@@ -32,6 +50,10 @@ func ParseKeyValueOpt(opt string) (string, string, error) {
// 3,2,1 // 3,2,1
// 0-2,3,1 // 0-2,3,1
func ParseUintList(val string) (map[int]bool, error) { func ParseUintList(val string) (map[int]bool, error) {
return parseUintList(val, 0)
}
func parseUintList(val string, maximum int) (map[int]bool, error) {
if val == "" { if val == "" {
return map[int]bool{}, nil return map[int]bool{}, nil
} }
...@@ -46,6 +68,9 @@ func ParseUintList(val string) (map[int]bool, error) { ...@@ -46,6 +68,9 @@ func ParseUintList(val string) (map[int]bool, error) {
if err != nil { if err != nil {
return nil, errInvalidFormat return nil, errInvalidFormat
} }
if maximum != 0 && v > maximum {
return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
}
availableInts[v] = true availableInts[v] = true
} else { } else {
split := strings.SplitN(r, "-", 2) split := strings.SplitN(r, "-", 2)
...@@ -60,6 +85,9 @@ func ParseUintList(val string) (map[int]bool, error) { ...@@ -60,6 +85,9 @@ func ParseUintList(val string) (map[int]bool, error) {
if max < min { if max < min {
return nil, errInvalidFormat return nil, errInvalidFormat
} }
if maximum != 0 && max > maximum {
return nil, fmt.Errorf("value of out range, maximum is %d", maximum)
}
for i := min; i <= max; i++ { for i := min; i <= max; i++ {
availableInts[i] = true availableInts[i] = true
} }
......
...@@ -47,6 +47,9 @@ type cgroupMemInfo struct { ...@@ -47,6 +47,9 @@ type cgroupMemInfo struct {
// Whether kernel memory limit is supported or not // Whether kernel memory limit is supported or not
KernelMemory bool KernelMemory bool
// Whether kernel memory TCP limit is supported or not
KernelMemoryTCP bool
} }
type cgroupCPUInfo struct { type cgroupCPUInfo struct {
...@@ -117,11 +120,19 @@ func (c cgroupCpusetInfo) IsCpusetMemsAvailable(provided string) (bool, error) { ...@@ -117,11 +120,19 @@ func (c cgroupCpusetInfo) IsCpusetMemsAvailable(provided string) (bool, error) {
} }
func isCpusetListAvailable(provided, available string) (bool, error) { func isCpusetListAvailable(provided, available string) (bool, error) {
parsedProvided, err := parsers.ParseUintList(provided) parsedAvailable, err := parsers.ParseUintList(available)
if err != nil { if err != nil {
return false, err return false, err
} }
parsedAvailable, err := parsers.ParseUintList(available) // 8192 is the normal maximum number of CPUs in Linux, so accept numbers up to this
// or more if we actually have more CPUs.
max := 8192
for m := range parsedAvailable {
if m > max {
max = m
}
}
parsedProvided, err := parsers.ParseUintListMaximum(provided, max)
if err != nil { if err != nil {
return false, err return false, err
} }
......
...@@ -26,218 +26,241 @@ func findCgroupMountpoints() (map[string]string, error) { ...@@ -26,218 +26,241 @@ func findCgroupMountpoints() (map[string]string, error) {
return mps, nil return mps, nil
} }
type infoCollector func(info *SysInfo, cgMounts map[string]string) (warnings []string)
// New returns a new SysInfo, using the filesystem to detect which features // New returns a new SysInfo, using the filesystem to detect which features
// the kernel supports. If `quiet` is `false` warnings are printed in logs // the kernel supports. If `quiet` is `false` warnings are printed in logs
// whenever an error occurs or misconfigurations are present. // whenever an error occurs or misconfigurations are present.
func New(quiet bool) *SysInfo { func New(quiet bool) *SysInfo {
var ops []infoCollector
var warnings []string
sysInfo := &SysInfo{} sysInfo := &SysInfo{}
cgMounts, err := findCgroupMountpoints() cgMounts, err := findCgroupMountpoints()
if err != nil { if err != nil {
logrus.Warnf("Failed to parse cgroup information: %v", err) logrus.Warn(err)
} else { } else {
sysInfo.cgroupMemInfo = checkCgroupMem(cgMounts, quiet) ops = append(ops, []infoCollector{
sysInfo.cgroupCPUInfo = checkCgroupCPU(cgMounts, quiet) applyMemoryCgroupInfo,
sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(cgMounts, quiet) applyCPUCgroupInfo,
sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(cgMounts, quiet) applyBlkioCgroupInfo,
sysInfo.cgroupPids = checkCgroupPids(quiet) applyCPUSetCgroupInfo,
} applyPIDSCgroupInfo,
applyDevicesCgroupInfo,
_, ok := cgMounts["devices"] }...)
sysInfo.CgroupDevicesEnabled = ok }
sysInfo.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward") ops = append(ops, []infoCollector{
sysInfo.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables") applyNetworkingInfo,
sysInfo.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables") applyAppArmorInfo,
applySeccompInfo,
// Check if AppArmor is supported. }...)
if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
sysInfo.AppArmor = true for _, o := range ops {
} w := o(sysInfo, cgMounts)
warnings = append(warnings, w...)
// Check if Seccomp is supported, via CONFIG_SECCOMP. }
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL { if !quiet {
// Make sure the kernel has CONFIG_SECCOMP_FILTER. for _, w := range warnings {
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL { logrus.Warn(w)
sysInfo.Seccomp = true
} }
} }
return sysInfo return sysInfo
} }
// checkCgroupMem reads the memory information from the memory cgroup mount point. // applyMemoryCgroupInfo reads the memory information from the memory cgroup mount point.
func checkCgroupMem(cgMounts map[string]string, quiet bool) cgroupMemInfo { func applyMemoryCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
var warnings []string
mountPoint, ok := cgMounts["memory"] mountPoint, ok := cgMounts["memory"]
if !ok { if !ok {
if !quiet { warnings = append(warnings, "Your kernel does not support cgroup memory limit")
logrus.Warn("Your kernel does not support cgroup memory limit") return warnings
}
return cgroupMemInfo{}
} }
info.MemoryLimit = ok
swapLimit := cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes") info.SwapLimit = cgroupEnabled(mountPoint, "memory.memsw.limit_in_bytes")
if !quiet && !swapLimit { if !info.SwapLimit {
logrus.Warn("Your kernel does not support swap memory limit") warnings = append(warnings, "Your kernel does not support swap memory limit")
} }
memoryReservation := cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes") info.MemoryReservation = cgroupEnabled(mountPoint, "memory.soft_limit_in_bytes")
if !quiet && !memoryReservation { if !info.MemoryReservation {
logrus.Warn("Your kernel does not support memory reservation") warnings = append(warnings, "Your kernel does not support memory reservation")
} }
oomKillDisable := cgroupEnabled(mountPoint, "memory.oom_control") info.OomKillDisable = cgroupEnabled(mountPoint, "memory.oom_control")
if !quiet && !oomKillDisable { if !info.OomKillDisable {
logrus.Warn("Your kernel does not support oom control") warnings = append(warnings, "Your kernel does not support oom control")
} }
memorySwappiness := cgroupEnabled(mountPoint, "memory.swappiness") info.MemorySwappiness = cgroupEnabled(mountPoint, "memory.swappiness")
if !quiet && !memorySwappiness { if !info.MemorySwappiness {
logrus.Warn("Your kernel does not support memory swappiness") warnings = append(warnings, "Your kernel does not support memory swappiness")
} }
kernelMemory := cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes") info.KernelMemory = cgroupEnabled(mountPoint, "memory.kmem.limit_in_bytes")
if !quiet && !kernelMemory { if !info.KernelMemory {
logrus.Warn("Your kernel does not support kernel memory limit") warnings = append(warnings, "Your kernel does not support kernel memory limit")
} }
info.KernelMemoryTCP = cgroupEnabled(mountPoint, "memory.kmem.tcp.limit_in_bytes")
return cgroupMemInfo{ if !info.KernelMemoryTCP {
MemoryLimit: true, warnings = append(warnings, "Your kernel does not support kernel memory TCP limit")
SwapLimit: swapLimit,
MemoryReservation: memoryReservation,
OomKillDisable: oomKillDisable,
MemorySwappiness: memorySwappiness,
KernelMemory: kernelMemory,
} }
return warnings
} }
// checkCgroupCPU reads the cpu information from the cpu cgroup mount point. // applyCPUCgroupInfo reads the cpu information from the cpu cgroup mount point.
func checkCgroupCPU(cgMounts map[string]string, quiet bool) cgroupCPUInfo { func applyCPUCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
var warnings []string
mountPoint, ok := cgMounts["cpu"] mountPoint, ok := cgMounts["cpu"]
if !ok { if !ok {
if !quiet { warnings = append(warnings, "Unable to find cpu cgroup in mounts")
logrus.Warn("Unable to find cpu cgroup in mounts") return warnings
}
return cgroupCPUInfo{}
} }
cpuShares := cgroupEnabled(mountPoint, "cpu.shares") info.CPUShares = cgroupEnabled(mountPoint, "cpu.shares")
if !quiet && !cpuShares { if !info.CPUShares {
logrus.Warn("Your kernel does not support cgroup cpu shares") warnings = append(warnings, "Your kernel does not support cgroup cpu shares")
} }
cpuCfsPeriod := cgroupEnabled(mountPoint, "cpu.cfs_period_us") info.CPUCfsPeriod = cgroupEnabled(mountPoint, "cpu.cfs_period_us")
if !quiet && !cpuCfsPeriod { if !info.CPUCfsPeriod {
logrus.Warn("Your kernel does not support cgroup cfs period") warnings = append(warnings, "Your kernel does not support cgroup cfs period")
} }
cpuCfsQuota := cgroupEnabled(mountPoint, "cpu.cfs_quota_us") info.CPUCfsQuota = cgroupEnabled(mountPoint, "cpu.cfs_quota_us")
if !quiet && !cpuCfsQuota { if !info.CPUCfsQuota {
logrus.Warn("Your kernel does not support cgroup cfs quotas") warnings = append(warnings, "Your kernel does not support cgroup cfs quotas")
} }
cpuRealtimePeriod := cgroupEnabled(mountPoint, "cpu.rt_period_us") info.CPURealtimePeriod = cgroupEnabled(mountPoint, "cpu.rt_period_us")
if !quiet && !cpuRealtimePeriod { if !info.CPURealtimePeriod {
logrus.Warn("Your kernel does not support cgroup rt period") warnings = append(warnings, "Your kernel does not support cgroup rt period")
} }
cpuRealtimeRuntime := cgroupEnabled(mountPoint, "cpu.rt_runtime_us") info.CPURealtimeRuntime = cgroupEnabled(mountPoint, "cpu.rt_runtime_us")
if !quiet && !cpuRealtimeRuntime { if !info.CPURealtimeRuntime {
logrus.Warn("Your kernel does not support cgroup rt runtime") warnings = append(warnings, "Your kernel does not support cgroup rt runtime")
} }
return cgroupCPUInfo{ return warnings
CPUShares: cpuShares,
CPUCfsPeriod: cpuCfsPeriod,
CPUCfsQuota: cpuCfsQuota,
CPURealtimePeriod: cpuRealtimePeriod,
CPURealtimeRuntime: cpuRealtimeRuntime,
}
} }
// checkCgroupBlkioInfo reads the blkio information from the blkio cgroup mount point. // applyBlkioCgroupInfo reads the blkio information from the blkio cgroup mount point.
func checkCgroupBlkioInfo(cgMounts map[string]string, quiet bool) cgroupBlkioInfo { func applyBlkioCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
var warnings []string
mountPoint, ok := cgMounts["blkio"] mountPoint, ok := cgMounts["blkio"]
if !ok { if !ok {
if !quiet { warnings = append(warnings, "Unable to find blkio cgroup in mounts")
logrus.Warn("Unable to find blkio cgroup in mounts") return warnings
}
return cgroupBlkioInfo{}
} }
weight := cgroupEnabled(mountPoint, "blkio.weight") info.BlkioWeight = cgroupEnabled(mountPoint, "blkio.weight")
if !quiet && !weight { if !info.BlkioWeight {
logrus.Warn("Your kernel does not support cgroup blkio weight") warnings = append(warnings, "Your kernel does not support cgroup blkio weight")
} }
weightDevice := cgroupEnabled(mountPoint, "blkio.weight_device") info.BlkioWeightDevice = cgroupEnabled(mountPoint, "blkio.weight_device")
if !quiet && !weightDevice { if !info.BlkioWeightDevice {
logrus.Warn("Your kernel does not support cgroup blkio weight_device") warnings = append(warnings, "Your kernel does not support cgroup blkio weight_device")
} }
readBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device") info.BlkioReadBpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.read_bps_device")
if !quiet && !readBpsDevice { if !info.BlkioReadBpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.read_bps_device") warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.read_bps_device")
} }
writeBpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device") info.BlkioWriteBpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.write_bps_device")
if !quiet && !writeBpsDevice { if !info.BlkioWriteBpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.write_bps_device") warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.write_bps_device")
} }
readIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device") info.BlkioReadIOpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.read_iops_device")
if !quiet && !readIOpsDevice { if !info.BlkioReadIOpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.read_iops_device") warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.read_iops_device")
} }
writeIOpsDevice := cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device") info.BlkioWriteIOpsDevice = cgroupEnabled(mountPoint, "blkio.throttle.write_iops_device")
if !quiet && !writeIOpsDevice { if !info.BlkioWriteIOpsDevice {
logrus.Warn("Your kernel does not support cgroup blkio throttle.write_iops_device") warnings = append(warnings, "Your kernel does not support cgroup blkio throttle.write_iops_device")
}
return cgroupBlkioInfo{
BlkioWeight: weight,
BlkioWeightDevice: weightDevice,
BlkioReadBpsDevice: readBpsDevice,
BlkioWriteBpsDevice: writeBpsDevice,
BlkioReadIOpsDevice: readIOpsDevice,
BlkioWriteIOpsDevice: writeIOpsDevice,
} }
return warnings
} }
// checkCgroupCpusetInfo reads the cpuset information from the cpuset cgroup mount point. // applyCPUSetCgroupInfo reads the cpuset information from the cpuset cgroup mount point.
func checkCgroupCpusetInfo(cgMounts map[string]string, quiet bool) cgroupCpusetInfo { func applyCPUSetCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
var warnings []string
mountPoint, ok := cgMounts["cpuset"] mountPoint, ok := cgMounts["cpuset"]
if !ok { if !ok {
if !quiet { warnings = append(warnings, "Unable to find cpuset cgroup in mounts")
logrus.Warn("Unable to find cpuset cgroup in mounts") return warnings
}
return cgroupCpusetInfo{}
} }
info.Cpuset = ok
var err error
cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus")) cpus, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.cpus"))
if err != nil { if err != nil {
return cgroupCpusetInfo{} return warnings
} }
info.Cpus = strings.TrimSpace(string(cpus))
mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems")) mems, err := ioutil.ReadFile(path.Join(mountPoint, "cpuset.mems"))
if err != nil { if err != nil {
return cgroupCpusetInfo{} return warnings
} }
info.Mems = strings.TrimSpace(string(mems))
return cgroupCpusetInfo{ return warnings
Cpuset: true,
Cpus: strings.TrimSpace(string(cpus)),
Mems: strings.TrimSpace(string(mems)),
}
} }
// checkCgroupPids reads the pids information from the pids cgroup mount point. // applyPIDSCgroupInfo reads the pids information from the pids cgroup mount point.
func checkCgroupPids(quiet bool) cgroupPids { func applyPIDSCgroupInfo(info *SysInfo, _ map[string]string) []string {
_, err := cgroups.FindCgroupMountpoint("pids") var warnings []string
_, err := cgroups.FindCgroupMountpoint("", "pids")
if err != nil { if err != nil {
if !quiet { warnings = append(warnings, err.Error())
logrus.Warn(err) return warnings
}
info.PidsLimit = true
return warnings
}
// applyDevicesCgroupInfo reads the pids information from the devices cgroup mount point.
func applyDevicesCgroupInfo(info *SysInfo, cgMounts map[string]string) []string {
var warnings []string
_, ok := cgMounts["devices"]
info.CgroupDevicesEnabled = ok
return warnings
}
// applyNetworkingInfo adds networking information to the info.
func applyNetworkingInfo(info *SysInfo, _ map[string]string) []string {
var warnings []string
info.IPv4ForwardingDisabled = !readProcBool("/proc/sys/net/ipv4/ip_forward")
info.BridgeNFCallIPTablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-iptables")
info.BridgeNFCallIP6TablesDisabled = !readProcBool("/proc/sys/net/bridge/bridge-nf-call-ip6tables")
return warnings
}
// applyAppArmorInfo adds AppArmor information to the info.
func applyAppArmorInfo(info *SysInfo, _ map[string]string) []string {
var warnings []string
if _, err := os.Stat("/sys/kernel/security/apparmor"); !os.IsNotExist(err) {
if _, err := ioutil.ReadFile("/sys/kernel/security/apparmor/profiles"); err == nil {
info.AppArmor = true
} }
return cgroupPids{}
} }
return warnings
}
return cgroupPids{ // applySeccompInfo checks if Seccomp is supported, via CONFIG_SECCOMP.
PidsLimit: true, func applySeccompInfo(info *SysInfo, _ map[string]string) []string {
var warnings []string
// Check if Seccomp is supported, via CONFIG_SECCOMP.
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
// Make sure the kernel has CONFIG_SECCOMP_FILTER.
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
info.Seccomp = true
}
} }
return warnings
} }
func cgroupEnabled(mountPoint, name string) bool { func cgroupEnabled(mountPoint, name string) bool {
......
...@@ -62,13 +62,6 @@ func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { ...@@ -62,13 +62,6 @@ func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) {
} }
} }
if os.Getenv("ConEmuANSI") == "ON" || os.Getenv("ConsoleZVersion") != "" {
// The ConEmu and ConsoleZ terminals emulate ANSI on output streams well.
emulateStdin = true
emulateStdout = false
emulateStderr = false
}
// Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and // Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and
// STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as // STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as
// go-ansiterm hasn't switch to x/sys/windows. // go-ansiterm hasn't switch to x/sys/windows.
......
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"aec.go",
"ansi.go",
"builder.go",
"sgr.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/morikuni/aec",
importpath = "github.com/morikuni/aec",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
The MIT License (MIT)
Copyright (c) 2016 Taihei Morikuni
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# aec
[![GoDoc](https://godoc.org/github.com/morikuni/aec?status.svg)](https://godoc.org/github.com/morikuni/aec)
Go wrapper for ANSI escape code.
## Install
```bash
go get github.com/morikuni/aec
```
## Features
ANSI escape codes depend on terminal environment.
Some of these features may not work.
Check supported Font-Style/Font-Color features with [checkansi](./checkansi).
[Wikipedia](https://en.wikipedia.org/wiki/ANSI_escape_code) for more detail.
### Cursor
- `Up(n)`
- `Down(n)`
- `Right(n)`
- `Left(n)`
- `NextLine(n)`
- `PreviousLine(n)`
- `Column(col)`
- `Position(row, col)`
- `Save`
- `Restore`
- `Hide`
- `Show`
- `Report`
### Erase
- `EraseDisplay(mode)`
- `EraseLine(mode)`
### Scroll
- `ScrollUp(n)`
- `ScrollDown(n)`
### Font Style
- `Bold`
- `Faint`
- `Italic`
- `Underline`
- `BlinkSlow`
- `BlinkRapid`
- `Inverse`
- `Conceal`
- `CrossOut`
- `Frame`
- `Encircle`
- `Overline`
### Font Color
Foreground color.
- `DefaultF`
- `BlackF`
- `RedF`
- `GreenF`
- `YellowF`
- `BlueF`
- `MagentaF`
- `CyanF`
- `WhiteF`
- `LightBlackF`
- `LightRedF`
- `LightGreenF`
- `LightYellowF`
- `LightBlueF`
- `LightMagentaF`
- `LightCyanF`
- `LightWhiteF`
- `Color3BitF(color)`
- `Color8BitF(color)`
- `FullColorF(r, g, b)`
Background color.
- `DefaultB`
- `BlackB`
- `RedB`
- `GreenB`
- `YellowB`
- `BlueB`
- `MagentaB`
- `CyanB`
- `WhiteB`
- `LightBlackB`
- `LightRedB`
- `LightGreenB`
- `LightYellowB`
- `LightBlueB`
- `LightMagentaB`
- `LightCyanB`
- `LightWhiteB`
- `Color3BitB(color)`
- `Color8BitB(color)`
- `FullColorB(r, g, b)`
### Color Converter
24bit RGB color to ANSI color.
- `NewRGB3Bit(r, g, b)`
- `NewRGB8Bit(r, g, b)`
### Builder
To mix these features.
```go
custom := aec.EmptyBuilder.Right(2).RGB8BitF(128, 255, 64).RedB().ANSI
custom.Apply("Hello World")
```
## Usage
1. Create ANSI by `aec.XXX().With(aec.YYY())` or `aec.EmptyBuilder.XXX().YYY().ANSI`
2. Print ANSI by `fmt.Print(ansi, "some string", aec.Reset)` or `fmt.Print(ansi.Apply("some string"))`
`aec.Reset` should be added when using font style or font color features.
## Example
Simple progressbar.
![sample](./sample.gif)
```go
package main
import (
"fmt"
"strings"
"time"
"github.com/morikuni/aec"
)
func main() {
const n = 20
builder := aec.EmptyBuilder
up2 := aec.Up(2)
col := aec.Column(n + 2)
bar := aec.Color8BitF(aec.NewRGB8Bit(64, 255, 64))
label := builder.LightRedF().Underline().With(col).Right(1).ANSI
// for up2
fmt.Println()
fmt.Println()
for i := 0; i <= n; i++ {
fmt.Print(up2)
fmt.Println(label.Apply(fmt.Sprint(i, "/", n)))
fmt.Print("[")
fmt.Print(bar.Apply(strings.Repeat("=", i)))
fmt.Println(col.Apply("]"))
time.Sleep(100 * time.Millisecond)
}
}
```
## License
[MIT](./LICENSE)
package aec
import "fmt"
// EraseMode is listed in a variable EraseModes.
type EraseMode uint
var (
// EraseModes is a list of EraseMode.
EraseModes struct {
// All erase all.
All EraseMode
// Head erase to head.
Head EraseMode
// Tail erase to tail.
Tail EraseMode
}
// Save saves the cursor position.
Save ANSI
// Restore restores the cursor position.
Restore ANSI
// Hide hides the cursor.
Hide ANSI
// Show shows the cursor.
Show ANSI
// Report reports the cursor position.
Report ANSI
)
// Up moves up the cursor.
func Up(n uint) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dA", n))
}
// Down moves down the cursor.
func Down(n uint) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dB", n))
}
// Right moves right the cursor.
func Right(n uint) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dC", n))
}
// Left moves left the cursor.
func Left(n uint) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dD", n))
}
// NextLine moves down the cursor to head of a line.
func NextLine(n uint) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dE", n))
}
// PreviousLine moves up the cursor to head of a line.
func PreviousLine(n uint) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dF", n))
}
// Column set the cursor position to a given column.
func Column(col uint) ANSI {
return newAnsi(fmt.Sprintf(esc+"%dG", col))
}
// Position set the cursor position to a given absolute position.
func Position(row, col uint) ANSI {
return newAnsi(fmt.Sprintf(esc+"%d;%dH", row, col))
}
// EraseDisplay erases display by given EraseMode.
func EraseDisplay(m EraseMode) ANSI {
return newAnsi(fmt.Sprintf(esc+"%dJ", m))
}
// EraseLine erases lines by given EraseMode.
func EraseLine(m EraseMode) ANSI {
return newAnsi(fmt.Sprintf(esc+"%dK", m))
}
// ScrollUp scrolls up the page.
func ScrollUp(n int) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dS", n))
}
// ScrollDown scrolls down the page.
func ScrollDown(n int) ANSI {
if n == 0 {
return empty
}
return newAnsi(fmt.Sprintf(esc+"%dT", n))
}
func init() {
EraseModes = struct {
All EraseMode
Head EraseMode
Tail EraseMode
}{
Tail: 0,
Head: 1,
All: 2,
}
Save = newAnsi(esc + "s")
Restore = newAnsi(esc + "u")
Hide = newAnsi(esc + "?25l")
Show = newAnsi(esc + "?25h")
Report = newAnsi(esc + "6n")
}
package aec
import (
"fmt"
"strings"
)
const esc = "\x1b["
// Reset resets SGR effect.
const Reset string = "\x1b[0m"
var empty = newAnsi("")
// ANSI represents ANSI escape code.
type ANSI interface {
fmt.Stringer
// With adapts given ANSIs.
With(...ANSI) ANSI
// Apply wraps given string in ANSI.
Apply(string) string
}
type ansiImpl string
func newAnsi(s string) *ansiImpl {
r := ansiImpl(s)
return &r
}
func (a *ansiImpl) With(ansi ...ANSI) ANSI {
return concat(append([]ANSI{a}, ansi...))
}
func (a *ansiImpl) Apply(s string) string {
return a.String() + s + Reset
}
func (a *ansiImpl) String() string {
return string(*a)
}
// Apply wraps given string in ANSIs.
func Apply(s string, ansi ...ANSI) string {
if len(ansi) == 0 {
return s
}
return concat(ansi).Apply(s)
}
func concat(ansi []ANSI) ANSI {
strs := make([]string, 0, len(ansi))
for _, p := range ansi {
strs = append(strs, p.String())
}
return newAnsi(strings.Join(strs, ""))
}
package aec
// Builder is a lightweight syntax to construct customized ANSI.
type Builder struct {
ANSI ANSI
}
// EmptyBuilder is an initialized Builder.
var EmptyBuilder *Builder
// NewBuilder creates a Builder from existing ANSI.
func NewBuilder(a ...ANSI) *Builder {
return &Builder{concat(a)}
}
// With is a syntax for With.
func (builder *Builder) With(a ...ANSI) *Builder {
return NewBuilder(builder.ANSI.With(a...))
}
// Up is a syntax for Up.
func (builder *Builder) Up(n uint) *Builder {
return builder.With(Up(n))
}
// Down is a syntax for Down.
func (builder *Builder) Down(n uint) *Builder {
return builder.With(Down(n))
}
// Right is a syntax for Right.
func (builder *Builder) Right(n uint) *Builder {
return builder.With(Right(n))
}
// Left is a syntax for Left.
func (builder *Builder) Left(n uint) *Builder {
return builder.With(Left(n))
}
// NextLine is a syntax for NextLine.
func (builder *Builder) NextLine(n uint) *Builder {
return builder.With(NextLine(n))
}
// PreviousLine is a syntax for PreviousLine.
func (builder *Builder) PreviousLine(n uint) *Builder {
return builder.With(PreviousLine(n))
}
// Column is a syntax for Column.
func (builder *Builder) Column(col uint) *Builder {
return builder.With(Column(col))
}
// Position is a syntax for Position.
func (builder *Builder) Position(row, col uint) *Builder {
return builder.With(Position(row, col))
}
// EraseDisplay is a syntax for EraseDisplay.
func (builder *Builder) EraseDisplay(m EraseMode) *Builder {
return builder.With(EraseDisplay(m))
}
// EraseLine is a syntax for EraseLine.
func (builder *Builder) EraseLine(m EraseMode) *Builder {
return builder.With(EraseLine(m))
}
// ScrollUp is a syntax for ScrollUp.
func (builder *Builder) ScrollUp(n int) *Builder {
return builder.With(ScrollUp(n))
}
// ScrollDown is a syntax for ScrollDown.
func (builder *Builder) ScrollDown(n int) *Builder {
return builder.With(ScrollDown(n))
}
// Save is a syntax for Save.
func (builder *Builder) Save() *Builder {
return builder.With(Save)
}
// Restore is a syntax for Restore.
func (builder *Builder) Restore() *Builder {
return builder.With(Restore)
}
// Hide is a syntax for Hide.
func (builder *Builder) Hide() *Builder {
return builder.With(Hide)
}
// Show is a syntax for Show.
func (builder *Builder) Show() *Builder {
return builder.With(Show)
}
// Report is a syntax for Report.
func (builder *Builder) Report() *Builder {
return builder.With(Report)
}
// Bold is a syntax for Bold.
func (builder *Builder) Bold() *Builder {
return builder.With(Bold)
}
// Faint is a syntax for Faint.
func (builder *Builder) Faint() *Builder {
return builder.With(Faint)
}
// Italic is a syntax for Italic.
func (builder *Builder) Italic() *Builder {
return builder.With(Italic)
}
// Underline is a syntax for Underline.
func (builder *Builder) Underline() *Builder {
return builder.With(Underline)
}
// BlinkSlow is a syntax for BlinkSlow.
func (builder *Builder) BlinkSlow() *Builder {
return builder.With(BlinkSlow)
}
// BlinkRapid is a syntax for BlinkRapid.
func (builder *Builder) BlinkRapid() *Builder {
return builder.With(BlinkRapid)
}
// Inverse is a syntax for Inverse.
func (builder *Builder) Inverse() *Builder {
return builder.With(Inverse)
}
// Conceal is a syntax for Conceal.
func (builder *Builder) Conceal() *Builder {
return builder.With(Conceal)
}
// CrossOut is a syntax for CrossOut.
func (builder *Builder) CrossOut() *Builder {
return builder.With(CrossOut)
}
// BlackF is a syntax for BlackF.
func (builder *Builder) BlackF() *Builder {
return builder.With(BlackF)
}
// RedF is a syntax for RedF.
func (builder *Builder) RedF() *Builder {
return builder.With(RedF)
}
// GreenF is a syntax for GreenF.
func (builder *Builder) GreenF() *Builder {
return builder.With(GreenF)
}
// YellowF is a syntax for YellowF.
func (builder *Builder) YellowF() *Builder {
return builder.With(YellowF)
}
// BlueF is a syntax for BlueF.
func (builder *Builder) BlueF() *Builder {
return builder.With(BlueF)
}
// MagentaF is a syntax for MagentaF.
func (builder *Builder) MagentaF() *Builder {
return builder.With(MagentaF)
}
// CyanF is a syntax for CyanF.
func (builder *Builder) CyanF() *Builder {
return builder.With(CyanF)
}
// WhiteF is a syntax for WhiteF.
func (builder *Builder) WhiteF() *Builder {
return builder.With(WhiteF)
}
// DefaultF is a syntax for DefaultF.
func (builder *Builder) DefaultF() *Builder {
return builder.With(DefaultF)
}
// BlackB is a syntax for BlackB.
func (builder *Builder) BlackB() *Builder {
return builder.With(BlackB)
}
// RedB is a syntax for RedB.
func (builder *Builder) RedB() *Builder {
return builder.With(RedB)
}
// GreenB is a syntax for GreenB.
func (builder *Builder) GreenB() *Builder {
return builder.With(GreenB)
}
// YellowB is a syntax for YellowB.
func (builder *Builder) YellowB() *Builder {
return builder.With(YellowB)
}
// BlueB is a syntax for BlueB.
func (builder *Builder) BlueB() *Builder {
return builder.With(BlueB)
}
// MagentaB is a syntax for MagentaB.
func (builder *Builder) MagentaB() *Builder {
return builder.With(MagentaB)
}
// CyanB is a syntax for CyanB.
func (builder *Builder) CyanB() *Builder {
return builder.With(CyanB)
}
// WhiteB is a syntax for WhiteB.
func (builder *Builder) WhiteB() *Builder {
return builder.With(WhiteB)
}
// DefaultB is a syntax for DefaultB.
func (builder *Builder) DefaultB() *Builder {
return builder.With(DefaultB)
}
// Frame is a syntax for Frame.
func (builder *Builder) Frame() *Builder {
return builder.With(Frame)
}
// Encircle is a syntax for Encircle.
func (builder *Builder) Encircle() *Builder {
return builder.With(Encircle)
}
// Overline is a syntax for Overline.
func (builder *Builder) Overline() *Builder {
return builder.With(Overline)
}
// LightBlackF is a syntax for LightBlueF.
func (builder *Builder) LightBlackF() *Builder {
return builder.With(LightBlackF)
}
// LightRedF is a syntax for LightRedF.
func (builder *Builder) LightRedF() *Builder {
return builder.With(LightRedF)
}
// LightGreenF is a syntax for LightGreenF.
func (builder *Builder) LightGreenF() *Builder {
return builder.With(LightGreenF)
}
// LightYellowF is a syntax for LightYellowF.
func (builder *Builder) LightYellowF() *Builder {
return builder.With(LightYellowF)
}
// LightBlueF is a syntax for LightBlueF.
func (builder *Builder) LightBlueF() *Builder {
return builder.With(LightBlueF)
}
// LightMagentaF is a syntax for LightMagentaF.
func (builder *Builder) LightMagentaF() *Builder {
return builder.With(LightMagentaF)
}
// LightCyanF is a syntax for LightCyanF.
func (builder *Builder) LightCyanF() *Builder {
return builder.With(LightCyanF)
}
// LightWhiteF is a syntax for LightWhiteF.
func (builder *Builder) LightWhiteF() *Builder {
return builder.With(LightWhiteF)
}
// LightBlackB is a syntax for LightBlackB.
func (builder *Builder) LightBlackB() *Builder {
return builder.With(LightBlackB)
}
// LightRedB is a syntax for LightRedB.
func (builder *Builder) LightRedB() *Builder {
return builder.With(LightRedB)
}
// LightGreenB is a syntax for LightGreenB.
func (builder *Builder) LightGreenB() *Builder {
return builder.With(LightGreenB)
}
// LightYellowB is a syntax for LightYellowB.
func (builder *Builder) LightYellowB() *Builder {
return builder.With(LightYellowB)
}
// LightBlueB is a syntax for LightBlueB.
func (builder *Builder) LightBlueB() *Builder {
return builder.With(LightBlueB)
}
// LightMagentaB is a syntax for LightMagentaB.
func (builder *Builder) LightMagentaB() *Builder {
return builder.With(LightMagentaB)
}
// LightCyanB is a syntax for LightCyanB.
func (builder *Builder) LightCyanB() *Builder {
return builder.With(LightCyanB)
}
// LightWhiteB is a syntax for LightWhiteB.
func (builder *Builder) LightWhiteB() *Builder {
return builder.With(LightWhiteB)
}
// Color3BitF is a syntax for Color3BitF.
func (builder *Builder) Color3BitF(c RGB3Bit) *Builder {
return builder.With(Color3BitF(c))
}
// Color3BitB is a syntax for Color3BitB.
func (builder *Builder) Color3BitB(c RGB3Bit) *Builder {
return builder.With(Color3BitB(c))
}
// Color8BitF is a syntax for Color8BitF.
func (builder *Builder) Color8BitF(c RGB8Bit) *Builder {
return builder.With(Color8BitF(c))
}
// Color8BitB is a syntax for Color8BitB.
func (builder *Builder) Color8BitB(c RGB8Bit) *Builder {
return builder.With(Color8BitB(c))
}
// FullColorF is a syntax for FullColorF.
func (builder *Builder) FullColorF(r, g, b uint8) *Builder {
return builder.With(FullColorF(r, g, b))
}
// FullColorB is a syntax for FullColorB.
func (builder *Builder) FullColorB(r, g, b uint8) *Builder {
return builder.With(FullColorB(r, g, b))
}
// RGB3BitF is a syntax for Color3BitF with NewRGB3Bit.
func (builder *Builder) RGB3BitF(r, g, b uint8) *Builder {
return builder.Color3BitF(NewRGB3Bit(r, g, b))
}
// RGB3BitB is a syntax for Color3BitB with NewRGB3Bit.
func (builder *Builder) RGB3BitB(r, g, b uint8) *Builder {
return builder.Color3BitB(NewRGB3Bit(r, g, b))
}
// RGB8BitF is a syntax for Color8BitF with NewRGB8Bit.
func (builder *Builder) RGB8BitF(r, g, b uint8) *Builder {
return builder.Color8BitF(NewRGB8Bit(r, g, b))
}
// RGB8BitB is a syntax for Color8BitB with NewRGB8Bit.
func (builder *Builder) RGB8BitB(r, g, b uint8) *Builder {
return builder.Color8BitB(NewRGB8Bit(r, g, b))
}
func init() {
EmptyBuilder = &Builder{empty}
}
package aec
import (
"fmt"
)
// RGB3Bit is a 3bit RGB color.
type RGB3Bit uint8
// RGB8Bit is a 8bit RGB color.
type RGB8Bit uint8
func newSGR(n uint) ANSI {
return newAnsi(fmt.Sprintf(esc+"%dm", n))
}
// NewRGB3Bit create a RGB3Bit from given RGB.
func NewRGB3Bit(r, g, b uint8) RGB3Bit {
return RGB3Bit((r >> 7) | ((g >> 6) & 0x2) | ((b >> 5) & 0x4))
}
// NewRGB8Bit create a RGB8Bit from given RGB.
func NewRGB8Bit(r, g, b uint8) RGB8Bit {
return RGB8Bit(16 + 36*(r/43) + 6*(g/43) + b/43)
}
// Color3BitF set the foreground color of text.
func Color3BitF(c RGB3Bit) ANSI {
return newAnsi(fmt.Sprintf(esc+"%dm", c+30))
}
// Color3BitB set the background color of text.
func Color3BitB(c RGB3Bit) ANSI {
return newAnsi(fmt.Sprintf(esc+"%dm", c+40))
}
// Color8BitF set the foreground color of text.
func Color8BitF(c RGB8Bit) ANSI {
return newAnsi(fmt.Sprintf(esc+"38;5;%dm", c))
}
// Color8BitB set the background color of text.
func Color8BitB(c RGB8Bit) ANSI {
return newAnsi(fmt.Sprintf(esc+"48;5;%dm", c))
}
// FullColorF set the foreground color of text.
func FullColorF(r, g, b uint8) ANSI {
return newAnsi(fmt.Sprintf(esc+"38;2;%d;%d;%dm", r, g, b))
}
// FullColorB set the foreground color of text.
func FullColorB(r, g, b uint8) ANSI {
return newAnsi(fmt.Sprintf(esc+"48;2;%d;%d;%dm", r, g, b))
}
// Style
var (
// Bold set the text style to bold or increased intensity.
Bold ANSI
// Faint set the text style to faint.
Faint ANSI
// Italic set the text style to italic.
Italic ANSI
// Underline set the text style to underline.
Underline ANSI
// BlinkSlow set the text style to slow blink.
BlinkSlow ANSI
// BlinkRapid set the text style to rapid blink.
BlinkRapid ANSI
// Inverse swap the foreground color and background color.
Inverse ANSI
// Conceal set the text style to conceal.
Conceal ANSI
// CrossOut set the text style to crossed out.
CrossOut ANSI
// Frame set the text style to framed.
Frame ANSI
// Encircle set the text style to encircled.
Encircle ANSI
// Overline set the text style to overlined.
Overline ANSI
)
// Foreground color of text.
var (
// DefaultF is the default color of foreground.
DefaultF ANSI
// Normal color
BlackF ANSI
RedF ANSI
GreenF ANSI
YellowF ANSI
BlueF ANSI
MagentaF ANSI
CyanF ANSI
WhiteF ANSI
// Light color
LightBlackF ANSI
LightRedF ANSI
LightGreenF ANSI
LightYellowF ANSI
LightBlueF ANSI
LightMagentaF ANSI
LightCyanF ANSI
LightWhiteF ANSI
)
// Background color of text.
var (
// DefaultB is the default color of background.
DefaultB ANSI
// Normal color
BlackB ANSI
RedB ANSI
GreenB ANSI
YellowB ANSI
BlueB ANSI
MagentaB ANSI
CyanB ANSI
WhiteB ANSI
// Light color
LightBlackB ANSI
LightRedB ANSI
LightGreenB ANSI
LightYellowB ANSI
LightBlueB ANSI
LightMagentaB ANSI
LightCyanB ANSI
LightWhiteB ANSI
)
func init() {
Bold = newSGR(1)
Faint = newSGR(2)
Italic = newSGR(3)
Underline = newSGR(4)
BlinkSlow = newSGR(5)
BlinkRapid = newSGR(6)
Inverse = newSGR(7)
Conceal = newSGR(8)
CrossOut = newSGR(9)
BlackF = newSGR(30)
RedF = newSGR(31)
GreenF = newSGR(32)
YellowF = newSGR(33)
BlueF = newSGR(34)
MagentaF = newSGR(35)
CyanF = newSGR(36)
WhiteF = newSGR(37)
DefaultF = newSGR(39)
BlackB = newSGR(40)
RedB = newSGR(41)
GreenB = newSGR(42)
YellowB = newSGR(43)
BlueB = newSGR(44)
MagentaB = newSGR(45)
CyanB = newSGR(46)
WhiteB = newSGR(47)
DefaultB = newSGR(49)
Frame = newSGR(51)
Encircle = newSGR(52)
Overline = newSGR(53)
LightBlackF = newSGR(90)
LightRedF = newSGR(91)
LightGreenF = newSGR(92)
LightYellowF = newSGR(93)
LightBlueF = newSGR(94)
LightMagentaF = newSGR(95)
LightCyanF = newSGR(96)
LightWhiteF = newSGR(97)
LightBlackB = newSGR(100)
LightRedB = newSGR(101)
LightGreenB = newSGR(102)
LightYellowB = newSGR(103)
LightBlueB = newSGR(104)
LightMagentaB = newSGR(105)
LightCyanB = newSGR(106)
LightWhiteB = newSGR(107)
}
...@@ -58,8 +58,6 @@ github.com/Microsoft/hcsshim/internal/timeout ...@@ -58,8 +58,6 @@ github.com/Microsoft/hcsshim/internal/timeout
github.com/Microsoft/hcsshim/internal/wclayer github.com/Microsoft/hcsshim/internal/wclayer
# github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 => github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 # github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46 => github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46
github.com/NYTimes/gziphandler github.com/NYTimes/gziphandler
# github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 => github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5
github.com/Nvveen/Gotty
# github.com/PuerkitoBio/purell v1.1.0 => github.com/PuerkitoBio/purell v1.1.0 # github.com/PuerkitoBio/purell v1.1.0 => github.com/PuerkitoBio/purell v1.1.0
github.com/PuerkitoBio/purell github.com/PuerkitoBio/purell
# github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 => github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 # github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 => github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578
...@@ -351,7 +349,8 @@ github.com/dgrijalva/jwt-go ...@@ -351,7 +349,8 @@ github.com/dgrijalva/jwt-go
# github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff => github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff # github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff => github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff
github.com/docker/distribution/digestset github.com/docker/distribution/digestset
github.com/docker/distribution/reference github.com/docker/distribution/reference
# github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 => github.com/docker/docker v0.0.0-20180612054059-a9fbbdc8dd87 github.com/docker/distribution/registry/api/errcode
# github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0 => github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/docker/api github.com/docker/docker/api
github.com/docker/docker/api/types github.com/docker/docker/api/types
github.com/docker/docker/api/types/blkiodev github.com/docker/docker/api/types/blkiodev
...@@ -370,6 +369,7 @@ github.com/docker/docker/api/types/versions ...@@ -370,6 +369,7 @@ github.com/docker/docker/api/types/versions
github.com/docker/docker/api/types/volume github.com/docker/docker/api/types/volume
github.com/docker/docker/client github.com/docker/docker/client
github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog
github.com/docker/docker/errdefs
github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/pkg/jsonmessage
github.com/docker/docker/pkg/mount github.com/docker/docker/pkg/mount
github.com/docker/docker/pkg/parsers github.com/docker/docker/pkg/parsers
...@@ -691,6 +691,8 @@ github.com/modern-go/concurrent ...@@ -691,6 +691,8 @@ github.com/modern-go/concurrent
github.com/modern-go/reflect2 github.com/modern-go/reflect2
# github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb => github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb # github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb => github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb
github.com/mohae/deepcopy github.com/mohae/deepcopy
# github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c => github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c
github.com/morikuni/aec
# github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 => github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 # github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058 => github.com/mrunalp/fileutils v0.0.0-20160930181131-4ee1cc9a8058
github.com/mrunalp/fileutils github.com/mrunalp/fileutils
# github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d # github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment