Skip to content

Commit f55b399

Browse files
committed
Merge remote-tracking branch 'contributor/0.2' into feat/started-generic-container
2 parents 9d83a05 + a1d29e4 commit f55b399

File tree

2 files changed

+67
-41
lines changed

2 files changed

+67
-41
lines changed

src/Container/StartedGenericContainer.php

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
use Docker\API\Runtime\Client\Client as DockerRuntimeClient;
1111
use Docker\Docker;
1212
use Psr\Http\Message\ResponseInterface;
13+
use RuntimeException;
1314
use Testcontainers\ContainerClient\DockerContainerClient;
15+
use Throwable;
1416

1517
class StartedGenericContainer implements StartedTestContainer
1618
{
@@ -53,7 +55,7 @@ public function exec(array $command): string
5355
$exec = $this->dockerClient->containerExec($this->id, $execConfig);
5456

5557
if ($exec === null || $exec->getId() === null) {
56-
throw new \RuntimeException('Failed to create exec command');
58+
throw new RuntimeException('Failed to create exec command');
5759
}
5860

5961
$this->lastExecId = $exec->getId();
@@ -95,78 +97,100 @@ public function logs(): string
9597
return preg_replace('/[\x00-\x1F\x7F]/u', '', mb_convert_encoding($output, 'UTF-8', 'UTF-8')) ?? '';
9698
}
9799

98-
//TODO: replace with the proper implementation
99100
public function getHost(): string
100101
{
101-
return '127.0.0.1';
102+
return $this->inspect()['NetworkSettings']['Gateway'] ?? '127.0.0.1';
102103
}
103104

104-
//TODO: not ready yet
105105
public function getMappedPort(int $port): int
106106
{
107-
return $this->inspect()->ports[$port];
107+
$ports = $this->ports();
108+
if (isset($ports["{$port}/tcp"][0]['HostPort'])) {
109+
return (int) $ports["{$port}/tcp"][0]['HostPort'];
110+
}
111+
112+
throw new RuntimeException("Failed to get mapped port $port for container");
108113
}
109114

110-
/**
111-
* @throws \JsonException
112-
*/
113115
public function getFirstMappedPort(): int
114116
{
115-
//For some reason, containerInspect can crash when using FETCH_OBJECT option (e.g. with OpenSearch)
116-
//should be checked within beluga-php/docker-php client library
117-
/** @var ResponseInterface | null $containerInspectResponse */
118-
$containerInspectResponse = $this->dockerClient->containerInspect($this->id, [], Docker::FETCH_RESPONSE);
119-
if ($containerInspectResponse === null) {
120-
throw new \RuntimeException('Failed to inspect container');
121-
}
122-
123-
$containerInspectResponseAsArray = json_decode(
124-
$containerInspectResponse->getBody()->getContents(),
125-
true,
126-
512,
127-
JSON_THROW_ON_ERROR
128-
);
129-
130-
/** @var array<string, array<array<string, string>>> $ports */
131-
$ports = $containerInspectResponseAsArray['NetworkSettings']['Ports'] ?? [];
132-
133-
if ($ports === []) {
134-
throw new \RuntimeException('Failed to get ports from container');
135-
}
136-
117+
$ports = $this->ports();
137118
$port = array_key_first($ports);
138119

139120
return (int) $ports[$port][0]['HostPort'];
140121
}
141122

142123
public function getName(): string
143124
{
144-
// TODO: Implement getName() method.
145-
return '';
125+
return trim($this->inspect()['Name'], '/ ');
146126
}
147127

128+
/**
129+
* @return string[]
130+
*/
148131
public function getLabels(): array
149132
{
150-
// TODO: Implement getLabels() method.
151-
return [];
133+
return $this->inspect()['Config']['Labels'] ?? [];
152134
}
153135

154-
136+
/**
137+
* @return string[]
138+
*/
155139
public function getNetworkNames(): array
156140
{
157-
// TODO: Implement getNetworkNames() method.
158-
return [];
141+
$networks = $this->inspect()['NetworkSettings']['Networks'] ?? [];
142+
return array_keys($networks);
159143
}
160144

161145
public function getNetworkId(string $networkName): string
162146
{
163-
// TODO: Implement getNetworkId() method.
164-
return '';
147+
$networks = $this->inspect()['NetworkSettings']['Networks'];
148+
if (isset($networks[$networkName])) {
149+
return $networks[$networkName]['NetworkID'];
150+
}
151+
throw new RuntimeException("Network with name {$networkName} not exists");
165152
}
166153

167154
public function getIpAddress(string $networkName): string
168155
{
169-
// TODO: Implement getIpAddress() method.
170-
return '';
156+
$networks = $this->inspect()['NetworkSettings']['Networks'];
157+
if (isset($networks[$networkName])) {
158+
return $networks[$networkName]['IPAddress'];
159+
}
160+
throw new RuntimeException("Network with name {$networkName} not exists");
161+
}
162+
163+
private function inspect(): array
164+
{
165+
//For some reason, containerInspect can crash when using FETCH_OBJECT option (e.g. with OpenSearch)
166+
//should be checked within beluga-php/docker-php client library
167+
/** @var ResponseInterface | null $containerInspectResponse */
168+
$containerInspectResponse = $this->dockerClient->containerInspect($this->id, [], Docker::FETCH_RESPONSE);
169+
if ($containerInspectResponse === null) {
170+
throw new RuntimeException('Failed to inspect container');
171+
}
172+
173+
try {
174+
return json_decode(
175+
$containerInspectResponse->getBody()->getContents(),
176+
true,
177+
512,
178+
JSON_THROW_ON_ERROR
179+
);
180+
} catch (Throwable $exception) {
181+
throw new RuntimeException('Failed to inspect container', 0, $exception);
182+
}
183+
}
184+
185+
private function ports(): array
186+
{
187+
/** @var array<string, array<array<string, string>>> $ports */
188+
$ports = $this->inspect()['NetworkSettings']['Ports'] ?? [];
189+
190+
if ($ports === []) {
191+
throw new RuntimeException('Failed to get ports from container');
192+
}
193+
194+
return $ports;
171195
}
172196
}

src/Modules/MySQLContainer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public function __construct(string $version = 'latest', string $mysqlRootPasswor
1717
$this->withWait(new WaitForExec([
1818
"mysqladmin",
1919
"ping",
20+
"-u", "root",
21+
"-p{$mysqlRootPassword}",
2022
"-h", "127.0.0.1",
2123
]));
2224
}

0 commit comments

Comments
 (0)