/** * Execute a task * * @param string $taskName * @param \TYPO3\Surf\Domain\Model\Node $node * @param \TYPO3\Surf\Domain\Model\Application $application * @param \TYPO3\Surf\Domain\Model\Deployment $deployment * @param string $stage * @param array $options Local task options * @return void * @throws \TYPO3\Surf\Exception\InvalidConfigurationException */ public function execute($taskName, Node $node, Application $application, Deployment $deployment, $stage, array $options = array()) { $deployment->getLogger()->info($node->getName() . ' (' . $application->getName() . ') ' . $taskName); $task = $this->createTaskInstance($taskName); $globalOptions = $this->overrideOptions($taskName, $deployment, $node, $application, $options); if (!$deployment->isDryRun()) { $task->execute($node, $application, $deployment, $globalOptions); } else { $task->simulate($node, $application, $deployment, $globalOptions); } $this->taskHistory[] = array('task' => $task, 'node' => $node, 'application' => $application, 'deployment' => $deployment, 'stage' => $stage, 'options' => $globalOptions); }
/** * Executes this task * * @param Node $node * @param Application $application * @param Deployment $deployment * @param array $options * @return void * @throws InvalidConfigurationException * @throws TaskExecutionException */ public function execute(Node $node, Application $application, Deployment $deployment, array $options = array()) { if (!empty($options['disableDeploymentTag'])) { return; } if (isset($options['useApplicationWorkspace']) && $options['useApplicationWorkspace'] === TRUE) { $gitRootPath = $deployment->getWorkspacePath($application); } else { $gitRootPath = $deployment->getApplicationReleasePath($application); } $tagPrefix = isset($options['deploymentTagPrefix']) ? $options['deploymentTagPrefix'] : 'server-'; $tagName = preg_replace('/[^a-zA-Z0-9-_\\.]*/', '', $tagPrefix . $node->getName()); $quietFlag = isset($options['verbose']) && $options['verbose'] ? '' : '-q'; if (!empty($options['nodeName'])) { $node = $deployment->getNode($options['nodeName']); if ($node === NULL) { throw new InvalidConfigurationException(sprintf('Node "%s" not found', $options['nodeName']), 1408441582); } } $commands = array('cd ' . escapeshellarg($gitRootPath), 'git tag --force -- ' . escapeshellarg($tagName), 'git push origin --force ' . $quietFlag . ' -- ' . escapeshellarg($tagName)); $this->shell->executeOrSimulate($commands, $node, $deployment); }
/** * Return TRUE if the given node is registered for this application * * @param Node $node The node to test * @return bool TRUE if the node is registered for this application */ public function hasNode(Node $node) { return isset($this->nodes[$node->getName()]); }
/** * Execute a stage for a node and application * * @param string $stage * @param \TYPO3\Surf\Domain\Model\Node $node * @param \TYPO3\Surf\Domain\Model\Application $application * @param \TYPO3\Surf\Domain\Model\Deployment $deployment * @return void */ protected function executeStage($stage, Node $node, Application $application, Deployment $deployment) { foreach (array('before', 'tasks', 'after') as $stageStep) { foreach (array('_', $application->getName()) as $applicationName) { $label = $applicationName === '_' ? 'for all' : 'for application ' . $applicationName; if (isset($this->tasks['stage'][$applicationName][$stage][$stageStep])) { $deployment->getLogger()->debug('Executing stage "' . $stage . '" (step "' . $stageStep . '") on "' . $node->getName() . '" ' . $label); foreach ($this->tasks['stage'][$applicationName][$stage][$stageStep] as $task) { $this->executeTask($task, $node, $application, $deployment, $stage); } } } } }
/** * Execute a shell command via SSH * * @param mixed $command * @param \TYPO3\Surf\Domain\Model\Node $node * @param \TYPO3\Surf\Domain\Model\Deployment $deployment * @param bool $logOutput TRUE if the output of the command should be logged * @return array */ protected function executeRemoteCommand($command, Node $node, Deployment $deployment, $logOutput = true) { $command = $this->prepareCommand($command); $deployment->getLogger()->debug('$' . $node->getName() . ': "' . $command . '"'); if ($node->hasOption('remoteCommandExecutionHandler')) { $remoteCommandExecutionHandler = $node->getOption('remoteCommandExecutionHandler'); /** @var $remoteCommandExecutionHandler callable */ return $remoteCommandExecutionHandler($this, $command, $node, $deployment, $logOutput); } $username = $node->hasOption('username') ? $node->getOption('username') : null; if (!empty($username)) { $username = $username . '@'; } $hostname = $node->getHostname(); // TODO Get SSH options from node or deployment $sshOptions = array('-A'); if ($node->hasOption('port')) { $sshOptions[] = '-p ' . escapeshellarg($node->getOption('port')); } if ($node->hasOption('password')) { $sshOptions[] = '-o PubkeyAuthentication=no'; } if ($node->hasOption('privateKeyFile')) { $sshOptions[] = '-i ' . escapeshellarg($node->getOption('privateKeyFile')); } $sshCommand = 'ssh ' . implode(' ', $sshOptions) . ' ' . escapeshellarg($username . $hostname) . ' ' . escapeshellarg($command); if ($node->hasOption('password')) { $passwordSshLoginScriptPathAndFilename = Files::concatenatePaths(array(dirname(dirname(dirname(__DIR__))), 'Resources', 'Private/Scripts/PasswordSshLogin.expect')); if (\Phar::running() !== '') { $passwordSshLoginScriptContents = file_get_contents($passwordSshLoginScriptPathAndFilename); $passwordSshLoginScriptPathAndFilename = Files::concatenatePaths(array($deployment->getTemporaryPath(), 'PasswordSshLogin.expect')); file_put_contents($passwordSshLoginScriptPathAndFilename, $passwordSshLoginScriptContents); } $sshCommand = sprintf('expect %s %s %s', escapeshellarg($passwordSshLoginScriptPathAndFilename), escapeshellarg($node->getOption('password')), $sshCommand); } $success = $this->executeProcess($deployment, $sshCommand, $logOutput, ' > '); if (isset($passwordSshLoginScriptPathAndFilename) && \Phar::running() !== '') { unlink($passwordSshLoginScriptPathAndFilename); } return $success; }
/** * Execute a shell command via SSH * * @param mixed $command * @param \TYPO3\Surf\Domain\Model\Node $node * @param \TYPO3\Surf\Domain\Model\Deployment $deployment * @param bool $logOutput TRUE if the output of the command should be logged * @return array */ protected function executeRemoteCommand($command, Node $node, Deployment $deployment, $logOutput = true) { $command = $this->prepareCommand($command); $deployment->getLogger()->debug('$' . $node->getName() . ': "' . $command . '"'); if ($node->hasOption('remoteCommandExecutionHandler')) { $remoteCommandExecutionHandler = $node->getOption('remoteCommandExecutionHandler'); /** @var $remoteCommandExecutionHandler callable */ return $remoteCommandExecutionHandler($this, $command, $node, $deployment, $logOutput); } $username = $node->hasOption('username') ? $node->getOption('username') : null; if (!empty($username)) { $username = $username . '@'; } $hostname = $node->getHostname(); // TODO Get SSH options from node or deployment $sshOptions = array('-A'); if ($node->hasOption('port')) { $sshOptions[] = '-p ' . escapeshellarg($node->getOption('port')); } if ($node->hasOption('password')) { $sshOptions[] = '-o PubkeyAuthentication=no'; } if ($node->hasOption('privateKeyFile')) { $sshOptions[] = '-i ' . escapeshellarg($node->getOption('privateKeyFile')); } $sshCommand = 'ssh ' . implode(' ', $sshOptions) . ' ' . escapeshellarg($username . $hostname) . ' ' . escapeshellarg($command); if ($node->hasOption('password')) { $resourcesPath = realpath(__DIR__ . '/../../../Resources'); $passwordSshLoginScriptPathAndFilename = $resourcesPath . '/Private/Scripts/PasswordSshLogin.expect'; $sshCommand = sprintf('expect %s %s %s', escapeshellarg($passwordSshLoginScriptPathAndFilename), escapeshellarg($node->getOption('password')), $sshCommand); } return $this->executeProcess($deployment, $sshCommand, $logOutput, ' > '); }