Skip to content

Commit f5e8bdc

Browse files
committed
Merge branch 'develop'
Merge details: (0e8ab9c) Fix tests. by Jelle Sebreghts on Wed Sep 12 16:01:31 2018 (b1e724e) Rename doCreate to doBuild, doRemove to doDestroy. by Jelle Sebreghts on Wed Sep 12 15:57:25 2018 (1af976a) Fix codeclimate issues. by Jelle Sebreghts on Mon Sep 10 09:23:42 2018 (549e23a) Fix codeclimate issues. by Jelle Sebreghts on Mon Sep 10 09:20:58 2018 (bc57e72) Try to fix travis, add PHP 7.2 to tests. by Jelle Sebreghts on Mon Sep 10 09:06:31 2018 (c78c3e7) Split provisioners. by Jelle Sebreghts on Fri Sep 7 16:13:07 2018
2 parents c428c17 + 45266a1 commit f5e8bdc

26 files changed

+1307
-829
lines changed

.travis.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@ language: php
22

33
php:
44
- 7.1
5+
- 7.2
6+
7+
before_install:
8+
- echo "memory_limit=2G" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
59

610
install:
711
- composer self-update
8-
- composer install
12+
- COMPOSER_MEMORY_LIMIT=-1 travis_retry composer install --prefer-dist --no-interaction
913

1014
before_script:
1115
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
@@ -16,4 +20,4 @@ script:
1620
- vendor/bin/phpunit --disallow-test-output --strict-coverage -d error_reporting=-1 --coverage-clover=build/logs/clover.xml Tests
1721

