diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1d68ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.*.un~ +.*.swp \ No newline at end of file diff --git a/BeSimpleDeploymentBundle.php b/BeSimpleDeploymentBundle.php new file mode 100755 index 0000000..f783299 --- /dev/null +++ b/BeSimpleDeploymentBundle.php @@ -0,0 +1,9 @@ +setDefinition(array( new InputArgument('server', InputArgument::OPTIONAL, 'The target server name', null), @@ -23,23 +26,23 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { - $deployer = $this->container->get('besimple_deployment.deployer'); + $deployer = $this->container->get('be_simple_deployment.deployer'); $eventDispatcher = $this->container->get('event_dispatcher'); $this->output = $output; $this->output->setDecorated(true); - if ($output->getVerbosity() > Output::VERBOSITY_QUIET) { - $dispatcher->connect('besimple_deployment.start', function ($event) use ($that) { $that->write($event, 'start'); }); - $dispatcher->connect('besimple_deployment.error', function ($event) use ($that) { $that->write($event, 'error'); }); - $dispatcher->connect('besimple_deployment.success', function ($event) use ($that) { $that->write($event, 'success'); }); + //if ($output->getVerbosity() > Output::VERBOSITY_QUIET) { + //$eventDispatcher->addListener('besimple_deployment.start', function ($event) use ($that) { $that->write($event, 'start'); }); + //$eventDispatcher->addListener('besimple_deployment.error', function ($event) use ($that) { $that->write($event, 'error'); }); + //$eventDispatcher->addListener('besimple_deployment.success', function ($event) use ($that) { $that->write($event, 'success'); }); - if ($output->getVerbosity() > Output::VERBOSITY_NORMAL) { - $dispatcher->connect('besimple_deployment.rsync', function ($event) use ($that) { $that->write($event, 'rsync'); }); - } + //if ($output->getVerbosity() > Output::VERBOSITY_NORMAL) { + //$eventDispatcher->addListener('besimple_deployment.rsync', function ($event) use ($that) { $that->write($event, 'rsync'); }); + //} - // TODO: add SSH events - } + //// TODO: add SSH events + //} $this->executeDeployment($deployer, $input->getArgument('server')); } @@ -77,4 +80,4 @@ public function write(EventInterface $event, $type) } abstract protected function executeDeployment(Deployer $deployer, $server); -} \ No newline at end of file +} diff --git a/Command/LaunchDeploymentCommand.php b/Command/LaunchDeploymentCommand.php index bffad00..86ed521 100644 --- a/Command/LaunchDeploymentCommand.php +++ b/Command/LaunchDeploymentCommand.php @@ -2,12 +2,14 @@ namespace BeSimple\DeploymentBundle\Command; -use Bundle\DeploymentBundle\Deployer\Deployer; +use BeSimple\DeploymentBundle\Deployer\Deployer; +use Symfony\Component\Console\Command\Command; -abstract class DeploymentCommand extends Command +class LaunchDeploymentCommand extends DeploymentCommand { protected function configure() { + parent::configure(); $this->setName('deployment:launch'); } @@ -15,4 +17,4 @@ protected function executeDeployment(Deployer $deployer, $server) { $deployer->launch($server); } -} \ No newline at end of file +} diff --git a/Command/TestDeploymentCommand.php b/Command/TestDeploymentCommand.php index 767e873..71e816e 100644 --- a/Command/TestDeploymentCommand.php +++ b/Command/TestDeploymentCommand.php @@ -2,12 +2,14 @@ namespace BeSimple\DeploymentBundle\Command; -use Bundle\DeploymentBundle\Deployer\Deployer; +use BeSimple\DeploymentBundle\Deployer\Deployer; +use Symfony\Component\Console\Command\Command; -abstract class DeploymentCommand extends Command +class TestDeploymentCommand extends DeploymentCommand { protected function configure() { + parent::configure(); $this->setName('deployment:test'); } @@ -15,4 +17,4 @@ protected function executeDeployment(Deployer $deployer, $server) { $deployer->test($server); } -} \ No newline at end of file +} diff --git a/DependencyInjection/DeploymentExtension.php b/DependencyInjection/BeSimpleDeploymentExtension.php similarity index 51% rename from DependencyInjection/DeploymentExtension.php rename to DependencyInjection/BeSimpleDeploymentExtension.php index 3b9d6c5..974f64b 100755 --- a/DependencyInjection/DeploymentExtension.php +++ b/DependencyInjection/BeSimpleDeploymentExtension.php @@ -3,9 +3,10 @@ namespace BeSimple\DeploymentBundle\DependencyInjection; use Symfony\Component\Config\Definition\Processor; -use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Config\FileLocator; class BeSimpleDeploymentExtension extends Extension { @@ -18,10 +19,15 @@ public function load(array $configs, ContainerBuilder $container) $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('deployment.xml'); - $container->setParameter('besimple_deployment.config.rsync', $config['rsync']); - $container->setParameter('besimple_deployment.config.ssh', $config['rsync']); - $container->setParameter('besimple_deployment.config.rules', $config['rules']); - $container->setParameter('besimple_deployment.config.commands', $config['commands']); - $container->setParameter('besimple_deployment.config.servers', $config['servers']); + $container->setParameter('be_simple_deployment.config.rsync', $config['rsync']); + $container->setParameter('be_simple_deployment.config.ssh', $config['rsync']); + $container->setParameter('be_simple_deployment.config.rules', $config['rules']); + $container->setParameter('be_simple_deployment.config.commands', $config['commands']); + $container->setParameter('be_simple_deployment.config.servers', $config['servers']); } -} \ No newline at end of file + + public function getAlias() + { + return 'be_simple_deployment'; + } +} diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 03665cc..ca71fdc 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -2,7 +2,7 @@ namespace BeSimple\DeploymentBundle\DependencyInjection; -use Symfony\Component\Config\Definition\Builder\NodeBuilder; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; class Configuration @@ -15,7 +15,7 @@ class Configuration public function getConfigTree() { $treeBuilder = new TreeBuilder(); - $rootNode = $treeBuilder->root('besimple_deployment', 'array'); + $rootNode = $treeBuilder->root('be_simple_deployment', 'array'); $this->addRsyncSection($rootNode); $this->addSshSection($rootNode); @@ -26,73 +26,76 @@ public function getConfigTree() return $treeBuilder->buildTree(); } - protected function addRsyncSection(NodeBuilder $node) + protected function addRsyncSection(ArrayNodeDefinition $node) { - $node + $node->children() ->arrayNode('rsync') - ->scalarNode('command')->defaultValue('rsync')->cannotBeEmpty()->end() - ->booleanNode('delete')->defaultFalse()->end() - ->scalarNode('options')->defaultValue('-Cva')->end() - ->scalarNode('root')->defaultValue('%kernel.root_dir%/..')->isRequired()->cannotBeEmpty()->end() - ->end() + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('command')->defaultValue('rsync')->cannotBeEmpty()->end() + ->booleanNode('delete')->defaultFalse()->end() + ->scalarNode('options')->defaultValue('-Cva')->end() + ->scalarNode('root')->defaultValue('%kernel.root_dir%/..')->cannotBeEmpty()->end() + ->end() ; } - protected function addSshSection(NodeBuilder $node) + protected function addSshSection(ArrayNodeDefinition $node) { - $node - ->arrayNode('rsync') + $node->children() + ->arrayNode('ssh')->children() ->scalarNode('pubkey_file')->defaultNull()->end() ->scalarNode('privkey_file')->defaultNull()->end() - ->scalarNode('passpharse')->defaultNull()->end() + ->scalarNode('passphrase')->defaultNull()->end() ->end() ; } - protected function addRulesSection(NodeBuilder $node) + protected function addRulesSection(ArrayNodeDefinition $node) { - $node + $node->children() ->arrayNode('rules') ->useAttributeAsKey('name') - ->prototype('array') - ->arrayNode('ignore')->defaultValue(array())->end() - ->arrayNode('force')->defaultValue(array())->end() + ->prototype('array')->children() + ->arrayNode('ignore')->defaultValue(array())->ignoreExtraKeys()->end() + ->arrayNode('force')->defaultValue(array())->ignoreExtraKeys()->end() ->end() ->end() ; } - protected function addCommandsSection(NodeBuilder $node) + protected function addCommandsSection(ArrayNodeDefinition $node) { - $node + $node->children() ->arrayNode('commands') + ->useAttributeAsKey('name') + ->children() ->scalarNode('command')->defaultValue('./app/console')->cannotBeEmpty()->end() - ->useAttributeAsKey('name') - ->prototype('array') - ->arrayNode('type')->defaultValue('symfony')->end() - ->arrayNode('command')->isRequired()->cannotBeEmpty()->end() - ->arrayNode('env')->defaultNull()->end() - ->end() + ->end() + ->prototype('array')->children() + ->scalarNode('type')->defaultValue('symfony')->end() + ->scalarNode('command')->isRequired()->cannotBeEmpty()->end() + ->scalarNode('env')->defaultNull()->end() ->end() ; } - protected function addServersSection(NodeBuilder $node) + protected function addServersSection(ArrayNodeDefinition $node) { - $node + $node->children() ->arrayNode('servers') ->useAttributeAsKey('name') - ->prototype('array') + ->prototype('array')->children() ->scalarNode('host')->defaultValue('localhost')->end() ->scalarNode('rsync_port')->defaultNull()->end() ->scalarNode('ssh_port')->defaultValue(22)->cannotBeEmpty()->end() ->scalarNode('username')->defaultNull()->end() ->scalarNode('password')->defaultNull()->end() ->scalarNode('path')->isRequired()->cannotBeEmpty()->end() - ->arrayNode('rules')->defaultValue(array())->end() - ->arrayNode('commands')->defaultValue(array())->end() + ->arrayNode('rules')->defaultValue(array())->ignoreExtraKeys()->end() + ->arrayNode('commands')->defaultValue(array())->ignoreExtraKeys()->end() ->end() ->end() ; } -} \ No newline at end of file +} diff --git a/Deployer/Config.php b/Deployer/Config.php index 019c465..1255011 100755 --- a/Deployer/Config.php +++ b/Deployer/Config.php @@ -1,6 +1,6 @@ rules = $rules; $this->commands = $commands; $this->servers = $servers; - $this->config = $config; + $this->config = array(); } public function getServerNames() @@ -22,26 +22,26 @@ public function getServerNames() return array_keys($this->servers); } - public function getSeverConfig($name) + public function getServerConfig($server) { - if (!isset($this->servers[$name])) { - throw new \InvalidArgumentException(sprintf('Server "%s" not configured', $name)); + if (!isset($this->servers[$server])) { + throw new \InvalidArgumentException(sprintf('Server "%s" not configured', $server)); } - if (!isset($this->config[$name])) { - $this->config[$name] = array( - 'connection' => $this->getConnectionConfig($this->server[$name]), - 'rules' => $this->getRulesConfig($this->server[$name]), - 'commands' => $this->getCommandsConfig($this->server[$name]), + if (!isset($this->config[$server])) { + $this->config[$server] = array( + 'connection' => $this->getConnectionConfig($server), + 'rules' => $this->getRulesConfig($server), + 'commands' => $this->getCommandsConfig($server), ); } - return $this->config[$name]; + return $this->config[$server]; } protected function getConnectionConfig($server) { - $config = $this->server[$server]; + $config = $this->servers[$server]; unset($config['rules'], $config['commands']); return $config; @@ -56,7 +56,7 @@ protected function getRulesConfig($server) $parameters = array_keys($config); - foreach ($this->server[$server]['rules'] as $name) { + foreach ($this->servers[$server]['rules'] as $name) { if (!isset($this->rules[$name])) { throw new \InvalidArgumentException(sprintf('Rule "%s" declared in server "%s" is not configured', $name, $server)); } @@ -73,7 +73,7 @@ protected function getCommandsConfig($server) { $config = array(); - foreach ($this->server[$server]['commands'] as $name) { + foreach ($this->servers[$server]['commands'] as $name) { if (!isset($this->commands[$name])) { throw new \InvalidArgumentException(sprintf('Command "%s" declared in server "%s" is not configured', $name, $server)); } @@ -83,4 +83,4 @@ protected function getCommandsConfig($server) return $config; } -} \ No newline at end of file +} diff --git a/Deployer/Deployer.php b/Deployer/Deployer.php index efc7315..20d01ec 100755 --- a/Deployer/Deployer.php +++ b/Deployer/Deployer.php @@ -1,8 +1,8 @@ rsync = $rsync; $this->ssh = $ssh; @@ -48,14 +48,15 @@ protected function call($server = null, $real = false) } catch(\Exception $e) { - $this->dispatchEvent('error', array('server' => $server, 'method' => $method, 'exception' => $e)); + throw $e; + //$this->dispatchEvent('error', array('server' => $server, 'method' => $method, 'exception' => $e)); } - $this->dispatchEvent('success', array('server' => $server, 'real' => $real, 'rsync' => $rsync, 'ssh' => $ssh)); + //$this->dispatchEvent('success', array('server' => $server, 'real' => $real, 'rsync' => $rsync, 'ssh' => $ssh)); } protected function dispatchEvent($name, array $parameters) { - $this->eventDispatcher->notify(new Event($this, 'besimple_deployment.'.$name, $parameters)); + //$this->eventDispatcher->notify(new Event($this, 'besimple_deployment.'.$name, $parameters)); } -} \ No newline at end of file +} diff --git a/Deployer/Rsync.php b/Deployer/Rsync.php index d1ae654..d4bdbbe 100644 --- a/Deployer/Rsync.php +++ b/Deployer/Rsync.php @@ -2,7 +2,7 @@ namespace BeSimple\DeploymentBundle\Deployer; -use Symfony\Bundle\FrameworkBundle\EventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Process\Process; @@ -15,7 +15,7 @@ class Rsync protected $stdout; protected $callback; - public function __construct(Logger $logger, EventDispatcher $eventDispatcher, array $config) + public function __construct(Logger $logger, EventDispatcherInterface $eventDispatcher, array $config) { $this->logger = $logger; $this->eventDispatcher = $eventDispatcher; @@ -52,7 +52,8 @@ public function run(array $connection, array $rules, $real = false) } $command = $this->buildCommand($connection, $rules, $real); - $process = new Process($commant, $root); + echo $command; + $process = new Process($command, $root); $this->stderr = array(); $this->stdout = array(); @@ -60,7 +61,7 @@ public function run(array $connection, array $rules, $real = false) $code = $process->run(array($this, 'onStdLine')); if ($code !== 0) { - throw new \RuntimeErrorException($this->stderr, $process->getExitCode()); + throw new \Exception($this->stderr, $process->getExitCode()); } return $this->stdout; @@ -74,7 +75,7 @@ public function onStdLine($type, $line) $this->stderr = $line; } - $this->eventDispatcher->notify(new Event($this, 'besimple_deployer.rsync', array('line' => $line, 'type' => $type))); + //$this->eventDispatcher->notify(new Event($this, 'besimple_deployer.rsync', array('line' => $line, 'type' => $type))); } protected function buildCommand(array $connection, array $rules, $real = false) @@ -82,18 +83,19 @@ protected function buildCommand(array $connection, array $rules, $real = false) $source = '.'; $user = $connection['username'] ? $connection['username'].'@' : ''; $destination = sprintf('%s%s:%s', $user, $connection['host'], $connection['path']); - $options = $this->config['options']; + $options = array(); + $options[] = $this->config['options']; - if ($connection['port']) { + if (!empty($connection['port'])) { $options[] = '-p '.$connection['port']; } - if ($this->options['delete']) { + if ($this->config['delete']) { $options[] = '--delete'; } if (count($rules)) { - $options[] = '-f +*'; + $options[] = "--filter='+ *'"; foreach ($rules['ignore'] as $mask) { $options[] = sprintf('-f -%s', $mask); @@ -104,6 +106,6 @@ protected function buildCommand(array $connection, array $rules, $real = false) } } - return sprintf('%s -e ssh %s %s %s', $this->config['command'], implode(' ', $options), $source, $detination); + return sprintf('%s -e ssh %s %s %s', $this->config['command'], implode(' ', $options), $source, $destination); } -} \ No newline at end of file +} diff --git a/Deployer/Ssh.php b/Deployer/Ssh.php index 0ce7b63..37106cd 100644 --- a/Deployer/Ssh.php +++ b/Deployer/Ssh.php @@ -2,22 +2,25 @@ namespace BeSimple\DeploymentBundle\Deployer; +use Symfony\Component\DependencyInjection\ContainerInterface; + class Ssh { protected $logger; - protected $config; + protected $container; protected $session; protected $shell; protected $stdout; protected $stderr; - public function __construct(Logger $logger, array $config) + public function __construct(Logger $logger, ContainerInterface $container) { $this->logger = $logger; - $this->config = $config; + $this->container = $container; $this->session = null; $this->stdout = array(); $this->stdin = array(); + $this->stderr = array(); } public function getStdout($glue = "\n") @@ -41,7 +44,7 @@ public function getStderr($glue = "\n") public function run(array $connection, array $commands, $real = false) { $this->connect($connection); - $this->execute(sprintf('cd %s', $connection['path'])); + $this->execute(array('type' => 'shell', 'command' => sprintf('cd %s', $connection['path']))); if ($real) { foreach ($commands as $command) { @@ -62,7 +65,7 @@ protected function connect(array $connection) throw new \InvalidArgumentException(sprintf('SSH connection failed on "%s:%s"', $connection['host'], $connection['ssh_port'])); } - if ($connection['username'] && $connection['pubkey_file'] && $connection['privkey_file']) { + if (isset($connection['username']) && isset($connection['pubkey_file']) && isset($connection['privkey_file'])) { if (!ssh2_auth_pubkey_file($connection['username'], $connection['pubkey_file'], $connection['privkey_file'], $connection['passphrase'])) { throw new \InvalidArgumentException(sprintf('SSH authentication failed for user "%s" with public key "%s"', $connection['username'], $connection['pubkey_file'])); } @@ -72,7 +75,7 @@ protected function connect(array $connection) } } - $this->shell = ssh2_shell($this->session, $this->config['shell']); + $this->shell = ssh2_shell($this->session); if (!$this->shell) { throw new \RuntimeException(sprintf('Failed opening "%s" shell', $this->config['shell'])); @@ -91,8 +94,8 @@ protected function execute(array $command) { $command = $this->buildCommand($command); - $outStream = ssh2_exec($connection, $command); - $errStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR); + $outStream = ssh2_exec($this->session, $command); + $errStream = ssh2_fetch_stream($outStream, SSH2_STREAM_STDERR); stream_set_blocking($outStream, true); stream_set_blocking($errStream, true); @@ -100,10 +103,12 @@ protected function execute(array $command) $stdout = explode("\n", stream_get_contents($outStream)); $stderr = explode("\n", stream_get_contents($errStream)); - $this->dispatch('command', array('stdout' => stdout, 'stderr' => $stderr)); + //$this->dispatch('command', array('stdout' => stdout, 'stderr' => $stderr)); $this->stdout = array_merge($this->stdout, $stdout); - $this->stderr = array_merge($this->stderr, $stderr); + if (is_array($stderr)) { + $this->stderr = array_merge($this->stderr, $stderr); + } fclose($outStream); fclose($errStream); @@ -120,4 +125,4 @@ protected function buildCommand(array $command) return sprintf('%s %s --env="%s"', $symfony, $command['command'], $env); } -} \ No newline at end of file +} diff --git a/DeploymentBundle.php b/DeploymentBundle.php deleted file mode 100755 index 8545c9d..0000000 --- a/DeploymentBundle.php +++ /dev/null @@ -1,9 +0,0 @@ - - + xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - BeSimple\DeploymentBundle\Deployer\Rsync - BeSimple\DeploymentBundle\Deployer\Ssh - BeSimple\DeploymentBundle\Deployer\Config - BeSimple\DeploymentBundle\Deployer\Logger - BeSimple\DeploymentBundle\Deployer\Deployer + BeSimple\DeploymentBundle\Deployer\Rsync + BeSimple\DeploymentBundle\Deployer\Ssh + BeSimple\DeploymentBundle\Deployer\Config + BeSimple\DeploymentBundle\Deployer\Logger + BeSimple\DeploymentBundle\Deployer\Deployer - - + + - %besimple_deployment.config.rsync% + %be_simple_deployment.config.rsync% - - - - %besimple_deployment.config.ssh% + + + + %be_simple_deployment.config.ssh% - - %besimple_deployment.config.rules% - %besimple_deployment.config.commands% - %besimple_deployment.config.servers% + + %be_simple_deployment.config.rules% + %be_simple_deployment.config.commands% + %be_simple_deployment.config.servers% - + - - - + + + + - \ No newline at end of file +