protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $variableName = $input->getArgument('name'); $variable = $this->getSelectedEnvironment()->getVariable($variableName); if (!$variable) { $this->stdErr->writeln("Variable not found: <error>{$variableName}</error>"); return 1; } if (!$variable->operationAvailable('delete')) { if ($variable->inherited) { $this->stdErr->writeln("The variable <error>{$variableName}</error> is inherited," . " so it cannot be deleted from this environment." . "\nYou could override it with the <comment>variable:set</comment> command."); } else { $this->stdErr->writeln("The variable <error>{$variableName}</error> cannot be deleted"); } return 1; } $environmentId = $this->getSelectedEnvironment()->id; $confirm = $this->getHelper('question')->confirm("Delete the variable <info>{$variableName}</info> from the environment <info>{$environmentId}</info>?", false); if (!$confirm) { return 1; } $result = $variable->delete(); $this->stdErr->writeln("Deleted variable <info>{$variableName}</info>"); $success = true; if (!$result->countActivities()) { $this->rebuildWarning(); } elseif (!$input->getOption('no-wait')) { $success = ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $this->getSelectedProject()); } return $success ? 0 : 1; }
protected function execute(InputInterface $input, OutputInterface $output) { if (!$this->validateInput($input, $output)) { return 1; } $selectedEnvironment = $this->getSelectedEnvironment(); $environmentId = $selectedEnvironment['id']; if (!$selectedEnvironment->operationAvailable('merge')) { $output->writeln("Operation not available: The environment <error>{$environmentId}</error> can't be merged."); return 1; } $parentId = $selectedEnvironment['parent']; if (!$this->getHelper('question')->confirm("Are you sure you want to merge <info>{$environmentId}</info> with its parent, <info>{$parentId}</info>?", $input, $output)) { return 0; } $output->writeln("Merging <info>{$environmentId}</info> with <info>{$parentId}</info>"); $activity = $selectedEnvironment->merge(); if (!$input->getOption('no-wait')) { $success = ActivityUtil::waitAndLog($activity, $output, 'Merge complete', 'Merge failed'); if (!$success) { return 1; } } // Reload the stored environments. $this->getEnvironments(null, true); return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $environment = $this->getSelectedEnvironment(); $startsAt = null; if ($input->getOption('start') && !($startsAt = strtotime($input->getOption('start')))) { $this->stdErr->writeln('Invalid date: <error>' . $input->getOption('start') . '</error>'); return 1; } $limit = (int) $input->getOption('limit'); $activities = $environment->getActivities($limit, $input->getOption('type'), $startsAt); if (!$activities) { $this->stdErr->writeln('No activities found'); return 1; } $table = new Table($input, $output); $rows = []; foreach ($activities as $activity) { $description = $activity->getDescription(); if (!$table->formatIsMachineReadable()) { $description = wordwrap($description, 40); } $rows[] = [$activity->id, date('Y-m-d H:i:s', strtotime($activity['created_at'])), $description, $activity->getCompletionPercent(), ActivityUtil::formatState($activity->state)]; } if (!$table->formatIsMachineReadable()) { $this->stdErr->writeln("Activities for the environment <info>" . $environment->id . "</info>"); } $headers = ['ID', 'Created', 'Description', '% Complete', 'State']; $table->render($rows, $headers); return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $selectedEnvironment = $this->getSelectedEnvironment(); $environmentId = $selectedEnvironment->id; if (!$selectedEnvironment->operationAvailable('merge')) { $this->stdErr->writeln("Operation not available: The environment <error>{$environmentId}</error> can't be merged."); return 1; } $parentId = $selectedEnvironment->parent; $confirmText = "Are you sure you want to merge <info>{$environmentId}</info> with its parent, <info>{$parentId}</info>?"; if (!$this->getHelper('question')->confirm($confirmText)) { return 1; } $this->stdErr->writeln("Merging <info>{$environmentId}</info> with <info>{$parentId}</info>"); $this->api()->clearEnvironmentsCache($selectedEnvironment->project); $activity = $selectedEnvironment->merge(); if (!$input->getOption('no-wait')) { $success = ActivityUtil::waitAndLog($activity, $this->stdErr, 'Merge complete', 'Merge failed'); if (!$success) { return 1; } } return 0; }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); if (!$this->validateDomainInput($input)) { return 1; } $project = $this->getSelectedProject(); $domain = $project->getDomain($this->domainName); if (!$domain) { $this->stdErr->writeln('Domain not found: <error>' . $this->domainName . '</error>'); return 1; } $needsUpdate = false; foreach (['key' => '', 'certificate' => '', 'chain' => []] as $option => $default) { if (empty($this->sslOptions[$option])) { $this->sslOptions[$option] = $domain->ssl[$option] ?: $default; } elseif ($this->sslOptions[$option] != $domain->ssl[$option]) { $needsUpdate = true; } } if (!$needsUpdate) { $this->stdErr->writeln('There is nothing to update.'); return 0; } $this->stdErr->writeln('Updating the domain <info>' . $this->domainName . '</info>'); $result = $domain->update(['ssl' => $this->sslOptions]); if (!$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $project); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $selectedEnvironment = $this->getSelectedEnvironment(); $environmentId = $selectedEnvironment->id; if (!$selectedEnvironment->operationAvailable('backup')) { $this->stdErr->writeln("Operation not available: cannot create a snapshot of <error>{$environmentId}</error>"); if ($selectedEnvironment->is_dirty) { $this->api()->clearEnvironmentsCache($selectedEnvironment->project); } return 1; } $activity = $selectedEnvironment->backup(); $this->stdErr->writeln("Creating a snapshot of <info>{$environmentId}</info>"); if (!$input->getOption('no-wait')) { $this->stdErr->writeln("Waiting for the snapshot to complete..."); $success = ActivityUtil::waitAndLog($activity, $this->stdErr, "A snapshot of environment <info>{$environmentId}</info> has been created", "The snapshot failed"); if (!$success) { return 1; } } if (!empty($activity['payload']['backup_name'])) { $name = $activity['payload']['backup_name']; $output->writeln("Snapshot name: <info>{$name}</info>"); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $variableName = $input->getArgument('name'); $variableValue = $input->getArgument('value'); $json = $input->getOption('json'); if ($json && !$this->validateJson($variableValue)) { throw new \Exception("Invalid JSON: <error>{$variableValue}</error>"); } // Check whether the variable already exists. If there is no change, // quit early. $existing = $this->getSelectedEnvironment()->getVariable($variableName); if ($existing && $existing->getProperty('value') === $variableValue && $existing->getProperty('is_json') == $json) { $this->stdErr->writeln("Variable <info>{$variableName}</info> already set as: {$variableValue}"); return 0; } // Set the variable to a new value. $result = $this->getSelectedEnvironment()->setVariable($variableName, $variableValue, $json); $this->stdErr->writeln("Variable <info>{$variableName}</info> set to: {$variableValue}"); $success = true; if (!$result->countActivities()) { $this->rebuildWarning(); } elseif (!$input->getOption('no-wait')) { $success = ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $this->getSelectedProject()); } return $success ? 0 : 1; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $project = $this->getSelectedProject(); $email = $input->getArgument('email'); $selectedUser = $this->api()->loadProjectAccessByEmail($project, $email); if (empty($selectedUser)) { $this->stdErr->writeln("User not found: <error>{$email}</error>"); return 1; } if ($project->owner === $selectedUser->id) { $this->stdErr->writeln(sprintf('The user <error>%s</error> is the owner of the project %s.', $email, $this->api()->getProjectLabel($project, 'error'))); $this->stdErr->writeln("The project's owner cannot be deleted."); return 1; } /** @var \Platformsh\Cli\Helper\QuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); if (!$questionHelper->confirm("Are you sure you want to delete the user <info>{$email}</info>?")) { return 1; } $result = $selectedUser->delete(); $this->stdErr->writeln("User <info>{$email}</info> deleted"); if (!$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $project); } // If the user was deleting themselves from the project, then invalidate // the projects cache. $myUuid = $this->api()->getMyAccount()['uuid']; if ($myUuid === $selectedUser->id) { $this->api()->clearProjectsCache(); } return 0; }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); if (!$this->validateDomainInput($input)) { return 1; } $project = $this->getSelectedProject(); try { $this->stdErr->writeln("Adding the domain <info>{$this->domainName}</info>"); $result = $project->addDomain($this->domainName, $this->sslOptions); } catch (ClientException $e) { // Catch 409 Conflict errors. $response = $e->getResponse(); if ($response && $response->getStatusCode() === 409) { $this->stdErr->writeln("The domain <error>{$this->domainName}</error> already exists on the project."); $this->stdErr->writeln("Use <info>domain:delete</info> to delete an existing domain"); } else { $this->handleApiException($e, $project); } return 1; } if (!$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); if ($input->getOption('list')) { return $this->listBackups($output); } $selectedEnvironment = $this->getSelectedEnvironment(); $environmentId = $selectedEnvironment['id']; if (!$selectedEnvironment->operationAvailable('backup')) { $this->stdErr->writeln("Operation not available: the environment <error>{$environmentId}</error> cannot be backed up"); return 1; } $activity = $selectedEnvironment->backup(); $this->stdErr->writeln("Backing up <info>{$environmentId}</info>"); if (!$input->getOption('no-wait')) { $success = ActivityUtil::waitAndLog($activity, $this->stdErr, "A backup of environment <info>{$environmentId}</info> has been created", "The backup failed"); if (!$success) { return 1; } } if (!empty($activity['payload']['backup_name'])) { $name = $activity['payload']['backup_name']; $output->writeln("Backup name: <info>{$name}</info>"); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { if (!$this->validateInput($input, $output)) { return 1; } $environment = $this->getSelectedEnvironment(); $backupName = $input->getArgument('backup'); if (!empty($backupName)) { // Find the specified backup. $backupActivities = $environment->getActivities(0, 'environment.backup'); foreach ($backupActivities as $activity) { if ($activity['payload']['backup_name'] == $backupName) { $selectedActivity = $activity; break; } } if (empty($selectedActivity)) { $output->writeln("Backup not found: <error>{$backupName}</error>"); return 1; } } else { // Find the most recent backup. $environmentId = $environment['id']; $output->writeln("Finding the most recent backup for the environment <info>{$environmentId}</info>"); $backupActivities = $environment->getActivities(1, 'environment.backup'); if (!$backupActivities) { $output->writeln("No backups found"); return 1; } /** @var \Platformsh\Client\Model\Activity $selectedActivity */ $selectedActivity = reset($backupActivities); } if (!$selectedActivity->operationAvailable('restore')) { if (!$selectedActivity->isComplete()) { $output->writeln("The backup is not complete, so it cannot be restored"); } else { $output->writeln("The backup cannot be restored"); } return 1; } /** @var \Platformsh\Cli\Helper\PlatformQuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); $name = $selectedActivity['payload']['backup_name']; $environmentId = $environment['id']; $date = date('Y-m-d H:i', strtotime($selectedActivity['created_at'])); if (!$questionHelper->confirm("Are you sure you want to restore the backup <comment>{$name}</comment> from <comment>{$date}</comment>?", $input, $output)) { return 1; } $output->writeln("Restoring backup <info>{$name}</info>"); $activity = $selectedActivity->restore(); if (!$input->getOption('no-wait')) { $success = ActivityUtil::waitAndLog($activity, $output, "The backup was successfully restored", "Restoring failed"); if (!$success) { return 1; } } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $values = $this->getForm()->resolveOptions($input, $this->stdErr, $this->getHelper('question')); $result = $this->getSelectedProject()->addIntegration($values['type'], $values); /** @var Integration $integration */ $integration = $result->getEntity(); $this->stdErr->writeln("Created integration <info>{$integration->id}</info> (type: {$values['type']})"); $success = true; if (!$input->getOption('no-wait')) { $success = ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr); } $output->writeln($this->formatIntegrationData($integration)); return $success ? 0 : 1; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input, $input->getOption('all')); $project = $this->getSelectedProject(); $startsAt = null; if ($input->getOption('start') && !($startsAt = strtotime($input->getOption('start')))) { $this->stdErr->writeln('Invalid date: <error>' . $input->getOption('start') . '</error>'); return 1; } $limit = (int) $input->getOption('limit'); if ($this->hasSelectedEnvironment() && !$input->getOption('all')) { $environmentSpecific = true; $environment = $this->getSelectedEnvironment(); $activities = $environment->getActivities($limit, $input->getOption('type'), $startsAt); } else { $environmentSpecific = false; $activities = $project->getActivities($limit, $input->getOption('type'), $startsAt); } if (!$activities) { $this->stdErr->writeln('No activities found'); return 1; } $table = new Table($input, $output); $rows = []; foreach ($activities as $activity) { $row = [new AdaptiveTableCell($activity->id, ['wrap' => false]), date('Y-m-d H:i:s', strtotime($activity['created_at'])), $activity->getDescription(), $activity->getCompletionPercent(), ActivityUtil::formatState($activity->state)]; if (!$environmentSpecific) { $row[] = implode(', ', $activity->environments); } $rows[] = $row; } $headers = ['ID', 'Created', 'Description', '% Complete', 'State']; if (!$environmentSpecific) { $headers[] = 'Environment(s)'; } if (!$table->formatIsMachineReadable()) { if ($environmentSpecific && isset($environment)) { $this->stdErr->writeln("Activities for the environment <info>" . $environment->id . "</info>"); } elseif (!$environmentSpecific) { $this->stdErr->writeln("Activities for the project <info>" . $project->id . "</info>"); } } $table->render($rows, $headers); return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $selectedEnvironment = $this->getSelectedEnvironment(); $environmentId = $selectedEnvironment->id; if (!$selectedEnvironment->operationAvailable('synchronize')) { $this->stdErr->writeln("Operation not available: The environment <error>{$environmentId}</error> can't be synchronized."); if ($selectedEnvironment->is_dirty) { $this->api()->clearEnvironmentsCache($selectedEnvironment->project); } return 1; } $parentId = $selectedEnvironment->parent; $questionHelper = $this->getHelper('question'); if ($synchronize = $input->getArgument('synchronize')) { // The input was invalid. if (array_diff($input->getArgument('synchronize'), ['code', 'data', 'both'])) { $this->stdErr->writeln("Specify 'code', 'data', or 'both'"); return 1; } $syncCode = in_array('code', $synchronize) || in_array('both', $synchronize); $syncData = in_array('data', $synchronize) || in_array('both', $synchronize); $confirmText = "Are you sure you want to synchronize <info>{$parentId}</info> to <info>{$environmentId}</info>?"; if (!$questionHelper->confirm($confirmText)) { return 1; } } else { $syncCode = $questionHelper->confirm("Synchronize code from <info>{$parentId}</info> to <info>{$environmentId}</info>?", false); $syncData = $questionHelper->confirm("Synchronize data from <info>{$parentId}</info> to <info>{$environmentId}</info>?", false); } if (!$syncCode && !$syncData) { $this->stdErr->writeln("<error>You must synchronize at least code or data.</error>"); return 1; } $this->stdErr->writeln("Synchronizing environment <info>{$environmentId}</info>"); $activity = $selectedEnvironment->synchronize($syncData, $syncCode); if (!$input->getOption('no-wait')) { $success = ActivityUtil::waitAndLog($activity, $this->stdErr, "Synchronization complete", "Synchronization failed"); if (!$success) { return 1; } } return 0; }
/** * @param Environment[] $environments * @param InputInterface $input * @param OutputInterface $output * * @return bool */ protected function activateMultiple(array $environments, InputInterface $input, OutputInterface $output) { $count = count($environments); $processed = 0; // Confirm which environments the user wishes to be activated. $process = []; $questionHelper = $this->getHelper('question'); foreach ($environments as $environment) { $environmentId = $environment->id; if ($environment->isActive()) { $output->writeln("The environment <info>{$environmentId}</info> is already active."); $count--; continue; } if (!$environment->operationAvailable('activate')) { $output->writeln("Operation not available: The environment <error>{$environmentId}</error> can't be activated."); continue; } $question = "Are you sure you want to activate the environment <info>{$environmentId}</info>?"; if (!$questionHelper->confirm($question, $input, $output)) { continue; } $process[$environmentId] = $environment; } $activities = []; /** @var Environment $environment */ foreach ($process as $environmentId => $environment) { try { $activities[] = $environment->activate(); $processed++; $output->writeln("Activating environment <info>{$environmentId}</info>"); } catch (\Exception $e) { $output->writeln($e->getMessage()); } } $success = true; if ($processed) { if (!$input->getOption('no-wait')) { $success = ActivityUtil::waitMultiple($activities, $output); } $this->clearEnvironmentsCache(); } return $processed >= $count && $success; }
/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $name = $input->getArgument('name'); $project = $this->getSelectedProject(); $domain = $project->getDomain($name); if (!$domain) { $this->stdErr->writeln("Domain not found: <error>{$name}</error>"); return 1; } if (!$this->getHelper('question')->confirm("Are you sure you want to delete the domain <info>{$name}</info>?")) { return 1; } $result = $domain->delete(); $this->stdErr->writeln("The domain <info>{$name}</info> has been deleted."); if (!$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $project); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $id = $input->getArgument('id'); $integration = $this->getSelectedProject()->getIntegration($id); if (!$integration) { $this->stdErr->writeln("Integration not found: <error>{$id}</error>"); return 1; } $type = $integration->getProperty('type'); $confirmText = "Delete the integration <info>{$id}</info> (type: {$type})?"; if (!$this->getHelper('question')->confirm($confirmText)) { return 1; } $result = $integration->delete(); $this->stdErr->writeln("Deleted integration <info>{$id}</info>"); if (!$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $this->getSelectedProject()); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $project = $this->getSelectedProject(); $email = $input->getArgument('email'); foreach ($project->getUsers() as $user) { if ($this->getAccount($user)['email'] === $email) { $selectedUser = $user; break; } } if (empty($selectedUser)) { $this->stdErr->writeln("User not found: <error>{$email}</error>"); return 1; } if ($project->owner === $selectedUser->id) { $this->stdErr->writeln("The user <error>{$email}</error> is the owner of the project <error>{$project->title}</error>."); $this->stdErr->writeln("The project's owner cannot be deleted."); return 1; } /** @var \Platformsh\Cli\Helper\PlatformQuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); if (!$questionHelper->confirm("Are you sure you want to delete the user <info>{$email}</info>?", $input, $this->stdErr)) { return 1; } $result = $selectedUser->delete(); $this->stdErr->writeln("User <info>{$email}</info> deleted"); if (!$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr); } // If the user was deleting themselves from the project, then invalidate // the projects cache. $account = $this->getClient()->getAccountInfo(); if ($account['uuid'] === $selectedUser->id) { $this->clearProjectsCache(); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $id = $input->getArgument('id'); $integration = $this->getSelectedProject()->getIntegration($id); if (!$integration) { $this->stdErr->writeln("Integration not found: <error>{$id}</error>"); return 1; } $values = []; $form = $this->getForm(); $currentValues = $integration->getProperties(); foreach ($form->getFields() as $key => $field) { $value = $field->getValueFromInput($input); if ($value !== null && $currentValues[$key] !== $value) { $values[$key] = $value; } } if (!$values) { $this->stdErr->writeln("No changed values were provided to update"); return 1; } // Complete the PATCH request with the current values. This is a // workaround: at the moment a PATCH with only the changed values will // cause a 500 error. foreach ($currentValues as $key => $currentValue) { if ($key !== 'id' && !array_key_exists($key, $values)) { $values[$key] = $currentValue; } } $result = $integration->update($values); $this->stdErr->writeln("Integration <info>{$id}</info> (<info>{$integration->type}</info>) updated"); $this->displayIntegration($integration, $input, $this->stdErr); if (!$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $this->getSelectedProject()); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->envArgName = 'parent'; $this->validateInput($input, true); $selectedProject = $this->getSelectedProject(); $branchName = $input->getArgument('name'); if (empty($branchName)) { if ($input->isInteractive()) { // List environments. return $this->runOtherCommand('environments', array('--project' => $selectedProject->id)); } $this->stdErr->writeln("<error>You must specify the name of the new branch.</error>"); return 1; } $machineName = Environment::sanitizeId($branchName); $environmentId = $this->getSelectedEnvironment()['id']; if ($machineName == $environmentId) { $this->stdErr->writeln("<comment>Already on {$machineName}</comment>"); return 1; } if ($environment = $this->getEnvironment($machineName, $selectedProject)) { $checkout = $this->getHelper('question')->confirm("The environment <comment>{$machineName}</comment> already exists. Check out?", $input, $this->stdErr); if ($checkout) { return $this->runOtherCommand('environment:checkout', array('id' => $environment->id)); } return 1; } if (!$this->getSelectedEnvironment()->operationAvailable('branch')) { $this->stdErr->writeln("Operation not available: The environment <error>{$environmentId}</error> can't be branched."); return 1; } $force = $input->getOption('force'); $projectRoot = $this->getProjectRoot(); if (!$projectRoot && $force) { $this->stdErr->writeln("<comment>This command was run from outside your local project root, the new Platform.sh branch cannot be checked out in your local Git repository." . " Make sure to run 'platform checkout' or 'git checkout' in your repository directory to switch to the branch you are expecting.</comment>"); $local_error = true; } elseif (!$projectRoot) { $this->stdErr->writeln("<error>You must run this command inside the project root, or specify --force.</error>"); return 1; } $selectedEnvironment = $this->getSelectedEnvironment(); $this->stdErr->writeln("Creating a new environment <info>{$branchName}</info>, branched from <info>{$selectedEnvironment['title']}</info>"); $activity = $selectedEnvironment->branch($branchName, $machineName); // Clear the environments cache, as branching has started. $this->clearEnvironmentsCache($selectedProject); if ($projectRoot) { $gitHelper = new GitHelper(new ShellHelper($this->stdErr)); $gitHelper->setDefaultRepositoryDir($projectRoot . '/' . LocalProject::REPOSITORY_DIR); // If the Git branch already exists locally, just check it out. $existsLocally = $gitHelper->branchExists($machineName); if ($existsLocally) { $this->stdErr->writeln("Checking out <info>{$machineName}</info> locally"); if (!$gitHelper->checkOut($machineName)) { $this->stdErr->writeln('<error>Failed to check out branch locally: ' . $machineName . '</error>'); $local_error = true; if (!$force) { return 1; } } } else { // Create a new branch, using the current or specified environment as the parent if it exists locally. $parent = $this->getSelectedEnvironment()['id']; if (!$gitHelper->branchExists($parent)) { $parent = null; } $this->stdErr->writeln("Creating local branch <info>{$machineName}</info>"); if (!$gitHelper->checkOutNew($machineName, $parent)) { $this->stdErr->writeln('<error>Failed to create branch locally: ' . $machineName . '</error>'); $local_error = true; if (!$force) { return 1; } } } } $remoteSuccess = true; if (!$input->getOption('no-wait')) { $remoteSuccess = ActivityUtil::waitAndLog($activity, $this->stdErr, "The environment <info>{$branchName}</info> has been branched.", '<error>Branching failed</error>'); // Clear the environments cache again. $this->clearEnvironmentsCache($selectedProject); } $build = $input->getOption('build'); if (empty($local_error) && $build && $projectRoot) { // Build the new branch. try { $buildSettings = array('environmentId' => $machineName, 'verbosity' => $output->getVerbosity()); $builder = new LocalBuild($buildSettings, $output); $builder->buildProject($projectRoot); } catch (\Exception $e) { $this->stdErr->writeln("<comment>The new branch could not be built: \n" . $e->getMessage() . "</comment>"); return 1; } } $this->clearEnvironmentsCache(); return $remoteSuccess ? 0 : 1; }
protected function execute(InputInterface $input, OutputInterface $output) { $level = $input->getOption('level'); $validLevels = ['project', 'environment']; if (!in_array($level, $validLevels)) { $this->stdErr->writeln("Invalid level: <error>{$level}</error>"); return 1; } $this->validateInput($input, true); $project = $this->getSelectedProject(); $email = $input->getArgument('email'); foreach ($project->getUsers() as $user) { $account = $this->getAccount($user); if ($account['email'] === $email) { $selectedUser = $user; break; } } if (empty($selectedUser)) { $this->stdErr->writeln("User not found: <error>{$email}</error>"); return 1; } $currentRole = false; $environmentAccess = false; $validRoles = ProjectAccess::$roles; if ($level == 'project') { $currentRole = $selectedUser['role']; } elseif ($level == 'environment') { if (!$this->hasSelectedEnvironment()) { $this->stdErr->writeln('You must specify an environment'); return 1; } $environment = $this->getSelectedEnvironment(); $environmentAccesses = $environment->getUsers(); foreach ($environmentAccesses as $candidate) { if ($candidate->user === $selectedUser->id) { $environmentAccess = $candidate; $currentRole = $environmentAccess->role; break; } } $validRoles = EnvironmentAccess::$roles; } $role = $input->getOption('role'); if ($role && $role !== 'none' && !in_array($role, $validRoles)) { $this->stdErr->writeln("Invalid role: {$role}"); return 1; } if ($role && $project->owner === $selectedUser->id) { $this->stdErr->writeln("The user <error>{$email}</error> is the owner of the project <error>{$project->title}</error>."); $this->stdErr->writeln("You cannot change the role of the project's owner."); return 1; } if ($role === $currentRole || $role === 'none' && $currentRole === false) { $this->stdErr->writeln("There is nothing to change"); } elseif ($role && $level == 'project') { $result = $selectedUser->update(['role' => $role]); $this->stdErr->writeln("User <info>{$email}</info> updated"); } elseif ($role && $level == 'environment') { $environment = $this->getSelectedEnvironment(); if ($role == 'none') { if ($environmentAccess) { $result = $environmentAccess->delete(); } } elseif ($environmentAccess) { $result = $environmentAccess->update(['role' => $role]); } else { $result = $environment->addUser($selectedUser->id, $role); } $this->stdErr->writeln("User <info>{$email}</info> updated"); } if (isset($result) && !$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr); } if ($input->getOption('pipe')) { if ($level == 'project') { $output->writeln($selectedUser->role); } elseif ($level == 'environment') { $environment = $this->getSelectedEnvironment(); $output->writeln($selectedUser->getEnvironmentRole($environment) ?: 'none'); } return 0; } $output->writeln("Project role: <info>{$selectedUser->role}</info>"); if ($this->hasSelectedEnvironment()) { $environment = $this->getSelectedEnvironment(); $environmentAccesses = $environment->getUsers(); $currentEnvironmentRole = 'none'; foreach ($environmentAccesses as $environmentAccess) { if ($selectedUser->id === $environmentAccess->user) { $currentEnvironmentRole = $environmentAccess->role; } } $output->writeln("Role for environment {$environment->title}: <info>{$currentEnvironmentRole}</info>"); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); /** @var \Platformsh\Cli\Helper\QuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); $email = $input->getArgument('email'); if ($email && !$this->validateEmail($email)) { return 1; } elseif (!$email) { $question = new Question('Email address: '); $question->setValidator([$this, 'validateEmail']); $question->setMaxAttempts(5); $email = $questionHelper->ask($input, $this->stdErr, $question); } $project = $this->getSelectedProject(); if ($this->api()->loadProjectAccessByEmail($project, $email)) { $this->stdErr->writeln("The user already exists: <comment>{$email}</comment>"); return 1; } $projectRole = $input->getOption('role'); if ($projectRole && !in_array($projectRole, ProjectAccess::$roles)) { $this->stdErr->writeln("Valid project-level roles are 'admin' or 'viewer'"); return 1; } elseif (!$projectRole) { if (!$input->isInteractive()) { $this->stdErr->writeln('You must specify a project role for the user.'); return 1; } $this->stdErr->writeln("The user's project role can be 'viewer' ('v') or 'admin' ('a')."); $question = new Question('Project role <question>[V/a]</question>: ', 'viewer'); $question->setValidator([$this, 'validateRole']); $question->setMaxAttempts(5); $projectRole = $this->standardizeRole($questionHelper->ask($input, $this->stdErr, $question)); } $environmentRoles = []; $environments = []; if ($projectRole !== 'admin') { $environments = $this->api()->getEnvironments($project); if ($input->isInteractive()) { $this->stdErr->writeln("The user's environment-level roles can be 'viewer', 'contributor', 'admin', or 'none'."); } foreach ($environments as $environment) { $question = new Question('<info>' . $environment->id . '</info> environment role <question>[v/c/a/N]</question>: ', 'none'); $question->setValidator([$this, 'validateRole']); $question->setMaxAttempts(5); $environmentRoles[$environment->id] = $this->standardizeRole($questionHelper->ask($input, $this->stdErr, $question)); } } $summaryFields = ['Email address' => $email, 'Project role' => $projectRole]; if (!empty($environmentRoles)) { foreach ($environments as $environment) { if (isset($environmentRoles[$environment->id])) { $summaryFields[$environment->title] = $environmentRoles[$environment->id]; } } } $this->stdErr->writeln('Summary:'); foreach ($summaryFields as $field => $value) { $this->stdErr->writeln(" {$field}: <info>{$value}</info>"); } $this->stdErr->writeln("<comment>Adding users can result in additional charges.</comment>"); if ($input->isInteractive()) { if (!$questionHelper->confirm("Are you sure you want to add this user?")) { return 1; } } $this->stdErr->writeln("Adding the user to the project"); $result = $project->addUser($email, $projectRole); $activities = $result->getActivities(); $this->stdErr->writeln("User <info>{$email}</info> created"); $success = true; if (!empty($environmentRoles)) { /** @var ProjectAccess $projectAccess */ $projectAccess = $result->getEntity(); $uuid = $projectAccess->id; $this->stdErr->writeln("Setting environment role(s)"); foreach ($environmentRoles as $environmentId => $role) { if (!isset($environments[$environmentId])) { $this->stdErr->writeln("<error>Environment not found: {$environmentId}</error>"); $success = false; continue; } if ($role == 'none') { continue; } $access = $environments[$environmentId]->getUser($uuid); if ($access) { $this->stdErr->writeln("Modifying the user's role on the environment: <info>{$environmentId}</info>"); $result = $access->update(['role' => $role]); } else { $this->stdErr->writeln("Adding the user to the environment: <info>{$environmentId}</info>"); $result = $environments[$environmentId]->addUser($uuid, $role); } $activities = array_merge($activities, $result->getActivities()); } } if (!$input->getOption('no-wait')) { if (!ActivityUtil::waitMultiple($activities, $this->stdErr, $project)) { $success = false; } } return $success ? 0 : 1; }
/** * @param Environment[] $environments * @param InputInterface $input * @param OutputInterface $output * * @return bool */ protected function deleteMultiple(array $environments, InputInterface $input, OutputInterface $output) { // Confirm which environments the user wishes to be deleted. $delete = array(); $deactivate = array(); $questionHelper = $this->getHelper('question'); foreach ($environments as $environment) { $environmentId = $environment['id']; if ($environmentId == 'master') { $output->writeln("The <error>master</error> environment cannot be deleted."); continue; } // Check that the environment does not have children. // @todo remove this check when Platform's behavior is fixed foreach ($this->getEnvironments() as $potentialChild) { if ($potentialChild['parent'] == $environment['id']) { $output->writeln("The environment <error>{$environmentId}</error> has children and therefore can't be deleted."); $output->writeln("Please delete the environment's children first."); continue 2; } } if ($environment->status === 'dirty') { $environment->refresh(); } if ($environment->isActive()) { $output->writeln("The environment <comment>{$environmentId}</comment> is currently active: deleting it will delete all associated data."); $question = "Are you sure you want to delete the environment <comment>{$environmentId}</comment>?"; if ($questionHelper->confirm($question, $input, $output)) { $deactivate[$environmentId] = $environment; $question = "Delete the remote Git branch too?"; if ($questionHelper->confirm($question, $input, $output)) { $delete[$environmentId] = $environment; } } } elseif ($environment->status === 'inactive') { $question = "Are you sure you want to delete the remote Git branch <comment>{$environmentId}</comment>?"; if ($questionHelper->confirm($question, $input, $output)) { $delete[$environmentId] = $environment; } } elseif ($environment->status === 'dirty') { $output->writeln("The environment <error>{$environmentId}</error> is currently building, and therefore can't be deleted. Please wait"); continue; } } $deactivateActivities = array(); $deactivated = 0; /** @var Environment $environment */ foreach ($deactivate as $environmentId => $environment) { try { $output->writeln("Deleting environment <info>{$environmentId}</info>"); $deactivateActivities[] = $environment->deactivate(); $deactivated++; } catch (\Exception $e) { $output->writeln($e->getMessage()); } } ActivityUtil::waitMultiple($deactivateActivities, $output); $deleted = 0; foreach ($delete as $environmentId => $environment) { try { if ($environment->status !== 'inactive') { $environment->refresh(); if ($environment->status !== 'inactive') { $output->writeln("Cannot delete environment <error>{$environmentId}</error>: it is not (yet) inactive."); continue; } } $environment->delete(); $output->writeln("Deleted remote Git branch <info>{$environmentId}</info>"); $deleted++; } catch (\Exception $e) { $output->writeln($e->getMessage()); } } if ($deleted || $deactivated) { $this->getEnvironments(null, true); } return $deleted >= count($delete) && $deactivated >= count($deactivate); }
/** * @param string $property * @param string $value * @param Environment $environment * @param bool $noWait * * @return int */ protected function setProperty($property, $value, Environment $environment, $noWait) { if (!$this->validateValue($property, $value)) { return 1; } $type = $this->getType($property); if ($type === 'boolean' && $value === 'false') { $value = false; } settype($value, $type); $currentValue = $environment->getProperty($property, false); if ($currentValue === $value) { $this->stdErr->writeln("Property <info>{$property}</info> already set as: " . $this->formatter->format($environment->getProperty($property, false), $property)); return 0; } $result = $environment->update([$property => $value]); $this->stdErr->writeln("Property <info>{$property}</info> set to: " . $this->formatter->format($environment->{$property}, $property)); $this->api()->clearEnvironmentsCache($environment->project); $rebuildProperties = ['enable_smtp', 'restrict_robots']; $success = true; if ($result->countActivities() && !$noWait) { $success = ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $this->getSelectedProject()); } elseif (!$result->countActivities() && in_array($property, $rebuildProperties)) { $this->rebuildWarning(); } return $success ? 0 : 1; }
/** * @param Environment[] $environments * @param InputInterface $input * @param OutputInterface $output * * @return bool */ protected function deleteMultiple(array $environments, InputInterface $input, OutputInterface $output) { // Confirm which environments the user wishes to be deleted. $delete = []; $deactivate = []; $error = false; $questionHelper = $this->getHelper('question'); foreach ($environments as $environment) { $environmentId = $environment->id; if ($environmentId == 'master') { $output->writeln("The <error>master</error> environment cannot be deleted."); $error = true; continue; } // Check that the environment does not have children. // @todo remove this check when Platform's behavior is fixed foreach ($this->api()->getEnvironments($this->getSelectedProject()) as $potentialChild) { if ($potentialChild->parent == $environment->id) { $output->writeln("The environment <error>{$environmentId}</error> has children and therefore can't be deleted."); $output->writeln("Please delete the environment's children first."); $error = true; continue 2; } } if ($environment->isActive()) { $output->writeln("The environment <comment>{$environmentId}</comment> is currently active: deleting it will delete all associated data."); if ($questionHelper->confirm("Are you sure you want to delete the environment <comment>{$environmentId}</comment>?")) { $deactivate[$environmentId] = $environment; if (!$input->getOption('no-delete-branch')) { if ($input->getOption('delete-branch') || $input->isInteractive() && $questionHelper->confirm("Delete the remote Git branch too?")) { $delete[$environmentId] = $environment; } } } } elseif ($environment->status === 'inactive') { if ($questionHelper->confirm("Are you sure you want to delete the remote Git branch <comment>{$environmentId}</comment>?")) { $delete[$environmentId] = $environment; } } elseif ($environment->status === 'dirty') { $output->writeln("The environment <error>{$environmentId}</error> is currently building, and therefore can't be deleted. Please wait."); $error = true; continue; } } $deactivateActivities = []; $deactivated = 0; /** @var Environment $environment */ foreach ($deactivate as $environmentId => $environment) { try { $output->writeln("Deleting environment <info>{$environmentId}</info>"); $deactivateActivities[] = $environment->deactivate(); $deactivated++; } catch (\Exception $e) { $output->writeln($e->getMessage()); } } if (!$input->getOption('no-wait')) { if (!ActivityUtil::waitMultiple($deactivateActivities, $output, $this->getSelectedProject())) { $error = true; } } $deleted = 0; foreach ($delete as $environmentId => $environment) { try { if ($environment->status !== 'inactive') { $environment->refresh(); if ($environment->status !== 'inactive') { $output->writeln("Cannot delete branch <error>{$environmentId}</error>: it is not (yet) inactive."); continue; } } $environment->delete(); $output->writeln("Deleted remote Git branch <info>{$environmentId}</info>"); $deleted++; } catch (\Exception $e) { $output->writeln($e->getMessage()); } } if ($deleted < count($delete) || $deactivated < count($deactivate)) { $error = true; } if (($deleted || $deactivated || $error) && isset($environment)) { $this->api()->clearEnvironmentsCache($environment->project); } return !$error; }
protected function execute(InputInterface $input, OutputInterface $output) { $level = $input->getOption('level'); $role = $input->getOption('role'); $validLevels = ['project', 'environment', null]; if (!in_array($level, $validLevels)) { $this->stdErr->writeln("Invalid level: <error>{$level}</error>"); return 1; } $this->validateInput($input, $level !== 'environment'); $project = $this->getSelectedProject(); if ($level === null && $role && $this->hasSelectedEnvironment() && $input->isInteractive()) { $environment = $this->getSelectedEnvironment(); /** @var \Platformsh\Cli\Helper\QuestionHelper $questionHelper */ $questionHelper = $this->getHelper('question'); $question = new ChoiceQuestion('For which access level do you want to set the role?', ['project' => 'The project', 'environment' => sprintf('The environment (%s)', $environment->id)]); $level = $questionHelper->ask($input, $output, $question); } elseif ($level === null && $role) { $level = 'project'; } // Validate the --role option, according to the level. $validRoles = $level !== 'environment' ? ProjectAccess::$roles : array_merge(EnvironmentAccess::$roles, ['none']); if ($role && !in_array($role, $validRoles)) { $this->stdErr->writeln('Invalid ' . $level . ' role: ' . $role); return 1; } // Load the user. $email = $input->getArgument('email'); $selectedUser = $this->api()->loadProjectAccessByEmail($project, $email); if (!$selectedUser) { $this->stdErr->writeln("User not found: <error>{$email}</error>"); return 1; } // Get the current role. if ($level !== 'environment') { $currentRole = $selectedUser->role; $environmentAccess = false; } else { $environmentAccess = $this->getSelectedEnvironment()->getUser($selectedUser->id); $currentRole = $environmentAccess === false ? 'none' : $environmentAccess->role; } if ($role === $currentRole) { $this->stdErr->writeln("There is nothing to change"); } elseif ($role && $project->owner === $selectedUser->id) { $this->stdErr->writeln(sprintf('The user <error>%s</error> is the owner of the project %s.', $email, $this->api()->getProjectLabel($project, 'error'))); $this->stdErr->writeln("You cannot change the role of the project's owner."); return 1; } elseif ($role && $level === 'environment' && $selectedUser->role === ProjectAccess::ROLE_ADMIN) { $this->stdErr->writeln(sprintf('The user <error>%s</error> is an admin on the project %s.', $email, $this->api()->getProjectLabel($project, 'error'))); $this->stdErr->writeln('You cannot change the environment-level role of a project admin.'); return 1; } elseif ($role && $level !== 'environment') { $result = $selectedUser->update(['role' => $role]); $this->stdErr->writeln("User <info>{$email}</info> updated"); } elseif ($role && $level === 'environment') { $environment = $this->getSelectedEnvironment(); if ($role === 'none') { if ($environmentAccess instanceof EnvironmentAccess) { $result = $environmentAccess->delete(); } } elseif ($environmentAccess instanceof EnvironmentAccess) { $result = $environmentAccess->update(['role' => $role]); } else { $result = $environment->addUser($selectedUser->id, $role); } $this->stdErr->writeln("User <info>{$email}</info> updated"); } if (isset($result) && !$input->getOption('no-wait')) { ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $project); } if ($input->getOption('pipe')) { if ($level !== 'environment') { $output->writeln($selectedUser->role); } else { $access = $this->getSelectedEnvironment()->getUser($selectedUser->id); $output->writeln($access ? $access->role : 'none'); } return 0; } if ($level !== 'environment') { $output->writeln("Project role: <info>{$selectedUser->role}</info>"); } $environments = []; if ($level === 'environment') { $environments = [$this->getSelectedEnvironment()]; } elseif ($level === null && $selectedUser->role !== ProjectAccess::ROLE_ADMIN) { $environments = $this->api()->getEnvironments($project); $this->api()->sortResources($environments, 'id'); if ($this->hasSelectedEnvironment()) { $environment = $this->getSelectedEnvironment(); unset($environments[$environment->id]); array_splice($environments, 0, 0, [$environment->id => $environment]); } } foreach ($environments as $environment) { $access = $environment->getUser($selectedUser->id); $output->writeln(sprintf('Role for environment %s: <info>%s</info>', $environment->id, $access ? $access->role : 'none')); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $this->validateInput($input); $auth = $input->getOption('auth'); $access = $input->getOption('access'); $accessOpts = []; $enabled = $input->getOption('enabled'); if ($enabled !== null) { $accessOpts['is_enabled'] = !in_array($enabled, ['0', 'false']); } if ($access) { $accessOpts['addresses'] = []; foreach (array_filter($access) as $access) { $accessOpts["addresses"][] = $this->parseAccess($access); } } if ($auth) { $accessOpts['basic_auth'] = []; foreach (array_filter($auth) as $auth) { $parsed = $this->parseAuth($auth); $accessOpts["basic_auth"][$parsed["username"]] = $parsed["password"]; } } // Ensure the environment is refreshed. $selectedEnvironment = $this->getSelectedEnvironment(); $selectedEnvironment->ensureFull(); $environmentId = $selectedEnvironment->id; $formatter = new PropertyFormatter(); if (!empty($accessOpts)) { $current = (array) $selectedEnvironment->getProperty('http_access'); // Merge existing settings. Not using a reference here, as that // would affect the comparison with $current later. foreach ($current as $key => $value) { if (!isset($accessOpts[$key])) { $accessOpts[$key] = $value; } } if ($current != $accessOpts) { // The API only accepts {} for an empty "basic_auth" value, // rather than []. if (isset($accessOpts['basic_auth']) && $accessOpts['basic_auth'] === []) { $accessOpts['basic_auth'] = (object) []; } // Patch the environment with the changes. $result = $selectedEnvironment->update(['http_access' => $accessOpts]); $this->clearEnvironmentsCache(); $this->stdErr->writeln("Updated HTTP access settings for the environment <info>{$environmentId}</info>:"); $output->writeln($formatter->format($selectedEnvironment->getProperty('http_access'), 'http_access')); $success = true; if (!$result->countActivities()) { $this->rebuildWarning(); } elseif (!$input->getOption('no-wait')) { $success = ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr); } return $success ? 0 : 1; } } $this->stdErr->writeln("HTTP access settings for the environment <info>{$environmentId}</info>:"); $output->writeln($formatter->format($selectedEnvironment->getProperty('http_access'), 'http_access')); return 0; }
/** * @param string $property * @param string $value * @param Project $project * @param bool $noWait * * @return int */ protected function setProperty($property, $value, Project $project, $noWait) { if (!$this->validateValue($property, $value)) { return 1; } $type = $this->getType($property); if ($type === 'boolean' && $value === 'false') { $value = false; } settype($value, $type); $currentValue = $project->getProperty($property); if ($currentValue === $value) { $this->stdErr->writeln("Property <info>{$property}</info> already set as: " . $this->formatter->format($value, $property)); return 0; } $project->ensureFull(); $result = $project->update([$property => $value]); $this->stdErr->writeln("Property <info>{$property}</info> set to: " . $this->formatter->format($value, $property)); $this->api()->clearProjectsCache(); $success = true; if (!$noWait) { $success = ActivityUtil::waitMultiple($result->getActivities(), $this->stdErr, $project); } return $success ? 0 : 1; }