This commit is contained in:
2024-08-22 19:49:44 -04:00
parent a617bcf040
commit d251d8bd7d
14 changed files with 2971 additions and 0 deletions

117
app/src/Command/Create.php Normal file
View File

@ -0,0 +1,117 @@
<?php
namespace ProVM\ComposeManager\Command;
use Symfony\Component\Console;
#[Console\Attribute\AsCommand(
name: 'create'
)]
class Create extends Console\Command\Command
{
public function __construct(protected string $root, protected string $output, ?string $name = null)
{
parent::__construct($name);
}
protected function configure(): void
{
$this->addArgument('name', Console\Input\InputArgument::REQUIRED, 'Name of the project, same as project folder where docker compose file is located');
$this->addOption('group', 'g', Console\Input\InputOption::VALUE_REQUIRED, "Sub-path to the project folder relative to the root {$this->root}");
$this->addOption('description', 'd', Console\Input\InputOption::VALUE_REQUIRED, 'Description of the project');
$this->addOption('remove-orphans', 'r', Console\Input\InputOption::VALUE_NONE, 'Remove containers for services not defined in the Compose file');
}
protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output): int
{
$filename = implode(DIRECTORY_SEPARATOR, [rtrim($this->output, '/'), "docker-{$input->getArgument('name')}.service"]);
$after = 'docker.service';
$sourceParts = [rtrim($this->root, '/')];
if ($input->hasOption('group') and $input->getOption('group')) {
$sourceParts[] = $input->getOption('group');
$after = $this->getGroupServiceName($input->getOption('group'));
if (!$this->checkGroupFile($input->getOption('group'))) {
$this->buildGroupFile($input->getOption('group'));
}
}
$sourceParts[] = $input->getArgument('name');
$source = implode(DIRECTORY_SEPARATOR, $sourceParts);
if ($input->hasOption('description') and $input->getOption('description')) {
$description = $input->getOption('description');
} else {
$descriptionParts = [];
if ($input->hasOption('group') and $input->getOption('group')) {
$descriptionParts[] = $input->getOption('group');
}
$descriptionParts[] = $input->getArgument('name');
$description = "Docker Compose service for " . implode(DIRECTORY_SEPARATOR, $descriptionParts);
}
$content = $this->buildServiceFile($source, $description, $after, $input->getOption('remove-orphans'));
file_put_contents($filename, $content);
return Console\Command\Command::SUCCESS;
}
protected function buildServiceFile(string $source, string $description, string $after = 'docker.service', bool $removeOrphans = false): string
{
$removeOrphans = $removeOrphans ? ' --remove-orphans' : '';
return <<<SERVICE
[Unit]
Description={$description}
PartOf={$after}
After={$after}
Before=docker-services.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory={$source}
ExecStart=/usr/local/bin/docker-compose up -d
ExecStop=/usr/local/bin/docker-compose down{$removeOrphans}
[Install]
RequiredBy=docker-services.target
SERVICE;
}
protected function getGroupServiceName(string $groupName): string
{
return "docker-{$groupName}.service";
}
protected function checkGroupFile(string $groupName): bool
{
$filename = implode(DIRECTORY_SEPARATOR, [rtrim($this->output, '/'), $this->getGroupServiceName($groupName)]);
return file_exists($filename);
}
protected function buildGroupFile(string $groupName): void
{
$filename = implode(DIRECTORY_SEPARATOR, [rtrim($this->output, '/'), $this->getGroupServiceName($groupName)]);
$content = $this->buildGroupServiceFile($groupName);
file_put_contents($filename, $content);
}
protected function buildGroupServiceFile(string $groupName): string
{
return <<<SERVICE
[Unit]
Description=Docker Compose service for group {$groupName}
PartOf=docker.service
After=docker.service
Before=docker-services.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory={$this->root}/{$groupName}
ExecStart=/bin/true
[Install]
RequiredBy=docker-services.target
SERVICE;
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace ProVM\ComposeManager\Wrapper;
use Psr\Container\ContainerInterface;
use Symfony\Component\Console;
class Application extends Console\Application
{
protected ContainerInterface $container;
public function getContainer(): ContainerInterface
{
return $this->container;
}
public function setContainer(ContainerInterface $container): Application
{
$this->container = $container;
return $this;
}
}