Esempio n. 1
0
 /**
  * Cleanup old releases by listing all releases and keeping a configurable
  * number of old releases (application option "keepReleases"). The current
  * and previous release (if one exists) are protected from removal.
  *
  * Example configuration:
  *
  *     $application->setOption('keepReleases', 2);
  *
  * Note: There is no rollback for this cleanup, so we have to be sure not to delete any
  *       live or referenced releases.
  *
  * @param \TYPO3\Surf\Domain\Model\Node $node
  * @param \TYPO3\Surf\Domain\Model\Application $application
  * @param \TYPO3\Surf\Domain\Model\Deployment $deployment
  * @param array $options
  * @return void
  */
 public function execute(Node $node, Application $application, Deployment $deployment, array $options = array())
 {
     if (!isset($options['keepReleases'])) {
         $deployment->getLogger()->debug(($deployment->isDryRun() ? 'Would keep' : 'Keeping') . ' all releases for "' . $application->getName() . '"');
         return;
     }
     $keepReleases = $options['keepReleases'];
     $releasesPath = $application->getReleasesPath();
     $currentReleaseIdentifier = $deployment->getReleaseIdentifier();
     $previousReleasePath = $application->getReleasesPath() . '/previous';
     $previousReleaseIdentifier = trim($this->shell->execute("if [ -h {$previousReleasePath} ]; then basename `readlink {$previousReleasePath}` ; fi", $node, $deployment));
     $allReleasesList = $this->shell->execute("if [ -d {$releasesPath}/. ]; then find {$releasesPath}/. -maxdepth 1 -type d -exec basename {} \\; ; fi", $node, $deployment);
     $allReleases = preg_split('/\\s+/', $allReleasesList, -1, PREG_SPLIT_NO_EMPTY);
     $removableReleases = array();
     foreach ($allReleases as $release) {
         if ($release !== '.' && $release !== $currentReleaseIdentifier && $release !== $previousReleaseIdentifier && $release !== 'current' && $release !== 'previous') {
             $removableReleases[] = trim($release);
         }
     }
     sort($removableReleases);
     $removeReleases = array_slice($removableReleases, 0, count($removableReleases) - $keepReleases);
     $removeCommand = '';
     foreach ($removeReleases as $removeRelease) {
         $removeCommand .= "rm -rf {$releasesPath}/{$removeRelease};rm -f {$releasesPath}/{$removeRelease}REVISION;";
     }
     if (count($removeReleases) > 0) {
         $deployment->getLogger()->info(($deployment->isDryRun() ? 'Would remove' : 'Removing') . ' releases ' . implode(', ', $removeReleases));
         $this->shell->executeOrSimulate($removeCommand, $node, $deployment);
     } else {
         $deployment->getLogger()->info('No releases to remove');
     }
 }
Esempio n. 2
0
 /**
  * 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);
 }
Esempio n. 3
0
 /**
  * @param Node $node
  * @param Application $application
  * @param Deployment $deployment
  * @param array $options
  * @throws \TYPO3\Flow\Http\Client\InfiniteRedirectionException
  */
 protected function executeOrSimulate(Node $node, Application $application, Deployment $deployment, array $options = array())
 {
     if (empty($options['clearPhpCacheUris'])) {
         return;
     }
     $uris = is_array($options['clearPhpCacheUris']) ? $options['clearPhpCacheUris'] : array($options['clearPhpCacheUris']);
     foreach ($uris as $uri) {
         $deployment->getLogger()->log('... (localhost): curl "' . $uri . '"', LOG_DEBUG);
         if ($deployment->isDryRun() === FALSE) {
             $this->browser->request($uri);
         }
     }
 }
