- Move most of the stuff for backwards compatibility support into one class

- Added random port logic
- Updated wait wtrategies
- API alignments to make it similar to other official implementations
- ...
This commit is contained in:
Sergei Shitikov
2024-09-06 19:08:37 +02:00
parent a956794279
commit f05ea0020d
43 changed files with 1191 additions and 601 deletions
-20
View File
@@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
namespace Testcontainers\Wait;
use Docker\Docker;
use Testcontainers\ContainerRuntime\ContainerRuntimeClient;
abstract class BaseWait implements WaitInterface
{
protected Docker $dockerClient;
public function __construct(protected int $timeout = 10000, protected int $pollInterval = 500)
{
$this->dockerClient = ContainerRuntimeClient::getDockerClient();
}
abstract public function wait(string $id): void;
}
+17
View File
@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace Testcontainers\Wait;
use Testcontainers\Container\StartedTestContainer;
abstract class BaseWaitStrategy implements WaitStrategy
{
public function __construct(protected int $timeout = 10000, protected int $pollInterval = 500)
{
}
abstract public function wait(StartedTestContainer $container): void;
}
@@ -5,16 +5,18 @@ declare(strict_types=1);
namespace Testcontainers\Wait;
use Docker\API\Model\ContainersIdJsonGetResponse200;
use Testcontainers\Container\StartedTestContainer;
use Testcontainers\Exception\ContainerNotReadyException;
/**
* Simply makes container inspect and checks if container is running.
* Uses $timout and $pollInterval in milliseconds to set the parameters for waiting.
*/
class WaitForContainerRunning extends BaseWait
class WaitForContainer extends BaseWaitStrategy
{
public function wait(string $id): void
public function wait(StartedTestContainer $container): void
{
$id = $container->getId();
$startTime = microtime(true) * 1000;
while (true) {
@@ -25,7 +27,7 @@ class WaitForContainerRunning extends BaseWait
}
/** @var ContainersIdJsonGetResponse200 | null $containerInspect */
$containerInspect = $this->dockerClient->containerInspect($id);
$containerInspect = $container->getClient()->containerInspect($id);
$containerStatus = $containerInspect?->getState()?->getStatus();
if ($containerStatus === 'running') {
+9 -17
View File
@@ -5,14 +5,15 @@ declare(strict_types=1);
namespace Testcontainers\Wait;
use Closure;
use Docker\API\Client;
use Docker\API\Model\ContainersIdExecPostBody;
use Docker\API\Model\ExecIdJsonGetResponse200;
use Testcontainers\Container\StartedTestContainer;
use Testcontainers\Exception\ContainerWaitingTimeoutException;
/**
* Uses $timout and $pollInterval in milliseconds to set the parameters for waiting.
*/
class WaitForExec extends BaseWait
class WaitForExec extends BaseWaitStrategy
{
protected ContainersIdExecPostBody $execConfig;
@@ -28,32 +29,23 @@ class WaitForExec extends BaseWait
parent::__construct($timeout, $pollInterval);
}
public function wait(string $id): void
public function wait(StartedTestContainer $container): void
{
$this->execConfig = (new ContainersIdExecPostBody())
->setCmd($this->command)
->setAttachStdout(true)
->setAttachStderr(true);
$startTime = microtime(true) * 1000;
while (true) {
$elapsedTime = (microtime(true) * 1000) - $startTime;
if ($elapsedTime > $this->timeout) {
throw new ContainerWaitingTimeoutException($id);
throw new ContainerWaitingTimeoutException($container->getId());
}
// Create and start the exec command
$exec = $this->dockerClient->containerExec($id, $this->execConfig);
$contents = $this->dockerClient
->execStart($exec->getId(), null, Client::FETCH_RESPONSE)
?->getBody()
->getContents() ?? '';
$contents = $container->exec($this->command);
// Inspect the exec to check the exit code
$execInspect = $this->dockerClient->execInspect($exec->getId());
$exitCode = $execInspect->getExitCode();
/** @var ExecIdJsonGetResponse200 | null $execInspect */
$execInspect = $container->getClient()->execInspect($container->getLastExecId() ?? '');
$exitCode = $execInspect?->getExitCode();
// If a custom check function is provided, use it to validate the command output
if ($this->checkFunction !== null) {
+8 -14
View File
@@ -5,25 +5,18 @@ declare(strict_types=1);
namespace Testcontainers\Wait;
use Docker\Docker;
use Docker\DockerClientFactory;
use Http\Client\Socket\Exception\TimeoutException;
use Testcontainers\ContainerRuntime\ContainerRuntimeClient;
use Testcontainers\Container\StartedTestContainer;
use Testcontainers\Exception\ContainerNotReadyException;
class WaitForHealthCheck implements WaitInterface
class WaitForHealthCheck extends BaseWaitStrategy
{
protected Docker $dockerClient;
protected int $timeout;
protected int $pollInterval;
public function __construct(int $timeout = 5000, int $pollInterval = 1000)
public function __construct(protected int $timeout = 5000, protected int $pollInterval = 1000)
{
$this->dockerClient = ContainerRuntimeClient::getDockerClient();
$this->timeout = $timeout;
$this->pollInterval = $pollInterval;
parent::__construct($timeout, $pollInterval);
}
public function wait(string $id): void
public function wait(StartedTestContainer $container): void
{
$startTime = microtime(true) * 1000;
@@ -34,10 +27,11 @@ class WaitForHealthCheck implements WaitInterface
throw new TimeoutException(sprintf("Health check not healthy after %d ms", $this->timeout));
}
$containerInspect = $this->dockerClient->containerInspect($id, [], Docker::FETCH_RESPONSE);
/** @var \Psr\Http\Message\ResponseInterface | null $containerInspect */
$containerInspect = $container->getClient()->containerInspect($container->getId(), [], Docker::FETCH_RESPONSE);
//$containerStatus = $containerInspect?->getArrayCopy() ?? null;
var_dump($containerInspect->getBody()->getContents());
$containerStatus='';
$containerStatus = '';
if ($containerStatus === 'healthy') {
return;
}
+1 -1
View File
@@ -7,7 +7,7 @@ namespace Testcontainers\Wait;
use Docker\Docker;
use Testcontainers\Exception\ContainerNotReadyException;
class WaitForHttp implements WaitInterface
class WaitForHttp implements WaitStrategy
{
public const METHOD_GET = 'GET';
public const METHOD_POST = 'POST';
+5 -10
View File
@@ -4,13 +4,13 @@ declare(strict_types=1);
namespace Testcontainers\Wait;
use Docker\API\Runtime\Client\Client;
use Testcontainers\Container\StartedTestContainer;
use Testcontainers\Exception\ContainerWaitingTimeoutException;
/**
* Uses $timout and $pollInterval in milliseconds to set the parameters for waiting.
*/
class WaitForLog extends BaseWait
class WaitForLog extends BaseWaitStrategy
{
public function __construct(
protected string $message,
@@ -21,7 +21,7 @@ class WaitForLog extends BaseWait
parent::__construct($timeout, $pollInterval);
}
public function wait(string $id): void
public function wait(StartedTestContainer $container): void
{
$startTime = microtime(true) * 1000;
@@ -29,15 +29,10 @@ class WaitForLog extends BaseWait
$elapsedTime = (microtime(true) * 1000) - $startTime;
if ($elapsedTime > $this->timeout) {
throw new ContainerWaitingTimeoutException($id);
throw new ContainerWaitingTimeoutException($container->getId());
}
$output = $this->dockerClient
->containerLogs($id, ['stdout' => true, 'stderr' => true], Client::FETCH_RESPONSE)
?->getBody()
->getContents() ?? '';
$output = preg_replace('/[\x00-\x1F\x7F]/u', '', mb_convert_encoding($output, 'UTF-8', 'UTF-8')) ?? '';
$output = $container->logs();
if ($this->enableRegex) {
if (preg_match($this->message, $output)) {
+1 -1
View File
@@ -9,7 +9,7 @@ use JsonException;
use RuntimeException;
use Testcontainers\Exception\ContainerNotReadyException;
final class WaitForTcpPortOpen implements WaitInterface
final class WaitForTcpPortOpen implements WaitStrategy
{
private Docker $dockerClient;
-10
View File
@@ -1,10 +0,0 @@
<?php
declare(strict_types=1);
namespace Testcontainers\Wait;
interface WaitInterface
{
public function wait(string $id): void;
}
+12
View File
@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Testcontainers\Wait;
use Testcontainers\Container\StartedTestContainer;
interface WaitStrategy
{
public function wait(StartedTestContainer $container): void;
}