mirror of
https://github.com/stan220/testcontainers-php.git
synced 2026-09-08 20:29:35 +00:00
Implement WaitForExec using new Client library. Add BaseWait to avoid some code duplication. Adjust Postgres test
This commit is contained in:
@@ -8,11 +8,18 @@ use Testcontainers\Wait\WaitForExec;
|
||||
|
||||
class PostgresContainer extends GenericContainer
|
||||
{
|
||||
public function __construct(string $version = 'latest', string $rootPassword = 'root')
|
||||
{
|
||||
public function __construct(
|
||||
string $version = 'latest',
|
||||
public readonly string $username = 'test',
|
||||
public readonly string $password = 'test',
|
||||
public readonly string $database = 'test'
|
||||
) {
|
||||
parent::__construct('postgres:' . $version);
|
||||
$this->withEnvironment('POSTGRES_PASSWORD', $rootPassword);
|
||||
$this->withWait(new WaitForExec(["pg_isready", "-h", "127.0.0.1"]));
|
||||
$this->withExposedPorts(5432);
|
||||
$this->withEnvironment('POSTGRES_USER', $this->username);
|
||||
$this->withEnvironment('POSTGRES_PASSWORD', $this->password);
|
||||
$this->withEnvironment('POSTGRES_DB', $this->database);
|
||||
$this->withWait(new WaitForExec(["pg_isready", "-h", "127.0.0.1", "-U", $this->username]));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,7 +28,10 @@ class PostgresContainer extends GenericContainer
|
||||
*/
|
||||
public static function make(string $version = 'latest', string $dbPassword = 'root'): self
|
||||
{
|
||||
return new self($version, $dbPassword);
|
||||
return new self(
|
||||
version: $version,
|
||||
password: $dbPassword
|
||||
);
|
||||
}
|
||||
|
||||
public function withPostgresUser(string $username): self
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
}
|
||||
@@ -5,23 +5,14 @@ declare(strict_types=1);
|
||||
namespace Testcontainers\Wait;
|
||||
|
||||
use Docker\API\Model\ContainersIdJsonGetResponse200;
|
||||
use Docker\Docker;
|
||||
use Testcontainers\ContainerRuntime\ContainerRuntimeClient;
|
||||
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 implements WaitInterface
|
||||
class WaitForContainerRunning extends BaseWait
|
||||
{
|
||||
protected Docker $dockerClient;
|
||||
|
||||
public function __construct(protected int $timeout = 10000, protected int $pollInterval = 500)
|
||||
{
|
||||
$this->dockerClient = ContainerRuntimeClient::getDockerClient();
|
||||
}
|
||||
|
||||
public function wait(string $id): void
|
||||
{
|
||||
$startTime = microtime(true) * 1000;
|
||||
@@ -41,8 +32,6 @@ class WaitForContainerRunning implements WaitInterface
|
||||
return;
|
||||
}
|
||||
|
||||
var_dump($containerStatus);
|
||||
|
||||
usleep($this->pollInterval * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
+50
-17
@@ -5,34 +5,67 @@ declare(strict_types=1);
|
||||
namespace Testcontainers\Wait;
|
||||
|
||||
use Closure;
|
||||
use Docker\API\Client;
|
||||
use Docker\API\Model\ContainersIdExecPostBody;
|
||||
use Docker\API\Model\ExecIdStartPostBody;
|
||||
use Docker\Docker;
|
||||
use Testcontainers\Exception\ContainerWaitingTimeoutException;
|
||||
|
||||
class WaitForExec implements WaitInterface
|
||||
/**
|
||||
* Uses $timout and $pollInterval in milliseconds to set the parameters for waiting.
|
||||
*/
|
||||
class WaitForExec extends BaseWait
|
||||
{
|
||||
protected Docker $dockerClient;
|
||||
|
||||
protected ContainersIdExecPostBody $execConfig;
|
||||
|
||||
/**
|
||||
* @param array<string> $command
|
||||
*/
|
||||
public function __construct(private array $command, private ?Closure $checkFunction = null)
|
||||
{
|
||||
$this->dockerClient = Docker::create();
|
||||
$execConfig = new ContainersIdExecPostBody();
|
||||
$execConfig->setTty(true);
|
||||
$execConfig->setAttachStdout(true);
|
||||
$execConfig->setAttachStderr(true);
|
||||
$execConfig->setCmd($this->command);
|
||||
public function __construct(
|
||||
protected array $command,
|
||||
protected ?Closure $checkFunction = null,
|
||||
int $timeout = 10000,
|
||||
int $pollInterval = 500
|
||||
) {
|
||||
parent::__construct($timeout, $pollInterval);
|
||||
}
|
||||
|
||||
public function wait(string $id): void
|
||||
{
|
||||
$execid = $this->dockerClient->containerExec($id, $this->execConfig)->getId() ?? '';
|
||||
$execStartConfig = new ExecIdStartPostBody();
|
||||
$execStartConfig->setDetach(false);
|
||||
$this->dockerClient->execStart($execid, $execStartConfig);
|
||||
$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);
|
||||
}
|
||||
|
||||
// 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() ?? '';
|
||||
|
||||
// Inspect the exec to check the exit code
|
||||
$execInspect = $this->dockerClient->execInspect($exec->getId());
|
||||
$exitCode = $execInspect->getExitCode();
|
||||
|
||||
// If a custom check function is provided, use it to validate the command output
|
||||
if ($this->checkFunction !== null) {
|
||||
$checkResult = ($this->checkFunction)($exitCode, $contents);
|
||||
if ($checkResult) {
|
||||
return;
|
||||
}
|
||||
} elseif ($exitCode === 0) {
|
||||
return; // Command succeeded
|
||||
}
|
||||
|
||||
usleep($this->pollInterval * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,23 +5,20 @@ declare(strict_types=1);
|
||||
namespace Testcontainers\Wait;
|
||||
|
||||
use Docker\API\Runtime\Client\Client;
|
||||
use Docker\Docker;
|
||||
use Testcontainers\Exception\ContainerWaitingTimeoutException;
|
||||
|
||||
/**
|
||||
* Uses $timout and $pollInterval in milliseconds to set the parameters for waiting.
|
||||
*/
|
||||
class WaitForLog implements WaitInterface
|
||||
class WaitForLog extends BaseWait
|
||||
{
|
||||
protected Docker $dockerClient;
|
||||
|
||||
public function __construct(
|
||||
protected string $message,
|
||||
protected bool $enableRegex = false,
|
||||
protected int $timeout = 10000,
|
||||
protected int $pollInterval = 500
|
||||
int $timeout = 10000,
|
||||
int $pollInterval = 500
|
||||
) {
|
||||
$this->dockerClient = Docker::create();
|
||||
parent::__construct($timeout, $pollInterval);
|
||||
}
|
||||
|
||||
public function wait(string $id): void
|
||||
|
||||
@@ -10,8 +10,8 @@ class PostgreSQLContainerTest extends ContainerTestCase
|
||||
{
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
self::$container = (new PostgresContainer('latest', 'test'))
|
||||
->withPostgresUser('test')
|
||||
self::$container = (new PostgresContainer())
|
||||
->withPostgresUser('bar')
|
||||
->withPostgresDatabase('foo')
|
||||
->start();
|
||||
}
|
||||
@@ -19,8 +19,8 @@ class PostgreSQLContainerTest extends ContainerTestCase
|
||||
public function testPostgreSQLContainer(): void
|
||||
{
|
||||
$pdo = new \PDO(
|
||||
sprintf('pgsql:host=%s;port=5432;dbname=foo', self::$container->getAddress()),
|
||||
'test',
|
||||
'pgsql:host=127.0.0.1;port=5432;dbname=foo',
|
||||
'bar',
|
||||
'test',
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user