瀏覽代碼

api: remove POST /containers/{id}/copy endpoint (api < v1.23)

This endpoint was deprecated in API v1.20 (Docker Engine v1.8.0) in
commit db9cc91a9ef7dea4c8d85f64578889cec3dd99b2, in favor of the
`PUT /containers/{id}/archive` and `HEAD /containers/{id}/archive`
endpoints, and disabled in API v1.24 (Docker Engine v1.12.0) through
commit 428328908dc529b1678fb3d8b033fb0591a294e3.

This patch removes the endpoint, and the associated `daemon.ContainerCopy`
method in the backend.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 1 年之前
父節點
當前提交
b3a0ff9944

+ 0 - 1
api/server/router/container/backend.go

@@ -24,7 +24,6 @@ type execBackend interface {
 // copyBackend includes functions to implement to provide container copy functionality.
 // copyBackend includes functions to implement to provide container copy functionality.
 type copyBackend interface {
 type copyBackend interface {
 	ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error)
 	ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error)
-	ContainerCopy(name string, res string) (io.ReadCloser, error)
 	ContainerExport(ctx context.Context, name string, out io.Writer) error
 	ContainerExport(ctx context.Context, name string, out io.Writer) error
 	ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error
 	ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error
 	ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error)
 	ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error)

+ 0 - 1
api/server/router/container/container.go

@@ -56,7 +56,6 @@ func (r *containerRouter) initRoutes() {
 		router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
 		router.NewPostRoute("/containers/{name:.*}/wait", r.postContainersWait),
 		router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
 		router.NewPostRoute("/containers/{name:.*}/resize", r.postContainersResize),
 		router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
 		router.NewPostRoute("/containers/{name:.*}/attach", r.postContainersAttach),
-		router.NewPostRoute("/containers/{name:.*}/copy", r.postContainersCopy), // Deprecated since 1.8 (API v1.20), errors out since 1.12 (API v1.24)
 		router.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate),
 		router.NewPostRoute("/containers/{name:.*}/exec", r.postContainerExecCreate),
 		router.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart),
 		router.NewPostRoute("/exec/{name:.*}/start", r.postContainerExecStart),
 		router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),
 		router.NewPostRoute("/exec/{name:.*}/resize", r.postContainerExecResize),

+ 1 - 40
api/server/router/container/copy.go

@@ -11,49 +11,10 @@ import (
 
 
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/versions"
 	gddohttputil "github.com/golang/gddo/httputil"
 	gddohttputil "github.com/golang/gddo/httputil"
 )
 )
 
 
-type pathError struct{}
-
-func (pathError) Error() string {
-	return "Path cannot be empty"
-}
-
-func (pathError) InvalidParameter() {}
-
-// postContainersCopy is deprecated in favor of getContainersArchive.
-//
-// Deprecated since 1.8 (API v1.20), errors out since 1.12 (API v1.24)
-func (s *containerRouter) postContainersCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
-	version := httputils.VersionFromContext(ctx)
-	if versions.GreaterThanOrEqualTo(version, "1.24") {
-		w.WriteHeader(http.StatusNotFound)
-		return nil
-	}
-
-	cfg := types.CopyConfig{}
-	if err := httputils.ReadJSON(r, &cfg); err != nil {
-		return err
-	}
-
-	if cfg.Resource == "" {
-		return pathError{}
-	}
-
-	data, err := s.backend.ContainerCopy(vars["name"], cfg.Resource)
-	if err != nil {
-		return err
-	}
-	defer data.Close()
-
-	w.Header().Set("Content-Type", "application/x-tar")
-	_, err = io.Copy(w, data)
-	return err
-}
-
-// // Encode the stat to JSON, base64 encode, and place in a header.
+// setContainerPathStatHeader encodes the stat to JSON, base64 encode, and place in a header.
 func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error {
 func setContainerPathStatHeader(stat *types.ContainerPathStat, header http.Header) error {
 	statJSON, err := json.Marshal(stat)
 	statJSON, err := json.Marshal(stat)
 	if err != nil {
 	if err != nil {

+ 0 - 19
daemon/archive.go

@@ -8,25 +8,6 @@ import (
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/errdefs"
 )
 )
 
 
-// ContainerCopy performs a deprecated operation of archiving the resource at
-// the specified path in the container identified by the given name.
-func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, error) {
-	ctr, err := daemon.GetContainer(name)
-	if err != nil {
-		return nil, err
-	}
-
-	data, err := daemon.containerCopy(ctr, res)
-	if err == nil {
-		return data, nil
-	}
-
-	if os.IsNotExist(err) {
-		return nil, containerFileNotFound{res, name}
-	}
-	return nil, errdefs.System(err)
-}
-
 // ContainerStatPath stats the filesystem resource at the specified path in the
 // ContainerStatPath stats the filesystem resource at the specified path in the
 // container identified by the given name.
 // container identified by the given name.
 func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error) {
 func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error) {

+ 0 - 49
daemon/archive_unix.go

@@ -161,55 +161,6 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path
 	return nil
 	return nil
 }
 }
 
 
