diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000..d95b72a20
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+charset = utf-8
+trim_trailing_whitespace = true
+
+# JSON files
+[*.json]
+indent_style = space
+indent_size = 4
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 000000000..d018c1530
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,5 @@
+# These are supported funding model platforms
+
+github: flavioheleno
+patreon: flavioheleno
+custom: "https://www.buymeacoffee.com/flavioheleno"
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..e5fae30f4
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,12 @@
+version: 2
+updates:
+ # Maintain dependencies for GitHub Actions
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ # Maintain dependencies for PHP Packages
+ - package-ecosystem: "composer"
+ directory: "/"
+ schedule:
+ interval: "daily"
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
new file mode 100644
index 000000000..854f94f74
--- /dev/null
+++ b/.github/workflows/continuous-integration.yml
@@ -0,0 +1,54 @@
+name: "Continuous Integration"
+
+on:
+ push:
+ paths-ignore:
+ - "doc/**"
+ pull_request:
+ paths-ignore:
+ - "doc/**"
+
+jobs:
+ phpunit:
+ name: PHP ${{ matrix.php-version }} (${{ matrix.dependency-versions }})
+
+ runs-on: ubuntu-latest
+ continue-on-error: ${{ matrix.experimental }}
+
+ strategy:
+ fail-fast: false
+ matrix:
+ php-version:
+ - "8.1"
+ - "8.2"
+ - "8.3"
+ - "8.4"
+ - "8.5"
+ dependency-versions: [lowest, highest]
+ experimental: [false]
+
+ steps:
+ - name: Repository checkout
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+
+ - name: Setup PHP with PECL extension
+ uses: shivammathur/setup-php@bf6b4fbd49ca58e4608c9c89fba0b8d90bd2a39f # v2.35.5
+ with:
+ php-version: ${{ matrix.php-version }}
+ tools: composer:v2
+ coverage: pcov
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Install dependencies
+ uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1
+ with:
+ dependency-versions: ${{ matrix.dependency-versions }}
+ composer-options: ${{ matrix.composer-options }}
+
+ - name: Pull the docker image used by the tests.
+ run: docker pull busybox:latest
+
+ - name: Run PHPUnit test suite
+ run: composer run-script test-ci
diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml
new file mode 100644
index 000000000..43f70ce66
--- /dev/null
+++ b/.github/workflows/static-analysis.yml
@@ -0,0 +1,39 @@
+name: "Static Analysis"
+
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '.github/**'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '.github/**'
+
+jobs:
+ phpstan:
+ name: PHPStan
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Repository checkout
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+
+ - name: Setup PHP with PECL extension
+ uses: shivammathur/setup-php@bf6b4fbd49ca58e4608c9c89fba0b8d90bd2a39f # v2.35.5
+ with:
+ php-version: 8.1
+ tools: composer:v2
+ coverage: none
+
+ - name: Validate composer.json and composer.lock
+ run: composer validate --strict
+
+ - name: Install dependencies
+ uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1
+ with:
+ dependency-versions: lowest
+
+ - name: Run PHPStan
+ run: composer run-script phpstan -- --no-progress
diff --git a/.gitignore b/.gitignore
index 228f5459f..8d49b5514 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@ vendor/
bin/
composer.lock
.vagrant
-/.php_cs.cache
+/.php-cs-fixer.cache
+/.phpunit.result.cache
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
new file mode 100644
index 000000000..3bde3b9fc
--- /dev/null
+++ b/.php-cs-fixer.php
@@ -0,0 +1,47 @@
+in([
+ __DIR__.'/src',
+ __DIR__.'/tests',
+ ])
+ ->notPath('/fixtures/')
+;
+
+$config = new \PhpCsFixer\Config();
+return $config
+ ->setRules([
+ '@Symfony' => true,
+ '@Symfony:risky' => true,
+ '@PHP56Migration:risky' => true,
+ '@PHP70Migration' => true,
+ '@PHP70Migration:risky' => true,
+ '@PHP71Migration' => true,
+ '@PHP71Migration:risky' => true,
+ '@PHP73Migration' => true,
+ '@PHP74Migration' => true,
+ '@PHP74Migration:risky' => true,
+ '@PHP80Migration' => true,
+ '@PHP80Migration:risky' => true,
+ '@PHPUnit75Migration:risky' => true,
+ '@PHPUnit84Migration:risky' => true,
+ 'array_syntax' => [
+ 'syntax' => 'short'
+ ],
+ 'combine_consecutive_unsets' => true,
+ 'declare_strict_types' => true,
+ 'linebreak_after_opening_tag' => true,
+ 'modernize_types_casting' => true,
+ 'native_function_invocation' => true,
+ 'no_php4_constructor' => true,
+ 'ordered_imports' => true,
+ 'php_unit_strict' => true,
+ 'phpdoc_order' => true,
+ 'strict_comparison' => true,
+ 'strict_param' => true,
+ ])
+ ->setRiskyAllowed(true)
+ ->setIndent(' ')
+ ->setLineEnding("\n")
+ ->setFinder($finder)
+;
diff --git a/.php_cs b/.php_cs
deleted file mode 100644
index 3eaf3dae5..000000000
--- a/.php_cs
+++ /dev/null
@@ -1,38 +0,0 @@
-in([
- __DIR__.'/src',
- __DIR__.'/tests',
- ])
- ->notPath('/fixtures/')
-;
-
-return \PhpCsFixer\Config::create()
- ->setRules([
- '@Symfony' => true,
- '@Symfony:risky' => true,
- '@PHP56Migration' => true,
- '@PHP56Migration:risky' => true,
- '@PHP70Migration' => true,
- '@PHP70Migration:risky' => true,
- '@PHP71Migration' => true,
- '@PHP71Migration:risky' => true,
- 'array_syntax' => [
- 'syntax' => 'short'
- ],
- 'combine_consecutive_unsets' => true,
- 'declare_strict_types' => true,
- 'linebreak_after_opening_tag' => true,
- 'modernize_types_casting' => true,
- 'native_function_invocation' => true,
- 'no_php4_constructor' => true,
- 'ordered_imports' => true,
- 'php_unit_strict' => true,
- 'phpdoc_order' => true,
- 'strict_comparison' => true,
- 'strict_param' => true,
- ])
- ->setRiskyAllowed(true)
- ->setFinder($finder)
-;
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
deleted file mode 100644
index 60d211bf7..000000000
--- a/.scrutinizer.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-filter:
- paths: [src/*]
-checks:
- php:
- code_rating: true
- duplication: true
-tools:
- external_code_coverage: true
- php_code_sniffer:
- config:
- standard: "PSR2"
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 41708d6f6..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,68 +0,0 @@
-language: php
-sudo: required
-
-services:
- - docker
-
-cache:
- directories:
- - $HOME/.composer/cache
-
-php: 7.2
-
-env:
- global:
- - TEST_COMMAND="composer test"
- matrix:
- - DOCKER_API_VERSION=1.36 DOCKER_VERSION=18.02.0~ce-0~ubuntu
- - DOCKER_API_VERSION=1.36 DOCKER_VERSION=18.01.0~ce-0~ubuntu
- - DOCKER_API_VERSION=1.35 DOCKER_VERSION=17.12.0~ce-0~ubuntu
- - DOCKER_API_VERSION=1.34 DOCKER_VERSION=17.11.0~ce-0~ubuntu
- - DOCKER_API_VERSION=1.33 DOCKER_VERSION=17.10.0~ce-0~ubuntu
- - DOCKER_API_VERSION=1.32 DOCKER_VERSION=17.09.0~ce-0~ubuntu
- - DOCKER_API_VERSION=1.31 DOCKER_VERSION=17.07.0~ce-0~ubuntu
- - DOCKER_API_VERSION=1.30 DOCKER_VERSION=17.06.2~ce-0~ubuntu
- - DOCKER_API_VERSION=1.29 DOCKER_VERSION=17.05.0~ce-0~ubuntu-trusty
- - DOCKER_API_VERSION=1.28 DOCKER_VERSION=17.04.0~ce-0~ubuntu-trusty
- - DOCKER_API_VERSION=1.27 DOCKER_VERSION=17.03.2~ce-0~ubuntu-trusty
- - DOCKER_API_VERSION=1.26 DOCKER_VERSION=17.03.2~ce-0~ubuntu-trusty
- - DOCKER_API_VERSION=1.25 DOCKER_VERSION=17.03.2~ce-0~ubuntu-trusty
-
-matrix:
- allow_failures:
- - php: hhvm
- fast_finish: true
- include:
- - php: 7.1
- sudo: required
- services:
- - docker
- env: DOCKER_API_VERSION=1.25 DOCKER_VERSION=17.03.2~ce-0~ubuntu-trusty COMPOSER_FLAGS="--prefer-stable --prefer-lowest" COVERAGE=true TEST_COMMAND="composer test-ci"
- - php: 7.1
- env: DOCKER_API_VERSION=1.36 DOCKER_VERSION=18.02.0~ce-0~ubuntu TEST_COMMAND="composer lint"
- - php: 7.2
- sudo: required
- services:
- - docker
- env: DOCKER_API_VERSION=1.36 DOCKER_VERSION=18.02.0~ce-0~ubuntu
-
-before_install:
- - sudo apt-get update
- - sudo apt-cache madison docker-ce
- - sudo apt-get -o Dpkg::Options::="--force-confnew" install -y --force-yes docker-ce=${DOCKER_VERSION}
- - travis_retry composer self-update
-
-install:
- - travis_retry composer install
- - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction
- - travis_retry composer require docker-php/docker-php-api:4.${DOCKER_API_VERSION}.*
-
-script:
- - $TEST_COMMAND
-
-after_success:
- - if [[ "$COVERAGE" = true ]]; then wget https://scrutinizer-ci.com/ocular.phar; fi
- - if [[ "$COVERAGE" = true ]]; then php ocular.phar code-coverage:upload --format=php-clover build/coverage.xml; fi
-
-after_script:
- - sudo cat /var/log/upstart/docker.log
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6be589b9f..d25bfef16 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -67,9 +67,9 @@ $ git pull --rebase upstream master
$ git push -f origin feature-or-bug-fix-description
```
-## Internal
+## Internal
-This library consist, for the most part, of auto generated code where the reference is an [Open API Specification (Swagger v2)](https://openapis.org/). In order to modify API
+This library consist, for the most part, of auto generated code where the reference is an [Open API Specification (Swagger v2)](https://openapis.org/). In order to modify API
endpoint or requested / returned object, you will need to update the `docker-swagger.json` file instead of files in the `generated` directory.
There is a bash script at the root of this repository `generate.sh` which helps launching the command to generate files according to the
diff --git a/README.md b/README.md
index 27464be66..51495e03b 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,4 @@
-# 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
-==========
+# Docker PHP
**Docker PHP** (for lack of a better name) is a [Docker](http://docker.com/) client written in PHP.
This library aim to reach 100% API support of the Docker Engine.
@@ -11,40 +6,32 @@ This library aim to reach 100% API support of the Docker Engine.
The test suite currently passes against Docker Remote API v1.25 to v1.36.
[](http://docker-php.readthedocs.org/en/latest/)
-[](https://github.com/docker-php/docker-php/releases)
+[](https://github.com/beluga-php/docker-php/releases)
[](LICENSE)
-[](https://travis-ci.org/docker-php/docker-php)
-[](https://scrutinizer-ci.com/g/docker-php/docker-php)
-[](https://scrutinizer-ci.com/g/docker-php/docker-php)
-[](https://packagist.org/packages/docker-php/docker-php)
-[](http://slack.httplug.io)
+[](https://packagist.org/packages/beluga-php/docker-php)
-Installation
-------------
+## Installation
The recommended way to install Docker PHP is of course to use [Composer](http://getcomposer.org/):
```bash
-composer require docker-php/docker-php
+composer require beluga-php/docker-php
```
-Docker API Version
-------------------
+## Docker API Version
-By default it will use the last version of docker api available, if you want to fix a version (like 1.25) you can add this
+By default it will use the last version of docker api available, if you want to fix a version (like 1.41) you can add this
requirement to composer:
```bash
-composer require "docker-php/docker-php-api:4.1.25.*"
+composer require "beluga-php/docker-php-api:6.1.41.*"
```
-Usage
------
+## Usage
See [the documentation](http://docker-php.readthedocs.org/en/latest/).
-Unit Tests
-----------
+## Unit Tests
Setup the test suite using [Composer](http://getcomposer.org/) if not already done:
@@ -58,17 +45,16 @@ Run it using [PHPUnit](http://phpunit.de/):
$ composer test
```
-Contributing
-------------
+## Contributing
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
-Credits
--------
+## Credits
This README heavily inspired by [willdurand/Negotiation](https://github.com/willdurand/Negotiation) by @willdurand. This guy is pretty awesome.
-License
--------
+This library is a fork of the original [docker-php/docker-php](https://github.com/docker-php/docker-php), created by [Geoffrey Bachelet](https://github.com/ubermuda) and [Joel Wurtz](https://github.com/joelwurtz).
+
+## License
The MIT License (MIT). Please see [License File](LICENSE) for more information.
diff --git a/composer.json b/composer.json
index 64019814f..eca91be79 100644
--- a/composer.json
+++ b/composer.json
@@ -1,8 +1,42 @@
{
- "name": "docker-php/docker-php",
+ "name": "beluga-php/docker-php",
+ "description": "A Docker PHP client",
"license": "MIT",
"type": "library",
- "description": "A Docker PHP client",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/flavioheleno"
+ }
+ ],
+ "require": {
+ "php": ">=8.1",
+ "beluga-php/docker-php-api": "7.1.45.*",
+ "nyholm/psr7": "^1.8",
+ "php-http/client-common": "^2.7",
+ "php-http/discovery": "^1.19",
+ "php-http/socket-client": "^2.3",
+ "psr/http-message": "^2.0",
+ "symfony/filesystem": "^6.3 || ^7.0 || ^8.0",
+ "symfony/process": "^6.3 || ^7.0 || ^8.0",
+ "symfony/serializer": "^6.3 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "ergebnis/composer-normalize": "^2.42",
+ "friendsofphp/php-cs-fixer": "^3.8",
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.5.46",
+ "psy/psysh": "^0.12.8",
+ "roave/security-advisories": "dev-latest"
+ },
+ "conflict": {
+ "docker-php/docker-php": "*",
+ "nikic/php-parser": "<4.13",
+ "php-http/message": "<1.15"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true,
"autoload": {
"psr-4": {
"Docker\\": "src/"
@@ -13,41 +47,44 @@
"Docker\\Tests\\": "tests/"
}
},
- "require": {
- "php": ">=7.1",
- "docker-php/docker-php-api": "4.1.*",
- "guzzlehttp/psr7": "^1.2",
- "php-http/client-common": "^1.6",
- "php-http/socket-client": "^1.3",
- "php-http/message": "^1.0",
- "symfony/filesystem": "^2.3 || ^3.0 || ^4.0",
- "symfony/process": "^2.3 || ^3.0 || ^4.0"
- },
- "suggest": {
- "php-http/httplug-bundle": "For integration with Symfony",
- "amphp/artax": "To use the async api"
- },
- "require-dev": {
- "phpunit/phpunit": "^6.0",
- "friendsofphp/php-cs-fixer": "2.8.1",
- "amphp/artax": "^3.0",
- "amphp/socket": "^0.10.5"
- },
- "conflict": {
- "amphp/socket": "<0.10.5",
- "amphp/artax": "<3.0"
- },
- "scripts": {
- "test": "vendor/bin/phpunit",
- "test-ci": "vendor/bin/phpunit --coverage-clover build/coverage.xml",
- "lint": "vendor/bin/php-cs-fixer fix --dry-run --verbose --diff",
- "lint-fix": "vendor/bin/php-cs-fixer fix --verbose"
+ "config": {
+ "allow-plugins": {
+ "ergebnis/composer-normalize": true,
+ "php-http/discovery": false
+ },
+ "optimize-autoloader": true,
+ "preferred-install": "dist",
+ "sort-packages": true
},
"extra": {
"branch-alias": {
- "dev-master": "2.x-dev"
+ "1.41": "1.41.x-dev",
+ "1.42": "1.42.x-dev",
+ "1.43": "1.43.x-dev",
+ "1.44": "1.44.x-dev",
+ "dev-master": "1.45.x-dev"
}
},
- "prefer-stable": true,
- "minimum-stability": "dev"
+ "scripts": {
+ "console": "vendor/bin/psysh",
+ "lint": "vendor/bin/parallel-lint --exclude vendor .",
+ "php-cs-fixer": "vendor/bin/php-cs-fixer fix --dry-run --verbose --diff",
+ "php-cs-fixer-fix": "vendor/bin/php-cs-fixer fix --verbose",
+ "phpstan": "vendor/bin/phpstan analyse --level 2 src",
+ "phpunit": "vendor/bin/phpunit ./tests/ --coverage-html=./report/coverage/ --testdox-html=./report/testdox.html --disallow-test-output --process-isolation",
+ "test": [
+ "@lint",
+ "@phpunit"
+ ],
+ "test-ci": "vendor/bin/phpunit ./tests/ --disallow-test-output --process-isolation",
+ "test-coverage": "vendor/bin/phpunit ./tests/ --whitelist=./src/ --coverage-clover=clover.xml"
+ },
+ "scripts-descriptions": {
+ "console": "Runs PsySH Console",
+ "lint": "Runs complete codebase lint testing",
+ "phpunit": "Runs library test suite",
+ "test": "Runs all tests",
+ "test-ci": "Runs library test suite (for continuous integration)",
+ "test-coverage": "Runs test-coverage analysis"
+ }
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index c40525666..cbc386105 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,27 +1,23 @@
-
-
-
-
-
- tests/
-
-
-
-
- src
-
-
-
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd"
+ backupGlobals="false"
+ colors="true"
+ processIsolation="false"
+ stopOnFailure="false"
+ bootstrap="vendor/autoload.php"
+ cacheDirectory=".phpunit.cache"
+ backupStaticProperties="false">
+
+
+
+ tests/
+
+
+
+
+ src
+
+
diff --git a/src/Client/AmpArtaxStreamEndpoint.php b/src/Client/AmpArtaxStreamEndpoint.php
deleted file mode 100644
index ec7f3b9a0..000000000
--- a/src/Client/AmpArtaxStreamEndpoint.php
+++ /dev/null
@@ -1,26 +0,0 @@
-transformResponseBody($chunk, $response->getStatus(), $serializer);
- };
- }
-
- return new ArtaxCallbackStream($response->getBody(), $cancellationTokenSource, $responseTransformer);
- });
- }
-}
diff --git a/src/Client/ProvideAmpArtaxClientOptions.php b/src/Client/ProvideAmpArtaxClientOptions.php
deleted file mode 100644
index cd1aa87db..000000000
--- a/src/Client/ProvideAmpArtaxClientOptions.php
+++ /dev/null
@@ -1,15 +0,0 @@
-directory = $directory;
$this->format = $format;
@@ -86,7 +86,7 @@ public function setDirectory($directory): void
*/
public function getDockerfileContent()
{
- return \file_get_contents($this->directory.DIRECTORY_SEPARATOR.'Dockerfile');
+ return file_get_contents($this->directory.\DIRECTORY_SEPARATOR.'Dockerfile');
}
/**
@@ -114,7 +114,7 @@ public function read()
*/
public function toTar()
{
- $process = new Process('/usr/bin/env tar c .', $this->directory);
+ $process = new Process(['/usr/bin/env', 'tar', '-c', '.'], $this->directory);
$process->run();
if (!$process->isSuccessful()) {
@@ -132,7 +132,7 @@ public function toTar()
public function toStream()
{
if (!\is_resource($this->process)) {
- $this->process = \proc_open('/usr/bin/env tar c .', [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes, $this->directory);
+ $this->process = proc_open('/usr/bin/env tar -c .', [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipes, $this->directory);
$this->stream = $pipes[1];
}
@@ -142,11 +142,11 @@ public function toStream()
public function __destruct()
{
if (\is_resource($this->stream)) {
- \fclose($this->stream);
+ fclose($this->stream);
}
if (\is_resource($this->process)) {
- \proc_close($this->process);
+ proc_close($this->process);
}
if ($this->cleanup) {
diff --git a/src/Context/ContextBuilder.php b/src/Context/ContextBuilder.php
index 74a4308bf..cda9629f5 100644
--- a/src/Context/ContextBuilder.php
+++ b/src/Context/ContextBuilder.php
@@ -39,9 +39,9 @@ class ContextBuilder
private $entrypoint;
/**
- * @param \Symfony\Component\Filesystem\Filesystem
+ * @param \Symfony\Component\Filesystem\Filesystem $fs
*/
- public function __construct(Filesystem $fs = null)
+ public function __construct(?Filesystem $fs = null)
{
$this->fs = $fs ?: new Filesystem();
$this->format = Context::FORMAT_STREAM;
@@ -255,7 +255,7 @@ public function volume($volume)
*/
public function getContext()
{
- $directory = \sys_get_temp_dir().'/ctb-'.\microtime();
+ $directory = sys_get_temp_dir().'/ctb-'.microtime();
$this->fs->mkdir($directory);
$this->write($directory);
@@ -276,7 +276,7 @@ private function write($directory): void
{
$dockerfile = [];
// Insert a FROM instruction if the file does not start with one.
- if (empty($this->commands) || $this->commands[0]['type'] !== 'FROM') {
+ if (empty($this->commands) || 'FROM' !== $this->commands[0]['type']) {
$dockerfile[] = 'FROM base';
}
foreach ($this->commands as $command) {
@@ -325,7 +325,7 @@ private function write($directory): void
$dockerfile[] = 'CMD '.$this->command;
}
- $this->fs->dumpFile($directory.DIRECTORY_SEPARATOR.'Dockerfile', \implode(PHP_EOL, $dockerfile));
+ $this->fs->dumpFile($directory.\DIRECTORY_SEPARATOR.'Dockerfile', implode(\PHP_EOL, $dockerfile));
}
/**
@@ -338,12 +338,12 @@ private function write($directory): void
*/
private function getFile($directory, $content)
{
- $hash = \md5($content);
+ $hash = md5($content);
if (!\array_key_exists($hash, $this->files)) {
- $file = \tempnam($directory, '');
+ $file = tempnam($directory, '');
$this->fs->dumpFile($file, $content);
- $this->files[$hash] = \basename($file);
+ $this->files[$hash] = basename($file);
}
return $this->files[$hash];
@@ -359,14 +359,14 @@ private function getFile($directory, $content)
*/
private function getFileFromStream($directory, $stream)
{
- $file = \tempnam($directory, '');
- $target = \fopen($file, 'w');
- if (0 === \stream_copy_to_stream($stream, $target)) {
+ $file = tempnam($directory, '');
+ $target = fopen($file, 'w');
+ if (0 === stream_copy_to_stream($stream, $target)) {
throw new \RuntimeException('Failed to write stream to file');
}
- \fclose($target);
+ fclose($target);
- return \basename($file);
+ return basename($file);
}
/**
@@ -379,10 +379,10 @@ private function getFileFromStream($directory, $stream)
*/
private function getFileFromDisk($directory, $source)
{
- $hash = 'DISK-'.\md5(\realpath($source));
+ $hash = 'DISK-'.md5(realpath($source));
if (!\array_key_exists($hash, $this->files)) {
// Check if source is a directory or a file.
- if (\is_dir($source)) {
+ if (is_dir($source)) {
$this->fs->mirror($source, $directory.'/'.$hash, null, ['copy_on_windows' => true]);
} else {
$this->fs->copy($source, $directory.'/'.$hash);
diff --git a/src/Docker.php b/src/Docker.php
index 591acb5f0..9333e7e3c 100644
--- a/src/Docker.php
+++ b/src/Docker.php
@@ -5,7 +5,10 @@
namespace Docker;
use Docker\API\Client;
+use Docker\API\Endpoint\SystemInfo;
+use Docker\API\Exception\BadRequestException;
use Docker\API\Model\AuthConfig;
+use Docker\API\Model\ExecIdStartPostBody;
use Docker\Endpoint\ContainerAttach;
use Docker\Endpoint\ContainerAttachWebsocket;
use Docker\Endpoint\ContainerLogs;
@@ -23,61 +26,57 @@ class Docker extends Client
/**
* {@inheritdoc}
*/
- public function containerAttach(string $id, array $queryParameters = [], string $fetch = self::FETCH_OBJECT)
+ public function containerAttach(string $id, array $queryParameters = [], string $fetch = self::FETCH_OBJECT, array $accept = [])
{
- return $this->executePsr7Endpoint(new ContainerAttach($id, $queryParameters), $fetch);
+ return $this->executeEndpoint(new ContainerAttach($id, $queryParameters, $accept), $fetch);
}
/**
* {@inheritdoc}
*/
- public function containerAttachWebsocket(string $id, array $queryParameters = [], string $fetch = self::FETCH_OBJECT)
+ public function containerAttachWebsocket(string $id, array $queryParameters = [], string $fetch = self::FETCH_OBJECT, array $accept = [])
{
- return $this->executePsr7Endpoint(new ContainerAttachWebsocket($id, $queryParameters), $fetch);
+ return $this->executeEndpoint(new ContainerAttachWebsocket($id, $queryParameters, $accept), $fetch);
}
/**
* {@inheritdoc}
*/
- public function containerLogs(string $id, array $queryParameters = [], string $fetch = self::FETCH_OBJECT)
+ public function containerLogs(string $id, array $queryParameters = [], string $fetch = self::FETCH_OBJECT, array $accept = [])
{
- return $this->executePsr7Endpoint(new ContainerLogs($id, $queryParameters), $fetch);
+ return $this->executeEndpoint(new ContainerLogs($id, $queryParameters, $accept), $fetch);
}
/**
* {@inheritdoc}
*/
- public function execStart(string $id, \Docker\API\Model\ExecIdStartPostBody $execStartConfig, string $fetch = self::FETCH_OBJECT)
+ public function execStart(string $id, ?ExecIdStartPostBody $requestBody = null, string $fetch = self::FETCH_OBJECT, array $accept = [])
{
- return $this->executePsr7Endpoint(new ExecStart($id, $execStartConfig), $fetch);
+ return $this->executeEndpoint(new ExecStart($id, $requestBody, $accept), $fetch);
}
/**
* {@inheritdoc}
*/
- public function imageBuild($inputStream, array $queryParameters = [], array $headerParameters = [], string $fetch = self::FETCH_OBJECT)
+ public function imageBuild($requestBody = null, array $queryParameters = [], array $headerParameters = [], string $fetch = self::FETCH_OBJECT)
{
- return $this->executePsr7Endpoint(new ImageBuild($inputStream, $queryParameters, $headerParameters), $fetch);
+ return $this->executeEndpoint(new ImageBuild($requestBody, $queryParameters, $headerParameters), $fetch);
}
/**
* {@inheritdoc}
*/
- public function imageCreate(string $inputImage, array $queryParameters = [], array $headerParameters = [], string $fetch = self::FETCH_OBJECT)
+ public function imageCreate(?string $requestBody = null, array $queryParameters = [], array $headerParameters = [], string $fetch = self::FETCH_OBJECT)
{
- return $this->executePsr7Endpoint(new ImageCreate($inputImage, $queryParameters, $headerParameters), $fetch);
+ return $this->executeEndpoint(new ImageCreate($requestBody, $queryParameters, $headerParameters), $fetch);
}
-
- /**
- * {@inheritdoc}
- */
- public function imagePush(string $name, array $queryParameters = [], array $headerParameters = [], string $fetch = self::FETCH_OBJECT)
+ public function imagePush(string $name, array $queryParameters = [], array $headerParameters = [], string $fetch = self::FETCH_OBJECT, array $accept = [])
{
if (isset($headerParameters['X-Registry-Auth']) && $headerParameters['X-Registry-Auth'] instanceof AuthConfig) {
- $headerParameters['X-Registry-Auth'] = \base64_encode($this->serializer->serialize($headerParameters['X-Registry-Auth'], 'json'));
+ $headerParameters['X-Registry-Auth'] = base64_encode($this->serializer->serialize($headerParameters['X-Registry-Auth'], 'json'));
}
- return $this->executePsr7Endpoint(new ImagePush($name, $queryParameters, $headerParameters), $fetch);
+ return $this->executeEndpoint(new ImagePush($name, $queryParameters, $headerParameters, $accept), $fetch);
}
/**
@@ -85,15 +84,35 @@ public function imagePush(string $name, array $queryParameters = [], array $head
*/
public function systemEvents(array $queryParameters = [], string $fetch = self::FETCH_OBJECT)
{
- return $this->executePsr7Endpoint(new SystemEvents($queryParameters), $fetch);
+ return $this->executeEndpoint(new SystemEvents($queryParameters), $fetch);
}
- public static function create($httpClient = null)
+ public static function create(
+ $httpClient = null,
+ array $additionalPlugins = [],
+ array $additionalNormalizers = []
+ ): self
{
if (null === $httpClient) {
$httpClient = DockerClientFactory::createFromEnv();
}
- return parent::create($httpClient);
+ $client = parent::create($httpClient, $additionalPlugins, $additionalNormalizers);
+ $testClient = $client->executeRawEndpoint(new SystemInfo())->getBody()->getContents();
+ $jsonObj = json_decode($testClient);
+
+ if ($jsonObj !== null) {
+ if (isset($jsonObj->message)) {
+ // Check if the client is too new
+ if (strpos($jsonObj->message, 'client version') !== false && strpos($jsonObj->message, 'is too new') !== false) {
+ throw new BadRequestException("The client version is not supported by your version of Docker. Message: {$jsonObj->message}");
+ } else {
+ throw new BadRequestException($jsonObj->message);
+ }
+ }
+ } else {
+ throw new BadRequestException("Failed to decode JSON.");
+ }
+ return $client;
}
}
diff --git a/src/DockerAsync.php b/src/DockerAsync.php
deleted file mode 100644
index 111b4efc5..000000000
--- a/src/DockerAsync.php
+++ /dev/null
@@ -1,74 +0,0 @@
-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/DockerAsyncClient.php b/src/DockerAsyncClient.php
deleted file mode 100644
index ca440bd7b..000000000
--- a/src/DockerAsyncClient.php
+++ /dev/null
@@ -1,87 +0,0 @@
-resolveOptions($options);
- $socketPool = new HttpSocketPool(new StaticSocketPool($options['remote_socket'], new BasicSocketPool()));
- $this->client = new DefaultClient(null, $socketPool, $options['ssl']);
- }
-
- public function request($uriOrRequest, array $options = [], CancellationToken $cancellation = null): Promise
- {
- if ($uriOrRequest instanceof Request) {
- $uriOrRequest = $uriOrRequest->withUri('http://localhost'.$uriOrRequest->getUri());
- }
-
- return $this->client->request($uriOrRequest, $options, $cancellation);
- }
-
- protected function resolveOptions(array $options = []): array
- {
- $resolver = new OptionsResolver();
-
- $resolver->setDefaults([
- 'ssl' => null,
- ]);
-
- $resolver->setRequired([
- 'remote_socket',
- ]);
-
- $resolver->setAllowedTypes('ssl', ['null', ClientTlsContext::class]);
-
- return $resolver->resolve($options);
- }
-
- public static function createFromEnv(): self
- {
- $options = [
- 'remote_socket' => \getenv('DOCKER_HOST') ? \getenv('DOCKER_HOST') : 'unix:///var/run/docker.sock',
- ];
-
- 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 environment variable');
- }
-
- $tlsContext = new ClientTlsContext();
-
- $cafile = \getenv('DOCKER_CERT_PATH').DIRECTORY_SEPARATOR.'ca.pem';
- $certfile = \getenv('DOCKER_CERT_PATH').DIRECTORY_SEPARATOR.'cert.pem';
- $keyfile = \getenv('DOCKER_CERT_PATH').DIRECTORY_SEPARATOR.'key.pem';
-
- $certificate = new Certificate($certfile, $keyfile);
-
- $tlsContext = $tlsContext->withCaFile($cafile);
- $tlsContext = $tlsContext->withCertificate($certificate);
-
- if (\getenv('DOCKER_PEER_NAME')) {
- $tlsContext = $tlsContext->withPeerName(\getenv('DOCKER_PEER_NAME'));
- }
-
- $options['ssl'] = $tlsContext;
- }
-
- return new static($options);
- }
-}
diff --git a/src/DockerClientFactory.php b/src/DockerClientFactory.php
index 918d87240..39b07e890 100644
--- a/src/DockerClientFactory.php
+++ b/src/DockerClientFactory.php
@@ -4,55 +4,62 @@
namespace Docker;
-use GuzzleHttp\Psr7\Uri;
use Http\Client\Common\Plugin\AddHostPlugin;
+use Http\Client\Common\Plugin\AddPathPlugin;
use Http\Client\Common\Plugin\ContentLengthPlugin;
use Http\Client\Common\Plugin\DecoderPlugin;
+use Http\Client\Common\Plugin\HeaderDefaultsPlugin;
+use Http\Client\Common\PluginClient;
use Http\Client\Common\PluginClientFactory;
-use Http\Client\HttpClient;
-use Http\Client\Socket\Client as SocketHttpClient;
-use Http\Message\MessageFactory\GuzzleMessageFactory;
+use Http\Client\Socket\Client;
+use Http\Discovery\Psr17FactoryDiscovery;
final class DockerClientFactory
{
- /**
- * ( .
- */
- public static function create(array $config = [], PluginClientFactory $pluginClientFactory = null): HttpClient
+ public static function create(array $config = [], ?PluginClientFactory $pluginClientFactory = null): PluginClient
{
if (!\array_key_exists('remote_socket', $config)) {
$config['remote_socket'] = 'unix:///var/run/docker.sock';
}
- $messageFactory = new GuzzleMessageFactory();
- $socketClient = new SocketHttpClient($messageFactory, $config);
- $host = \preg_match('/unix:\/\//', $config['remote_socket']) ? 'http://localhost' : $config['remote_socket'];
+ $socketClient = new Client($config);
- $pluginClientFactory = $pluginClientFactory ?? new PluginClientFactory();
+ $uriFactory = Psr17FactoryDiscovery::findUriFactory();
+ $host = preg_match('/unix:\/\//', $config['remote_socket']) ? 'http://localhost' : $config['remote_socket'];
- return $pluginClientFactory->createClient($socketClient, [
- new ContentLengthPlugin(),
- new DecoderPlugin(),
- new AddHostPlugin(new Uri($host)),
- ], [
- 'client_name' => 'docker-client',
- ]);
+ $pluginClientFactory ??= new PluginClientFactory();
+
+ return $pluginClientFactory->createClient(
+ $socketClient,
+ [
+ new ContentLengthPlugin(),
+ new DecoderPlugin(),
+ new AddPathPlugin($uriFactory->createUri('/v1.45')),
+ new AddHostPlugin($uriFactory->createUri($host)),
+ new HeaderDefaultsPlugin([
+ 'host' => parse_url($host, \PHP_URL_HOST),
+ ]),
+ ],
+ [
+ 'client_name' => 'docker-client',
+ ]
+ );
}
- public static function createFromEnv(PluginClientFactory $pluginClientFactory = null): HttpClient
+ public static function createFromEnv(?PluginClientFactory $pluginClientFactory = null): PluginClient
{
$options = [
- 'remote_socket' => \getenv('DOCKER_HOST') ? \getenv('DOCKER_HOST') : 'unix:///var/run/docker.sock',
+ 'remote_socket' => getenv('DOCKER_HOST') ? getenv('DOCKER_HOST') : 'unix:///var/run/docker.sock',
];
- if (\getenv('DOCKER_TLS_VERIFY') && '1' === \getenv('DOCKER_TLS_VERIFY')) {
- if (!\getenv('DOCKER_CERT_PATH')) {
+ 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 environment variable');
}
- $cafile = \getenv('DOCKER_CERT_PATH').DIRECTORY_SEPARATOR.'ca.pem';
- $certfile = \getenv('DOCKER_CERT_PATH').DIRECTORY_SEPARATOR.'cert.pem';
- $keyfile = \getenv('DOCKER_CERT_PATH').DIRECTORY_SEPARATOR.'key.pem';
+ $cafile = getenv('DOCKER_CERT_PATH').\DIRECTORY_SEPARATOR.'ca.pem';
+ $certfile = getenv('DOCKER_CERT_PATH').\DIRECTORY_SEPARATOR.'cert.pem';
+ $keyfile = getenv('DOCKER_CERT_PATH').\DIRECTORY_SEPARATOR.'key.pem';
$stream_context = [
'cafile' => $cafile,
@@ -60,8 +67,8 @@ public static function createFromEnv(PluginClientFactory $pluginClientFactory =
'local_pk' => $keyfile,
];
- if (\getenv('DOCKER_PEER_NAME')) {
- $stream_context['peer_name'] = \getenv('DOCKER_PEER_NAME');
+ if (getenv('DOCKER_PEER_NAME')) {
+ $stream_context['peer_name'] = getenv('DOCKER_PEER_NAME');
}
$options['ssl'] = true;
diff --git a/src/Endpoint/ContainerAttach.php b/src/Endpoint/ContainerAttach.php
index a2d180e93..1c776639e 100644
--- a/src/Endpoint/ContainerAttach.php
+++ b/src/Endpoint/ContainerAttach.php
@@ -6,27 +6,17 @@
use Docker\API\Endpoint\ContainerAttach as BaseEndpoint;
use Docker\Stream\DockerRawStream;
-use Jane\OpenApiRuntime\Client\Client;
-use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\SerializerInterface;
class ContainerAttach extends BaseEndpoint
{
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (200 === $response->getStatusCode() && DockerRawStream::HEADER === $response->getHeaderLine('Content-Type')) {
- return new DockerRawStream($response->getBody());
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode() && DockerRawStream::HEADER === $contentType) {
+ return new DockerRawStream($response->getBody());
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Endpoint/ContainerAttachWebsocket.php b/src/Endpoint/ContainerAttachWebsocket.php
index fefb3638a..ee6fe0237 100644
--- a/src/Endpoint/ContainerAttachWebsocket.php
+++ b/src/Endpoint/ContainerAttachWebsocket.php
@@ -6,8 +6,7 @@
use Docker\API\Endpoint\ContainerAttachWebsocket as BaseEndpoint;
use Docker\Stream\AttachWebsocketStream;
-use Jane\OpenApiRuntime\Client\Client;
-use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException;
+use Docker\Stream\DockerRawStream;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\SerializerInterface;
@@ -15,30 +14,26 @@ class ContainerAttachWebsocket extends BaseEndpoint
{
public function getExtraHeaders(): array
{
- return \array_merge(parent::getExtraHeaders(), [
- 'Host' => 'localhost',
- 'Origin' => 'php://docker-php',
- 'Upgrade' => 'websocket',
- 'Connection' => 'Upgrade',
- 'Sec-WebSocket-Version' => '13',
- 'Sec-WebSocket-Key' => \base64_encode(\uniqid()),
- ]);
+ return array_merge(
+ parent::getExtraHeaders(),
+ [
+ 'Host' => 'localhost',
+ 'Origin' => 'php://docker-php',
+ 'Upgrade' => 'websocket',
+ 'Connection' => 'Upgrade',
+ 'Sec-WebSocket-Version' => '13',
+ 'Sec-WebSocket-Key' => base64_encode(uniqid()),
+ ]
+ );
}
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string
+ $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (101 === $response->getStatusCode()) {
- return new AttachWebsocketStream($response->getBody());
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode() && DockerRawStream::HEADER === $contentType) {
+ return new AttachWebsocketStream($response->getBody());
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Endpoint/ContainerLogs.php b/src/Endpoint/ContainerLogs.php
index 42335752f..996b09c39 100644
--- a/src/Endpoint/ContainerLogs.php
+++ b/src/Endpoint/ContainerLogs.php
@@ -6,27 +6,17 @@
use Docker\API\Endpoint\ContainerLogs as BaseEndpoint;
use Docker\Stream\DockerRawStream;
-use Jane\OpenApiRuntime\Client\Client;
-use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\SerializerInterface;
class ContainerLogs extends BaseEndpoint
{
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (200 === $response->getStatusCode()) {
- return new DockerRawStream($response->getBody());
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode() && DockerRawStream::HEADER === $contentType) {
+ return new DockerRawStream($response->getBody());
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Endpoint/ExecStart.php b/src/Endpoint/ExecStart.php
index 48ddd5c8d..e2d8985be 100644
--- a/src/Endpoint/ExecStart.php
+++ b/src/Endpoint/ExecStart.php
@@ -6,27 +6,17 @@
use Docker\API\Endpoint\ExecStart as BaseEndpoint;
use Docker\Stream\DockerRawStream;
-use Jane\OpenApiRuntime\Client\Client;
-use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\SerializerInterface;
class ExecStart extends BaseEndpoint
{
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (200 === $response->getStatusCode() && DockerRawStream::HEADER === $response->getHeaderLine('Content-Type')) {
- return new DockerRawStream($response->getBody());
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode() && DockerRawStream::HEADER === $contentType) {
+ return new DockerRawStream($response->getBody());
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Endpoint/ImageBuild.php b/src/Endpoint/ImageBuild.php
index 65d3353fc..49239c4cf 100644
--- a/src/Endpoint/ImageBuild.php
+++ b/src/Endpoint/ImageBuild.php
@@ -7,38 +7,29 @@
use Docker\API\Endpoint\ImageBuild as BaseEndpoint;
use Docker\Stream\BuildStream;
use Docker\Stream\TarStream;
-use Jane\OpenApiRuntime\Client\Client;
-use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException;
+use Nyholm\Psr7\Stream;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\SerializerInterface;
class ImageBuild extends BaseEndpoint
{
- public function getBody(\Symfony\Component\Serializer\SerializerInterface $serializer, \Http\Message\StreamFactory $streamFactory = null): array
+ public function getBody(SerializerInterface $serializer, $streamFactory = null): array
{
$body = $this->body;
if (\is_resource($body)) {
- $body = new TarStream($body);
+ $body = new TarStream(Stream::create($body));
}
- return [[], $body];
+ return [['Content-Type' => ['application/octet-stream']], $body];
}
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (200 === $response->getStatusCode()) {
- return new BuildStream($response->getBody(), $serializer);
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode()) {
+ return new BuildStream($response->getBody(), $serializer);
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Endpoint/ImageCreate.php b/src/Endpoint/ImageCreate.php
index 196ba3e5e..3a50da2e9 100644
--- a/src/Endpoint/ImageCreate.php
+++ b/src/Endpoint/ImageCreate.php
@@ -6,27 +6,17 @@
use Docker\API\Endpoint\ImageCreate as BaseEndpoint;
use Docker\Stream\CreateImageStream;
-use Jane\OpenApiRuntime\Client\Client;
-use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\SerializerInterface;
class ImageCreate extends BaseEndpoint
{
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (200 === $response->getStatusCode()) {
- return new CreateImageStream($response->getBody(), $serializer);
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode()) {
+ return new CreateImageStream($response->getBody(), $serializer);
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Endpoint/ImagePush.php b/src/Endpoint/ImagePush.php
index 3d2eabcca..61e165915 100644
--- a/src/Endpoint/ImagePush.php
+++ b/src/Endpoint/ImagePush.php
@@ -6,8 +6,6 @@
use Docker\API\Endpoint\ImagePush as BaseEndpoint;
use Docker\Stream\PushStream;
-use Jane\OpenApiRuntime\Client\Client;
-use Jane\OpenApiRuntime\Client\Exception\InvalidFetchModeException;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\SerializerInterface;
@@ -15,23 +13,15 @@ class ImagePush extends BaseEndpoint
{
public function getUri(): string
{
- return \str_replace(['{name}'], [\urlencode($this->name)], '/images/{name}/push');
+ return str_replace(['{name}'], [urlencode($this->name)], '/images/{name}/push');
}
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (200 === $response->getStatusCode()) {
- return new PushStream($response->getBody(), $serializer);
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode()) {
+ return new PushStream($response->getBody(), $serializer);
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Endpoint/SystemEvents.php b/src/Endpoint/SystemEvents.php
index 712e67da5..3f57e916c 100644
--- a/src/Endpoint/SystemEvents.php
+++ b/src/Endpoint/SystemEvents.php
@@ -4,40 +4,19 @@
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 implements ProvideAmpArtaxClientOptions, AmpArtaxStreamEndpoint
+class SystemEvents extends BaseEndpoint
{
- use AmpArtaxStreamEndpointTrait;
-
- public function getAmpArtaxClientOptions(): array
- {
- return [ArtaxClient::OP_TRANSFER_TIMEOUT => 0];
- }
-
- public function parsePSR7Response(ResponseInterface $response, SerializerInterface $serializer, string $fetchMode = Client::FETCH_OBJECT)
+ protected function transformResponseBody(ResponseInterface $response, SerializerInterface $serializer, ?string $contentType = null)
{
- if (Client::FETCH_OBJECT === $fetchMode) {
- if (200 === $response->getStatusCode()) {
- return new EventStream($response->getBody(), $serializer);
- }
-
- return $this->transformResponseBody((string) $response->getBody(), $response->getStatusCode(), $serializer);
- }
-
- if (Client::FETCH_RESPONSE === $fetchMode) {
- return $response;
+ if (200 === $response->getStatusCode()) {
+ return new EventStream($response->getBody(), $serializer);
}
- throw new InvalidFetchModeException(\sprintf('Fetch mode %s is not supported', $fetchMode));
+ return parent::transformResponseBody($response, $serializer, $contentType);
}
}
diff --git a/src/Stream/ArtaxCallbackStream.php b/src/Stream/ArtaxCallbackStream.php
deleted file mode 100644
index f85d5219e..000000000
--- a/src/Stream/ArtaxCallbackStream.php
+++ /dev/null
@@ -1,78 +0,0 @@
-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/src/Stream/AttachWebsocketStream.php b/src/Stream/AttachWebsocketStream.php
index 402e417ca..0394ac2f8 100644
--- a/src/Stream/AttachWebsocketStream.php
+++ b/src/Stream/AttachWebsocketStream.php
@@ -30,7 +30,7 @@ public function __construct(StreamInterface $stream)
*/
public function write($data): void
{
- $rand = \random_int(0, 28);
+ $rand = random_int(0, 28);
$frame = [
'fin' => 1,
'rsv1' => 0,
@@ -39,7 +39,7 @@ public function write($data): void
'opcode' => 1, // We always send text
'mask' => 1,
'len' => \strlen($data),
- 'mask_key' => \substr(\md5(\uniqid()), $rand, 4),
+ 'mask_key' => substr(md5(uniqid()), $rand, 4),
'data' => $data,
];
@@ -65,12 +65,12 @@ public function write($data): void
$this->socketWrite(\chr($secondByte));
if (126 === $len) {
- $this->socketWrite(\pack('n', $frame['len']));
+ $this->socketWrite(pack('n', $frame['len']));
} elseif (127 === $len) {
$higher = $frame['len'] >> 32;
$lower = ($frame['len'] << 32) >> 32;
- $this->socketWrite(\pack('N', $higher));
- $this->socketWrite(\pack('N', $lower));
+ $this->socketWrite(pack('N', $higher));
+ $this->socketWrite(pack('N', $lower));
}
if (1 === $frame['mask']) {
@@ -87,11 +87,11 @@ public function write($data): void
* @param int $waitMicroTime Time to wait in microseconds before return false
* @param bool $getFrame Whether to return the frame of websocket or only the data
*
- * @return null|false|string|array Null for socket not available, false for no message, string for the last message and the frame array if $getFrame is set to true
+ * @return false|string|array|null Null for socket not available, false for no message, string for the last message and the frame array if $getFrame is set to true
*/
public function read($waitTime = 0, $waitMicroTime = 200000, $getFrame = false)
{
- if (!\is_resource($this->socket) || \feof($this->socket)) {
+ if (!\is_resource($this->socket) || feof($this->socket)) {
return null;
}
@@ -99,7 +99,7 @@ public function read($waitTime = 0, $waitMicroTime = 200000, $getFrame = false)
$write = null;
$expect = null;
- if (0 === \stream_select($read, $write, $expect, $waitTime, $waitMicroTime)) {
+ if (0 === stream_select($read, $write, $expect, $waitTime, $waitMicroTime)) {
return false;
}
@@ -121,9 +121,9 @@ public function read($waitTime = 0, $waitMicroTime = 200000, $getFrame = false)
// Get length of the frame
if (126 === $frame['len']) {
- $frame['len'] = \unpack('n', $this->socketRead(2))[1];
+ $frame['len'] = unpack('n', $this->socketRead(2))[1];
} elseif (127 === $frame['len']) {
- list($higher, $lower) = \array_values(\unpack('N2', $this->socketRead(8)));
+ [$higher, $lower] = array_values(unpack('N2', $this->socketRead(8)));
$frame['len'] = ($higher << 32) | $lower;
}
@@ -151,8 +151,6 @@ public function read($waitTime = 0, $waitMicroTime = 200000, $getFrame = false)
/**
* Force to have something of the expected size (block).
*
- * @param $length
- *
* @return string
*/
private function socketRead($length)
@@ -160,8 +158,8 @@ private function socketRead($length)
$read = '';
do {
- $read .= \fread($this->socket, $length - \strlen($read));
- } while (\strlen($read) < $length && !\feof($this->socket));
+ $read .= fread($this->socket, $length - \strlen($read));
+ } while (\strlen($read) < $length && !feof($this->socket));
return $read;
}
@@ -169,12 +167,10 @@ private function socketRead($length)
/**
* Write to the socket.
*
- * @param $data
- *
* @return int
*/
private function socketWrite($data)
{
- return \fwrite($this->socket, $data);
+ return fwrite($this->socket, $data);
}
}
diff --git a/src/Stream/BuildStream.php b/src/Stream/BuildStream.php
index b6ba9e705..34f32ac41 100644
--- a/src/Stream/BuildStream.php
+++ b/src/Stream/BuildStream.php
@@ -12,7 +12,7 @@
class BuildStream extends MultiJsonStream
{
/**
- * [@inheritdoc}.
+ * {@inheritdoc}.
*/
protected function getDecodeClass()
{
diff --git a/src/Stream/CallbackStream.php b/src/Stream/CallbackStream.php
index 62b746130..382c935f4 100644
--- a/src/Stream/CallbackStream.php
+++ b/src/Stream/CallbackStream.php
@@ -19,8 +19,6 @@ public function __construct(StreamInterface $stream)
/**
* Called when there is a new frame from the stream.
- *
- * @param callable $onNewFrame
*/
public function onFrame(callable $onNewFrame): void
{
@@ -29,8 +27,6 @@ public function onFrame(callable $onNewFrame): void
/**
* Read a frame in the stream.
- *
- * @return mixed
*/
abstract protected function readFrame();
diff --git a/src/Stream/CreateImageStream.php b/src/Stream/CreateImageStream.php
index f6cb92ca9..8d5aea7c6 100644
--- a/src/Stream/CreateImageStream.php
+++ b/src/Stream/CreateImageStream.php
@@ -12,7 +12,7 @@
class CreateImageStream extends MultiJsonStream
{
/**
- * [@inheritdoc}.
+ * {@inheritdoc}.
*/
protected function getDecodeClass()
{
diff --git a/src/Stream/DockerRawStream.php b/src/Stream/DockerRawStream.php
index 5f71d629c..1ec7ce8b0 100644
--- a/src/Stream/DockerRawStream.php
+++ b/src/Stream/DockerRawStream.php
@@ -29,8 +29,6 @@ public function __construct(StreamInterface $stream)
/**
* Add a callable to read stdin.
- *
- * @param callable $callback
*/
public function onStdin(callable $callback): void
{
@@ -39,8 +37,6 @@ public function onStdin(callable $callback): void
/**
* Add a callable to read stdout.
- *
- * @param callable $callback
*/
public function onStdout(callable $callback): void
{
@@ -49,8 +45,6 @@ public function onStdout(callable $callback): void
/**
* Add a callable to read stderr.
- *
- * @param callable $callback
*/
public function onStderr(callable $callback): void
{
@@ -68,7 +62,7 @@ protected function readFrame(): void
return;
}
- $decoded = \unpack('C1type/C3/N1size', $header);
+ $decoded = unpack('C1type/C3/N1size', $header);
$output = $this->forceRead($decoded['size']);
$callbackList = [];
@@ -92,8 +86,6 @@ protected function readFrame(): void
/**
* Force to have something of the expected size (block).
*
- * @param $length
- *
* @return string
*/
private function forceRead($length)
diff --git a/src/Stream/EventStream.php b/src/Stream/EventStream.php
index 0ba9df6f7..1c18a8050 100644
--- a/src/Stream/EventStream.php
+++ b/src/Stream/EventStream.php
@@ -12,10 +12,10 @@
class EventStream extends MultiJsonStream
{
/**
- * [@inheritdoc}.
+ * {@inheritdoc}.
*/
protected function getDecodeClass()
{
- return 'EventsGetResponse200';
+ return 'EventMessage';
}
}
diff --git a/src/Stream/MultiJsonStream.php b/src/Stream/MultiJsonStream.php
index 0973f98a5..536afa171 100644
--- a/src/Stream/MultiJsonStream.php
+++ b/src/Stream/MultiJsonStream.php
@@ -22,9 +22,6 @@ public function __construct(StreamInterface $stream, SerializerInterface $serial
$this->serializer = $serializer;
}
- /**
- * {@inheritdoc}
- */
protected function readFrame()
{
$jsonFrameEnd = false;
diff --git a/src/Stream/PushStream.php b/src/Stream/PushStream.php
index c40cb6688..4b7242db9 100644
--- a/src/Stream/PushStream.php
+++ b/src/Stream/PushStream.php
@@ -12,7 +12,7 @@
class PushStream extends MultiJsonStream
{
/**
- * [@inheritdoc}.
+ * {@inheritdoc}.
*/
protected function getDecodeClass()
{
diff --git a/src/Stream/TarStream.php b/src/Stream/TarStream.php
index ee0a17519..f14823c89 100644
--- a/src/Stream/TarStream.php
+++ b/src/Stream/TarStream.php
@@ -4,18 +4,92 @@
namespace Docker\Stream;
-use GuzzleHttp\Psr7\Stream;
+use Psr\Http\Message\StreamInterface;
/**
* This class avoid a bug in PHP where fstat return a size of 0 for process stream.
*/
-class TarStream extends Stream
+class TarStream implements StreamInterface
{
- /**
- * {@inheritdoc}
- */
- public function getSize()
+ protected $stream;
+
+ public function __construct(StreamInterface $stream)
+ {
+ $this->stream = $stream;
+ }
+
+ public function __toString()
+ {
+ return $this->stream->__toString();
+ }
+
+ public function close(): void
+ {
+ $this->stream->close();
+ }
+
+ public function detach()
+ {
+ return $this->stream->detach();
+ }
+
+ public function getSize(): ?int
{
return null;
}
+
+ public function tell(): int
+ {
+ return $this->stream->tell();
+ }
+
+ public function eof(): bool
+ {
+ return $this->stream->eof();
+ }
+
+ public function isSeekable(): bool
+ {
+ return $this->stream->isSeekable();
+ }
+
+ public function seek($offset, $whence = \SEEK_SET): void
+ {
+ $this->stream->seek($offset, $whence);
+ }
+
+ public function rewind(): void
+ {
+ $this->stream->rewind();
+ }
+
+ public function isWritable(): bool
+ {
+ return $this->stream->isWritable();
+ }
+
+ public function write($string): int
+ {
+ return $this->stream->write($string);
+ }
+
+ public function isReadable(): bool
+ {
+ return $this->stream->isReadable();
+ }
+
+ public function read($length): string
+ {
+ return $this->stream->read($length);
+ }
+
+ public function getContents(): string
+ {
+ return $this->stream->getContents();
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $this->stream->getMetadata($key);
+ }
}
diff --git a/tests/Context/ContextBuilderTest.php b/tests/Context/ContextBuilderTest.php
index 828faa63f..613964f01 100644
--- a/tests/Context/ContextBuilderTest.php
+++ b/tests/Context/ContextBuilderTest.php
@@ -61,11 +61,10 @@ public function testWriteTmpFiles(): void
$contextBuilder->add('/foo', 'random content');
$context = $contextBuilder->getContext();
- $filename = \preg_replace(<<getDockerfileContent());
+ $filename = preg_replace(<<getDockerfileContent());
$this->assertStringEqualsFile($context->getDirectory().'/'.$filename, 'random content');
}
@@ -73,53 +72,50 @@ public function testWriteTmpFiles(): void
public function testWriteTmpFileFromStream(): void
{
$contextBuilder = new ContextBuilder();
- $stream = \fopen('php://temp', 'r+');
- $this->assertSame(7, \fwrite($stream, 'test123'));
- \rewind($stream);
+ $stream = fopen('php://temp', 'r+');
+ $this->assertSame(7, fwrite($stream, 'test123'));
+ rewind($stream);
$contextBuilder->addStream('/foo', $stream);
$context = $contextBuilder->getContext();
- $filename = \preg_replace(<<getDockerfileContent());
+ $filename = preg_replace(<<getDockerfileContent());
$this->assertStringEqualsFile($context->getDirectory().'/'.$filename, 'test123');
}
public function testWriteTmpFileFromDisk(): void
{
$contextBuilder = new ContextBuilder();
- $file = \tempnam('', '');
- \file_put_contents($file, 'abc');
+ $file = tempnam('', '');
+ file_put_contents($file, 'abc');
$this->assertStringEqualsFile($file, 'abc');
$contextBuilder->addFile('/foo', $file);
$context = $contextBuilder->getContext();
- $filename = \preg_replace(<<getDockerfileContent());
+ $filename = preg_replace(<<getDockerfileContent());
$this->assertStringEqualsFile($context->getDirectory().'/'.$filename, 'abc');
}
public function testWriteTmpDirFromDisk(): void
{
$contextBuilder = new ContextBuilder();
- $dir = \tempnam(\sys_get_temp_dir(), '');
- \unlink($dir);
- \mkdir($dir);
- \file_put_contents($dir.'/test', 'abc');
+ $dir = tempnam(sys_get_temp_dir(), '');
+ unlink($dir);
+ mkdir($dir);
+ file_put_contents($dir.'/test', 'abc');
$this->assertStringEqualsFile($dir.'/test', 'abc');
$contextBuilder->addFile('/foo', $dir);
$context = $contextBuilder->getContext();
- $filename = \preg_replace(<<getDockerfileContent());
+ $filename = preg_replace(<<getDockerfileContent());
$this->assertStringEqualsFile($context->getDirectory().'/'.$filename.'/test', 'abc');
}
@@ -130,11 +126,12 @@ public function testWritesAddCommands(): void
$context = $contextBuilder->getContext();
- $this->assertRegExp(<<getDockerfileContent()
+ $this->assertMatchesRegularExpression(
+ <<getDockerfileContent()
);
}
@@ -145,10 +142,12 @@ public function testWritesRunCommands(): void
$context = $contextBuilder->getContext();
- $this->assertStringEqualsFile($context->getDirectory().'/Dockerfile', <<assertStringEqualsFile(
+ $context->getDirectory().'/Dockerfile',
+ <<getContext();
- $this->assertStringEqualsFile($context->getDirectory().'/Dockerfile', <<assertStringEqualsFile(
+ $context->getDirectory().'/Dockerfile',
+ <<getContext();
- $this->assertStringEqualsFile($context->getDirectory().'/Dockerfile', <<assertStringEqualsFile(
+ $context->getDirectory().'/Dockerfile',
+ <<getContext();
- $this->assertStringEqualsFile($context->getDirectory().'/Dockerfile', <<assertStringEqualsFile(
+ $context->getDirectory().'/Dockerfile',
+ <<getContext();
- $this->assertStringEqualsFile($context->getDirectory().'/Dockerfile', <<assertStringEqualsFile(
+ $context->getDirectory().'/Dockerfile',
+ <<command('changed');
$content = $contextBuilder->getContext()->getDockerfileContent();
- $this->assertNotContains('CMD test123', $content);
+ $this->assertStringNotContainsString('CMD test123', $content);
$this->assertStringEndsWith("\nCMD changed", $content);
}
@@ -256,7 +263,7 @@ public function testWritesEntrypointCommand(): void
$contextBuilder->entrypoint('changed');
$content = $contextBuilder->getContext()->getDockerfileContent();
- $this->assertNotContains('ENTRYPOINT test123', $content);
+ $this->assertStringNotContainsString('ENTRYPOINT test123', $content);
$this->assertStringEndsWith("\nENTRYPOINT changed", $content);
}
@@ -266,33 +273,32 @@ public function testTar(): void
$contextBuilder->setFormat(Context::FORMAT_TAR);
$context = $contextBuilder->getContext();
$content = $context->read();
- $this->assertInternalType('string', $content);
+ $this->assertIsString($content);
$this->assertSame($context->toTar(), $content);
}
public function testTraverseSymlinks(): void
{
$contextBuilder = new ContextBuilder();
- $dir = \tempnam('', '');
- \unlink($dir);
- \mkdir($dir);
+ $dir = tempnam('', '');
+ unlink($dir);
+ mkdir($dir);
$file = $dir.'/test';
- \file_put_contents($file, 'abc');
+ file_put_contents($file, 'abc');
$linkFile = $file.'-symlink';
- \symlink($file, $linkFile);
+ symlink($file, $linkFile);
$contextBuilder->addFile('/foo', $dir);
$context = $contextBuilder->getContext();
- $filename = \preg_replace(<<getDockerfileContent());
- \unlink($file);
+ $filename = preg_replace(<<getDockerfileContent());
+ unlink($file);
$context->setCleanup(false);
$this->assertStringEqualsFile($context->getDirectory().'/'.$filename.'/test-symlink', 'abc');
}
diff --git a/tests/Context/ContextTest.php b/tests/Context/ContextTest.php
index cd2a113f2..1038213b7 100644
--- a/tests/Context/ContextTest.php
+++ b/tests/Context/ContextTest.php
@@ -13,10 +13,10 @@ class ContextTest extends TestCase
{
public function testReturnsValidTarContent(): void
{
- $directory = __DIR__.DIRECTORY_SEPARATOR.'context-test';
+ $directory = __DIR__.\DIRECTORY_SEPARATOR.'context-test';
$context = new Context($directory);
- $process = new Process('/usr/bin/env tar c .', $directory);
+ $process = new Process(['/usr/bin/env', 'tar', 'c', '.'], $directory);
$process->run();
$this->assertSame(\strlen($process->getOutput()), \strlen($context->toTar()));
@@ -24,10 +24,10 @@ public function testReturnsValidTarContent(): void
public function testReturnsValidTarStream(): void
{
- $directory = __DIR__.DIRECTORY_SEPARATOR.'context-test';
+ $directory = __DIR__.\DIRECTORY_SEPARATOR.'context-test';
$context = new Context($directory);
- $this->assertInternalType('resource', $context->toStream());
+ $this->assertIsResource($context->toStream());
}
public function testDirectorySetter(): void
@@ -38,19 +38,18 @@ public function testDirectorySetter(): void
$this->assertSame('def', $context->getDirectory());
}
- /**
- * @expectedException \Symfony\Component\Process\Exception\ProcessFailedException
- */
public function testTarFailed(): void
{
- $directory = __DIR__.DIRECTORY_SEPARATOR.'context-test';
- $path = \getenv('PATH');
- \putenv('PATH=/');
+ $this->expectException(\Symfony\Component\Process\Exception\ProcessFailedException::class);
+
+ $directory = __DIR__.\DIRECTORY_SEPARATOR.'context-test';
+ $path = getenv('PATH');
+ putenv('PATH=/');
$context = new Context($directory);
try {
$context->toTar();
} finally {
- \putenv("PATH=$path");
+ putenv("PATH=$path");
}
}
@@ -62,6 +61,6 @@ public function testRemovesFilesOnDestruct(): void
unset($context);
- $this->assertFileNotExists($file);
+ $this->assertFileDoesNotExist($file);
}
}
diff --git a/tests/DockerAsyncTest.php b/tests/DockerAsyncTest.php
deleted file mode 100644
index 29b2f3bf1..000000000
--- a/tests/DockerAsyncTest.php
+++ /dev/null
@@ -1,86 +0,0 @@
-assertInstanceOf(DockerAsync::class, DockerAsync::create());
- }
-
- public function testAsync(): void
- {
- Loop::run(function () {
- $docker = DockerAsync::create();
-
- $containerConfig = new ContainersCreatePostBody();
- $containerConfig->setImage('busybox:latest');
- $containerConfig->setCmd(['echo', '-n', 'output']);
- $containerConfig->setAttachStdout(true);
- $containerConfig->setLabels(new \ArrayObject(['docker-php-test' => 'true']));
-
- $response = yield $docker->imageCreate('', [
- 'fromImage' => 'busybox:latest',
- ], [], DockerAsync::FETCH_RESPONSE);
-
- yield $response->getBody();
-
- $containerCreate = yield $docker->containerCreate($containerConfig);
- $containerStart = yield $docker->containerStart($containerCreate->getId());
- $containerInfo = yield $docker->containerInspect($containerCreate->getId());
-
- $this->assertSame($containerCreate->getId(), $containerInfo->getId());
- });
- }
-
- public function testSystemEventsAllowTheConsumptionOfDockerEvents(): void
- {
- $matchedEvents = [];
-
- Loop::run(function () use (&$matchedEvents) {
- $docker = DockerAsync::create();
-
- /** @var ArtaxCallbackStream $events */
- $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']);
-
- yield $docker->containerCreate($containerConfig);
-
- Loop::delay(1000, function (): void {
- Loop::stop();
- });
- });
-
- $this->assertCount(1, $matchedEvents);
- }
-}
diff --git a/tests/DockerClientFactoryTest.php b/tests/DockerClientFactoryTest.php
index 286419d43..ed09a955c 100644
--- a/tests/DockerClientFactoryTest.php
+++ b/tests/DockerClientFactoryTest.php
@@ -5,45 +5,44 @@
namespace Docker\Tests;
use Docker\DockerClientFactory;
-use Http\Client\HttpClient;
+use Psr\Http\Client\ClientInterface;
class DockerClientFactoryTest extends TestCase
{
protected function tearDown(): void
{
parent::tearDown();
- \putenv('DOCKER_TLS_VERIFY');
+ putenv('DOCKER_TLS_VERIFY');
}
public function testStaticConstructor(): void
{
- $this->assertInstanceOf(HttpClient::class, DockerClientFactory::create());
+ $this->assertInstanceOf(ClientInterface::class, DockerClientFactory::create());
}
- /**
- * @expectedException \RuntimeException
- * @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
{
- \putenv('DOCKER_TLS_VERIFY=1');
+ $this->expectException(\RuntimeException::class);
+ $this->expectExceptionMessage('Connection to docker has been set to use TLS, but no PATH is defined for certificate in DOCKER_CERT_PATH docker environment variable');
+
+ putenv('DOCKER_TLS_VERIFY=1');
DockerClientFactory::createFromEnv();
}
public function testCreateCustomCa(): void
{
- \putenv('DOCKER_TLS_VERIFY=1');
- \putenv('DOCKER_CERT_PATH=/tmp');
+ putenv('DOCKER_TLS_VERIFY=1');
+ putenv('DOCKER_CERT_PATH=/tmp');
- $count = \count(\get_resources('stream-context'));
+ $count = \count(get_resources('stream-context'));
$client = DockerClientFactory::createFromEnv();
- $this->assertInstanceOf(HttpClient::class, $client);
+ $this->assertInstanceOf(ClientInterface::class, $client);
- $contexts = \get_resources('stream-context');
+ $contexts = get_resources('stream-context');
$this->assertCount($count + 1, $contexts);
// Get the last stream context.
- $context = \stream_context_get_options(\end($contexts));
+ $context = stream_context_get_options(end($contexts));
$this->assertSame('/tmp/ca.pem', $context['ssl']['cafile']);
$this->assertSame('/tmp/cert.pem', $context['ssl']['local_cert']);
$this->assertSame('/tmp/key.pem', $context['ssl']['local_pk']);
@@ -51,19 +50,19 @@ public function testCreateCustomCa(): void
public function testCreateCustomPeerName(): void
{
- \putenv('DOCKER_TLS_VERIFY=1');
- \putenv('DOCKER_CERT_PATH=/abc');
- \putenv('DOCKER_PEER_NAME=test');
+ putenv('DOCKER_TLS_VERIFY=1');
+ putenv('DOCKER_CERT_PATH=/abc');
+ putenv('DOCKER_PEER_NAME=test');
- $count = \count(\get_resources('stream-context'));
+ $count = \count(get_resources('stream-context'));
$client = DockerClientFactory::createFromEnv();
- $this->assertInstanceOf(HttpClient::class, $client);
+ $this->assertInstanceOf(ClientInterface::class, $client);
- $contexts = \get_resources('stream-context');
+ $contexts = get_resources('stream-context');
$this->assertCount($count + 1, $contexts);
// Get the last stream context.
- $context = \stream_context_get_options(\end($contexts));
+ $context = stream_context_get_options(end($contexts));
$this->assertSame('/abc/ca.pem', $context['ssl']['cafile']);
$this->assertSame('/abc/cert.pem', $context['ssl']['local_cert']);
$this->assertSame('/abc/key.pem', $context['ssl']['local_pk']);
diff --git a/tests/Resource/ContainerResourceTest.php b/tests/Resource/ContainerResourceTest.php
index d89f3ada9..eb6024a18 100644
--- a/tests/Resource/ContainerResourceTest.php
+++ b/tests/Resource/ContainerResourceTest.php
@@ -35,13 +35,16 @@ public function testAttach(): void
$containerConfig->setImage('busybox:latest');
$containerConfig->setCmd(['echo', '-n', 'output']);
$containerConfig->setAttachStdout(true);
- $containerConfig->setLabels(new \ArrayObject(['docker-php-test' => 'true']));
+ $containerConfig->setLabels(['docker-php-test' => 'true']);
$containerCreateResult = $this->getManager()->containerCreate($containerConfig);
- $dockerRawStream = $this->getManager()->containerAttach($containerCreateResult->getId(), [
- 'stream' => true,
- 'stdout' => true,
- ]);
+ $dockerRawStream = $this->getManager()->containerAttach(
+ $containerCreateResult->getId(),
+ [
+ 'stream' => true,
+ 'stdout' => true,
+ ]
+ );
$stdoutFull = '';
$dockerRawStream->onStdout(function ($stdout) use (&$stdoutFull): void {
@@ -58,6 +61,8 @@ public function testAttach(): void
public function testAttachWebsocket(): void
{
+ $this->markTestSkipped('Since docker API 1.28 Websockets are binary so this test needs work. ' .
+ 'See https://github.com/xtermjs/xterm.js/issues/883');
$containerConfig = new ContainersCreatePostBody();
$containerConfig->setImage('busybox:latest');
$containerConfig->setCmd(['sh']);
@@ -69,12 +74,15 @@ public function testAttachWebsocket(): void
$containerConfig->setLabels(new \ArrayObject(['docker-php-test' => 'true']));
$containerCreateResult = $this->getManager()->containerCreate($containerConfig);
- $webSocketStream = $this->getManager()->containerAttachWebsocket($containerCreateResult->getId(), [
- 'stream' => true,
- 'stdout' => true,
- 'stderr' => true,
- 'stdin' => true,
- ]);
+ $webSocketStream = $this->getManager()->containerAttachWebsocket(
+ $containerCreateResult->getId(),
+ [
+ 'stream' => true,
+ 'stdout' => true,
+ 'stderr' => true,
+ 'stdin' => true,
+ ]
+ );
$this->getManager()->containerStart($containerCreateResult->getId());
@@ -102,21 +110,28 @@ public function testAttachWebsocket(): void
public function testLogs(): void
{
+ $this->markTestSkipped('Since at least 1.43 docker API does not return a `application/vnd.docker.raw-stream` ' .
+ 'but a `application/vnd.docker.multiplexed-stream` so this needs review. '.
+ 'See https://github.com/beluga-php/docker-php/issues/19');
$containerConfig = new ContainersCreatePostBody();
$containerConfig->setImage('busybox:latest');
$containerConfig->setCmd(['echo', '-n', 'output']);
$containerConfig->setAttachStdout(true);
- $containerConfig->setLabels(new \ArrayObject(['docker-php-test' => 'true']));
+ $containerConfig->setLabels(['docker-php-test' => 'true']);
$containerCreateResult = $this->getManager()->containerCreate($containerConfig);
$this->getManager()->containerStart($containerCreateResult->getId());
$this->getManager()->containerWait($containerCreateResult->getId());
- $logsStream = $this->getManager()->containerLogs($containerCreateResult->getId(), [
- 'stdout' => true,
- 'stderr' => true,
- ], Docker::FETCH_OBJECT);
+ $logsStream = $this->getManager()->containerLogs(
+ $containerCreateResult->getId(),
+ [
+ 'stdout' => true,
+ 'stderr' => true,
+ ],
+ Docker::FETCH_OBJECT
+ );
self::assertInstanceOf(DockerRawStream::class, $logsStream);
}
diff --git a/tests/Resource/ImageResourceTest.php b/tests/Resource/ImageResourceTest.php
index e1c129dd0..8e88982da 100644
--- a/tests/Resource/ImageResourceTest.php
+++ b/tests/Resource/ImageResourceTest.php
@@ -37,7 +37,7 @@ public function testBuild(): void
});
$buildStream->wait();
- $this->assertContains('Successfully', $lastMessage);
+ $this->assertStringContainsString('Successfully', $lastMessage);
}
public function testCreate(): void
@@ -57,7 +57,7 @@ public function testCreate(): void
});
$createImageStream->wait();
- $this->assertContains('Pulling from library/registry', $firstMessage);
+ $this->assertStringContainsString('Pulling from library/registry', $firstMessage);
}
public function testPushStream(): void
@@ -86,6 +86,6 @@ public function testPushStream(): void
});
$pushImageStream->wait();
- $this->assertContains('repository [localhost:5000/test-image]', $firstMessage);
+ $this->assertStringContainsString('repository [localhost:5000/test-image]', $firstMessage);
}
}
diff --git a/tests/Resource/SystemResourceTest.php b/tests/Resource/SystemResourceTest.php
index 474f3506e..fb1badf30 100644
--- a/tests/Resource/SystemResourceTest.php
+++ b/tests/Resource/SystemResourceTest.php
@@ -4,7 +4,7 @@
namespace Docker\Tests\Resource;
-use Docker\API\Model\EventsGetResponse200;
+use Docker\API\Model\EventMessage;
use Docker\Tests\TestCase;
class SystemResourceTest extends TestCase
@@ -20,8 +20,8 @@ private function getManager()
public function testGetEvents(): void
{
$stream = $this->getManager()->systemEvents([
- 'since' => (string) (\time() - 1),
- 'until' => (string) (\time() + 4),
+ 'since' => (string) (time() - 1),
+ 'until' => (string) (time() + 4),
]);
$lastEvent = null;
@@ -36,6 +36,6 @@ public function testGetEvents(): void
$stream->wait();
- $this->assertInstanceOf(EventsGetResponse200::class, $lastEvent);
+ $this->assertInstanceOf(EventMessage::class, $lastEvent);
}
}
diff --git a/tests/Stream/MultiJsonStreamTest.php b/tests/Stream/MultiJsonStreamTest.php
index a999f4929..e3683e5c3 100644
--- a/tests/Stream/MultiJsonStreamTest.php
+++ b/tests/Stream/MultiJsonStreamTest.php
@@ -7,12 +7,12 @@
use Docker\API\Model\BuildInfo;
use Docker\Stream\MultiJsonStream;
use Docker\Tests\TestCase;
-use GuzzleHttp\Psr7\BufferStream;
+use Nyholm\Psr7\Stream;
use Symfony\Component\Serializer\SerializerInterface;
class MultiJsonStreamTest extends TestCase
{
- public function jsonStreamDataProvider()
+ public static function jsonStreamDataProvider()
{
return [
[
@@ -20,7 +20,7 @@ public function jsonStreamDataProvider()
['{}', '{"abc":"def"}'],
],
[
- '{"test": "abc\"\""}',
+ '{"test": "abc\"\""}',
['{"test":"abc\"\""}'],
],
[
@@ -31,25 +31,28 @@ public function jsonStreamDataProvider()
}
/**
- * @param $jsonStream
- * @param $jsonParts
* @dataProvider jsonStreamDataProvider
*/
public function testReadJsonEscapedDoubleQuote(string $jsonStream, array $jsonParts): void
{
- $stream = new BufferStream();
- $stream->write($jsonStream);
+ $stream = Stream::create($jsonStream);
+ $stream->rewind();
$serializer = $this->getMockBuilder(SerializerInterface::class)
->getMock();
+ $callIndex = 0;
$serializer
->expects($this->exactly(\count($jsonParts)))
->method('deserialize')
- ->withConsecutive(...\array_map(function ($part) {
- return [$part, BuildInfo::class, 'json', []];
- }, $jsonParts))
- ;
+ ->willReturnCallback(function ($data, $class, $format, $context) use ($jsonParts, &$callIndex) {
+ $this->assertEquals($jsonParts[$callIndex], $data);
+ $this->assertEquals(BuildInfo::class, $class);
+ $this->assertEquals('json', $format);
+ $this->assertEquals([], $context);
+ $callIndex++;
+ return null;
+ });
$stub = $this->getMockForAbstractClass(MultiJsonStream::class, [$stream, $serializer]);
$stub->expects($this->any())