Skip to content

Commit 16edd3b

Browse files
committed
feat: add docker:prune command
fixes #15
1 parent e549b37 commit 16edd3b

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of Ymir command-line tool.
7+
*
8+
* (c) Carl Alexander <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Ymir\Cli\Command\Docker;
15+
16+
use Symfony\Component\Console\Exception\RuntimeException;
17+
use Symfony\Component\Console\Input\InputInterface;
18+
use Symfony\Component\Console\Input\InputOption;
19+
use Ymir\Cli\Command\AbstractCommand;
20+
use Ymir\Cli\Console\OutputInterface;
21+
use Ymir\Cli\Tool\Docker;
22+
23+
class PruneDockerImagesCommand extends AbstractCommand
24+
{
25+
/**
26+
* The name of the command.
27+
*
28+
* @var string
29+
*/
30+
public const NAME = 'docker:prune';
31+
32+
/**
33+
* The grep pattern used with "--all" option.
34+
*
35+
* @var string
36+
*/
37+
private const ALL_PATTERN = 'dkr.ecr';
38+
39+
/**
40+
* {@inheritdoc}
41+
*/
42+
protected function configure()
43+
{
44+
$this
45+
->setName(self::NAME)
46+
->setDescription('Prune deployment docker images')
47+
->addOption('all', null, InputOption::VALUE_NONE, 'Delete all deployment docker images');
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
protected function perform(InputInterface $input, OutputInterface $output)
54+
{
55+
$pattern = $this->getBooleanOption($input, 'all') ? self::ALL_PATTERN : null;
56+
57+
if (!is_string($pattern)) {
58+
$pattern = $this->determinePattern($input, $output);
59+
}
60+
61+
if (!is_string($pattern) || !$output->confirm(self::ALL_PATTERN === $pattern ? 'Are you sure you want to delete all deployment docker images?' : 'Are you sure you want to delete the project\'s deployment docker images?', false)) {
62+
return;
63+
}
64+
65+
Docker::rmigrep($pattern);
66+
67+
$output->info('Deployment docker images pruned successfully');
68+
}
69+
70+
/**
71+
* Determine the grep pattern to use.
72+
*/
73+
private function determinePattern(InputInterface $input, OutputInterface $output): ?string
74+
{
75+
$project = $this->projectConfiguration->exists() ? $this->apiClient->getProject($this->projectConfiguration->getProjectId()) : null;
76+
77+
if (null !== $project && !empty($project['repository_uri'])) {
78+
return $project['repository_uri'];
79+
} elseif (null !== $project && empty($project['repository_uri'])) {
80+
throw new RuntimeException(sprintf('The "%s" project has\'t been deployed using container images', $project['name']));
81+
} elseif (!$input->isInteractive()) {
82+
throw new RuntimeException('Must run command inside an existing project or with "--all" option in non-interactive mode');
83+
}
84+
85+
$output->warning('No project detected in the current directory');
86+
87+
return $output->confirm('Do you want to delete all deployment docker images?', false) ? self::ALL_PATTERN : null;
88+
}
89+
}

src/Tool/Docker.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace Ymir\Cli\Tool;
1515

16+
use Symfony\Component\Console\Exception\RuntimeException;
17+
1618
class Docker extends CommandLineTool
1719
{
1820
/**
@@ -39,6 +41,27 @@ public static function push(string $image, ?string $cwd = null)
3941
self::runCommand(sprintf('push %s', $image), $cwd);
4042
}
4143

44+
/**
45+
* Remove all images matching grep pattern.
46+
*/
47+
public static function rmigrep(string $pattern, ?string $cwd = null)
48+
{
49+
try {
50+
self::runCommand(sprintf('rmi -f $(docker images | grep \'%s\')', $pattern), $cwd);
51+
} catch (RuntimeException $exception) {
52+
$throwException = collect([
53+
'"docker rmi" requires at least 1 argument',
54+
'Error: No such image',
55+
])->doesntContain(function (string $ignore) use ($exception) {
56+
return false === stripos($exception->getMessage(), $ignore);
57+
});
58+
59+
if ($throwException) {
60+
throw $exception;
61+
}
62+
}
63+
}
64+
4265
/**
4366
* Create a docker image tag.
4467
*/

0 commit comments

Comments
 (0)