-func (daemon *Daemon) containerCopy(container *container.Container, resource string) (rc io.ReadCloser, err error) {
-	container.Lock()
-
-	defer func() {
-		if err != nil {
-			// Wait to unlock the container until the archive is fully read
-			// (see the ReadCloseWrapper func below) or if there is an error
-			// before that occurs.
-			container.Unlock()
-		}
-	}()
-
-	cfs, err := daemon.openContainerFS(container)
-	if err != nil {
-		return nil, err
-	}
-	defer func() {
-		if err != nil {
-			cfs.Close()
-		}
-	}()
-
-	err = cfs.RunInFS(context.TODO(), func() error {
-		_, err := os.Stat(resource)
-		return err
-	})
-	if err != nil {
-		return nil, err
-	}
-
-	tb, err := archive.NewTarballer(resource, &archive.TarOptions{
-		Compression: archive.Uncompressed,
-	})
-	if err != nil {
-		return nil, err
-	}
-
-	cfs.GoInFS(context.TODO(), tb.Do)
-	archv := tb.Reader()
-	reader := ioutils.NewReadCloserWrapper(archv, func() error {
-		err := archv.Close()
-		_ = cfs.Close()
-		container.Unlock()
-		return err
-	})
-	daemon.LogContainerEvent(container, events.ActionCopy)
-	return reader, nil
-}
-
 // checkIfPathIsInAVolume checks if the path is in a volume. If it is, it
 // checkIfPathIsInAVolume checks if the path is in a volume. If it is, it
 // cannot be in a read-only volume. If it  is not in a volume, the container
 // cannot be in a read-only volume. If it  is not in a volume, the container
 // cannot be configured with a read-only rootfs.
 // cannot be configured with a read-only rootfs.

+ 0 - 75
integration-cli/docker_api_containers_test.go

@@ -958,81 +958,6 @@ func (s *DockerAPISuite) TestContainerAPICopyNotExistsAnyMore(c *testing.T) {
 	assert.Equal(c, res.StatusCode, http.StatusNotFound)
 	assert.Equal(c, res.StatusCode, http.StatusNotFound)
 }
 }
 
 
-func (s *DockerAPISuite) TestContainerAPICopyPre124(c *testing.T) {
-	testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later
-	const name = "test-container-api-copy"
-	cli.DockerCmd(c, "run", "--name", name, "busybox", "touch", "/test.txt")
-
-	postData := types.CopyConfig{
-		Resource: "/test.txt",
-	}
-
-	res, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/"+name+"/copy", request.JSONBody(postData))
-	assert.NilError(c, err)
-	assert.Equal(c, res.StatusCode, http.StatusOK)
-
-	found := false
-	for tarReader := tar.NewReader(body); ; {
-		h, err := tarReader.Next()
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			c.Fatal(err)
-		}
-		if h.Name == "test.txt" {
-			found = true
-			break
-		}
-	}
-	assert.Assert(c, found)
-}
-
-func (s *DockerAPISuite) TestContainerAPICopyResourcePathEmptyPre124(c *testing.T) {
-	testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later
-	const name = "test-container-api-copy-resource-empty"
-	cli.DockerCmd(c, "run", "--name", name, "busybox", "touch", "/test.txt")
-
-	postData := types.CopyConfig{
-		Resource: "",
-	}
-
-	res, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/"+name+"/copy", request.JSONBody(postData))
-	assert.NilError(c, err)
-	assert.Equal(c, res.StatusCode, http.StatusBadRequest)
-	b, err := request.ReadBody(body)
-	assert.NilError(c, err)
-	assert.Assert(c, is.Regexp("^Path cannot be empty\n$", string(b)))
-}
-
-func (s *DockerAPISuite) TestContainerAPICopyResourcePathNotFoundPre124(c *testing.T) {
-	testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later
-	const name = "test-container-api-copy-resource-not-found"
-	cli.DockerCmd(c, "run", "--name", name, "busybox")
-
-	postData := types.CopyConfig{
-		Resource: "/notexist",
-	}
-
-	res, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/"+name+"/copy", request.JSONBody(postData))
-	assert.NilError(c, err)
-	assert.Equal(c, res.StatusCode, http.StatusNotFound)
-	b, err := request.ReadBody(body)
-	assert.NilError(c, err)
-	assert.Assert(c, is.Regexp("^Could not find the file /notexist in container "+name+"\n$", string(b)))
-}
-
-func (s *DockerAPISuite) TestContainerAPICopyContainerNotFoundPr124(c *testing.T) {
-	testRequires(c, DaemonIsLinux) // Windows only supports 1.25 or later
-	postData := types.CopyConfig{
-		Resource: "/something",
-	}
-
-	res, _, err := request.Post(testutil.GetContext(c), "/v1.23/containers/notexists/copy", request.JSONBody(postData))
-	assert.NilError(c, err)
-	assert.Equal(c, res.StatusCode, http.StatusNotFound)
-}
-
 func (s *DockerAPISuite) TestContainerAPIDelete(c *testing.T) {
 func (s *DockerAPISuite) TestContainerAPIDelete(c *testing.T) {
 	id := runSleepingContainer(c)
 	id := runSleepingContainer(c)
 	cli.WaitRun(c, id)
 	cli.WaitRun(c, id)

+ 0 - 1
integration/container/container_test.go

@@ -29,7 +29,6 @@ func TestContainerInvalidJSON(t *testing.T) {
 	if runtime.GOOS != "windows" {
 	if runtime.GOOS != "windows" {
 		endpoints = append(
 		endpoints = append(
 			endpoints,
 			endpoints,
-			"/v1.23/containers/foobar/copy",  // deprecated since 1.8 (API v1.20), errors out since 1.12 (API v1.24)
 			"/v1.23/containers/foobar/start", // accepts a body on API < v1.24
 			"/v1.23/containers/foobar/start", // accepts a body on API < v1.24
 		)
 		)
 	}
 	}