Skip to content

Commit

Permalink
Allow to expose ports
Browse files Browse the repository at this point in the history
  • Loading branch information
AydinHassan committed Sep 4, 2024
1 parent 6f461ac commit d97450f
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 25 deletions.
20 changes: 20 additions & 0 deletions src/Exercise/Scenario/ExerciseScenario.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ abstract class ExerciseScenario
*/
private array $files = [];

/**
* @var list<int>
*/
private array $exposedPorts = [];

public function withFile(string $relativeFileName, string $content): static
{
$this->files[$relativeFileName] = $content;
Expand All @@ -23,4 +28,19 @@ public function getFiles(): array
{
return $this->files;
}

public function exposePort(int $port): static
{
$this->exposedPorts = [$port];

return $this;
}

/**
* @return list<int>
*/
public function getExposedPorts(): array
{
return $this->exposedPorts;
}
}
10 changes: 5 additions & 5 deletions src/ExerciseRunner/CgiRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ private function executePhpFile(
RequestInterface $request,
string $type,
): ResponseInterface {
$process = $this->getPhpProcess($workingDirectory, $fileName, $request);
$process = $this->getPhpProcess($workingDirectory, $fileName, $request, $scenario->getExposedPorts());

$process->start();
$this->eventDispatcher->dispatch(
Expand All @@ -238,11 +238,9 @@ private function executePhpFile(
}

/**
* @param string $fileName
* @param RequestInterface $request
* @return Process
* @param list<int> $exposedPorts
*/
private function getPhpProcess(string $workingDirectory, string $fileName, RequestInterface $request): Process
private function getPhpProcess(string $workingDirectory, string $fileName, RequestInterface $request, array $exposedPorts): Process
{
$env = [
'REQUEST_METHOD' => $request->getMethod(),
Expand Down Expand Up @@ -270,6 +268,7 @@ private function getPhpProcess(string $workingDirectory, string $fileName, Reque
],
$workingDirectory,
$env,
$exposedPorts,
$content,
);

Expand Down Expand Up @@ -311,6 +310,7 @@ public function run(ExecutionContext $context, OutputInterface $output): bool
$context->getStudentExecutionDirectory(),
$context->getEntryPoint(),
$event->getRequest(),
$scenario->getExposedPorts(),
);

$process->start();
Expand Down
9 changes: 6 additions & 3 deletions src/ExerciseRunner/CliRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ public function run(ExecutionContext $context, OutputInterface $output): bool
$context->getStudentExecutionDirectory(),
$context->getEntryPoint(),
$args,
$scenario->getExposedPorts(),
);

$process->start();
Expand All @@ -231,6 +232,7 @@ public function run(ExecutionContext $context, OutputInterface $output): bool
$process->wait(function ($outputType, $outputBuffer) use ($output) {
$output->write($outputBuffer);
});

$output->emptyLine();

if (!$process->isSuccessful()) {
Expand All @@ -254,7 +256,7 @@ public function run(ExecutionContext $context, OutputInterface $output): bool
*/
private function executePhpFile(ExecutionContext $context, CliScenario $scenario, string $workingDirectory, string $fileName, Collection $args, string $type): string
{
$process = $this->getPhpProcess($workingDirectory, $fileName, $args);
$process = $this->getPhpProcess($workingDirectory, $fileName, $args, $scenario->getExposedPorts());

$process->start();
$this->eventDispatcher->dispatch(
Expand All @@ -271,11 +273,12 @@ private function executePhpFile(ExecutionContext $context, CliScenario $scenario

/**
* @param Collection<int, string> $args
* @param list<int> $exposedPorts
*/
private function getPhpProcess(string $workingDirectory, string $fileName, Collection $args): Process
private function getPhpProcess(string $workingDirectory, string $fileName, Collection $args, array $exposedPorts): Process
{
return $this->processFactory->create(
new ProcessInput('php', [$fileName, ...$args->getArrayCopy()], $workingDirectory, []),
new ProcessInput('php', [$fileName, ...$args->getArrayCopy()], $workingDirectory, [], $exposedPorts),
);
}
}
2 changes: 1 addition & 1 deletion src/Listener/PrepareSolutionListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function __invoke(ExerciseRunnerEvent $event): void
//only install if vendor folder not available
if (!file_exists(sprintf('%s/vendor', $event->getContext()->getReferenceExecutionDirectory()))) {
$process = $this->processFactory->create(
new ProcessInput('composer', ['install', '--no-interaction'], $event->getContext()->getReferenceExecutionDirectory(), []),
new ProcessInput('composer', ['install', '--no-interaction'], $event->getContext()->getReferenceExecutionDirectory(), [], []),
);

try {
Expand Down
16 changes: 13 additions & 3 deletions src/Process/DockerProcessFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,18 @@ public function create(ProcessInput $processInput): Process
$env[] = $key . '=' . $value;
}

$ports = [];
foreach ($processInput->getExposedPorts() as $port) {
$ports[] = '-p';
$ports[] = $port . ':' . $port;
}

$env[] = '-e';
$env[] = 'COMPOSER_HOME=/tmp/composer';

return new Process(
$p = new Process(
[
...$this->baseComposeCommand($mounts, $env),
...$this->baseComposeCommand($mounts, $env, $ports),
'runtime',
$processInput->getExecutable(),
...$processInput->getArgs(),
Expand All @@ -59,14 +65,17 @@ public function create(ProcessInput $processInput): Process
$processInput->getInput(),
30,
);

return $p;
}

/**
* @param array<string> $mounts
* @param array<string> $env
* @param list<string> $ports
* @return array<string>
*/
private function baseComposeCommand(array $mounts, array $env): array
private function baseComposeCommand(array $mounts, array $env, array $ports): array
{
$dockerPath = $this->executableFinder->find('docker');
if ($dockerPath === null) {
Expand All @@ -85,6 +94,7 @@ private function baseComposeCommand(array $mounts, array $env): array
getmyuid() . ':' . getmygid(),
'--rm',
...$env,
...$ports,
'-w',
'/solution',
...array_merge(...array_map(fn($mount) => ['-v', $mount], $mounts)),
Expand Down
10 changes: 10 additions & 0 deletions src/Process/ProcessInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ class ProcessInput
/**
* @param list<string> $args
* @param array<string, string> $env
* @param list<int> $exposedPorts
*/
public function __construct(
private string $executable,
private array $args,
private string $workingDirectory,
private array $env,
private array $exposedPorts,
private ?string $input = null,
) {}

Expand Down Expand Up @@ -42,6 +44,14 @@ public function getEnv(): array
return $this->env;
}

/**
* @return list<int>
*/
public function getExposedPorts(): array
{
return $this->exposedPorts;
}

public function getInput(): ?string
{
return $this->input;
Expand Down
14 changes: 7 additions & 7 deletions test/Process/DockerProcessFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function testCreateThrowsExceptionIfDockerNotFound(): void
->willReturn(null);

$factory = new DockerProcessFactory('/docker-dir', 'php8appreciate', '/composer/cache/dir', $finder);
$input = new ProcessInput('composer', [], __DIR__, []);
$input = new ProcessInput('composer', [], __DIR__, [], []);

$factory->create($input);
}
Expand All @@ -35,7 +35,7 @@ public function testCreate(): void
->willReturn('/usr/local/bin/docker');

$factory = new DockerProcessFactory('/docker-dir', 'php8appreciate', '/composer/cache/dir', $finder);
$input = new ProcessInput('php', [], __DIR__, []);
$input = new ProcessInput('php', [], __DIR__, [], []);

$process = $factory->create($input);
$cmd = "'/usr/local/bin/docker' 'compose' '-p' 'php8appreciate' '-f' '.docker/runtime/docker-compose.yml'";
Expand All @@ -53,7 +53,7 @@ public function testCreateMountsComposerCacheDirIfExecutableIsComposer(): void
->willReturn('/usr/local/bin/docker');

$factory = new DockerProcessFactory('/docker-dir', 'php8appreciate', '/composer/cache/dir', $finder);
$input = new ProcessInput('composer', [], __DIR__, []);
$input = new ProcessInput('composer', [], __DIR__, [], []);

$process = $factory->create($input);
$cmd = "'/usr/local/bin/docker' 'compose' '-p' 'php8appreciate' '-f' '.docker/runtime/docker-compose.yml'";
Expand All @@ -71,7 +71,7 @@ public function testCreateWithArgs(): void
->willReturn('/usr/local/bin/docker');

$factory = new DockerProcessFactory('/docker-dir', 'php8appreciate', '/composer/cache/dir', $finder);
$input = new ProcessInput('php', ['one', 'two'], __DIR__, []);
$input = new ProcessInput('php', ['one', 'two'], __DIR__, [], []);

$process = $factory->create($input);
$cmd = "'/usr/local/bin/docker' 'compose' '-p' 'php8appreciate' '-f' '.docker/runtime/docker-compose.yml'";
Expand All @@ -89,7 +89,7 @@ public function testCreateWithEnv(): void
->willReturn('/usr/local/bin/docker');

$factory = new DockerProcessFactory('/docker-dir', 'php8appreciate', '/composer/cache/dir', $finder);
$input = new ProcessInput('php', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value']);
$input = new ProcessInput('php', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value'], []);

$process = $factory->create($input);
$cmd = "'/usr/local/bin/docker' 'compose' '-p' 'php8appreciate' '-f' '.docker/runtime/docker-compose.yml'";
Expand All @@ -107,7 +107,7 @@ public function testWithInput(): void
->willReturn('/usr/local/bin/docker');

$factory = new DockerProcessFactory('/composer-dir', 'php8appreciate', '/composer/cache/dir', $finder);
$input = new ProcessInput('php', [], __DIR__, [], 'someinput');
$input = new ProcessInput('php', [], __DIR__, [], [], 'someinput');

$process = $factory->create($input);
$cmd = "'/usr/local/bin/docker' 'compose' '-p' 'php8appreciate' '-f' '.docker/runtime/docker-compose.yml'";
Expand All @@ -125,7 +125,7 @@ public function testSolutionDirectoryIsPassedAsEnvVar(): void
->willReturn('/usr/local/bin/docker');

$factory = new DockerProcessFactory('/docker-dir', 'php8appreciate', '/composer/cache/dir', $finder);
$input = new ProcessInput('php', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value']);
$input = new ProcessInput('php', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value'], []);

$process = $factory->create($input);
$cmd = "'/usr/local/bin/docker' 'compose' '-p' 'php8appreciate' '-f' '.docker/runtime/docker-compose.yml'";
Expand Down
10 changes: 5 additions & 5 deletions test/Process/HostProcessFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function testCreateThrowsExceptionIfExecutableNotFound(): void
->willReturn(null);

$factory = new HostProcessFactory($finder);
$input = new ProcessInput('composer', [], __DIR__, []);
$input = new ProcessInput('composer', [], __DIR__, [], []);

$factory->create($input);
}
Expand All @@ -35,7 +35,7 @@ public function testCreate(): void
->willReturn('/usr/local/bin/composer');

$factory = new HostProcessFactory($finder);
$input = new ProcessInput('composer', [], __DIR__, []);
$input = new ProcessInput('composer', [], __DIR__, [], []);

$process = $factory->create($input);
static::assertSame("'/usr/local/bin/composer'", $process->getCommandLine());
Expand All @@ -50,7 +50,7 @@ public function testCreateWithArgs(): void
->willReturn('/usr/local/bin/composer');

$factory = new HostProcessFactory($finder);
$input = new ProcessInput('composer', ['one', 'two'], __DIR__, []);
$input = new ProcessInput('composer', ['one', 'two'], __DIR__, [], []);

$process = $factory->create($input);
static::assertSame("'/usr/local/bin/composer' 'one' 'two'", $process->getCommandLine());
Expand All @@ -65,7 +65,7 @@ public function testCreateWithEnv(): void
->willReturn('/usr/local/bin/composer');

$factory = new HostProcessFactory($finder);
$input = new ProcessInput('composer', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value']);
$input = new ProcessInput('composer', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value'], []);

$process = $factory->create($input);
static::assertSame(['SOME_VAR' => 'value'], $process->getEnv());
Expand All @@ -80,7 +80,7 @@ public function testWithInput(): void
->willReturn('/usr/local/bin/composer');

$factory = new HostProcessFactory($finder);
$input = new ProcessInput('composer', [], __DIR__, [], 'someinput');
$input = new ProcessInput('composer', [], __DIR__, [], [], 'someinput');

$process = $factory->create($input);
static::assertSame('someinput', $process->getInput());
Expand Down
3 changes: 2 additions & 1 deletion test/Process/ProcessInputTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ class ProcessInputTest extends TestCase
{
public function testProcessInput(): void
{
$input = new ProcessInput('composer', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value'], 'input');
$input = new ProcessInput('composer', ['one', 'two'], __DIR__, ['SOME_VAR' => 'value'], [], 'input');

static::assertSame('composer', $input->getExecutable());
static::assertSame(['one', 'two'], $input->getArgs());
static::assertSame(__DIR__, $input->getWorkingDirectory());
static::assertSame(['SOME_VAR' => 'value'], $input->getEnv());
static::assertSame([], $input->getExposedPorts());
static::assertSame('input', $input->getInput());
}
}

0 comments on commit d97450f

Please sign in to comment.