Bump docker/docker and containerd/console

Signed-off-by: ulyssessouza <ulyssessouza@gmail.com>
pull/207/head
ulyssessouza 5 years ago
parent a0490a8720
commit 9f4f945d4f

@ -13,7 +13,7 @@ require (
github.com/bugsnag/panicwrap v1.2.0 // indirect github.com/bugsnag/panicwrap v1.2.0 // indirect
github.com/cenkalti/backoff v2.1.1+incompatible // indirect github.com/cenkalti/backoff v2.1.1+incompatible // indirect
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e // indirect
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e
github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0 github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 // indirect
github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20 // indirect github.com/containerd/typeurl v0.0.0-20190228175220-2a93cfde8c20 // indirect
@ -82,7 +82,6 @@ require (
github.com/xeipuuv/gojsonschema v0.0.0-20160323030313-93e72a773fad // indirect github.com/xeipuuv/gojsonschema v0.0.0-20160323030313-93e72a773fad // indirect
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 // indirect github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1 // indirect
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc // indirect
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
gopkg.in/fatih/pool.v2 v2.0.0 // indirect gopkg.in/fatih/pool.v2 v2.0.0 // indirect
@ -95,3 +94,5 @@ require (
) )
replace github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305 replace github.com/jaguilar/vt100 => github.com/tonistiigi/vt100 v0.0.0-20190402012908-ad4c4a574305
replace github.com/docker/docker v1.14.0-0.20190410063227-3998dffb806f3887f804b813069f59bc14a7f3c1 => github.com/docker/docker v0.7.3-0.20191210192822-1347481b9eb5

@ -38,6 +38,8 @@ github.com/containerd/cgroups v0.0.0-20190226200435-dbea6f2bd416 h1:AaSMvkPaxfZD
github.com/containerd/cgroups v0.0.0-20190226200435-dbea6f2bd416/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= github.com/containerd/cgroups v0.0.0-20190226200435-dbea6f2bd416/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 h1:WMpHmC6AxwWb9hMqhudkqG7A/p14KiMnl6d3r1iUMjU= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 h1:WMpHmC6AxwWb9hMqhudkqG7A/p14KiMnl6d3r1iUMjU=
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e h1:GdiIYd8ZDOrT++e1NjhSD4rGt9zaJukHm4rt5F4mRQc=
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
github.com/containerd/containerd v1.2.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.2.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0 h1:enps1EZBEgR8QxwdrpsoSxcsCXWnMKchIQ/0dzC0eKw= github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0 h1:enps1EZBEgR8QxwdrpsoSxcsCXWnMKchIQ/0dzC0eKw=
github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0-0.20190507210959-7c1e88399ec0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
@ -74,9 +76,9 @@ github.com/docker/compose-on-kubernetes v0.4.19-0.20190128150448-356b2919c496/go
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible h1:dvc1KSkIYTVjZgHf/CTC2diTYC8PzhaA5sFISRfNVrE= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible h1:dvc1KSkIYTVjZgHf/CTC2diTYC8PzhaA5sFISRfNVrE=
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.0.0-20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.0.0-20180531152204-71cd53e4a197/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v0.7.3-0.20191210192822-1347481b9eb5 h1:TlqwKXVW6frcHSbZMMp1rE7j5mi9M53NMAGDBFKtvlI=
github.com/docker/docker v0.7.3-0.20191210192822-1347481b9eb5/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.14.0-0.20190319215453-e7b5f7dbe98c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.14.0-0.20190410063227-3998dffb806f3887f804b813069f59bc14a7f3c1 h1:7RxCTE2/CdvPF5C622C/L8bPqbJd+/Sjz22p5GdcjcQ=
github.com/docker/docker v1.14.0-0.20190410063227-3998dffb806f3887f804b813069f59bc14a7f3c1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.0/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.6.0/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.1 h1:Dq4iIfcM7cNtddhLVWe9h4QDjsi4OER3Z8voPu/I52g= github.com/docker/docker-credential-helpers v0.6.1 h1:Dq4iIfcM7cNtddhLVWe9h4QDjsi4OER3Z8voPu/I52g=
github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/docker-credential-helpers v0.6.1/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
@ -309,8 +311,8 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190303122642-d455e41777fc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190303122642-d455e41777fc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc h1:4gbWbmmPFp4ySWICouJl6emP0MyS31yy9SrTlAGFT+g= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

@ -1,17 +1,16 @@
language: go language: go
go: go:
- "1.10.x" - "1.12.x"
- "1.11.x" - "1.13.x"
go_import_path: github.com/containerd/console go_import_path: github.com/containerd/console
env:
- GO111MODULE=on
install: install:
- go get -d - pushd ..; go get -u github.com/vbatts/git-validation; popd
- GOOS=openbsd go get -d - pushd ..; go get -u github.com/kunalkushwaha/ltag; popd
- GOOS=solaris go get -d
- GOOS=windows go get -d
- go get -u github.com/vbatts/git-validation
- go get -u github.com/kunalkushwaha/ltag
before_script: before_script:
- pushd ..; git clone https://github.com/containerd/project; popd - pushd ..; git clone https://github.com/containerd/project; popd
@ -19,6 +18,7 @@ before_script:
script: script:
- DCO_VERBOSITY=-q ../project/script/validate/dco - DCO_VERBOSITY=-q ../project/script/validate/dco
- ../project/script/validate/fileheader ../project/ - ../project/script/validate/fileheader ../project/
- travis_wait ../project/script/validate/vendor
- go test -race - go test -race
- GOOS=openbsd go build - GOOS=openbsd go build
- GOOS=openbsd go test -c - GOOS=openbsd go test -c

@ -24,10 +24,17 @@ import (
var ErrNotAConsole = errors.New("provided file is not a console") var ErrNotAConsole = errors.New("provided file is not a console")
type File interface {
io.ReadWriteCloser
// Fd returns its file descriptor
Fd() uintptr
// Name returns its file name
Name() string
}
type Console interface { type Console interface {
io.Reader File
io.Writer
io.Closer
// Resize resizes the console to the provided window size // Resize resizes the console to the provided window size
Resize(WinSize) error Resize(WinSize) error
@ -42,10 +49,6 @@ type Console interface {
Reset() error Reset() error
// Size returns the window size of the console // Size returns the window size of the console
Size() (WinSize, error) Size() (WinSize, error)
// Fd returns the console's file descriptor
Fd() uintptr
// Name returns the console's file name
Name() string
} }
// WinSize specifies the window size of the console // WinSize specifies the window size of the console
@ -70,7 +73,7 @@ func Current() Console {
} }
// ConsoleFromFile returns a console using the provided file // ConsoleFromFile returns a console using the provided file
func ConsoleFromFile(f *os.File) (Console, error) { func ConsoleFromFile(f File) (Console, error) {
if err := checkConsole(f); err != nil { if err := checkConsole(f); err != nil {
return nil, err return nil, err
} }

@ -47,7 +47,7 @@ func NewPty() (Console, string, error) {
} }
type master struct { type master struct {
f *os.File f File
original *unix.Termios original *unix.Termios
} }
@ -122,7 +122,7 @@ func (m *master) Name() string {
} }
// checkConsole checks if the provided file is a console // checkConsole checks if the provided file is a console
func checkConsole(f *os.File) error { func checkConsole(f File) error {
var termios unix.Termios var termios unix.Termios
if tcget(f.Fd(), &termios) != nil { if tcget(f.Fd(), &termios) != nil {
return ErrNotAConsole return ErrNotAConsole
@ -130,7 +130,7 @@ func checkConsole(f *os.File) error {
return nil return nil
} }
func newMaster(f *os.File) (Console, error) { func newMaster(f File) (Console, error) {
m := &master{ m := &master{
f: f, f: f,
} }

@ -198,7 +198,7 @@ func makeInputRaw(fd windows.Handle, mode uint32) error {
return nil return nil
} }
func checkConsole(f *os.File) error { func checkConsole(f File) error {
var mode uint32 var mode uint32
if err := windows.GetConsoleMode(windows.Handle(f.Fd()), &mode); err != nil { if err := windows.GetConsoleMode(windows.Handle(f.Fd()), &mode); err != nil {
return err return err
@ -206,7 +206,7 @@ func checkConsole(f *os.File) error {
return nil return nil
} }
func newMaster(f *os.File) (Console, error) { func newMaster(f File) (Console, error) {
if f != os.Stdin && f != os.Stdout && f != os.Stderr { if f != os.Stdin && f != os.Stdout && f != os.Stderr {
return nil, errors.New("creating a console from a file is not supported on windows") return nil, errors.New("creating a console from a file is not supported on windows")
} }

@ -0,0 +1,8 @@
module github.com/containerd/console
go 1.13
require (
github.com/pkg/errors v0.8.1
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e
)

@ -0,0 +1,4 @@
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

@ -18,6 +18,7 @@ Abhishek Chanda <abhishek.becs@gmail.com>
Abhishek Sharma <abhishek@asharma.me> Abhishek Sharma <abhishek@asharma.me>
Abin Shahab <ashahab@altiscale.com> Abin Shahab <ashahab@altiscale.com>
Adam Avilla <aavilla@yp.com> Adam Avilla <aavilla@yp.com>
Adam Dobrawy <naczelnik@jawnosc.tk>
Adam Eijdenberg <adam.eijdenberg@gmail.com> Adam Eijdenberg <adam.eijdenberg@gmail.com>
Adam Kunk <adam.kunk@tiaa-cref.org> Adam Kunk <adam.kunk@tiaa-cref.org>
Adam Miller <admiller@redhat.com> Adam Miller <admiller@redhat.com>
@ -113,6 +114,7 @@ Anda Xu <anda.xu@docker.com>
Anders Janmyr <anders@janmyr.com> Anders Janmyr <anders@janmyr.com>
Andre Dublin <81dublin@gmail.com> Andre Dublin <81dublin@gmail.com>
Andre Granovsky <robotciti@live.com> Andre Granovsky <robotciti@live.com>
Andrea Denisse Gómez <crypto.andrea@protonmail.ch>
Andrea Luzzardi <aluzzardi@gmail.com> Andrea Luzzardi <aluzzardi@gmail.com>
Andrea Turli <andrea.turli@gmail.com> Andrea Turli <andrea.turli@gmail.com>
Andreas Elvers <andreas@work.de> Andreas Elvers <andreas@work.de>
@ -177,8 +179,10 @@ Anusha Ragunathan <anusha.ragunathan@docker.com>
apocas <petermdias@gmail.com> apocas <petermdias@gmail.com>
Arash Deshmeh <adeshmeh@ca.ibm.com> Arash Deshmeh <adeshmeh@ca.ibm.com>
ArikaChen <eaglesora@gmail.com> ArikaChen <eaglesora@gmail.com>
Arko Dasgupta <arko.dasgupta@docker.com>
Arnaud Lefebvre <a.lefebvre@outlook.fr> Arnaud Lefebvre <a.lefebvre@outlook.fr>
Arnaud Porterie <arnaud.porterie@docker.com> Arnaud Porterie <arnaud.porterie@docker.com>
Arnaud Rebillout <arnaud.rebillout@collabora.com>
Arthur Barr <arthur.barr@uk.ibm.com> Arthur Barr <arthur.barr@uk.ibm.com>
Arthur Gautier <baloo@gandi.net> Arthur Gautier <baloo@gandi.net>
Artur Meyster <arthurfbi@yahoo.com> Artur Meyster <arthurfbi@yahoo.com>
@ -280,6 +284,7 @@ Carl Loa Odin <carlodin@gmail.com>
Carl X. Su <bcbcarl@gmail.com> Carl X. Su <bcbcarl@gmail.com>
Carlo Mion <mion00@gmail.com> Carlo Mion <mion00@gmail.com>
Carlos Alexandro Becker <caarlos0@gmail.com> Carlos Alexandro Becker <caarlos0@gmail.com>
Carlos de Paula <me@carlosedp.com>
Carlos Sanchez <carlos@apache.org> Carlos Sanchez <carlos@apache.org>
Carol Fager-Higgins <carol.fager-higgins@docker.com> Carol Fager-Higgins <carol.fager-higgins@docker.com>
Cary <caryhartline@users.noreply.github.com> Cary <caryhartline@users.noreply.github.com>
@ -329,6 +334,7 @@ Chris Gibson <chris@chrisg.io>
Chris Khoo <chris.khoo@gmail.com> Chris Khoo <chris.khoo@gmail.com>
Chris McKinnel <chris.mckinnel@tangentlabs.co.uk> Chris McKinnel <chris.mckinnel@tangentlabs.co.uk>
Chris McKinnel <chrismckinnel@gmail.com> Chris McKinnel <chrismckinnel@gmail.com>
Chris Price <chris.price@docker.com>
Chris Seto <chriskseto@gmail.com> Chris Seto <chriskseto@gmail.com>
Chris Snow <chsnow123@gmail.com> Chris Snow <chsnow123@gmail.com>
Chris St. Pierre <chris.a.st.pierre@gmail.com> Chris St. Pierre <chris.a.st.pierre@gmail.com>
@ -418,12 +424,14 @@ Daniel Norberg <dano@spotify.com>
Daniel Nordberg <dnordberg@gmail.com> Daniel Nordberg <dnordberg@gmail.com>
Daniel Robinson <gottagetmac@gmail.com> Daniel Robinson <gottagetmac@gmail.com>
Daniel S <dan.streby@gmail.com> Daniel S <dan.streby@gmail.com>
Daniel Sweet <danieljsweet@icloud.com>
Daniel Von Fange <daniel@leancoder.com> Daniel Von Fange <daniel@leancoder.com>
Daniel Watkins <daniel@daniel-watkins.co.uk> Daniel Watkins <daniel@daniel-watkins.co.uk>
Daniel X Moore <yahivin@gmail.com> Daniel X Moore <yahivin@gmail.com>
Daniel YC Lin <dlin.tw@gmail.com> Daniel YC Lin <dlin.tw@gmail.com>
Daniel Zhang <jmzwcn@gmail.com> Daniel Zhang <jmzwcn@gmail.com>
Danny Berger <dpb587@gmail.com> Danny Berger <dpb587@gmail.com>
Danny Milosavljevic <dannym@scratchpost.org>
Danny Yates <danny@codeaholics.org> Danny Yates <danny@codeaholics.org>
Danyal Khaliq <danyal.khaliq@tenpearls.com> Danyal Khaliq <danyal.khaliq@tenpearls.com>
Darren Coxall <darren@darrencoxall.com> Darren Coxall <darren@darrencoxall.com>
@ -517,6 +525,8 @@ Dmitry Smirnov <onlyjob@member.fsf.org>
Dmitry V. Krivenok <krivenok.dmitry@gmail.com> Dmitry V. Krivenok <krivenok.dmitry@gmail.com>
Dmitry Vorobev <dimahabr@gmail.com> Dmitry Vorobev <dimahabr@gmail.com>
Dolph Mathews <dolph.mathews@gmail.com> Dolph Mathews <dolph.mathews@gmail.com>
Dominic Tubach <dominic.tubach@to.com>
Dominic Yin <yindongchao@inspur.com>
Dominik Dingel <dingel@linux.vnet.ibm.com> Dominik Dingel <dingel@linux.vnet.ibm.com>
Dominik Finkbeiner <finkes93@gmail.com> Dominik Finkbeiner <finkes93@gmail.com>
Dominik Honnef <dominik@honnef.co> Dominik Honnef <dominik@honnef.co>
@ -585,6 +595,7 @@ Erik Weathers <erikdw@gmail.com>
Erno Hopearuoho <erno.hopearuoho@gmail.com> Erno Hopearuoho <erno.hopearuoho@gmail.com>
Erwin van der Koogh <info@erronis.nl> Erwin van der Koogh <info@erronis.nl>
Ethan Bell <ebgamer29@gmail.com> Ethan Bell <ebgamer29@gmail.com>
Ethan Mosbaugh <ethan@replicated.com>
Euan Kemp <euan.kemp@coreos.com> Euan Kemp <euan.kemp@coreos.com>
Eugen Krizo <eugen.krizo@gmail.com> Eugen Krizo <eugen.krizo@gmail.com>
Eugene Yakubovich <eugene.yakubovich@coreos.com> Eugene Yakubovich <eugene.yakubovich@coreos.com>
@ -621,6 +632,7 @@ 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>
Felipe Oliveira <felipeweb.programador@gmail.com> Felipe Oliveira <felipeweb.programador@gmail.com>
Felipe Ruhland <felipe.ruhland@gmail.com>
Felix Abecassis <fabecassis@nvidia.com> Felix Abecassis <fabecassis@nvidia.com>
Felix Geisendörfer <felix@debuggable.com> Felix Geisendörfer <felix@debuggable.com>
Felix Hupfeld <felix@quobyte.com> Felix Hupfeld <felix@quobyte.com>
@ -655,6 +667,7 @@ Frank Groeneveld <frank@ivaldi.nl>
Frank Herrmann <fgh@4gh.tv> Frank Herrmann <fgh@4gh.tv>
Frank Macreery <frank@macreery.com> Frank Macreery <frank@macreery.com>
Frank Rosquin <frank.rosquin+github@gmail.com> Frank Rosquin <frank.rosquin+github@gmail.com>
frankyang <yyb196@gmail.com>
Fred Lifton <fred.lifton@docker.com> Fred Lifton <fred.lifton@docker.com>
Frederick F. Kautz IV <fkautz@redhat.com> Frederick F. Kautz IV <fkautz@redhat.com>
Frederik Loeffert <frederik@zitrusmedia.de> Frederik Loeffert <frederik@zitrusmedia.de>
@ -702,6 +715,7 @@ Gleb M Borisov <borisov.gleb@gmail.com>
Glyn Normington <gnormington@gopivotal.com> Glyn Normington <gnormington@gopivotal.com>
GoBella <caili_welcome@163.com> GoBella <caili_welcome@163.com>
Goffert van Gool <goffert@phusion.nl> Goffert van Gool <goffert@phusion.nl>
Goldwyn Rodrigues <rgoldwyn@suse.com>
Gopikannan Venugopalsamy <gopikannan.venugopalsamy@gmail.com> 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>
@ -725,6 +739,7 @@ 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>
Haichao Yang <yang.haichao@zte.com.cn>
haikuoliu <haikuo@amazon.com> haikuoliu <haikuo@amazon.com>
Hakan Özler <hakan.ozler@kodcu.com> Hakan Özler <hakan.ozler@kodcu.com>
Hamish Hutchings <moredhel@aoeu.me> Hamish Hutchings <moredhel@aoeu.me>
@ -733,6 +748,7 @@ Hans Rødtang <hansrodtang@gmail.com>
Hao Shu Wei <haosw@cn.ibm.com> Hao Shu Wei <haosw@cn.ibm.com>
Hao Zhang <21521210@zju.edu.cn> Hao Zhang <21521210@zju.edu.cn>
Harald Albers <github@albersweb.de> Harald Albers <github@albersweb.de>
Harald Niesche <harald@niesche.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> Harrison Turton <harrisonturton@gmail.com>
@ -752,9 +768,11 @@ Hobofan <goisser94@gmail.com>
Hollie Teal <hollie@docker.com> Hollie Teal <hollie@docker.com>
Hong Xu <hong@topbug.net> Hong Xu <hong@topbug.net>
Hongbin Lu <hongbin034@gmail.com> Hongbin Lu <hongbin034@gmail.com>
Hongxu Jia <hongxu.jia@windriver.com>
hsinko <21551195@zju.edu.cn> hsinko <21551195@zju.edu.cn>
Hu Keping <hukeping@huawei.com> Hu Keping <hukeping@huawei.com>
Hu Tao <hutao@cn.fujitsu.com> Hu Tao <hutao@cn.fujitsu.com>
HuanHuan Ye <logindaveye@gmail.com>
Huanzhong Zhang <zhanghuanzhong90@gmail.com> Huanzhong Zhang <zhanghuanzhong90@gmail.com>
Huayi Zhang <irachex@gmail.com> Huayi Zhang <irachex@gmail.com>
Hugo Duncan <hugo@hugoduncan.org> Hugo Duncan <hugo@hugoduncan.org>
@ -898,6 +916,7 @@ 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>
Jim Alateras <jima@comware.com.au> Jim Alateras <jima@comware.com.au>
Jim Ehrismann <jim.ehrismann@docker.com>
Jim Galasyn <jim.galasyn@docker.com> Jim Galasyn <jim.galasyn@docker.com>
Jim Minter <jminter@redhat.com> Jim Minter <jminter@redhat.com>
Jim Perrin <jperrin@centos.org> Jim Perrin <jperrin@centos.org>
@ -935,7 +954,7 @@ John Feminella <jxf@jxf.me>
John Gardiner Myers <jgmyers@proofpoint.com> John Gardiner Myers <jgmyers@proofpoint.com>
John Gossman <johngos@microsoft.com> John Gossman <johngos@microsoft.com>
John Harris <john@johnharris.io> John Harris <john@johnharris.io>
John Howard (VM) <John.Howard@microsoft.com> John Howard <github@lowenna.com>
John Laswell <john.n.laswell@gmail.com> John Laswell <john.n.laswell@gmail.com>
John Maguire <jmaguire@duosecurity.com> John Maguire <jmaguire@duosecurity.com>
John Mulhausen <john@docker.com> John Mulhausen <john@docker.com>
@ -949,6 +968,7 @@ John Willis <john.willis@docker.com>
Jon Johnson <jonjohnson@google.com> 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 Dohse <jonas@dohse.ch>
Jonas Pfenniger <jonas@pfenniger.name> Jonas Pfenniger <jonas@pfenniger.name>
Jonathan A. Schweder <jonathanschweder@gmail.com> Jonathan A. Schweder <jonathanschweder@gmail.com>
Jonathan A. Sternberg <jonathansternberg@gmail.com> Jonathan A. Sternberg <jonathansternberg@gmail.com>
@ -1002,6 +1022,7 @@ Julio Montes <imc.coder@gmail.com>
Jun-Ru Chang <jrjang@gmail.com> Jun-Ru Chang <jrjang@gmail.com>
Jussi Nummelin <jussi.nummelin@gmail.com> Jussi Nummelin <jussi.nummelin@gmail.com>
Justas Brazauskas <brazauskasjustas@gmail.com> Justas Brazauskas <brazauskasjustas@gmail.com>
Justen Martin <jmart@the-coder.com>
Justin Cormack <justin.cormack@docker.com> Justin Cormack <justin.cormack@docker.com>
Justin Force <justin.force@gmail.com> Justin Force <justin.force@gmail.com>
Justin Menga <justin.menga@gmail.com> Justin Menga <justin.menga@gmail.com>
@ -1010,6 +1031,7 @@ Justin Simonelis <justin.p.simonelis@gmail.com>
Justin Terry <juterry@microsoft.com> Justin Terry <juterry@microsoft.com>
Justyn Temme <justyntemme@gmail.com> Justyn Temme <justyntemme@gmail.com>
Jyrki Puttonen <jyrkiput@gmail.com> Jyrki Puttonen <jyrkiput@gmail.com>
Jérémy Leherpeur <amenophis@leherpeur.net>
Jérôme Petazzoni <jerome.petazzoni@docker.com> Jérôme Petazzoni <jerome.petazzoni@docker.com>
Jörg Thalheim <joerg@higgsboson.tk> Jörg Thalheim <joerg@higgsboson.tk>
K. Heller <pestophagous@gmail.com> K. Heller <pestophagous@gmail.com>
@ -1047,6 +1069,7 @@ 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>
Kenta Tada <Kenta.Tada@sony.com>
Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com> Kevin "qwazerty" Houdebert <kevin.houdebert@gmail.com>
Kevin Burke <kev@inburke.com> Kevin Burke <kev@inburke.com>
Kevin Clark <kevin.clark@gmail.com> Kevin Clark <kevin.clark@gmail.com>
@ -1057,6 +1080,7 @@ Kevin Kern <kaiwentan@harmonycloud.cn>
Kevin Menard <kevin@nirvdrum.com> Kevin Menard <kevin@nirvdrum.com>
Kevin Meredith <kevin.m.meredith@gmail.com> Kevin Meredith <kevin.m.meredith@gmail.com>
Kevin P. Kucharczyk <kevinkucharczyk@gmail.com> Kevin P. Kucharczyk <kevinkucharczyk@gmail.com>
Kevin Parsons <kevpar@microsoft.com>
Kevin Richardson <kevin@kevinrichardson.co> Kevin Richardson <kevin@kevinrichardson.co>
Kevin Shi <kshi@andrew.cmu.edu> Kevin Shi <kshi@andrew.cmu.edu>
Kevin Wallace <kevin@pentabarf.net> Kevin Wallace <kevin@pentabarf.net>
@ -1147,6 +1171,7 @@ longliqiang88 <394564827@qq.com>
Lorenz Leutgeb <lorenz.leutgeb@gmail.com> Lorenz Leutgeb <lorenz.leutgeb@gmail.com>
Lorenzo Fontana <fontanalorenz@gmail.com> Lorenzo Fontana <fontanalorenz@gmail.com>
Lotus Fenn <fenn.lotus@gmail.com> Lotus Fenn <fenn.lotus@gmail.com>
Louis Delossantos <ldelossa.ld@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>
@ -1159,12 +1184,14 @@ Lucas Silvestre <lukas.silvestre@gmail.com>
Luciano Mores <leslau@gmail.com> Luciano Mores <leslau@gmail.com>
Luis Martínez de Bartolomé Izquierdo <lmartinez@biicode.com> Luis Martínez de Bartolomé Izquierdo <lmartinez@biicode.com>
Luiz Svoboda <luizek@gmail.com> Luiz Svoboda <luizek@gmail.com>
Lukas Heeren <lukas-heeren@hotmail.com>
Lukas Waslowski <cr7pt0gr4ph7@gmail.com> Lukas Waslowski <cr7pt0gr4ph7@gmail.com>
lukaspustina <lukas.pustina@centerdevice.com> lukaspustina <lukas.pustina@centerdevice.com>
Lukasz Zajaczkowski <Lukasz.Zajaczkowski@ts.fujitsu.com> Lukasz Zajaczkowski <Lukasz.Zajaczkowski@ts.fujitsu.com>
Luke Marsden <me@lukemarsden.net> Luke Marsden <me@lukemarsden.net>
Lyn <energylyn@zju.edu.cn> Lyn <energylyn@zju.edu.cn>
Lynda O'Leary <lyndaoleary29@gmail.com> Lynda O'Leary <lyndaoleary29@gmail.com>
lzhfromutsc <lzhfromustc@gmail.com>
Lénaïc Huard <lhuard@amadeus.com> Lénaïc Huard <lhuard@amadeus.com>
Ma Müller <mueller-ma@users.noreply.github.com> Ma Müller <mueller-ma@users.noreply.github.com>
Ma Shimiao <mashimiao.fnst@cn.fujitsu.com> Ma Shimiao <mashimiao.fnst@cn.fujitsu.com>
@ -1298,6 +1325,7 @@ Michael Stapelberg <michael+gh@stapelberg.de>
Michael Steinert <mike.steinert@gmail.com> Michael Steinert <mike.steinert@gmail.com>
Michael Thies <michaelthies78@gmail.com> Michael Thies <michaelthies78@gmail.com>
Michael West <mwest@mdsol.com> Michael West <mwest@mdsol.com>
Michael Zhao <michael.zhao@arm.com>
Michal Fojtik <mfojtik@redhat.com> Michal Fojtik <mfojtik@redhat.com>
Michal Gebauer <mishak@mishak.net> Michal Gebauer <mishak@mishak.net>
Michal Jemala <michal.jemala@gmail.com> Michal Jemala <michal.jemala@gmail.com>
@ -1382,6 +1410,7 @@ Neyazul Haque <nuhaque@gmail.com>
Nghia Tran <nghia@google.com> Nghia Tran <nghia@google.com>
Niall O'Higgins <niallo@unworkable.org> Niall O'Higgins <niallo@unworkable.org>
Nicholas E. Rabenau <nerab@gmx.at> Nicholas E. Rabenau <nerab@gmx.at>
Nick Adcock <nick.adcock@docker.com>
Nick DeCoursin <n.decoursin@foodpanda.com> Nick DeCoursin <n.decoursin@foodpanda.com>
Nick Irvine <nfirvine@nfirvine.com> Nick Irvine <nfirvine@nfirvine.com>
Nick Neisen <nwneisen@gmail.com> Nick Neisen <nwneisen@gmail.com>
@ -1420,6 +1449,7 @@ Nuutti Kotivuori <naked@iki.fi>
nzwsch <hi@nzwsch.com> nzwsch <hi@nzwsch.com>
O.S. Tezer <ostezer@gmail.com> O.S. Tezer <ostezer@gmail.com>
objectified <objectified@gmail.com> objectified <objectified@gmail.com>
Odin Ugedal <odin@ugedal.com>
Oguz Bilgic <fisyonet@gmail.com> Oguz Bilgic <fisyonet@gmail.com>
Oh Jinkyun <tintypemolly@gmail.com> Oh Jinkyun <tintypemolly@gmail.com>
Ohad Schneider <ohadschn@users.noreply.github.com> Ohad Schneider <ohadschn@users.noreply.github.com>
@ -1430,6 +1460,7 @@ 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> Olli Janatuinen <olli.janatuinen@gmail.com>
Olly Pomeroy <oppomeroy@gmail.com>
Omri Shiv <Omri.Shiv@teradata.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>
@ -1439,6 +1470,7 @@ Ovidio Mallo <ovidio.mallo@gmail.com>
Panagiotis Moustafellos <pmoust@elastic.co> Panagiotis Moustafellos <pmoust@elastic.co>
Paolo G. Giarrusso <p.giarrusso@gmail.com> Paolo G. Giarrusso <p.giarrusso@gmail.com>
Pascal <pascalgn@users.noreply.github.com> Pascal <pascalgn@users.noreply.github.com>
Pascal Bach <pascal.bach@siemens.com>
Pascal Borreli <pascal@borreli.com> Pascal Borreli <pascal@borreli.com>
Pascal Hartig <phartig@rdrei.net> Pascal Hartig <phartig@rdrei.net>
Patrick Böänziger <patrick.baenziger@bsi-software.com> Patrick Böänziger <patrick.baenziger@bsi-software.com>
@ -1463,6 +1495,7 @@ Paul Nasrat <pnasrat@gmail.com>
Paul Weaver <pauweave@cisco.com> Paul Weaver <pauweave@cisco.com>
Paulo Ribeiro <paigr.io@gmail.com> Paulo Ribeiro <paigr.io@gmail.com>
Pavel Lobashov <ShockwaveNN@gmail.com> Pavel Lobashov <ShockwaveNN@gmail.com>
Pavel Matěja <pavel@verotel.cz>
Pavel Pletenev <cpp.create@gmail.com> Pavel Pletenev <cpp.create@gmail.com>
Pavel Pospisil <pospispa@gmail.com> Pavel Pospisil <pospispa@gmail.com>
Pavel Sutyrin <pavel.sutyrin@gmail.com> Pavel Sutyrin <pavel.sutyrin@gmail.com>
@ -1574,6 +1607,7 @@ Riku Voipio <riku.voipio@linaro.org>
Riley Guerin <rileytg.dev@gmail.com> Riley Guerin <rileytg.dev@gmail.com>
Ritesh H Shukla <sritesh@vmware.com> Ritesh H Shukla <sritesh@vmware.com>
Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com> Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
Rob Gulewich <rgulewich@netflix.com>
Rob Vesse <rvesse@dotnetrdf.org> Rob Vesse <rvesse@dotnetrdf.org>
Robert Bachmann <rb@robertbachmann.at> Robert Bachmann <rb@robertbachmann.at>
Robert Bittle <guywithnose@gmail.com> Robert Bittle <guywithnose@gmail.com>
@ -1582,11 +1616,13 @@ Robert Schneider <mail@shakeme.info>
Robert Stern <lexandro2000@gmail.com> Robert Stern <lexandro2000@gmail.com>
Robert Terhaar <rterhaar@atlanticdynamic.com> Robert Terhaar <rterhaar@atlanticdynamic.com>
Robert Wallis <smilingrob@gmail.com> Robert Wallis <smilingrob@gmail.com>
Robert Wang <robert@arctic.tw>
Roberto G. Hashioka <roberto.hashioka@docker.com> Roberto G. Hashioka <roberto.hashioka@docker.com>
Roberto Muñoz Fernández <robertomf@gmail.com> Roberto Muñoz Fernández <robertomf@gmail.com>
Robin Naundorf <r.naundorf@fh-muenster.de> Robin Naundorf <r.naundorf@fh-muenster.de>
Robin Schneider <ypid@riseup.net> Robin Schneider <ypid@riseup.net>
Robin Speekenbrink <robin@kingsquare.nl> Robin Speekenbrink <robin@kingsquare.nl>
Robin Thoni <robin@rthoni.com>
robpc <rpcann@gmail.com> robpc <rpcann@gmail.com>
Rodolfo Carvalho <rhcarvalho@gmail.com> Rodolfo Carvalho <rhcarvalho@gmail.com>
Rodrigo Vaz <rodrigo.vaz@gmail.com> Rodrigo Vaz <rodrigo.vaz@gmail.com>
@ -1620,6 +1656,7 @@ Rozhnov Alexandr <nox73@ya.ru>
Rudolph Gottesheim <r.gottesheim@loot.at> Rudolph Gottesheim <r.gottesheim@loot.at>
Rui Cao <ruicao@alauda.io> Rui Cao <ruicao@alauda.io>
Rui Lopes <rgl@ruilopes.com> Rui Lopes <rgl@ruilopes.com>
Ruilin Li <liruilin4@huawei.com>
Runshen Zhu <runshen.zhu@gmail.com> Runshen Zhu <runshen.zhu@gmail.com>
Russ Magee <rmagee@gmail.com> Russ Magee <rmagee@gmail.com>
Ryan Abrams <rdabrams@gmail.com> Ryan Abrams <rdabrams@gmail.com>
@ -1658,6 +1695,7 @@ Sam J Sharpe <sam.sharpe@digital.cabinet-office.gov.uk>
Sam Neirinck <sam@samneirinck.com> Sam Neirinck <sam@samneirinck.com>
Sam Reis <sreis@atlassian.com> Sam Reis <sreis@atlassian.com>
Sam Rijs <srijs@airpost.net> Sam Rijs <srijs@airpost.net>
Sam Whited <sam@samwhited.com>
Sambuddha Basu <sambuddhabasu1@gmail.com> Sambuddha Basu <sambuddhabasu1@gmail.com>
Sami Wagiaalla <swagiaal@redhat.com> Sami Wagiaalla <swagiaal@redhat.com>
Samuel Andaya <samuel@andaya.net> Samuel Andaya <samuel@andaya.net>
@ -1672,6 +1710,7 @@ 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> Sascha Grunert <sgrunert@suse.com>
SataQiu <qiushida@beyondcent.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>
@ -1720,6 +1759,7 @@ Shijun Qin <qinshijun16@mails.ucas.ac.cn>
Shishir Mahajan <shishir.mahajan@redhat.com> Shishir Mahajan <shishir.mahajan@redhat.com>
Shoubhik Bose <sbose78@gmail.com> Shoubhik Bose <sbose78@gmail.com>
Shourya Sarcar <shourya.sarcar@gmail.com> Shourya Sarcar <shourya.sarcar@gmail.com>
Shu-Wai Chow <shu-wai.chow@seattlechildrens.org>
shuai-z <zs.broccoli@gmail.com> shuai-z <zs.broccoli@gmail.com>
Shukui Yang <yangshukui@huawei.com> Shukui Yang <yangshukui@huawei.com>
Shuwei Hao <haosw@cn.ibm.com> Shuwei Hao <haosw@cn.ibm.com>
@ -1730,6 +1770,7 @@ Silas Sewell <silas@sewell.org>
Silvan Jegen <s.jegen@gmail.com> Silvan Jegen <s.jegen@gmail.com>
Simão Reis <smnrsti@gmail.com> Simão Reis <smnrsti@gmail.com>
Simei He <hesimei@zju.edu.cn> Simei He <hesimei@zju.edu.cn>
Simon Barendse <simon.barendse@gmail.com>
Simon Eskildsen <sirup@sirupsen.com> Simon Eskildsen <sirup@sirupsen.com>
Simon Ferquel <simon.ferquel@docker.com> Simon Ferquel <simon.ferquel@docker.com>
Simon Leinen <simon.leinen@gmail.com> Simon Leinen <simon.leinen@gmail.com>
@ -1738,6 +1779,7 @@ Simon Taranto <simon.taranto@gmail.com>
Simon Vikstrom <pullreq@devsn.se> Simon Vikstrom <pullreq@devsn.se>
Sindhu S <sindhus@live.in> Sindhu S <sindhus@live.in>
Sjoerd Langkemper <sjoerd-github@linuxonly.nl> Sjoerd Langkemper <sjoerd-github@linuxonly.nl>
skanehira <sho19921005@gmail.com>
Solganik Alexander <solganik@gmail.com> Solganik Alexander <solganik@gmail.com>
Solomon Hykes <solomon@docker.com> Solomon Hykes <solomon@docker.com>
Song Gao <song@gao.io> Song Gao <song@gao.io>
@ -1749,6 +1791,7 @@ Sridatta Thatipamala <sthatipamala@gmail.com>
Sridhar Ratnakumar <sridharr@activestate.com> Sridhar Ratnakumar <sridharr@activestate.com>
Srini Brahmaroutu <srbrahma@us.ibm.com> Srini Brahmaroutu <srbrahma@us.ibm.com>
Srinivasan Srivatsan <srinivasan.srivatsan@hpe.com> Srinivasan Srivatsan <srinivasan.srivatsan@hpe.com>
Staf Wagemakers <staf@wagemakers.be>
Stanislav Bondarenko <stanislav.bondarenko@gmail.com> Stanislav Bondarenko <stanislav.bondarenko@gmail.com>
Steeve Morin <steeve.morin@gmail.com> Steeve Morin <steeve.morin@gmail.com>
Stefan Berger <stefanb@linux.vnet.ibm.com> Stefan Berger <stefanb@linux.vnet.ibm.com>
@ -1759,6 +1802,7 @@ Stefan Scherer <stefan.scherer@docker.com>
Stefan Staudenmeyer <doerte@instana.com> Stefan Staudenmeyer <doerte@instana.com>
Stefan Weil <sw@weilnetz.de> Stefan Weil <sw@weilnetz.de>
Stephan Spindler <shutefan@gmail.com> Stephan Spindler <shutefan@gmail.com>
Stephen Benjamin <stephen@redhat.com>
Stephen Crosby <stevecrozz@gmail.com> Stephen Crosby <stevecrozz@gmail.com>
Stephen Day <stephen.day@docker.com> Stephen Day <stephen.day@docker.com>
Stephen Drake <stephen@xenolith.net> Stephen Drake <stephen@xenolith.net>
@ -1775,10 +1819,12 @@ Steven Iveson <sjiveson@outlook.com>
Steven Merrill <steven.merrill@gmail.com> Steven Merrill <steven.merrill@gmail.com>
Steven Richards <steven@axiomzen.co> Steven Richards <steven@axiomzen.co>
Steven Taylor <steven.taylor@me.com> Steven Taylor <steven.taylor@me.com>
Stig Larsson <stig@larsson.dev>
Subhajit Ghosh <isubuz.g@gmail.com> Subhajit Ghosh <isubuz.g@gmail.com>
Sujith Haridasan <sujith.h@gmail.com> Sujith Haridasan <sujith.h@gmail.com>
Sun Gengze <690388648@qq.com> Sun Gengze <690388648@qq.com>
Sun Jianbo <wonderflow.sun@gmail.com> Sun Jianbo <wonderflow.sun@gmail.com>
Sune Keller <sune.keller@gmail.com>
Sunny Gogoi <indiasuny000@gmail.com> Sunny Gogoi <indiasuny000@gmail.com>
Suryakumar Sudar <surya.trunks@gmail.com> Suryakumar Sudar <surya.trunks@gmail.com>
Sven Dowideit <SvenDowideit@home.org.au> Sven Dowideit <SvenDowideit@home.org.au>
@ -1829,6 +1875,7 @@ Tianyi Wang <capkurmagati@gmail.com>
Tibor Vass <teabee89@gmail.com> Tibor Vass <teabee89@gmail.com>
Tiffany Jernigan <tiffany.f.j@gmail.com> Tiffany Jernigan <tiffany.f.j@gmail.com>
Tiffany Low <tiffany@box.com> Tiffany Low <tiffany@box.com>
Tim <elatllat@gmail.com>
Tim Bart <tim@fewagainstmany.com> Tim Bart <tim@fewagainstmany.com>
Tim Bosse <taim@bosboot.org> Tim Bosse <taim@bosboot.org>
Tim Dettrick <t.dettrick@uq.edu.au> Tim Dettrick <t.dettrick@uq.edu.au>
@ -1914,6 +1961,7 @@ Victor Palma <palma.victor@gmail.com>
Victor Vieux <victor.vieux@docker.com> Victor Vieux <victor.vieux@docker.com>
Victoria Bialas <victoria.bialas@docker.com> Victoria Bialas <victoria.bialas@docker.com>
Vijaya Kumar K <vijayak@caviumnetworks.com> Vijaya Kumar K <vijayak@caviumnetworks.com>
Vikram bir Singh <vikrambir.singh@docker.com>
Viktor Stanchev <me@viktorstanchev.com> Viktor Stanchev <me@viktorstanchev.com>
Viktor Vojnovski <viktor.vojnovski@amadeus.com> Viktor Vojnovski <viktor.vojnovski@amadeus.com>
VinayRaghavanKS <raghavan.vinay@gmail.com> VinayRaghavanKS <raghavan.vinay@gmail.com>
@ -1971,6 +2019,7 @@ Wenyu You <21551128@zju.edu.cn>
Wenzhi Liang <wenzhi.liang@gmail.com> Wenzhi Liang <wenzhi.liang@gmail.com>
Wes Morgan <cap10morgan@gmail.com> Wes Morgan <cap10morgan@gmail.com>
Wewang Xiaorenfine <wang.xiaoren@zte.com.cn> Wewang Xiaorenfine <wang.xiaoren@zte.com.cn>
Wiktor Kwapisiewicz <wiktor@metacode.biz>
Will Dietz <w@wdtz.org> Will Dietz <w@wdtz.org>
Will Rouesnel <w.rouesnel@gmail.com> Will Rouesnel <w.rouesnel@gmail.com>
Will Weaver <monkey@buildingbananas.com> Will Weaver <monkey@buildingbananas.com>
@ -1998,6 +2047,7 @@ xichengliudui <1693291525@qq.com>
xiekeyang <xiekeyang@huawei.com> xiekeyang <xiekeyang@huawei.com>
Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com> Ximo Guanter Gonzálbez <joaquin.guantergonzalbez@telefonica.com>
Xinbo Weng <xihuanbo_0521@zju.edu.cn> Xinbo Weng <xihuanbo_0521@zju.edu.cn>
Xinfeng Liu <xinfeng.liu@gmail.com>
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>
@ -2012,6 +2062,7 @@ Yang Pengfei <yangpengfei4@huawei.com>
yangchenliang <yangchenliang@huawei.com> yangchenliang <yangchenliang@huawei.com>
Yanqiang Miao <miao.yanqiang@zte.com.cn> Yanqiang Miao <miao.yanqiang@zte.com.cn>
Yao Zaiyong <yaozaiyong@hotmail.com> Yao Zaiyong <yaozaiyong@hotmail.com>
Yash Murty <yashmurty@gmail.com>
Yassine Tijani <yasstij11@gmail.com> Yassine Tijani <yasstij11@gmail.com>
Yasunori Mahata <nori@mahata.net> Yasunori Mahata <nori@mahata.net>
Yazhong Liu <yorkiefixer@gmail.com> Yazhong Liu <yorkiefixer@gmail.com>
@ -2026,6 +2077,7 @@ 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>
youcai <omegacoleman@gmail.com>
Youcef YEKHLEF <yyekhlef@gmail.com> Youcef YEKHLEF <yyekhlef@gmail.com>
Yu Changchun <yuchangchun1@huawei.com> Yu Changchun <yuchangchun1@huawei.com>
Yu Chengxia <yuchengxia@huawei.com> Yu Chengxia <yuchengxia@huawei.com>
@ -2062,6 +2114,7 @@ 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>
Ziheng Liu <lzhfromustc@gmail.com>
Zilin Du <zilin.du@gmail.com> Zilin Du <zilin.du@gmail.com>
zimbatm <zimbatm@zimbatm.com> zimbatm <zimbatm@zimbatm.com>
Ziming Dong <bnudzm@foxmail.com> Ziming Dong <bnudzm@foxmail.com>
@ -2070,7 +2123,7 @@ zmarouf <zeid.marouf@gmail.com>
Zoltan Tombol <zoltan.tombol@gmail.com> Zoltan Tombol <zoltan.tombol@gmail.com>
Zou Yu <zouyu7@huawei.com> Zou Yu <zouyu7@huawei.com>
zqh <zqhxuyuan@gmail.com> zqh <zqhxuyuan@gmail.com>
Zuhayr Elahi <elahi.zuhayr@gmail.com> Zuhayr Elahi <zuhayr.elahi@docker.com>
Zunayed Ali <zunayed@gmail.com> Zunayed Ali <zunayed@gmail.com>
Álex González <agonzalezro@gmail.com> Álex González <agonzalezro@gmail.com>
Álvaro Lázaro <alvaro.lazaro.g@gmail.com> Álvaro Lázaro <alvaro.lazaro.g@gmail.com>

@ -3,7 +3,7 @@ Copyright 2012-2017 Docker, Inc.
This product includes software developed at Docker, Inc. (https://www.docker.com). This product includes software developed at Docker, Inc. (https://www.docker.com).
This product contains software (https://github.com/kr/pty) developed This product contains software (https://github.com/creack/pty) developed
by Keith Rarick, licensed under the MIT License. by Keith Rarick, licensed under the MIT License.
The following is courtesy of our legal counsel: The following is courtesy of our legal counsel:

@ -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.40" DefaultVersion = "1.41"
// 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:
consumes: consumes:
- "application/json" - "application/json"
- "text/plain" - "text/plain"
basePath: "/v1.40" basePath: "/v1.41"
info: info:
title: "Docker Engine API" title: "Docker Engine API"
version: "1.40" version: "1.41"
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:
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.40) is used. If you omit the version-prefix, the current version of the API (v1.41) is used.
For example, calling `/info` is the same as calling `/v1.40/info`. Using the For example, calling `/info` is the same as calling `/v1.41/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,
@ -703,6 +703,19 @@ definitions:
description: "A list of kernel capabilities to drop from the container. Conflicts with option 'Capabilities'" description: "A list of kernel capabilities to drop from the container. Conflicts with option 'Capabilities'"
items: items:
type: "string" type: "string"
CgroupnsMode:
type: "string"
enum:
- "private"
- "host"
description: |
cgroup namespace mode for the container. Possible values are:
- `"private"`: the container runs in its own private cgroup namespace
- `"host"`: use the host system's cgroup namespace
If not specified, the daemon default is used, which can either be `"private"`
or `"host"`, depending on daemon version, kernel support and configuration.
Dns: Dns:
type: "array" type: "array"
description: "A list of DNS servers for the container to use." description: "A list of DNS servers for the container to use."
@ -1141,6 +1154,7 @@ definitions:
type: "object" type: "object"
additionalProperties: additionalProperties:
type: "array" type: "array"
x-nullable: true
items: items:
$ref: "#/definitions/PortBinding" $ref: "#/definitions/PortBinding"
example: example:
@ -1165,7 +1179,6 @@ definitions:
PortBinding represents a binding between a host IP address and a host PortBinding represents a binding between a host IP address and a host
port. port.
type: "object" type: "object"
x-nullable: true
properties: properties:
HostIp: HostIp:
description: "Host IP address that the container's port is mapped to." description: "Host IP address that the container's port is mapped to."
@ -2869,6 +2882,18 @@ definitions:
type: "object" type: "object"
additionalProperties: additionalProperties:
type: "string" type: "string"
# This option is not used by Windows containers
Capabilities:
type: "array"
description: |
A list of kernel capabilities to be available for container (this overrides the default set).
items:
type: "string"
example:
- "CAP_NET_RAW"
- "CAP_SYS_ADMIN"
- "CAP_SYS_CHROOT"
- "CAP_SYSLOG"
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
@ -2970,16 +2995,10 @@ definitions:
description: "Runtime is the type of runtime specified for the task executor." description: "Runtime is the type of runtime specified for the task executor."
type: "string" type: "string"
Networks: Networks:
description: "Specifies which networks the service should attach to."
type: "array" type: "array"
items: items:
type: "object" $ref: "#/definitions/NetworkAttachmentConfig"
properties:
Target:
type: "string"
Aliases:
type: "array"
items:
type: "string"
LogDriver: LogDriver:
description: "Specifies the log driver to use for tasks created from this spec. If not present, the default one for the swarm will be used, finally falling back to the engine default if not specified." description: "Specifies the log driver to use for tasks created from this spec. If not present, the default one for the swarm will be used, finally falling back to the engine default if not specified."
type: "object" type: "object"
@ -3225,17 +3244,11 @@ definitions:
- "stop-first" - "stop-first"
- "start-first" - "start-first"
Networks: Networks:
description: "Array of network names or IDs to attach the service to." description: "Specifies which networks the service should attach to."
type: "array" type: "array"
items: items:
type: "object" $ref: "#/definitions/NetworkAttachmentConfig"
properties:
Target:
type: "string"
Aliases:
type: "array"
items:
type: "string"
EndpointSpec: EndpointSpec:
$ref: "#/definitions/EndpointSpec" $ref: "#/definitions/EndpointSpec"
@ -3262,7 +3275,7 @@ definitions:
<p><br /></p> <p><br /></p>
- "ingress" makes the target port accessible on on every node, - "ingress" makes the target port accessible on every node,
regardless of whether there is a task for the service running on regardless of whether there is a task for the service running on
that node or not. that node or not.
- "host" bypasses the routing mesh and publish the port directly on - "host" bypasses the routing mesh and publish the port directly on
@ -3280,8 +3293,8 @@ definitions:
type: "object" type: "object"
properties: properties:
Mode: Mode:
description: "The mode of resolution to use for internal load balancing description: |
between tasks." The mode of resolution to use for internal load balancing between tasks.
type: "string" type: "string"
enum: enum:
- "vip" - "vip"
@ -3344,6 +3357,27 @@ definitions:
format: "dateTime" format: "dateTime"
Message: Message:
type: "string" type: "string"
ServiceStatus:
description: |
The status of the service's tasks. Provided only when requested as
part of a ServiceList operation.
type: "object"
properties:
RunningTasks:
description: "The number of tasks for the service currently in the Running state"
type: "integer"
format: "uint64"
example: 7
DesiredTasks:
description: |
The number of tasks for the service desired to be running.
For replicated services, this is the replica count from the
service spec. For global services, this is computed by taking
count of all tasks for the service with a Desired State other
than Shutdown.
type: "integer"
format: "uint64"
example: 10
example: example:
ID: "9mnpnzenvg8p8tdbtq4wvbkcz" ID: "9mnpnzenvg8p8tdbtq4wvbkcz"
Version: Version:
@ -3805,7 +3839,7 @@ definitions:
description: | description: |
The driver to use for managing cgroups. The driver to use for managing cgroups.
type: "string" type: "string"
enum: ["cgroupfs", "systemd"] enum: ["cgroupfs", "systemd", "none"]
default: "cgroupfs" default: "cgroupfs"
example: "cgroupfs" example: "cgroupfs"
NEventsListener: NEventsListener:
@ -3827,6 +3861,17 @@ definitions:
or "Windows Server 2016 Datacenter" or "Windows Server 2016 Datacenter"
type: "string" type: "string"
example: "Alpine Linux v3.5" example: "Alpine Linux v3.5"
OSVersion:
description: |
Version of the host's operating system
<p><br /></p>
> **Note**: The information returned in this field, including its
> very existence, and the formatting of values, should not be considered
> stable, and may change without notice.
type: "string"
example: "16.04"
OSType: OSType:
description: | description: |
Generic type of the operating system of the host, as returned by the Generic type of the operating system of the host, as returned by the
@ -4040,7 +4085,7 @@ definitions:
SecurityOptions: SecurityOptions:
description: | description: |
List of security features that are enabled on the daemon, such as List of security features that are enabled on the daemon, such as
apparmor, seccomp, SELinux, and user-namespaces (userns). apparmor, seccomp, SELinux, user-namespaces (userns), and rootless.
Additional configuration options for each security feature may Additional configuration options for each security feature may
be present, and are included as a comma-separated list of key/value be present, and are included as a comma-separated list of key/value
@ -4053,6 +4098,7 @@ definitions:
- "name=seccomp,profile=default" - "name=seccomp,profile=default"
- "name=selinux" - "name=selinux"
- "name=userns" - "name=userns"
- "name=rootless"
ProductLicense: ProductLicense:
description: | description: |
Reports a summary of the product license on the daemon. Reports a summary of the product license on the daemon.
@ -4406,6 +4452,24 @@ definitions:
IP address and ports at which this node can be reached. IP address and ports at which this node can be reached.
type: "string" type: "string"
NetworkAttachmentConfig:
description: "Specifies how a service should be attached to a particular network."
type: "object"
properties:
Target:
description: "The target network for attachment. Must be a network name or ID."
type: "string"
Aliases:
description: "Discoverable alternate names for the service on this network."
type: "array"
items:
type: "string"
DriverOpts:
description: "Driver attachment options for the network target"
type: "object"
additionalProperties:
type: "string"
paths: paths:
/containers/json: /containers/json:
get: get:
@ -4836,7 +4900,7 @@ paths:
Note that a running container can be _paused_. The `Running` and `Paused` Note that a running container can be _paused_. The `Running` and `Paused`
booleans are not mutually exclusive: booleans are not mutually exclusive:
When pausing a container (on Linux), the cgroups freezer is used to suspend When pausing a container (on Linux), the freezer cgroup is used to suspend
all processes in the container. Freezing the process requires the process to all processes in the container. Freezing the process requires the process to
be running. As a result, paused containers are both `Running` _and_ `Paused`. be running. As a result, paused containers are both `Running` _and_ `Paused`.
@ -4887,6 +4951,8 @@ paths:
type: "integer" type: "integer"
Driver: Driver:
type: "string" type: "string"
Platform:
type: "string"
MountLabel: MountLabel:
type: "string" type: "string"
ProcessLabel: ProcessLabel:
@ -5462,7 +5528,7 @@ paths:
/containers/{id}/resize: /containers/{id}/resize:
post: post:
summary: "Resize a container TTY" summary: "Resize a container TTY"
description: "Resize the TTY for a container. You must restart the container for the resize to take effect." description: "Resize the TTY for a container."
operationId: "ContainerResize" operationId: "ContainerResize"
consumes: consumes:
- "application/octet-stream" - "application/octet-stream"
@ -5506,8 +5572,6 @@ paths:
description: "no error" description: "no error"
304: 304:
description: "container already started" description: "container already started"
schema:
$ref: "#/definitions/ErrorResponse"
404: 404:
description: "no such container" description: "no such container"
schema: schema:
@ -5539,8 +5603,6 @@ paths:
description: "no error" description: "no error"
304: 304:
description: "container already stopped" description: "container already stopped"
schema:
$ref: "#/definitions/ErrorResponse"
404: 404:
description: "no such container" description: "no such container"
schema: schema:
@ -5731,9 +5793,9 @@ paths:
post: post:
summary: "Pause a container" summary: "Pause a container"
description: | description: |
Use the cgroups freezer to suspend all processes in a container. Use the freezer cgroup to suspend all processes in a container.
Traditionally, when suspending a process the `SIGSTOP` signal is used, which is observable by the process being suspended. With the cgroups freezer the process is unaware, and unable to capture, that it is being suspended, and subsequently resumed. Traditionally, when suspending a process the `SIGSTOP` signal is used, which is observable by the process being suspended. With the freezer cgroup the process is unaware, and unable to capture, that it is being suspended, and subsequently resumed.
operationId: "ContainerPause" operationId: "ContainerPause"
responses: responses:
204: 204:
@ -6216,12 +6278,17 @@ paths:
in: "query" in: "query"
description: "If “1”, “true”, or “True” then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa." description: "If “1”, “true”, or “True” then it will be an error if unpacking the given content would cause an existing directory to be replaced with a non-directory and vice versa."
type: "string" type: "string"
- name: "copyUIDGID"
in: "query"
description: "If “1”, “true”, then it will copy UID/GID maps to the dest file or dir"
type: "string"
- name: "inputStream" - name: "inputStream"
in: "body" in: "body"
required: true required: true
description: "The input stream must be a tar archive compressed with one of the following algorithms: identity (no compression), gzip, bzip2, xz." description: "The input stream must be a tar archive compressed with one of the following algorithms: identity (no compression), gzip, bzip2, xz."
schema: schema:
type: "string" type: "string"
format: "binary"
tags: ["Container"] tags: ["Container"]
/containers/prune: /containers/prune:
post: post:
@ -6451,10 +6518,11 @@ paths:
type: "string" type: "string"
- name: "networkmode" - name: "networkmode"
in: "query" in: "query"
description: "Sets the networking mode for the run commands during description: |
build. Supported standard values are: `bridge`, `host`, `none`, and Sets the networking mode for the run commands during build. Supported
`container:<name|id>`. Any other value is taken as a custom network's standard values are: `bridge`, `host`, `none`, and `container:<name|id>`.
name to which this container should connect to." Any other value is taken as a custom network's name or ID to which this
container should connect to.
type: "string" type: "string"
- name: "Content-type" - name: "Content-type"
in: "header" in: "header"
@ -9106,7 +9174,9 @@ paths:
type: "string" type: "string"
RemoteAddrs: RemoteAddrs:
description: "Addresses of manager nodes already participating in the swarm." description: "Addresses of manager nodes already participating in the swarm."
type: "string" type: "array"
items:
type: "string"
JoinToken: JoinToken:
description: "Secret token for joining this swarm." description: "Secret token for joining this swarm."
type: "string" type: "string"
@ -9275,6 +9345,10 @@ paths:
- `label=<service label>` - `label=<service label>`
- `mode=["replicated"|"global"]` - `mode=["replicated"|"global"]`
- `name=<service name>` - `name=<service name>`
- name: "status"
in: "query"
type: "boolean"
description: "Include service status, with count of running and desired tasks"
tags: ["Service"] tags: ["Service"]
/services/create: /services/create:
post: post:
@ -9541,17 +9615,19 @@ paths:
type: "integer" type: "integer"
- name: "registryAuthFrom" - name: "registryAuthFrom"
in: "query" in: "query"
description: |
If the `X-Registry-Auth` header is not specified, this parameter
indicates where to find registry authorization credentials.
type: "string" type: "string"
description: "If the X-Registry-Auth header is not specified, this enum: ["spec", "previous-spec"]
parameter indicates where to find registry authorization credentials. The
valid values are `spec` and `previous-spec`."
default: "spec" default: "spec"
- name: "rollback" - name: "rollback"
in: "query" in: "query"
description: |
Set to this parameter to `previous` to cause a server-side rollback
to the previous service spec. The supplied spec will be ignored in
this case.
type: "string" type: "string"
description: "Set to this parameter to `previous` to cause a
server-side rollback to the previous service spec. The supplied spec will be
ignored in this case."
- name: "X-Registry-Auth" - name: "X-Registry-Auth"
in: "header" in: "header"
description: "A base64-encoded auth configuration for pulling from private registries. [See the authentication section for details.](#section/Authentication)" description: "A base64-encoded auth configuration for pulling from private registries. [See the authentication section for details.](#section/Authentication)"
@ -10371,9 +10447,6 @@ paths:
description: | description: |
Start a new interactive session with a server. Session allows server to call back to the client for advanced capabilities. Start a new interactive session with a server. Session allows server to call back to the client for advanced capabilities.
> **Note**: This endpoint is *experimental* and only available if the daemon is started with experimental
> features enabled. The specifications for this endpoint may still change in a future version of the API.
### Hijacking ### Hijacking
This endpoint hijacks the HTTP connection to HTTP2 transport that allows the client to expose gPRC services on that connection. This endpoint hijacks the HTTP connection to HTTP2 transport that allows the client to expose gPRC services on that connection.
@ -10407,4 +10480,4 @@ paths:
description: "server error" description: "server error"
schema: schema:
$ref: "#/definitions/ErrorResponse" $ref: "#/definitions/ErrorResponse"
tags: ["Session (experimental)"] tags: ["Session"]

@ -363,6 +363,10 @@ type ServiceUpdateOptions struct {
// ServiceListOptions holds parameters to list services with. // ServiceListOptions holds parameters to list services with.
type ServiceListOptions struct { type ServiceListOptions struct {
Filters filters.Args Filters filters.Args
// Status indicates whether the server should include the service task
// count of running and desired tasks.
Status bool
} }
// ServiceInspectOptions holds parameters related to the "service inspect" // ServiceInspectOptions holds parameters related to the "service inspect"

@ -1,8 +1,7 @@
package container // import "github.com/docker/docker/api/types/container" package container // import "github.com/docker/docker/api/types/container"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -1,8 +1,7 @@
package container // import "github.com/docker/docker/api/types/container" package container // import "github.com/docker/docker/api/types/container"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -1,8 +1,7 @@
package container // import "github.com/docker/docker/api/types/container" package container // import "github.com/docker/docker/api/types/container"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -1,8 +1,7 @@
package container // import "github.com/docker/docker/api/types/container" package container // import "github.com/docker/docker/api/types/container"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -1,8 +1,7 @@
package container // import "github.com/docker/docker/api/types/container" package container // import "github.com/docker/docker/api/types/container"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -7,9 +7,32 @@ import (
"github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/strslice" "github.com/docker/docker/api/types/strslice"
"github.com/docker/go-connections/nat" "github.com/docker/go-connections/nat"
"github.com/docker/go-units" units "github.com/docker/go-units"
) )
// CgroupnsMode represents the cgroup namespace mode of the container
type CgroupnsMode string
// IsPrivate indicates whether the container uses its own private cgroup namespace
func (c CgroupnsMode) IsPrivate() bool {
return c == "private"
}
// IsHost indicates whether the container shares the host's cgroup namespace
func (c CgroupnsMode) IsHost() bool {
return c == "host"
}
// IsEmpty indicates whether the container cgroup namespace mode is unset
func (c CgroupnsMode) IsEmpty() bool {
return c == ""
}
// Valid indicates whether the cgroup namespace mode is valid
func (c CgroupnsMode) Valid() bool {
return c.IsEmpty() || c.IsPrivate() || c.IsHost()
}
// Isolation represents the isolation technology of a container. The supported // Isolation represents the isolation technology of a container. The supported
// values are platform specific // values are platform specific
type Isolation string type Isolation string
@ -381,9 +404,10 @@ type HostConfig struct {
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
Capabilities []string `json:"Capabilities"` // List of kernel capabilities to be available for container (this overrides the default set) Capabilities []string `json:"Capabilities"` // List of kernel capabilities to be available for container (this overrides the default set)
DNS []string `json:"Dns"` // List of DNS server to lookup CgroupnsMode CgroupnsMode // Cgroup namespace mode to use for the container
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

@ -0,0 +1,6 @@
package types
// Error returns the error message
func (e ErrorResponse) Error() string {
return e.Message
}

@ -36,6 +36,15 @@ func NewArgs(initialArgs ...KeyValuePair) Args {
return args return args
} }
// Keys returns all the keys in list of Args
func (args Args) Keys() []string {
keys := make([]string, 0, len(args.fields))
for k := range args.fields {
keys = append(keys, k)
}
return keys
}
// MarshalJSON returns a JSON byte representation of the Args // MarshalJSON returns a JSON byte representation of the Args
func (args Args) MarshalJSON() ([]byte, error) { func (args Args) MarshalJSON() ([]byte, error) {
if len(args.fields) == 0 { if len(args.fields) == 0 {
@ -57,7 +66,7 @@ func ToJSON(a Args) (string, error) {
// then the encoded format will use an older legacy format where the values are a // then the encoded format will use an older legacy format where the values are a
// list of strings, instead of a set. // list of strings, instead of a set.
// //
// Deprecated: Use ToJSON // Deprecated: do not use in any new code; use ToJSON instead
func ToParamWithVersion(version string, a Args) (string, error) { func ToParamWithVersion(version string, a Args) (string, error) {
if a.Len() == 0 { if a.Len() == 0 {
return "", nil return "", nil

@ -1,8 +1,7 @@
package image // import "github.com/docker/docker/api/types/image" package image // import "github.com/docker/docker/api/types/image"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"net" "net"
"github.com/opencontainers/image-spec/specs-go/v1" v1 "github.com/opencontainers/image-spec/specs-go/v1"
) )
// ServiceConfig stores daemon registry services configuration. // ServiceConfig stores daemon registry services configuration.

@ -67,10 +67,11 @@ type ContainerSpec struct {
// The format of extra hosts on swarmkit is specified in: // The format of extra hosts on swarmkit is specified in:
// http://man7.org/linux/man-pages/man5/hosts.5.html // http://man7.org/linux/man-pages/man5/hosts.5.html
// IP_address canonical_hostname [aliases...] // IP_address canonical_hostname [aliases...]
Hosts []string `json:",omitempty"` Hosts []string `json:",omitempty"`
DNSConfig *DNSConfig `json:",omitempty"` DNSConfig *DNSConfig `json:",omitempty"`
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"` Sysctls map[string]string `json:",omitempty"`
Capabilities []string `json:",omitempty"`
} }

@ -1,6 +1,5 @@
// Code generated by protoc-gen-gogo. // Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: plugin.proto // source: plugin.proto
// DO NOT EDIT!
/* /*
Package runtime is a generated protocol buffer package. Package runtime is a generated protocol buffer package.
@ -38,6 +37,7 @@ type PluginSpec struct {
Remote string `protobuf:"bytes,2,opt,name=remote,proto3" json:"remote,omitempty"` Remote string `protobuf:"bytes,2,opt,name=remote,proto3" json:"remote,omitempty"`
Privileges []*PluginPrivilege `protobuf:"bytes,3,rep,name=privileges" json:"privileges,omitempty"` Privileges []*PluginPrivilege `protobuf:"bytes,3,rep,name=privileges" json:"privileges,omitempty"`
Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"` Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"`
Env []string `protobuf:"bytes,5,rep,name=env" json:"env,omitempty"`
} }
func (m *PluginSpec) Reset() { *m = PluginSpec{} } func (m *PluginSpec) Reset() { *m = PluginSpec{} }
@ -73,6 +73,13 @@ func (m *PluginSpec) GetDisabled() bool {
return false return false
} }
func (m *PluginSpec) GetEnv() []string {
if m != nil {
return m.Env
}
return nil
}
// PluginPrivilege describes a permission the user has to accept // PluginPrivilege describes a permission the user has to accept
// upon installing a plugin. // upon installing a plugin.
type PluginPrivilege struct { type PluginPrivilege struct {
@ -160,6 +167,21 @@ func (m *PluginSpec) MarshalTo(dAtA []byte) (int, error) {
} }
i++ i++
} }
if len(m.Env) > 0 {
for _, s := range m.Env {
dAtA[i] = 0x2a
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
}
}
return i, nil return i, nil
} }
@ -208,24 +230,6 @@ func (m *PluginPrivilege) MarshalTo(dAtA []byte) (int, error) {
return i, nil return i, nil
} }
func encodeFixed64Plugin(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Plugin(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintPlugin(dAtA []byte, offset int, v uint64) int { func encodeVarintPlugin(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 { for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80) dAtA[offset] = uint8(v&0x7f | 0x80)
@ -255,6 +259,12 @@ func (m *PluginSpec) Size() (n int) {
if m.Disabled { if m.Disabled {
n += 2 n += 2
} }
if len(m.Env) > 0 {
for _, s := range m.Env {
l = len(s)
n += 1 + l + sovPlugin(uint64(l))
}
}
return n return n
} }
@ -429,6 +439,35 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error {
} }
} }
m.Disabled = bool(v != 0) m.Disabled = bool(v != 0)
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Env", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPlugin
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthPlugin
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Env = append(m.Env, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipPlugin(dAtA[iNdEx:]) skippy, err := skipPlugin(dAtA[iNdEx:])
@ -695,18 +734,21 @@ var (
func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) } func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) }
var fileDescriptorPlugin = []byte{ var fileDescriptorPlugin = []byte{
// 196 bytes of a gzipped FileDescriptorProto // 256 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0xc8, 0x29, 0x4d, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x4d, 0x4b, 0xc3, 0x30,
0xcf, 0xcc, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x6a, 0x63, 0xe4, 0xe2, 0x0a, 0x00, 0x0b, 0x18, 0xc7, 0x89, 0xdd, 0xc6, 0xfa, 0x4c, 0x70, 0x04, 0x91, 0xe2, 0xa1, 0x94, 0x9d, 0x7a, 0x6a,
0x04, 0x17, 0xa4, 0x26, 0x0b, 0x09, 0x71, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x45, 0x2f, 0x82, 0x37, 0x0f, 0x9e, 0x47, 0xbc, 0x09, 0x1e, 0xd2, 0xf6, 0xa1, 0x06, 0x9b, 0x17,
0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x62, 0x5c, 0x6c, 0x45, 0xa9, 0xb9, 0xf9, 0x25, 0xa9, 0x12, 0x92, 0xb4, 0xe2, 0x37, 0xf1, 0x23, 0x79, 0xf4, 0x23, 0x48, 0x3f, 0x89, 0x98, 0x75, 0x32, 0x64,
0x4c, 0x60, 0x51, 0x28, 0x4f, 0xc8, 0x80, 0x8b, 0xab, 0xa0, 0x28, 0xb3, 0x2c, 0x33, 0x27, 0x35, 0xa7, 0xff, 0x4b, 0xc2, 0x9f, 0x1f, 0x0f, 0x9c, 0x9a, 0xae, 0x6f, 0x85, 0x2a, 0x8c, 0xd5, 0x5e,
0x3d, 0xb5, 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x40, 0x0f, 0x62, 0x58, 0x00, 0x4c, 0x6f, 0x3e, 0x08, 0xc0, 0x36, 0x14, 0x8f, 0x06, 0x6b, 0x4a, 0x61, 0xa6, 0xb8, 0xc4, 0x84, 0x64,
0x22, 0x08, 0x49, 0x8d, 0x90, 0x14, 0x17, 0x47, 0x4a, 0x66, 0x71, 0x62, 0x52, 0x4e, 0x6a, 0x8a, 0x24, 0x8f, 0x59, 0xf0, 0xf4, 0x02, 0x16, 0x16, 0xa5, 0xf6, 0x98, 0x9c, 0x84, 0x76, 0x4a, 0xf4,
0x04, 0x8b, 0x02, 0xa3, 0x06, 0x47, 0x10, 0x9c, 0xaf, 0x14, 0xcb, 0xc5, 0x8f, 0xa6, 0x15, 0xab, 0x0a, 0xc0, 0x58, 0x31, 0x88, 0x0e, 0x5b, 0x74, 0x49, 0x94, 0x45, 0xf9, 0xea, 0x7a, 0x5d, 0xec,
0x63, 0x14, 0xb8, 0xb8, 0x53, 0x52, 0x8b, 0x93, 0x8b, 0x32, 0x0b, 0x4a, 0x32, 0xf3, 0xf3, 0xa0, 0xc6, 0xb6, 0xfb, 0x07, 0x76, 0xf0, 0x87, 0x5e, 0xc2, 0xb2, 0x11, 0x8e, 0x57, 0x1d, 0x36, 0xc9,
0x2e, 0x42, 0x16, 0x12, 0x12, 0xe1, 0x62, 0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x05, 0xbb, 0x88, 0x33, 0x2c, 0x23, 0xf9, 0x92, 0xfd, 0x65, 0xba, 0x86, 0x08, 0xd5, 0x90, 0xcc, 0xb3, 0x28, 0x8f, 0xd9,
0x08, 0xc2, 0x71, 0xe2, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0xaf, 0xdd, 0x3c, 0xc3, 0xd9, 0xbf, 0xb1, 0xa3, 0x78, 0x19, 0xac, 0x1a, 0x74, 0xb5, 0x15, 0xc6,
0x18, 0x93, 0xd8, 0xc0, 0x9e, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x84, 0xad, 0x79, 0x0b, 0xad, 0x26, 0xc6, 0xc3, 0x8a, 0x9e, 0xc3, 0x7c, 0xe0, 0x5d, 0x8f, 0x81, 0x31, 0x66, 0xbb,
0x0c, 0x01, 0x00, 0x00, 0x70, 0xff, 0xf0, 0x39, 0xa6, 0xe4, 0x6b, 0x4c, 0xc9, 0xf7, 0x98, 0x92, 0xa7, 0xdb, 0x56, 0xf8,
0x97, 0xbe, 0x2a, 0x6a, 0x2d, 0xcb, 0x46, 0xd7, 0xaf, 0x68, 0xf7, 0xc2, 0x8d, 0x28, 0xfd, 0xbb,
0x41, 0x57, 0xba, 0x37, 0x6e, 0x65, 0x69, 0x7b, 0xe5, 0x85, 0xc4, 0xbb, 0x49, 0xab, 0x45, 0x38,
0xe4, 0xcd, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x99, 0xa8, 0xd9, 0x9b, 0x58, 0x01, 0x00, 0x00,
} }

@ -9,6 +9,7 @@ message PluginSpec {
string remote = 2; string remote = 2;
repeated PluginPrivilege privileges = 3; repeated PluginPrivilege privileges = 3;
bool disabled = 4; bool disabled = 4;
repeated string env = 5;
} }
// PluginPrivilege describes a permission the user has to accept // PluginPrivilege describes a permission the user has to accept

@ -10,6 +10,13 @@ type Service struct {
PreviousSpec *ServiceSpec `json:",omitempty"` PreviousSpec *ServiceSpec `json:",omitempty"`
Endpoint Endpoint `json:",omitempty"` Endpoint Endpoint `json:",omitempty"`
UpdateStatus *UpdateStatus `json:",omitempty"` UpdateStatus *UpdateStatus `json:",omitempty"`
// ServiceStatus is an optional, extra field indicating the number of
// desired and running tasks. It is provided primarily as a shortcut to
// calculating these values client-side, which otherwise would require
// listing all tasks for a service, an operation that could be
// computation and network expensive.
ServiceStatus *ServiceStatus `json:",omitempty"`
} }
// ServiceSpec represents the spec of a service. // ServiceSpec represents the spec of a service.
@ -122,3 +129,17 @@ type UpdateConfig struct {
// started, or the new task is started before the old task is shut down. // started, or the new task is started before the old task is shut down.
Order string Order string
} }
// ServiceStatus represents the number of running tasks in a service and the
// number of tasks desired to be running.
type ServiceStatus struct {
// RunningTasks is the number of tasks for the service actually in the
// Running state
RunningTasks uint64
// DesiredTasks is the number of tasks desired to be running by the
// service. For replicated services, this is the replica count. For global
// services, this is computed by taking the number of tasks with desired
// state of not-Shutdown.
DesiredTasks uint64
}

@ -39,6 +39,7 @@ type ImageInspect struct {
Author string Author string
Config *container.Config Config *container.Config
Architecture string Architecture string
Variant string `json:",omitempty"`
Os string Os string
OsVersion string `json:",omitempty"` OsVersion string `json:",omitempty"`
Size int64 Size int64
@ -177,6 +178,7 @@ type Info struct {
NEventsListener int NEventsListener int
KernelVersion string KernelVersion string
OperatingSystem string OperatingSystem string
OSVersion string
OSType string OSType string
Architecture string Architecture string
IndexServerAddress string IndexServerAddress string

@ -1,8 +1,7 @@
package volume // import "github.com/docker/docker/api/types/volume" package volume // import "github.com/docker/docker/api/types/volume"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -1,8 +1,7 @@
package volume // import "github.com/docker/docker/api/types/volume" package volume // import "github.com/docker/docker/api/types/volume"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// DO NOT EDIT THIS FILE // Code generated by `swagger generate operation`. DO NOT EDIT.
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

@ -252,7 +252,8 @@ func (cli *Client) DaemonHost() string {
// HTTPClient returns a copy of the HTTP client bound to the server // HTTPClient returns a copy of the HTTP client bound to the server
func (cli *Client) HTTPClient() *http.Client { func (cli *Client) HTTPClient() *http.Client {
return &*cli.client c := *cli.client
return &c
} }
// ParseHostURL parses a url string, validates the string is a host url, and // ParseHostURL parses a url string, validates the string is a host url, and

@ -35,6 +35,7 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis
} }
if options.Filters.Len() > 0 { if options.Filters.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters) filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
if err != nil { if err != nil {

@ -90,6 +90,7 @@ func buildEventsQueryParams(cliVersion string, options types.EventsOptions) (url
} }
if options.Filters.Len() > 0 { if options.Filters.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cliVersion, options.Filters) filterJSON, err := filters.ToParamWithVersion(cliVersion, options.Filters)
if err != nil { if err != nil {
return nil, err return nil, err

@ -24,7 +24,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
} }
apiPath := cli.getAPIPath(ctx, path, query) apiPath := cli.getAPIPath(ctx, path, query)
req, err := http.NewRequest("POST", apiPath, bodyEncoded) req, err := http.NewRequest(http.MethodPost, apiPath, bodyEncoded)
if err != nil { if err != nil {
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
} }
@ -40,7 +40,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
// DialHijack returns a hijacked connection with negotiated protocol proto. // DialHijack returns a hijacked connection with negotiated protocol proto.
func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) { func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) {
req, err := http.NewRequest("POST", url, nil) req, err := http.NewRequest(http.MethodPost, url, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -87,6 +87,8 @@ func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto
// Server hijacks the connection, error 'connection closed' expected // Server hijacks the connection, error 'connection closed' expected
resp, err := clientconn.Do(req) resp, err := clientconn.Do(req)
//nolint:staticcheck // ignore SA1019 for connecting to old (pre go1.8) daemons
if err != httputil.ErrPersistEOF { if err != httputil.ErrPersistEOF {
if err != nil { if err != nil {
return nil, err return nil, err

@ -24,6 +24,7 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
} }
} }
if optionFilters.Len() > 0 { if optionFilters.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cli.version, optionFilters) filterJSON, err := filters.ToParamWithVersion(cli.version, optionFilters)
if err != nil { if err != nil {
return images, err return images, err

@ -13,6 +13,7 @@ import (
func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) { func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error) {
query := url.Values{} query := url.Values{}
if options.Filters.Len() > 0 { if options.Filters.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters) filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
if err != nil { if err != nil {
return nil, err return nil, err

@ -19,7 +19,7 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
// Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest() // Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest()
// because ping requests are used during API version negotiation, so we want // because ping requests are used during API version negotiation, so we want
// to hit the non-versioned /_ping endpoint, not /v1.xx/_ping // to hit the non-versioned /_ping endpoint, not /v1.xx/_ping
req, err := cli.buildRequest("HEAD", path.Join(cli.basePath, "/_ping"), nil, nil) req, err := cli.buildRequest(http.MethodHead, path.Join(cli.basePath, "/_ping"), nil, nil)
if err != nil { if err != nil {
return ping, err return ping, err
} }
@ -31,9 +31,11 @@ func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
// Server handled the request, so parse the response // Server handled the request, so parse the response
return parsePingResponse(cli, serverResp) return parsePingResponse(cli, serverResp)
} }
} else if IsErrConnectionFailed(err) {
return ping, err
} }
req, err = cli.buildRequest("GET", path.Join(cli.basePath, "/_ping"), nil, nil) req, err = cli.buildRequest(http.MethodGet, path.Join(cli.basePath, "/_ping"), nil, nil)
if err != nil { if err != nil {
return ping, err return ping, err
} }

@ -15,6 +15,7 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P
query := url.Values{} query := url.Values{}
if filter.Len() > 0 { if filter.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cli.version, filter) filterJSON, err := filters.ToParamWithVersion(cli.version, filter)
if err != nil { if err != nil {
return plugins, err return plugins, err

@ -29,12 +29,12 @@ type serverResponse struct {
// head sends an http request to the docker API using the method HEAD. // head sends an http request to the docker API using the method HEAD.
func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) { func (cli *Client) head(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "HEAD", path, query, nil, headers) return cli.sendRequest(ctx, http.MethodHead, path, query, nil, headers)
} }
// get sends an http request to the docker API using the method GET with a specific Go context. // get sends an http request to the docker API using the method GET with a specific Go context.
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) { func (cli *Client) get(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "GET", path, query, nil, headers) return cli.sendRequest(ctx, http.MethodGet, path, query, nil, headers)
} }
// post sends an http request to the docker API using the method POST with a specific Go context. // post sends an http request to the docker API using the method POST with a specific Go context.
@ -43,30 +43,21 @@ func (cli *Client) post(ctx context.Context, path string, query url.Values, obj
if err != nil { if err != nil {
return serverResponse{}, err return serverResponse{}, err
} }
return cli.sendRequest(ctx, "POST", path, query, body, headers) return cli.sendRequest(ctx, http.MethodPost, path, query, body, headers)
} }
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) { func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "POST", path, query, body, headers) return cli.sendRequest(ctx, http.MethodPost, path, query, body, headers)
}
// put sends an http request to the docker API using the method PUT.
func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
body, headers, err := encodeBody(obj, headers)
if err != nil {
return serverResponse{}, err
}
return cli.sendRequest(ctx, "PUT", path, query, body, headers)
} }
// putRaw sends an http request to the docker API using the method PUT. // putRaw sends an http request to the docker API using the method PUT.
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) { func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "PUT", path, query, body, headers) return cli.sendRequest(ctx, http.MethodPut, path, query, body, headers)
} }
// delete sends an http request to the docker API using the method DELETE. // delete sends an http request to the docker API using the method DELETE.
func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) { func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers map[string][]string) (serverResponse, error) {
return cli.sendRequest(ctx, "DELETE", path, query, nil, headers) return cli.sendRequest(ctx, http.MethodDelete, path, query, nil, headers)
} }
type headers map[string][]string type headers map[string][]string
@ -88,7 +79,7 @@ func encodeBody(obj interface{}, headers headers) (io.Reader, headers, error) {
} }
func (cli *Client) buildRequest(method, path string, body io.Reader, headers headers) (*http.Request, error) { func (cli *Client) buildRequest(method, path string, body io.Reader, headers headers) (*http.Request, error) {
expectedPayload := (method == "POST" || method == "PUT") expectedPayload := (method == http.MethodPost || method == http.MethodPut)
if expectedPayload && body == nil { if expectedPayload && body == nil {
body = bytes.NewReader([]byte{}) body = bytes.NewReader([]byte{})
} }
@ -178,7 +169,13 @@ func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResp
// this is localised - for example in French the error would be // this is localised - for example in French the error would be
// `open //./pipe/docker_engine: Le fichier spécifié est introuvable.` // `open //./pipe/docker_engine: Le fichier spécifié est introuvable.`
if strings.Contains(err.Error(), `open //./pipe/docker_engine`) { if strings.Contains(err.Error(), `open //./pipe/docker_engine`) {
err = errors.New(err.Error() + " In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.") // Checks if client is running with elevated privileges
if f, elevatedErr := os.Open("\\\\.\\PHYSICALDRIVE0"); elevatedErr == nil {
err = errors.Wrap(err, "In the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect.")
} else {
f.Close()
err = errors.Wrap(err, "This error may indicate that the docker daemon is not running.")
}
} }
return serverResp, errors.Wrap(err, "error during connect") return serverResp, errors.Wrap(err, "error during connect")

@ -9,7 +9,7 @@ import (
"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/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors" "github.com/pkg/errors"
) )

@ -23,6 +23,10 @@ func (cli *Client) ServiceList(ctx context.Context, options types.ServiceListOpt
query.Set("filters", filterJSON) query.Set("filters", filterJSON)
} }
if options.Status {
query.Set("status", "true")
}
resp, err := cli.get(ctx, "/services", query, nil) resp, err := cli.get(ctx, "/services", query, nil)
defer ensureReaderClosed(resp) defer ensureReaderClosed(resp)
if err != nil { if err != nil {

@ -15,6 +15,7 @@ func (cli *Client) VolumeList(ctx context.Context, filter filters.Args) (volumet
query := url.Values{} query := url.Values{}
if filter.Len() > 0 { if filter.Len() > 0 {
//nolint:staticcheck // ignore SA1019 for old code
filterJSON, err := filters.ToParamWithVersion(cli.version, filter) filterJSON, err := filters.ToParamWithVersion(cli.version, filter)
if err != nil { if err != nil {
return volumes, err return volumes, err

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
containerderrors "github.com/containerd/containerd/errdefs"
"github.com/docker/distribution/registry/api/errcode" "github.com/docker/distribution/registry/api/errcode"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
@ -47,6 +48,10 @@ func GetHTTPErrorStatusCode(err error) int {
if statusCode != http.StatusInternalServerError { if statusCode != http.StatusInternalServerError {
return statusCode return statusCode
} }
statusCode = statusCodeFromContainerdError(err)
if statusCode != http.StatusInternalServerError {
return statusCode
}
statusCode = statusCodeFromDistributionError(err) statusCode = statusCodeFromDistributionError(err)
if statusCode != http.StatusInternalServerError { if statusCode != http.StatusInternalServerError {
return statusCode return statusCode
@ -136,9 +141,6 @@ func statusCodeFromGRPCError(err error) int {
case codes.Unavailable: // code 14 case codes.Unavailable: // code 14
return http.StatusServiceUnavailable return http.StatusServiceUnavailable
default: default:
if e, ok := err.(causer); ok {
return statusCodeFromGRPCError(e.Cause())
}
// codes.Canceled(1) // codes.Canceled(1)
// codes.Unknown(2) // codes.Unknown(2)
// codes.DeadlineExceeded(4) // codes.DeadlineExceeded(4)
@ -163,10 +165,27 @@ func statusCodeFromDistributionError(err error) int {
} }
case errcode.ErrorCoder: case errcode.ErrorCoder:
return errs.ErrorCode().Descriptor().HTTPStatusCode return errs.ErrorCode().Descriptor().HTTPStatusCode
default:
if e, ok := err.(causer); ok {
return statusCodeFromDistributionError(e.Cause())
}
} }
return http.StatusInternalServerError return http.StatusInternalServerError
} }
// statusCodeFromContainerdError returns status code for containerd errors when
// consumed directly (not through gRPC)
func statusCodeFromContainerdError(err error) int {
switch {
case containerderrors.IsInvalidArgument(err):
return http.StatusBadRequest
case containerderrors.IsNotFound(err):
return http.StatusNotFound
case containerderrors.IsAlreadyExists(err):
return http.StatusConflict
case containerderrors.IsFailedPrecondition(err):
return http.StatusPreconditionFailed
case containerderrors.IsUnavailable(err):
return http.StatusServiceUnavailable
case containerderrors.IsNotImplemented(err):
return http.StatusNotImplemented
default:
return http.StatusInternalServerError
}
}

@ -5,24 +5,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/docker/docker/pkg/idtools"
) )
// GetStatic returns the home directory for the current user without calling
// os/user.Current(). This is useful for static-linked binary on glibc-based
// system, because a call to os/user.Current() in a static binary leads to
// segfault due to a glibc issue that won't be fixed in a short term.
// (#29344, golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341)
func GetStatic() (string, error) {
uid := os.Getuid()
usr, err := idtools.LookupUID(uid)
if err != nil {
return "", err
}
return usr.Home, nil
}
// GetRuntimeDir returns XDG_RUNTIME_DIR. // GetRuntimeDir returns XDG_RUNTIME_DIR.
// XDG_RUNTIME_DIR is typically configured via pam_systemd. // XDG_RUNTIME_DIR is typically configured via pam_systemd.
// GetRuntimeDir returns non-nil error if XDG_RUNTIME_DIR is not set. // GetRuntimeDir returns non-nil error if XDG_RUNTIME_DIR is not set.

@ -6,12 +6,6 @@ import (
"errors" "errors"
) )
// GetStatic is not needed for non-linux systems.
// (Precisely, it is needed only for glibc-based linux systems.)
func GetStatic() (string, error) {
return "", errors.New("homedir.GetStatic() is not supported on this system")
}
// GetRuntimeDir is unsupported on non-linux system. // GetRuntimeDir is unsupported on non-linux system.
func GetRuntimeDir() (string, error) { func GetRuntimeDir() (string, error) {
return "", errors.New("homedir.GetRuntimeDir() is not supported on this system") return "", errors.New("homedir.GetRuntimeDir() is not supported on this system")

@ -4,8 +4,7 @@ package homedir // import "github.com/docker/docker/pkg/homedir"
import ( import (
"os" "os"
"os/user"
"github.com/opencontainers/runc/libcontainer/user"
) )
// Key returns the env var name for the user's home dir based on // Key returns the env var name for the user's home dir based on
@ -17,11 +16,16 @@ func Key() string {
// Get returns the home directory of the current user with the help of // Get returns the home directory of the current user with the help of
// environment variables depending on the target operating system. // environment variables depending on the target operating system.
// Returned path should be used with "path/filepath" to form new paths. // Returned path should be used with "path/filepath" to form new paths.
//
// If linking statically with cgo enabled against glibc, ensure the
// osusergo build tag is used.
//
// If needing to do nss lookups, do not disable cgo or set osusergo.
func Get() string { func Get() string {
home := os.Getenv(Key()) home := os.Getenv(Key())
if home == "" { if home == "" {
if u, err := user.CurrentUser(); err == nil { if u, err := user.Current(); err == nil {
return u.Home return u.HomeDir
} }
} }
return home return home

@ -1,267 +0,0 @@
package idtools // import "github.com/docker/docker/pkg/idtools"
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
// IDMap contains a single entry for user namespace range remapping. An array
// of IDMap entries represents the structure that will be provided to the Linux
// kernel for creating a user namespace.
type IDMap struct {
ContainerID int `json:"container_id"`
HostID int `json:"host_id"`
Size int `json:"size"`
}
type subIDRange struct {
Start int
Length int
}
type ranges []subIDRange
func (e ranges) Len() int { return len(e) }
func (e ranges) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
func (e ranges) Less(i, j int) bool { return e[i].Start < e[j].Start }
const (
subuidFileName = "/etc/subuid"
subgidFileName = "/etc/subgid"
)
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
// ownership to the requested uid/gid. If the directory already exists, this
// function will still change ownership to the requested uid/gid pair.
func MkdirAllAndChown(path string, mode os.FileMode, owner Identity) error {
return mkdirAs(path, mode, owner, true, true)
}
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
// If the directory already exists, this function still changes ownership.
// Note that unlike os.Mkdir(), this function does not return IsExist error
// in case path already exists.
func MkdirAndChown(path string, mode os.FileMode, owner Identity) error {
return mkdirAs(path, mode, owner, false, true)
}
// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
// ownership ONLY of newly created directories to the requested uid/gid. If the
// directories along the path exist, no change of ownership will be performed
func MkdirAllAndChownNew(path string, mode os.FileMode, owner Identity) error {
return mkdirAs(path, mode, owner, true, false)
}
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
// If the maps are empty, then the root uid/gid will default to "real" 0/0
func GetRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
uid, err := toHost(0, uidMap)
if err != nil {
return -1, -1, err
}
gid, err := toHost(0, gidMap)
if err != nil {
return -1, -1, err
}
return uid, gid, nil
}
// toContainer takes an id mapping, and uses it to translate a
// host ID to the remapped ID. If no map is provided, then the translation
// assumes a 1-to-1 mapping and returns the passed in id
func toContainer(hostID int, idMap []IDMap) (int, error) {
if idMap == nil {
return hostID, nil
}
for _, m := range idMap {
if (hostID >= m.HostID) && (hostID <= (m.HostID + m.Size - 1)) {
contID := m.ContainerID + (hostID - m.HostID)
return contID, nil
}
}
return -1, fmt.Errorf("Host ID %d cannot be mapped to a container ID", hostID)
}
// toHost takes an id mapping and a remapped ID, and translates the
// ID to the mapped host ID. If no map is provided, then the translation
// assumes a 1-to-1 mapping and returns the passed in id #
func toHost(contID int, idMap []IDMap) (int, error) {
if idMap == nil {
return contID, nil
}
for _, m := range idMap {
if (contID >= m.ContainerID) && (contID <= (m.ContainerID + m.Size - 1)) {
hostID := m.HostID + (contID - m.ContainerID)
return hostID, nil
}
}
return -1, fmt.Errorf("Container ID %d cannot be mapped to a host ID", contID)
}
// Identity is either a UID and GID pair or a SID (but not both)
type Identity struct {
UID int
GID int
SID string
}
// IdentityMapping contains a mappings of UIDs and GIDs
type IdentityMapping struct {
uids []IDMap
gids []IDMap
}
// NewIdentityMapping takes a requested user and group name and
// using the data from /etc/sub{uid,gid} ranges, creates the
// proper uid and gid remapping ranges for that user/group pair
func NewIdentityMapping(username, groupname string) (*IdentityMapping, error) {
subuidRanges, err := parseSubuid(username)
if err != nil {
return nil, err
}
subgidRanges, err := parseSubgid(groupname)
if err != nil {
return nil, err
}
if len(subuidRanges) == 0 {
return nil, fmt.Errorf("No subuid ranges found for user %q", username)
}
if len(subgidRanges) == 0 {
return nil, fmt.Errorf("No subgid ranges found for group %q", groupname)
}
return &IdentityMapping{
uids: createIDMap(subuidRanges),
gids: createIDMap(subgidRanges),
}, nil
}
// NewIDMappingsFromMaps creates a new mapping from two slices
// Deprecated: this is a temporary shim while transitioning to IDMapping
func NewIDMappingsFromMaps(uids []IDMap, gids []IDMap) *IdentityMapping {
return &IdentityMapping{uids: uids, gids: gids}
}
// RootPair returns a uid and gid pair for the root user. The error is ignored
// because a root user always exists, and the defaults are correct when the uid
// and gid maps are empty.
func (i *IdentityMapping) RootPair() Identity {
uid, gid, _ := GetRootUIDGID(i.uids, i.gids)
return Identity{UID: uid, GID: gid}
}
// ToHost returns the host UID and GID for the container uid, gid.
// Remapping is only performed if the ids aren't already the remapped root ids
func (i *IdentityMapping) ToHost(pair Identity) (Identity, error) {
var err error
target := i.RootPair()
if pair.UID != target.UID {
target.UID, err = toHost(pair.UID, i.uids)
if err != nil {
return target, err
}
}
if pair.GID != target.GID {
target.GID, err = toHost(pair.GID, i.gids)
}
return target, err
}
// ToContainer returns the container UID and GID for the host uid and gid
func (i *IdentityMapping) ToContainer(pair Identity) (int, int, error) {
uid, err := toContainer(pair.UID, i.uids)
if err != nil {
return -1, -1, err
}
gid, err := toContainer(pair.GID, i.gids)
return uid, gid, err
}
// Empty returns true if there are no id mappings
func (i *IdentityMapping) Empty() bool {
return len(i.uids) == 0 && len(i.gids) == 0
}
// UIDs return the UID mapping
// TODO: remove this once everything has been refactored to use pairs
func (i *IdentityMapping) UIDs() []IDMap {
return i.uids
}
// GIDs return the UID mapping
// TODO: remove this once everything has been refactored to use pairs
func (i *IdentityMapping) GIDs() []IDMap {
return i.gids
}
func createIDMap(subidRanges ranges) []IDMap {
idMap := []IDMap{}
// sort the ranges by lowest ID first
sort.Sort(subidRanges)
containerID := 0
for _, idrange := range subidRanges {
idMap = append(idMap, IDMap{
ContainerID: containerID,
HostID: idrange.Start,
Size: idrange.Length,
})
containerID = containerID + idrange.Length
}
return idMap
}
func parseSubuid(username string) (ranges, error) {
return parseSubidFile(subuidFileName, username)
}
func parseSubgid(username string) (ranges, error) {
return parseSubidFile(subgidFileName, username)
}
// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid)
// and return all found ranges for a specified username. If the special value
// "ALL" is supplied for username, then all ranges in the file will be returned
func parseSubidFile(path, username string) (ranges, error) {
var rangeList ranges
subidFile, err := os.Open(path)
if err != nil {
return rangeList, err
}
defer subidFile.Close()
s := bufio.NewScanner(subidFile)
for s.Scan() {
if err := s.Err(); err != nil {
return rangeList, err
}
text := strings.TrimSpace(s.Text())
if text == "" || strings.HasPrefix(text, "#") {
continue
}
parts := strings.Split(text, ":")
if len(parts) != 3 {
return rangeList, fmt.Errorf("Cannot parse subuid/gid information: Format not correct for %s file", path)
}
if parts[0] == username || username == "ALL" {
startid, err := strconv.Atoi(parts[1])
if err != nil {
return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err)
}
length, err := strconv.Atoi(parts[2])
if err != nil {
return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err)
}
rangeList = append(rangeList, subIDRange{startid, length})
}
}
return rangeList, nil
}

@ -1,231 +0,0 @@
// +build !windows
package idtools // import "github.com/docker/docker/pkg/idtools"
import (
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"sync"
"syscall"
"github.com/docker/docker/pkg/system"
"github.com/opencontainers/runc/libcontainer/user"
)
var (
entOnce sync.Once
getentCmd string
)
func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
// make an array containing the original path asked for, plus (for mkAll == true)
// all path components leading up to the complete path that don't exist before we MkdirAll
// so that we can chown all of them properly at the end. If chownExisting is false, we won't
// chown the full directory path if it exists
var paths []string
stat, err := system.Stat(path)
if err == nil {
if !stat.IsDir() {
return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
}
if !chownExisting {
return nil
}
// short-circuit--we were called with an existing directory and chown was requested
return lazyChown(path, owner.UID, owner.GID, stat)
}
if os.IsNotExist(err) {
paths = []string{path}
}
if mkAll {
// walk back to "/" looking for directories which do not exist
// and add them to the paths array for chown after creation
dirPath := path
for {
dirPath = filepath.Dir(dirPath)
if dirPath == "/" {
break
}
if _, err := os.Stat(dirPath); err != nil && os.IsNotExist(err) {
paths = append(paths, dirPath)
}
}
if err := system.MkdirAll(path, mode, ""); err != nil {
return err
}
} else {
if err := os.Mkdir(path, mode); err != nil && !os.IsExist(err) {
return err
}
}
// even if it existed, we will chown the requested path + any subpaths that
// didn't exist when we called MkdirAll
for _, pathComponent := range paths {
if err := lazyChown(pathComponent, owner.UID, owner.GID, nil); err != nil {
return err
}
}
return nil
}
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
// if that uid, gid pair has access (execute bit) to the directory
func CanAccess(path string, pair Identity) bool {
statInfo, err := system.Stat(path)
if err != nil {
return false
}
fileMode := os.FileMode(statInfo.Mode())
permBits := fileMode.Perm()
return accessible(statInfo.UID() == uint32(pair.UID),
statInfo.GID() == uint32(pair.GID), permBits)
}
func accessible(isOwner, isGroup bool, perms os.FileMode) bool {
if isOwner && (perms&0100 == 0100) {
return true
}
if isGroup && (perms&0010 == 0010) {
return true
}
if perms&0001 == 0001 {
return true
}
return false
}
// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupUser(username string) (user.User, error) {
// first try a local system files lookup using existing capabilities
usr, err := user.LookupUser(username)
if err == nil {
return usr, nil
}
// local files lookup failed; attempt to call `getent` to query configured passwd dbs
usr, err = getentUser(fmt.Sprintf("%s %s", "passwd", username))
if err != nil {
return user.User{}, err
}
return usr, nil
}
// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupUID(uid int) (user.User, error) {
// first try a local system files lookup using existing capabilities
usr, err := user.LookupUid(uid)
if err == nil {
return usr, nil
}
// local files lookup failed; attempt to call `getent` to query configured passwd dbs
return getentUser(fmt.Sprintf("%s %d", "passwd", uid))
}
func getentUser(args string) (user.User, error) {
reader, err := callGetent(args)
if err != nil {
return user.User{}, err
}
users, err := user.ParsePasswd(reader)
if err != nil {
return user.User{}, err
}
if len(users) == 0 {
return user.User{}, fmt.Errorf("getent failed to find passwd entry for %q", strings.Split(args, " ")[1])
}
return users[0], nil
}
// LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupGroup(groupname string) (user.Group, error) {
// first try a local system files lookup using existing capabilities
group, err := user.LookupGroup(groupname)
if err == nil {
return group, nil
}
// local files lookup failed; attempt to call `getent` to query configured group dbs
return getentGroup(fmt.Sprintf("%s %s", "group", groupname))
}
// LookupGID uses traditional local system files lookup (from libcontainer/user) on a group ID,
// followed by a call to `getent` for supporting host configured non-files passwd and group dbs
func LookupGID(gid int) (user.Group, error) {
// first try a local system files lookup using existing capabilities
group, err := user.LookupGid(gid)
if err == nil {
return group, nil
}
// local files lookup failed; attempt to call `getent` to query configured group dbs
return getentGroup(fmt.Sprintf("%s %d", "group", gid))
}
func getentGroup(args string) (user.Group, error) {
reader, err := callGetent(args)
if err != nil {
return user.Group{}, err
}
groups, err := user.ParseGroup(reader)
if err != nil {
return user.Group{}, err
}
if len(groups) == 0 {
return user.Group{}, fmt.Errorf("getent failed to find groups entry for %q", strings.Split(args, " ")[1])
}
return groups[0], nil
}
func callGetent(args string) (io.Reader, error) {
entOnce.Do(func() { getentCmd, _ = resolveBinary("getent") })
// if no `getent` command on host, can't do anything else
if getentCmd == "" {
return nil, fmt.Errorf("")
}
out, err := execCmd(getentCmd, args)
if err != nil {
exitCode, errC := system.GetExitCode(err)
if errC != nil {
return nil, err
}
switch exitCode {
case 1:
return nil, fmt.Errorf("getent reported invalid parameters/database unknown")
case 2:
terms := strings.Split(args, " ")
return nil, fmt.Errorf("getent unable to find entry %q in %s database", terms[1], terms[0])
case 3:
return nil, fmt.Errorf("getent database doesn't support enumeration")
default:
return nil, err
}
}
return bytes.NewReader(out), nil
}
// lazyChown performs a chown only if the uid/gid don't match what's requested
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
// dir is on an NFS share, so don't call chown unless we absolutely must.
func lazyChown(p string, uid, gid int, stat *system.StatT) error {
if stat == nil {
var err error
stat, err = system.Stat(p)
if err != nil {
return err
}
}
if stat.UID() == uint32(uid) && stat.GID() == uint32(gid) {
return nil
}
return os.Chown(p, uid, gid)
}

@ -1,25 +0,0 @@
package idtools // import "github.com/docker/docker/pkg/idtools"
import (
"os"
"github.com/docker/docker/pkg/system"
)
// This is currently a wrapper around MkdirAll, however, since currently
// permissions aren't set through this path, the identity isn't utilized.
// Ownership is handled elsewhere, but in the future could be support here
// too.
func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
if err := system.MkdirAll(path, mode, ""); err != nil {
return err
}
return nil
}
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
// if that uid, gid pair has access (execute bit) to the directory
// Windows does not require/support this function, so always return true
func CanAccess(path string, identity Identity) bool {
return true
}

@ -1,164 +0,0 @@
package idtools // import "github.com/docker/docker/pkg/idtools"
import (
"fmt"
"regexp"
"sort"
"strconv"
"strings"
"sync"
)
// add a user and/or group to Linux /etc/passwd, /etc/group using standard
// Linux distribution commands:
// adduser --system --shell /bin/false --disabled-login --disabled-password --no-create-home --group <username>
// useradd -r -s /bin/false <username>
var (
once sync.Once
userCommand string
cmdTemplates = map[string]string{
"adduser": "--system --shell /bin/false --no-create-home --disabled-login --disabled-password --group %s",
"useradd": "-r -s /bin/false %s",
"usermod": "-%s %d-%d %s",
}
idOutRegexp = regexp.MustCompile(`uid=([0-9]+).*gid=([0-9]+)`)
// default length for a UID/GID subordinate range
defaultRangeLen = 65536
defaultRangeStart = 100000
userMod = "usermod"
)
// AddNamespaceRangesUser takes a username and uses the standard system
// utility to create a system user/group pair used to hold the
// /etc/sub{uid,gid} ranges which will be used for user namespace
// mapping ranges in containers.
func AddNamespaceRangesUser(name string) (int, int, error) {
if err := addUser(name); err != nil {
return -1, -1, fmt.Errorf("Error adding user %q: %v", name, err)
}
// Query the system for the created uid and gid pair
out, err := execCmd("id", name)
if err != nil {
return -1, -1, fmt.Errorf("Error trying to find uid/gid for new user %q: %v", name, err)
}
matches := idOutRegexp.FindStringSubmatch(strings.TrimSpace(string(out)))
if len(matches) != 3 {
return -1, -1, fmt.Errorf("Can't find uid, gid from `id` output: %q", string(out))
}
uid, err := strconv.Atoi(matches[1])
if err != nil {
return -1, -1, fmt.Errorf("Can't convert found uid (%s) to int: %v", matches[1], err)
}
gid, err := strconv.Atoi(matches[2])
if err != nil {
return -1, -1, fmt.Errorf("Can't convert found gid (%s) to int: %v", matches[2], err)
}
// Now we need to create the subuid/subgid ranges for our new user/group (system users
// do not get auto-created ranges in subuid/subgid)
if err := createSubordinateRanges(name); err != nil {
return -1, -1, fmt.Errorf("Couldn't create subordinate ID ranges: %v", err)
}
return uid, gid, nil
}
func addUser(userName string) error {
once.Do(func() {
// set up which commands are used for adding users/groups dependent on distro
if _, err := resolveBinary("adduser"); err == nil {
userCommand = "adduser"
} else if _, err := resolveBinary("useradd"); err == nil {
userCommand = "useradd"
}
})
if userCommand == "" {
return fmt.Errorf("Cannot add user; no useradd/adduser binary found")
}
args := fmt.Sprintf(cmdTemplates[userCommand], userName)
out, err := execCmd(userCommand, args)
if err != nil {
return fmt.Errorf("Failed to add user with error: %v; output: %q", err, string(out))
}
return nil
}
func createSubordinateRanges(name string) error {
// first, we should verify that ranges weren't automatically created
// by the distro tooling
ranges, err := parseSubuid(name)
if err != nil {
return fmt.Errorf("Error while looking for subuid ranges for user %q: %v", name, err)
}
if len(ranges) == 0 {
// no UID ranges; let's create one
startID, err := findNextUIDRange()
if err != nil {
return fmt.Errorf("Can't find available subuid range: %v", err)
}
out, err := execCmd(userMod, fmt.Sprintf(cmdTemplates[userMod], "v", startID, startID+defaultRangeLen-1, name))
if err != nil {
return fmt.Errorf("Unable to add subuid range to user: %q; output: %s, err: %v", name, out, err)
}
}
ranges, err = parseSubgid(name)
if err != nil {
return fmt.Errorf("Error while looking for subgid ranges for user %q: %v", name, err)
}
if len(ranges) == 0 {
// no GID ranges; let's create one
startID, err := findNextGIDRange()
if err != nil {
return fmt.Errorf("Can't find available subgid range: %v", err)
}
out, err := execCmd(userMod, fmt.Sprintf(cmdTemplates[userMod], "w", startID, startID+defaultRangeLen-1, name))
if err != nil {
return fmt.Errorf("Unable to add subgid range to user: %q; output: %s, err: %v", name, out, err)
}
}
return nil
}
func findNextUIDRange() (int, error) {
ranges, err := parseSubuid("ALL")
if err != nil {
return -1, fmt.Errorf("Couldn't parse all ranges in /etc/subuid file: %v", err)
}
sort.Sort(ranges)
return findNextRangeStart(ranges)
}
func findNextGIDRange() (int, error) {
ranges, err := parseSubgid("ALL")
if err != nil {
return -1, fmt.Errorf("Couldn't parse all ranges in /etc/subgid file: %v", err)
}
sort.Sort(ranges)
return findNextRangeStart(ranges)
}
func findNextRangeStart(rangeList ranges) (int, error) {
startID := defaultRangeStart
for _, arange := range rangeList {
if wouldOverlap(arange, startID) {
startID = arange.Start + arange.Length
}
}
return startID, nil
}
func wouldOverlap(arange subIDRange, ID int) bool {
low := ID
high := ID + defaultRangeLen
if (low >= arange.Start && low <= arange.Start+arange.Length) ||
(high <= arange.Start+arange.Length && high >= arange.Start) {
return true
}
return false
}

@ -1,12 +0,0 @@
// +build !linux
package idtools // import "github.com/docker/docker/pkg/idtools"
import "fmt"
// AddNamespaceRangesUser takes a name and finds an unused uid, gid pair
// and calls the appropriate helper function to add the group and then
// the user to the group in /etc/group and /etc/passwd respectively.
func AddNamespaceRangesUser(name string) (int, int, error) {
return -1, -1, fmt.Errorf("No support for adding users or groups on this OS")
}

@ -1,32 +0,0 @@
// +build !windows
package idtools // import "github.com/docker/docker/pkg/idtools"
import (
"fmt"
"os/exec"
"path/filepath"
"strings"
)
func resolveBinary(binname string) (string, error) {
binaryPath, err := exec.LookPath(binname)
if err != nil {
return "", err
}
resolvedPath, err := filepath.EvalSymlinks(binaryPath)
if err != nil {
return "", err
}
//only return no error if the final resolved binary basename
//matches what was searched for
if filepath.Base(resolvedPath) == binname {
return resolvedPath, nil
}
return "", fmt.Errorf("Binary %q does not resolve to a binary of that name in $PATH (%q)", binname, resolvedPath)
}
func execCmd(cmd, args string) ([]byte, error) {
execCmd := exec.Command(cmd, strings.Split(args, " ")...)
return execCmd.CombinedOutput()
}

@ -128,8 +128,9 @@ func (bp *BytesPipe) Read(p []byte) (n int, err error) {
bp.mu.Lock() bp.mu.Lock()
if bp.bufLen == 0 { if bp.bufLen == 0 {
if bp.closeErr != nil { if bp.closeErr != nil {
err := bp.closeErr
bp.mu.Unlock() bp.mu.Unlock()
return 0, bp.closeErr return 0, err
} }
bp.wait.Wait() bp.wait.Wait()
if bp.bufLen == 0 && bp.closeErr != nil { if bp.bufLen == 0 && bp.closeErr != nil {

@ -8,7 +8,7 @@ import (
"time" "time"
"github.com/docker/docker/pkg/term" "github.com/docker/docker/pkg/term"
"github.com/docker/go-units" units "github.com/docker/go-units"
"github.com/morikuni/aec" "github.com/morikuni/aec"
) )
@ -139,13 +139,13 @@ type JSONMessage struct {
Stream string `json:"stream,omitempty"` Stream string `json:"stream,omitempty"`
Status string `json:"status,omitempty"` Status string `json:"status,omitempty"`
Progress *JSONProgress `json:"progressDetail,omitempty"` Progress *JSONProgress `json:"progressDetail,omitempty"`
ProgressMessage string `json:"progress,omitempty"` //deprecated ProgressMessage string `json:"progress,omitempty"` // deprecated
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
From string `json:"from,omitempty"` From string `json:"from,omitempty"`
Time int64 `json:"time,omitempty"` Time int64 `json:"time,omitempty"`
TimeNano int64 `json:"timeNano,omitempty"` TimeNano int64 `json:"timeNano,omitempty"`
Error *JSONError `json:"errorDetail,omitempty"` Error *JSONError `json:"errorDetail,omitempty"`
ErrorMessage string `json:"error,omitempty"` //deprecated ErrorMessage string `json:"error,omitempty"` // deprecated
// Aux contains out-of-band data, such as digests for push signing and image id after building. // Aux contains out-of-band data, such as digests for push signing and image id after building.
Aux *json.RawMessage `json:"aux,omitempty"` Aux *json.RawMessage `json:"aux,omitempty"`
} }
@ -177,7 +177,7 @@ func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
if isTerminal && jm.Stream == "" && jm.Progress != nil { if isTerminal && jm.Stream == "" && jm.Progress != nil {
clearLine(out) clearLine(out)
endl = "\r" endl = "\r"
fmt.Fprintf(out, endl) fmt.Fprint(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
return nil return nil
} }
@ -194,7 +194,7 @@ func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
} }
if jm.Progress != nil && isTerminal { 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)
} else if jm.Stream != "" { } else if jm.Stream != "" {
fmt.Fprintf(out, "%s%s", jm.Stream, endl) fmt.Fprintf(out, "%s%s", jm.Stream, endl)

@ -102,13 +102,13 @@ func Mounted(mountpoint string) (bool, error) {
// specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See // specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See
// flags.go for supported option flags. // flags.go for supported option flags.
func Mount(device, target, mType, options string) error { func Mount(device, target, mType, options string) error {
flag, _ := parseOptions(options) flag, data := parseOptions(options)
if flag&REMOUNT != REMOUNT { if flag&REMOUNT != REMOUNT {
if mounted, err := Mounted(target); err != nil || mounted { if mounted, err := Mounted(target); err != nil || mounted {
return err return err
} }
} }
return ForceMount(device, target, mType, options) return mount(device, target, mType, uintptr(flag), data)
} }
// ForceMount will mount a filesystem according to the specified configuration, // ForceMount will mount a filesystem according to the specified configuration,

@ -13,8 +13,7 @@ import (
"unsafe" "unsafe"
) )
// Parse /proc/self/mountinfo because comparing Dev and ino does not work from //parseMountTable returns information about mounted filesystems
// bind mounts.
func parseMountTable(filter FilterFunc) ([]*Info, error) { func parseMountTable(filter FilterFunc) ([]*Info, error) {
var rawEntries *C.struct_statfs var rawEntries *C.struct_statfs
@ -37,7 +36,7 @@ func parseMountTable(filter FilterFunc) ([]*Info, error) {
if filter != nil { if filter != nil {
// filter out entries we're not interested in // filter out entries we're not interested in
skip, stop = filter(p) skip, stop = filter(&mountinfo)
if skip { if skip {
continue continue
} }

@ -90,7 +90,6 @@ func parseInfoFile(r io.Reader, filter FilterFunc) ([]*Info, error) {
mount propagation flags in fields[6]. The correct mount propagation flags in fields[6]. The correct
behavior is to ignore any unknown optional fields. behavior is to ignore any unknown optional fields.
*/ */
break
} }
} }
if i == numFields { if i == numFields {

@ -3,49 +3,49 @@ package mount // import "github.com/docker/docker/pkg/mount"
// MakeShared ensures a mounted filesystem has the SHARED mount option enabled. // MakeShared ensures a mounted filesystem has the SHARED mount option enabled.
// See the supported options in flags.go for further reference. // See the supported options in flags.go for further reference.
func MakeShared(mountPoint string) error { func MakeShared(mountPoint string) error {
return ensureMountedAs(mountPoint, "shared") return ensureMountedAs(mountPoint, SHARED)
} }
// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled. // MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled.
// See the supported options in flags.go for further reference. // See the supported options in flags.go for further reference.
func MakeRShared(mountPoint string) error { func MakeRShared(mountPoint string) error {
return ensureMountedAs(mountPoint, "rshared") return ensureMountedAs(mountPoint, RSHARED)
} }
// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled. // MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled.
// See the supported options in flags.go for further reference. // See the supported options in flags.go for further reference.
func MakePrivate(mountPoint string) error { func MakePrivate(mountPoint string) error {
return ensureMountedAs(mountPoint, "private") return ensureMountedAs(mountPoint, PRIVATE)
} }
// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option // MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option
// enabled. See the supported options in flags.go for further reference. // enabled. See the supported options in flags.go for further reference.
func MakeRPrivate(mountPoint string) error { func MakeRPrivate(mountPoint string) error {
return ensureMountedAs(mountPoint, "rprivate") return ensureMountedAs(mountPoint, RPRIVATE)
} }
// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled. // MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled.
// See the supported options in flags.go for further reference. // See the supported options in flags.go for further reference.
func MakeSlave(mountPoint string) error { func MakeSlave(mountPoint string) error {
return ensureMountedAs(mountPoint, "slave") return ensureMountedAs(mountPoint, SLAVE)
} }
// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled. // MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled.
// See the supported options in flags.go for further reference. // See the supported options in flags.go for further reference.
func MakeRSlave(mountPoint string) error { func MakeRSlave(mountPoint string) error {
return ensureMountedAs(mountPoint, "rslave") return ensureMountedAs(mountPoint, RSLAVE)
} }
// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option // MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option
// enabled. See the supported options in flags.go for further reference. // enabled. See the supported options in flags.go for further reference.
func MakeUnbindable(mountPoint string) error { func MakeUnbindable(mountPoint string) error {
return ensureMountedAs(mountPoint, "unbindable") return ensureMountedAs(mountPoint, UNBINDABLE)
} }
// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount // MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount
// option enabled. See the supported options in flags.go for further reference. // option enabled. See the supported options in flags.go for further reference.
func MakeRUnbindable(mountPoint string) error { func MakeRUnbindable(mountPoint string) error {
return ensureMountedAs(mountPoint, "runbindable") return ensureMountedAs(mountPoint, RUNBINDABLE)
} }
// MakeMount ensures that the file or directory given is a mount point, // MakeMount ensures that the file or directory given is a mount point,
@ -59,13 +59,13 @@ func MakeMount(mnt string) error {
return nil return nil
} }
return Mount(mnt, mnt, "none", "bind") return mount(mnt, mnt, "none", uintptr(BIND), "")
} }
func ensureMountedAs(mountPoint, options string) error { func ensureMountedAs(mnt string, flags int) error {
if err := MakeMount(mountPoint); err != nil { if err := MakeMount(mnt); err != nil {
return err return err
} }
return ForceMount("", mountPoint, "none", options) return mount("", mnt, "none", uintptr(flags), "")
} }

@ -22,7 +22,6 @@ var (
"busy", "busy",
"charming", "charming",
"clever", "clever",
"cocky",
"cool", "cool",
"compassionate", "compassionate",
"competent", "competent",
@ -154,7 +153,7 @@ var (
// Stefan Banach - Polish mathematician, was one of the founders of modern functional analysis. https://en.wikipedia.org/wiki/Stefan_Banach // Stefan Banach - Polish mathematician, was one of the founders of modern functional analysis. https://en.wikipedia.org/wiki/Stefan_Banach
"banach", "banach",
// Buckaroo Banzai and his mentor Dr. Hikita perfectd the "oscillation overthruster", a device that allows one to pass through solid matter. - https://en.wikipedia.org/wiki/The_Adventures_of_Buckaroo_Banzai_Across_the_8th_Dimension // Buckaroo Banzai and his mentor Dr. Hikita perfected the "oscillation overthruster", a device that allows one to pass through solid matter. - https://en.wikipedia.org/wiki/The_Adventures_of_Buckaroo_Banzai_Across_the_8th_Dimension
"banzai", "banzai",
// John Bardeen co-invented the transistor - https://en.wikipedia.org/wiki/John_Bardeen // John Bardeen co-invented the transistor - https://en.wikipedia.org/wiki/John_Bardeen
@ -588,9 +587,6 @@ var (
// Johanna Mestorf - German prehistoric archaeologist and first female museum director in Germany - https://en.wikipedia.org/wiki/Johanna_Mestorf // Johanna Mestorf - German prehistoric archaeologist and first female museum director in Germany - https://en.wikipedia.org/wiki/Johanna_Mestorf
"mestorf", "mestorf",
// Marvin Minsky - Pioneer in Artificial Intelligence, co-founder of the MIT's AI Lab, won the Turing Award in 1969. https://en.wikipedia.org/wiki/Marvin_Minsky
"minsky",
// Maryam Mirzakhani - an Iranian mathematician and the first woman to win the Fields Medal. https://en.wikipedia.org/wiki/Maryam_Mirzakhani // Maryam Mirzakhani - an Iranian mathematician and the first woman to win the Fields Medal. https://en.wikipedia.org/wiki/Maryam_Mirzakhani
"mirzakhani", "mirzakhani",
@ -738,9 +734,6 @@ var (
// Frances Spence - one of the original programmers of the ENIAC. https://en.wikipedia.org/wiki/ENIAC - https://en.wikipedia.org/wiki/Frances_Spence // Frances Spence - one of the original programmers of the ENIAC. https://en.wikipedia.org/wiki/ENIAC - https://en.wikipedia.org/wiki/Frances_Spence
"spence", "spence",
// Richard Matthew Stallman - the founder of the Free Software movement, the GNU project, the Free Software Foundation, and the League for Programming Freedom. He also invented the concept of copyleft to protect the ideals of this movement, and enshrined this concept in the widely-used GPL (General Public License) for software. https://en.wikiquote.org/wiki/Richard_Stallman
"stallman",
// Michael Stonebraker is a database research pioneer and architect of Ingres, Postgres, VoltDB and SciDB. Winner of 2014 ACM Turing Award. https://en.wikipedia.org/wiki/Michael_Stonebraker // Michael Stonebraker is a database research pioneer and architect of Ingres, Postgres, VoltDB and SciDB. Winner of 2014 ACM Turing Award. https://en.wikipedia.org/wiki/Michael_Stonebraker
"stonebraker", "stonebraker",

@ -2,17 +2,12 @@
package stringid // import "github.com/docker/docker/pkg/stringid" package stringid // import "github.com/docker/docker/pkg/stringid"
import ( import (
cryptorand "crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"io"
"math"
"math/big"
"math/rand"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"time"
) )
const shortLen = 12 const shortLen = 12
@ -41,10 +36,11 @@ func TruncateID(id string) string {
return id return id
} }
func generateID(r io.Reader) string { // GenerateRandomID returns a unique id.
func GenerateRandomID() string {
b := make([]byte, 32) b := make([]byte, 32)
for { for {
if _, err := io.ReadFull(r, b); err != nil { if _, err := rand.Read(b); err != nil {
panic(err) // This shouldn't happen panic(err) // This shouldn't happen
} }
id := hex.EncodeToString(b) id := hex.EncodeToString(b)
@ -58,18 +54,6 @@ func generateID(r io.Reader) string {
} }
} }
// GenerateRandomID returns a unique id.
func GenerateRandomID() string {
return generateID(cryptorand.Reader)
}
// GenerateNonCryptoID generates unique id without using cryptographically
// secure sources of random.
// It helps you to save entropy.
func GenerateNonCryptoID() string {
return generateID(readerFunc(rand.Read))
}
// ValidateID checks whether an ID string is a valid image ID. // ValidateID checks whether an ID string is a valid image ID.
func ValidateID(id string) error { func ValidateID(id string) error {
if ok := validHex.MatchString(id); !ok { if ok := validHex.MatchString(id); !ok {
@ -77,23 +61,3 @@ func ValidateID(id string) error {
} }
return nil return nil
} }
func init() {
// safely set the seed globally so we generate random ids. Tries to use a
// crypto seed before falling back to time.
var seed int64
if cryptoseed, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64)); err != nil {
// This should not happen, but worst-case fallback to time-based seed.
seed = time.Now().UnixNano()
} else {
seed = cryptoseed.Int64()
}
rand.Seed(seed)
}
type readerFunc func(p []byte) (int, error)
func (fn readerFunc) Read(p []byte) (int, error) {
return fn(p)
}

@ -8,14 +8,14 @@ import (
"path/filepath" "path/filepath"
) )
// MkdirAllWithACL is a wrapper for MkdirAll on unix systems. // MkdirAllWithACL is a wrapper for os.MkdirAll on unix systems.
func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error { func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error {
return MkdirAll(path, perm, sddl) return os.MkdirAll(path, perm)
} }
// MkdirAll creates a directory named path along with any necessary parents, // MkdirAll creates a directory named path along with any necessary parents,
// with permission specified by attribute perm for all dir created. // with permission specified by attribute perm for all dir created.
func MkdirAll(path string, perm os.FileMode, sddl string) error { func MkdirAll(path string, perm os.FileMode) error {
return os.MkdirAll(path, perm) return os.MkdirAll(path, perm)
} }

@ -11,7 +11,6 @@ import (
"time" "time"
"unsafe" "unsafe"
winio "github.com/Microsoft/go-winio"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
@ -26,9 +25,10 @@ func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error {
return mkdirall(path, true, sddl) return mkdirall(path, true, sddl)
} }
// MkdirAll implementation that is volume path aware for Windows. // MkdirAll implementation that is volume path aware for Windows. It can be used
func MkdirAll(path string, _ os.FileMode, sddl string) error { // as a drop-in replacement for os.MkdirAll()
return mkdirall(path, false, sddl) func MkdirAll(path string, _ os.FileMode) error {
return mkdirall(path, false, "")
} }
// mkdirall is a custom version of os.MkdirAll modified for use on Windows // mkdirall is a custom version of os.MkdirAll modified for use on Windows
@ -102,13 +102,13 @@ func mkdirall(path string, applyACL bool, sddl string) error {
// and Local System. // and Local System.
func mkdirWithACL(name string, sddl string) error { func mkdirWithACL(name string, sddl string) error {
sa := windows.SecurityAttributes{Length: 0} sa := windows.SecurityAttributes{Length: 0}
sd, err := winio.SddlToSecurityDescriptor(sddl) sd, err := windows.SecurityDescriptorFromString(sddl)
if err != nil { if err != nil {
return &os.PathError{Op: "mkdir", Path: name, Err: err} return &os.PathError{Op: "mkdir", Path: name, Err: err}
} }
sa.Length = uint32(unsafe.Sizeof(sa)) sa.Length = uint32(unsafe.Sizeof(sa))
sa.InheritHandle = 1 sa.InheritHandle = 1
sa.SecurityDescriptor = uintptr(unsafe.Pointer(&sd[0])) sa.SecurityDescriptor = sd
namep, err := windows.UTF16PtrFromString(name) namep, err := windows.UTF16PtrFromString(name)
if err != nil { if err != nil {

@ -18,8 +18,7 @@ var (
// InitLCOW sets whether LCOW is supported or not. Requires RS5+ // InitLCOW sets whether LCOW is supported or not. Requires RS5+
func InitLCOW(experimental bool) { func InitLCOW(experimental bool) {
v := GetOSVersion() if experimental && osversion.Build() >= osversion.RS5 {
if experimental && v.Build >= osversion.RS5 {
lcowSupported = true lcowSupported = true
} }
} }

@ -7,7 +7,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/docker/go-units" units "github.com/docker/go-units"
) )
// ReadMemInfo retrieves memory statistics of the host system and returns a // ReadMemInfo retrieves memory statistics of the host system and returns a
@ -27,6 +27,7 @@ func ReadMemInfo() (*MemInfo, error) {
func parseMemInfo(reader io.Reader) (*MemInfo, error) { func parseMemInfo(reader io.Reader) (*MemInfo, error) {
meminfo := &MemInfo{} meminfo := &MemInfo{}
scanner := bufio.NewScanner(reader) scanner := bufio.NewScanner(reader)
memAvailable := int64(-1)
for scanner.Scan() { for scanner.Scan() {
// Expected format: ["MemTotal:", "1234", "kB"] // Expected format: ["MemTotal:", "1234", "kB"]
parts := strings.Fields(scanner.Text()) parts := strings.Fields(scanner.Text())
@ -48,6 +49,8 @@ func parseMemInfo(reader io.Reader) (*MemInfo, error) {
meminfo.MemTotal = bytes meminfo.MemTotal = bytes
case "MemFree:": case "MemFree:":
meminfo.MemFree = bytes meminfo.MemFree = bytes
case "MemAvailable:":
memAvailable = bytes
case "SwapTotal:": case "SwapTotal:":
meminfo.SwapTotal = bytes meminfo.SwapTotal = bytes
case "SwapFree:": case "SwapFree:":
@ -55,6 +58,9 @@ func parseMemInfo(reader io.Reader) (*MemInfo, error) {
} }
} }
if memAvailable != -1 {
meminfo.MemFree = memAvailable
}
// Handle errors that may have occurred during the reading of the file. // Handle errors that may have occurred during the reading of the file.
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {

@ -5,8 +5,6 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"github.com/containerd/continuity/pathdriver"
) )
const defaultUnixPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" const defaultUnixPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
@ -27,6 +25,12 @@ func DefaultPathEnv(os string) string {
} }
// PathVerifier defines the subset of a PathDriver that CheckSystemDriveAndRemoveDriveLetter
// actually uses in order to avoid system depending on containerd/continuity.
type PathVerifier interface {
IsAbs(string) bool
}
// CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter, // CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter,
// is the system drive. // is the system drive.
// On Linux: this is a no-op. // On Linux: this is a no-op.
@ -42,7 +46,7 @@ func DefaultPathEnv(os string) string {
// a --> a // a --> a
// /a --> \a // /a --> \a
// d:\ --> Fail // d:\ --> Fail
func CheckSystemDriveAndRemoveDriveLetter(path string, driver pathdriver.PathDriver) (string, error) { func CheckSystemDriveAndRemoveDriveLetter(path string, driver PathVerifier) (string, error) {
if runtime.GOOS != "windows" || LCOWSupported() { if runtime.GOOS != "windows" || LCOWSupported() {
return path, nil return path, nil
} }

@ -8,7 +8,8 @@ func fromStatT(s *syscall.Stat_t) (*StatT, error) {
mode: s.Mode, mode: s.Mode,
uid: s.Uid, uid: s.Uid,
gid: s.Gid, gid: s.Gid,
rdev: s.Rdev, // the type is 32bit on mips
rdev: uint64(s.Rdev), // nolint: unconvert
mtim: s.Mtim}, nil mtim: s.Mtim}, nil
} }

@ -1,13 +0,0 @@
package system // import "github.com/docker/docker/pkg/system"
import "syscall"
// fromStatT converts a syscall.Stat_t type to a system.Stat_t type
func fromStatT(s *syscall.Stat_t) (*StatT, error) {
return &StatT{size: s.Size,
mode: uint32(s.Mode),
uid: s.Uid,
gid: s.Gid,
rdev: uint64(s.Rdev),
mtim: s.Mtim}, nil
}

@ -1,10 +1,10 @@
package system // import "github.com/docker/docker/pkg/system" package system // import "github.com/docker/docker/pkg/system"
import ( import (
"fmt"
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/Microsoft/hcsshim/osversion"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
@ -55,19 +55,13 @@ var (
ntuserApiset = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0") ntuserApiset = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
procGetVersionExW = modkernel32.NewProc("GetVersionExW") procGetVersionExW = modkernel32.NewProc("GetVersionExW")
procGetProductInfo = modkernel32.NewProc("GetProductInfo")
procSetNamedSecurityInfo = modadvapi32.NewProc("SetNamedSecurityInfoW") procSetNamedSecurityInfo = modadvapi32.NewProc("SetNamedSecurityInfoW")
procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl") procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl")
) )
// OSVersion is a wrapper for Windows version information // OSVersion is a wrapper for Windows version information
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
type OSVersion struct { type OSVersion = osversion.OSVersion
Version uint32
MajorVersion uint8
MinorVersion uint8
Build uint16
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
type osVersionInfoEx struct { type osVersionInfoEx struct {
@ -85,23 +79,10 @@ type osVersionInfoEx struct {
} }
// GetOSVersion gets the operating system version on Windows. Note that // GetOSVersion gets the operating system version on Windows. Note that
// docker.exe must be manifested to get the correct version information. // dockerd.exe must be manifested to get the correct version information.
// Deprecated: use github.com/Microsoft/hcsshim/osversion.Get() instead
func GetOSVersion() OSVersion { func GetOSVersion() OSVersion {
var err error return osversion.Get()
osv := OSVersion{}
osv.Version, err = windows.GetVersion()
if err != nil {
// GetVersion never fails.
panic(err)
}
osv.MajorVersion = uint8(osv.Version & 0xFF)
osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
osv.Build = uint16(osv.Version >> 16)
return osv
}
func (osv OSVersion) ToString() string {
return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build)
} }
// IsWindowsClient returns true if the SKU is client // IsWindowsClient returns true if the SKU is client
@ -118,22 +99,6 @@ func IsWindowsClient() bool {
return osviex.ProductType == verNTWorkstation return osviex.ProductType == verNTWorkstation
} }
// IsIoTCore returns true if the currently running image is based off of
// Windows 10 IoT Core.
// @engine maintainers - this function should not be removed or modified as it
// is used to enforce licensing restrictions on Windows.
func IsIoTCore() bool {
var returnedProductType uint32
r1, _, err := procGetProductInfo.Call(6, 1, 0, 0, uintptr(unsafe.Pointer(&returnedProductType)))
if r1 == 0 {
logrus.Warnf("GetProductInfo failed - assuming this is not IoT: %v", err)
return false
}
const productIoTUAP = 0x0000007B
const productIoTUAPCommercial = 0x00000083
return returnedProductType == productIoTUAP || returnedProductType == productIoTUAPCommercial
}
// Unmount is a platform-specific helper function to call // Unmount is a platform-specific helper function to call
// the unmount syscall. Not supported on Windows // the unmount syscall. Not supported on Windows
func Unmount(dest string) error { func Unmount(dest string) error {

@ -1,25 +0,0 @@
package system // import "github.com/docker/docker/pkg/system"
import (
"syscall"
"unsafe"
"golang.org/x/sys/unix"
)
// LUtimesNano is used to change access and modification time of the specified path.
// It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm.
func LUtimesNano(path string, ts []syscall.Timespec) error {
atFdCwd := unix.AT_FDCWD
var _path *byte
_path, err := unix.BytePtrFromString(path)
if err != nil {
return err
}
if _, _, err := unix.Syscall6(unix.SYS_UTIMENSAT, uintptr(atFdCwd), uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), unix.AT_SYMLINK_NOFOLLOW, 0, 0); err != 0 && err != unix.ENOSYS {
return err
}
return nil
}

@ -1,8 +1,9 @@
// +build linux freebsd
package system // import "github.com/docker/docker/pkg/system" package system // import "github.com/docker/docker/pkg/system"
import ( import (
"syscall" "syscall"
"unsafe"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -10,13 +11,12 @@ import (
// LUtimesNano is used to change access and modification time of the specified path. // LUtimesNano is used to change access and modification time of the specified path.
// It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm. // It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm.
func LUtimesNano(path string, ts []syscall.Timespec) error { func LUtimesNano(path string, ts []syscall.Timespec) error {
var _path *byte uts := []unix.Timespec{
_path, err := unix.BytePtrFromString(path) unix.NsecToTimespec(syscall.TimespecToNsec(ts[0])),
if err != nil { unix.NsecToTimespec(syscall.TimespecToNsec(ts[1])),
return err
} }
err := unix.UtimesNanoAt(unix.AT_FDCWD, path, uts, unix.AT_SYMLINK_NOFOLLOW)
if _, _, err := unix.Syscall(unix.SYS_LUTIMES, uintptr(unsafe.Pointer(_path)), uintptr(unsafe.Pointer(&ts[0])), 0); err != 0 && err != unix.ENOSYS { if err != nil && err != unix.ENOSYS {
return err return err
} }

@ -6,19 +6,28 @@ import "golang.org/x/sys/unix"
// and associated with the given path in the file system. // and associated with the given path in the file system.
// It will returns a nil slice and nil error if the xattr is not set. // It will returns a nil slice and nil error if the xattr is not set.
func Lgetxattr(path string, attr string) ([]byte, error) { func Lgetxattr(path string, attr string) ([]byte, error) {
// Start with a 128 length byte array
dest := make([]byte, 128) dest := make([]byte, 128)
sz, errno := unix.Lgetxattr(path, attr, dest) sz, errno := unix.Lgetxattr(path, attr, dest)
if errno == unix.ENODATA {
switch {
case errno == unix.ENODATA:
return nil, nil return nil, nil
} case errno == unix.ERANGE:
if errno == unix.ERANGE { // 128 byte array might just not be good enough. A dummy buffer is used
// to get the real size of the xattrs on disk
sz, errno = unix.Lgetxattr(path, attr, []byte{})
if errno != nil {
return nil, errno
}
dest = make([]byte, sz) dest = make([]byte, sz)
sz, errno = unix.Lgetxattr(path, attr, dest) sz, errno = unix.Lgetxattr(path, attr, dest)
} if errno != nil {
if errno != nil { return nil, errno
}
case errno != nil:
return nil, errno return nil, errno
} }
return dest[:sz], nil return dest[:sz], nil
} }

@ -7,7 +7,7 @@ import (
"syscall" // used for STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE "syscall" // used for STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and STD_ERROR_HANDLE
"github.com/Azure/go-ansiterm/winterm" "github.com/Azure/go-ansiterm/winterm"
"github.com/docker/docker/pkg/term/windows" windowsconsole "github.com/docker/docker/pkg/term/windows"
) )
// State holds the console mode for the terminal. // State holds the console mode for the terminal.

@ -1,3 +1,4 @@
// +build windows
// These files implement ANSI-aware input and output streams for use by the Docker Windows client. // These files implement ANSI-aware input and output streams for use by the Docker Windows client.
// When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create // When asked for the set of standard streams (e.g., stdin, stdout, stderr), the code will create
// and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls. // and return pseudo-streams that convert ANSI sequences to / from Windows Console API calls.
@ -9,7 +10,7 @@ import (
"os" "os"
"sync" "sync"
"github.com/Azure/go-ansiterm" ansiterm "github.com/Azure/go-ansiterm"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )

@ -33,7 +33,7 @@ func loginV1(authConfig *types.AuthConfig, apiEndpoint APIEndpoint, userAgent st
return "", "", errdefs.System(errors.New("server Error: Server Address not set")) return "", "", errdefs.System(errors.New("server Error: Server Address not set"))
} }
req, err := http.NewRequest("GET", serverAddress+"users/", nil) req, err := http.NewRequest(http.MethodGet, serverAddress+"users/", nil)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -140,7 +140,7 @@ func loginV2(authConfig *types.AuthConfig, endpoint APIEndpoint, userAgent strin
} }
endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/" endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/"
req, err := http.NewRequest("GET", endpointStr, nil) req, err := http.NewRequest(http.MethodGet, endpointStr, nil)
if err != nil { if err != nil {
if !foundV2 { if !foundV2 {
err = fallbackError{err: err} err = fallbackError{err: err}
@ -262,7 +262,7 @@ func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.M
Timeout: 15 * time.Second, Timeout: 15 * time.Second,
} }
endpointStr := strings.TrimRight(endpoint.String(), "/") + "/v2/" endpointStr := strings.TrimRight(endpoint.String(), "/") + "/v2/"
req, err := http.NewRequest("GET", endpointStr, nil) req, err := http.NewRequest(http.MethodGet, endpointStr, nil)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }

@ -124,9 +124,6 @@ func newV1EndpointFromStr(address string, tlsConfig *tls.Config, userAgent strin
} }
endpoint := newV1Endpoint(*uri, tlsConfig, userAgent, metaHeaders) endpoint := newV1Endpoint(*uri, tlsConfig, userAgent, metaHeaders)
if err != nil {
return nil, err
}
return endpoint, nil return endpoint, nil
} }
@ -152,7 +149,7 @@ func (e *V1Endpoint) Ping() (PingResult, error) {
return PingResult{Standalone: false}, nil return PingResult{Standalone: false}, nil
} }
req, err := http.NewRequest("GET", e.Path("_ping"), nil) req, err := http.NewRequest(http.MethodGet, e.Path("_ping"), nil)
if err != nil { if err != nil {
return PingResult{Standalone: false}, err return PingResult{Standalone: false}, err
} }

@ -14,9 +14,11 @@ import (
"time" "time"
"github.com/docker/distribution/registry/client/transport" "github.com/docker/distribution/registry/client/transport"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig" "github.com/docker/go-connections/tlsconfig"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/docker/docker/pkg/homedir"
"github.com/docker/docker/rootless"
) )
var ( var (
@ -32,7 +34,19 @@ func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) {
tlsConfig.InsecureSkipVerify = !isSecure tlsConfig.InsecureSkipVerify = !isSecure
if isSecure && CertsDir != "" { if isSecure && CertsDir != "" {
hostDir := filepath.Join(CertsDir, cleanPath(hostname)) certsDir := CertsDir
if rootless.RunningWithRootlessKit() {
configHome, err := homedir.GetConfigHome()
if err != nil {
return nil, err
}
certsDir = filepath.Join(configHome, "docker/certs.d")
}
hostDir := filepath.Join(certsDir, cleanPath(hostname))
logrus.Debugf("hostDir: %s", hostDir) logrus.Debugf("hostDir: %s", hostDir)
if err := ReadCertsDirectory(tlsConfig, hostDir); err != nil { if err := ReadCertsDirectory(tlsConfig, hostDir); err != nil {
return nil, err return nil, err
@ -56,7 +70,7 @@ func hasFile(files []os.FileInfo, name string) bool {
// provided TLS configuration. // provided TLS configuration.
func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error { func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error {
fs, err := ioutil.ReadDir(directory) fs, err := ioutil.ReadDir(directory)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) && !os.IsPermission(err) {
return err return err
} }
@ -176,16 +190,12 @@ func NewTransport(tlsConfig *tls.Config) *http.Transport {
base := &http.Transport{ base := &http.Transport{
Proxy: http.ProxyFromEnvironment, Proxy: http.ProxyFromEnvironment,
Dial: direct.Dial, DialContext: direct.DialContext,
TLSHandshakeTimeout: 10 * time.Second, TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
// TODO(dmcgowan): Call close idle connections when complete and use keep alive // TODO(dmcgowan): Call close idle connections when complete and use keep alive
DisableKeepAlives: true, DisableKeepAlives: true,
} }
proxyDialer, err := sockets.DialerFromEnvironment(direct)
if err == nil {
base.Dial = proxyDialer.Dial
}
return base return base
} }

@ -56,10 +56,10 @@ func (r *requestReader) Read(p []byte) (n int, err error) {
r.cleanUpResponse() r.cleanUpResponse()
return 0, err return 0, err
} }
if r.currentResponse.StatusCode == 416 && r.lastRange == r.totalSize && r.currentResponse.ContentLength == 0 { if r.currentResponse.StatusCode == http.StatusRequestedRangeNotSatisfiable && r.lastRange == r.totalSize && r.currentResponse.ContentLength == 0 {
r.cleanUpResponse() r.cleanUpResponse()
return 0, io.EOF return 0, io.EOF
} else if r.currentResponse.StatusCode != 206 && r.lastRange != 0 && isFreshRequest { } else if r.currentResponse.StatusCode != http.StatusPartialContent && r.lastRange != 0 && isFreshRequest {
r.cleanUpResponse() r.cleanUpResponse()
return 0, fmt.Errorf("the server doesn't support byte ranges") return 0, fmt.Errorf("the server doesn't support byte ranges")
} }

@ -1,40 +0,0 @@
package registry // import "github.com/docker/docker/registry"
import "net/url"
func (s *DefaultService) lookupV1Endpoints(hostname string) (endpoints []APIEndpoint, err error) {
if hostname == DefaultNamespace || hostname == DefaultV2Registry.Host || hostname == IndexHostname {
return []APIEndpoint{}, nil
}
tlsConfig, err := s.tlsConfig(hostname)
if err != nil {
return nil, err
}
endpoints = []APIEndpoint{
{
URL: &url.URL{
Scheme: "https",
Host: hostname,
},
Version: APIVersion1,
TrimHostname: true,
TLSConfig: tlsConfig,
},
}
if tlsConfig.InsecureSkipVerify {
endpoints = append(endpoints, APIEndpoint{ // or this
URL: &url.URL{
Scheme: "http",
Host: hostname,
},
Version: APIVersion1,
TrimHostname: true,
// used to check if supposed to be secure via InsecureSkipVerify
TLSConfig: tlsConfig,
})
}
return endpoints, nil
}

@ -3,6 +3,7 @@ package registry // import "github.com/docker/docker/registry"
import ( import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
// this is required for some certificates // this is required for some certificates
_ "crypto/sha512" _ "crypto/sha512"
"encoding/hex" "encoding/hex"
@ -132,7 +133,9 @@ func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) {
} }
resp, err := tr.RoundTripper.RoundTrip(req) resp, err := tr.RoundTripper.RoundTrip(req)
if err != nil { if err != nil {
tr.mu.Lock()
delete(tr.modReq, orig) delete(tr.modReq, orig)
tr.mu.Unlock()
return nil, err return nil, err
} }
if len(resp.Header["X-Docker-Token"]) > 0 { if len(resp.Header["X-Docker-Token"]) > 0 {
@ -224,8 +227,8 @@ func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) {
return nil, err return nil, err
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
if res.StatusCode == 401 { if res.StatusCode == http.StatusUnauthorized {
return nil, errcode.ErrorCodeUnauthorized.WithArgs() return nil, errcode.ErrorCodeUnauthorized.WithArgs()
} }
return nil, newJSONError(fmt.Sprintf("Server error: %d trying to fetch remote history for %s", res.StatusCode, imgID), res) return nil, newJSONError(fmt.Sprintf("Server error: %d trying to fetch remote history for %s", res.StatusCode, imgID), res)
@ -247,7 +250,7 @@ func (r *Session) LookupRemoteImage(imgID, registry string) error {
return err return err
} }
res.Body.Close() res.Body.Close()
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
return newJSONError(fmt.Sprintf("HTTP code %d", res.StatusCode), res) return newJSONError(fmt.Sprintf("HTTP code %d", res.StatusCode), res)
} }
return nil return nil
@ -260,7 +263,7 @@ func (r *Session) GetRemoteImageJSON(imgID, registry string) ([]byte, int64, err
return nil, -1, fmt.Errorf("Failed to download json: %s", err) return nil, -1, fmt.Errorf("Failed to download json: %s", err)
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
return nil, -1, newJSONError(fmt.Sprintf("HTTP code %d", res.StatusCode), res) return nil, -1, newJSONError(fmt.Sprintf("HTTP code %d", res.StatusCode), res)
} }
// if the size header is not present, then set it to '-1' // if the size header is not present, then set it to '-1'
@ -288,7 +291,7 @@ func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io
imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID) imageURL = fmt.Sprintf("%simages/%s/layer", registry, imgID)
) )
req, err := http.NewRequest("GET", imageURL, nil) req, err := http.NewRequest(http.MethodGet, imageURL, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error while getting from the server: %v", err) return nil, fmt.Errorf("Error while getting from the server: %v", err)
} }
@ -307,7 +310,7 @@ func (r *Session) GetRemoteImageLayer(imgID, registry string, imgSize int64) (io
statusCode, imgID) statusCode, imgID)
} }
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
res.Body.Close() res.Body.Close()
return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)", return nil, fmt.Errorf("Server error: Status %d while fetching image layer (%s)",
res.StatusCode, imgID) res.StatusCode, imgID)
@ -346,7 +349,7 @@ func (r *Session) GetRemoteTag(registries []string, repositoryRef reference.Name
if res.StatusCode == 404 { if res.StatusCode == 404 {
return "", ErrRepoNotFound return "", ErrRepoNotFound
} }
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
continue continue
} }
@ -384,7 +387,7 @@ func (r *Session) GetRemoteTags(registries []string, repositoryRef reference.Nam
if res.StatusCode == 404 { if res.StatusCode == 404 {
return nil, ErrRepoNotFound return nil, ErrRepoNotFound
} }
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
continue continue
} }
@ -422,7 +425,7 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro
logrus.Debugf("[registry] Calling GET %s", repositoryTarget) logrus.Debugf("[registry] Calling GET %s", repositoryTarget)
req, err := http.NewRequest("GET", repositoryTarget, nil) req, err := http.NewRequest(http.MethodGet, repositoryTarget, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -440,14 +443,14 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro
return nil, fmt.Errorf("Error while pulling image: %v", err) return nil, fmt.Errorf("Error while pulling image: %v", err)
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode == 401 { if res.StatusCode == http.StatusUnauthorized {
return nil, errcode.ErrorCodeUnauthorized.WithArgs() return nil, errcode.ErrorCodeUnauthorized.WithArgs()
} }
// TODO: Right now we're ignoring checksums in the response body. // TODO: Right now we're ignoring checksums in the response body.
// In the future, we need to use them to check image validity. // In the future, we need to use them to check image validity.
if res.StatusCode == 404 { if res.StatusCode == 404 {
return nil, newJSONError(fmt.Sprintf("HTTP code: %d", res.StatusCode), res) return nil, newJSONError(fmt.Sprintf("HTTP code: %d", res.StatusCode), res)
} else if res.StatusCode != 200 { } else if res.StatusCode != http.StatusOK {
errBody, err := ioutil.ReadAll(res.Body) errBody, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
logrus.Debugf("Error reading response body: %s", err) logrus.Debugf("Error reading response body: %s", err)
@ -489,7 +492,7 @@ func (r *Session) PushImageChecksumRegistry(imgData *ImgData, registry string) e
logrus.Debugf("[registry] Calling PUT %s", u) logrus.Debugf("[registry] Calling PUT %s", u)
req, err := http.NewRequest("PUT", u, nil) req, err := http.NewRequest(http.MethodPut, u, nil)
if err != nil { if err != nil {
return err return err
} }
@ -504,7 +507,7 @@ func (r *Session) PushImageChecksumRegistry(imgData *ImgData, registry string) e
if len(res.Cookies()) > 0 { if len(res.Cookies()) > 0 {
r.client.Jar.SetCookies(req.URL, res.Cookies()) r.client.Jar.SetCookies(req.URL, res.Cookies())
} }
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
errBody, err := ioutil.ReadAll(res.Body) errBody, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
return fmt.Errorf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err) return fmt.Errorf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err)
@ -527,7 +530,7 @@ func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regist
logrus.Debugf("[registry] Calling PUT %s", u) logrus.Debugf("[registry] Calling PUT %s", u)
req, err := http.NewRequest("PUT", u, bytes.NewReader(jsonRaw)) req, err := http.NewRequest(http.MethodPut, u, bytes.NewReader(jsonRaw))
if err != nil { if err != nil {
return err return err
} }
@ -538,10 +541,10 @@ func (r *Session) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, regist
return fmt.Errorf("Failed to upload metadata: %s", err) return fmt.Errorf("Failed to upload metadata: %s", err)
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode == 401 && strings.HasPrefix(registry, "http://") { if res.StatusCode == http.StatusUnauthorized && strings.HasPrefix(registry, "http://") {
return newJSONError("HTTP code 401, Docker will not send auth headers over HTTP.", res) return newJSONError("HTTP code 401, Docker will not send auth headers over HTTP.", res)
} }
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
errBody, err := ioutil.ReadAll(res.Body) errBody, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
return newJSONError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res) return newJSONError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res)
@ -572,7 +575,7 @@ func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry
h.Write([]byte{'\n'}) h.Write([]byte{'\n'})
checksumLayer := io.TeeReader(tarsumLayer, h) checksumLayer := io.TeeReader(tarsumLayer, h)
req, err := http.NewRequest("PUT", u, checksumLayer) req, err := http.NewRequest(http.MethodPut, u, checksumLayer)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -590,7 +593,7 @@ func (r *Session) PushImageLayerRegistry(imgID string, layer io.Reader, registry
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
errBody, err := ioutil.ReadAll(res.Body) errBody, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
return "", "", newJSONError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res) return "", "", newJSONError(fmt.Sprintf("HTTP code %d while uploading metadata and error when trying to parse response body: %s", res.StatusCode, err), res)
@ -609,7 +612,7 @@ func (r *Session) PushRegistryTag(remote reference.Named, revision, tag, registr
revision = "\"" + revision + "\"" revision = "\"" + revision + "\""
path := fmt.Sprintf("repositories/%s/tags/%s", reference.Path(remote), tag) path := fmt.Sprintf("repositories/%s/tags/%s", reference.Path(remote), tag)
req, err := http.NewRequest("PUT", registry+path, strings.NewReader(revision)) req, err := http.NewRequest(http.MethodPut, registry+path, strings.NewReader(revision))
if err != nil { if err != nil {
return err return err
} }
@ -620,7 +623,7 @@ func (r *Session) PushRegistryTag(remote reference.Named, revision, tag, registr
return err return err
} }
res.Body.Close() res.Body.Close()
if res.StatusCode != 200 && res.StatusCode != 201 { if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusCreated {
return newJSONError(fmt.Sprintf("Internal server error: %d trying to push tag %s on %s", res.StatusCode, tag, reference.Path(remote)), res) return newJSONError(fmt.Sprintf("Internal server error: %d trying to push tag %s on %s", res.StatusCode, tag, reference.Path(remote)), res)
} }
return nil return nil
@ -674,13 +677,13 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode == 401 { if res.StatusCode == http.StatusUnauthorized {
return nil, errcode.ErrorCodeUnauthorized.WithArgs() return nil, errcode.ErrorCodeUnauthorized.WithArgs()
} }
var tokens, endpoints []string var tokens, endpoints []string
if !validate { if !validate {
if res.StatusCode != 200 && res.StatusCode != 201 { if res.StatusCode != http.StatusOK && res.StatusCode != http.StatusCreated {
errBody, err := ioutil.ReadAll(res.Body) errBody, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
logrus.Debugf("Error reading response body: %s", err) logrus.Debugf("Error reading response body: %s", err)
@ -698,7 +701,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
return nil, err return nil, err
} }
} else { } else {
if res.StatusCode != 204 { if res.StatusCode != http.StatusNoContent {
errBody, err := ioutil.ReadAll(res.Body) errBody, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
logrus.Debugf("Error reading response body: %s", err) logrus.Debugf("Error reading response body: %s", err)
@ -713,7 +716,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData,
} }
func (r *Session) putImageRequest(u string, headers map[string][]string, body []byte) (*http.Response, error) { func (r *Session) putImageRequest(u string, headers map[string][]string, body []byte) (*http.Response, error) {
req, err := http.NewRequest("PUT", u, bytes.NewReader(body)) req, err := http.NewRequest(http.MethodPut, u, bytes.NewReader(body))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -740,7 +743,7 @@ func (r *Session) SearchRepositories(term string, limit int) (*registrytypes.Sea
logrus.Debugf("Index server: %s", r.indexEndpoint) logrus.Debugf("Index server: %s", r.indexEndpoint)
u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit)) u := r.indexEndpoint.String() + "search?q=" + url.QueryEscape(term) + "&n=" + url.QueryEscape(fmt.Sprintf("%d", limit))
req, err := http.NewRequest("GET", u, nil) req, err := http.NewRequest(http.MethodGet, u, nil)
if err != nil { if err != nil {
return nil, errors.Wrap(errdefs.InvalidParameter(err), "Error building request") return nil, errors.Wrap(errdefs.InvalidParameter(err), "Error building request")
} }
@ -751,7 +754,7 @@ func (r *Session) SearchRepositories(term string, limit int) (*registrytypes.Sea
return nil, errdefs.System(err) return nil, errdefs.System(err)
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode != 200 { if res.StatusCode != http.StatusOK {
return nil, newJSONError(fmt.Sprintf("Unexpected status code %d", res.StatusCode), res) return nil, newJSONError(fmt.Sprintf("Unexpected status code %d", res.StatusCode), res)
} }
result := new(registrytypes.SearchResults) result := new(registrytypes.SearchResults)

@ -0,0 +1,25 @@
package rootless // import "github.com/docker/docker/rootless"
import (
"os"
"sync"
)
const (
// RootlessKitDockerProxyBinary is the binary name of rootlesskit-docker-proxy
RootlessKitDockerProxyBinary = "rootlesskit-docker-proxy"
)
var (
runningWithRootlessKit bool
runningWithRootlessKitOnce sync.Once
)
// RunningWithRootlessKit returns true if running under RootlessKit namespaces.
func RunningWithRootlessKit() bool {
runningWithRootlessKitOnce.Do(func() {
u := os.Getenv("ROOTLESSKIT_STATE_DIR")
runningWithRootlessKit = u != ""
})
return runningWithRootlessKit
}

@ -0,0 +1,17 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
#include "textflag.h"
//
// System calls for ppc64, AIX are implemented in runtime/syscall_aix.go
//
TEXT ·syscall6(SB),NOSPLIT,$0-88
JMP syscall·syscall6(SB)
TEXT ·rawSyscall6(SB),NOSPLIT,$0-88
JMP syscall·rawSyscall6(SB)

@ -5,26 +5,56 @@
package cpu package cpu
import ( import (
"encoding/binary"
"runtime" "runtime"
) )
// byteOrder is a subset of encoding/binary.ByteOrder.
type byteOrder interface {
Uint32([]byte) uint32
Uint64([]byte) uint64
}
type littleEndian struct{}
type bigEndian struct{}
func (littleEndian) Uint32(b []byte) uint32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
func (littleEndian) Uint64(b []byte) uint64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}
func (bigEndian) Uint32(b []byte) uint32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}
func (bigEndian) Uint64(b []byte) uint64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
}
// hostByteOrder returns binary.LittleEndian on little-endian machines and // hostByteOrder returns binary.LittleEndian on little-endian machines and
// binary.BigEndian on big-endian machines. // binary.BigEndian on big-endian machines.
func hostByteOrder() binary.ByteOrder { func hostByteOrder() byteOrder {
switch runtime.GOARCH { switch runtime.GOARCH {
case "386", "amd64", "amd64p32", case "386", "amd64", "amd64p32",
"arm", "arm64", "arm", "arm64",
"mipsle", "mips64le", "mips64p32le", "mipsle", "mips64le", "mips64p32le",
"ppc64le", "ppc64le",
"riscv", "riscv64": "riscv", "riscv64":
return binary.LittleEndian return littleEndian{}
case "armbe", "arm64be", case "armbe", "arm64be",
"mips", "mips64", "mips64p32", "mips", "mips64", "mips64p32",
"ppc", "ppc64", "ppc", "ppc64",
"s390", "s390x", "s390", "s390x",
"sparc", "sparc64": "sparc", "sparc64":
return binary.BigEndian return bigEndian{}
} }
panic("unknown architecture") panic("unknown architecture")
} }

@ -78,6 +78,42 @@ var ARM64 struct {
_ CacheLinePad _ CacheLinePad
} }
// ARM contains the supported CPU features of the current ARM (32-bit) platform.
// All feature flags are false if:
// 1. the current platform is not arm, or
// 2. the current operating system is not Linux.
var ARM struct {
_ CacheLinePad
HasSWP bool // SWP instruction support
HasHALF bool // Half-word load and store support
HasTHUMB bool // ARM Thumb instruction set
Has26BIT bool // Address space limited to 26-bits
HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support
HasFPA bool // Floating point arithmetic support
HasVFP bool // Vector floating point support
HasEDSP bool // DSP Extensions support
HasJAVA bool // Java instruction set
HasIWMMXT bool // Intel Wireless MMX technology support
HasCRUNCH bool // MaverickCrunch context switching and handling
HasTHUMBEE bool // Thumb EE instruction set
HasNEON bool // NEON instruction set
HasVFPv3 bool // Vector floating point version 3 support
HasVFPv3D16 bool // Vector floating point version 3 D8-D15
HasTLS bool // Thread local storage support
HasVFPv4 bool // Vector floating point version 4 support
HasIDIVA bool // Integer divide instruction support in ARM mode
HasIDIVT bool // Integer divide instruction support in Thumb mode
HasVFPD32 bool // Vector floating point version 3 D15-D31
HasLPAE bool // Large Physical Address Extensions
HasEVTSTRM bool // Event stream support
HasAES bool // AES hardware implementation
HasPMULL bool // Polynomial multiplication instruction set
HasSHA1 bool // SHA1 hardware implementation
HasSHA2 bool // SHA2 hardware implementation
HasCRC32 bool // CRC32 hardware implementation
_ CacheLinePad
}
// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms. // PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms.
// If the current platform is not ppc64/ppc64le then all feature flags are false. // If the current platform is not ppc64/ppc64le then all feature flags are false.
// //

@ -6,8 +6,6 @@
package cpu package cpu
import "golang.org/x/sys/unix"
const cacheLineSize = 128 const cacheLineSize = 128
const ( const (
@ -18,7 +16,7 @@ const (
) )
func init() { func init() {
impl := unix.Getsystemcfg(_SC_IMPL) impl := getsystemcfg(_SC_IMPL)
if impl&_IMPL_POWER8 != 0 { if impl&_IMPL_POWER8 != 0 {
PPC64.IsPOWER8 = true PPC64.IsPOWER8 = true
} }
@ -28,3 +26,9 @@ func init() {
Initialized = true Initialized = true
} }
func getsystemcfg(label int) (n uint64) {
r0, _ := callgetsystemcfg(label)
n = uint64(r0)
return
}

@ -6,4 +6,35 @@ package cpu
const cacheLineSize = 32 const cacheLineSize = 32
func doinit() {} // HWCAP/HWCAP2 bits.
// These are specific to Linux.
const (
hwcap_SWP = 1 << 0
hwcap_HALF = 1 << 1
hwcap_THUMB = 1 << 2
hwcap_26BIT = 1 << 3
hwcap_FAST_MULT = 1 << 4
hwcap_FPA = 1 << 5
hwcap_VFP = 1 << 6
hwcap_EDSP = 1 << 7
hwcap_JAVA = 1 << 8
hwcap_IWMMXT = 1 << 9
hwcap_CRUNCH = 1 << 10
hwcap_THUMBEE = 1 << 11
hwcap_NEON = 1 << 12
hwcap_VFPv3 = 1 << 13
hwcap_VFPv3D16 = 1 << 14
hwcap_TLS = 1 << 15
hwcap_VFPv4 = 1 << 16
hwcap_IDIVA = 1 << 17
hwcap_IDIVT = 1 << 18
hwcap_VFPD32 = 1 << 19
hwcap_LPAE = 1 << 20
hwcap_EVTSTRM = 1 << 21
hwcap2_AES = 1 << 0
hwcap2_PMULL = 1 << 1
hwcap2_SHA1 = 1 << 2
hwcap2_SHA2 = 1 << 3
hwcap2_CRC32 = 1 << 4
)

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//+build !amd64,!amd64p32,!386 // +build !amd64,!amd64p32,!386
package cpu package cpu

@ -0,0 +1,39 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cpu
func doinit() {
ARM.HasSWP = isSet(hwCap, hwcap_SWP)
ARM.HasHALF = isSet(hwCap, hwcap_HALF)
ARM.HasTHUMB = isSet(hwCap, hwcap_THUMB)
ARM.Has26BIT = isSet(hwCap, hwcap_26BIT)
ARM.HasFASTMUL = isSet(hwCap, hwcap_FAST_MULT)
ARM.HasFPA = isSet(hwCap, hwcap_FPA)
ARM.HasVFP = isSet(hwCap, hwcap_VFP)
ARM.HasEDSP = isSet(hwCap, hwcap_EDSP)
ARM.HasJAVA = isSet(hwCap, hwcap_JAVA)
ARM.HasIWMMXT = isSet(hwCap, hwcap_IWMMXT)
ARM.HasCRUNCH = isSet(hwCap, hwcap_CRUNCH)
ARM.HasTHUMBEE = isSet(hwCap, hwcap_THUMBEE)
ARM.HasNEON = isSet(hwCap, hwcap_NEON)
ARM.HasVFPv3 = isSet(hwCap, hwcap_VFPv3)
ARM.HasVFPv3D16 = isSet(hwCap, hwcap_VFPv3D16)
ARM.HasTLS = isSet(hwCap, hwcap_TLS)
ARM.HasVFPv4 = isSet(hwCap, hwcap_VFPv4)
ARM.HasIDIVA = isSet(hwCap, hwcap_IDIVA)
ARM.HasIDIVT = isSet(hwCap, hwcap_IDIVT)
ARM.HasVFPD32 = isSet(hwCap, hwcap_VFPD32)
ARM.HasLPAE = isSet(hwCap, hwcap_LPAE)
ARM.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM)
ARM.HasAES = isSet(hwCap2, hwcap2_AES)
ARM.HasPMULL = isSet(hwCap2, hwcap2_PMULL)
ARM.HasSHA1 = isSet(hwCap2, hwcap2_SHA1)
ARM.HasSHA2 = isSet(hwCap2, hwcap2_SHA2)
ARM.HasCRC32 = isSet(hwCap2, hwcap2_CRC32)
}
func isSet(hwc uint, value uint) bool {
return hwc&value != 0
}

@ -0,0 +1,9 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux,!arm,!arm64,!ppc64,!ppc64le,!s390x
package cpu
func doinit() {}

@ -7,5 +7,3 @@
package cpu package cpu
const cacheLineSize = 32 const cacheLineSize = 32
func doinit() {}

@ -7,5 +7,3 @@
package cpu package cpu
const cacheLineSize = 32 const cacheLineSize = 32
func doinit() {}

@ -7,5 +7,3 @@
package cpu package cpu
const cacheLineSize = 64 const cacheLineSize = 64
func doinit() {}

@ -0,0 +1,9 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build riscv64
package cpu
const cacheLineSize = 32

@ -11,5 +11,3 @@ package cpu
// rules are good enough. // rules are good enough.
const cacheLineSize = 0 const cacheLineSize = 0
func doinit() {}

@ -0,0 +1,36 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Minimal copy of x/sys/unix so the cpu package can make a
// system call on AIX without depending on x/sys/unix.
// (See golang.org/issue/32102)
// +build aix,ppc64
// +build !gccgo
package cpu
import (
"syscall"
"unsafe"
)
//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o"
//go:linkname libc_getsystemcfg libc_getsystemcfg
type syscallFunc uintptr
var libc_getsystemcfg syscallFunc
type errno = syscall.Errno
// Implemented in runtime/syscall_aix.go.
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno)
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno)
func callgetsystemcfg(label int) (r1 uintptr, e1 errno) {
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsystemcfg)), 1, uintptr(label), 0, 0, 0, 0, 0)
return
}

