Skip to content

Commit

Permalink
Move docker related stuff to docker NS
Browse files Browse the repository at this point in the history
  • Loading branch information
welcoMattic authored and lyrixx committed Feb 24, 2024
1 parent 9fc495e commit 7021f29
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 243 deletions.
229 changes: 229 additions & 0 deletions .castor/utils.php → .castor/docker.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
<?php

namespace docker;

use Castor\Attribute\AsContext;
use Castor\Attribute\AsOption;
use Castor\Attribute\AsTask;
use Castor\Context;
use Symfony\Component\Process\Exception\ExceptionInterface;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;

use function Castor\cache;
use function Castor\capture;
use function Castor\context;
use function Castor\finder;
use function Castor\fs;
use function Castor\io;
use function Castor\log;
use function Castor\run;
Expand Down Expand Up @@ -46,6 +53,202 @@ function about(): void
io()->listing(array_map(fn ($url) => "https://{$url}", $urls));
}

#[AsTask(description: 'Builds the infrastructure', aliases: ['build'])]
function build(): void
{
$userId = variable('user_id');
$phpVersion = variable('php_version');

$command = [
'build',
'--build-arg', "USER_ID={$userId}",
'--build-arg', "PHP_VERSION={$phpVersion}",
];

docker_compose($command, withBuilder: true);
}

#[AsTask(description: 'Builds and starts the infrastructure', aliases: ['up'])]
function up(): void
{
try {
docker_compose(['up', '--remove-orphans', '--detach', '--no-build']);
} catch (ExceptionInterface $e) {
io()->error('An error occured while starting the infrastructure.');
io()->note('Did you forget to run "castor infra:build"?');
io()->note('Or you forget to login to the registry?');

throw $e;
}
}

#[AsTask(description: 'Stops the infrastructure', aliases: ['stop'])]
function stop(): void
{
docker_compose(['stop']);
}

#[AsTask(description: 'Opens a shell (bash) into a builder container', aliases: ['builder'])]
function builder(): void
{
$c = context()
->withTimeout(null)
->withTty()
->withEnvironment($_ENV + $_SERVER)
->withAllowFailure()
;
docker_compose_run('bash', c: $c);
}

#[AsTask(description: 'Displays infrastructure logs', aliases: ['logs'])]
function logs(): void
{
docker_compose(['logs', '-f', '--tail', '150'], c: context()->withTty());
}

#[AsTask(description: 'Lists containers status', aliases: ['ps'])]
function ps(): void
{
docker_compose(['ps'], withBuilder: false);
}

#[AsTask(description: 'Cleans the infrastructure (remove container, volume, networks)', aliases: ['destroy'])]
function destroy(
#[AsOption(description: 'Force the destruction without confirmation', shortcut: 'f')]
bool $force = false,
): void {
if (!$force) {
io()->warning('This will permanently remove all containers, volumes, networks... created for this project.');
io()->note('You can use the --force option to avoid this confirmation.');
if (!io()->confirm('Are you sure?', false)) {
io()->comment('Aborted.');

return;
}
}

docker_compose(['down', '--remove-orphans', '--volumes', '--rmi=local'], withBuilder: true);
$files = finder()
->in(variable('root_dir') . '/infrastructure/docker/services/router/certs/')
->name('*.pem')
->files()
;
fs()->remove($files);
}

#[AsTask(description: 'Generates SSL certificates (with mkcert if available or self-signed if not)')]
function generate_certificates(
#[AsOption(description: 'Force the certificates re-generation without confirmation', shortcut: 'f')]
bool $force = false,
): void {
$sslDir = variable('root_dir') . '/infrastructure/docker/services/router/certs';

if (file_exists("$sslDir/cert.pem") && !$force) {
io()->comment('SSL certificates already exists.');
io()->note('Run "castor infra:generate-certificates --force" to generate new certificates.');

return;
}

if ($force) {
if (file_exists($f = "$sslDir/cert.pem")) {
io()->comment('Removing existing certificates in infrastructure/docker/services/router/certs/*.pem.');
unlink($f);
}

if (file_exists($f = "$sslDir/key.pem")) {
unlink($f);
}
}

$finder = new ExecutableFinder();
$mkcert = $finder->find('mkcert');

if ($mkcert) {
$pathCaRoot = capture(['mkcert', '-CAROOT']);

if (!is_dir($pathCaRoot)) {
io()->warning('You must have mkcert CA Root installed on your host with "mkcert -install" command.');

return;
}

$rootDomain = variable('root_domain');

run([
'mkcert',
'-cert-file', "$sslDir/cert.pem",
'-key-file', "$sslDir/key.pem",
$rootDomain,
"*.{$rootDomain}",
...variable('extra_domains'),
]);

io()->success('Successfully generated SSL certificates with mkcert.');

if ($force) {
io()->note('Please restart the infrastructure to use the new certificates with "castor up" or "castor start".');
}

return;
}

run(['infrastructure/docker/services/router/generate-ssl.sh'], quiet: true);

io()->success('Successfully generated self-signed SSL certificates in infrastructure/docker/services/router/certs/*.pem.');
io()->comment('Consider installing mkcert to generate locally trusted SSL certificates and run "castor infra:generate-certificates --force".');

if ($force) {
io()->note('Please restart the infrastructure to use the new certificates with "castor up" or "castor start".');
}
}

#[AsTask(description: 'Starts the workers', namespace: 'infra:worker', name: 'start', aliases: ['start-workers'])]
function workers_start(): void
{
$workers = get_workers();

if (!$workers) {
return;
}

run([
'docker',
'update',
'--restart=unless-stopped',
...$workers,
], quiet: true);

run([
'docker',
'start',
...$workers,
], quiet: true);
}

#[AsTask(description: 'Stops the workers', namespace: 'infra:worker', name: 'stop', aliases: ['stop-workers'])]
function workers_stop(): void
{
$workers = get_workers();

if (!$workers) {
return;
}

run([
'docker',
'update',
'--restart=no',
...$workers,
]);

run([
'docker',
'stop',
...$workers,
]);
}

#[AsContext(default: true)]
function create_default_context(): Context
{
Expand Down Expand Up @@ -195,6 +398,7 @@ function docker_compose(array $subCommand, Context $c = null, bool $withBuilder
$command[] = '-f';
$command[] = variable('root_dir') . '/infrastructure/docker/' . $file;
}

if ($withBuilder) {
$command[] = '-f';
$command[] = variable('root_dir') . '/infrastructure/docker/docker-compose.builder.yml';
Expand All @@ -217,3 +421,28 @@ function run_in_docker_or_locally_for_mac(string $command, Context $c = null): v
docker_compose_run($command, c: $c);
}
}

/**
* Find worker containers for the current project.
*
* @return array<string>
*/
function get_workers(): array
{
$command = [
'docker',
'ps',
'-a',
'--filter', 'label=docker-starter.worker.' . variable('project_name'),
'--quiet',
];
$out = capture($command);

if (!$out) {
return [];
}

$workers = explode("\n", $out);

return array_map('trim', $workers);
}
Loading

0 comments on commit 7021f29

Please sign in to comment.