-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathPackageCommand.php
149 lines (127 loc) · 6.46 KB
/
PackageCommand.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<?php
/**
* WindowsAzure DistributionBundle
*
* LICENSE
*
* This source file is subject to the MIT license that is bundled
* with this package in the file LICENSE.txt.
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@beberlei.de so I can send you a copy immediately.
*/
namespace WindowsAzure\DistributionBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use WindowsAzure\DistributionBundle\Deployment\BuildNumber;
/**
* Package a Symfony application for deployment.
*
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Stéphane Escandell <stephane.escandell@gmail.com>
*/
class PackageCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName('azure:cloud-services:package')
->setDescription('Packages this symfony application for deployment on Windows Azure Cloud Services.')
->addOption('dev-fabric', null, InputOption::VALUE_NONE, 'Build package for dev-fabric? This will only copy the files and startup the Azure Simulator.')
->addOption('output-dir', null, InputOption::VALUE_REQUIRED, 'Output directory. Will override the default directory configured as approot/build.')
->addOption('skip-role-file-generation', null, InputOption::VALUE_NONE, 'Skip the generation of role files for the /roleFiles argument of cspack.exe. This will reuse old existing files.')
->addOption('timeout', null, InputOption::VALUE_OPTIONAL, 'Timeout for process execution to generate package', 400);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln("Loading Azure Deployment details..");
$deployment = $this->getContainer()->get('windows_azure_distribution.deployment');
if (! $deployment->exists()) {
$output->writeln('<error>No Azure deployment details found</error>');
$output->writeln('Execute the windowsazure:init command to create the basic structure for a deployment.');
return;
}
$output->writeln('..done.');
$output->writeln('');
$serviceDefinition = $deployment->getServiceDefinition();
$serviceConfiguration = $deployment->getServiceConfiguration();
$outputDir = $input->getOption('output-dir') ? : $this->getContainer()->getParameter('windows_azure_distribution.config.application_root') . '/build';
$output->writeln("Building Azure SDK packages into directory:");
$output->writeln($outputDir);
if (! file_exists($outputDir)) {
$fs = new Filesystem();
$fs->mkdir($outputDir, 0777);
$output->writeln('<info>Output directory created, because it didn\'t exist yet.</info>');
}
$outputDir = realpath($outputDir);
$kernelRoot = $this->getContainer()->getParameter('kernel.root_dir');
if (! is_writeable($outputDir)) {
throw new \RuntimeException("Output-directory is not writable!");
}
$buildNumber = BuildNumber::createInDirectory($kernelRoot . "/config")->increment();
$outputFile = $outputDir . "/azure-" . $buildNumber . ".cspkg";
if (file_exists($outputFile)) {
if (is_file($outputFile)) {
unlink($outputFile);
} else {
$this->rmdir($outputFile, true);
}
}
$output->writeln('Compiling assets for build ' . $buildNumber);
$webRoleStrategy = $this->getContainer()->get('windows_azure_distribution.assets'); // TODO: passer par un package compiler
foreach ($serviceDefinition->getPhysicalDirectories() as $dir) {
$webRoleStrategy->deploy($dir, $buildNumber);
}
foreach ($this->getContainer()
->get('windows_azure_distribution.package_compiler')
->getCompilers() as $compiler) {
$compiler->compileDependencies($serviceDefinition, $buildNumber);
}
if (! $input->getOption('skip-role-file-generation')) {
$output->writeln('Starting to compile role files for each physical directory.');
$s = microtime(true);
$inputDir = $kernelRoot . '/../';
$serviceDefinition->createRoleFiles($inputDir, $outputFile);
$output->writeln('..compiled role-files. (Took ' . number_format(microtime(true) - $s, 4) . ' seconds)');
}
$serviceConfiguration->copyForDeployment($outputDir, $input->getOption('dev-fabric'));
$output->writeln('Calling cspack.exe to build Azure Package:');
$s = microtime(true);
$azureCmdBuilder = $this->getContainer()->get('windows_azure_distribution.deployment.azure_sdk_command_builder');
$args = $azureCmdBuilder->buildPackageCmd($serviceDefinition, $outputFile, $input->getOption('dev-fabric'));
$process = $azureCmdBuilder->getProcess($args); // @todo: Update to ProcessBuilder in 2.1 Symfony
$process->setTimeout($input->getOption('timeout'));
$process->run();
if (! $process->isSuccessful()) {
throw new \RuntimeException($process->getErrorOutput() ? : $process->getOutput());
}
$output->writeln(trim($process->getOutput()));
$output->writeln('Completed. (Took ' . number_format(microtime(true) - $s, 4) . ' seconds)');
}
private function rmdir($dir, $recursive = true)
{
if (! is_dir($dir)) {
throw new \InvalidArgumentException("No directory given.");
}
if ($recursive) {
$nodes = scandir($dir);
foreach ($nodes as $node) {
if ($node == "." || $node == "..") {
continue;
} else
if (is_dir($node)) {
if (! $this->rmdir($node, true)) {
throw new \RuntimeException("could not delete subnode.");
}
} else
if (is_file($node)) {
unlink($node);
}
}
}
return rmdir($dir);
}
}