Esempio n. 4
0
 /**
  * Execute this task
  *
  * @param \TYPO3\Surf\Domain\Model\Node $node
  * @param \TYPO3\Surf\Domain\Model\Application $application
  * @param \TYPO3\Surf\Domain\Model\Deployment $deployment
  * @param array $options Supported options: "baseUrl" (required) and "scriptIdentifier" (is passed by the create script task)
  * @return void
  * @throws \TYPO3\Surf\Exception\InvalidConfigurationException
  * @throws \TYPO3\Surf\Exception\TaskExecutionException
  */
 public function execute(Node $node, Application $application, Deployment $deployment, array $options = array())
 {
     if (!isset($options['baseUrl'])) {
         throw new \TYPO3\Surf\Exception\InvalidConfigurationException('No "baseUrl" option provided for WebOpcacheResetExecuteTask', 1421932609);
     }
     if (!isset($options['scriptIdentifier'])) {
         throw new \TYPO3\Surf\Exception\InvalidConfigurationException('No "scriptIdentifier" option provided for WebOpcacheResetExecuteTask, make sure to execute "TYPO3\\Surf\\Task\\Php\\WebOpcacheResetCreateScriptTask" before this task or pass one explicitly', 1421932610);
     }
     $scriptIdentifier = $options['scriptIdentifier'];
     $scriptUrl = rtrim($options['baseUrl'], '/') . '/surf-opcache-reset-' . $scriptIdentifier . '.php';
     $result = file_get_contents($scriptUrl);
     if ($result !== 'success') {
         $deployment->getLogger()->warning('Executing PHP opcache reset script at "' . $scriptUrl . '" did not return expected result');
     }
 }
 /**
  * Execute this task
  *
  * @param \TYPO3\Surf\Domain\Model\Node $node
  * @param \TYPO3\Surf\Domain\Model\Application $application
  * @param \TYPO3\Surf\Domain\Model\Deployment $deployment
  * @param array $options
  * @return void
  * @throws \TYPO3\Surf\Exception\InvalidConfigurationException
  */
 public function execute(Node $node, Application $application, Deployment $deployment, array $options = array())
 {
     if (!$node->getOption('webBaseUrl')) {
         throw new \InvalidArgumentException('The webBaseUrl option must be set in all nodes for which the ClearOpcacheTask should be executed.');
     }
     if (empty($options['deployutilsToken'])) {
         throw new \InvalidArgumentException('The deployutilsToken option is missing.');
     }
     $url = rtrim($node->getOption('webBaseUrl'), '/') . '/typo3conf/ext/deployutils/Resources/Php/ClearOpcache.php?token=';
     $deployment->getLogger()->debug('Calling opcache clearing script at: ' . $url . 'xxx');
     $url = $url . urlencode($options['deployutilsToken']);
     $result = $this->executeLocalCurlRequest($url, 5);
     $this->assertExpectedStatus(['expectedStatus' => 200], $result);
     $this->assertExpectedRegexp(['expectedRegexp' => '/success/'], $result);
 }
 /**
  * Executes this task
  *
  * @param Node $node
  * @param Application $application
  * @param Deployment $deployment
  * @param array $options
  * @throws TaskExecutionException
  * @return void
  */
 public function execute(Node $node, Application $application, Deployment $deployment, array $options = array())
 {
     if ($node->isLocalhost()) {
         $deployment->getLogger()->log('node seems not to be a remote node', LOG_DEBUG);
     } else {
         $username = $node->hasOption('username') ? $node->getOption('username') : NULL;
         if (!empty($username)) {
             $username = $username . '@';
         }
         $hostname = $node->getHostname();
         $sshOptions = array('-A', '-q', '-o BatchMode=yes');
         if ($node->hasOption('port')) {
             $sshOptions[] = '-p ' . escapeshellarg($node->getOption('port'));
         }
         $command = 'ssh ' . implode(' ', $sshOptions) . ' ' . escapeshellarg($username . $hostname) . ' exit;';
         $this->shell->execute($command, $deployment->getNode('localhost'), $deployment);
         $deployment->getLogger()->log('SSH connection successfully established', LOG_DEBUG);
     }
 }
Esempio n. 7
0
 /**
  * Execute this task
  *
  * @param Node $node
  * @param Application $application
  * @param Deployment $deployment
  * @param array $options
  * @return void
  * @throws InvalidConfigurationException
  */
 public function execute(Node $node, Application $application, Deployment $deployment, array $options = array())
 {
     if (!$application instanceof FlowApplication) {
         throw new InvalidConfigurationException(sprintf('Flow application needed for MigrateTask, got "%s"', get_class($application)), 1429774224);
     }
     if (!isset($options['flushCacheList']) || trim($options['flushCacheList']) === '') {
         throw new InvalidConfigurationException('Missing option "flushCacheList" for FlushCacheListTask', 1429774229);
     }
     if ($application->getVersion() >= '2.3') {
         $caches = is_array($options['flushCacheList']) ? $options['flushCacheList'] : explode(',', $options['flushCacheList']);
         $targetPath = $deployment->getApplicationReleasePath($application);
         foreach ($caches as $cache) {
             $deployment->getLogger()->debug(sprintf('Flush cache with identifier "%s"', $cache));
             $this->shell->executeOrSimulate('cd ' . $targetPath . ' && ' . 'FLOW_CONTEXT=' . $application->getContext() . ' ./' . $application->getFlowScriptName() . ' ' . sprintf('typo3.flow:cache:flushone --identifier %s', $cache), $node, $deployment);
         }
     } else {
         throw new InvalidConfigurationException(sprintf('FlushCacheListTask is available since Flow Framework 2.3, your application version is "%s"', $application->getVersion()), 1434126060);
     }
 }
