Verified Commit 2d02a313 authored by Steve Azzopardi's avatar Steve Azzopardi 🌃

Version pin github.com/docker/docker

Change the source for `github.com/docker/docker` to
`github.com/docker/engine` and version pin it to the latest tag `18.09`
this would match the version of `github.com/docker/cli`. There is a good
explantion as to why use `github.com/docker/engine` as a source instead
of `github.com/moby/moby` in
https://github.com/moby/moby/issues/38063#issuecomment-431324613.

Some other related issues as to why using `github.com/docker/engine` is
ideal:
- https://github.com/moby/moby/issues/38507
- https://github.com/moby/moby/issues/38134
- https://github.com/moby/moby/issues/37683
- https://github.com/moby/moby/issues/37529
- https://github.com/moby/moby/issues/38063

gitlab-org/gitlab-runner#3488
parent 02762661
Pipeline #46684691 passed with stages
in 28 minutes and 47 seconds
......@@ -144,8 +144,7 @@
version = "v2.7.0"
[[projects]]
branch = "master"
digest = "1:f42dd37461aa6e799cbd6165311d1be69c670d62685fe325853a0363763d2b83"
digest = "1:2b83a7c64adb49e6068c189032bbdd63638abfa29ec108cb9a6d03dd58beebfe"
name = "github.com/docker/docker"
packages = [
"api",
......@@ -182,7 +181,9 @@
"registry/resumable",
]
pruneopts = "N"
revision = "beef00cb2612754d73024fd89d417b3a7114f87f"
revision = "a79fabbfe84117696a19671f4aa88b82d0f64fc1"
source = "github.com/docker/engine"
version = "v18.09.1"
[[projects]]
digest = "1:ee3f6491ac8a1721b5fa9655da1f7a11e4ab56c0eaf8ffe79debaee49807cfab"
......
......@@ -42,9 +42,14 @@ ignored = ["test", "appengine"]
name = "github.com/docker/distribution"
version = "2.7"
# We are using `github.com/docker/engine` as source since it has tagged
# versions, unlike `github.com/moby/moby`, please read
# https://github.com/moby/moby/issues/38063#issuecomment-431324613 for a
# detailed explanation.
[[constraint]]
name = "github.com/docker/docker"
branch = "master"
source = "github.com/docker/engine"
version = "18.09"
[[constraint]]
name = "github.com/docker/cli"
......
This diff is collapsed.
......@@ -176,7 +176,7 @@
END OF TERMS AND CONDITIONS
Copyright 2013-2018 Docker, Inc.
Copyright 2013-2017 Docker, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......
......@@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
// Common constants for daemon and client.
const (
// DefaultVersion of Current REST API
DefaultVersion = "1.40"
DefaultVersion = "1.39"
// NoBaseImageSpecifier is the symbol used by the FROM
// command to specify that no base image is to be used.
......
......@@ -9,8 +9,8 @@ import (
"github.com/docker/docker/errdefs"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type causer interface {
......@@ -89,14 +89,14 @@ func MakeErrorHandler(err error) http.HandlerFunc {
}
WriteJSON(w, statusCode, response)
} else {
http.Error(w, status.Convert(err).Message(), statusCode)
http.Error(w, grpc.ErrorDesc(err), statusCode)
}
}
}
// statusCodeFromGRPCError returns status code according to gRPC error
func statusCodeFromGRPCError(err error) int {
switch status.Code(err) {
switch grpc.Code(err) {
case codes.InvalidArgument: // code 3
return http.StatusBadRequest
case codes.NotFound: // code 5
......
......@@ -12,8 +12,10 @@ import (
"github.com/sirupsen/logrus"
)
type contextKey string
// APIVersionKey is the client's requested API version.
type APIVersionKey struct{}
const APIVersionKey contextKey = "api-version"
// APIFunc is an adapter to allow the use of ordinary functions as Docker API endpoints.
// Any function that has the appropriate signature can be registered as an API endpoint (e.g. getVersion).
......@@ -81,7 +83,7 @@ func VersionFromContext(ctx context.Context) string {
return ""
}
if val := ctx.Value(APIVersionKey{}); val != nil {
if val := ctx.Value(APIVersionKey); val != nil {
return val.(string)
}
......
......@@ -58,7 +58,7 @@ func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http.
if versions.GreaterThan(apiVersion, v.defaultVersion) {
return versionUnsupportedError{version: apiVersion, maxVersion: v.defaultVersion}
}
ctx = context.WithValue(ctx, httputils.APIVersionKey{}, apiVersion)
ctx = context.WithValue(ctx, httputils.APIVersionKey, apiVersion)
return handler(ctx, w, r, vars)
}
......
......@@ -31,8 +31,8 @@ func (r *buildRouter) Routes() []router.Route {
func (r *buildRouter) initRoutes() {
r.routes = []router.Route{
router.NewPostRoute("/build", r.postBuild),
router.NewPostRoute("/build/prune", r.postPrune),
router.NewPostRoute("/build", r.postBuild, router.WithCancel),
router.NewPostRoute("/build/prune", r.postPrune, router.WithCancel),
router.NewPostRoute("/build/cancel", r.postCancel),
}
}
......
......@@ -38,8 +38,8 @@ func (r *containerRouter) initRoutes() {
router.NewGetRoute("/containers/{name:.*}/changes", r.getContainersChanges),
router.NewGetRoute("/containers/{name:.*}/json", r.getContainersByName),
router.NewGetRoute("/containers/{name:.*}/top", r.getContainersTop),
router.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs),
router.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats),
router.NewGetRoute("/containers/{name:.*}/logs", r.getContainersLogs, router.WithCancel),
router.NewGetRoute("/containers/{name:.*}/stats", r.getContainersStats, router.WithCancel),
router.NewGetRoute("/containers/{name:.*}/attach/ws", r.wsContainersAttach),
router.NewGetRoute("/exec/{id:.*}/json", r.getExecByID),
router.NewGetRoute("/containers/{name:.*}/archive", r.getContainersArchive),
......@@ -51,7 +51,7 @@ func (r *containerRouter) initRoutes() {
router.NewPostRoute("/containers/{name:.*}/restart", r.postContainersRestart),
router.NewPostRoute("/containers/{name:.*}/start", r.postContainersStart),
router.NewPostRoute("/containers/{name:.*}/stop", r.postContainersStop),
router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait, router.WithCancel),
router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
router.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), // Deprecated since 1.8, Errors out since 1.12
......@@ -60,7 +60,7 @@ func (r *containerRouter) initRoutes() {
router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
router.NewPostRoute("/containers/{name:.*}/rename", r.postContainerRename),
router.NewPostRoute("/containers/{name:.*}/update", r.postContainerUpdate),
router.NewPostRoute("/containers/prune", r.postContainersPrune),
router.NewPostRoute("/containers/prune", r.postContainersPrune, router.WithCancel),
router.NewPostRoute("/commit", r.postCommit),
// PUT
router.NewPutRoute("/containers/{name:.*}/archive", r.putContainersArchive),
......
......@@ -338,6 +338,9 @@ func (s *containerRouter) postContainersWait(ctx context.Context, w http.Respons
}
}
// Note: the context should get canceled if the client closes the
// connection since this handler has been wrapped by the
// router.WithCancel() wrapper.
waitC, err := s.backend.ContainerWait(ctx, vars["name"], waitCondition)
if err != nil {
return err
......@@ -462,17 +465,6 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
hostConfig.AutoRemove = false
}
if hostConfig != nil && versions.LessThan(version, "1.40") {
// Ignore BindOptions.NonRecursive because it was added in API 1.40.
for _, m := range hostConfig.Mounts {
if bo := m.BindOptions; bo != nil {
bo.NonRecursive = false
}
}
// Ignore KernelMemoryTCP because it was added in API 1.40.
hostConfig.KernelMemoryTCP = 0
}
ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
Name: name,
Config: config,
......
......@@ -44,7 +44,7 @@ func experimentalHandler(ctx context.Context, w http.ResponseWriter, r *http.Req
return notImplementedError{}
}
// Handler returns the APIFunc to let the server wrap it in middlewares.
// Handler returns returns the APIFunc to let the server wrap it in middlewares.
func (r *experimentalRoute) Handler() httputils.APIFunc {
return r.handler
}
......
......@@ -34,10 +34,10 @@ func (r *imageRouter) initRoutes() {
router.NewGetRoute("/images/{name:.*}/json", r.getImagesByName),
// POST
router.NewPostRoute("/images/load", r.postImagesLoad),
router.NewPostRoute("/images/create", r.postImagesCreate),
router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush),
router.NewPostRoute("/images/create", r.postImagesCreate, router.WithCancel),
router.NewPostRoute("/images/{name:.*}/push", r.postImagesPush, router.WithCancel),
router.NewPostRoute("/images/{name:.*}/tag", r.postImagesTag),
router.NewPostRoute("/images/prune", r.postImagesPrune),
router.NewPostRoute("/images/prune", r.postImagesPrune, router.WithCancel),
// DELETE
router.NewDeleteRoute("/images/{name:.*}", r.deleteImages),
}
......
package router // import "github.com/docker/docker/api/server/router"
import (
"context"
"net/http"
"github.com/docker/docker/api/server/httputils"
)
......@@ -69,3 +72,33 @@ func NewOptionsRoute(path string, handler httputils.APIFunc, opts ...RouteWrappe
func NewHeadRoute(path string, handler httputils.APIFunc, opts ...RouteWrapper) Route {
return NewRoute("HEAD", path, handler, opts...)
}
func cancellableHandler(h httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
if notifier, ok := w.(http.CloseNotifier); ok {
notify := notifier.CloseNotify()
notifyCtx, cancel := context.WithCancel(ctx)
finished := make(chan struct{})
defer close(finished)
ctx = notifyCtx
go func() {
select {
case <-notify:
cancel()
case <-finished:
}
}()
}
return h(ctx, w, r, vars)
}
}
// WithCancel makes new route which embeds http.CloseNotifier feature to
// context.Context of handler.
func WithCancel(r Route) Route {
return localRoute{
method: r.Method(),
path: r.Path(),
handler: cancellableHandler(r.Handler()),
}
}
......@@ -36,7 +36,7 @@ func (r *networkRouter) initRoutes() {
router.NewPostRoute("/networks/create", r.postNetworkCreate),
router.NewPostRoute("/networks/{id:.*}/connect", r.postNetworkConnect),
router.NewPostRoute("/networks/{id:.*}/disconnect", r.postNetworkDisconnect),
router.NewPostRoute("/networks/prune", r.postNetworksPrune),
router.NewPostRoute("/networks/prune", r.postNetworksPrune, router.WithCancel),
// DELETE
router.NewDeleteRoute("/networks/{id:.*}", r.deleteNetwork),
}
......
......@@ -28,11 +28,11 @@ func (r *pluginRouter) initRoutes() {
router.NewGetRoute("/plugins/{name:.*}/json", r.inspectPlugin),
router.NewGetRoute("/plugins/privileges", r.getPrivileges),
router.NewDeleteRoute("/plugins/{name:.*}", r.removePlugin),
router.NewPostRoute("/plugins/{name:.*}/enable", r.enablePlugin),
router.NewPostRoute("/plugins/{name:.*}/enable", r.enablePlugin), // PATCH?
router.NewPostRoute("/plugins/{name:.*}/disable", r.disablePlugin),
router.NewPostRoute("/plugins/pull", r.pullPlugin),
router.NewPostRoute("/plugins/{name:.*}/push", r.pushPlugin),
router.NewPostRoute("/plugins/{name:.*}/upgrade", r.upgradePlugin),
router.NewPostRoute("/plugins/pull", r.pullPlugin, router.WithCancel),
router.NewPostRoute("/plugins/{name:.*}/push", r.pushPlugin, router.WithCancel),
router.NewPostRoute("/plugins/{name:.*}/upgrade", r.upgradePlugin, router.WithCancel),
router.NewPostRoute("/plugins/{name:.*}/set", r.setPlugin),
router.NewPostRoute("/plugins/create", r.createPlugin),
}
......
......@@ -37,7 +37,7 @@ func (sr *swarmRouter) initRoutes() {
router.NewPostRoute("/services/create", sr.createService),
router.NewPostRoute("/services/{id}/update", sr.updateService),
router.NewDeleteRoute("/services/{id}", sr.removeService),
router.NewGetRoute("/services/{id}/logs", sr.getServiceLogs),
router.NewGetRoute("/services/{id}/logs", sr.getServiceLogs, router.WithCancel),
router.NewGetRoute("/nodes", sr.getNodes),
router.NewGetRoute("/nodes/{id}", sr.getNode),
......@@ -46,7 +46,7 @@ func (sr *swarmRouter) initRoutes() {
router.NewGetRoute("/tasks", sr.getTasks),
router.NewGetRoute("/tasks/{id}", sr.getTask),
router.NewGetRoute("/tasks/{id}/logs", sr.getTaskLogs),
router.NewGetRoute("/tasks/{id}/logs", sr.getTaskLogs, router.WithCancel),
router.NewGetRoute("/secrets", sr.getSecrets),
router.NewPostRoute("/secrets/create", sr.createSecret),
......
......@@ -28,16 +28,11 @@ func (sr *swarmRouter) initCluster(ctx context.Context, w http.ResponseWriter, r
return errdefs.InvalidParameter(err)
}
version := httputils.VersionFromContext(ctx)
// DefaultAddrPool and SubnetSize were added in API 1.39. Ignore on older API versions.
if versions.LessThan(version, "1.39") {
req.DefaultAddrPool = nil
req.SubnetSize = 0
}
// DataPathPort was added in API 1.40. Ignore this option on older API versions.
if versions.LessThan(version, "1.40") {
req.DataPathPort = 0
}
nodeID, err := sr.backend.Init(req)
if err != nil {
logrus.Errorf("Error initializing swarm: %v", err)
......@@ -209,23 +204,8 @@ func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter,
encodedAuth := r.Header.Get("X-Registry-Auth")
cliVersion := r.Header.Get("version")
queryRegistry := false
if cliVersion != "" {
if versions.LessThan(cliVersion, "1.30") {
queryRegistry = true
}
if versions.LessThan(cliVersion, "1.40") {
if service.TaskTemplate.ContainerSpec != nil {
// Sysctls for docker swarm services weren't supported before
// API version 1.40
service.TaskTemplate.ContainerSpec.Sysctls = nil
}
if service.TaskTemplate.Placement != nil {
// MaxReplicas for docker swarm services weren't supported before
// API version 1.40
service.TaskTemplate.Placement.MaxReplicas = 0
}
}
if cliVersion != "" && versions.LessThan(cliVersion, "1.30") {
queryRegistry = true
}
resp, err := sr.backend.CreateService(service, encodedAuth, queryRegistry)
......@@ -261,23 +241,8 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
flags.Rollback = r.URL.Query().Get("rollback")
cliVersion := r.Header.Get("version")
queryRegistry := false
if cliVersion != "" {
if versions.LessThan(cliVersion, "1.30") {
queryRegistry = true
}
if versions.LessThan(cliVersion, "1.40") {
if service.TaskTemplate.ContainerSpec != nil {
// Sysctls for docker swarm services weren't supported before
// API version 1.40
service.TaskTemplate.ContainerSpec.Sysctls = nil
}
if service.TaskTemplate.Placement != nil {
// MaxReplicas for docker swarm services weren't supported before
// API version 1.40
service.TaskTemplate.Placement.MaxReplicas = 0
}
}
if cliVersion != "" && versions.LessThan(cliVersion, "1.30") {
queryRegistry = true
}
resp, err := sr.backend.UpdateService(vars["id"], version, service, flags, queryRegistry)
......
......@@ -30,10 +30,10 @@ func NewRouter(b Backend, c ClusterBackend, fscache *fscache.FSCache, builder *b
r.routes = []router.Route{
router.NewOptionsRoute("/{anyroute:.*}", optionsHandler),
router.NewGetRoute("/_ping", r.pingHandler),
router.NewGetRoute("/events", r.getEvents),
router.NewGetRoute("/events", r.getEvents, router.WithCancel),
router.NewGetRoute("/info", r.getInfo),
router.NewGetRoute("/version", r.getVersion),
router.NewGetRoute("/system/df", r.getDiskUsage),
router.NewGetRoute("/system/df", r.getDiskUsage, router.WithCancel),
router.NewPostRoute("/auth", r.postAuth),
}
......
......@@ -29,7 +29,7 @@ func (r *volumeRouter) initRoutes() {
router.NewGetRoute("/volumes/{name:.*}", r.getVolumeByName),
// POST
router.NewPostRoute("/volumes/create", r.postVolumesCreate),
router.NewPostRoute("/volumes/prune", r.postVolumesPrune),
router.NewPostRoute("/volumes/prune", r.postVolumesPrune, router.WithCancel),
// DELETE
router.NewDeleteRoute("/volumes/{name:.*}", r.deleteVolumes),
}
......
......@@ -129,8 +129,8 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc {
// use intermediate variable to prevent "should not use basic type
// string as key in context.WithValue" golint errors
ctx := context.WithValue(r.Context(), dockerversion.UAStringKey{}, r.Header.Get("User-Agent"))
r = r.WithContext(ctx)
var ki interface{} = dockerversion.UAStringKey
ctx := context.WithValue(context.Background(), ki, r.Header.Get("User-Agent"))
handlerFunc := s.handlerWithGlobalMiddlewares(handler)
vars := mux.Vars(r)
......@@ -192,7 +192,6 @@ func (s *Server) createMux() *mux.Router {
notFoundHandler := httputils.MakeErrorHandler(pageNotFoundError{})
m.HandleFunc(versionMatcher+"/{path:.*}", notFoundHandler)
m.NotFoundHandler = notFoundHandler
m.MethodNotAllowedHandler = notFoundHandler
return m
}
......
......@@ -329,7 +329,6 @@ type Resources struct {
DeviceCgroupRules []string // List of rule to be added to the device cgroup
DiskQuota int64 // Disk limit (in bytes)
KernelMemory int64 // Kernel memory limit (in bytes)
KernelMemoryTCP int64 // Hard limit for kernel TCP buffer memory (in bytes)
MemoryReservation int64 // Memory soft limit (in bytes)
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to enable unlimited swap
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
......
......@@ -323,22 +323,6 @@ func (args Args) WalkValues(field string, op func(value string) error) error {
return nil
}
// Clone returns a copy of args.
func (args Args) Clone() (newArgs Args) {
newArgs.fields = make(map[string]map[string]bool, len(args.fields))
for k, m := range args.fields {
var mm map[string]bool
if m != nil {
mm = make(map[string]bool, len(m))
for kk, v := range m {
mm[kk] = v
}
}
newArgs.fields[k] = mm
}
return newArgs
}
func deprecatedArgs(d map[string][]string) map[string]map[string]bool {
m := map[string]map[string]bool{}
for k, v := range d {
......
......@@ -421,11 +421,3 @@ func TestFuzzyMatch(t *testing.T) {
}
}
}
func TestClone(t *testing.T) {
f := NewArgs()
f.Add("foo", "bar")
f2 := f.Clone()
f2.Add("baz", "qux")
assert.Check(t, is.Len(f.Get("baz"), 0))
}
......@@ -79,8 +79,7 @@ const (
// BindOptions defines options specific to mounts of type "bind".
type BindOptions struct {
Propagation Propagation `json:",omitempty"`
NonRecursive bool `json:",omitempty"`
Propagation Propagation `json:",omitempty"`
}
// VolumeOptions represents the options for a mount of type volume.
......
......@@ -120,7 +120,7 @@ type NetworkStats struct {
RxBytes uint64 `json:"rx_bytes"`
// Packets received. Windows and Linux.
RxPackets uint64 `json:"rx_packets"`
// Received errors. Not used on Windows. Note that we don't `omitempty` this
// Received errors. Not used on Windows. Note that we dont `omitempty` this
// field as it is expected in the >=v1.21 API stats structure.
RxErrors uint64 `json:"rx_errors"`
// Incoming packets dropped. Windows and Linux.
......@@ -129,7 +129,7 @@ type NetworkStats struct {
TxBytes uint64 `json:"tx_bytes"`
// Packets sent. Windows and Linux.
TxPackets uint64 `json:"tx_packets"`
// Sent errors. Not used on Windows. Note that we don't `omitempty` this
// Sent errors. Not used on Windows. Note that we dont `omitempty` this
// field as it is expected in the >=v1.21 API stats structure.
TxErrors uint64 `json:"tx_errors"`
// Outgoing packets dropped. Windows and Linux.
......
......@@ -29,8 +29,8 @@ func TestStrSliceMarshalJSON(t *testing.T) {
func TestStrSliceUnmarshalJSON(t *testing.T) {
parts := map[string][]string{
"": {"default", "values"},
"[]": {},
"": {"default", "values"},
"[]": {},
`["/bin/sh","-c","echo"]`: {"/bin/sh", "-c", "echo"},
}
for json, expectedParts := range parts {
......
......@@ -71,5 +71,4 @@ type ContainerSpec struct {
Secrets []*SecretReference `json:",omitempty"`
Configs []*ConfigReference `json:",omitempty"`
Isolation container.Isolation `json:",omitempty"`
Sysctls map[string]string `json:",omitempty"`
}
......@@ -14,7 +14,6 @@ type ClusterInfo struct {
RootRotationInProgress bool
DefaultAddrPool []string
SubnetSize uint32
DataPathPort uint32
}
// Swarm represents a swarm.
......@@ -154,7 +153,6 @@ type InitRequest struct {
ListenAddr string
AdvertiseAddr string
DataPathAddr string
DataPathPort uint32
ForceNewCluster bool
Spec Spec
AutoLockManagers bool
......
......@@ -127,7 +127,6 @@ type ResourceRequirements struct {
type Placement struct {
Constraints []string `json:",omitempty"`
Preferences []PlacementPreference `json:",omitempty"`
MaxReplicas uint64 `json:",omitempty"`
// Platforms stores all the platforms that the image can run on.
// This field is used in the platform filter for scheduling. If empty,
......
......@@ -158,7 +158,6 @@ type Info struct {
MemoryLimit bool
SwapLimit bool
KernelMemory bool