diff --git a/src/Container/GenericContainer.php b/src/Container/GenericContainer.php index 0a3e42f..04e26b2 100644 --- a/src/Container/GenericContainer.php +++ b/src/Container/GenericContainer.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Testcontainers\Container; +use Docker\API\Client; use Docker\API\Exception\ContainerCreateNotFoundException; use Docker\API\Model\ContainersCreatePostBody; use Docker\API\Model\ContainersIdExecPostBody; @@ -35,6 +36,9 @@ class GenericContainer protected string $id; + /** @var array */ + protected array $command = []; + protected ?string $entryPoint = null; protected ?HealthConfig $healthConfig = null; @@ -77,6 +81,29 @@ class GenericContainer return $this->id; } + public function withCommand(array $command): self + { + $this->command = $command; + return $this; + } + + public function exec(array $command): string + { + $execConfig = (new ContainersIdExecPostBody()) + ->setCmd($command) + ->setAttachStdout(true) + ->setAttachStderr(true); + + // Create and start the exec command + $exec = $this->dockerClient->containerExec($this->id, $execConfig); + $contents = $this->dockerClient + ->execStart($exec->getId(), null, Client::FETCH_RESPONSE) + ?->getBody() + ->getContents() ?? ''; + + return preg_replace('/[\x00-\x1F\x7F]/u', '', $contents); + } + public function withEntryPoint(string $entryPoint): self { $this->entryPoint = $entryPoint; @@ -194,12 +221,6 @@ class GenericContainer return $this; } - public function wait(): self - { - $this->wait->wait($this->id); - return $this; - } - public function stop(): self { $this->dockerClient->containerStop($this->id); @@ -211,19 +232,23 @@ class GenericContainer { try { $containerCreatePostBody = new ContainersCreatePostBody(); - $portMap = new \ArrayObject(); + //setup only if we need to expose ports + if(!empty($this->exposedPorts)) { + $portMap = new \ArrayObject(); - foreach ($this->exposedPorts as $port) { - $portBinding = new PortBinding(); - $portBinding->setHostPort(explode('/', $port)[0]); - $portBinding->setHostIp('0.0.0.0'); - $portMap[$port] = [$portBinding]; + foreach ($this->exposedPorts as $port) { + $portBinding = new PortBinding(); + $portBinding->setHostPort(explode('/', $port)[0]); + $portBinding->setHostIp('0.0.0.0'); + $portMap[$port] = [$portBinding]; + } + + $hostConfig = new HostConfig(); + $hostConfig->setPortBindings($portMap); + $containerCreatePostBody->setHostConfig($hostConfig); } - - $hostConfig = new HostConfig(); - $hostConfig->setPortBindings($portMap); - $containerCreatePostBody->setHostConfig($hostConfig); $containerCreatePostBody->setImage($this->image); + $containerCreatePostBody->setCmd($this->command); $envs = []; foreach ($this->env as $key => $value) { $envs[] = $key . '=' . $value; @@ -245,7 +270,9 @@ class GenericContainer if(!isset($this->wait)) { $this->withWait(new WaitForContainerRunning()); } - $this->wait(); + + $this->wait->wait($this->id); + return $this; } diff --git a/tests/Integration/GenericContainerTest.php b/tests/Integration/GenericContainerTest.php new file mode 100644 index 0000000..4fc644f --- /dev/null +++ b/tests/Integration/GenericContainerTest.php @@ -0,0 +1,23 @@ +withCommand(['tail', '-f', '/dev/null']) + ->start(); + } + + public function testExec(): void + { + $actual = self::$container->exec(['echo', 'testcontainers']); + self::assertSame('testcontainers', $actual); + } +}