コード例 #1
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->validateInput($input);
     $app = $this->selectApp($input);
     $environment = $this->getSelectedEnvironment();
     $cacheKey = implode('-', ['relationships', $environment->id . $environment->project . $app]);
     $cache = CacheUtil::getCache();
     $relationships = $cache->fetch($cacheKey);
     if (empty($relationships) || $input->getOption('refresh')) {
         $util = new RelationshipsUtil($this->stdErr);
         $sshUrl = $environment->getSshUrl($app);
         $relationships = $util->getRelationships($sshUrl);
         if (empty($relationships)) {
             $this->stdErr->writeln('No relationships found');
             return 1;
         }
         $cache->save($cacheKey, $relationships, 3600);
     }
     $value = $relationships;
     $key = null;
     if ($property = $input->getOption('property')) {
         $parents = explode('.', $property);
         $key = end($parents);
         $value = Util::getNestedArrayValue($relationships, $parents, $key_exists);
         if (!$key_exists) {
             $this->stdErr->writeln("Relationship property not found: <error>{$property}</error>");
             return 1;
         }
     }
     $formatter = new PropertyFormatter();
     $formatter->yamlInline = 10;
     $output->writeln($formatter->format($value, $key));
     return 0;
 }
コード例 #2
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     if (!$this->validateInput($input, $output)) {
         return 1;
     }
     $sshUrl = $this->getSelectedEnvironment()->getSshUrl($input->getOption('app'));
     $util = new RelationshipsUtil($output);
     $relationships = $util->getRelationships($sshUrl);
     if (!$relationships) {
         $output->writeln('No relationships found');
         return 1;
     }
     foreach ($relationships as $key => $relationship) {
         foreach ($relationship as $delta => $info) {
             $output->writeln("<comment>{$key}:{$delta}:</comment>");
             foreach ($info as $prop => $value) {
                 if (is_scalar($value)) {
                     $propString = str_pad("{$prop}", 10, " ");
                     $output->writeln("<info>  {$propString}: {$value}</info>");
                 }
             }
         }
     }
     return 0;
 }
コード例 #3
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     if (!$this->validateInput($input, $output)) {
         return 1;
     }
     $sshOptions = '';
     $sshUrl = $this->getSelectedEnvironment()->getSshUrl($input->getOption('app'));
     $util = new RelationshipsUtil($output);
     $database = $util->chooseDatabase($sshUrl, $input);
     if (empty($database)) {
         return 1;
     }
     $sqlCommand = "mysql --no-auto-rehash --database={$database['path']}" . " --host={$database['host']} --port={$database['port']}" . " --user={$database['username']} --password={$database['password']}";
     $query = $input->getArgument('query');
     if ($query) {
         $sqlCommand .= ' --execute ' . escapeshellarg($query) . ' 2>&1';
     } else {
         $sshOptions .= ' -qt';
     }
     $command = 'ssh' . $sshOptions . ' ' . escapeshellarg($sshUrl) . ' ' . escapeshellarg($sqlCommand);
     if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
         $output->writeln("Running command: <info>{$command}</info>");
     }
     passthru($command, $return_var);
     return $return_var;
 }