Esempio n. 8
0
 /**
  * Execute a task and consider configured before / after "hooks"
  *
  * Will also execute tasks that are registered to run before or after this task.
  *
  * @param string $task
  * @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 $callstack
  * @return void
  * @throws \TYPO3\Surf\Exception\TaskExecutionException
  */
 protected function executeTask($task, Node $node, Application $application, Deployment $deployment, $stage, array &$callstack = array())
 {
     foreach (array('_', $application->getName()) as $applicationName) {
         if (isset($this->tasks['before'][$applicationName][$task])) {
             foreach ($this->tasks['before'][$applicationName][$task] as $beforeTask) {
                 $deployment->getLogger()->debug('Task "' . $beforeTask . '" before "' . $task);
                 $this->executeTask($beforeTask, $node, $application, $deployment, $stage, $callstack);
             }
         }
     }
     if (isset($callstack[$task])) {
         throw new \TYPO3\Surf\Exception\TaskExecutionException('Cycle for task "' . $task . '" detected, aborting.', 1335976544);
     }
     if (isset($this->tasks['defined'][$task])) {
         $this->taskManager->execute($this->tasks['defined'][$task]['task'], $node, $application, $deployment, $stage, $this->tasks['defined'][$task]['options'], $task);
     } else {
         $this->taskManager->execute($task, $node, $application, $deployment, $stage);
     }
     $callstack[$task] = true;
     foreach (array('_', $application->getName()) as $applicationName) {
         $label = $applicationName === '_' ? 'for all' : 'for application ' . $applicationName;
         if (isset($this->tasks['after'][$applicationName][$task])) {
             foreach ($this->tasks['after'][$applicationName][$task] as $beforeTask) {
                 $deployment->getLogger()->debug('Task "' . $beforeTask . '" after "' . $task . '" ' . $label);
                 $this->executeTask($beforeTask, $node, $application, $deployment, $stage, $callstack);
             }
         }
     }
 }
Esempio n. 9
0
 /**
  * Open a process with symfony/process and process each line by logging and
  * collecting its output.
  *
  * @param \TYPO3\Surf\Domain\Model\Deployment $deployment
  * @param string $command
  * @param bool $logOutput
  * @param string $logPrefix
  * @return array The exit code of the command and the returned output
  */
 public function executeProcess($deployment, $command, $logOutput, $logPrefix)
 {
     $process = new Process($command);
     $process->setTimeout(null);
     $callback = null;
     if ($logOutput) {
         $callback = function ($type, $data) use($deployment, $logPrefix) {
             if ($type === Process::OUT) {
                 $deployment->getLogger()->debug($logPrefix . trim($data));
             } elseif ($type === Process::ERR) {
                 $deployment->getLogger()->error($logPrefix . trim($data));
             }
         };
     }
     $exitCode = $process->run($callback);
     return array($exitCode, trim($process->getOutput()));
 }
 /**
  * Writes the given message along with the additional information into the log.
  *
  * @param string $message The message to log
  * @param integer $severity An integer value, one of the LOG_* constants
  * @param mixed $additionalData A variable containing more information about the event to be logged
  * @param string $packageKey Key of the package triggering the log (determined automatically if not specified)
  * @param string $className Name of the class triggering the log (determined automatically if not specified)
  * @param string $methodName Name of the method triggering the log (determined automatically if not specified)
  * @return void
  * @api
  */
 public function log($message, $severity = LOG_INFO, $additionalData = null, $packageKey = null, $className = null, $methodName = null)
 {
     $this->deployment->getLogger()->log($message, $severity, $additionalData, $packageKey, $className, $methodName);
 }