Skip to content

Commit

Permalink
Reuse logic for determining container address
Browse files Browse the repository at this point in the history
  • Loading branch information
dinamic committed Jul 16, 2024
1 parent 0edcaee commit 1b2ac03
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 53 deletions.
24 changes: 8 additions & 16 deletions src/Container/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
use Symfony\Component\Process\Process;
use Testcontainer\Exception\ContainerNotReadyException;
use Testcontainer\Registry;
use Testcontainer\Trait\DockerContainerAwareTrait;
use Testcontainer\Wait\WaitForNothing;
use Testcontainer\Wait\WaitInterface;
use UnexpectedValueException;

/**
* @phpstan-type ContainerInspectSingleNetwork array<int, array{'NetworkSettings': array{'IPAddress': string}}>
Expand All @@ -18,6 +18,8 @@
*/
class Container
{
use DockerContainerAwareTrait;

private string $id;

private ?string $entryPoint = null;
Expand Down Expand Up @@ -259,20 +261,10 @@ public function logs(): string

public function getAddress(): string
{
if (is_string($this->network)) {
$containerAddress = $this->inspectedData[0]['NetworkSettings']['Networks'][$this->network]['IPAddress'] ?? null;

if (is_string($containerAddress)) {
return $containerAddress;
}
}

$containerAddress = $this->inspectedData[0]['NetworkSettings']['IPAddress'] ?? null;

if (is_string($containerAddress)) {
return $containerAddress;
}

throw new UnexpectedValueException('Unable to find container IP address');
return $this->getContainerAddress(
containerId: $this->id,
networkName: $this->network,
inspectedData: $this->inspectedData
);
}
}
49 changes: 49 additions & 0 deletions src/Trait/DockerContainerAwareTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);

namespace Testcontainer\Trait;

use JsonException;
use Symfony\Component\Process\Process;
use UnexpectedValueException;

/**
* @phpstan-import-type ContainerInspect from \Testcontainer\Container\Container
*/
trait DockerContainerAwareTrait
{
/**
* @param string $containerId
* @param string|null $networkName
* @param ContainerInspect|null $inspectedData
* @return string
*
* @throws JsonException
*/
protected function getContainerAddress(string $containerId, ?string $networkName = null, ?array $inspectedData = null): string
{
if (! is_array($inspectedData)) {
$process = new Process(['docker', 'inspect', $containerId]);
$process->mustRun();

/** @var ContainerInspect $inspectedData */
$inspectedData = json_decode($process->getOutput(), true, 512, JSON_THROW_ON_ERROR);
}

if (is_string($networkName)) {
$containerAddress = $inspectedData[0]['NetworkSettings']['Networks'][$networkName]['IPAddress'] ?? null;

if (is_string($containerAddress)) {
return $containerAddress;
}
}

$containerAddress = $inspectedData[0]['NetworkSettings']['IPAddress'] ?? null;

if (is_string($containerAddress)) {
return $containerAddress;
}

throw new UnexpectedValueException('Unable to find container IP address');
}
}
17 changes: 5 additions & 12 deletions src/Wait/WaitForHttp.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@

namespace Testcontainer\Wait;

use Symfony\Component\Process\Process;
use Testcontainer\Exception\ContainerNotReadyException;
use Testcontainer\Trait\DockerContainerAwareTrait;

/**
* @phpstan-import-type ContainerInspect from \Testcontainer\Container\Container
*/
class WaitForHttp implements WaitInterface
{
use DockerContainerAwareTrait;

public const METHOD_GET = 'GET';
public const METHOD_POST = 'POST';
public const METHOD_PUT = 'PUT';
Expand Down Expand Up @@ -59,16 +58,10 @@ public function withStatusCode(int $statusCode): self

public function wait(string $id): void
{
$process = new Process(['docker', 'inspect', $id]);
$process->mustRun();

/** @var ContainerInspect $data */
$data = json_decode($process->getOutput(), true);

$ip = $data[0]['NetworkSettings']['IPAddress'];
$containerAddress = $this->getContainerAddress(containerId: $id);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, sprintf('http://%s:%d%s', $ip, $this->port, $this->path));
curl_setopt($ch, CURLOPT_URL, sprintf('http://%s:%d%s', $containerAddress, $this->port, $this->path));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
curl_setopt($ch, CURLOPT_HEADER, true);
Expand Down
29 changes: 4 additions & 25 deletions src/Wait/WaitForTcpPortOpen.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@

use JsonException;
use RuntimeException;
use Symfony\Component\Process\Process;
use Testcontainer\Exception\ContainerNotReadyException;
use Testcontainer\Trait\DockerContainerAwareTrait;

/**
* @phpstan-import-type ContainerInspect from \Testcontainer\Container\Container
*/
final class WaitForTcpPortOpen implements WaitInterface
{
use DockerContainerAwareTrait;

public function __construct(private readonly int $port)
{
}
Expand All @@ -28,28 +27,8 @@ public static function make(int $port): self
*/
public function wait(string $id): void
{
if (@fsockopen($this->findContainerAddress($id), $this->port) === false) {
if (@fsockopen($this->getContainerAddress($id), $this->port) === false) {
throw new ContainerNotReadyException($id, new RuntimeException('Unable to connect to container TCP port'));
}
}

/**
* @throws JsonException
*/
private function findContainerAddress(string $id): string
{
$process = new Process(['docker', 'inspect', $id]);
$process->mustRun();

/** @var ContainerInspect $data */
$data = json_decode($process->getOutput(), true, 512, JSON_THROW_ON_ERROR);

$containerAddress = $data[0]['NetworkSettings']['IPAddress'] ?? null;

if (! is_string($containerAddress)) {
throw new ContainerNotReadyException($id, new RuntimeException('Unable to find container IP address'));
}

return $containerAddress;
}
}

0 comments on commit 1b2ac03

Please sign in to comment.