コード例 #4
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->validateInput($input);
     $environment = $this->getSelectedEnvironment();
     $appName = $this->selectApp($input);
     $sshUrl = $environment->getSshUrl($appName);
     if (!$input->getOption('stdout')) {
         if ($input->getOption('file')) {
             $dumpFile = $input->getOption('file');
             /** @var \Platformsh\Cli\Helper\FilesystemHelper $fsHelper */
             $fsHelper = $this->getHelper('fs');
             $dumpFile = $fsHelper->makePathAbsolute($dumpFile);
             if (is_dir($dumpFile)) {
                 $dumpFile .= "/{$environment->id}-dump.sql";
             }
         } else {
             if (!($projectRoot = $this->getProjectRoot())) {
                 throw new RootNotFoundException('Project root not found. Specify --file or go to a project directory.');
             }
             $dumpFile = $projectRoot . '/' . $environment->id;
             if ($appName) {
                 $dumpFile .= '--' . $appName;
             }
             $dumpFile .= '-dump.sql';
         }
     }
     if (isset($dumpFile)) {
         if (file_exists($dumpFile)) {
             /** @var \Platformsh\Cli\Helper\PlatformQuestionHelper $questionHelper */
             $questionHelper = $this->getHelper('question');
             if (!$questionHelper->confirm("File exists: <comment>{$dumpFile}</comment>. Overwrite?", $input, $this->stdErr, false)) {
                 return 1;
             }
         }
         $this->stdErr->writeln("Creating SQL dump file: <info>{$dumpFile}</info>");
     }
     $util = new RelationshipsUtil($this->stdErr);
     $database = $util->chooseDatabase($sshUrl, $input);
     if (empty($database)) {
         return 1;
     }
     switch ($database['scheme']) {
         case 'pgsql':
             $dumpCommand = "pg_dump --clean" . " postgresql://{$database['username']}:{$database['password']}@{$database['host']}/{$database['path']}";
             break;
         default:
             $dumpCommand = "mysqldump --no-autocommit --single-transaction" . " --opt -Q {$database['path']}" . " --host={$database['host']} --port={$database['port']}" . " --user={$database['username']} --password={$database['password']}";
             break;
     }
     set_time_limit(0);
     $command = 'ssh ' . escapeshellarg($sshUrl) . ' ' . escapeshellarg($dumpCommand);
     if (isset($dumpFile)) {
         $command .= ' > ' . escapeshellarg($dumpFile);
     }
     $this->debug("Running command: <info>{$command}</info>");
     passthru($command, $return_var);
     return $return_var;
 }
コード例 #5
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     if (!$this->validateInput($input, $output)) {
         return 1;
     }
     $projectRoot = $this->getProjectRoot();
     $dumpFile = $input->getOption('file');
     if ($dumpFile !== null) {
         if (file_exists($dumpFile)) {
             $output->writeln("File exists: <error>{$dumpFile}</error>");
             return 1;
         }
         $dir = dirname($dumpFile);
         if (!is_dir($dir)) {
             $output->writeln("Directory not found: <error>{$dir}</error>");
             return 1;
         } elseif (!is_writable($dir)) {
             $output->writeln("Directory not writable: <error>{$dir}</error>");
             return 1;
         }
         $dumpFile = realpath($dir) . '/' . basename($dumpFile);
     } else {
         $dumpFile = $projectRoot . '/dump.sql';
         if (file_exists($dumpFile)) {
             $output->writeln("File exists: <error>{$dumpFile}</error>");
             return 1;
         }
     }
     $output->writeln("Creating SQL dump file: <info>{$dumpFile}</info>");
     $sshUrl = $this->getSelectedEnvironment()->getSshUrl($input->getOption('app'));
     $util = new RelationshipsUtil($output);
     $database = $util->chooseDatabase($sshUrl, $input);
     if (empty($database)) {
         return 1;
     }
     // @todo correct dump command for pgsql and other DBs
     $dumpCommand = "mysqldump --no-autocommit --single-transaction" . " --opt -Q {$database['path']}" . " --host={$database['host']} --port={$database['port']}" . " --user={$database['username']} --password={$database['password']}";
     set_time_limit(0);
     $command = 'ssh ' . escapeshellarg($sshUrl) . ' ' . escapeshellarg($dumpCommand) . ' > ' . escapeshellarg($dumpFile);
     if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
         $output->writeln("Running command: <info>{$command}</info>");
     }
     passthru($command, $return_var);
     return $return_var;
 }
