vendor: update docker cadvisor winterm

This vendor change was purely for the changes in docker to allow for setting the Masked and Read-only paths. See: moby/moby#36644 But because of the docker dep update it also needed cadvisor to be updated and winterm due to changes in pkg/tlsconfig in docker See: google/cadvisor#1967 Signed-off-by: 's avatarJess Frazelle <acidburn@microsoft.com>
parent dbf7186b
...@@ -10,7 +10,7 @@ go_library( ...@@ -10,7 +10,7 @@ go_library(
"//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library", "//pkg/kubelet/apis/cri/runtime/v1alpha2:go_default_library",
"//pkg/util/tail:go_default_library", "//pkg/util/tail:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//vendor/github.com/docker/docker/pkg/jsonlog:go_default_library", "//vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog:go_default_library",
"//vendor/github.com/fsnotify/fsnotify:go_default_library", "//vendor/github.com/fsnotify/fsnotify:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
], ],
......
...@@ -168,23 +168,18 @@ filegroup( ...@@ -168,23 +168,18 @@ filegroup(
"//vendor/github.com/docker/distribution/reference:all-srcs", "//vendor/github.com/docker/distribution/reference:all-srcs",
"//vendor/github.com/docker/docker/api:all-srcs", "//vendor/github.com/docker/docker/api:all-srcs",
"//vendor/github.com/docker/docker/client:all-srcs", "//vendor/github.com/docker/docker/client:all-srcs",
"//vendor/github.com/docker/docker/pkg/ioutils:all-srcs", "//vendor/github.com/docker/docker/daemon/logger/jsonfilelog/jsonlog:all-srcs",
"//vendor/github.com/docker/docker/pkg/jsonlog:all-srcs",
"//vendor/github.com/docker/docker/pkg/jsonmessage:all-srcs", "//vendor/github.com/docker/docker/pkg/jsonmessage:all-srcs",
"//vendor/github.com/docker/docker/pkg/longpath:all-srcs",
"//vendor/github.com/docker/docker/pkg/mount:all-srcs", "//vendor/github.com/docker/docker/pkg/mount:all-srcs",
"//vendor/github.com/docker/docker/pkg/parsers:all-srcs", "//vendor/github.com/docker/docker/pkg/parsers:all-srcs",
"//vendor/github.com/docker/docker/pkg/stdcopy:all-srcs", "//vendor/github.com/docker/docker/pkg/stdcopy:all-srcs",
"//vendor/github.com/docker/docker/pkg/sysinfo:all-srcs", "//vendor/github.com/docker/docker/pkg/sysinfo:all-srcs",
"//vendor/github.com/docker/docker/pkg/system:all-srcs",
"//vendor/github.com/docker/docker/pkg/term:all-srcs", "//vendor/github.com/docker/docker/pkg/term:all-srcs",
"//vendor/github.com/docker/docker/pkg/tlsconfig:all-srcs",
"//vendor/github.com/docker/go-connections/nat:all-srcs", "//vendor/github.com/docker/go-connections/nat:all-srcs",
"//vendor/github.com/docker/go-connections/sockets:all-srcs", "//vendor/github.com/docker/go-connections/sockets:all-srcs",
"//vendor/github.com/docker/go-connections/tlsconfig:all-srcs", "//vendor/github.com/docker/go-connections/tlsconfig:all-srcs",
"//vendor/github.com/docker/go-units:all-srcs", "//vendor/github.com/docker/go-units:all-srcs",
"//vendor/github.com/docker/libnetwork/ipvs:all-srcs", "//vendor/github.com/docker/libnetwork/ipvs:all-srcs",
"//vendor/github.com/docker/libtrust:all-srcs",
"//vendor/github.com/docker/spdystream:all-srcs", "//vendor/github.com/docker/spdystream:all-srcs",
"//vendor/github.com/elazarl/go-bindata-assetfs:all-srcs", "//vendor/github.com/elazarl/go-bindata-assetfs:all-srcs",
"//vendor/github.com/elazarl/goproxy:all-srcs", "//vendor/github.com/elazarl/goproxy:all-srcs",
......
...@@ -21,7 +21,6 @@ go_library( ...@@ -21,7 +21,6 @@ go_library(
importmap = "k8s.io/kubernetes/vendor/github.com/Azure/go-ansiterm", importmap = "k8s.io/kubernetes/vendor/github.com/Azure/go-ansiterm",
importpath = "github.com/Azure/go-ansiterm", importpath = "github.com/Azure/go-ansiterm",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = ["//vendor/github.com/sirupsen/logrus:go_default_library"],
) )
filegroup( filegroup(
......
...@@ -5,7 +5,7 @@ type csiEntryState struct { ...@@ -5,7 +5,7 @@ type csiEntryState struct {
} }
func (csiState csiEntryState) Handle(b byte) (s state, e error) { func (csiState csiEntryState) Handle(b byte) (s state, e error) {
logger.Infof("CsiEntry::Handle %#x", b) csiState.parser.logf("CsiEntry::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b) nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
...@@ -25,7 +25,7 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) { ...@@ -25,7 +25,7 @@ func (csiState csiEntryState) Handle(b byte) (s state, e error) {
} }
func (csiState csiEntryState) Transition(s state) error { func (csiState csiEntryState) Transition(s state) error {
logger.Infof("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name()) csiState.parser.logf("CsiEntry::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s) csiState.baseState.Transition(s)
switch s { switch s {
......
...@@ -5,7 +5,7 @@ type csiParamState struct { ...@@ -5,7 +5,7 @@ type csiParamState struct {
} }
func (csiState csiParamState) Handle(b byte) (s state, e error) { func (csiState csiParamState) Handle(b byte) (s state, e error) {
logger.Infof("CsiParam::Handle %#x", b) csiState.parser.logf("CsiParam::Handle %#x", b)
nextState, err := csiState.baseState.Handle(b) nextState, err := csiState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
...@@ -26,7 +26,7 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) { ...@@ -26,7 +26,7 @@ func (csiState csiParamState) Handle(b byte) (s state, e error) {
} }
func (csiState csiParamState) Transition(s state) error { func (csiState csiParamState) Transition(s state) error {
logger.Infof("CsiParam::Transition %s --> %s", csiState.Name(), s.Name()) csiState.parser.logf("CsiParam::Transition %s --> %s", csiState.Name(), s.Name())
csiState.baseState.Transition(s) csiState.baseState.Transition(s)
switch s { switch s {
......
...@@ -5,7 +5,7 @@ type escapeIntermediateState struct { ...@@ -5,7 +5,7 @@ type escapeIntermediateState struct {
} }
func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
logger.Infof("escapeIntermediateState::Handle %#x", b) escState.parser.logf("escapeIntermediateState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b) nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
return nextState, err return nextState, err
...@@ -24,7 +24,7 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) { ...@@ -24,7 +24,7 @@ func (escState escapeIntermediateState) Handle(b byte) (s state, e error) {
} }
func (escState escapeIntermediateState) Transition(s state) error { func (escState escapeIntermediateState) Transition(s state) error {
logger.Infof("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name()) escState.parser.logf("escapeIntermediateState::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s) escState.baseState.Transition(s)
switch s { switch s {
......
...@@ -5,7 +5,7 @@ type escapeState struct { ...@@ -5,7 +5,7 @@ type escapeState struct {
} }
func (escState escapeState) Handle(b byte) (s state, e error) { func (escState escapeState) Handle(b byte) (s state, e error) {
logger.Infof("escapeState::Handle %#x", b) escState.parser.logf("escapeState::Handle %#x", b)
nextState, err := escState.baseState.Handle(b) nextState, err := escState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
return nextState, err return nextState, err
...@@ -28,7 +28,7 @@ func (escState escapeState) Handle(b byte) (s state, e error) { ...@@ -28,7 +28,7 @@ func (escState escapeState) Handle(b byte) (s state, e error) {
} }
func (escState escapeState) Transition(s state) error { func (escState escapeState) Transition(s state) error {
logger.Infof("Escape::Transition %s --> %s", escState.Name(), s.Name()) escState.parser.logf("Escape::Transition %s --> %s", escState.Name(), s.Name())
escState.baseState.Transition(s) escState.baseState.Transition(s)
switch s { switch s {
......
...@@ -5,7 +5,7 @@ type oscStringState struct { ...@@ -5,7 +5,7 @@ type oscStringState struct {
} }
func (oscState oscStringState) Handle(b byte) (s state, e error) { func (oscState oscStringState) Handle(b byte) (s state, e error) {
logger.Infof("OscString::Handle %#x", b) oscState.parser.logf("OscString::Handle %#x", b)
nextState, err := oscState.baseState.Handle(b) nextState, err := oscState.baseState.Handle(b)
if nextState != nil || err != nil { if nextState != nil || err != nil {
return nextState, err return nextState, err
......
...@@ -2,14 +2,10 @@ package ansiterm ...@@ -2,14 +2,10 @@ package ansiterm
import ( import (
"errors" "errors"
"io/ioutil" "log"
"os" "os"
"github.com/sirupsen/logrus"
) )
var logger *logrus.Logger
type AnsiParser struct { type AnsiParser struct {
currState state currState state
eventHandler AnsiEventHandler eventHandler AnsiEventHandler
...@@ -23,50 +19,69 @@ type AnsiParser struct { ...@@ -23,50 +19,69 @@ type AnsiParser struct {
ground state ground state
oscString state oscString state
stateMap []state stateMap []state
logf func(string, ...interface{})
} }
func CreateParser(initialState string, evtHandler AnsiEventHandler) *AnsiParser { type Option func(*AnsiParser)
logFile := ioutil.Discard
if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" { func WithLogf(f func(string, ...interface{})) Option {
logFile, _ = os.Create("ansiParser.log") return func(ap *AnsiParser) {
} ap.logf = f
logger = &logrus.Logger{
Out: logFile,
Formatter: new(logrus.TextFormatter),
Level: logrus.InfoLevel,
} }
}
parser := &AnsiParser{ func CreateParser(initialState string, evtHandler AnsiEventHandler, opts ...Option) *AnsiParser {
ap := &AnsiParser{
eventHandler: evtHandler, eventHandler: evtHandler,
context: &ansiContext{}, context: &ansiContext{},
} }
for _, o := range opts {
o(ap)
}
if isDebugEnv := os.Getenv(LogEnv); isDebugEnv == "1" {
logFile, _ := os.Create("ansiParser.log")
logger := log.New(logFile, "", log.LstdFlags)
if ap.logf != nil {
l := ap.logf
ap.logf = func(s string, v ...interface{}) {
l(s, v...)
logger.Printf(s, v...)
}
} else {
ap.logf = logger.Printf
}
}
if ap.logf == nil {
ap.logf = func(string, ...interface{}) {}
}
parser.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: parser}} ap.csiEntry = csiEntryState{baseState{name: "CsiEntry", parser: ap}}
parser.csiParam = csiParamState{baseState{name: "CsiParam", parser: parser}} ap.csiParam = csiParamState{baseState{name: "CsiParam", parser: ap}}
parser.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: parser}} ap.dcsEntry = dcsEntryState{baseState{name: "DcsEntry", parser: ap}}
parser.escape = escapeState{baseState{name: "Escape", parser: parser}} ap.escape = escapeState{baseState{name: "Escape", parser: ap}}
parser.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: parser}} ap.escapeIntermediate = escapeIntermediateState{baseState{name: "EscapeIntermediate", parser: ap}}
parser.error = errorState{baseState{name: "Error", parser: parser}} ap.error = errorState{baseState{name: "Error", parser: ap}}
parser.ground = groundState{baseState{name: "Ground", parser: parser}} ap.ground = groundState{baseState{name: "Ground", parser: ap}}
parser.oscString = oscStringState{baseState{name: "OscString", parser: parser}} ap.oscString = oscStringState{baseState{name: "OscString", parser: ap}}
parser.stateMap = []state{ ap.stateMap = []state{
parser.csiEntry, ap.csiEntry,
parser.csiParam, ap.csiParam,
parser.dcsEntry, ap.dcsEntry,
parser.escape, ap.escape,
parser.escapeIntermediate, ap.escapeIntermediate,
parser.error, ap.error,
parser.ground, ap.ground,
parser.oscString, ap.oscString,
} }
parser.currState = getState(initialState, parser.stateMap) ap.currState = getState(initialState, ap.stateMap)
logger.Infof("CreateParser: parser %p", parser) ap.logf("CreateParser: parser %p", ap)
return parser return ap
} }
func getState(name string, states []state) state { func getState(name string, states []state) state {
...@@ -97,7 +112,7 @@ func (ap *AnsiParser) handle(b byte) error { ...@@ -97,7 +112,7 @@ func (ap *AnsiParser) handle(b byte) error {
} }
if newState == nil { if newState == nil {
logger.Warning("newState is nil") ap.logf("WARNING: newState is nil")
return errors.New("New state of 'nil' is invalid.") return errors.New("New state of 'nil' is invalid.")
} }
...@@ -111,23 +126,23 @@ func (ap *AnsiParser) handle(b byte) error { ...@@ -111,23 +126,23 @@ func (ap *AnsiParser) handle(b byte) error {
} }
func (ap *AnsiParser) changeState(newState state) error { func (ap *AnsiParser) changeState(newState state) error {
logger.Infof("ChangeState %s --> %s", ap.currState.Name(), newState.Name()) ap.logf("ChangeState %s --> %s", ap.currState.Name(), newState.Name())
// Exit old state // Exit old state
if err := ap.currState.Exit(); err != nil { if err := ap.currState.Exit(); err != nil {
logger.Infof("Exit state '%s' failed with : '%v'", ap.currState.Name(), err) ap.logf("Exit state '%s' failed with : '%v'", ap.currState.Name(), err)
return err return err
} }
// Perform transition action // Perform transition action
if err := ap.currState.Transition(newState); err != nil { if err := ap.currState.Transition(newState); err != nil {
logger.Infof("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err) ap.logf("Transition from '%s' to '%s' failed with: '%v'", ap.currState.Name(), newState.Name, err)
return err return err
} }
// Enter new state // Enter new state
if err := newState.Enter(); err != nil { if err := newState.Enter(); err != nil {
logger.Infof("Enter state '%s' failed with: '%v'", newState.Name(), err) ap.logf("Enter state '%s' failed with: '%v'", newState.Name(), err)
return err return err
} }
......
...@@ -27,7 +27,6 @@ func parseParams(bytes []byte) ([]string, error) { ...@@ -27,7 +27,6 @@ func parseParams(bytes []byte) ([]string, error) {
params = append(params, s) params = append(params, s)
} }
logger.Infof("Parsed params: %v with length: %d", params, len(params))
return params, nil return params, nil
} }
...@@ -37,7 +36,6 @@ func parseCmd(context ansiContext) (string, error) { ...@@ -37,7 +36,6 @@ func parseCmd(context ansiContext) (string, error) {
func getInt(params []string, dflt int) int { func getInt(params []string, dflt int) int {
i := getInts(params, 1, dflt)[0] i := getInts(params, 1, dflt)[0]
logger.Infof("getInt: %v", i)
return i return i
} }
...@@ -60,8 +58,6 @@ func getInts(params []string, minCount int, dflt int) []int { ...@@ -60,8 +58,6 @@ func getInts(params []string, minCount int, dflt int) []int {
} }
} }
logger.Infof("getInts: %v", ints)
return ints return ints
} }
......
package ansiterm package ansiterm
import (
"fmt"
)
func (ap *AnsiParser) collectParam() error { func (ap *AnsiParser) collectParam() error {
currChar := ap.context.currentChar currChar := ap.context.currentChar
logger.Infof("collectParam %#x", currChar) ap.logf("collectParam %#x", currChar)
ap.context.paramBuffer = append(ap.context.paramBuffer, currChar) ap.context.paramBuffer = append(ap.context.paramBuffer, currChar)
return nil return nil
} }
func (ap *AnsiParser) collectInter() error { func (ap *AnsiParser) collectInter() error {
currChar := ap.context.currentChar currChar := ap.context.currentChar
logger.Infof("collectInter %#x", currChar) ap.logf("collectInter %#x", currChar)
ap.context.paramBuffer = append(ap.context.interBuffer, currChar) ap.context.paramBuffer = append(ap.context.interBuffer, currChar)
return nil return nil
} }
...@@ -21,8 +17,8 @@ func (ap *AnsiParser) collectInter() error { ...@@ -21,8 +17,8 @@ func (ap *AnsiParser) collectInter() error {
func (ap *AnsiParser) escDispatch() error { func (ap *AnsiParser) escDispatch() error {
cmd, _ := parseCmd(*ap.context) cmd, _ := parseCmd(*ap.context)
intermeds := ap.context.interBuffer intermeds := ap.context.interBuffer
logger.Infof("escDispatch currentChar: %#x", ap.context.currentChar) ap.logf("escDispatch currentChar: %#x", ap.context.currentChar)
logger.Infof("escDispatch: %v(%v)", cmd, intermeds) ap.logf("escDispatch: %v(%v)", cmd, intermeds)
switch cmd { switch cmd {
case "D": // IND case "D": // IND
...@@ -43,8 +39,9 @@ func (ap *AnsiParser) escDispatch() error { ...@@ -43,8 +39,9 @@ func (ap *AnsiParser) escDispatch() error {
func (ap *AnsiParser) csiDispatch() error { func (ap *AnsiParser) csiDispatch() error {
cmd, _ := parseCmd(*ap.context) cmd, _ := parseCmd(*ap.context)
params, _ := parseParams(ap.context.paramBuffer) params, _ := parseParams(ap.context.paramBuffer)
ap.logf("Parsed params: %v with length: %d", params, len(params))
logger.Infof("csiDispatch: %v(%v)", cmd, params) ap.logf("csiDispatch: %v(%v)", cmd, params)
switch cmd { switch cmd {
case "@": case "@":
...@@ -102,7 +99,7 @@ func (ap *AnsiParser) csiDispatch() error { ...@@ -102,7 +99,7 @@ func (ap *AnsiParser) csiDispatch() error {
top, bottom := ints[0], ints[1] top, bottom := ints[0], ints[1]
return ap.eventHandler.DECSTBM(top, bottom) return ap.eventHandler.DECSTBM(top, bottom)
default: default:
logger.Errorf(fmt.Sprintf("Unsupported CSI command: '%s', with full context: %v", cmd, ap.context)) ap.logf("ERROR: Unsupported CSI command: '%s', with full context: %v", cmd, ap.context)
return nil return nil
} }
......
...@@ -18,7 +18,6 @@ go_library( ...@@ -18,7 +18,6 @@ go_library(
deps = select({ deps = select({
"@io_bazel_rules_go//go/platform:windows": [ "@io_bazel_rules_go//go/platform:windows": [
"//vendor/github.com/Azure/go-ansiterm:go_default_library", "//vendor/github.com/Azure/go-ansiterm:go_default_library",
"//vendor/github.com/sirupsen/logrus:go_default_library",
], ],
"//conditions:default": [], "//conditions:default": [],
}), }),
......
...@@ -175,7 +175,7 @@ func GetStdFile(nFile int) (*os.File, uintptr) { ...@@ -175,7 +175,7 @@ func GetStdFile(nFile int) (*os.File, uintptr) {
fd, err := syscall.GetStdHandle(nFile) fd, err := syscall.GetStdHandle(nFile)
if err != nil { if err != nil {
panic(fmt.Errorf("Invalid standard handle indentifier: %v -- %v", nFile, err)) panic(fmt.Errorf("Invalid standard handle identifier: %v -- %v", nFile, err))
} }
return file, uintptr(fd) return file, uintptr(fd)
......
...@@ -49,17 +49,22 @@ var ( ...@@ -49,17 +49,22 @@ var (
const ( const (
// Console modes // Console modes
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx. // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx.
ENABLE_PROCESSED_INPUT = 0x0001 ENABLE_PROCESSED_INPUT = 0x0001
ENABLE_LINE_INPUT = 0x0002 ENABLE_LINE_INPUT = 0x0002
ENABLE_ECHO_INPUT = 0x0004 ENABLE_ECHO_INPUT = 0x0004
ENABLE_WINDOW_INPUT = 0x0008 ENABLE_WINDOW_INPUT = 0x0008
ENABLE_MOUSE_INPUT = 0x0010 ENABLE_MOUSE_INPUT = 0x0010
ENABLE_INSERT_MODE = 0x0020 ENABLE_INSERT_MODE = 0x0020
ENABLE_QUICK_EDIT_MODE = 0x0040 ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_EXTENDED_FLAGS = 0x0080 ENABLE_EXTENDED_FLAGS = 0x0080
ENABLE_AUTO_POSITION = 0x0100
ENABLE_PROCESSED_OUTPUT = 0x0001 ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
DISABLE_NEWLINE_AUTO_RETURN = 0x0008
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
// Character attributes // Character attributes
// Note: // Note:
......
...@@ -34,7 +34,7 @@ func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL ...@@ -34,7 +34,7 @@ func (h *windowsAnsiEventHandler) setCursorPosition(position COORD, window SMALL
if err != nil { if err != nil {
return err return err
} }
logger.Infof("Cursor position set: (%d, %d)", position.X, position.Y) h.logf("Cursor position set: (%d, %d)", position.X, position.Y)
return err return err
} }
......
...@@ -50,8 +50,8 @@ func (h *windowsAnsiEventHandler) insertLines(param int) error { ...@@ -50,8 +50,8 @@ func (h *windowsAnsiEventHandler) insertLines(param int) error {
// scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates. // scroll scrolls the provided scroll region by param lines. The scroll region is in buffer coordinates.
func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error { func (h *windowsAnsiEventHandler) scroll(param int, sr scrollRegion, info *CONSOLE_SCREEN_BUFFER_INFO) error {
logger.Infof("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom) h.logf("scroll: scrollTop: %d, scrollBottom: %d", sr.top, sr.bottom)
logger.Infof("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom) h.logf("scroll: windowTop: %d, windowBottom: %d", info.Window.Top, info.Window.Bottom)
// Copy from and clip to the scroll region (full buffer width) // Copy from and clip to the scroll region (full buffer width)
scrollRect := SMALL_RECT{ scrollRect := SMALL_RECT{
......
...@@ -6,16 +6,10 @@ go_library( ...@@ -6,16 +6,10 @@ go_library(
"common.go", "common.go",
"common_unix.go", "common_unix.go",
"common_windows.go", "common_windows.go",
"names.go",
], ],
importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api", importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api",
importpath = "github.com/docker/docker/api", importpath = "github.com/docker/docker/api",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/docker/docker/pkg/ioutils:go_default_library",
"//vendor/github.com/docker/docker/pkg/system:go_default_library",
"//vendor/github.com/docker/libtrust:go_default_library",
],
) )
filegroup( filegroup(
......
...@@ -10,7 +10,7 @@ It consists of various components in this repository: ...@@ -10,7 +10,7 @@ It consists of various components in this repository:
- `client/` The Go client used by the command-line client. It can also be used by third-party Go programs. - `client/` The Go client used by the command-line client. It can also be used by third-party Go programs.
- `daemon/` The daemon, which serves the API. - `daemon/` The daemon, which serves the API.
## Swagger definition ## Swagger definition
The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to: The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to:
...@@ -20,7 +20,7 @@ The API is defined by the [Swagger](http://swagger.io/specification/) definition ...@@ -20,7 +20,7 @@ The API is defined by the [Swagger](http://swagger.io/specification/) definition
## Updating the API documentation ## Updating the API documentation
The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, you'll need to edit this file to represent the change in the documentation. The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, edit this file to represent the change in the documentation.
The file is split into two main sections: The file is split into two main sections:
...@@ -29,9 +29,9 @@ The file is split into two main sections: ...@@ -29,9 +29,9 @@ The file is split into two main sections:
To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section. To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section.
There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919) There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919).
`swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful for when you are making edits to ensure you are doing the right thing. `swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful when making edits to ensure you are doing the right thing.
## Viewing the API documentation ## Viewing the API documentation
......
package api package api
import (
"encoding/json"
"encoding/pem"
"fmt"
"os"
"path/filepath"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/system"
"github.com/docker/libtrust"
)
// 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 string = "1.31" 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.
NoBaseImageSpecifier string = "scratch" NoBaseImageSpecifier = "scratch"
) )
// LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
// otherwise generates a new one
func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
err := system.MkdirAll(filepath.Dir(trustKeyPath), 0700, "")
if err != nil {
return nil, err
}
trustKey, err := libtrust.LoadKeyFile(trustKeyPath)
if err == libtrust.ErrKeyFileDoesNotExist {
trustKey, err = libtrust.GenerateECP256PrivateKey()
if err != nil {
return nil, fmt.Errorf("Error generating key: %s", err)
}
encodedKey, err := serializePrivateKey(trustKey, filepath.Ext(trustKeyPath))
if err != nil {
return nil, fmt.Errorf("Error serializing key: %s", err)
}
if err := ioutils.AtomicWriteFile(trustKeyPath, encodedKey, os.FileMode(0600)); err != nil {
return nil, fmt.Errorf("Error saving key file: %s", err)
}
} else if err != nil {
return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
}
return trustKey, nil
}
func serializePrivateKey(key libtrust.PrivateKey, ext string) (encoded []byte, err error) {
if ext == ".json" || ext == ".jwk" {
encoded, err = json.Marshal(key)
if err != nil {
return nil, fmt.Errorf("unable to encode private key JWK: %s", err)
}
} else {
pemBlock, err := key.PEMBlock()
if err != nil {
return nil, fmt.Errorf("unable to encode private key PEM: %s", err)
}
encoded = pem.EncodeToMemory(pemBlock)
}
return
}
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
package api package api
// MinVersion represents Minimum REST API version supported // MinVersion represents Minimum REST API version supported
const MinVersion string = "1.12" const MinVersion = "1.12"
package api
import "regexp"
// RestrictedNameChars collects the characters allowed to represent a name, normally used to validate container and volume names.
const RestrictedNameChars = `[a-zA-Z0-9][a-zA-Z0-9_.-]`
// RestrictedNamePattern is a regular expression to validate names against the collection of restricted characters.
var RestrictedNamePattern = regexp.MustCompile(`^` + RestrictedNameChars + `+$`)
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
units "github.com/docker/go-units" "github.com/docker/go-units"
) )
// CheckpointCreateOptions holds parameters to create a checkpoint from a container // CheckpointCreateOptions holds parameters to create a checkpoint from a container
...@@ -74,6 +74,7 @@ type ContainerLogsOptions struct { ...@@ -74,6 +74,7 @@ type ContainerLogsOptions struct {
ShowStdout bool ShowStdout bool
ShowStderr bool ShowStderr bool
Since string Since string
Until string
Timestamps bool Timestamps bool
Follow bool Follow bool
Tail string Tail string
...@@ -179,10 +180,7 @@ type ImageBuildOptions struct { ...@@ -179,10 +180,7 @@ type ImageBuildOptions struct {
ExtraHosts []string // List of extra hosts ExtraHosts []string // List of extra hosts
Target string Target string
SessionID string SessionID string
Platform string
// TODO @jhowardmsft LCOW Support: This will require extending to include
// `Platform string`, but is ommited for now as it's hard-coded temporarily
// to avoid API changes.
} }
// ImageBuildResponse holds information // ImageBuildResponse holds information
...@@ -195,7 +193,8 @@ type ImageBuildResponse struct { ...@@ -195,7 +193,8 @@ type ImageBuildResponse struct {
// ImageCreateOptions holds information to create images. // ImageCreateOptions holds information to create images.
type ImageCreateOptions struct { type ImageCreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
} }
// ImageImportSource holds source information for ImageImport // ImageImportSource holds source information for ImageImport
...@@ -206,9 +205,10 @@ type ImageImportSource struct { ...@@ -206,9 +205,10 @@ type ImageImportSource struct {
// ImageImportOptions holds information to import images from the client host. // ImageImportOptions holds information to import images from the client host.
type ImageImportOptions struct { type ImageImportOptions struct {
Tag string // Tag is the name to tag this image with. This attribute is deprecated. Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
} }
// ImageListOptions holds parameters to filter the list of images with. // ImageListOptions holds parameters to filter the list of images with.
...@@ -229,6 +229,7 @@ type ImagePullOptions struct { ...@@ -229,6 +229,7 @@ type ImagePullOptions struct {
All bool All bool
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
PrivilegeFunc RequestPrivilegeFunc PrivilegeFunc RequestPrivilegeFunc
Platform string
} }
// RequestPrivilegeFunc is a function interface that // RequestPrivilegeFunc is a function interface that
......
...@@ -16,7 +16,6 @@ type ContainerCreateConfig struct { ...@@ -16,7 +16,6 @@ type ContainerCreateConfig struct {
HostConfig *container.HostConfig HostConfig *container.HostConfig
NetworkingConfig *network.NetworkingConfig NetworkingConfig *network.NetworkingConfig
AdjustCPUShares bool AdjustCPUShares bool
Platform string
} }
// ContainerRmConfig holds arguments for the container remove // ContainerRmConfig holds arguments for the container remove
...@@ -26,19 +25,6 @@ type ContainerRmConfig struct { ...@@ -26,19 +25,6 @@ type ContainerRmConfig struct {
ForceRemove, RemoveVolume, RemoveLink bool ForceRemove, RemoveVolume, RemoveLink bool
} }
// ContainerCommitConfig contains build configs for commit operation,
// and is used when making a commit with the current state of the container.
type ContainerCommitConfig struct {
Pause bool
Repo string
Tag string
Author string
Comment string
// merge container config into commit config before commit
MergeConfigs bool
Config *container.Config
}
// ExecConfig is a small subset of the Config struct that holds the configuration // ExecConfig is a small subset of the Config struct that holds the configuration
// for the exec feature of docker. // for the exec feature of docker.
type ExecConfig struct { type ExecConfig struct {
...@@ -51,6 +37,7 @@ type ExecConfig struct { ...@@ -51,6 +37,7 @@ type ExecConfig struct {
Detach bool // Execute in detach mode Detach bool // Execute in detach mode
DetachKeys string // Escape keys for detach DetachKeys string // Escape keys for detach
Env []string // Environment variables Env []string // Environment variables
WorkingDir string // Working directory
Cmd []string // Execution commands and args Cmd []string // Execution commands and args
} }
......
...@@ -7,7 +7,7 @@ package container ...@@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerChangeResponseItem container change response item // ContainerChangeResponseItem change item in response to ContainerChanges operation
// swagger:model ContainerChangeResponseItem // swagger:model ContainerChangeResponseItem
type ContainerChangeResponseItem struct { type ContainerChangeResponseItem struct {
......
...@@ -7,7 +7,7 @@ package container ...@@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerCreateCreatedBody container create created body // ContainerCreateCreatedBody OK response to ContainerCreate operation
// swagger:model ContainerCreateCreatedBody // swagger:model ContainerCreateCreatedBody
type ContainerCreateCreatedBody struct { type ContainerCreateCreatedBody struct {
......
...@@ -7,7 +7,7 @@ package container ...@@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerTopOKBody container top o k body // ContainerTopOKBody OK response to ContainerTop operation
// swagger:model ContainerTopOKBody // swagger:model ContainerTopOKBody
type ContainerTopOKBody struct { type ContainerTopOKBody struct {
......
...@@ -7,7 +7,7 @@ package container ...@@ -7,7 +7,7 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerUpdateOKBody container update o k body // ContainerUpdateOKBody OK response to ContainerUpdate operation
// swagger:model ContainerUpdateOKBody // swagger:model ContainerUpdateOKBody
type ContainerUpdateOKBody struct { type ContainerUpdateOKBody struct {
......
...@@ -7,10 +7,22 @@ package container ...@@ -7,10 +7,22 @@ package container
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ContainerWaitOKBody container wait o k body // ContainerWaitOKBodyError container waiting error, if any
// swagger:model ContainerWaitOKBodyError
type ContainerWaitOKBodyError struct {
// Details of an error
Message string `json:"Message,omitempty"`
}
// ContainerWaitOKBody OK response to ContainerWait operation
// swagger:model ContainerWaitOKBody // swagger:model ContainerWaitOKBody
type ContainerWaitOKBody struct { type ContainerWaitOKBody struct {
// error
// Required: true
Error *ContainerWaitOKBodyError `json:"Error"`
// Exit code of the container // Exit code of the container
// Required: true // Required: true
StatusCode int64 `json:"StatusCode"` StatusCode int64 `json:"StatusCode"`
......
...@@ -20,44 +20,70 @@ func (i Isolation) IsDefault() bool { ...@@ -20,44 +20,70 @@ func (i Isolation) IsDefault() bool {
return strings.ToLower(string(i)) == "default" || string(i) == "" return strings.ToLower(string(i)) == "default" || string(i) == ""
} }
// IsHyperV indicates the use of a Hyper-V partition for isolation
func (i Isolation) IsHyperV() bool {
return strings.ToLower(string(i)) == "hyperv"
}
// IsProcess indicates the use of process isolation
func (i Isolation) IsProcess() bool {
return strings.ToLower(string(i)) == "process"
}
const (
// IsolationEmpty is unspecified (same behavior as default)
IsolationEmpty = Isolation("")
// IsolationDefault is the default isolation mode on current daemon
IsolationDefault = Isolation("default")
// IsolationProcess is process isolation mode
IsolationProcess = Isolation("process")
// IsolationHyperV is HyperV isolation mode
IsolationHyperV = Isolation("hyperv")
)
// IpcMode represents the container ipc stack. // IpcMode represents the container ipc stack.
type IpcMode string type IpcMode string
// IsPrivate indicates whether the container uses its private ipc stack. // IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared.
func (n IpcMode) IsPrivate() bool { func (n IpcMode) IsPrivate() bool {
return !(n.IsHost() || n.IsContainer()) return n == "private"
} }
// IsHost indicates whether the container uses the host's ipc stack. // IsHost indicates whether the container shares the host's ipc namespace.
func (n IpcMode) IsHost() bool { func (n IpcMode) IsHost() bool {
return n == "host" return n == "host"
} }
// IsContainer indicates whether the container uses a container's ipc stack. // IsShareable indicates whether the container's ipc namespace can be shared with another container.
func (n IpcMode) IsShareable() bool {
return n == "shareable"
}
// IsContainer indicates whether the container uses another container's ipc namespace.
func (n IpcMode) IsContainer() bool { func (n IpcMode) IsContainer() bool {
parts := strings.SplitN(string(n), ":", 2) parts := strings.SplitN(string(n), ":", 2)
return len(parts) > 1 && parts[0] == "container" return len(parts) > 1 && parts[0] == "container"
} }
// Valid indicates whether the ipc stack is valid. // IsNone indicates whether container IpcMode is set to "none".
func (n IpcMode) IsNone() bool {
return n == "none"
}
// IsEmpty indicates whether container IpcMode is empty
func (n IpcMode) IsEmpty() bool {
return n == ""
}
// Valid indicates whether the ipc mode is valid.
func (n IpcMode) Valid() bool { func (n IpcMode) Valid() bool {
parts := strings.Split(string(n), ":") return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
switch mode := parts[0]; mode {
case "", "host":
case "container":
if len(parts) != 2 || parts[1] == "" {
return false
}
default:
return false
}
return true
} }
// Container returns the name of the container ipc stack is going to be used. // Container returns the name of the container ipc stack is going to be used.
func (n IpcMode) Container() string { func (n IpcMode) Container() string {
parts := strings.SplitN(string(n), ":", 2) parts := strings.SplitN(string(n), ":", 2)
if len(parts) > 1 { if len(parts) > 1 && parts[0] == "container" {
return parts[1] return parts[1]
} }
return "" return ""
...@@ -375,6 +401,12 @@ type HostConfig struct { ...@@ -375,6 +401,12 @@ type HostConfig struct {
// Mounts specs used by the container // Mounts specs used by the container
Mounts []mount.Mount `json:",omitempty"` Mounts []mount.Mount `json:",omitempty"`
// MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths)
MaskedPaths []string
// ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths)
ReadonlyPaths []string
// Run a custom init inside the container, if null, use the daemon's configured settings // Run a custom init inside the container, if null, use the daemon's configured settings
Init *bool `json:",omitempty"` Init *bool `json:",omitempty"`
} }
package container package container
import (
"strings"
)
// IsBridge indicates whether container uses the bridge network stack // IsBridge indicates whether container uses the bridge network stack
// in windows it is given the name NAT // in windows it is given the name NAT
func (n NetworkMode) IsBridge() bool { func (n NetworkMode) IsBridge() bool {
...@@ -21,16 +17,6 @@ func (n NetworkMode) IsUserDefined() bool { ...@@ -21,16 +17,6 @@ func (n NetworkMode) IsUserDefined() bool {
return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer() return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer()
} }
// IsHyperV indicates the use of a Hyper-V partition for isolation
func (i Isolation) IsHyperV() bool {
return strings.ToLower(string(i)) == "hyperv"
}
// IsProcess indicates the use of process isolation
func (i Isolation) IsProcess() bool {
return strings.ToLower(string(i)) == "process"
}
// IsValid indicates if an isolation technology is valid // IsValid indicates if an isolation technology is valid
func (i Isolation) IsValid() bool { func (i Isolation) IsValid() bool {
return i.IsDefault() || i.IsHyperV() || i.IsProcess() return i.IsDefault() || i.IsHyperV() || i.IsProcess()
......
...@@ -7,7 +7,7 @@ package image ...@@ -7,7 +7,7 @@ package image
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// HistoryResponseItem history response item // HistoryResponseItem individual image layer information in response to ImageHistory operation
// swagger:model HistoryResponseItem // swagger:model HistoryResponseItem
type HistoryResponseItem struct { type HistoryResponseItem struct {
......
...@@ -15,6 +15,8 @@ const ( ...@@ -15,6 +15,8 @@ const (
TypeVolume Type = "volume" TypeVolume Type = "volume"
// TypeTmpfs is the type for mounting tmpfs // TypeTmpfs is the type for mounting tmpfs
TypeTmpfs Type = "tmpfs" TypeTmpfs Type = "tmpfs"
// TypeNamedPipe is the type for mounting Windows named pipes
TypeNamedPipe Type = "npipe"
) )
// Mount represents a mount (volume). // Mount represents a mount (volume).
...@@ -65,7 +67,7 @@ var Propagations = []Propagation{ ...@@ -65,7 +67,7 @@ var Propagations = []Propagation{
type Consistency string type Consistency string
const ( const (
// ConsistencyFull guarantees bind-mount-like consistency // ConsistencyFull guarantees bind mount-like consistency
ConsistencyFull Consistency = "consistent" ConsistencyFull Consistency = "consistent"
// ConsistencyCached mounts can cache read data and FS structure // ConsistencyCached mounts can cache read data and FS structure
ConsistencyCached Consistency = "cached" ConsistencyCached Consistency = "cached"
......
...@@ -121,6 +121,9 @@ type PluginConfigArgs struct { ...@@ -121,6 +121,9 @@ type PluginConfigArgs struct {
// swagger:model PluginConfigInterface // swagger:model PluginConfigInterface
type PluginConfigInterface struct { type PluginConfigInterface struct {
// Protocol to use for clients connecting to the plugin.
ProtocolScheme string `json:"ProtocolScheme,omitempty"`
// socket // socket
// Required: true // Required: true
Socket string `json:"Socket"` Socket string `json:"Socket"`
......
...@@ -7,7 +7,7 @@ package types ...@@ -7,7 +7,7 @@ package types
// swagger:model Port // swagger:model Port
type Port struct { type Port struct {
// IP // Host IP address that the container's port is mapped to
IP string `json:"IP,omitempty"` IP string `json:"IP,omitempty"`
// Port on the container // Port on the container
......
...@@ -20,7 +20,7 @@ type Annotations struct { ...@@ -20,7 +20,7 @@ type Annotations struct {
Labels map[string]string `json:"Labels"` Labels map[string]string `json:"Labels"`
} }
// Driver represents a driver (network, logging). // Driver represents a driver (network, logging, secrets backend).
type Driver struct { type Driver struct {
Name string `json:",omitempty"` Name string `json:",omitempty"`
Options map[string]string `json:",omitempty"` Options map[string]string `json:",omitempty"`
......
...@@ -13,6 +13,10 @@ type Config struct { ...@@ -13,6 +13,10 @@ type Config struct {
type ConfigSpec struct { type ConfigSpec struct {
Annotations Annotations
Data []byte `json:",omitempty"` Data []byte `json:",omitempty"`
// Templating controls whether and how to evaluate the config payload as
// a template. If it is not set, no templating is used.
Templating *Driver `json:",omitempty"`
} }
// ConfigReferenceFileTarget is a file target in a config reference // ConfigReferenceFileTarget is a file target in a config reference
......
...@@ -55,6 +55,7 @@ type ContainerSpec struct { ...@@ -55,6 +55,7 @@ type ContainerSpec struct {
User string `json:",omitempty"` User string `json:",omitempty"`
Groups []string `json:",omitempty"` Groups []string `json:",omitempty"`
Privileges *Privileges `json:",omitempty"` Privileges *Privileges `json:",omitempty"`
Init *bool `json:",omitempty"`
StopSignal string `json:",omitempty"` StopSignal string `json:",omitempty"`
TTY bool `json:",omitempty"` TTY bool `json:",omitempty"`
OpenStdin bool `json:",omitempty"` OpenStdin bool `json:",omitempty"`
...@@ -65,8 +66,9 @@ type ContainerSpec struct { ...@@ -65,8 +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"`
} }
...@@ -62,6 +62,8 @@ const ( ...@@ -62,6 +62,8 @@ const (
PortConfigProtocolTCP PortConfigProtocol = "tcp" PortConfigProtocolTCP PortConfigProtocol = "tcp"
// PortConfigProtocolUDP UDP // PortConfigProtocolUDP UDP
PortConfigProtocolUDP PortConfigProtocol = "udp" PortConfigProtocolUDP PortConfigProtocol = "udp"
// PortConfigProtocolSCTP SCTP
PortConfigProtocolSCTP PortConfigProtocol = "sctp"
) )
// EndpointVirtualIP represents the virtual ip of a port. // EndpointVirtualIP represents the virtual ip of a port.
......
...@@ -11,9 +11,17 @@ const ( ...@@ -11,9 +11,17 @@ const (
RuntimeContainer RuntimeType = "container" RuntimeContainer RuntimeType = "container"
// RuntimePlugin is the plugin based runtime // RuntimePlugin is the plugin based runtime
RuntimePlugin RuntimeType = "plugin" RuntimePlugin RuntimeType = "plugin"
// RuntimeNetworkAttachment is the network attachment runtime
RuntimeNetworkAttachment RuntimeType = "attachment"
// RuntimeURLContainer is the proto url for the container type // RuntimeURLContainer is the proto url for the container type
RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer" RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer"
// RuntimeURLPlugin is the proto url for the plugin type // RuntimeURLPlugin is the proto url for the plugin type
RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin" RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin"
) )
// NetworkAttachmentSpec represents the runtime spec type for network
// attachment tasks
type NetworkAttachmentSpec struct {
ContainerID string
}
syntax = "proto3"; syntax = "proto3";
option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime";
// PluginSpec defines the base payload which clients can specify for creating // PluginSpec defines the base payload which clients can specify for creating
// a service with the plugin runtime. // a service with the plugin runtime.
message PluginSpec { message PluginSpec {
......
...@@ -14,6 +14,10 @@ type SecretSpec struct { ...@@ -14,6 +14,10 @@ type SecretSpec struct {
Annotations Annotations
Data []byte `json:",omitempty"` Data []byte `json:",omitempty"`
Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store
// Templating controls whether and how to evaluate the secret payload as
// a template. If it is not set, no templating is used.
Templating *Driver `json:",omitempty"`
} }
// SecretReferenceFileTarget is a file target in a secret reference // SecretReferenceFileTarget is a file target in a secret reference
......
...@@ -36,6 +36,10 @@ const ( ...@@ -36,6 +36,10 @@ const (
TaskStateFailed TaskState = "failed" TaskStateFailed TaskState = "failed"
// TaskStateRejected REJECTED // TaskStateRejected REJECTED
TaskStateRejected TaskState = "rejected" TaskStateRejected TaskState = "rejected"
// TaskStateRemove REMOVE
TaskStateRemove TaskState = "remove"
// TaskStateOrphaned ORPHANED
TaskStateOrphaned TaskState = "orphaned"
) )
// Task represents a task. // Task represents a task.
...@@ -56,10 +60,13 @@ type Task struct { ...@@ -56,10 +60,13 @@ type Task struct {
// TaskSpec represents the spec of a task. // TaskSpec represents the spec of a task.
type TaskSpec struct { type TaskSpec struct {
// ContainerSpec and PluginSpec are mutually exclusive. // ContainerSpec, NetworkAttachmentSpec, and PluginSpec are mutually exclusive.
// PluginSpec will only be used when the `Runtime` field is set to `plugin` // PluginSpec is only used when the `Runtime` field is set to `plugin`
ContainerSpec *ContainerSpec `json:",omitempty"` // NetworkAttachmentSpec is used if the `Runtime` field is set to
PluginSpec *runtime.PluginSpec `json:",omitempty"` // `attachment`.
ContainerSpec *ContainerSpec `json:",omitempty"`
PluginSpec *runtime.PluginSpec `json:",omitempty"`
NetworkAttachmentSpec *NetworkAttachmentSpec `json:",omitempty"`
Resources *ResourceRequirements `json:",omitempty"` Resources *ResourceRequirements `json:",omitempty"`
RestartPolicy *RestartPolicy `json:",omitempty"` RestartPolicy *RestartPolicy `json:",omitempty"`
...@@ -162,19 +169,19 @@ const ( ...@@ -162,19 +169,19 @@ const (
// TaskStatus represents the status of a task. // TaskStatus represents the status of a task.
type TaskStatus struct { type TaskStatus struct {
Timestamp time.Time `json:",omitempty"` Timestamp time.Time `json:",omitempty"`
State TaskState `json:",omitempty"` State TaskState `json:",omitempty"`
Message string `json:",omitempty"` Message string `json:",omitempty"`
Err string `json:",omitempty"` Err string `json:",omitempty"`
ContainerStatus ContainerStatus `json:",omitempty"` ContainerStatus *ContainerStatus `json:",omitempty"`
PortStatus PortStatus `json:",omitempty"` PortStatus PortStatus `json:",omitempty"`
} }
// ContainerStatus represents the status of a container. // ContainerStatus represents the status of a container.
type ContainerStatus struct { type ContainerStatus struct {
ContainerID string `json:",omitempty"` ContainerID string
PID int `json:",omitempty"` PID int
ExitCode int `json:",omitempty"` ExitCode int
} }
// PortStatus represents the port status of a task's host ports whose // PortStatus represents the port status of a task's host ports whose
......
...@@ -29,10 +29,8 @@ func GetTimestamp(value string, reference time.Time) (string, error) { ...@@ -29,10 +29,8 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
} }
var format string var format string
var parseInLocation bool
// if the string has a Z or a + or three dashes use parse otherwise use parseinlocation // if the string has a Z or a + or three dashes use parse otherwise use parseinlocation
parseInLocation = !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3) parseInLocation := !(strings.ContainsAny(value, "zZ+") || strings.Count(value, "-") == 3)
if strings.Contains(value, ".") { if strings.Contains(value, ".") {
if parseInLocation { if parseInLocation {
...@@ -84,11 +82,14 @@ func GetTimestamp(value string, reference time.Time) (string, error) { ...@@ -84,11 +82,14 @@ func GetTimestamp(value string, reference time.Time) (string, error) {
} }
if err != nil { if err != nil {
// if there is a `-` then it's an RFC3339 like timestamp otherwise assume unixtimestamp // if there is a `-` then it's an RFC3339 like timestamp
if strings.Contains(value, "-") { if strings.Contains(value, "-") {
return "", err // was probably an RFC3339 like timestamp but the parser failed with an error return "", err // was probably an RFC3339 like timestamp but the parser failed with an error
} }
return value, nil // unixtimestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server) if _, _, err := parseTimestamp(value); err != nil {
return "", fmt.Errorf("failed to parse value as time or duration: %q", value)
}
return value, nil // unix timestamp in and out case (meaning: the value passed at the command line is already in the right format for passing to the server)
} }
return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil return fmt.Sprintf("%d.%09d", t.Unix(), int64(t.Nanosecond())), nil
...@@ -106,6 +107,10 @@ func ParseTimestamps(value string, def int64) (int64, int64, error) { ...@@ -106,6 +107,10 @@ func ParseTimestamps(value string, def int64) (int64, int64, error) {
if value == "" { if value == "" {
return def, 0, nil return def, 0, nil
} }
return parseTimestamp(value)
}
func parseTimestamp(value string) (int64, int64, error) {
sa := strings.SplitN(value, ".", 2) sa := strings.SplitN(value, ".", 2)
s, err := strconv.ParseInt(sa[0], 10, 64) s, err := strconv.ParseInt(sa[0], 10, 64)
if err != nil { if err != nil {
......
...@@ -107,9 +107,21 @@ type Ping struct { ...@@ -107,9 +107,21 @@ type Ping struct {
Experimental bool Experimental bool
} }
// ComponentVersion describes the version information for a specific component.
type ComponentVersion struct {
Name string
Version string
Details map[string]string `json:",omitempty"`
}
// Version contains response of Engine API: // Version contains response of Engine API:
// GET "/version" // GET "/version"
type Version struct { type Version struct {
Platform struct{ Name string } `json:",omitempty"`
Components []ComponentVersion `json:",omitempty"`
// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
Version string Version string
APIVersion string `json:"ApiVersion"` APIVersion string `json:"ApiVersion"`
MinAPIVersion string `json:"MinAPIVersion,omitempty"` MinAPIVersion string `json:"MinAPIVersion,omitempty"`
......
...@@ -3,8 +3,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") ...@@ -3,8 +3,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"volumes_create.go", "volume_create.go",
"volumes_list.go", "volume_list.go",
], ],
importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api/types/volume", importmap = "k8s.io/kubernetes/vendor/github.com/docker/docker/api/types/volume",
importpath = "github.com/docker/docker/api/types/volume", importpath = "github.com/docker/docker/api/types/volume",
......
...@@ -7,9 +7,9 @@ package volume ...@@ -7,9 +7,9 @@ package volume
// See hack/generate-swagger-api.sh // See hack/generate-swagger-api.sh
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// VolumesCreateBody volumes create body // VolumeCreateBody
// swagger:model VolumesCreateBody // swagger:model VolumeCreateBody
type VolumesCreateBody struct { type VolumeCreateBody struct {
// Name of the volume driver to use. // Name of the volume driver to use.
// Required: true // Required: true
......
...@@ -9,9 +9,9 @@ package volume ...@@ -9,9 +9,9 @@ package volume
import "github.com/docker/docker/api/types" import "github.com/docker/docker/api/types"
// VolumesListOKBody volumes list o k body // VolumeListOKBody
// swagger:model VolumesListOKBody // swagger:model VolumeListOKBody
type VolumesListOKBody struct { type VolumeListOKBody struct {
// List of volumes // List of volumes
// Required: true // Required: true
......
...@@ -74,7 +74,6 @@ go_library( ...@@ -74,7 +74,6 @@ go_library(
"node_list.go", "node_list.go",
"node_remove.go", "node_remove.go",
"node_update.go", "node_update.go",
"parse_logs.go",
"ping.go", "ping.go",
"plugin_create.go", "plugin_create.go",
"plugin_disable.go", "plugin_disable.go",
...@@ -135,12 +134,10 @@ go_library( ...@@ -135,12 +134,10 @@ go_library(
"//vendor/github.com/docker/docker/api/types/time:go_default_library", "//vendor/github.com/docker/docker/api/types/time:go_default_library",
"//vendor/github.com/docker/docker/api/types/versions:go_default_library", "//vendor/github.com/docker/docker/api/types/versions:go_default_library",
"//vendor/github.com/docker/docker/api/types/volume:go_default_library", "//vendor/github.com/docker/docker/api/types/volume:go_default_library",
"//vendor/github.com/docker/docker/pkg/tlsconfig:go_default_library",
"//vendor/github.com/docker/go-connections/sockets:go_default_library", "//vendor/github.com/docker/go-connections/sockets:go_default_library",
"//vendor/github.com/docker/go-connections/tlsconfig:go_default_library", "//vendor/github.com/docker/go-connections/tlsconfig:go_default_library",
"//vendor/github.com/opencontainers/go-digest:go_default_library", "//vendor/github.com/opencontainers/go-digest:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library", "//vendor/github.com/pkg/errors:go_default_library",
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/golang.org/x/net/context/ctxhttp:go_default_library", "//vendor/golang.org/x/net/context/ctxhttp:go_default_library",
], ],
) )
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// BuildCachePrune requests the daemon to delete unused cache data // BuildCachePrune requests the daemon to delete unused cache data
......
package client package client
import ( import (
"context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// CheckpointCreate creates a checkpoint from the given container with the given name // CheckpointCreate creates a checkpoint from the given container with the given name
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// CheckpointDelete deletes the checkpoint with the given name from the given container // CheckpointDelete deletes the checkpoint with the given name from the given container
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// CheckpointList returns the checkpoints of the given container in the docker host // CheckpointList returns the checkpoints of the given container in the docker host
...@@ -20,10 +19,7 @@ func (cli *Client) CheckpointList(ctx context.Context, container string, options ...@@ -20,10 +19,7 @@ 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)
if err != nil { if err != nil {
if resp.statusCode == http.StatusNotFound { return checkpoints, wrapResponseError(err, resp, "container", container)
return checkpoints, containerNotFoundError{container}
}
return checkpoints, err
} }
err = json.NewDecoder(resp.body).Decode(&checkpoints) err = json.NewDecoder(resp.body).Decode(&checkpoints)
......
// +build linux freebsd solaris openbsd darwin // +build linux freebsd openbsd darwin
package client package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset // DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "unix:///var/run/docker.sock" const DefaultDockerHost = "unix:///var/run/docker.sock"
const defaultProto = "unix"
const defaultAddr = "/var/run/docker.sock"
...@@ -2,3 +2,6 @@ package client ...@@ -2,3 +2,6 @@ package client
// DefaultDockerHost defines os specific default if DOCKER_HOST is unset // DefaultDockerHost defines os specific default if DOCKER_HOST is unset
const DefaultDockerHost = "npipe:////./pipe/docker_engine" const DefaultDockerHost = "npipe:////./pipe/docker_engine"
const defaultProto = "npipe"
const defaultAddr = "//./pipe/docker_engine"
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigCreate creates a new Config. // ConfigCreate creates a new Config.
......
...@@ -2,25 +2,24 @@ package client ...@@ -2,25 +2,24 @@ package client
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigInspectWithRaw returns the config information with raw data // ConfigInspectWithRaw returns the config information with raw data
func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) { func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) {
if id == "" {
return swarm.Config{}, nil, objectNotFoundError{object: "config", id: id}
}
if err := cli.NewVersionError("1.30", "config inspect"); err != nil { if err := cli.NewVersionError("1.30", "config inspect"); err != nil {
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)
if err != nil { if err != nil {
if resp.statusCode == http.StatusNotFound { return swarm.Config{}, nil, wrapResponseError(err, resp, "config", id)
return swarm.Config{}, nil, configNotFoundError{id}
}
return swarm.Config{}, nil, err
} }
defer ensureReaderClosed(resp) defer ensureReaderClosed(resp)
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"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/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigList returns the list of configs. // ConfigList returns the list of configs.
...@@ -18,7 +18,7 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio ...@@ -18,7 +18,7 @@ func (cli *Client) ConfigList(ctx context.Context, options types.ConfigListOptio
query := url.Values{} query := url.Values{}
if options.Filters.Len() > 0 { if options.Filters.Len() > 0 {
filterJSON, err := filters.ToParam(options.Filters) filterJSON, err := filters.ToJSON(options.Filters)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
package client package client
import "golang.org/x/net/context" import "context"
// ConfigRemove removes a Config. // ConfigRemove removes a Config.
func (cli *Client) ConfigRemove(ctx context.Context, id string) error { func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
...@@ -9,5 +9,5 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error { ...@@ -9,5 +9,5 @@ func (cli *Client) ConfigRemove(ctx context.Context, id string) error {
} }
resp, err := cli.delete(ctx, "/configs/"+id, nil, nil) resp, err := cli.delete(ctx, "/configs/"+id, nil, nil)
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return wrapResponseError(err, resp, "config", id)
} }
package client package client
import ( import (
"context"
"net/url" "net/url"
"strconv" "strconv"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"golang.org/x/net/context"
) )
// ConfigUpdate attempts to update a Config // ConfigUpdate attempts to update a Config
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerAttach attaches a connection to a container in the server. // ContainerAttach attaches a connection to a container in the server.
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"errors" "errors"
"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"
"golang.org/x/net/context"
) )
// ContainerCommit applies changes into a container and creates a new tagged image. // ContainerCommit applies changes into a container and creates a new tagged image.
...@@ -39,7 +39,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option ...@@ -39,7 +39,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, container string, option
for _, change := range options.Changes { for _, change := range options.Changes {
query.Add("changes", change) query.Add("changes", change)
} }
if options.Pause != true { if !options.Pause {
query.Set("pause", "0") query.Set("pause", "0")
} }
......
package client package client
import ( import (
"context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
...@@ -10,8 +11,6 @@ import ( ...@@ -10,8 +11,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
) )
...@@ -23,17 +22,17 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri ...@@ -23,17 +22,17 @@ 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)
if err != nil { if err != nil {
return types.ContainerPathStat{}, err return types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+path)
} }
defer ensureReaderClosed(response) defer ensureReaderClosed(response)
return getContainerPathStatFromHeader(response.header) return getContainerPathStatFromHeader(response.header)
} }
// CopyToContainer copies content into the container filesystem. // CopyToContainer copies content into the container filesystem.
// Note that `content` must be a Reader for a TAR // Note that `content` must be a Reader for a TAR archive
func (cli *Client) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error { func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options types.CopyToContainerOptions) error {
query := url.Values{} query := url.Values{}
query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. query.Set("path", filepath.ToSlash(dstPath)) // Normalize the paths used in the API.
// Do not allow for an existing directory to be overwritten by a non-directory and vice versa. // Do not allow for an existing directory to be overwritten by a non-directory and vice versa.
if !options.AllowOverwriteDirWithFile { if !options.AllowOverwriteDirWithFile {
query.Set("noOverwriteDirNonDir", "true") query.Set("noOverwriteDirNonDir", "true")
...@@ -43,11 +42,11 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string, ...@@ -43,11 +42,11 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string,
query.Set("copyUIDGID", "true") query.Set("copyUIDGID", "true")
} }
apiPath := "/containers/" + container + "/archive" apiPath := "/containers/" + containerID + "/archive"
response, err := cli.putRaw(ctx, apiPath, query, content, nil) response, err := cli.putRaw(ctx, apiPath, query, content, nil)
if err != nil { if err != nil {
return err return wrapResponseError(err, response, "container:path", containerID+":"+dstPath)
} }
defer ensureReaderClosed(response) defer ensureReaderClosed(response)
...@@ -59,15 +58,15 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string, ...@@ -59,15 +58,15 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string,
} }
// CopyFromContainer gets the content from the container and returns it as a Reader // CopyFromContainer gets the content from the container and returns it as a Reader
// to manipulate it in the host. It's up to the caller to close the reader. // for a TAR archive to manipulate it in the host. It's up to the caller to close the reader.
func (cli *Client) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) { func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, types.ContainerPathStat, error) {
query := make(url.Values, 1) query := make(url.Values, 1)
query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API.
apiPath := "/containers/" + container + "/archive" apiPath := "/containers/" + containerID + "/archive"
response, err := cli.get(ctx, apiPath, query, nil) response, err := cli.get(ctx, apiPath, query, nil)
if err != nil { if err != nil {
return nil, types.ContainerPathStat{}, err return nil, types.ContainerPathStat{}, wrapResponseError(err, response, "container:path", containerID+":"+srcPath)
} }
if response.statusCode != http.StatusOK { if response.statusCode != http.StatusOK {
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strings" "strings"
...@@ -8,7 +9,6 @@ import ( ...@@ -8,7 +9,6 @@ import (
"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"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"golang.org/x/net/context"
) )
type configWrapper struct { type configWrapper struct {
...@@ -45,7 +45,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config ...@@ -45,7 +45,7 @@ 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)
if err != nil { if err != nil {
if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") { if serverResp.statusCode == 404 && strings.Contains(err.Error(), "No such image") {
return response, imageNotFoundError{config.Image} return response, objectNotFoundError{object: "image", id: config.Image}
} }
return response, err return response, err
} }
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"golang.org/x/net/context"
) )
// ContainerDiff shows differences in a container filesystem since it was started. // ContainerDiff shows differences in a container filesystem since it was started.
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerExecCreate creates a new exec configuration to run an exec process. // ContainerExecCreate creates a new exec configuration to run an exec process.
...@@ -35,7 +35,7 @@ func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config ...@@ -35,7 +35,7 @@ func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config
// It returns a types.HijackedConnection with the hijacked connection // It returns a types.HijackedConnection with the hijacked connection
// and the a reader to get output. It's up to the called to close // and the a reader to get output. It's up to the called to close
// the hijacked connection by calling types.HijackedResponse.Close. // the hijacked connection by calling types.HijackedResponse.Close.
func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecConfig) (types.HijackedResponse, error) { func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) {
headers := map[string][]string{"Content-Type": {"application/json"}} headers := map[string][]string{"Content-Type": {"application/json"}}
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers) return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, headers)
} }
......
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"golang.org/x/net/context"
) )
// ContainerExport retrieves the raw contents of a container // ContainerExport retrieves the raw contents of a container
......
...@@ -2,23 +2,22 @@ package client ...@@ -2,23 +2,22 @@ package client
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerInspect returns the container information. // ContainerInspect returns the container information.
func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) { func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) {
if 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)
if err != nil { if err != nil {
if serverResp.statusCode == http.StatusNotFound { return types.ContainerJSON{}, wrapResponseError(err, serverResp, "container", containerID)
return types.ContainerJSON{}, containerNotFoundError{containerID}
}
return types.ContainerJSON{}, err
} }
var response types.ContainerJSON var response types.ContainerJSON
...@@ -29,16 +28,16 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty ...@@ -29,16 +28,16 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty
// ContainerInspectWithRaw returns the container information and its raw representation. // ContainerInspectWithRaw returns the container information and its raw representation.
func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) { func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
if containerID == "" {
return types.ContainerJSON{}, nil, objectNotFoundError{object: "container", id: containerID}
}
query := url.Values{} query := url.Values{}
if getSize { if getSize {
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)
if err != nil { if err != nil {
if serverResp.statusCode == http.StatusNotFound { return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
return types.ContainerJSON{}, nil, containerNotFoundError{containerID}
}
return types.ContainerJSON{}, nil, err
} }
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"golang.org/x/net/context"
) )
// ContainerKill terminates the container process but does not remove the container from the docker host. // ContainerKill terminates the container process but does not remove the container from the docker host.
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strconv" "strconv"
"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"
"golang.org/x/net/context"
) )
// ContainerList returns the list of containers in the docker host. // ContainerList returns the list of containers in the docker host.
......
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"time" "time"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
timetypes "github.com/docker/docker/api/types/time" timetypes "github.com/docker/docker/api/types/time"
"github.com/pkg/errors"
) )
// ContainerLogs returns the logs generated by a container in an io.ReadCloser. // ContainerLogs returns the logs generated by a container in an io.ReadCloser.
...@@ -46,11 +46,19 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options ...@@ -46,11 +46,19 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options
if options.Since != "" { if options.Since != "" {
ts, err := timetypes.GetTimestamp(options.Since, time.Now()) ts, err := timetypes.GetTimestamp(options.Since, time.Now())
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, `invalid value for "since"`)
} }
query.Set("since", ts) query.Set("since", ts)
} }
if options.Until != "" {
ts, err := timetypes.GetTimestamp(options.Until, time.Now())
if err != nil {
return nil, errors.Wrap(err, `invalid value for "until"`)
}
query.Set("until", ts)
}
if options.Timestamps { if options.Timestamps {
query.Set("timestamps", "1") query.Set("timestamps", "1")
} }
...@@ -66,7 +74,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options ...@@ -66,7 +74,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, container string, options
resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil)
if err != nil { if err != nil {
return nil, err return nil, wrapResponseError(err, resp, "container", container)
} }
return resp.body, nil return resp.body, nil
} }
package client package client
import "golang.org/x/net/context" import "context"
// ContainerPause pauses the main process of a given container without terminating it. // ContainerPause pauses the main process of a given container without terminating it.
func (cli *Client) ContainerPause(ctx context.Context, containerID string) error { func (cli *Client) ContainerPause(ctx context.Context, containerID string) error {
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"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"
"golang.org/x/net/context"
) )
// ContainersPrune requests the daemon to delete unused data // ContainersPrune requests the daemon to delete unused data
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerRemove kills and removes a container from the docker host. // ContainerRemove kills and removes a container from the docker host.
...@@ -23,5 +23,5 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti ...@@ -23,5 +23,5 @@ func (cli *Client) ContainerRemove(ctx context.Context, containerID string, opti
resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil) resp, err := cli.delete(ctx, "/containers/"+containerID, query, nil)
ensureReaderClosed(resp) ensureReaderClosed(resp)
return err return wrapResponseError(err, resp, "container", containerID)
} }
package client package client
import ( import (
"context"
"net/url" "net/url"
"golang.org/x/net/context"
) )
// ContainerRename changes the name of a given container. // ContainerRename changes the name of a given container.
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"strconv" "strconv"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerResize changes the size of the tty for a container. // ContainerResize changes the size of the tty for a container.
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"time" "time"
timetypes "github.com/docker/docker/api/types/time" timetypes "github.com/docker/docker/api/types/time"
"golang.org/x/net/context"
) )
// ContainerRestart stops and starts a container again. // ContainerRestart stops and starts a container again.
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
) )
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ContainerStats returns near realtime stats for a given container. // ContainerStats returns near realtime stats for a given container.
......
package client package client
import ( import (
"context"
"net/url" "net/url"
"time" "time"
timetypes "github.com/docker/docker/api/types/time" timetypes "github.com/docker/docker/api/types/time"
"golang.org/x/net/context"
) )
// ContainerStop stops a container without terminating the process. // ContainerStop stops a container. In case the container fails to stop
// The process is blocked until the container stops or the timeout expires. // gracefully within a time frame specified by the timeout argument,
// it is forcefully terminated (killed).
//
// If the timeout is nil, the container's StopTimeout value is used, if set,
// otherwise the engine default. A negative timeout value can be specified,
// meaning no timeout, i.e. no forceful termination is performed.
func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error { func (cli *Client) ContainerStop(ctx context.Context, containerID string, timeout *time.Duration) error {
query := url.Values{} query := url.Values{}
if timeout != nil { if timeout != nil {
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"strings" "strings"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"golang.org/x/net/context"
) )
// ContainerTop shows process information from within a container. // ContainerTop shows process information from within a container.
......
package client package client
import "golang.org/x/net/context" import "context"
// ContainerUnpause resumes the process execution within a container // ContainerUnpause resumes the process execution within a container
func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error { func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error {
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"golang.org/x/net/context"
) )
// ContainerUpdate updates resources of a container // ContainerUpdate updates resources of a container
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"golang.org/x/net/context"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
) )
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// DiskUsage requests the current data usage from the daemon // DiskUsage requests the current data usage from the daemon
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
registrytypes "github.com/docker/docker/api/types/registry" registrytypes "github.com/docker/docker/api/types/registry"
"golang.org/x/net/context"
) )
// DistributionInspect returns the image digest with full Manifest // DistributionInspect returns the image digest with full Manifest
func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) { func (cli *Client) DistributionInspect(ctx context.Context, image, encodedRegistryAuth string) (registrytypes.DistributionInspect, error) {
// Contact the registry to retrieve digest and platform information // Contact the registry to retrieve digest and platform information
var distributionInspect registrytypes.DistributionInspect var distributionInspect registrytypes.DistributionInspect
if image == "" {
return distributionInspect, objectNotFoundError{object: "distribution", id: image}
}
if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil { if err := cli.NewVersionError("1.30", "distribution inspect"); err != nil {
return distributionInspect, err return distributionInspect, err
......
...@@ -2,6 +2,7 @@ package client ...@@ -2,6 +2,7 @@ package client
import ( import (
"fmt" "fmt"
"net/http"
"github.com/docker/docker/api/types/versions" "github.com/docker/docker/api/types/versions"
"github.com/pkg/errors" "github.com/pkg/errors"
...@@ -36,95 +37,37 @@ type notFound interface { ...@@ -36,95 +37,37 @@ type notFound interface {
NotFound() bool // Is the error a NotFound error NotFound() bool // Is the error a NotFound error
} }
// IsErrNotFound returns true if the error is caused with an // IsErrNotFound returns true if the error is a NotFound error, which is returned
// object (image, container, network, volume, …) is not found in the docker host. // by the API when some object is not found.
func IsErrNotFound(err error) bool { func IsErrNotFound(err error) bool {
te, ok := err.(notFound) te, ok := err.(notFound)
return ok && te.NotFound() return ok && te.NotFound()
} }
// imageNotFoundError implements an error returned when an image is not in the docker host. type objectNotFoundError struct {
type imageNotFoundError struct { object string
imageID string id string
} }
// NotFound indicates that this error type is of NotFound func (e objectNotFoundError) NotFound() bool {
func (e imageNotFoundError) NotFound() bool {
return true return true
} }
// Error returns a string representation of an imageNotFoundError func (e objectNotFoundError) Error() string {
func (e imageNotFoundError) Error() string { return fmt.Sprintf("Error: No such %s: %s", e.object, e.id)
return fmt.Sprintf("Error: No such image: %s", e.imageID)
} }
// IsErrImageNotFound returns true if the error is caused func wrapResponseError(err error, resp serverResponse, object, id string) error {
// when an image is not found in the docker host. switch {
func IsErrImageNotFound(err error) bool { case err == nil:
return IsErrNotFound(err) return nil
} case resp.statusCode == http.StatusNotFound:
return objectNotFoundError{object: object, id: id}
// containerNotFoundError implements an error returned when a container is not in the docker host. case resp.statusCode == http.StatusNotImplemented:
type containerNotFoundError struct { return notImplementedError{message: err.Error()}
containerID string default:
} return err
}
// NotFound indicates that this error type is of NotFound
func (e containerNotFoundError) NotFound() bool {
return true
}
// Error returns a string representation of a containerNotFoundError
func (e containerNotFoundError) Error() string {
return fmt.Sprintf("Error: No such container: %s", e.containerID)
}
// IsErrContainerNotFound returns true if the error is caused
// when a container is not found in the docker host.
func IsErrContainerNotFound(err error) bool {
return IsErrNotFound(err)
}
// networkNotFoundError implements an error returned when a network is not in the docker host.
type networkNotFoundError struct {
networkID string
}
// NotFound indicates that this error type is of NotFound
func (e networkNotFoundError) NotFound() bool {
return true
}
// Error returns a string representation of a networkNotFoundError
func (e networkNotFoundError) Error() string {
return fmt.Sprintf("Error: No such network: %s", e.networkID)
}
// IsErrNetworkNotFound returns true if the error is caused
// when a network is not found in the docker host.
func IsErrNetworkNotFound(err error) bool {
return IsErrNotFound(err)
}
// volumeNotFoundError implements an error returned when a volume is not in the docker host.
type volumeNotFoundError struct {
volumeID string
}
// NotFound indicates that this error type is of NotFound
func (e volumeNotFoundError) NotFound() bool {
return true
}
// Error returns a string representation of a volumeNotFoundError
func (e volumeNotFoundError) Error() string {
return fmt.Sprintf("Error: No such volume: %s", e.volumeID)
}
// IsErrVolumeNotFound returns true if the error is caused
// when a volume is not found in the docker host.
func IsErrVolumeNotFound(err error) bool {
return IsErrNotFound(err)
} }
// unauthorizedError represents an authorization error in a remote registry. // unauthorizedError represents an authorization error in a remote registry.
...@@ -144,72 +87,6 @@ func IsErrUnauthorized(err error) bool { ...@@ -144,72 +87,6 @@ func IsErrUnauthorized(err error) bool {
return ok return ok
} }
// nodeNotFoundError implements an error returned when a node is not found.
type nodeNotFoundError struct {
nodeID string
}
// Error returns a string representation of a nodeNotFoundError
func (e nodeNotFoundError) Error() string {
return fmt.Sprintf("Error: No such node: %s", e.nodeID)
}
// NotFound indicates that this error type is of NotFound
func (e nodeNotFoundError) NotFound() bool {
return true
}
// IsErrNodeNotFound returns true if the error is caused
// when a node is not found.
func IsErrNodeNotFound(err error) bool {
_, ok := err.(nodeNotFoundError)
return ok
}
// serviceNotFoundError implements an error returned when a service is not found.
type serviceNotFoundError struct {
serviceID string
}
// Error returns a string representation of a serviceNotFoundError
func (e serviceNotFoundError) Error() string {
return fmt.Sprintf("Error: No such service: %s", e.serviceID)
}
// NotFound indicates that this error type is of NotFound
func (e serviceNotFoundError) NotFound() bool {
return true
}
// IsErrServiceNotFound returns true if the error is caused
// when a service is not found.
func IsErrServiceNotFound(err error) bool {
_, ok := err.(serviceNotFoundError)
return ok
}
// taskNotFoundError implements an error returned when a task is not found.
type taskNotFoundError struct {
taskID string
}
// Error returns a string representation of a taskNotFoundError
func (e taskNotFoundError) Error() string {
return fmt.Sprintf("Error: No such task: %s", e.taskID)
}
// NotFound indicates that this error type is of NotFound
func (e taskNotFoundError) NotFound() bool {
return true
}
// IsErrTaskNotFound returns true if the error is caused
// when a task is not found.
func IsErrTaskNotFound(err error) bool {
_, ok := err.(taskNotFoundError)
return ok
}
type pluginPermissionDenied struct { type pluginPermissionDenied struct {
name string name string
} }
...@@ -225,76 +102,31 @@ func IsErrPluginPermissionDenied(err error) bool { ...@@ -225,76 +102,31 @@ func IsErrPluginPermissionDenied(err error) bool {
return ok return ok
} }
// NewVersionError returns an error if the APIVersion required type notImplementedError struct {
// if less than the current supported version message string
func (cli *Client) NewVersionError(APIrequired, feature string) error {
if cli.version != "" && versions.LessThan(cli.version, APIrequired) {
return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version)
}
return nil
}
// secretNotFoundError implements an error returned when a secret is not found.
type secretNotFoundError struct {
name string
} }
// Error returns a string representation of a secretNotFoundError func (e notImplementedError) Error() string {
func (e secretNotFoundError) Error() string { return e.message
return fmt.Sprintf("Error: no such secret: %s", e.name)
} }
// NotFound indicates that this error type is of NotFound func (e notImplementedError) NotImplemented() bool {
func (e secretNotFoundError) NotFound() bool {
return true return true
} }
// IsErrSecretNotFound returns true if the error is caused // IsErrNotImplemented returns true if the error is a NotImplemented error.
// when a secret is not found. // This is returned by the API when a requested feature has not been
func IsErrSecretNotFound(err error) bool { // implemented.
_, ok := err.(secretNotFoundError) func IsErrNotImplemented(err error) bool {
return ok te, ok := err.(notImplementedError)
} return ok && te.NotImplemented()
// configNotFoundError implements an error returned when a config is not found.
type configNotFoundError struct {
name string
} }
// Error returns a string representation of a configNotFoundError // NewVersionError returns an error if the APIVersion required
func (e configNotFoundError) Error() string { // if less than the current supported version
return fmt.Sprintf("Error: no such config: %s", e.name) func (cli *Client) NewVersionError(APIrequired, feature string) error {
} if cli.version != "" && versions.LessThan(cli.version, APIrequired) {
return fmt.Errorf("%q requires API version %s, but the Docker daemon API version is %s", feature, APIrequired, cli.version)
// NotFound indicates that this error type is of NotFound }
func (e configNotFoundError) NotFound() bool { return nil
return true
}
// IsErrConfigNotFound returns true if the error is caused
// when a config is not found.
func IsErrConfigNotFound(err error) bool {
_, ok := err.(configNotFoundError)
return ok
}
// pluginNotFoundError implements an error returned when a plugin is not in the docker host.
type pluginNotFoundError struct {
name string
}
// NotFound indicates that this error type is of NotFound
func (e pluginNotFoundError) NotFound() bool {
return true
}
// Error returns a string representation of a pluginNotFoundError
func (e pluginNotFoundError) Error() string {
return fmt.Sprintf("Error: No such plugin: %s", e.name)
}
// IsErrPluginNotFound returns true if the error is caused
// when a plugin is not found in the docker host.
func IsErrPluginNotFound(err error) bool {
return IsErrNotFound(err)
} }
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"time" "time"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
......
...@@ -2,37 +2,20 @@ package client ...@@ -2,37 +2,20 @@ package client
import ( import (
"bufio" "bufio"
"context"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"strings"
"time" "time"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/tlsconfig"
"github.com/docker/go-connections/sockets" "github.com/docker/go-connections/sockets"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/net/context"
) )
// tlsClientCon holds tls information and a dialed connection.
type tlsClientCon struct {
*tls.Conn
rawConn net.Conn
}
func (c *tlsClientCon) CloseWrite() error {
// Go standard tls.Conn doesn't provide the CloseWrite() method so we do it
// on its underlying connection.
if conn, ok := c.rawConn.(types.CloseWriter); ok {
return conn.CloseWrite()
}
return nil
}
// postHijacked sends a POST request and hijacks the connection. // postHijacked sends a POST request and hijacks the connection.
func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) { func (cli *Client) postHijacked(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (types.HijackedResponse, error) {
bodyEncoded, err := encodeData(body) bodyEncoded, err := encodeData(body)
...@@ -55,96 +38,9 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu ...@@ -55,96 +38,9 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err return types.HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn)}, err
} }
func tlsDial(network, addr string, config *tls.Config) (net.Conn, error) {
return tlsDialWithDialer(new(net.Dialer), network, addr, config)
}
// We need to copy Go's implementation of tls.Dial (pkg/cryptor/tls/tls.go) in
// order to return our custom tlsClientCon struct which holds both the tls.Conn
// object _and_ its underlying raw connection. The rationale for this is that
// we need to be able to close the write end of the connection when attaching,
// which tls.Conn does not provide.
func tlsDialWithDialer(dialer *net.Dialer, network, addr string, config *tls.Config) (net.Conn, error) {
// We want the Timeout and Deadline values from dialer to cover the
// whole process: TCP connection and TLS handshake. This means that we
// also need to start our own timers now.
timeout := dialer.Timeout
if !dialer.Deadline.IsZero() {
deadlineTimeout := dialer.Deadline.Sub(time.Now())
if timeout == 0 || deadlineTimeout < timeout {
timeout = deadlineTimeout
}
}
var errChannel chan error
if timeout != 0 {
errChannel = make(chan error, 2)
time.AfterFunc(timeout, func() {
errChannel <- errors.New("")
})
}
proxyDialer, err := sockets.DialerFromEnvironment(dialer)
if err != nil {
return nil, err
}
rawConn, err := proxyDialer.Dial(network, addr)
if err != nil {
return nil, err
}
// When we set up a TCP connection for hijack, there could be long periods
// of inactivity (a long running command with no output) that in certain
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
// state. Setting TCP KeepAlive on the socket connection will prohibit
// ECONNTIMEOUT unless the socket connection truly is broken
if tcpConn, ok := rawConn.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(30 * time.Second)
}
colonPos := strings.LastIndex(addr, ":")
if colonPos == -1 {
colonPos = len(addr)
}
hostname := addr[:colonPos]
// If no ServerName is set, infer the ServerName
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
config = tlsconfig.Clone(config)
config.ServerName = hostname
}
conn := tls.Client(rawConn, config)
if timeout == 0 {
err = conn.Handshake()
} else {
go func() {
errChannel <- conn.Handshake()
}()
err = <-errChannel
}
if err != nil {
rawConn.Close()
return nil, err
}
// This is Docker difference with standard's crypto/tls package: returned a
// wrapper which holds both the TLS and raw connections.
return &tlsClientCon{conn, rawConn}, nil
}
func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) { func dial(proto, addr string, tlsConfig *tls.Config) (net.Conn, error) {
if tlsConfig != nil && proto != "unix" && proto != "npipe" { if tlsConfig != nil && proto != "unix" && proto != "npipe" {
// Notice this isn't Go standard's tls.Dial function return tls.Dial(proto, addr, tlsConfig)
return tlsDial(proto, addr, tlsConfig)
} }
if proto == "npipe" { if proto == "npipe" {
return sockets.DialPipe(addr, 32*time.Second) return sockets.DialPipe(addr, 32*time.Second)
...@@ -189,8 +85,14 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e ...@@ -189,8 +85,14 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e
c, br := clientconn.Hijack() c, br := clientconn.Hijack()
if br.Buffered() > 0 { if br.Buffered() > 0 {
// If there is buffered content, wrap the connection // If there is buffered content, wrap the connection. We return an
c = &hijackedConn{c, br} // object that implements CloseWrite iff the underlying connection
// implements it.
if _, ok := c.(types.CloseWriter); ok {
c = &hijackedConnCloseWriter{&hijackedConn{c, br}}
} else {
c = &hijackedConn{c, br}
}
} else { } else {
br.Reset(nil) br.Reset(nil)
} }
...@@ -198,6 +100,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e ...@@ -198,6 +100,10 @@ func (cli *Client) setupHijackConn(req *http.Request, proto string) (net.Conn, e
return c, nil return c, nil
} }
// hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case
// that a) there was already buffered data in the http layer when Hijack() was
// called, and b) the underlying net.Conn does *not* implement CloseWrite().
// hijackedConn does not implement CloseWrite() either.
type hijackedConn struct { type hijackedConn struct {
net.Conn net.Conn
r *bufio.Reader r *bufio.Reader
...@@ -206,3 +112,18 @@ type hijackedConn struct { ...@@ -206,3 +112,18 @@ type hijackedConn struct {
func (c *hijackedConn) Read(b []byte) (int, error) { func (c *hijackedConn) Read(b []byte) (int, error) {
return c.r.Read(b) return c.r.Read(b)
} }
// hijackedConnCloseWriter is a hijackedConn which additionally implements
// CloseWrite(). It is returned by setupHijackConn in the case that a) there
// was already buffered data in the http layer when Hijack() was called, and b)
// the underlying net.Conn *does* implement CloseWrite().
type hijackedConnCloseWriter struct {
*hijackedConn
}
var _ types.CloseWriter = &hijackedConnCloseWriter{}
func (c *hijackedConnCloseWriter) CloseWrite() error {
conn := c.Conn.(types.CloseWriter)
return conn.CloseWrite()
}
package client package client
import ( import (
"context"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
"strings"
"golang.org/x/net/context"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
...@@ -29,6 +29,13 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio ...@@ -29,6 +29,13 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
return types.ImageBuildResponse{}, err return types.ImageBuildResponse{}, err
} }
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf)) headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
if options.Platform != "" {
if err := cli.NewVersionError("1.32", "platform"); err != nil {
return types.ImageBuildResponse{}, err
}
query.Set("platform", options.Platform)
}
headers.Set("Content-Type", "application/x-tar") headers.Set("Content-Type", "application/x-tar")
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers) serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
...@@ -123,6 +130,8 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur ...@@ -123,6 +130,8 @@ func (cli *Client) imageBuildOptionsToQuery(options types.ImageBuildOptions) (ur
if options.SessionID != "" { if options.SessionID != "" {
query.Set("session", options.SessionID) query.Set("session", options.SessionID)
} }
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}
return query, nil return query, nil
} }
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"strings"
"golang.org/x/net/context"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
...@@ -21,6 +21,9 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti ...@@ -21,6 +21,9 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
query := url.Values{} query := url.Values{}
query.Set("fromImage", reference.FamiliarName(ref)) query.Set("fromImage", reference.FamiliarName(ref))
query.Set("tag", getAPITagFromNamedRef(ref)) query.Set("tag", getAPITagFromNamedRef(ref))
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}
resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth) resp, err := cli.tryImageCreate(ctx, query, options.RegistryAuth)
if err != nil { if err != nil {
return nil, err return nil, err
......
package client package client
import ( import (
"context"
"encoding/json" "encoding/json"
"net/url" "net/url"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
"golang.org/x/net/context"
) )
// ImageHistory returns the changes in an image in history format. // ImageHistory returns the changes in an image in history format.
......
package client package client
import ( import (
"context"
"io" "io"
"net/url" "net/url"
"strings"
"golang.org/x/net/context"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
...@@ -25,6 +25,9 @@ func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSour ...@@ -25,6 +25,9 @@ func (cli *Client) ImageImport(ctx context.Context, source types.ImageImportSour
query.Set("repo", ref) query.Set("repo", ref)
query.Set("tag", options.Tag) query.Set("tag", options.Tag)
query.Set("message", options.Message) query.Set("message", options.Message)
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}
for _, change := range options.Changes { for _, change := range options.Changes {
query.Add("changes", change) query.Add("changes", change)
} }
......
...@@ -2,22 +2,21 @@ package client ...@@ -2,22 +2,21 @@ package client
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"golang.org/x/net/context"
) )
// ImageInspectWithRaw returns the image information and its raw representation. // ImageInspectWithRaw returns the image information and its raw representation.
func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) { func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) {
if 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)
if err != nil { if err != nil {
if serverResp.statusCode == http.StatusNotFound { return types.ImageInspect{}, nil, wrapResponseError(err, serverResp, "image", imageID)
return types.ImageInspect{}, nil, imageNotFoundError{imageID}
}
return types.ImageInspect{}, nil, err
} }
defer ensureReaderClosed(serverResp) defer ensureReaderClosed(serverResp)
......
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