Commit 48eb3d81 authored by loganhz's avatar loganhz

Update docker vendor

parent b7ec43c9
...@@ -16,6 +16,7 @@ replace ( ...@@ -16,6 +16,7 @@ replace (
github.com/coreos/flannel => github.com/rancher/flannel v0.11.0-k3s.1 github.com/coreos/flannel => github.com/rancher/flannel v0.11.0-k3s.1
github.com/coreos/go-systemd => github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e github.com/coreos/go-systemd => github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
github.com/docker/distribution => github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154 github.com/docker/distribution => github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154
github.com/docker/docker => github.com/docker/docker v17.12.0-ce-rc1.0.20190219214528-cbe11bdc6da8+incompatible
github.com/docker/libnetwork => github.com/docker/libnetwork v0.8.0-dev.2.0.20190624125649-f0e46a78ea34 github.com/docker/libnetwork => github.com/docker/libnetwork v0.8.0-dev.2.0.20190624125649-f0e46a78ea34
github.com/go-critic/go-critic => github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540 github.com/go-critic/go-critic => github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540
github.com/golangci/errcheck => github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 github.com/golangci/errcheck => github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6
......
...@@ -53,6 +53,7 @@ github.com/Microsoft/hcsshim v0.8.7-0.20190926181021-82c7525d98c8/go.mod h1:1+Au ...@@ -53,6 +53,7 @@ github.com/Microsoft/hcsshim v0.8.7-0.20190926181021-82c7525d98c8/go.mod h1:1+Au
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o=
github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM=
...@@ -200,6 +201,14 @@ github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154/go.mod h1:J2gT ...@@ -200,6 +201,14 @@ github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154/go.mod h1:J2gT
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20191205034852-d163fbba3c82 h1:kf0UYG15U+KsO7mA8Lsz+OkuoC1Ldc+cTQUyUnAFmg8= github.com/docker/docker v1.4.2-0.20191205034852-d163fbba3c82 h1:kf0UYG15U+KsO7mA8Lsz+OkuoC1Ldc+cTQUyUnAFmg8=
github.com/docker/docker v1.4.2-0.20191205034852-d163fbba3c82/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20191205034852-d163fbba3c82/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20200309214505-aa6a9891b09c h1:zviRyz1SWO8+WVJbi9/jlJCkrsZ54r/lTRbgtcaQhLs=
github.com/docker/docker v1.4.2-0.20200309214505-aa6a9891b09c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v17.12.0-ce-rc1.0.20190219214528-cbe11bdc6da8+incompatible h1:ZZvtagdntE3LlHuNFoj0r5nVFllfu6Mn413hOu01cZI=
github.com/docker/docker v17.12.0-ce-rc1.0.20190219214528-cbe11bdc6da8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v17.12.0-ce-rc1.0.20190327010347-be7ac8be2ae0+incompatible h1:OGKd8UInXYNzUc+SgqizkHsPoIYJp7+rc5+HcYrWfqs=
github.com/docker/docker v17.12.0-ce-rc1.0.20190327010347-be7ac8be2ae0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible h1:G2hY8RD7jB9QaSmcb8mYEIg8QbEvVAB7se8+lXHZHfg=
github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
......
package osversion
import (
"fmt"
"golang.org/x/sys/windows"
)
// OSVersion is a wrapper for Windows version information
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
type OSVersion struct {
Version uint32
MajorVersion uint8
MinorVersion uint8
Build uint16
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
type osVersionInfoEx struct {
OSVersionInfoSize uint32
MajorVersion uint32
MinorVersion uint32
BuildNumber uint32
PlatformID uint32
CSDVersion [128]uint16
ServicePackMajor uint16
ServicePackMinor uint16
SuiteMask uint16
ProductType byte
Reserve byte
}
// Get gets the operating system version on Windows.
// The calling application must be manifested to get the correct version information.
func Get() OSVersion {
var err error
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
}
// Build gets the build-number on Windows
// The calling application must be manifested to get the correct version information.
func Build() uint16 {
return Get().Build
}
func (osv OSVersion) ToString() string {
return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build)
}
package osversion
const (
// RS1 (version 1607, codename "Redstone 1") corresponds to Windows Server
// 2016 (ltsc2016) and Windows 10 (Anniversary Update).
RS1 = 14393
// RS2 (version 1703, codename "Redstone 2") was a client-only update, and
// corresponds to Windows 10 (Creators Update).
RS2 = 15063
// RS3 (version 1709, codename "Redstone 3") corresponds to Windows Server
// 1709 (Semi-Annual Channel (SAC)), and Windows 10 (Fall Creators Update).
RS3 = 16299
// RS4 (version 1803, codename "Redstone 4") corresponds to Windows Server
// 1803 (Semi-Annual Channel (SAC)), and Windows 10 (April 2018 Update).
RS4 = 17134
// RS5 (version 1809, codename "Redstone 5") corresponds to Windows Server
// 2019 (ltsc2019), and Windows 10 (October 2018 Update).
RS5 = 17763
// V19H1 (version 1903) corresponds to Windows Sever 1903 (semi-annual
// channel).
V19H1 = 18362
)
Copyright (c) 2012, Neal van Veen (nealvanveen@gmail.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
Gotty is a library written in Go that determines and reads termcap database
files to produce an interface for interacting with the capabilities of a
terminal.
See the godoc documentation or the source code for more information about
function usage.
gotty.go:// TODO add more concurrency to name lookup, look for more opportunities.
all:// TODO add more documentation, with function usage in a doc.go file.
all:// TODO add more testing/benchmarking with go test.
// Copyright 2012 Neal van Veen. All rights reserved.
// Usage of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Gotty is a Go-package for reading and parsing the terminfo database
package gotty
// TODO add more concurrency to name lookup, look for more opportunities.
import (
"encoding/binary"
"errors"
"fmt"
"os"
"reflect"
"strings"
"sync"
)
// Open a terminfo file by the name given and construct a TermInfo object.
// If something went wrong reading the terminfo database file, an error is
// returned.
func OpenTermInfo(termName string) (*TermInfo, error) {
var term *TermInfo
var err error
// Find the environment variables
termloc := os.Getenv("TERMINFO")
if len(termloc) == 0 {
// Search like ncurses
locations := []string{os.Getenv("HOME") + "/.terminfo/", "/etc/terminfo/",
"/lib/terminfo/", "/usr/share/terminfo/"}
var path string
for _, str := range locations {
// Construct path
path = str + string(termName[0]) + "/" + termName
// Check if path can be opened
file, _ := os.Open(path)
if file != nil {
// Path can open, fall out and use current path
file.Close()
break
}
}
if len(path) > 0 {
term, err = readTermInfo(path)
} else {
err = errors.New(fmt.Sprintf("No terminfo file(-location) found"))
}
}
return term, err
}
// Open a terminfo file from the environment variable containing the current
// terminal name and construct a TermInfo object. If something went wrong
// reading the terminfo database file, an error is returned.
func OpenTermInfoEnv() (*TermInfo, error) {
termenv := os.Getenv("TERM")
return OpenTermInfo(termenv)
}
// Return an attribute by the name attr provided. If none can be found,
// an error is returned.
func (term *TermInfo) GetAttribute(attr string) (stacker, error) {
// Channel to store the main value in.
var value stacker
// Add a blocking WaitGroup
var block sync.WaitGroup
// Keep track of variable being written.
written := false
// Function to put into goroutine.
f := func(ats interface{}) {
var ok bool
var v stacker
// Switch on type of map to use and assign value to it.
switch reflect.TypeOf(ats).Elem().Kind() {
case reflect.Bool:
v, ok = ats.(map[string]bool)[attr]
case reflect.Int16:
v, ok = ats.(map[string]int16)[attr]
case reflect.String:
v, ok = ats.(map[string]string)[attr]
}
// If ok, a value is found, so we can write.
if ok {
value = v
written = true
}
// Goroutine is done
block.Done()
}
block.Add(3)
// Go for all 3 attribute lists.
go f(term.boolAttributes)
go f(term.numAttributes)
go f(term.strAttributes)
// Wait until every goroutine is done.
block.Wait()
// If a value has been written, return it.
if written {
return value, nil
}
// Otherwise, error.
return nil, fmt.Errorf("Erorr finding attribute")
}
// Return an attribute by the name attr provided. If none can be found,
// an error is returned. A name is first converted to its termcap value.
func (term *TermInfo) GetAttributeName(name string) (stacker, error) {
tc := GetTermcapName(name)
return term.GetAttribute(tc)
}
// A utility function that finds and returns the termcap equivalent of a
// variable name.
func GetTermcapName(name string) string {
// Termcap name
var tc string
// Blocking group
var wait sync.WaitGroup
// Function to put into a goroutine
f := func(attrs []string) {
// Find the string corresponding to the name
for i, s := range attrs {
if s == name {
tc = attrs[i+1]
}
}
// Goroutine is finished
wait.Done()
}
wait.Add(3)
// Go for all 3 attribute lists
go f(BoolAttr[:])
go f(NumAttr[:])
go f(StrAttr[:])
// Wait until every goroutine is done
wait.Wait()
// Return the termcap name
return tc
}
// This function takes a path to a terminfo file and reads it in binary
// form to construct the actual TermInfo file.
func readTermInfo(path string) (*TermInfo, error) {
// Open the terminfo file
file, err := os.Open(path)
defer file.Close()
if err != nil {
return nil, err
}
// magic, nameSize, boolSize, nrSNum, nrOffsetsStr, strSize
// Header is composed of the magic 0432 octal number, size of the name
// section, size of the boolean section, the amount of number values,
// the number of offsets of strings, and the size of the string section.
var header [6]int16
// Byte array is used to read in byte values
var byteArray []byte
// Short array is used to read in short values
var shArray []int16
// TermInfo object to store values
var term TermInfo
// Read in the header
err = binary.Read(file, binary.LittleEndian, &header)
if err != nil {
return nil, err
}
// If magic number isn't there or isn't correct, we have the wrong filetype
if header[0] != 0432 {
return nil, errors.New(fmt.Sprintf("Wrong filetype"))
}
// Read in the names
byteArray = make([]byte, header[1])
err = binary.Read(file, binary.LittleEndian, &byteArray)
if err != nil {
return nil, err
}
term.Names = strings.Split(string(byteArray), "|")
// Read in the booleans
byteArray = make([]byte, header[2])
err = binary.Read(file, binary.LittleEndian, &byteArray)
if err != nil {
return nil, err
}
term.boolAttributes = make(map[string]bool)
for i, b := range byteArray {
if b == 1 {
term.boolAttributes[BoolAttr[i*2+1]] = true
}
}
// If the number of bytes read is not even, a byte for alignment is added
if len(byteArray)%2 != 0 {
err = binary.Read(file, binary.LittleEndian, make([]byte, 1))
if err != nil {
return nil, err
}
}
// Read in shorts
shArray = make([]int16, header[3])
err = binary.Read(file, binary.LittleEndian, &shArray)
if err != nil {
return nil, err
}
term.numAttributes = make(map[string]int16)
for i, n := range shArray {
if n != 0377 && n > -1 {
term.numAttributes[NumAttr[i*2+1]] = n
}
}
// Read the offsets into the short array
shArray = make([]int16, header[4])
err = binary.Read(file, binary.LittleEndian, &shArray)
if err != nil {
return nil, err
}
// Read the actual strings in the byte array
byteArray = make([]byte, header[5])
err = binary.Read(file, binary.LittleEndian, &byteArray)
if err != nil {
return nil, err
}
term.strAttributes = make(map[string]string)
// We get an offset, and then iterate until the string is null-terminated
for i, offset := range shArray {
if offset > -1 {
r := offset
for ; byteArray[r] != 0; r++ {
}
term.strAttributes[StrAttr[i*2+1]] = string(byteArray[offset:r])
}
}
return &term, nil
}
// Copyright 2012 Neal van Veen. All rights reserved.
// Usage of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package gotty
type TermInfo struct {
boolAttributes map[string]bool
numAttributes map[string]int16
strAttributes map[string]string
// The various names of the TermInfo file.
Names []string
}
type stacker interface {
}
type stack []stacker
type parser struct {
st stack
parameters []stacker
dynamicVar map[byte]stacker
}
...@@ -176,7 +176,7 @@ ...@@ -176,7 +176,7 @@
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
Copyright 2013-2018 Docker, Inc. Copyright 2013-2017 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
......
...@@ -3,7 +3,7 @@ Copyright 2012-2017 Docker, Inc. ...@@ -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/creack/pty) developed This product contains software (https://github.com/kr/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" ...@@ -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.41" DefaultVersion = "1.38"
// 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.
......
...@@ -187,15 +187,6 @@ type ImageBuildOptions struct { ...@@ -187,15 +187,6 @@ type ImageBuildOptions struct {
// build request. The same identifier can be used to gracefully cancel the // build request. The same identifier can be used to gracefully cancel the
// build with the cancel request. // build with the cancel request.
BuildID string BuildID string
// Outputs defines configurations for exporting build results. Only supported
// in BuildKit mode
Outputs []ImageBuildOutput
}
// ImageBuildOutput defines configuration for exporting a build result
type ImageBuildOutput struct {
Type string
Attrs map[string]string
} }
// BuilderVersion sets the version of underlying builder to use // BuilderVersion sets the version of underlying builder to use
...@@ -363,10 +354,6 @@ type ServiceUpdateOptions struct { ...@@ -363,10 +354,6 @@ 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"
......
...@@ -55,10 +55,3 @@ type PluginEnableConfig struct { ...@@ -55,10 +55,3 @@ type PluginEnableConfig struct {
type PluginDisableConfig struct { type PluginDisableConfig struct {
ForceDisable bool ForceDisable bool
} }
// NetworkListConfig stores the options available for listing networks
type NetworkListConfig struct {
// TODO(@cpuguy83): naming is hard, this is pulled from what was being used in the router before moving here
Detailed bool
Verbose bool
}
...@@ -54,7 +54,7 @@ type Config struct { ...@@ -54,7 +54,7 @@ type Config struct {
Env []string // List of environment variable to set in the container Env []string // List of environment variable to set in the container
Cmd strslice.StrSlice // Command to run when starting the container Cmd strslice.StrSlice // Command to run when starting the container
Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy Healthcheck *HealthConfig `json:",omitempty"` // Healthcheck describes how to check the container is healthy
ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (meaning treat as a command line) (Windows specific). ArgsEscaped bool `json:",omitempty"` // True if command is already escaped (Windows specific)
Image string // Name of the image as it was passed by the operator (e.g. could be symbolic) Image string // Name of the image as it was passed by the operator (e.g. could be symbolic)
Volumes map[string]struct{} // List of volumes (mounts) used for the container Volumes map[string]struct{} // List of volumes (mounts) used for the container
WorkingDir string // Current directory (PWD) in the command will be launched WorkingDir string // Current directory (PWD) in the command will be launched
......
package container // import "github.com/docker/docker/api/types/container" package container
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
package container // import "github.com/docker/docker/api/types/container" package container
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
package container // import "github.com/docker/docker/api/types/container" package container
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
package container // import "github.com/docker/docker/api/types/container" package container
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
package container // import "github.com/docker/docker/api/types/container" package container
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -7,32 +7,9 @@ import ( ...@@ -7,32 +7,9 @@ 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"
units "github.com/docker/go-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
...@@ -267,16 +244,6 @@ func (n PidMode) Container() string { ...@@ -267,16 +244,6 @@ func (n PidMode) Container() string {
return "" return ""
} }
// DeviceRequest represents a request for devices from a device driver.
// Used by GPU device drivers.
type DeviceRequest struct {
Driver string // Name of device driver
Count int // Number of devices to request (-1 = All)
DeviceIDs []string // List of device IDs as recognizable by the device driver
Capabilities [][]string // An OR list of AND lists of device capabilities (e.g. "gpu")
Options map[string]string // Options to pass onto the device driver
}
// DeviceMapping represents the device mapping between the host and the container. // DeviceMapping represents the device mapping between the host and the container.
type DeviceMapping struct { type DeviceMapping struct {
PathOnHost string PathOnHost string
...@@ -360,14 +327,13 @@ type Resources struct { ...@@ -360,14 +327,13 @@ type Resources struct {
CpusetMems string // CpusetMems 0-2, 0,1 CpusetMems string // CpusetMems 0-2, 0,1
Devices []DeviceMapping // List of devices to map inside the container Devices []DeviceMapping // List of devices to map inside the container
DeviceCgroupRules []string // List of rule to be added to the device cgroup DeviceCgroupRules []string // List of rule to be added to the device cgroup
DeviceRequests []DeviceRequest // List of device requests for device drivers DiskQuota int64 // Disk limit (in bytes)
KernelMemory int64 // Kernel memory limit (in bytes) KernelMemory int64 // Kernel memory limit (in bytes)
KernelMemoryTCP int64 // Hard limit for kernel TCP buffer memory (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes) MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
MemorySwappiness *int64 // Tuning container memory swappiness behaviour MemorySwappiness *int64 // Tuning container memory swappiness behaviour
OomKillDisable *bool // Whether to disable OOM Killer or not OomKillDisable *bool // Whether to disable OOM Killer or not
PidsLimit *int64 // Setting PIDs limit for a container; Set `0` or `-1` for unlimited, or `null` to not change. PidsLimit int64 // Setting pids limit for a container
Ulimits []*units.Ulimit // List of ulimits to be set in the container Ulimits []*units.Ulimit // List of ulimits to be set in the container
// Applicable to Windows // Applicable to Windows
...@@ -403,8 +369,6 @@ type HostConfig struct { ...@@ -403,8 +369,6 @@ type HostConfig struct {
// Applicable to UNIX platforms // Applicable to UNIX platforms
CapAdd strslice.StrSlice // List of kernel capabilities to add to the container CapAdd strslice.StrSlice // List of kernel capabilities to add to the container
CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container CapDrop strslice.StrSlice // List of kernel capabilities to remove from the container
Capabilities []string `json:"Capabilities"` // List of kernel capabilities to be available for container (this overrides the default set)
CgroupnsMode CgroupnsMode // Cgroup namespace mode to use for the container
DNS []string `json:"Dns"` // List of DNS server to lookup DNS []string `json:"Dns"` // List of DNS server to lookup
DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for DNSOptions []string `json:"DnsOptions"` // List of DNSOption to look for
DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for DNSSearch []string `json:"DnsSearch"` // List of DNSSearch to look for
......
package types
// Error returns the error message
func (e ErrorResponse) Error() string {
return e.Message
}
...@@ -5,6 +5,7 @@ package filters // import "github.com/docker/docker/api/types/filters" ...@@ -5,6 +5,7 @@ package filters // import "github.com/docker/docker/api/types/filters"
import ( import (
"encoding/json" "encoding/json"
"errors"
"regexp" "regexp"
"strings" "strings"
...@@ -36,13 +37,39 @@ func NewArgs(initialArgs ...KeyValuePair) Args { ...@@ -36,13 +37,39 @@ func NewArgs(initialArgs ...KeyValuePair) Args {
return args return args
} }
// Keys returns all the keys in list of Args // ParseFlag parses a key=value string and adds it to an Args.
func (args Args) Keys() []string { //
keys := make([]string, 0, len(args.fields)) // Deprecated: Use Args.Add()
for k := range args.fields { func ParseFlag(arg string, prev Args) (Args, error) {
keys = append(keys, k) filters := prev
if len(arg) == 0 {
return filters, nil
}
if !strings.Contains(arg, "=") {
return filters, ErrBadFormat
} }
return keys
f := strings.SplitN(arg, "=", 2)
name := strings.ToLower(strings.TrimSpace(f[0]))
value := strings.TrimSpace(f[1])
filters.Add(name, value)
return filters, nil
}
// ErrBadFormat is an error returned when a filter is not in the form key=value
//
// Deprecated: this error will be removed in a future version
var ErrBadFormat = errors.New("bad format of filter (expected name=value)")
// ToParam encodes the Args as args JSON encoded string
//
// Deprecated: use ToJSON
func ToParam(a Args) (string, error) {
return ToJSON(a)
} }
// MarshalJSON returns a JSON byte representation of the Args // MarshalJSON returns a JSON byte representation of the Args
...@@ -66,7 +93,7 @@ func ToJSON(a Args) (string, error) { ...@@ -66,7 +93,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: do not use in any new code; use ToJSON instead // Deprecated: Use ToJSON
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
...@@ -80,6 +107,13 @@ func ToParamWithVersion(version string, a Args) (string, error) { ...@@ -80,6 +107,13 @@ func ToParamWithVersion(version string, a Args) (string, error) {
return ToJSON(a) return ToJSON(a)
} }
// FromParam decodes a JSON encoded string into Args
//
// Deprecated: use FromJSON
func FromParam(p string) (Args, error) {
return FromJSON(p)
}
// FromJSON decodes a JSON encoded string into Args // FromJSON decodes a JSON encoded string into Args
func FromJSON(p string) (Args, error) { func FromJSON(p string) (Args, error) {
args := NewArgs() args := NewArgs()
...@@ -241,6 +275,14 @@ func (args Args) FuzzyMatch(key, source string) bool { ...@@ -241,6 +275,14 @@ func (args Args) FuzzyMatch(key, source string) bool {
return false return false
} }
// Include returns true if the key exists in the mapping
//
// Deprecated: use Contains
func (args Args) Include(field string) bool {
_, ok := args.fields[field]
return ok
}
// Contains returns true if the key exists in the mapping // Contains returns true if the key exists in the mapping
func (args Args) Contains(field string) bool { func (args Args) Contains(field string) bool {
_, ok := args.fields[field] _, ok := args.fields[field]
...@@ -281,22 +323,6 @@ func (args Args) WalkValues(field string, op func(value string) error) error { ...@@ -281,22 +323,6 @@ func (args Args) WalkValues(field string, op func(value string) error) error {
return nil return nil
} }
// Clone returns a copy of args.
func (args Args) Clone() (newArgs Args) {
newArgs.fields = make(map[string]map[string]bool, len(args.fields))
for k, m := range args.fields {
var mm map[string]bool
if m != nil {
mm = make(map[string]bool, len(m))
for kk, v := range m {
mm[kk] = v
}
}
newArgs.fields[k] = mm
}
return newArgs
}
func deprecatedArgs(d map[string][]string) map[string]map[string]bool { func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
m := map[string]map[string]bool{} m := map[string]map[string]bool{}
for k, v := range d { for k, v := range d {
......
package image // import "github.com/docker/docker/api/types/image" package image
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -79,8 +79,7 @@ const ( ...@@ -79,8 +79,7 @@ const (
// BindOptions defines options specific to mounts of type "bind". // BindOptions defines options specific to mounts of type "bind".
type BindOptions struct { type BindOptions struct {
Propagation Propagation `json:",omitempty"` Propagation Propagation `json:",omitempty"`
NonRecursive bool `json:",omitempty"`
} }
// VolumeOptions represents the options for a mount of type volume. // VolumeOptions represents the options for a mount of type volume.
......
package network // import "github.com/docker/docker/api/types/network" package network // import "github.com/docker/docker/api/types/network"
import (
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/errdefs"
)
// Address represents an IP address // Address represents an IP address
type Address struct { type Address struct {
...@@ -110,18 +106,3 @@ type NetworkingConfig struct { ...@@ -110,18 +106,3 @@ type NetworkingConfig struct {
type ConfigReference struct { type ConfigReference struct {
Network string Network string
} }
var acceptedFilters = map[string]bool{
"dangling": true,
"driver": true,
"id": true,
"label": true,
"name": true,
"scope": true,
"type": true,
}
// ValidateFilters validates the list of filter args with the available filters.
func ValidateFilters(filter filters.Args) error {
return errdefs.InvalidParameter(filter.Validate(acceptedFilters))
}
...@@ -4,7 +4,7 @@ import ( ...@@ -4,7 +4,7 @@ import (
"encoding/json" "encoding/json"
"net" "net"
v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/image-spec/specs-go/v1"
) )
// ServiceConfig stores daemon registry services configuration. // ServiceConfig stores daemon registry services configuration.
......
...@@ -77,9 +77,8 @@ type Arg struct { ...@@ -77,9 +77,8 @@ type Arg struct {
// Filter is used to conditionally apply Seccomp rules // Filter is used to conditionally apply Seccomp rules
type Filter struct { type Filter struct {
Caps []string `json:"caps,omitempty"` Caps []string `json:"caps,omitempty"`
Arches []string `json:"arches,omitempty"` Arches []string `json:"arches,omitempty"`
MinKernel string `json:"minKernel,omitempty"`
} }
// Syscall is used to match a group of syscalls in Seccomp // Syscall is used to match a group of syscalls in Seccomp
......
...@@ -120,7 +120,7 @@ type NetworkStats struct { ...@@ -120,7 +120,7 @@ type NetworkStats struct {
RxBytes uint64 `json:"rx_bytes"` RxBytes uint64 `json:"rx_bytes"`
// Packets received. Windows and Linux. // Packets received. Windows and Linux.
RxPackets uint64 `json:"rx_packets"` RxPackets uint64 `json:"rx_packets"`
// Received errors. Not used on Windows. Note that we don't `omitempty` this // Received errors. Not used on Windows. Note that we dont `omitempty` this
// field as it is expected in the >=v1.21 API stats structure. // field as it is expected in the >=v1.21 API stats structure.
RxErrors uint64 `json:"rx_errors"` RxErrors uint64 `json:"rx_errors"`
// Incoming packets dropped. Windows and Linux. // Incoming packets dropped. Windows and Linux.
...@@ -129,7 +129,7 @@ type NetworkStats struct { ...@@ -129,7 +129,7 @@ type NetworkStats struct {
TxBytes uint64 `json:"tx_bytes"` TxBytes uint64 `json:"tx_bytes"`
// Packets sent. Windows and Linux. // Packets sent. Windows and Linux.
TxPackets uint64 `json:"tx_packets"` TxPackets uint64 `json:"tx_packets"`
// Sent errors. Not used on Windows. Note that we don't `omitempty` this // Sent errors. Not used on Windows. Note that we dont `omitempty` this
// field as it is expected in the >=v1.21 API stats structure. // field as it is expected in the >=v1.21 API stats structure.
TxErrors uint64 `json:"tx_errors"` TxErrors uint64 `json:"tx_errors"`
// Outgoing packets dropped. Windows and Linux. // Outgoing packets dropped. Windows and Linux.
......
...@@ -27,14 +27,9 @@ type ConfigReferenceFileTarget struct { ...@@ -27,14 +27,9 @@ type ConfigReferenceFileTarget struct {
Mode os.FileMode Mode os.FileMode
} }
// ConfigReferenceRuntimeTarget is a target for a config specifying that it
// isn't mounted into the container but instead has some other purpose.
type ConfigReferenceRuntimeTarget struct{}
// ConfigReference is a reference to a config in swarm // ConfigReference is a reference to a config in swarm
type ConfigReference struct { type ConfigReference struct {
File *ConfigReferenceFileTarget `json:",omitempty"` File *ConfigReferenceFileTarget
Runtime *ConfigReferenceRuntimeTarget `json:",omitempty"`
ConfigID string ConfigID string
ConfigName string ConfigName string
} }
...@@ -33,7 +33,6 @@ type SELinuxContext struct { ...@@ -33,7 +33,6 @@ type SELinuxContext struct {
// CredentialSpec for managed service account (Windows only) // CredentialSpec for managed service account (Windows only)
type CredentialSpec struct { type CredentialSpec struct {
Config string
File string File string
Registry string Registry string
} }
...@@ -67,11 +66,9 @@ type ContainerSpec struct { ...@@ -67,11 +66,9 @@ 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"`
Capabilities []string `json:",omitempty"`
} }
// Code generated by protoc-gen-gogo. DO NOT EDIT. // Code generated by protoc-gen-gogo.
// 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.
...@@ -37,7 +38,6 @@ type PluginSpec struct { ...@@ -37,7 +38,6 @@ 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,13 +73,6 @@ func (m *PluginSpec) GetDisabled() bool { ...@@ -73,13 +73,6 @@ 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 {
...@@ -167,21 +160,6 @@ func (m *PluginSpec) MarshalTo(dAtA []byte) (int, error) { ...@@ -167,21 +160,6 @@ 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
} }
...@@ -230,6 +208,24 @@ func (m *PluginPrivilege) MarshalTo(dAtA []byte) (int, error) { ...@@ -230,6 +208,24 @@ 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)
...@@ -259,12 +255,6 @@ func (m *PluginSpec) Size() (n int) { ...@@ -259,12 +255,6 @@ 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
} }
...@@ -439,35 +429,6 @@ func (m *PluginSpec) Unmarshal(dAtA []byte) error { ...@@ -439,35 +429,6 @@ 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:])
...@@ -734,21 +695,18 @@ var ( ...@@ -734,21 +695,18 @@ var (
func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) } func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) }
var fileDescriptorPlugin = []byte{ var fileDescriptorPlugin = []byte{
// 256 bytes of a gzipped FileDescriptorProto // 196 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x4d, 0x4b, 0xc3, 0x30, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0xc8, 0x29, 0x4d,
0x18, 0xc7, 0x89, 0xdd, 0xc6, 0xfa, 0x4c, 0x70, 0x04, 0x91, 0xe2, 0xa1, 0x94, 0x9d, 0x7a, 0x6a, 0xcf, 0xcc, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x6a, 0x63, 0xe4, 0xe2, 0x0a, 0x00, 0x0b,
0x45, 0x2f, 0x82, 0x37, 0x0f, 0x9e, 0x47, 0xbc, 0x09, 0x1e, 0xd2, 0xf6, 0xa1, 0x06, 0x9b, 0x17, 0x04, 0x17, 0xa4, 0x26, 0x0b, 0x09, 0x71, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30,
0x92, 0xb4, 0xe2, 0x37, 0xf1, 0x23, 0x79, 0xf4, 0x23, 0x48, 0x3f, 0x89, 0x98, 0x75, 0x32, 0x64, 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x62, 0x5c, 0x6c, 0x45, 0xa9, 0xb9, 0xf9, 0x25, 0xa9, 0x12,
0xa7, 0xff, 0x4b, 0xc2, 0x9f, 0x1f, 0x0f, 0x9c, 0x9a, 0xae, 0x6f, 0x85, 0x2a, 0x8c, 0xd5, 0x5e, 0x4c, 0x60, 0x51, 0x28, 0x4f, 0xc8, 0x80, 0x8b, 0xab, 0xa0, 0x28, 0xb3, 0x2c, 0x33, 0x27, 0x35,
0x6f, 0x3e, 0x08, 0xc0, 0x36, 0x14, 0x8f, 0x06, 0x6b, 0x4a, 0x61, 0xa6, 0xb8, 0xc4, 0x84, 0x64, 0x3d, 0xb5, 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x40, 0x0f, 0x62, 0x58, 0x00, 0x4c,
0x24, 0x8f, 0x59, 0xf0, 0xf4, 0x02, 0x16, 0x16, 0xa5, 0xf6, 0x98, 0x9c, 0x84, 0x76, 0x4a, 0xf4, 0x22, 0x08, 0x49, 0x8d, 0x90, 0x14, 0x17, 0x47, 0x4a, 0x66, 0x71, 0x62, 0x52, 0x4e, 0x6a, 0x8a,
0x0a, 0xc0, 0x58, 0x31, 0x88, 0x0e, 0x5b, 0x74, 0x49, 0x94, 0x45, 0xf9, 0xea, 0x7a, 0x5d, 0xec, 0x04, 0x8b, 0x02, 0xa3, 0x06, 0x47, 0x10, 0x9c, 0xaf, 0x14, 0xcb, 0xc5, 0x8f, 0xa6, 0x15, 0xab,
0xc6, 0xb6, 0xfb, 0x07, 0x76, 0xf0, 0x87, 0x5e, 0xc2, 0xb2, 0x11, 0x8e, 0x57, 0x1d, 0x36, 0xc9, 0x63, 0x14, 0xb8, 0xb8, 0x53, 0x52, 0x8b, 0x93, 0x8b, 0x32, 0x0b, 0x4a, 0x32, 0xf3, 0xf3, 0xa0,
0x2c, 0x23, 0xf9, 0x92, 0xfd, 0x65, 0xba, 0x86, 0x08, 0xd5, 0x90, 0xcc, 0xb3, 0x28, 0x8f, 0xd9, 0x2e, 0x42, 0x16, 0x12, 0x12, 0xe1, 0x62, 0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x05, 0xbb, 0x88, 0x33,
0xaf, 0xdd, 0x3c, 0xc3, 0xd9, 0xbf, 0xb1, 0xa3, 0x78, 0x19, 0xac, 0x1a, 0x74, 0xb5, 0x15, 0xc6, 0x08, 0xc2, 0x71, 0xe2, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4,
0x0b, 0xad, 0x26, 0xc6, 0xc3, 0x8a, 0x9e, 0xc3, 0x7c, 0xe0, 0x5d, 0x8f, 0x81, 0x31, 0x66, 0xbb, 0x18, 0x93, 0xd8, 0xc0, 0x9e, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x84, 0xad, 0x79,
0x70, 0xff, 0xf0, 0x39, 0xa6, 0xe4, 0x6b, 0x4c, 0xc9, 0xf7, 0x98, 0x92, 0xa7, 0xdb, 0x56, 0xf8, 0x0c, 0x01, 0x00, 0x00,
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,7 +9,6 @@ message PluginSpec { ...@@ -9,7 +9,6 @@ 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,13 +10,6 @@ type Service struct { ...@@ -10,13 +10,6 @@ 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.
...@@ -129,17 +122,3 @@ type UpdateConfig struct { ...@@ -129,17 +122,3 @@ 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
}
package swarm // import "github.com/docker/docker/api/types/swarm" package swarm // import "github.com/docker/docker/api/types/swarm"
import ( import "time"
"time"
)
// ClusterInfo represents info about the cluster for outputting in "info" // ClusterInfo represents info about the cluster for outputting in "info"
// it contains the same information as "Swarm", but without the JoinTokens // it contains the same information as "Swarm", but without the JoinTokens
...@@ -12,9 +10,6 @@ type ClusterInfo struct { ...@@ -12,9 +10,6 @@ type ClusterInfo struct {
Spec Spec Spec Spec
TLSInfo TLSInfo TLSInfo TLSInfo
RootRotationInProgress bool RootRotationInProgress bool
DefaultAddrPool []string
SubnetSize uint32
DataPathPort uint32
} }
// Swarm represents a swarm. // Swarm represents a swarm.
...@@ -154,13 +149,10 @@ type InitRequest struct { ...@@ -154,13 +149,10 @@ type InitRequest struct {
ListenAddr string ListenAddr string
AdvertiseAddr string AdvertiseAddr string
DataPathAddr string DataPathAddr string
DataPathPort uint32
ForceNewCluster bool ForceNewCluster bool
Spec Spec Spec Spec
AutoLockManagers bool AutoLockManagers bool
Availability NodeAvailability Availability NodeAvailability
DefaultAddrPool []string
SubnetSize uint32
} }
// JoinRequest is the request used to join a swarm. // JoinRequest is the request used to join a swarm.
...@@ -209,8 +201,6 @@ type Info struct { ...@@ -209,8 +201,6 @@ type Info struct {
Managers int `json:",omitempty"` Managers int `json:",omitempty"`
Cluster *ClusterInfo `json:",omitempty"` Cluster *ClusterInfo `json:",omitempty"`
Warnings []string `json:",omitempty"`
} }
// Peer represents a peer. // Peer represents a peer.
......
...@@ -127,7 +127,6 @@ type ResourceRequirements struct { ...@@ -127,7 +127,6 @@ type ResourceRequirements struct {
type Placement struct { type Placement struct {
Constraints []string `json:",omitempty"` Constraints []string `json:",omitempty"`
Preferences []PlacementPreference `json:",omitempty"` Preferences []PlacementPreference `json:",omitempty"`
MaxReplicas uint64 `json:",omitempty"`
// Platforms stores all the platforms that the image can run on. // Platforms stores all the platforms that the image can run on.
// This field is used in the platform filter for scheduling. If empty, // This field is used in the platform filter for scheduling. If empty,
......
...@@ -39,7 +39,6 @@ type ImageInspect struct { ...@@ -39,7 +39,6 @@ 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
...@@ -103,10 +102,9 @@ type ContainerStats struct { ...@@ -103,10 +102,9 @@ type ContainerStats struct {
// Ping contains response of Engine API: // Ping contains response of Engine API:
// GET "/_ping" // GET "/_ping"
type Ping struct { type Ping struct {
APIVersion string APIVersion string
OSType string OSType string
Experimental bool Experimental bool
BuilderVersion BuilderVersion
} }
// ComponentVersion describes the version information for a specific component. // ComponentVersion describes the version information for a specific component.
...@@ -159,12 +157,10 @@ type Info struct { ...@@ -159,12 +157,10 @@ type Info struct {
MemoryLimit bool MemoryLimit bool
SwapLimit bool SwapLimit bool
KernelMemory bool KernelMemory bool
KernelMemoryTCP bool
CPUCfsPeriod bool `json:"CpuCfsPeriod"` CPUCfsPeriod bool `json:"CpuCfsPeriod"`
CPUCfsQuota bool `json:"CpuCfsQuota"` CPUCfsQuota bool `json:"CpuCfsQuota"`
CPUShares bool CPUShares bool
CPUSet bool CPUSet bool
PidsLimit bool
IPv4Forwarding bool IPv4Forwarding bool
BridgeNfIptables bool BridgeNfIptables bool
BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` BridgeNfIP6tables bool `json:"BridgeNfIp6tables"`
...@@ -178,7 +174,6 @@ type Info struct { ...@@ -178,7 +174,6 @@ 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
...@@ -209,8 +204,6 @@ type Info struct { ...@@ -209,8 +204,6 @@ type Info struct {
RuncCommit Commit RuncCommit Commit
InitCommit Commit InitCommit Commit
SecurityOptions []string SecurityOptions []string
ProductLicense string `json:",omitempty"`
Warnings []string
} }
// KeyValue holds a key/value pair // KeyValue holds a key/value pair
...@@ -547,7 +540,6 @@ type ImagesPruneReport struct { ...@@ -547,7 +540,6 @@ type ImagesPruneReport struct {
// BuildCachePruneReport contains the response for Engine API: // BuildCachePruneReport contains the response for Engine API:
// POST "/build/prune" // POST "/build/prune"
type BuildCachePruneReport struct { type BuildCachePruneReport struct {
CachesDeleted []string
SpaceReclaimed uint64 SpaceReclaimed uint64
} }
...@@ -597,21 +589,14 @@ type BuildResult struct { ...@@ -597,21 +589,14 @@ type BuildResult struct {
// BuildCache contains information about a build cache record // BuildCache contains information about a build cache record
type BuildCache struct { type BuildCache struct {
ID string ID string
Parent string Mutable bool
Type string InUse bool
Description string Size int64
InUse bool
Shared bool
Size int64
CreatedAt time.Time CreatedAt time.Time
LastUsedAt *time.Time LastUsedAt *time.Time
UsageCount int UsageCount int
} Parent string
Description string
// BuildCachePruneOptions hold parameters to prune the build cache
type BuildCachePruneOptions struct {
All bool
KeepStorage int64
Filters filters.Args
} }
package volume // import "github.com/docker/docker/api/types/volume" package volume
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// VolumeCreateBody Volume configuration // VolumeCreateBody
// swagger:model VolumeCreateBody // swagger:model VolumeCreateBody
type VolumeCreateBody struct { type VolumeCreateBody struct {
......
package volume // import "github.com/docker/docker/api/types/volume" package volume
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Code generated by `swagger generate operation`. DO NOT EDIT. // DO NOT EDIT THIS FILE
// This file was generated by `swagger generate operation`
// //
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
import "github.com/docker/docker/api/types" import "github.com/docker/docker/api/types"
// VolumeListOKBody Volume list response // VolumeListOKBody
// swagger:model VolumeListOKBody // swagger:model VolumeListOKBody
type VolumeListOKBody struct { type VolumeListOKBody struct {
......
...@@ -16,7 +16,7 @@ import ( ...@@ -16,7 +16,7 @@ import (
) )
func main() { func main() {
cli, err := client.NewClientWithOpts(client.FromEnv) cli, err := client.NewEnvClient()
if err != nil { if err != nil {
panic(err) panic(err)
} }
......
package client // import "github.com/docker/docker/client" package client // import "github.com/docker/docker/client"
import ( import (
"context"
"net/url" "net/url"
"golang.org/x/net/context"
) )
// BuildCancel requests the daemon to cancel ongoing build request // BuildCancel requests the daemon to cancel ongoing build request
...@@ -11,6 +12,10 @@ func (cli *Client) BuildCancel(ctx context.Context, id string) error { ...@@ -11,6 +12,10 @@ func (cli *Client) BuildCancel(ctx context.Context, id string) error {
query.Set("id", id) query.Set("id", id)
serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil) serverResp, err := cli.post(ctx, "/build/cancel", query, nil, nil)
ensureReaderClosed(serverResp) if err != nil {
return err return err
}
defer ensureReaderClosed(serverResp)
return nil
} }
...@@ -4,38 +4,23 @@ import ( ...@@ -4,38 +4,23 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/pkg/errors"
) )
// BuildCachePrune requests the daemon to delete unused cache data // BuildCachePrune requests the daemon to delete unused cache data
func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) { func (cli *Client) BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error) {
if err := cli.NewVersionError("1.31", "build prune"); err != nil { if err := cli.NewVersionError("1.31", "build prune"); err != nil {
return nil, err return nil, err
} }
report := types.BuildCachePruneReport{} report := types.BuildCachePruneReport{}
query := url.Values{} serverResp, err := cli.post(ctx, "/build/prune", nil, nil, nil)
if opts.All {
query.Set("all", "1")
}
query.Set("keep-storage", fmt.Sprintf("%d", opts.KeepStorage))
filters, err := filters.ToJSON(opts.Filters)
if err != nil {
return nil, errors.Wrap(err, "prune could not marshal filters option")
}
query.Set("filters", filters)
serverResp, err := cli.post(ctx, "/build/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return nil, fmt.Errorf("Error retrieving disk usage: %v", err) return nil, fmt.Errorf("Error retrieving disk usage: %v", err)
......
...@@ -18,11 +18,11 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options ...@@ -18,11 +18,11 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options
} }
resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil) resp, err := cli.get(ctx, "/containers/"+container+"/checkpoints", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return checkpoints, wrapResponseError(err, resp, "container", container) return checkpoints, wrapResponseError(err, resp, "container", container)
} }
err = json.NewDecoder(resp.body).Decode(&checkpoints) err = json.NewDecoder(resp.body).Decode(&checkpoints)
ensureReaderClosed(resp)
return checkpoints, err return checkpoints, err
} }
package client
import "net/http"
// NewClient initializes a new API client for the given host and API version.
// It uses the given http client as transport.
// It also initializes the custom http headers to add to each request.
//
// It won't send any version information if the version number is empty. It is
// highly recommended that you set a version or your client may break if the
// server is upgraded.
// Deprecated: use NewClientWithOpts
func NewClient(host string, version string, client *http.Client, httpHeaders map[string]string) (*Client, error) {
return NewClientWithOpts(WithHost(host), WithVersion(version), WithHTTPClient(client), WithHTTPHeaders(httpHeaders))
}
// NewEnvClient initializes a new API client based on environment variables.
// See FromEnv for a list of support environment variables.
//
// Deprecated: use NewClientWithOpts(FromEnv)
func NewEnvClient() (*Client, error) {
return NewClientWithOpts(FromEnv)
}
...@@ -15,11 +15,11 @@ func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (t ...@@ -15,11 +15,11 @@ func (cli *Client) ConfigCreate(ctx context.Context, config swarm.ConfigSpec) (t
return response, err return response, err
} }
resp, err := cli.post(ctx, "/configs/create", nil, config, nil) resp, err := cli.post(ctx, "/configs/create", nil, config, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -18,10 +18,10 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C ...@@ -18,10 +18,10 @@ func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.C
return swarm.Config{}, nil, err return swarm.Config{}, nil, err
} }
resp, err := cli.get(ctx, "/configs/"+id, nil, nil) resp, err := cli.get(ctx, "/configs/"+id, nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id) return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
......
...@@ -27,12 +27,12 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio ...@@ -27,12 +27,12 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio
} }
resp, err := cli.get(ctx, "/configs", query, nil) resp, err := cli.get(ctx, "/configs", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var configs []swarm.Config var configs []swarm.Config
err = json.NewDecoder(resp.body).Decode(&configs) err = json.NewDecoder(resp.body).Decode(&configs)
ensureReaderClosed(resp)
return configs, err return configs, err
} }
...@@ -8,6 +8,6 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error { ...@@ -8,6 +8,6 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
return err return err
} }
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
defer ensureReaderClosed(resp) ensureReaderClosed(resp)
return wrapResponseError(err, resp, "config", id) return wrapResponseError(err, resp, "config", id)
} }
...@@ -45,11 +45,11 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option ...@@ -45,11 +45,11 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option
var response types.IDResponse var response types.IDResponse
resp, err := cli.post(ctx, "/commit", query, options.Config, nil) resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -21,10 +21,10 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri ...@@ -21,10 +21,10 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri
urlStr := "/containers/" + containerID + "/archive" urlStr := "/containers/" + containerID + "/archive"
response, err := cli.head(ctx, urlStr, query, nil) response, err := cli.head(ctx, urlStr, query, nil)
defer ensureReaderClosed(response)
if err != nil { if err != nil {
return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path) return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path)
} }
defer ensureReaderClosed(response)
return getContainerPathStatFromHeader(response.header) return getContainerPathStatFromHeader(response.header)
} }
...@@ -45,12 +45,11 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str ...@@ -45,12 +45,11 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str
apiPath := "/containers/" + containerID + "/archive" apiPath := "/containers/" + containerID + "/archive"
response, err := cli.putRaw(ctx, apiPath, query, content, nil) response, err := cli.putRaw(ctx, apiPath, query, content, nil)
defer ensureReaderClosed(response)
if err != nil { if err != nil {
return wrapResponseError(err, response, "container:path", containerID+":"+dstPath) return wrapResponseError(err, response, "container:path", containerID+":"+dstPath)
} }
defer ensureReaderClosed(response)
// TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior
if response.statusCode != http.StatusOK { if response.statusCode != http.StatusOK {
return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) return fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
} }
...@@ -70,7 +69,6 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s ...@@ -70,7 +69,6 @@ func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath s
return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath) return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath)
} }
// TODO this code converts non-error status-codes (e.g., "204 No Content") into an error; verify if this is the desired behavior
if response.statusCode != http.StatusOK { if response.statusCode != http.StatusOK {
return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode) return nil, types.ContainerPathStat{}, fmt.Errorf("unexpected status code from daemon: %d", response.statusCode)
} }
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strings"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
...@@ -42,11 +43,14 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config ...@@ -42,11 +43,14 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config
} }
serverResp, err := cli.post(ctx, "/containers/create", query, body, nil) serverResp, err := cli.post(ctx, "/containers/create", query, body, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
return response, objectNotFoundError{object: "image", id: config.Image}
}
return response, err return response, err
} }
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -13,11 +13,11 @@ func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]con ...@@ -13,11 +13,11 @@ func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]con
var changes []container.ContainerChangeResponseItem var changes []container.ContainerChangeResponseItem
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return changes, err return changes, err
} }
err = json.NewDecoder(serverResp.body).Decode(&changes) err = json.NewDecoder(serverResp.body).Decode(&changes)
ensureReaderClosed(serverResp)
return changes, err return changes, err
} }
...@@ -16,11 +16,11 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co ...@@ -16,11 +16,11 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, container string, co
} }
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil) resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
......
...@@ -16,13 +16,13 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty ...@@ -16,13 +16,13 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty
return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID} return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID}
} }
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID) return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
} }
var response types.ContainerJSON var response types.ContainerJSON
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -36,10 +36,10 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri ...@@ -36,10 +36,10 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri
query.Set("size", "1") query.Set("size", "1")
} }
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID) return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -35,7 +35,6 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis ...@@ -35,7 +35,6 @@ 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 {
...@@ -46,12 +45,12 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis ...@@ -46,12 +45,12 @@ func (cli *Client) ContainerList(ctx context.Context, options types.ContainerLis
} }
resp, err := cli.get(ctx, "/containers/json", query, nil) resp, err := cli.get(ctx, "/containers/json", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var containers []types.Container var containers []types.Container
err = json.NewDecoder(resp.body).Decode(&containers) err = json.NewDecoder(resp.body).Decode(&containers)
ensureReaderClosed(resp)
return containers, err return containers, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Arg ...@@ -23,10 +23,10 @@ func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Arg
} }
serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return report, err return report, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return report, fmt.Errorf("Error retrieving disk usage: %v", err) return report, fmt.Errorf("Error retrieving disk usage: %v", err)
......
...@@ -22,6 +22,6 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti ...@@ -22,6 +22,6 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti
} }
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil)
defer ensureReaderClosed(resp) ensureReaderClosed(resp)
return wrapResponseError(err, resp, "container", containerID) return wrapResponseError(err, resp, "container", containerID)
} }
...@@ -18,11 +18,11 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen ...@@ -18,11 +18,11 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen
} }
resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -11,11 +11,12 @@ import ( ...@@ -11,11 +11,12 @@ import (
func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) { func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) {
var response container.ContainerUpdateOKBody var response container.ContainerUpdateOKBody
serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(serverResp.body).Decode(&response) err = json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -13,10 +13,10 @@ func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) { ...@@ -13,10 +13,10 @@ func (cli *Client) DiskUsage(ctx context.Context) (types.DiskUsage, error) {
var du types.DiskUsage var du types.DiskUsage
serverResp, err := cli.get(ctx, "/system/df", nil, nil) serverResp, err := cli.get(ctx, "/system/df", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return du, err return du, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&du); err != nil {
return du, fmt.Errorf("Error retrieving disk usage: %v", err) return du, fmt.Errorf("Error retrieving disk usage: %v", err)
......
...@@ -28,11 +28,11 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist ...@@ -28,11 +28,11 @@ func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegist
} }
resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers) resp, err := cli.get(ctx, "/distribution/"+image+"/json", url.Values{}, headers)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return distributionInspect, err return distributionInspect, err
} }
err = json.NewDecoder(resp.body).Decode(&distributionInspect) err = json.NewDecoder(resp.body).Decode(&distributionInspect)
ensureReaderClosed(resp)
return distributionInspect, err return distributionInspect, err
} }
...@@ -5,7 +5,6 @@ import ( ...@@ -5,7 +5,6 @@ import (
"net/http" "net/http"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -33,19 +32,16 @@ func ErrorConnectionFailed(host string) error { ...@@ -33,19 +32,16 @@ func ErrorConnectionFailed(host string) error {
return errConnectionFailed{host: host} return errConnectionFailed{host: host}
} }
// Deprecated: use the errdefs.NotFound() interface instead. Kept for backward compatibility
type notFound interface { type notFound interface {
error error
NotFound() bool NotFound() bool // Is the error a NotFound error
} }
// IsErrNotFound returns true if the error is a NotFound error, which is returned // IsErrNotFound returns true if the error is a NotFound error, which is returned
// by the API when some object is not found. // by the API when some object is not found.
func IsErrNotFound(err error) bool { func IsErrNotFound(err error) bool {
if _, ok := err.(notFound); ok { te, ok := err.(notFound)
return ok return ok && te.NotFound()
}
return errdefs.IsNotFound(err)
} }
type objectNotFoundError struct { type objectNotFoundError struct {
...@@ -53,7 +49,9 @@ type objectNotFoundError struct { ...@@ -53,7 +49,9 @@ type objectNotFoundError struct {
id string id string
} }
func (e objectNotFoundError) NotFound() {} func (e objectNotFoundError) NotFound() bool {
return true
}
func (e objectNotFoundError) Error() string { func (e objectNotFoundError) Error() string {
return fmt.Sprintf("Error: No such %s: %s", e.object, e.id) return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
...@@ -66,7 +64,7 @@ func wrapResponseError(err error, resp serverResponse, object, id string) error ...@@ -66,7 +64,7 @@ func wrapResponseError(err error, resp serverResponse, object, id string) error
case resp.statusCode == http.StatusNotFound: case resp.statusCode == http.StatusNotFound:
return objectNotFoundError{object: object, id: id} return objectNotFoundError{object: object, id: id}
case resp.statusCode == http.StatusNotImplemented: case resp.statusCode == http.StatusNotImplemented:
return errdefs.NotImplemented(err) return notImplementedError{message: err.Error()}
default: default:
return err return err
} }
...@@ -85,10 +83,8 @@ func (u unauthorizedError) Error() string { ...@@ -85,10 +83,8 @@ func (u unauthorizedError) Error() string {
// IsErrUnauthorized returns true if the error is caused // IsErrUnauthorized returns true if the error is caused
// when a remote registry authentication fails // when a remote registry authentication fails
func IsErrUnauthorized(err error) bool { func IsErrUnauthorized(err error) bool {
if _, ok := err.(unauthorizedError); ok { _, ok := err.(unauthorizedError)
return ok return ok
}
return errdefs.IsUnauthorized(err)
} }
type pluginPermissionDenied struct { type pluginPermissionDenied struct {
...@@ -122,10 +118,8 @@ func (e notImplementedError) NotImplemented() bool { ...@@ -122,10 +118,8 @@ func (e notImplementedError) NotImplemented() bool {
// This is returned by the API when a requested feature has not been // This is returned by the API when a requested feature has not been
// implemented. // implemented.
func IsErrNotImplemented(err error) bool { func IsErrNotImplemented(err error) bool {
if _, ok := err.(notImplementedError); ok { te, ok := err.(notImplementedError)
return ok return ok && te.NotImplemented()
}
return errdefs.IsNotImplemented(err)
} }
// NewVersionError returns an error if the APIVersion required // NewVersionError returns an error if the APIVersion required
......
...@@ -90,7 +90,6 @@ func buildEventsQueryParams(cliVersion string, options types.EventsOptions) (url ...@@ -90,7 +90,6 @@ 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
......
...@@ -23,14 +23,14 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu ...@@ -23,14 +23,14 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
} }
apiPath := cli.getAPIPath(ctx, path, query) apiPath := cli.getAPIPath(path, query)
req, err := http.NewRequest(http.MethodPost, apiPath, bodyEncoded) req, err := http.NewRequest("POST", apiPath, bodyEncoded)
if err != nil { if err != nil {
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
} }
req = cli.addHeaders(req, headers) req = cli.addHeaders(req, headers)
conn, err := cli.setupHijackConn(ctx, req, "tcp") conn, err := cli.setupHijackConn(req, "tcp")
if err != nil { if err != nil {
return types.HijackedResponse{}, err return types.HijackedResponse{}, err
} }
...@@ -38,20 +38,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu ...@@ -38,20 +38,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err
} }
// DialHijack returns a hijacked connection with negotiated protocol proto. func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) {
req, err := http.NewRequest(http.MethodPost, url, nil)
if err != nil {
return nil, err
}
req = cli.addHeaders(req, meta)
return cli.setupHijackConn(ctx, req, proto)
}
// fallbackDial is used when WithDialer() was not called.
// See cli.Dialer().
func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
if tlsConfig != nil && proto != "unix" && proto != "npipe" { if tlsConfig != nil && proto != "unix" && proto != "npipe" {
return tls.Dial(proto, addr, tlsConfig) return tls.Dial(proto, addr, tlsConfig)
} }
...@@ -61,13 +48,12 @@ func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { ...@@ -61,13 +48,12 @@ func fallbackDial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
return net.Dial(proto, addr) return net.Dial(proto, addr)
} }
func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto string) (net.Conn, error) { func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, error) {
req.Host = cli.addr req.Host = cli.addr
req.Header.Set("Connection", "Upgrade") req.Header.Set("Connection", "Upgrade")
req.Header.Set("Upgrade", proto) req.Header.Set("Upgrade", proto)
dialer := cli.Dialer() conn, err := dial(cli.proto, cli.addr, resolveTLSConfig(cli.client.Transport))
conn, err := dialer(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") return nil, errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
} }
...@@ -87,8 +73,6 @@ func (cli *Client) setupHijackConn(ctx context.Context, req *http.Request, proto ...@@ -87,8 +73,6 @@ 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
......
...@@ -134,13 +134,5 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur ...@@ -134,13 +134,5 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
query.Set("buildid", options.BuildID) query.Set("buildid", options.BuildID)
} }
query.Set("version", string(options.Version)) query.Set("version", string(options.Version))
if options.Outputs != nil {
outputsJSON, err := json.Marshal(options.Outputs)
if err != nil {
return query, err
}
query.Set("outputs", string(outputsJSON))
}
return query, nil return query, nil
} }
...@@ -12,11 +12,11 @@ import ( ...@@ -12,11 +12,11 @@ import (
func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) { func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) {
var history []image.HistoryResponseItem var history []image.HistoryResponseItem
serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil) serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return history, err return history, err
} }
err = json.NewDecoder(serverResp.body).Decode(&history) err = json.NewDecoder(serverResp.body).Decode(&history)
ensureReaderClosed(serverResp)
return history, err return history, err
} }
...@@ -15,10 +15,10 @@ func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (typ ...@@ -15,10 +15,10 @@ func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (typ
return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID} return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID}
} }
serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID) return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -24,7 +24,6 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions ...@@ -24,7 +24,6 @@ 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
...@@ -36,11 +35,11 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions ...@@ -36,11 +35,11 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
} }
serverResp, err := cli.get(ctx, "/images/json", query, nil) serverResp, err := cli.get(ctx, "/images/json", query, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return images, err return images, err
} }
err = json.NewDecoder(serverResp.body).Decode(&images) err = json.NewDecoder(serverResp.body).Decode(&images)
ensureReaderClosed(serverResp)
return images, err return images, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) ( ...@@ -23,10 +23,10 @@ func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (
} }
serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return report, err return report, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return report, fmt.Errorf("Error retrieving disk usage: %v", err) return report, fmt.Errorf("Error retrieving disk usage: %v", err)
......
...@@ -3,12 +3,12 @@ package client // import "github.com/docker/docker/client" ...@@ -3,12 +3,12 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"io" "io"
"net/http"
"net/url" "net/url"
"strings" "strings"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
) )
// ImagePull requests the docker host to pull an image from a remote registry. // ImagePull requests the docker host to pull an image from a remote registry.
...@@ -35,7 +35,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.I ...@@ -35,7 +35,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options types.I
} }
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
return nil, privilegeErr return nil, privilegeErr
......
...@@ -4,11 +4,11 @@ import ( ...@@ -4,11 +4,11 @@ import (
"context" "context"
"errors" "errors"
"io" "io"
"net/http"
"net/url" "net/url"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
) )
// ImagePush requests the docker host to push an image to a remote registry. // ImagePush requests the docker host to push an image to a remote registry.
...@@ -36,7 +36,7 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options types.Im ...@@ -36,7 +36,7 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options types.Im
query.Set("tag", tag) query.Set("tag", tag)
resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth) resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth)
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
return nil, privilegeErr return nil, privilegeErr
......
...@@ -21,11 +21,11 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type ...@@ -21,11 +21,11 @@ func (cli *Client) ImageRemove(ctx context.Context, imageID string, options type
var dels []types.ImageDeleteResponseItem var dels []types.ImageDeleteResponseItem
resp, err := cli.delete(ctx, "/images/"+imageID, query, nil) resp, err := cli.delete(ctx, "/images/"+imageID, query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return dels, wrapResponseError(err, resp, "image", imageID) return dels, wrapResponseError(err, resp, "image", imageID)
} }
err = json.NewDecoder(resp.body).Decode(&dels) err = json.NewDecoder(resp.body).Decode(&dels)
ensureReaderClosed(resp)
return dels, err return dels, err
} }
...@@ -4,12 +4,12 @@ import ( ...@@ -4,12 +4,12 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/registry"
"github.com/docker/docker/errdefs"
) )
// ImageSearch makes the docker host to search by a term in a remote registry. // ImageSearch makes the docker host to search by a term in a remote registry.
...@@ -29,8 +29,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I ...@@ -29,8 +29,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I
} }
resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth) resp, err := cli.tryImageSearch(ctx, query, options.RegistryAuth)
defer ensureReaderClosed(resp) if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
return results, privilegeErr return results, privilegeErr
...@@ -42,6 +41,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I ...@@ -42,6 +41,7 @@ func (cli *Client) ImageSearch(ctx context.Context, term string, options types.I
} }
err = json.NewDecoder(resp.body).Decode(&results) err = json.NewDecoder(resp.body).Decode(&results)
ensureReaderClosed(resp)
return results, err return results, err
} }
......
...@@ -13,10 +13,10 @@ import ( ...@@ -13,10 +13,10 @@ import (
func (cli *Client) Info(ctx context.Context) (types.Info, error) { func (cli *Client) Info(ctx context.Context) (types.Info, error) {
var info types.Info var info types.Info
serverResp, err := cli.get(ctx, "/info", url.Values{}, nil) serverResp, err := cli.get(ctx, "/info", url.Values{}, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return info, err return info, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&info); err != nil {
return info, fmt.Errorf("Error reading remote info: %v", err) return info, fmt.Errorf("Error reading remote info: %v", err)
......
...@@ -38,8 +38,7 @@ type CommonAPIClient interface { ...@@ -38,8 +38,7 @@ type CommonAPIClient interface {
ServerVersion(ctx context.Context) (types.Version, error) ServerVersion(ctx context.Context) (types.Version, error)
NegotiateAPIVersion(ctx context.Context) NegotiateAPIVersion(ctx context.Context)
NegotiateAPIVersionPing(types.Ping) NegotiateAPIVersionPing(types.Ping)
DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) DialSession(ctx context.Context, proto string, meta map[string][]string) (net.Conn, error)
Dialer() func(context.Context) (net.Conn, error)
Close() error Close() error
} }
...@@ -86,7 +85,7 @@ type DistributionAPIClient interface { ...@@ -86,7 +85,7 @@ type DistributionAPIClient interface {
// ImageAPIClient defines API client methods for the images // ImageAPIClient defines API client methods for the images
type ImageAPIClient interface { type ImageAPIClient interface {
ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) ImageBuild(ctx context.Context, context io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error)
BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) BuildCachePrune(ctx context.Context) (*types.BuildCachePruneReport, error)
BuildCancel(ctx context.Context, id string) error BuildCancel(ctx context.Context, id string) error
ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error) ImageCreate(ctx context.Context, parentReference string, options types.ImageCreateOptions) (io.ReadCloser, error)
ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error) ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error)
......
...@@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client" ...@@ -3,6 +3,7 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
...@@ -13,13 +14,16 @@ import ( ...@@ -13,13 +14,16 @@ import (
// It returns unauthorizedError when the authentication fails. // It returns unauthorizedError when the authentication fails.
func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) { func (cli *Client) RegistryLogin(ctx context.Context, auth types.AuthConfig) (registry.AuthenticateOKBody, error) {
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil) resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
defer ensureReaderClosed(resp)
if resp.statusCode == http.StatusUnauthorized {
return registry.AuthenticateOKBody{}, unauthorizedError{err}
}
if err != nil { if err != nil {
return registry.AuthenticateOKBody{}, err return registry.AuthenticateOKBody{}, err
} }
var response registry.AuthenticateOKBody var response registry.AuthenticateOKBody
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -15,11 +15,11 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options types ...@@ -15,11 +15,11 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options types
} }
var response types.NetworkCreateResponse var response types.NetworkCreateResponse
serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil) serverResp, err := cli.post(ctx, "/networks/create", nil, networkCreateRequest, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(serverResp.body).Decode(&response) json.NewDecoder(serverResp.body).Decode(&response)
ensureReaderClosed(serverResp)
return response, err return response, err
} }
...@@ -34,10 +34,10 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, ...@@ -34,10 +34,10 @@ func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string,
query.Set("scope", options.Scope) query.Set("scope", options.Scope)
} }
resp, err = cli.get(ctx, "/networks/"+networkID, query, nil) resp, err = cli.get(ctx, "/networks/"+networkID, query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return networkResource, nil, wrapResponseError(err, resp, "network", networkID) return networkResource, nil, wrapResponseError(err, resp, "network", networkID)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
......
...@@ -13,7 +13,6 @@ import ( ...@@ -13,7 +13,6 @@ 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
...@@ -23,10 +22,10 @@ func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOpt ...@@ -23,10 +22,10 @@ func (cli *Client) NetworkList(ctx context.Context, options types.NetworkListOpt
} }
var networkResources []types.NetworkResource var networkResources []types.NetworkResource
resp, err := cli.get(ctx, "/networks", query, nil) resp, err := cli.get(ctx, "/networks", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return networkResources, err return networkResources, err
} }
err = json.NewDecoder(resp.body).Decode(&networkResources) err = json.NewDecoder(resp.body).Decode(&networkResources)
ensureReaderClosed(resp)
return networkResources, err return networkResources, err
} }
...@@ -23,10 +23,10 @@ func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) ...@@ -23,10 +23,10 @@ func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args)
} }
serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil) serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return report, err return report, err
} }
defer ensureReaderClosed(serverResp)
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
return report, fmt.Errorf("Error retrieving network prune report: %v", err) return report, fmt.Errorf("Error retrieving network prune report: %v", err)
......
...@@ -5,6 +5,6 @@ import "context" ...@@ -5,6 +5,6 @@ import "context"
// NetworkRemove removes an existent network from the docker host. // NetworkRemove removes an existent network from the docker host.
func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil)
defer ensureReaderClosed(resp) ensureReaderClosed(resp)
return wrapResponseError(err, resp, "network", networkID) return wrapResponseError(err, resp, "network", networkID)
} }
...@@ -15,10 +15,10 @@ func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm ...@@ -15,10 +15,10 @@ func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm
return swarm.Node{}, nil, objectNotFoundError{object: "node", id: nodeID} return swarm.Node{}, nil, objectNotFoundError{object: "node", id: nodeID}
} }
serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil)
defer ensureReaderClosed(serverResp)
if err != nil { if err != nil {
return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID) return swarm.Node{}, nil, wrapResponseError(err, serverResp, "node", nodeID)
} }
defer ensureReaderClosed(serverResp)
body, err := ioutil.ReadAll(serverResp.body) body, err := ioutil.ReadAll(serverResp.body)
if err != nil { if err != nil {
......
...@@ -25,12 +25,12 @@ func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions) ...@@ -25,12 +25,12 @@ func (cli *Client) NodeList(ctx context.Context, options types.NodeListOptions)
} }
resp, err := cli.get(ctx, "/nodes", query, nil) resp, err := cli.get(ctx, "/nodes", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var nodes []swarm.Node var nodes []swarm.Node
err = json.NewDecoder(resp.body).Decode(&nodes) err = json.NewDecoder(resp.body).Decode(&nodes)
ensureReaderClosed(resp)
return nodes, err return nodes, err
} }
...@@ -15,6 +15,6 @@ func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types. ...@@ -15,6 +15,6 @@ func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types.
} }
resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil) resp, err := cli.delete(ctx, "/nodes/"+nodeID, query, nil)
defer ensureReaderClosed(resp) ensureReaderClosed(resp)
return wrapResponseError(err, resp, "node", nodeID) return wrapResponseError(err, resp, "node", nodeID)
} }
package client
import (
"context"
"net"
"net/http"
"os"
"path/filepath"
"time"
"github.com/docker/go-connections/sockets"
"github.com/docker/go-connections/tlsconfig"
"github.com/pkg/errors"
)
// Opt is a configuration option to initialize a client
type Opt func(*Client) error
// FromEnv configures the client with values from environment variables.
//
// Supported environment variables:
// DOCKER_HOST to set the url to the docker server.
// DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
// DOCKER_CERT_PATH to load the TLS certificates from.
// DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
func FromEnv(c *Client) error {
if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
options := tlsconfig.Options{
CAFile: filepath.Join(dockerCertPath, "ca.pem"),
CertFile: filepath.Join(dockerCertPath, "cert.pem"),
KeyFile: filepath.Join(dockerCertPath, "key.pem"),
InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
}
tlsc, err := tlsconfig.Client(options)
if err != nil {
return err
}
c.client = &http.Client{
Transport: &http.Transport{TLSClientConfig: tlsc},
CheckRedirect: CheckRedirect,
}
}
if host := os.Getenv("DOCKER_HOST"); host != "" {
if err := WithHost(host)(c); err != nil {
return err
}
}
if version := os.Getenv("DOCKER_API_VERSION"); version != "" {
if err := WithVersion(version)(c); err != nil {
return err
}
}
return nil
}
// WithDialer applies the dialer.DialContext to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
// Deprecated: use WithDialContext
func WithDialer(dialer *net.Dialer) Opt {
return WithDialContext(dialer.DialContext)
}
// WithDialContext applies the dialer to the client transport. This can be
// used to set the Timeout and KeepAlive settings of the client.
func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) Opt {
return func(c *Client) error {
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.DialContext = dialContext
return nil
}
return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport)
}
}
// WithHost overrides the client host with the specified one.
func WithHost(host string) Opt {
return func(c *Client) error {
hostURL, err := ParseHostURL(host)
if err != nil {
return err
}
c.host = host
c.proto = hostURL.Scheme
c.addr = hostURL.Host
c.basePath = hostURL.Path
if transport, ok := c.client.Transport.(*http.Transport); ok {
return sockets.ConfigureTransport(transport, c.proto, c.addr)
}
return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
}
}
// WithHTTPClient overrides the client http client with the specified one
func WithHTTPClient(client *http.Client) Opt {
return func(c *Client) error {
if client != nil {
c.client = client
}
return nil
}
}
// WithTimeout configures the time limit for requests made by the HTTP client
func WithTimeout(timeout time.Duration) Opt {
return func(c *Client) error {
c.client.Timeout = timeout
return nil
}
}
// WithHTTPHeaders overrides the client default http headers
func WithHTTPHeaders(headers map[string]string) Opt {
return func(c *Client) error {
c.customHTTPHeaders = headers
return nil
}
}
// WithScheme overrides the client scheme with the specified one
func WithScheme(scheme string) Opt {
return func(c *Client) error {
c.scheme = scheme
return nil
}
}
// WithTLSClientConfig applies a tls config to the client transport.
func WithTLSClientConfig(cacertPath, certPath, keyPath string) Opt {
return func(c *Client) error {
opts := tlsconfig.Options{
CAFile: cacertPath,
CertFile: certPath,
KeyFile: keyPath,
ExclusiveRootPools: true,
}
config, err := tlsconfig.Client(opts)
if err != nil {
return errors.Wrap(err, "failed to create tls config")
}
if transport, ok := c.client.Transport.(*http.Transport); ok {
transport.TLSClientConfig = config
return nil
}
return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport)
}
}
// WithVersion overrides the client version with the specified one. If an empty
// version is specified, the value will be ignored to allow version negotiation.
func WithVersion(version string) Opt {
return func(c *Client) error {
if version != "" {
c.version = version
c.manualOverride = true
}
return nil
}
}
// WithAPIVersionNegotiation enables automatic API version negotiation for the client.
// With this option enabled, the client automatically negotiates the API version
// to use when making requests. API version negotiation is performed on the first
// request; subsequent requests will not re-negotiate.
func WithAPIVersionNegotiation() Opt {
return func(c *Client) error {
c.negotiateVersion = true
return nil
}
}
...@@ -2,65 +2,31 @@ package client // import "github.com/docker/docker/client" ...@@ -2,65 +2,31 @@ package client // import "github.com/docker/docker/client"
import ( import (
"context" "context"
"net/http"
"path" "path"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
) )
// Ping pings the server and returns the value of the "Docker-Experimental", // Ping pings the server and returns the value of the "Docker-Experimental", "OS-Type" & "API-Version" headers
// "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use
// a HEAD request on the endpoint, but falls back to GET if HEAD is not supported
// by the daemon.
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
var ping types.Ping var ping types.Ping
req, err := cli.buildRequest("GET", path.Join(cli.basePath, "/_ping"), nil, nil)
// Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest()
// because ping requests are used during API version negotiation, so we want
// to hit the non-versioned /_ping endpoint, not /v1.xx/_ping
req, err := cli.buildRequest(http.MethodHead, path.Join(cli.basePath, "/_ping"), nil, nil)
if err != nil { if err != nil {
return ping, err return ping, err
} }
serverResp, err := cli.doRequest(ctx, req) serverResp, err := cli.doRequest(ctx, req)
if err == nil {
defer ensureReaderClosed(serverResp)
switch serverResp.statusCode {
case http.StatusOK, http.StatusInternalServerError:
// Server handled the request, so parse the response
return parsePingResponse(cli, serverResp)
}
} else if IsErrConnectionFailed(err) {
return ping, err
}
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
} }
serverResp, err = cli.doRequest(ctx, req)
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)
if err != nil {
return ping, err
}
return parsePingResponse(cli, serverResp)
}
func parsePingResponse(cli *Client, resp serverResponse) (types.Ping, error) { if serverResp.header != nil {
var ping types.Ping ping.APIVersion = serverResp.header.Get("API-Version")
if resp.header == nil {
err := cli.checkResponseErr(resp) if serverResp.header.Get("Docker-Experimental") == "true" {
return ping, errdefs.FromStatusCode(err, resp.statusCode) ping.Experimental = true
} }
ping.APIVersion = resp.header.Get("API-Version") ping.OSType = serverResp.header.Get("OSType")
ping.OSType = resp.header.Get("OSType")
if resp.header.Get("Docker-Experimental") == "true" {
ping.Experimental = true
}
if bv := resp.header.Get("Builder-Version"); bv != "" {
ping.BuilderVersion = types.BuilderVersion(bv)
} }
err := cli.checkResponseErr(resp) return ping, cli.checkResponseErr(serverResp)
return ping, errdefs.FromStatusCode(err, resp.statusCode)
} }
...@@ -18,6 +18,9 @@ func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, cr ...@@ -18,6 +18,9 @@ func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, cr
query.Set("name", createOptions.RepoName) query.Set("name", createOptions.RepoName)
resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers) resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers)
if err != nil {
return err
}
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return err
} }
...@@ -15,11 +15,11 @@ func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*type ...@@ -15,11 +15,11 @@ func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*type
return nil, nil, objectNotFoundError{object: "plugin", id: name} return nil, nil, objectNotFoundError{object: "plugin", id: name}
} }
resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, nil, wrapResponseError(err, resp, "plugin", name) return nil, nil, wrapResponseError(err, resp, "plugin", name)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
......
...@@ -4,11 +4,11 @@ import ( ...@@ -4,11 +4,11 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"io" "io"
"net/http"
"net/url" "net/url"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -78,7 +78,7 @@ func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileg ...@@ -78,7 +78,7 @@ func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileg
func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options types.PluginInstallOptions) (types.PluginPrivileges, error) { func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options types.PluginInstallOptions) (types.PluginPrivileges, error) {
resp, err := cli.tryPluginPrivileges(ctx, query, options.RegistryAuth) resp, err := cli.tryPluginPrivileges(ctx, query, options.RegistryAuth)
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil { if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
// todo: do inspect before to check existing name before checking privileges // todo: do inspect before to check existing name before checking privileges
newAuthHeader, privilegeErr := options.PrivilegeFunc() newAuthHeader, privilegeErr := options.PrivilegeFunc()
if privilegeErr != nil { if privilegeErr != nil {
......
...@@ -15,7 +15,6 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P ...@@ -15,7 +15,6 @@ 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
...@@ -23,11 +22,11 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P ...@@ -23,11 +22,11 @@ func (cli *Client) PluginList(ctx context.Context, filter filters.Args) (types.P
query.Set("filters", filterJSON) query.Set("filters", filterJSON)
} }
resp, err := cli.get(ctx, "/plugins", query, nil) resp, err := cli.get(ctx, "/plugins", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return plugins, wrapResponseError(err, resp, "plugin", "") return plugins, wrapResponseError(err, resp, "plugin", "")
} }
err = json.NewDecoder(resp.body).Decode(&plugins) err = json.NewDecoder(resp.body).Decode(&plugins)
ensureReaderClosed(resp)
return plugins, err return plugins, err
} }
...@@ -15,6 +15,6 @@ func (cli *Client) PluginRemove(ctx context.Context, name string, options types. ...@@ -15,6 +15,6 @@ func (cli *Client) PluginRemove(ctx context.Context, name string, options types.
} }
resp, err := cli.delete(ctx, "/plugins/"+name, query, nil) resp, err := cli.delete(ctx, "/plugins/"+name, query, nil)
defer ensureReaderClosed(resp) ensureReaderClosed(resp)
return wrapResponseError(err, resp, "plugin", name) return wrapResponseError(err, resp, "plugin", name)
} }
...@@ -15,8 +15,8 @@ import ( ...@@ -15,8 +15,8 @@ import (
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/docker/docker/errdefs"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/net/context/ctxhttp"
) )
// serverResponse is a wrapper for http API responses. // serverResponse is a wrapper for http API responses.
...@@ -29,12 +29,12 @@ type serverResponse struct { ...@@ -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, http.MethodHead, path, query, nil, headers) return cli.sendRequest(ctx, "HEAD", 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, http.MethodGet, path, query, nil, headers) return cli.sendRequest(ctx, "GET", 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,21 +43,30 @@ func (cli *Client) post(ctx context.Context, path string, query url.Values, obj ...@@ -43,21 +43,30 @@ 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, http.MethodPost, path, query, body, headers) return cli.sendRequest(ctx, "POST", 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, http.MethodPost, path, query, body, headers) return cli.sendRequest(ctx, "POST", 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, http.MethodPut, path, query, body, headers) return cli.sendRequest(ctx, "PUT", 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, http.MethodDelete, path, query, nil, headers) return cli.sendRequest(ctx, "DELETE", path, query, nil, headers)
} }
type headers map[string][]string type headers map[string][]string
...@@ -79,7 +88,7 @@ func encodeBody(obj interface{}, headers headers) (io.Reader, headers, error) { ...@@ -79,7 +88,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 == http.MethodPost || method == http.MethodPut) expectedPayload := (method == "POST" || method == "PUT")
if expectedPayload && body == nil { if expectedPayload && body == nil {
body = bytes.NewReader([]byte{}) body = bytes.NewReader([]byte{})
} }
...@@ -106,30 +115,28 @@ func (cli *Client) buildRequest(method, path string, body io.Reader, headers hea ...@@ -106,30 +115,28 @@ func (cli *Client) buildRequest(method, path string, body io.Reader, headers hea
} }
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) { func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) {
req, err := cli.buildRequest(method, cli.getAPIPath(ctx, path, query), body, headers) req, err := cli.buildRequest(method, cli.getAPIPath(path, query), body, headers)
if err != nil { if err != nil {
return serverResponse{}, err return serverResponse{}, err
} }
resp, err := cli.doRequest(ctx, req) resp, err := cli.doRequest(ctx, req)
if err != nil { if err != nil {
return resp, errdefs.FromStatusCode(err, resp.statusCode) return resp, err
} }
err = cli.checkResponseErr(resp) return resp, cli.checkResponseErr(resp)
return resp, errdefs.FromStatusCode(err, resp.statusCode)
} }
func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) { func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) {
serverResp := serverResponse{statusCode: -1, reqURL: req.URL} serverResp := serverResponse{statusCode: -1, reqURL: req.URL}
req = req.WithContext(ctx) resp, err := ctxhttp.Do(ctx, cli.client, req)
resp, err := cli.client.Do(req)
if err != nil { if err != nil {
if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") { if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err) return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
} }
if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") { if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
return serverResp, errors.Wrap(err, "The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings") return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
} }
// Don't decorate context sentinel errors; users may be comparing to // Don't decorate context sentinel errors; users may be comparing to
...@@ -169,13 +176,7 @@ func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResp ...@@ -169,13 +176,7 @@ 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`) {
// Checks if client is running with elevated privileges 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.")
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")
...@@ -194,21 +195,9 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error { ...@@ -194,21 +195,9 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error {
return nil return nil
} }
var body []byte body, err := ioutil.ReadAll(serverResp.body)
var err error if err != nil {
if serverResp.body != nil { return err
bodyMax := 1 * 1024 * 1024 // 1 MiB
bodyR := &io.LimitedReader{
R: serverResp.body,
N: int64(bodyMax),
}
body, err = ioutil.ReadAll(bodyR)
if err != nil {
return err
}
if bodyR.N == 0 {
return fmt.Errorf("request returned %s with a message (> %d bytes) for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), bodyMax, serverResp.reqURL)
}
} }
if len(body) == 0 { if len(body) == 0 {
return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL) return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(serverResp.statusCode), serverResp.reqURL)
...@@ -223,14 +212,14 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error { ...@@ -223,14 +212,14 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error {
if (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) && ct == "application/json" { if (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) && ct == "application/json" {
var errorResponse types.ErrorResponse var errorResponse types.ErrorResponse
if err := json.Unmarshal(body, &errorResponse); err != nil { if err := json.Unmarshal(body, &errorResponse); err != nil {
return errors.Wrap(err, "Error reading JSON") return fmt.Errorf("Error reading JSON: %v", err)
} }
errorMessage = strings.TrimSpace(errorResponse.Message) errorMessage = errorResponse.Message
} else { } else {
errorMessage = strings.TrimSpace(string(body)) errorMessage = string(body)
} }
return errors.Wrap(errors.New(errorMessage), "Error response from daemon") return fmt.Errorf("Error response from daemon: %s", strings.TrimSpace(errorMessage))
} }
func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request { func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request {
......
...@@ -15,11 +15,11 @@ func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (t ...@@ -15,11 +15,11 @@ func (cli *Client) SecretCreate(ctx context.Context, secret swarm.SecretSpec) (t
return response, err return response, err
} }
resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil) resp, err := cli.post(ctx, "/secrets/create", nil, secret, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return response, err return response, err
} }
err = json.NewDecoder(resp.body).Decode(&response) err = json.NewDecoder(resp.body).Decode(&response)
ensureReaderClosed(resp)
return response, err return response, err
} }
...@@ -18,10 +18,10 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S ...@@ -18,10 +18,10 @@ func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.S
return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id} return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id}
} }
resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) resp, err := cli.get(ctx, "/secrets/"+id, nil, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id) return swarm.Secret{}, nil, wrapResponseError(err, resp, "secret", id)
} }
defer ensureReaderClosed(resp)
body, err := ioutil.ReadAll(resp.body) body, err := ioutil.ReadAll(resp.body)
if err != nil { if err != nil {
......
...@@ -27,12 +27,12 @@ func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptio ...@@ -27,12 +27,12 @@ func (cli *Client) SecretList(ctx context.Context, options types.SecretListOptio
} }
resp, err := cli.get(ctx, "/secrets", query, nil) resp, err := cli.get(ctx, "/secrets", query, nil)
defer ensureReaderClosed(resp)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var secrets []swarm.Secret var secrets []swarm.Secret
err = json.NewDecoder(resp.body).Decode(&secrets) err = json.NewDecoder(resp.body).Decode(&secrets)
ensureReaderClosed(resp)
return secrets, err return secrets, err
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment