Skip to content

Commit c9d7444

Browse files
authored
Merge pull request #66 from ByteInternet/cleanup_by_labels
2 parents 823819a + 37f6d78 commit c9d7444

File tree

9 files changed

+220
-122
lines changed

9 files changed

+220
-122
lines changed

ci/test/magento/deploy_brancher.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
]);
1919

2020
$productionStage = $configuration->addStage('test', 'banaan.store');
21-
$productionStage->addBrancherServer('hndeployintegr8');
21+
$productionStage->addBrancherServer('hndeployintegr8')
22+
->setLabels(['gitref='.\getenv('GITHUB_SHA') ?: 'unknown']);
2223

2324
return $configuration;

ci/test/run-brancher.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,26 @@ $DP jq .brancher_hypernodes[0] deployment-report.json -r -e
5757

5858
# cleanup data
5959
$DP hypernode-deploy cleanup -vvv
60+
61+
rm -f deployment-report.json
62+
63+
# Now do a test deploy again to deploy to a brancher node and clean it up by hnapi and labels matching
64+
$DP hypernode-deploy deploy test -f /web/deploy.php -vvv
65+
66+
$DP ls -l
67+
$DP test -f deployment-report.json
68+
$DP jq . deployment-report.json
69+
$DP jq .version deployment-report.json -r -e
70+
$DP jq .stage deployment-report.json -r -e
71+
$DP jq .hostnames[0] deployment-report.json -r -e
72+
$DP jq .brancher_hypernodes[0] deployment-report.json -r -e
73+
74+
# Remove deployment report to make sure we can clean up using hnapi and labels matching
75+
BRANCHER_INSTANCE=$($DP jq .brancher_hypernodes[0] deployment-report.json -r -e)
76+
$DP rm -f deployment-report.json
77+
78+
# cleanup data
79+
$DP hypernode-deploy cleanup test -vvv | tee cleanup.log
80+
81+
# Run tests on cleanup
82+
grep "Stopping brancher Hypernode ${BRANCHER_INSTANCE}..." cleanup.log

composer.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Brancher/BrancherHypernodeManager.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,40 @@ public function __construct(LoggerInterface $log)
2222
$this->hypernodeClient = HypernodeClientFactory::create(getenv('HYPERNODE_API_TOKEN') ?: '');
2323
}
2424

25+
/**
26+
* Query brancher instances for given Hypernode and return the Brancher instance names.
27+
*
28+
* @param string $hypernode The parent hypernode to query the Brancher instances from
29+
* @param string[] $labels Labels to match against, may be empty
30+
* @return string[] The found Brancher instance names
31+
*/
32+
public function queryBrancherHypernodes(string $hypernode, array $labels = []): array
33+
{
34+
$result = [];
35+
36+
$hypernodes = $this->hypernodeClient->app->getList([
37+
'parent' => $hypernode,
38+
'type' => 'brancher',
39+
'destroyed' => 'False',
40+
]);
41+
foreach ($hypernodes as $brancher) {
42+
$match = true;
43+
44+
foreach ($labels as $label) {
45+
if (!in_array($label, $brancher->labels)) {
46+
$match = false;
47+
break;
48+
}
49+
}
50+
51+
if ($match) {
52+
$result[] = $brancher->name;
53+
}
54+
}
55+
56+
return $result;
57+
}
58+
2559
/**
2660
* Create brancher Hypernode instance for given Hypernode.
2761
*
@@ -82,7 +116,7 @@ public function waitForAvailability(string $brancherHypernode, int $timeout = 90
82116
} elseif ($timeElapsed < $allowedErrorWindow) {
83117
// Sometimes we get an error where the logbook is not yet available, but it will be soon.
84118
// We allow a small window for this to happen, and then we throw an exception.
85-
sprintf(
119+
printf(
86120
'Got an expected exception during the allowed error window of HTTP code %d, waiting for %s to become available',
87121
$e->getCode(),
88122
$brancherHypernode

src/Command/Cleanup.php

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,36 @@
55
namespace Hypernode\Deploy\Command;
66

77
use Hypernode\Deploy\Brancher\BrancherHypernodeManager;
8+
use Hypernode\Deploy\ConfigurationLoader;
9+
use Hypernode\Deploy\DeployerLoader;
810
use Hypernode\Deploy\Report\ReportLoader;
11+
use Hypernode\DeployConfiguration\BrancherServer;
12+
use Hypernode\DeployConfiguration\Configuration;
13+
use Hypernode\DeployConfiguration\Server;
914
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Input\InputArgument;
1016
use Symfony\Component\Console\Input\InputInterface;
1117
use Symfony\Component\Console\Output\OutputInterface;
1218
use Throwable;
1319

1420
class Cleanup extends Command
1521
{
1622
private ReportLoader $reportLoader;
23+
private DeployerLoader $deployerLoader;
24+
private ConfigurationLoader $configurationLoader;
1725
private BrancherHypernodeManager $brancherHypernodeManager;
1826

19-
public function __construct(ReportLoader $reportLoader, BrancherHypernodeManager $brancherHypernodeManager)
20-
{
27+
public function __construct(
28+
ReportLoader $reportLoader,
29+
DeployerLoader $deployerLoader,
30+
ConfigurationLoader $configurationLoader,
31+
BrancherHypernodeManager $brancherHypernodeManager
32+
) {
2133
parent::__construct();
2234

2335
$this->reportLoader = $reportLoader;
36+
$this->deployerLoader = $deployerLoader;
37+
$this->configurationLoader = $configurationLoader;
2438
$this->brancherHypernodeManager = $brancherHypernodeManager;
2539
}
2640

@@ -31,6 +45,7 @@ protected function configure()
3145
$this->setDescription(
3246
'Clean up any acquired resources during the deployment, like brancher Hypernodes.'
3347
);
48+
$this->addArgument('stage', InputArgument::OPTIONAL, 'Stage to cleanup');
3449
}
3550

3651
/**
@@ -40,13 +55,46 @@ protected function execute(InputInterface $input, OutputInterface $output)
4055
{
4156
$report = $this->reportLoader->loadReport();
4257

43-
if ($report === null) {
44-
$output->writeln('No report found, skipping cleanup.');
45-
return 0;
58+
if ($report) {
59+
$this->brancherHypernodeManager->cancel(...$report->getBrancherHypernodes());
4660
}
4761

48-
$this->brancherHypernodeManager->cancel(...$report->getBrancherHypernodes());
62+
/** @var string $stageName */
63+
$stageName = $input->getArgument('stage');
64+
if ($stageName) {
65+
$this->deployerLoader->getOrCreateInstance($output);
66+
$config = $this->configurationLoader->load($input->getOption('file') ?: 'deploy.php');
67+
$this->cancelByStage($stageName, $config);
68+
}
4969