コード例 #6
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->validateInput($input);
     if (!$input->getArgument('query') && $this->runningViaMulti) {
         throw new \InvalidArgumentException('The query argument is required when running via "multi"');
     }
     $sshOptions = '';
     $sshUrl = $this->getSelectedEnvironment()->getSshUrl($this->selectApp($input));
     $util = new RelationshipsUtil($this->stdErr);
     $database = $util->chooseDatabase($sshUrl, $input);
     if (empty($database)) {
         return 1;
     }
     switch ($database['scheme']) {
         case 'pgsql':
             $sqlCommand = "psql postgresql://{$database['username']}:{$database['password']}@{$database['host']}/{$database['path']}";
             $queryOption = ' -c ';
             break;
         default:
             $sqlCommand = "mysql --no-auto-rehash --database={$database['path']}" . " --host={$database['host']} --port={$database['port']}" . " --user={$database['username']} --password={$database['password']}";
             $queryOption = ' --execute ';
             break;
     }
     $query = $input->getArgument('query');
     if ($query) {
         $sqlCommand .= $queryOption . escapeshellarg($query) . ' 2>&1';
     }
     // Switch on pseudo-tty allocation when there is a local tty.
     if ($this->isTerminal($output)) {
         $sshOptions .= ' -t';
     }
     if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
         $sshOptions .= ' -vv';
     } elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) {
         $sshOptions .= ' -v';
     } elseif ($output->getVerbosity() <= OutputInterface::VERBOSITY_VERBOSE) {
         $sshOptions .= ' -q';
     }
     $command = 'ssh' . $sshOptions . ' ' . escapeshellarg($sshUrl) . ' ' . escapeshellarg($sqlCommand);
     return $this->getHelper('shell')->executeSimple($command);
 }
コード例 #7
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->validateInput($input);
     $sshOptions = '';
     $sshUrl = $this->getSelectedEnvironment()->getSshUrl($input->getOption('app'));
     $util = new RelationshipsUtil($this->stdErr);
     $database = $util->chooseDatabase($sshUrl, $input);
     if (empty($database)) {
         return 1;
     }
     switch ($database['scheme']) {
         case 'pgsql':
             $sqlCommand = "psql postgresql://{$database['username']}:{$database['password']}@{$database['host']}/{$database['path']}";
             break;
         default:
             $sqlCommand = "mysql --no-auto-rehash --database={$database['path']}" . " --host={$database['host']} --port={$database['port']}" . " --user={$database['username']} --password={$database['password']}";
             break;
     }
     $query = $input->getArgument('query');
     if ($query) {
         $sqlCommand .= ' --execute ' . escapeshellarg($query) . ' 2>&1';
     }
     // Switch on pseudo-tty allocation when there is a local tty.
     if ($this->isTerminal($output)) {
         $sshOptions .= ' -t';
     }
     if ($output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG) {
         $sshOptions .= ' -vv';
     } elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) {
         $sshOptions .= ' -v';
     } elseif ($output->getVerbosity() <= OutputInterface::VERBOSITY_VERBOSE) {
         $sshOptions .= ' -q';
     }
     $command = 'ssh' . $sshOptions . ' ' . escapeshellarg($sshUrl) . ' ' . escapeshellarg($sqlCommand);
     if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
         $this->stdErr->writeln("Running command: <info>{$command}</info>");
     }
     passthru($command, $return_var);
     return $return_var;
 }
コード例 #8
0
 /**
  * {@inheritdoc}
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->validateInput($input);
     $project = $this->getSelectedProject();
     $environment = $this->getSelectedEnvironment();
     if ($environment->id === 'master') {
         $this->stdErr->writeln('Tunnelling to the <error>master</error> environment is not safe.');
         if (count($this->getEnvironments($project)) === 1) {
             $this->stdErr->writeln('Use <info>platform branch</info> to create a new development environment.');
         }
         return 1;
     }
     $appName = $this->selectApp($input);
     $sshUrl = $environment->getSshUrl($appName);
     $util = new RelationshipsUtil($this->stdErr);
     $relationships = $util->getRelationships($sshUrl);
     if (!$relationships) {
         $this->stdErr->writeln('No relationships found.');
         return 1;
     }
     $logFile = $this->getConfigDir() . '/tunnels.log';
     if (!($log = $this->openLog($logFile))) {
         $this->stdErr->writeln(sprintf('Failed to open log file for writing: %s', $logFile));
         return 1;
     }
     $extraSshArgs = [];
     if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE) {
         $extraSshArgs[] = '-vv';
     } elseif ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
         $extraSshArgs[] = '-v';
     }
     $log->setVerbosity($output->getVerbosity());
     $processManager = new ProcessManager();
     $processManager->fork();
     $error = false;
     $processIds = [];
     foreach ($relationships as $relationship => $services) {
         foreach ($services as $serviceKey => $service) {
             $remoteHost = $service['host'];
             $remotePort = $service['port'];
             $localPort = $this->getPort();
             $tunnel = ['projectId' => $project->id, 'environmentId' => $environment->id, 'appName' => $appName, 'relationship' => $relationship, 'serviceKey' => $serviceKey, 'remotePort' => $remotePort, 'remoteHost' => $remoteHost, 'localPort' => $localPort, 'service' => $service, 'pid' => null];
             $relationshipString = $this->formatTunnelRelationship($tunnel);
             if ($openTunnelInfo = $this->isTunnelOpen($tunnel)) {
                 $this->stdErr->writeln("A tunnel is already open for the relationship: <info>{$relationshipString}</info>");
                 continue;
             }
             $process = $this->createTunnelProcess($sshUrl, $remoteHost, $remotePort, $localPort, $extraSshArgs);
             $pidFile = $this->getPidFile($tunnel);
             try {
                 $pid = $processManager->startProcess($process, $pidFile, $log);
             } catch (\Exception $e) {
                 $this->stdErr->writeln(sprintf('Failed to open tunnel for relationship <error>%s</error>: %s', $relationshipString, $e->getMessage()));
                 $error = true;
                 continue;
             }
             // Wait a very small time to capture any immediate errors.
             usleep(100000);
             if (!$process->isRunning() && !$process->isSuccessful()) {
                 $this->stdErr->writeln(trim($process->getErrorOutput()));
                 $this->stdErr->writeln(sprintf('Failed to open tunnel for relationship: <error>%s</error>', $relationshipString));
                 unlink($pidFile);
                 $error = true;
                 continue;
             }
             // Save information about the tunnel for use in other commands.
             $tunnel['pid'] = $pid;
             $this->tunnelInfo[] = $tunnel;
             $this->saveTunnelInfo();
             $this->stdErr->writeln(sprintf('SSH tunnel opened on port %s to relationship: <info>%s</info>', $localPort, $relationshipString));
             $processIds[] = $pid;
         }
     }
     if (count($processIds)) {
         $this->stdErr->writeln("Logs are written to: {$logFile}");
     }
     if (!$error) {
         $this->stdErr->writeln('');
         $this->stdErr->writeln("List tunnels with: <info>platform tunnels</info>");
         $this->stdErr->writeln("View tunnel details with: <info>platform tunnel:info</info>");
         $this->stdErr->writeln("Close tunnels with: <info>platform tunnel:close</info>");
     }
     $processManager->killParent($error);
     $processManager->monitor($log);
     return 0;
 }
コード例 #9
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->validateInput($input);
     $projectRoot = $this->getProjectRoot();
     if (!$projectRoot) {
         throw new RootNotFoundException();
     }
     $appName = $this->selectApp($input);
     $sshUrl = $this->getSelectedEnvironment()->getSshUrl($appName);
     // Get and parse app config.
     $app = LocalApplication::getApplication($appName, $projectRoot);
     $appConfig = $app->getConfig();
     if (empty($appConfig['relationships'])) {
         $this->stdErr->writeln('No application relationships found.');
         return 1;
     }
     $util = new RelationshipsUtil($this->stdErr);
     $database = $util->chooseDatabase($sshUrl, $input);
     if (empty($database)) {
         $this->stdErr->writeln('No database selected.');
         return 1;
     }
     // Find the database's service name in the relationships.
     $dbServiceName = false;
     foreach ($appConfig['relationships'] as $relationshipName => $relationship) {
         if ($database['_relationship_name'] === $relationshipName) {
             list($dbServiceName, ) = explode(':', $relationship, 2);
             break;
         }
     }
     if (!$dbServiceName) {
         $this->stdErr->writeln('Service name not found for relationship: ' . $database['_relationship_name']);
         return 1;
     }
     // Load services yaml.
     $services = Yaml::parse(file_get_contents($projectRoot . '/.platform/services.yaml'));
     if (!empty($services[$dbServiceName]['disk'])) {
         $allocatedDisk = $services[$dbServiceName]['disk'];
     } else {
         $this->stdErr->writeln('The allocated disk size could not be determined for service: ' . $dbServiceName);
         return 1;
     }
     $this->stdErr->write('Querying database <comment>' . $dbServiceName . '</comment> to estimate disk usage. ');
     $this->stdErr->writeln('This might take a while.');
     /** @var ShellHelper $shellHelper */
     $shellHelper = $this->getHelper('shell');
     $command = ['ssh'];
     $command[] = $sshUrl;
     switch ($database['scheme']) {
         case 'pgsql':
             $command[] = $this->psqlQuery($database);
             $result = $shellHelper->execute($command);
             $resultArr = explode(PHP_EOL, $result);
             $estimatedUsage = array_sum($resultArr) / 1048576;
             break;
         default:
             $command[] = $this->mysqlQuery($database);
             $estimatedUsage = $shellHelper->execute($command);
             break;
     }
     $percentsUsed = $estimatedUsage * 100 / $allocatedDisk;
     $table = new Table($input, $output);
     $propertyNames = ['max', 'used', 'percent_used'];
     $machineReadable = $table->formatIsMachineReadable();
     $values = [(int) $allocatedDisk . ($machineReadable ? '' : 'MB'), (int) $estimatedUsage . ($machineReadable ? '' : 'MB'), (int) $percentsUsed . '%'];
     $table->renderSimple($values, $propertyNames);
     return 0;
 }
コード例 #10
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->validateInput($input);
     $project = $this->getSelectedProject();
     $environment = $this->getSelectedEnvironment();
     $appName = $this->selectApp($input);
     $sshUrl = $environment->getSshUrl($appName);
     $timestamp = $input->getOption('timestamp') ? str_replace('+', '', date('Ymd-His-O')) : null;
     if (!$input->getOption('stdout')) {
         if ($input->getOption('file')) {
             $dumpFile = rtrim($input->getOption('file'), '/');
             /** @var \Platformsh\Cli\Helper\FilesystemHelper $fsHelper */
             $fsHelper = $this->getHelper('fs');
             // Insert the timestamp into the filename.
             if ($timestamp) {
                 $basename = basename($dumpFile);
                 $prefix = substr($dumpFile, 0, -strlen($basename));
                 if ($dotPos = strrpos($basename, '.')) {
                     $basename = substr($basename, 0, $dotPos) . '--' . $timestamp . substr($basename, $dotPos);
                 } else {
                     $basename .= '--' . $timestamp;
                 }
                 $dumpFile = $prefix . $basename;
             }
             // Make the filename absolute.
             $dumpFile = $fsHelper->makePathAbsolute($dumpFile);
             // Ensure the filename is not a directory.
             if (is_dir($dumpFile)) {
                 $dumpFile .= '/' . $this->getDefaultDumpFilename($project, $environment, $appName, $timestamp);
             }
         } else {
             $projectRoot = $this->getProjectRoot();
             $directory = $projectRoot ?: getcwd();
             $dumpFile = $directory . '/' . $this->getDefaultDumpFilename($project, $environment, $appName, $timestamp);
         }
     }
     if (isset($dumpFile)) {
         if (file_exists($dumpFile)) {
             /** @var \Platformsh\Cli\Helper\QuestionHelper $questionHelper */
             $questionHelper = $this->getHelper('question');
             if (!$questionHelper->confirm("File exists: <comment>{$dumpFile}</comment>. Overwrite?", false)) {
                 return 1;
             }
         }
         $this->stdErr->writeln("Creating SQL dump file: <info>{$dumpFile}</info>");
     }
     $util = new RelationshipsUtil($this->stdErr);
     $database = $util->chooseDatabase($sshUrl, $input);
     if (empty($database)) {
         return 1;
     }
     switch ($database['scheme']) {
         case 'pgsql':
             $dumpCommand = "pg_dump --clean" . " postgresql://{$database['username']}:{$database['password']}@{$database['host']}/{$database['path']}";
             break;
         default:
             $dumpCommand = "mysqldump --no-autocommit --single-transaction" . " --opt -Q {$database['path']}" . " --host={$database['host']} --port={$database['port']}" . " --user={$database['username']} --password={$database['password']}";
             break;
     }
     set_time_limit(0);
     $command = 'ssh -C ' . escapeshellarg($sshUrl) . ' ' . escapeshellarg($dumpCommand);
     if (isset($dumpFile)) {
         $command .= ' > ' . escapeshellarg($dumpFile);
     }
     return $this->getHelper('shell')->executeSimple($command);
 }