@ -7,6 +7,7 @@
package unix package unix
import ( import (
"math/bits"
"unsafe" "unsafe"
) )
@ -79,46 +80,7 @@ func (s *CPUSet) IsSet(cpu int) bool {
func (s *CPUSet) Count() int { func (s *CPUSet) Count() int {
c := 0 c := 0
for _, b := range s { for _, b := range s {
c += onesCount64(uint64(b)) c += bits.OnesCount64(uint64(b))
} }
return c return c
} }
// onesCount64 is a copy of Go 1.9's math/bits.OnesCount64.
// Once this package can require Go 1.9, we can delete this
// and update the caller to use bits.OnesCount64.
func onesCount64(x uint64) int {
const m0 = 0x5555555555555555 // 01010101 ...
const m1 = 0x3333333333333333 // 00110011 ...
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
const m3 = 0x00ff00ff00ff00ff // etc.
const m4 = 0x0000ffff0000ffff
// Implementation: Parallel summing of adjacent bits.
// See "Hacker's Delight", Chap. 5: Counting Bits.
// The following pattern shows the general approach:
//
// x = x>>1&(m0&m) + x&(m0&m)
// x = x>>2&(m1&m) + x&(m1&m)
// x = x>>4&(m2&m) + x&(m2&m)
// x = x>>8&(m3&m) + x&(m3&m)
// x = x>>16&(m4&m) + x&(m4&m)
// x = x>>32&(m5&m) + x&(m5&m)
// return int(x)
//
// Masking (& operations) can be left away when there's no
// danger that a field's sum will carry over into the next
// field: Since the result cannot be > 64, 8 bits is enough
// and we can ignore the masks for the shifts by 8 and up.
// Per "Hacker's Delight", the first line can be simplified
// more, but it saves at best one instruction, so we leave
// it alone for clarity.
const m = 1<<64 - 1
x = x>>1&(m0&m) + x&(m0&m)
x = x>>2&(m1&m) + x&(m1&m)
x = (x>>4 + x) & (m2 & m)
x += x >> 8
x += x >> 16
x += x >> 32
return int(x) & (1<<7 - 1)
}

@ -0,0 +1,54 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build riscv64,!gccgo
#include "textflag.h"
//
// System calls for linux/riscv64.
//
// Where available, just jump to package syscall's implementation of
// these functions.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
CALL runtime·entersyscall(SB)
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV $0, A3
MOV $0, A4
MOV $0, A5
MOV $0, A6
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP) // r1
MOV A1, r2+40(FP) // r2
CALL runtime·exitsyscall(SB)
RET
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)
TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
MOV a1+8(FP), A0
MOV a2+16(FP), A1
MOV a3+24(FP), A2
MOV ZERO, A3
MOV ZERO, A4
MOV ZERO, A5
MOV trap+0(FP), A7 // syscall entry
ECALL
MOV A0, r1+32(FP)
MOV A1, r2+40(FP)
RET

@ -0,0 +1,29 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
#include "textflag.h"
//
// System call support for arm64, OpenBSD
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-104
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
JMP syscall·RawSyscall6(SB)

@ -23,6 +23,7 @@ const (
HCI_CHANNEL_USER = 1 HCI_CHANNEL_USER = 1
HCI_CHANNEL_MONITOR = 2 HCI_CHANNEL_MONITOR = 2
HCI_CHANNEL_CONTROL = 3 HCI_CHANNEL_CONTROL = 3
HCI_CHANNEL_LOGGING = 4
) )
// Socketoption Level // Socketoption Level

@ -2,16 +2,101 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package unix package unix
import "syscall" import "unsafe"
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
if len(b) < int(off+size) {
return 0, false
}
if isBigEndian {
return readIntBE(b[off:], size), true
}
return readIntLE(b[off:], size), true
}
func readIntBE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[1]) | uint64(b[0])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
func readIntLE(b []byte, size uintptr) uint64 {
switch size {
case 1:
return uint64(b[0])
case 2:
_ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8
case 4:
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
case 8:
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
default:
panic("syscall: readInt with unsupported size")
}
}
// ParseDirent parses up to max directory entries in buf, // ParseDirent parses up to max directory entries in buf,
// appending the names to names. It returns the number of // appending the names to names. It returns the number of
// bytes consumed from buf, the number of entries added // bytes consumed from buf, the number of entries added
// to names, and the new names slice. // to names, and the new names slice.
func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) { func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
return syscall.ParseDirent(buf, max, names) origlen := len(buf)
count = 0
for max != 0 && len(buf) > 0 {
reclen, ok := direntReclen(buf)
if !ok || reclen > uint64(len(buf)) {
return origlen, count, names
}
rec := buf[:reclen]
buf = buf[reclen:]
ino, ok := direntIno(rec)
if !ok {
break
}
if ino == 0 { // File absent in directory.
continue
}
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
namlen, ok := direntNamlen(rec)
if !ok || namoff+namlen > uint64(len(rec)) {
break
}
name := rec[namoff : namoff+namlen]
for i, c := range name {
if c == 0 {
name = name[:i]
break
}
}
// Check for useless names before allocating a string.
if string(name) == "." || string(name) == ".." {
continue
}
max--
count++
names = append(names, string(name))
}
return origlen - len(buf), count, names
} }

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// //
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le // +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64
package unix package unix

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save