From e7449f77468d5c7f6e31d6f6e17f513e1eb6ca75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 7 Sep 2019 15:19:48 +0200 Subject: [PATCH] Add containerArchive() and containerArchiveStream() methods --- examples/{copy.php => archive.php} | 4 +- src/Client.php | 82 +++++++++++++++++++++++++++++- tests/ClientTest.php | 24 +++++++-- 3 files changed, 102 insertions(+), 8 deletions(-) rename examples/{copy.php => archive.php} (90%) diff --git a/examples/copy.php b/examples/archive.php similarity index 90% rename from examples/copy.php rename to examples/archive.php index acfea87..4fd03c2 100644 --- a/examples/copy.php +++ b/examples/archive.php @@ -1,5 +1,5 @@ createClient(); -$stream = $client->containerCopyStream($container, $path); +$stream = $client->containerArchiveStream($container, $path); $tar = new Decoder(); diff --git a/src/Client.php b/src/Client.php index bd18a7c..55ab995 100644 --- a/src/Client.php +++ b/src/Client.php @@ -557,7 +557,7 @@ public function containerRemove($container, $v = false, $force = false) } /** - * Copy files or folders of container id + * [deprecated] Copy files or folders of container id * * This resolves with a string in the TAR file format containing all files * specified in the given $path. @@ -575,6 +575,8 @@ public function containerRemove($container, $v = false, $force = false) * @return PromiseInterface Promise tar stream * @link https://docs.docker.com/engine/api/v1.22/#copy-files-or-folders-from-a-container * @link https://github.com/clue/reactphp-tar + * @deprecated 0.3.0 Deprecated in Docker Engine API v1.20 (Docker v1.8) and removed in Docker Engine API v1.24 (Docker v1.12), use `containerArchive()` instead + * @see self::containerArchive() * @see self::containerCopyStream() */ public function containerCopy($container, $path) @@ -593,7 +595,7 @@ public function containerCopy($container, $path) } /** - * Copy files or folders of container id + * [Deprecated] Copy files or folders of container id * * This returns a stream in the TAR file format containing all files * specified in the given $path. @@ -613,6 +615,8 @@ public function containerCopy($container, $path) * @return ReadableStreamInterface tar stream * @link https://docs.docker.com/engine/api/v1.22/#copy-files-or-folders-from-a-container * @link https://github.com/clue/reactphp-tar + * @deprecated 0.3.0 Deprecated in Docker Engine API v1.20 (Docker v1.8) and removed in Docker Engine API v1.24 (Docker v1.12), use `containerArchiveStream()` instead + * @see self::containerArchiveStream() * @see self::containerCopy() */ public function containerCopyStream($container, $path) @@ -635,6 +639,80 @@ public function containerCopyStream($container, $path) ); } + /** + * Get a tar archive of a resource in the filesystem of container id. + * + * This resolves with a string in the TAR file format containing all files + * specified in the given $path. + * + * Keep in mind that this means the whole string has to be kept in memory. + * For bigger containers it's usually a better idea to use a streaming approach, + * see containerArchiveStream() for more details. + * + * Accessing individual files in the TAR file format string is out of scope + * for this library. Several libraries are available, one that is known to + * work is clue/reactphp-tar (see links). + * + * @param string $container container ID + * @param string $resource path to file or directory to archive + * @return PromiseInterface Promise tar stream + * @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerArchive + * @link https://github.com/clue/reactphp-tar + * @since 0.3.0 Available as of Docker Engine API v1.20 (Docker v1.8), use deprecated `containerCopy()` on legacy versions + * @see self::containerArchiveStream() + */ + public function containerArchive($container, $path) + { + return $this->browser->get( + $this->uri->expand( + '/containers/{container}/archive{?path}', + array( + 'container' => $container, + 'path' => $path + ) + ) + )->then(array($this->parser, 'expectPlain')); + } + + /** + * Get a tar archive of a resource in the filesystem of container id. + * + * This returns a stream in the TAR file format containing all files + * specified in the given $path. + * + * This works for (any number of) files of arbitrary sizes as only small chunks have to + * be kept in memory. + * + * Accessing individual files in the TAR file format stream is out of scope + * for this library. Several libraries are available, one that is known to + * work is clue/reactphp-tar (see links). + * + * The resulting stream is a well-behaving readable stream that will emit + * the normal stream events. + * + * @param string $container container ID + * @param string $path path to file or directory to archive + * @return ReadableStreamInterface tar stream + * @link https://docs.docker.com/engine/api/v1.40/#operation/ContainerArchive + * @link https://github.com/clue/reactphp-tar + * @since 0.3.0 Available as of Docker Engine API v1.20 (Docker v1.8), use deprecated `containerCopyStream()` on legacy versions + * @see self::containerArchive() + */ + public function containerArchiveStream($container, $path) + { + return $this->streamingParser->parsePlainStream( + $this->browser->withOptions(array('streaming' => true))->get( + $this->uri->expand( + '/containers/{container}/archive{?path}', + array( + 'container' => $container, + 'path' => $path + ) + ) + ) + ); + } + /** * List images * diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 77685d2..0b604a1 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -244,8 +244,7 @@ public function testContainerCopy() $data = 'tar stream'; $this->expectRequestFlow('post', '/containers/123/copy', $this->createResponse($data), 'expectPlain'); - $config = array('Resource' => 'file.txt'); - $this->expectPromiseResolveWith($data, $this->client->containerCopy('123', $config)); + $this->expectPromiseResolveWith($data, $this->client->containerCopy('123', 'file.txt')); } public function testContainerCopyStream() @@ -255,8 +254,25 @@ public function testContainerCopyStream() $this->expectRequest('post', '/containers/123/copy', $this->createResponse('')); $this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream)); - $config = array('Resource' => 'file.txt'); - $this->assertSame($stream, $this->client->containerCopyStream('123', $config)); + $this->assertSame($stream, $this->client->containerCopyStream('123', 'file.txt')); + } + + public function testContainerArchive() + { + $data = 'tar stream'; + $this->expectRequestFlow('GET', '/containers/123/archive?path=file.txt', $this->createResponse($data), 'expectPlain'); + + $this->expectPromiseResolveWith($data, $this->client->containerArchive('123', 'file.txt')); + } + + public function testContainerArchiveStream() + { + $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); + + $this->expectRequest('GET', '/containers/123/archive?path=file.txt', $this->createResponse('')); + $this->streamingParser->expects($this->once())->method('parsePlainStream')->will($this->returnValue($stream)); + + $this->assertSame($stream, $this->client->containerArchiveStream('123', 'file.txt')); } public function testImageList()