1822
after_script:
19-
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
23+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
namespace DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner;
4+
5+
use DigipolisGent\Domainator9k\CoreBundle\Entity\ApplicationEnvironment;
6+
use DigipolisGent\Domainator9k\CoreBundle\Entity\Task;
7+
use DigipolisGent\Domainator9k\CoreBundle\Entity\VirtualServer;
8+
use DigipolisGent\Domainator9k\CoreBundle\Exception\LoggedException;
9+
use DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Entity\CapistranoCrontabLine;
10+
use phpseclib\Net\SSH2;
11+
12+
/**
13+
* Class AbstractBuildProvisioner
14+
*
15+
* @package DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner
16+
*/
17+
abstract class AbstractBuildProvisioner extends AbstractProvisioner
18+
{
19+
20+
public function doRun()
21+
{
22+
$appEnv = $this->task->getApplicationEnvironment();
23+
$environment = $appEnv->getEnvironment();
24+
25+
/** @var VirtualServer[] $servers */
26+
$servers = $this->entityManager->getRepository(VirtualServer::class)->findAll();
27+
28+
foreach ($servers as $server) {
29+
if ($server->getEnvironment() != $environment) {
30+
continue;
31+
}
32+
33+
if (!$this->dataValueService->getValue($server, 'manage_capistrano')) {
34+
continue;
35+
}
36+
37+
$this->taskLoggerService->addLogHeader(
38+
$this->task,
39+
sprintf('Capistrano server "%s"', $server->getName())
40+
);
41+
42+
try {
43+
$user = $this->dataValueService->getValue($appEnv, 'sock_ssh_user');
44+
$ssh = $this->getSshCommand($server, $user);
45+
46+
$this->doBuild($ssh, $appEnv);
47+
48+
$this->taskLoggerService->addSuccessLogMessage($this->task, 'Server provisioned.');
49+
} catch (\Exception $ex) {
50+
if (empty($ssh)) {
51+
$this->taskLoggerService->addErrorLogMessage($this->task, $ex->getMessage());
52+
}
53+
54+
$this->taskLoggerService->addFailedLogMessage($this->task, 'Provisioning failed.');
55+
throw new LoggedException('', 0, $ex);
56+
}
57+
}
58+
}
59+
60+
/**
61+
* @param SSH2 $ssh
62+
* @param ApplicationEnvironment $appEnv
63+
*/
64+
abstract protected function doBuild(SSH2 $ssh, ApplicationEnvironment $appEnv);
65+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner;
4+
5+
use DigipolisGent\Domainator9k\CoreBundle\Entity\ApplicationEnvironment;
6+
use DigipolisGent\Domainator9k\CoreBundle\Entity\VirtualServer;
7+
use DigipolisGent\Domainator9k\CoreBundle\Exception\LoggedException;
8+
use phpseclib\Net\SSH2;
9+
10+
/**
11+
* Class AbstractDestroyProvisioner
12+
*
13+
* @package DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner
14+
*/
15+
abstract class AbstractDestroyProvisioner extends AbstractProvisioner
16+
{
17+
18+
public function doRun()
19+
{
20+
$appEnv = $this->task->getApplicationEnvironment();
21+
$environment = $appEnv->getEnvironment();
22+
23+
/** @var VirtualServer[] $servers */
24+
$servers = $this->entityManager->getRepository(VirtualServer::class)->findAll();
25+
26+
foreach ($servers as $server) {
27+
if ($server->getEnvironment() != $environment) {
28+
continue;
29+
}
30+
31+
if (!$this->dataValueService->getValue($server, 'manage_capistrano')) {
32+
continue;
33+
}
34+
35+
$this->taskLoggerService->addLogHeader(
36+
$this->task,
37+
sprintf('Capistrano server "%s"', $server->getName())
38+
);
39+
40+
try {
41+
$user = $this->dataValueService->getValue($appEnv, 'sock_ssh_user');
42+
$ssh = $this->getSshCommand($server, $user);
43+
44+
$this->doDestroy($ssh, $appEnv);
45+
46+
$this->taskLoggerService->addSuccessLogMessage($this->task, 'Server cleaned.');
47+
} catch (\Exception $ex) {
48+
if (empty($ssh)) {
49+
$this->taskLoggerService->addErrorLogMessage($this->task, $ex->getMessage());
50+
}
51+
52+
$this->taskLoggerService->addFailedLogMessage($this->task, 'Cleanup failed.');
53+
throw new LoggedException('', 0, $ex);
54+
}
55+
}
56+
}
57+
58+
/**
59+
* @param SSH2 $ssh
60+
* @param ApplicationEnvironment $appEnv
61+
*/
62+
abstract protected function doDestroy(SSH2 $ssh, ApplicationEnvironment $appEnv);
63+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
3+
namespace DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner;
4+
5+
use DigipolisGent\Domainator9k\CoreBundle\Entity\ApplicationEnvironment;
6+
use phpseclib\Net\SSH2;
7+
8+
/**
9+
* Class BuildCrontabProvisioner
10+
*
11+
* @package DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner
12+
*/
13+
class BuildCrontabProvisioner extends AbstractBuildProvisioner
14+
{
15+
16+
public function getName()
17+
{
18+
return 'Capistrano crontab';
19+
}
20+
21+
protected function doBuild(SSH2 $ssh, ApplicationEnvironment $appEnv)
22+
{
23+
$this->taskLoggerService->addLogHeader($this->task, 'Creating crontab', 1);
24+
25+
$templateEntities = [
26+
'application_environment' => $appEnv,
27+
'application' => $appEnv->getApplication(),
28+
'environment' => $appEnv->getEnvironment(),
29+
];
30+
31+
// Get the application specific string to wrap arround the crontab lines.
32+
$wrapper = '### DOMAINATOR:';
33+
$wrapper .= $appEnv->getApplication()->getNameCanonical() . ':';
34+
$wrapper .= $appEnv->getEnvironment()->getName() . ' ###';
35+
36+
// Build the command to strip the current crontab lines.
37+
$command = 'crontab -l | ';
38+
$command .= 'tr -s [:cntrl:] \'\r\' | ';
39+
$command .= 'sed -e \'s/' . $wrapper . '.*' . $wrapper . '\r*//\' | ';
40+
$command .= 'sed -e \'s/#\s\+Edit this file[^\r]\+\r\(#\(\s[^\r]*\)\?\r\)*//\' | ';
41+
$command .= 'tr -s \'\r\' \'\n\'';
42+
43+
// Get the crontab lines.
44+
$crontabLines = $this->dataValueService->getValue($appEnv, 'capistrano_crontab_line');
45+
46+
try {
47+
if (!$crontabLines || $ssh->host !== $appEnv->getWorkerServerIp()) {
48+
// Remove the crontab lines.
49+
$command = '(' . $command . ') | crontab -';
50+
51+
$this->executeSshCommand($ssh, $command);
52+
$this->taskLoggerService->addSuccessLogMessage($this->task, 'Crontab cleared.', 2);
53+
return;
54+
}
55+
56+
// Build the application crontab lines.
57+
$crontab = '';
58+
/** @var CapistranoCrontabLine $crontabLine */
59+
foreach ($crontabLines as $crontabLine) {
60+
$crontab .= $this->templateService->replaceKeys((string) $crontabLine, $templateEntities);
61+
$crontab .= "\n";
62+
}
63+
64+
// Wrap and escape them.
65+
$crontab = $wrapper . "\n" . $crontab . $wrapper;
66+
$crontab = escapeshellarg($crontab);
67+
68+
// Apply the changes on the server.
69+
$command = '(echo ' . $crontab . ' && ' . $command . ') | crontab -';
70+
71+
$this->executeSshCommand($ssh, $command);
72+
73+
$this->taskLoggerService->addSuccessLogMessage($this->task, 'Crontab created.', 2);
74+
} catch (\Exception $ex) {
75+
$this->taskLoggerService
76+
->addErrorLogMessage($this->task, $ex->getMessage(), 2)
77+
->addFailedLogMessage($this->task, 'Creating crontab failed.', 2);
78+
79+
throw $ex;
80+
}
81+
}
82+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
namespace DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner;
4+
5+
use DigipolisGent\Domainator9k\CoreBundle\Entity\ApplicationEnvironment;
6+
use phpseclib\Net\SSH2;
7+
8+
/**
9+
* Class BuildFileProvisioner
10+
*
11+
* @package DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner
12+
*/
13+
class BuildFileProvisioner extends AbstractBuildProvisioner
14+
{
15+
16+
public function getName()
17+
{
18+
return 'Capistrano files';
19+
}
20+
21+
protected function doBuild(SSH2 $ssh, ApplicationEnvironment $appEnv)
22+
{
23+
$this->taskLoggerService->addLogHeader($this->task, 'Creating files', 1);
24+
25+
if (!$capistranoFiles = $this->dataValueService->getValue($appEnv, 'capistrano_file')) {
26+
$this->taskLoggerService->addInfoLogMessage($this->task, 'No files specified.', 2);
27+
return;
28+
}
29+
30+
$templateEntities = [
31+
'application_environment' => $appEnv,
32+
'application' => $appEnv->getApplication(),
33+
'environment' => $appEnv->getEnvironment(),
34+
];
35+
36+
try {
37+
foreach ($capistranoFiles as $capistranoFile) {
38+
$path = $capistranoFile->getLocation();
39+
$path .= '/' . $capistranoFile->getFilename();
40+
$path .= '.' . $capistranoFile->getExtension();
41+
$path = $this->templateService->replaceKeys($path, $templateEntities);
42+
43+
$this->taskLoggerService->addLogHeader(
44+
$this->task,
45+
sprintf('Creating "%s"', $path),
46+
2
47+
);
48+
49+
$tmpPath = escapeshellarg($path . uniqid('.', true) . '.tmp');
50+
$path = escapeshellarg($path);
51+
52+
$content = $this->templateService->replaceKeys($capistranoFile->getContent(), $templateEntities);
53+
$content = str_replace(["\r\n", "\r"], "\n", $content);
54+
55+
// 8192 bytes is the max length supported by escapeshellarg.
56+
if (strlen($content) > 8192) {
57+
$length = mb_strlen($content, 'UTF-8');
58+
$maxI = (int) ceil($length / 2048) - 1;
59+
60+
for ($i = 0; $i <= $maxI; $i++) {
61+
$part = mb_substr($content, $i * 2048, 2048, 'UTF-8');
62+
$part = escapeshellarg($part);
63+
64+
$command = 'echo ' . ($i === $maxI ? '' : '-n ') . $part . ($i ? ' >> ' : ' > ') . $tmpPath;
65+
66+
if ($i === $maxI) {
67+
$command .= ' && chmod ' . $capistranoFile->getChmod() . ' ' . $tmpPath;
68+
$command .= ' && mv -f ' . $tmpPath . ' ' . $path;
69+
}
70+
71+
$this->executeSshCommand($ssh, $command, 3);
72+
}
73+
74+
continue;
75+
}
76+
77+
$content = escapeshellarg($content);
78+
$command = 'echo ' . $content . ' > ' . $tmpPath;
79+
$command .= ' && chmod ' . $capistranoFile->getChmod() . ' ' . $tmpPath;
80+
$command .= ' && mv -f ' . $tmpPath . ' ' . $path;
81+
82+
$this->executeSshCommand($ssh, $command, 3);
83+
}
84+
85+
$this->taskLoggerService->addSuccessLogMessage($this->task, 'Files created.', 2);
86+
} catch (\Exception $ex) {
87+
$this->taskLoggerService
88+
->addErrorLogMessage($this->task, $ex->getMessage(), 2)
89+
->addFailedLogMessage($this->task, 'Creating files failed.', 2);
90+
91+
throw $ex;
92+
}
93+
}
94+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner;
4+
5+
use DigipolisGent\Domainator9k\CoreBundle\Entity\ApplicationEnvironment;
6+
use phpseclib\Net\SSH2;
7+
8+
/**
9+
* Class BuildFolderProvisioner
10+
*
11+
* @package DigipolisGent\Domainator9k\ServerTypes\CapistranoOpenmindsBundle\Provisioner
12+
*/
13+
class BuildFolderProvisioner extends AbstractBuildProvisioner
14+
{
15+
16+
public function getName()
17+
{
18+
return 'Capistrano folders';
19+
}
20+
21+
protected function doBuild(SSH2 $ssh, ApplicationEnvironment $appEnv)
22+
{
23+
$this->taskLoggerService->addLogHeader($this->task, 'Creating directories', 1);
24+
25+
if (!$capistranoFolders = $this->dataValueService->getValue($appEnv, 'capistrano_folder')) {
26+
$this->taskLoggerService->addInfoLogMessage($this->task, 'No directories specified.', 2);
27+
return;
28+
}
29+
30+
$templateEntities = [
31+
'application_environment' => $appEnv,
32+
'application' => $appEnv->getApplication(),
33+
'environment' => $appEnv->getEnvironment(),
34+
];
35+
36+
try {
37+
foreach ($capistranoFolders as $capistranoFolder) {
38+
$path = $this->templateService->replaceKeys($capistranoFolder->getLocation(), $templateEntities);
39+
40+
$this->taskLoggerService->addLogHeader(
41+
$this->task,
42+
sprintf('Creating "%s".', $path),
43+
2
44+
);
45+
$cmd = 'mkdir -p ' . escapeshellarg($path)
46+
. ' && chmod ' . $capistranoFolder->getChmod() . ' ' . escapeshellarg($path);
47+
$this->executeSshCommand($ssh, $cmd, 3);
48+
}
49+
50+
$this->taskLoggerService->addSuccessLogMessage($this->task, 'Directories created.', 2);
51+
} catch (\Exception $ex) {
52+
$this->taskLoggerService
53+
->addErrorLogMessage($this->task, $ex->getMessage(), 2)
54+
->addFailedLogMessage($this->task, 'Creating directories failed.', 2);
55+
56+
throw $ex;
57+
}
58+
}
59+
}

0 commit comments

Comments
 (0)