5070
return 0;
5171
}
72+
73+
/**
74+
* Cancel brancher nodes by stage and their configured labels.
75+
*
76+
* @param string $stageName Stage to clean up
77+
* @param Configuration $config Deployment configuration to read stages/servers from
78+
* @return void
79+
*/
80+
private function cancelByStage(string $stageName, Configuration $config): void
81+
{
82+
foreach ($config->getStages() as $stage) {
83+
if ($stage->getName() !== $stageName) {
84+
continue;
85+
}
86+
foreach ($stage->getServers() as $server) {
87+
if (!($server instanceof BrancherServer)) {
88+
continue;
89+
}
90+
$labels = $server->getLabels();
91+
$hypernode = $server->getOptions()[Server::OPTION_HN_PARENT_APP];
92+
$brancherHypernodes = $this->brancherHypernodeManager->queryBrancherHypernodes(
93+
$hypernode,
94+
$labels
95+
);
96+
$this->brancherHypernodeManager->cancel(...$brancherHypernodes);
97+
}
98+
}
99+
}
52100
}

src/Command/Deploy.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@
1212

1313
class Deploy extends Command
1414
{
15-
/**
16-
* @var DeployRunner
17-
*/
18-
private $deployRunner;
15+
private DeployRunner $deployRunner;
1916
private ReportWriter $reportWriter;
2017

2118
public function __construct(DeployRunner $deployRunner, ReportWriter $reportWriter)
@@ -38,7 +35,13 @@ protected function configure()
3835
*/
3936
protected function execute(InputInterface $input, OutputInterface $output)
4037
{
41-
$result = $this->deployRunner->run($output, $input->getArgument('stage'), DeployRunner::TASK_DEPLOY, false, true);
38+
$result = $this->deployRunner->run(
39+
$output,
40+
$input->getArgument('stage'),
41+
DeployRunner::TASK_DEPLOY,
42+
false,
43+
true
44+
);
4245

4346
if ($result === 0) {
4447
$this->reportWriter->write($this->deployRunner->getDeploymentReport());

src/ConfigurationLoader.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Hypernode\Deploy;
6+
7+
use Deployer\Deployer;
8+
use Deployer\Exception\Exception;
9+
use Deployer\Exception\GracefulShutdownException;
10+
use Hypernode\DeployConfiguration\Configuration;
11+
use Throwable;
12+
13+
class ConfigurationLoader
14+
{
15+
/**
16+
* @throws Exception
17+
* @throws GracefulShutdownException
18+
* @throws Throwable
19+
*/
20+
public function load(string $file): Configuration
21+
{
22+
if (!is_readable($file)) {
23+
throw new \RuntimeException(sprintf('No %s file found in project root %s', $file, getcwd()));
24+
}
25+
26+
$configuration = \call_user_func(function () use ($file) {
27+
return require $file;
28+
});
29+
30+
if (!$configuration instanceof Configuration) {
31+
throw new \RuntimeException(
32+
sprintf('%s/deploy.php did not return object of type %s', getcwd(), Configuration::class)
33+
);
34+
}
35+
36+
return $configuration;
37+
}
38+
}

0 commit comments

Comments
 (0)