From fa591757d6eb951275bbdbc13a82675e441f1dd1 Mon Sep 17 00:00:00 2001 From: Eric Poe Date: Wed, 28 Feb 2018 23:28:05 -0600 Subject: [PATCH 01/20] Grammar update Use punctuation for clarity and correct a verb conjugation --- docs/async.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/async.md b/docs/async.md index 36d7cb38..2411e9dc 100644 --- a/docs/async.md +++ b/docs/async.md @@ -1,6 +1,6 @@ # Asynchronous Client -Starting from 2.0 Docker-PHP propose an Asynchronous PHP Client using [Amp](https://amphp.org/) and +Starting from 2.0, Docker-PHP proposes an Asynchronous PHP Client using [Amp](https://amphp.org/) and [Artax](https://amphp.org/artax/). ## Installation From 629e42090debf9d91a5b3dd0133b5e3e0aea2660 Mon Sep 17 00:00:00 2001 From: Eric Poe Date: Wed, 28 Feb 2018 23:25:49 -0600 Subject: [PATCH 02/20] Correct spelling error This corrects a spelling error --- docs/basic.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/basic.md b/docs/basic.md index 2edaeb98..52a7f200 100644 --- a/docs/basic.md +++ b/docs/basic.md @@ -1,7 +1,7 @@ # Basic Usage -`Docker\Docker` API Client offers all endpoints available for your version of Docker. Each endpoint as a strong PHPDoc -documentation in its comment, so the best way to know what values to set for an endpoint and what it returns, is to go +`Docker\Docker` API Client offers all endpoints available for your version of Docker. Each endpoint has a strong PHPDoc +documentation in its comment, so the best way to know what values to set for an endpoint and what it returns is to go directly to the endpoint documentation in the code. As an example for listing container you can do: From 7bdc896dfdb1164a3d28845330bb63a1816e12ba Mon Sep 17 00:00:00 2001 From: Eric Poe Date: Wed, 28 Feb 2018 23:17:22 -0600 Subject: [PATCH 03/20] Grammar and spelling fixes This is a minor grammar/spelling fix PR to help increase clarity in the `installation` page. --- docs/installation.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index d37ad678..3b5a6e14 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,11 +1,11 @@ # Installation -The recommended way to install Docker PHP is of course to use [Composer](http://getcomposer.org/): +The recommended way to install Docker PHP is to use [Composer](http://getcomposer.org/): Run `composer require docker-php/docker-php` to add the dependency By default it will use the last API version. However you can specify the API version of docker by setting a specific -version for the ` docker-php/docker-php-api`. +version for the `docker-php/docker-php-api`. To use the 1.29 version you can do the following: @@ -13,9 +13,9 @@ To use the 1.29 version you can do the following: composer require docker-php/docker-php-api:4.1.29.* ``` -Do not use `^4.1.29.0` otherwise you will also depend on the lastest version. First digit of this version number match the -major version of [Jane PHP](https://github.com/janephp/janephp) which is the lib generating the API Client code. +Do not use `^4.1.29.0`; otherwise, you will also depend on the lastest version. The first digit of this version number matches the +major version of [Jane PHP](https://github.com/janephp/janephp), which is the lib generating the API Client code. -Also please not that, unfortunately some endpoints of the Docker API may have BC break during minor version. This library may -try to hide those BC break but it will always be a best effort. Feel free to raise an issue or pull request on github when +Note that some endpoints of the Docker API may have BC breaks during minor version updates. This library may +try to hide those BC breaks but it will always be a best effort. Feel free to raise an issue or pull request on github when you encounter one. From ee1444fceec0921be955da3898fb6896ffe30cef Mon Sep 17 00:00:00 2001 From: Eric Poe Date: Wed, 28 Feb 2018 23:23:34 -0600 Subject: [PATCH 04/20] Update grammar - minor This is just a minor grammar update to the connection instructions --- docs/connection.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/connection.md b/docs/connection.md index 5aaf622e..92c15212 100644 --- a/docs/connection.md +++ b/docs/connection.md @@ -42,7 +42,7 @@ to learn about possible options. ## Custom client -In fact `Docker\Docker` accept any client from [Httplug](http://httplug.io/) (respecting the `Http\Client\HttpClient` interface). +In fact `Docker\Docker` accepts any client from [Httplug](http://httplug.io/) (respecting the `Http\Client\HttpClient` interface). So you can use [React](https://github.com/reactphp/http-client), [Guzzle](http://docs.guzzlephp.org/en/latest/) or any [other adapters / clients](http://docs.php-http.org/en/latest/clients.html). @@ -65,10 +65,10 @@ $docker = Docker::create($adapter); However not all clients fully support Docker daemon features, such as unix socket domain connection, real time streaming, ... That's why it's strongly encouraged to use the [Socket Http Client](http://docs.php-http.org/en/latest/clients/socket-client.html) -which support all the docker daemon features. +which supports all the docker daemon features. Also this client needs to be decorated by [a plugin system](http://docs.php-http.org/en/latest/plugins/index.html). At least 2 plugins are required: * [Content-Length Plugin](http://docs.php-http.org/en/latest/plugins/content-length.html): Which will set correct header `Content-Length` header for the request; - * [Decoder Plugin](http://docs.php-http.org/en/latest/plugins/decoder.html): Which allow to manipulate chunked and/or encoded response + * [Decoder Plugin](http://docs.php-http.org/en/latest/plugins/decoder.html): Which can manipulate a chunked and/or encoded response From 9ef8a55109eb522297e1edb03845327b66d77131 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Thu, 1 Mar 2018 15:19:21 +0100 Subject: [PATCH 05/20] Update Changelog --- CHANGELOG.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3398fd8a..b3b5716d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,13 @@ -# Changelog +# Changelog + +## 2.0 + + - [BC Break] All endpoints have new names and potentially new parameters + - Add async (with amp artax) support + - It now uses the official swagger specification of docker + - Allow to use from 1.25 to 1.36 api version of Docker + - Add support for more keywords in ContextBuilder + - Lot of bug fixes ## 1.24.0 - 08/08/2014 From 75fc59679f0f005f03ae6c83d95a99b9a5356a2a Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Thu, 1 Mar 2018 18:05:45 +0100 Subject: [PATCH 06/20] Fixed typos --- CONTRIBUTING.md | 4 ++-- docs/installation.md | 2 +- src/DockerAsyncClient.php | 2 +- src/DockerClientFactory.php | 2 +- tests/DockerClientFactoryTest.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4360d0c3..6be589b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ please be as precise as possible. Here is a little list of required information: - Precise description of the bug - Details of your environment (for example: OS, PHP version, installed extensions) - - Backtrace which might help identifing the bug + - Backtrace which might help identifying the bug ## Feature requests @@ -75,7 +75,7 @@ endpoint or requested / returned object, you will need to update the `docker-swa There is a bash script at the root of this repository `generate.sh` which helps launching the command to generate files according to the specification. -When changing the specification don't hesite to do 2 commits for better reading: +When changing the specification don't hesitate to do 2 commits for better reading: * One with only changes to the specification * One with changes on the generated code diff --git a/docs/installation.md b/docs/installation.md index 3b5a6e14..2cc4fcec 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -13,7 +13,7 @@ To use the 1.29 version you can do the following: composer require docker-php/docker-php-api:4.1.29.* ``` -Do not use `^4.1.29.0`; otherwise, you will also depend on the lastest version. The first digit of this version number matches the +Do not use `^4.1.29.0`; otherwise, you will also depend on the latest version. The first digit of this version number matches the major version of [Jane PHP](https://github.com/janephp/janephp), which is the lib generating the API Client code. Note that some endpoints of the Docker API may have BC breaks during minor version updates. This library may diff --git a/src/DockerAsyncClient.php b/src/DockerAsyncClient.php index 2adc0cab..ca440bd7 100644 --- a/src/DockerAsyncClient.php +++ b/src/DockerAsyncClient.php @@ -61,7 +61,7 @@ public static function createFromEnv(): self if (\getenv('DOCKER_TLS_VERIFY') && '1' === \getenv('DOCKER_TLS_VERIFY')) { if (!\getenv('DOCKER_CERT_PATH')) { - throw new \RuntimeException('Connection to docker has been set to use TLS, but no PATH is defined for certificate in DOCKER_CERT_PATH docker environnement variable'); + throw new \RuntimeException('Connection to docker has been set to use TLS, but no PATH is defined for certificate in DOCKER_CERT_PATH docker environment variable'); } $tlsContext = new ClientTlsContext(); diff --git a/src/DockerClientFactory.php b/src/DockerClientFactory.php index 3d108d06..918d8724 100644 --- a/src/DockerClientFactory.php +++ b/src/DockerClientFactory.php @@ -47,7 +47,7 @@ public static function createFromEnv(PluginClientFactory $pluginClientFactory = if (\getenv('DOCKER_TLS_VERIFY') && '1' === \getenv('DOCKER_TLS_VERIFY')) { if (!\getenv('DOCKER_CERT_PATH')) { - throw new \RuntimeException('Connection to docker has been set to use TLS, but no PATH is defined for certificate in DOCKER_CERT_PATH docker environnement variable'); + throw new \RuntimeException('Connection to docker has been set to use TLS, but no PATH is defined for certificate in DOCKER_CERT_PATH docker environment variable'); } $cafile = \getenv('DOCKER_CERT_PATH').DIRECTORY_SEPARATOR.'ca.pem'; diff --git a/tests/DockerClientFactoryTest.php b/tests/DockerClientFactoryTest.php index 32554766..286419d4 100644 --- a/tests/DockerClientFactoryTest.php +++ b/tests/DockerClientFactoryTest.php @@ -22,7 +22,7 @@ public function testStaticConstructor(): void /** * @expectedException \RuntimeException - * @expectedExceptionMessage Connection to docker has been set to use TLS, but no PATH is defined for certificate in DOCKER_CERT_PATH docker environnement variable + * @expectedExceptionMessage Connection to docker has been set to use TLS, but no PATH is defined for certificate in DOCKER_CERT_PATH docker environment variable */ public function testCreateFromEnvWithoutCertPath(): void { From 3819da8eb917d6ff4b9a4c2f82e0ba047b509241 Mon Sep 17 00:00:00 2001 From: Pete Halverson Date: Mon, 7 May 2018 10:11:27 -0600 Subject: [PATCH 07/20] Fix `Reading logs in real time` example ContainersCreatePostBody::setNames() does not exist. Set name unique name with containerCreate() --- docs/cookbook/container-run.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/cookbook/container-run.md b/docs/cookbook/container-run.md index 9a506598..cb1df6fc 100644 --- a/docs/cookbook/container-run.md +++ b/docs/cookbook/container-run.md @@ -98,13 +98,12 @@ method need extra configuration: $containerConfig = new ContainersCreatePostBody(); $containerConfig->setImage('busybox:latest'); $containerConfig->setCmd(['echo', 'I am running a command']); -$containerConfig->setNames(['my-container-unique-name']]); // You need to attach stream of the container to docker $containerConfig->setAttachStdin(true); $containerConfig->setAttachStdout(true); $containerConfig->setAttachStderr(true); -$docker->containerCreate($containerConfig); +$docker->containerCreate($containerConfig, ['name' => 'my-container-unique-name']); // You also need to set stream to true to get the logs, and tell which stream you want to attach $attachStream = $docker->containerAttach('my-container-unique-name', [ From 1a2358e9a2d9911ab3467519ecb9e04c16e10af3 Mon Sep 17 00:00:00 2001 From: Pete Halverson Date: Mon, 7 May 2018 10:52:38 -0600 Subject: [PATCH 08/20] Add stop example --- docs/cookbook/container-run.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/cookbook/container-run.md b/docs/cookbook/container-run.md index cb1df6fc..0820e80a 100644 --- a/docs/cookbook/container-run.md +++ b/docs/cookbook/container-run.md @@ -58,6 +58,17 @@ seconds) $docker->containerWait('my-container-unique-name'); ``` +## Stopping the container + +Once your container is started you can stop it by using the `containerStop` method. You can use the id of the container or the name: + +```php +$docker->containerStop($containerCreateResult->getId()); +// Or +$docker->containerStop('my-container-unique-name'); +``` + + ## Reading logs in real time Sometimes you will need to read logs in real time for a container. You can use the `containerAttach` method for that. From 249744e5625c5ae999bfcc0218bfc94b5df20b80 Mon Sep 17 00:00:00 2001 From: Guillem CANAL Date: Sat, 12 May 2018 19:06:20 +0200 Subject: [PATCH 09/20] feat: Consume Docker system events asynchronously --- src/Client/AmpArtaxStreamEndpoint.php | 26 +++++++ src/Client/AmpArtaxStreamEndpointTrait.php | 41 +++++++++++ src/Client/ProvideAmpArtaxClientOptions.php | 15 ++++ src/DockerAsync.php | 52 ++++++++++++++ src/Endpoint/SystemEvents.php | 13 +++- src/Stream/ArtaxCallbackStream.php | 78 +++++++++++++++++++++ tests/DockerAsyncTest.php | 31 ++++++++ 7 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 src/Client/AmpArtaxStreamEndpoint.php create mode 100644 src/Client/AmpArtaxStreamEndpointTrait.php create mode 100644 src/Client/ProvideAmpArtaxClientOptions.php create mode 100644 src/Stream/ArtaxCallbackStream.php diff --git a/src/Client/AmpArtaxStreamEndpoint.php b/src/Client/AmpArtaxStreamEndpoint.php new file mode 100644 index 00000000..ec7f3b9a --- /dev/null +++ b/src/Client/AmpArtaxStreamEndpoint.php @@ -0,0 +1,26 @@ +transformResponseBody($chunk, $response->getStatus(), $serializer); + }; + } + + return new ArtaxCallbackStream($response->getBody(), $cancellationTokenSource, $responseTransformer); + }); + } +} diff --git a/src/Client/ProvideAmpArtaxClientOptions.php b/src/Client/ProvideAmpArtaxClientOptions.php new file mode 100644 index 00000000..cd1aa87d --- /dev/null +++ b/src/Client/ProvideAmpArtaxClientOptions.php @@ -0,0 +1,15 @@ +executeArtaxEndpoint(new SystemEvents($queryParameters), $fetch); + } + + /** + * {@inheritdoc} + */ + public function executeArtaxEndpoint(AmpArtaxEndpoint $endpoint, string $fetch = self::FETCH_OBJECT): Promise + { + return call(function () use ($endpoint, $fetch) { + [$bodyHeaders, $body] = $endpoint->getBody($this->serializer); + $queryString = $endpoint->getQueryString(); + $uri = '' !== $queryString ? $endpoint->getUri().'?'.$queryString : $endpoint->getUri(); + $request = new Request($uri, $endpoint->getMethod()); + $request = $request->withBody($body); + $request = $request->withHeaders($endpoint->getHeaders($bodyHeaders)); + $options = []; + if ($endpoint instanceof ProvideAmpArtaxClientOptions) { + $options = $endpoint->getAmpArtaxClientOptions(); + } + + if ($endpoint instanceof AmpArtaxStreamEndpoint) { + $cancellationTokenSource = new CancellationTokenSource(); + + return $endpoint->parseArtaxStreamResponse( + yield $this->httpClient->request($request, $options, $cancellationTokenSource->getToken()), + $this->serializer, + $cancellationTokenSource, + $fetch + ); + } + + return $endpoint->parseArtaxResponse( + yield $this->httpClient->request($request, $options), + $this->serializer, + $fetch + ); + }); + } } diff --git a/src/Endpoint/SystemEvents.php b/src/Endpoint/SystemEvents.php index ade82394..712e67da 100644 --- a/src/Endpoint/SystemEvents.php +++ b/src/Endpoint/SystemEvents.php @@ -4,15 +4,26 @@ namespace Docker\Endpoint; +use Amp\Artax\Client as ArtaxClient; use Docker\API\Endpoint\SystemEvents as BaseEndpoint; +use Docker\Client\AmpArtaxStreamEndpoint; +use Docker\Client\AmpArtaxStreamEndpointTrait; +use Docker\Client\ProvideAmpArtaxClientOptions; use Docker\Stream\EventStream; use Jane\OpenApiRuntime\Client\Client; use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException; use Psr\Http\Message\ResponseInterface; use Symfony\Component\Serializer\SerializerInterface; -class SystemEvents extends BaseEndpoint +class SystemEvents extends BaseEndpoint implements ProvideAmpArtaxClientOptions, AmpArtaxStreamEndpoint { + use AmpArtaxStreamEndpointTrait; + + public function getAmpArtaxClientOptions(): array + { + return [ArtaxClient::OP_TRANSFER_TIMEOUT => 0]; + } + public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT) { if (Client::FETCH_OBJECT === $fetchMode) { diff --git a/src/Stream/ArtaxCallbackStream.php b/src/Stream/ArtaxCallbackStream.php new file mode 100644 index 00000000..f85d5219 --- /dev/null +++ b/src/Stream/ArtaxCallbackStream.php @@ -0,0 +1,78 @@ +stream = $stream; + $this->cancellationTokenSource = $cancellationTokenSource; + $this->chunkTransformer = $chunkTransformer; + } + + /** + * Called when there is a new frame from the stream. + * + * @param callable $onNewFrame + */ + public function onFrame(callable $onNewFrame): void + { + $this->onNewFrameCallables[] = $onNewFrame; + } + + /** + * Consume stream chunks. + * + * @return Promise + */ + public function listen(): Promise + { + return call(function () { + while (null !== ($chunk = yield $this->stream->read())) { + foreach ($this->onNewFrameCallables as $newFrameCallable) { + $newFrameCallable($this->transformChunk($chunk)); + } + } + }); + } + + /** + * Stop consuming stream chunks. + */ + public function cancel(): void + { + $this->cancellationTokenSource->cancel(); + } + + /** + * Transform stream chunks if required. + * + * @param string $chunk + * + * @return mixed The raw chunk or the transformed chunk + */ + private function transformChunk(string $chunk) + { + if (null === $this->chunkTransformer) { + return $chunk; + } + + return \call_user_func($this->chunkTransformer, $chunk); + } +} diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php index 2fd15108..0d854511 100644 --- a/tests/DockerAsyncTest.php +++ b/tests/DockerAsyncTest.php @@ -4,8 +4,10 @@ namespace Docker\Tests; +use Amp\Delayed; use Amp\Loop; use Docker\API\Model\ContainersCreatePostBody; +use Docker\API\Model\EventsGetResponse200; use Docker\DockerAsync; class DockerAsyncTest extends \PHPUnit\Framework\TestCase @@ -39,4 +41,33 @@ public function testAsync(): void $this->assertSame($containerCreate->getId(), $containerInfo->getId()); }); } + + public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void + { + Loop::run(function () { + $docker = DockerAsync::create(); + + $actualEvent = null; + + $events = yield $docker->systemEvents(); + $events->onFrame(function ($event) use (&$actualEvent): void { + $actualEvent = $event; + }); + $events->listen(); + + $containerConfig = new ContainersCreatePostBody(); + $containerConfig->setImage('busybox:latest'); + $containerConfig->setCmd(['echo', '-n', 'output']); + + $containerCreate = yield $docker->containerCreate($containerConfig); + + // Let a chance for the container create event to be dispatched to the consumer + yield new Delayed(100); + + $events->cancel(); + + $this->assertInstanceOf(EventsGetResponse200::class, $actualEvent); + $this->assertSame($actualEvent->getActor()->getId(), $containerCreate->getId()); + }); + } } From 0b3cdcb3401fe583e9e9a4acf140f371e09c87e9 Mon Sep 17 00:00:00 2001 From: Guillem CANAL Date: Sat, 12 May 2018 21:13:42 +0200 Subject: [PATCH 10/20] fix: Increase the delay between the container creation and the phpunit assertions --- tests/DockerAsyncTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php index 0d854511..1c9e198e 100644 --- a/tests/DockerAsyncTest.php +++ b/tests/DockerAsyncTest.php @@ -9,6 +9,7 @@ use Docker\API\Model\ContainersCreatePostBody; use Docker\API\Model\EventsGetResponse200; use Docker\DockerAsync; +use Docker\Stream\ArtaxCallbackStream; class DockerAsyncTest extends \PHPUnit\Framework\TestCase { @@ -48,7 +49,7 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void $docker = DockerAsync::create(); $actualEvent = null; - + /** @var ArtaxCallbackStream $events */ $events = yield $docker->systemEvents(); $events->onFrame(function ($event) use (&$actualEvent): void { $actualEvent = $event; @@ -62,7 +63,7 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void $containerCreate = yield $docker->containerCreate($containerConfig); // Let a chance for the container create event to be dispatched to the consumer - yield new Delayed(100); + yield new Delayed(1000); $events->cancel(); From f98e572950ce85ae98d89a89379f8bbce6869b4b Mon Sep 17 00:00:00 2001 From: Guillem CANAL Date: Sat, 12 May 2018 21:30:53 +0200 Subject: [PATCH 11/20] fix: Only listen to Docker container create event --- tests/DockerAsyncTest.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php index 1c9e198e..1c231baa 100644 --- a/tests/DockerAsyncTest.php +++ b/tests/DockerAsyncTest.php @@ -48,11 +48,15 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void Loop::run(function () { $docker = DockerAsync::create(); - $actualEvent = null; + $receivedEvents = []; /** @var ArtaxCallbackStream $events */ - $events = yield $docker->systemEvents(); - $events->onFrame(function ($event) use (&$actualEvent): void { - $actualEvent = $event; + $events = yield $docker->systemEvents( + [ + 'filters' => json_encode(['type' => ['container'], 'action' => ['create']]) + ] + ); + $events->onFrame(function ($event) use (&$receivedEvents): void { + $receivedEvents[] = $event; }); $events->listen(); @@ -67,8 +71,9 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void $events->cancel(); - $this->assertInstanceOf(EventsGetResponse200::class, $actualEvent); - $this->assertSame($actualEvent->getActor()->getId(), $containerCreate->getId()); + $this->assertCount(1, $receivedEvents); + $this->assertInstanceOf(EventsGetResponse200::class, current($receivedEvents)); + $this->assertSame(current($receivedEvents)->getActor()->getId(), $containerCreate->getId()); }); } } From 9e7857c2ff596f6decba4b89dd7d0206e18ff88a Mon Sep 17 00:00:00 2001 From: Guillem CANAL Date: Sat, 12 May 2018 21:55:05 +0200 Subject: [PATCH 12/20] fix: attempt to catch the proper event using a macther (docker may not run in isolation in Travis CI) --- tests/DockerAsyncTest.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php index 1c231baa..5ea5c13c 100644 --- a/tests/DockerAsyncTest.php +++ b/tests/DockerAsyncTest.php @@ -7,6 +7,7 @@ use Amp\Delayed; use Amp\Loop; use Docker\API\Model\ContainersCreatePostBody; +use Docker\API\Model\ContainersCreatePostResponse201; use Docker\API\Model\EventsGetResponse200; use Docker\DockerAsync; use Docker\Stream\ArtaxCallbackStream; @@ -64,6 +65,7 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void $containerConfig->setImage('busybox:latest'); $containerConfig->setCmd(['echo', '-n', 'output']); + /** @var ContainersCreatePostResponse201 $containerCreate */ $containerCreate = yield $docker->containerCreate($containerConfig); // Let a chance for the container create event to be dispatched to the consumer @@ -71,9 +73,19 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void $events->cancel(); - $this->assertCount(1, $receivedEvents); - $this->assertInstanceOf(EventsGetResponse200::class, current($receivedEvents)); - $this->assertSame(current($receivedEvents)->getActor()->getId(), $containerCreate->getId()); + $matchedEvents = array_filter( + $receivedEvents, + function ($event) use ($containerCreate) { + return \is_object($event) + && $event instanceof EventsGetResponse200 + && $event->getAction() === 'create' + && $event->getType() === 'container' + && $event->getActor() !== null + && $event->getActor()->getID() === $containerCreate->getId(); + } + ); + + $this->assertCount(1, $matchedEvents); }); } } From f072ecf38473383ba5e372d56ea632815b3ce9d6 Mon Sep 17 00:00:00 2001 From: Guillem CANAL Date: Sat, 12 May 2018 22:19:09 +0200 Subject: [PATCH 13/20] fix: Crazy formatting requirements in tests --- tests/DockerAsyncTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php index 5ea5c13c..c04a281a 100644 --- a/tests/DockerAsyncTest.php +++ b/tests/DockerAsyncTest.php @@ -53,7 +53,7 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void /** @var ArtaxCallbackStream $events */ $events = yield $docker->systemEvents( [ - 'filters' => json_encode(['type' => ['container'], 'action' => ['create']]) + 'filters' => \json_encode(['type' => ['container'], 'action' => ['create']]), ] ); $events->onFrame(function ($event) use (&$receivedEvents): void { @@ -73,14 +73,14 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void $events->cancel(); - $matchedEvents = array_filter( + $matchedEvents = \array_filter( $receivedEvents, function ($event) use ($containerCreate) { return \is_object($event) && $event instanceof EventsGetResponse200 - && $event->getAction() === 'create' - && $event->getType() === 'container' - && $event->getActor() !== null + && 'create' === $event->getAction() + && 'container' === $event->getType() + && null !== $event->getActor() && $event->getActor()->getID() === $containerCreate->getId(); } ); From d7bdc16654eca91ee22b04913052eb5aafe67481 Mon Sep 17 00:00:00 2001 From: Guillem CANAL Date: Sun, 13 May 2018 20:34:45 +0200 Subject: [PATCH 14/20] fix: Use Loop::delay instead of a Delayed callback --- tests/DockerAsyncTest.php | 59 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php index c04a281a..0cda17c5 100644 --- a/tests/DockerAsyncTest.php +++ b/tests/DockerAsyncTest.php @@ -4,10 +4,8 @@ namespace Docker\Tests; -use Amp\Delayed; use Amp\Loop; use Docker\API\Model\ContainersCreatePostBody; -use Docker\API\Model\ContainersCreatePostResponse201; use Docker\API\Model\EventsGetResponse200; use Docker\DockerAsync; use Docker\Stream\ArtaxCallbackStream; @@ -44,48 +42,47 @@ public function testAsync(): void }); } + /** @group sys */ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void { - Loop::run(function () { + \putenv('AMP_DEBUG=1'); + $matchedEvents = []; + + Loop::run(function () use (&$matchedEvents) { $docker = DockerAsync::create(); - $receivedEvents = []; /** @var ArtaxCallbackStream $events */ - $events = yield $docker->systemEvents( - [ - 'filters' => \json_encode(['type' => ['container'], 'action' => ['create']]), - ] - ); - $events->onFrame(function ($event) use (&$receivedEvents): void { - $receivedEvents[] = $event; + $events = yield $docker->systemEvents([ + 'filters' => \json_encode( + [ + 'type' => ['container'], + 'action' => ['create'], + ] + ), + ]); + $events->onFrame(function ($event) use (&$matchedEvents): void { + if (\is_object($event) + && $event instanceof EventsGetResponse200 + && 'create' === $event->getAction() + && 'container' === $event->getType() + ) { + $matchedEvents[] = $event; + } }); + $events->listen(); $containerConfig = new ContainersCreatePostBody(); $containerConfig->setImage('busybox:latest'); $containerConfig->setCmd(['echo', '-n', 'output']); - /** @var ContainersCreatePostResponse201 $containerCreate */ - $containerCreate = yield $docker->containerCreate($containerConfig); - - // Let a chance for the container create event to be dispatched to the consumer - yield new Delayed(1000); + yield $docker->containerCreate($containerConfig); - $events->cancel(); - - $matchedEvents = \array_filter( - $receivedEvents, - function ($event) use ($containerCreate) { - return \is_object($event) - && $event instanceof EventsGetResponse200 - && 'create' === $event->getAction() - && 'container' === $event->getType() - && null !== $event->getActor() - && $event->getActor()->getID() === $containerCreate->getId(); - } - ); - - $this->assertCount(1, $matchedEvents); + Loop::delay(1000, function () use ($events): void { + $events->cancel(); + }); }); + + $this->assertCount(1, $matchedEvents); } } From 73c0949843c29c076fb84147de86b7b9a9f8f1d3 Mon Sep 17 00:00:00 2001 From: Guillem CANAL Date: Sun, 13 May 2018 23:46:13 +0200 Subject: [PATCH 15/20] fix: Replaced $events->cancel() by Loop::stop() Reason: The travis step responsible to generate the coverage report is doing a composer update --prefer-stable --prefer-lowest --no-interaction which retreive an unstable version of amphp/artax. please check https://github.com/amphp/artax/blob/master/CHANGELOG.md#306 --- tests/DockerAsyncTest.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php index 0cda17c5..29b2f3bf 100644 --- a/tests/DockerAsyncTest.php +++ b/tests/DockerAsyncTest.php @@ -42,10 +42,8 @@ public function testAsync(): void }); } - /** @group sys */ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void { - \putenv('AMP_DEBUG=1'); $matchedEvents = []; Loop::run(function () use (&$matchedEvents) { @@ -78,8 +76,8 @@ public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void yield $docker->containerCreate($containerConfig); - Loop::delay(1000, function () use ($events): void { - $events->cancel(); + Loop::delay(1000, function (): void { + Loop::stop(); }); }); From 2a6df3d431e16a0b153cec1df8247b1031b3e72a Mon Sep 17 00:00:00 2001 From: Dibyajyoti Panda Date: Mon, 18 Jun 2018 02:42:49 +0530 Subject: [PATCH 16/20] Update container-run.md Added an example for executing command on running container. --- docs/cookbook/container-run.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/cookbook/container-run.md b/docs/cookbook/container-run.md index 0820e80a..6876d79e 100644 --- a/docs/cookbook/container-run.md +++ b/docs/cookbook/container-run.md @@ -208,3 +208,29 @@ $hostConfig->setPortBindings($portMap); $containerConfig->setHostConfig($hostConfig); ``` + +## Executing a command on a running container + +This example shows how you can execute an command on any running container. It is same as `docker exec CONTAINER_ID some_command `. + +```php +setTty(true); +$execConfig->setAttachStdout(true); +$execConfig->setAttachStderr(true); +$execConfig->setCmd(['mkdir', '/tmp/testDir']); + +$execid = $docker->containerExec('android',$execConfig)->getId(); +$execStartConfig = new ExecIdStartPostBody(); +$execStartConfig->setDetach(false); +$output = $docker->execStart($execid,$execStartConfig); + +var_dump($output); +``` From bbc493426d853581bc4aa73dc95b323fb05606d7 Mon Sep 17 00:00:00 2001 From: Dibyajyoti Panda Date: Mon, 18 Jun 2018 03:14:54 +0530 Subject: [PATCH 17/20] Update container-run.md --- docs/cookbook/container-run.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/cookbook/container-run.md b/docs/cookbook/container-run.md index 6876d79e..2ee824bf 100644 --- a/docs/cookbook/container-run.md +++ b/docs/cookbook/container-run.md @@ -230,7 +230,22 @@ $execConfig->setCmd(['mkdir', '/tmp/testDir']); $execid = $docker->containerExec('android',$execConfig)->getId(); $execStartConfig = new ExecIdStartPostBody(); $execStartConfig->setDetach(false); -$output = $docker->execStart($execid,$execStartConfig); -var_dump($output); +// Execute the command +$stream = $docker->execStart($execid,$execStartConfig); + +// To see the output stream of the 'exec' command +$stdoutText = ""; +$stderrText = ""; + +$stream->onStdout(function ($stdout) use (&$stdoutText) { + $stdoutText .= $stdout; +}); + +$stream->onStderr(function ($stderr) use (&$stderrText) { + $stderrText .= $stderr; +}); + +$stream->wait(); +var_dump([ "stdout" => $stdoutText, "stderr" => $stderrText ]) ; ``` From 885695f2f77be3727293664ad602ef16188f0c91 Mon Sep 17 00:00:00 2001 From: philip keighley Date: Mon, 9 Jul 2018 18:28:18 -0400 Subject: [PATCH 18/20] Fix grammatical error --- docs/cookbook/build-image.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cookbook/build-image.md b/docs/cookbook/build-image.md index e412361f..bea40589 100644 --- a/docs/cookbook/build-image.md +++ b/docs/cookbook/build-image.md @@ -37,7 +37,7 @@ $buildStream->wait(); ### Docker::FETCH_RESPONSE -The build function will return the raw [PSR7](http://www.php-fig.org/psr/psr-7/) Response. It's up too you handle +The build function will return the raw [PSR7](http://www.php-fig.org/psr/psr-7/) Response. It's up to you handle decoding and receiving correct output in this case. ## Context From 909d1c2d73284645035ff971cef814917f9a1997 Mon Sep 17 00:00:00 2001 From: Philip Keighley Date: Fri, 28 Dec 2018 09:39:17 -0500 Subject: [PATCH 19/20] Add missing 'to' before 'handle' --- docs/cookbook/build-image.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cookbook/build-image.md b/docs/cookbook/build-image.md index bea40589..71a5d4bc 100644 --- a/docs/cookbook/build-image.md +++ b/docs/cookbook/build-image.md @@ -37,7 +37,7 @@ $buildStream->wait(); ### Docker::FETCH_RESPONSE -The build function will return the raw [PSR7](http://www.php-fig.org/psr/psr-7/) Response. It's up to you handle +The build function will return the raw [PSR7](http://www.php-fig.org/psr/psr-7/) Response. It's up to you to handle decoding and receiving correct output in this case. ## Context From c44f1f2f288cef810abbb1288f9835dfeaddb929 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Fri, 25 Oct 2019 20:36:58 +0200 Subject: [PATCH 20/20] No longer maintained --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 94092f39..27464be6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +# No longer maintained + +I'm backing off maintaining this library due to a lack of motivation, time and usage of docker, contact me on twitter https://twitter.com/joelwurtz if you wish to take over this repository (or just do a fork). + Docker PHP ==========