1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Make "bin/storage destroy" target individual hosts in database cluster mode

Summary:
Ref T13336. Currently, "bin/storage destroy" destroys every master. This is wonderfully destructive, but if replication fails it's useful to be able to destroy only a replica.

Operate on a single host, and require "--host" to target the operation in cluster mode, so `bin/storage destroy --host dbreplica001` is a useful operation.

Test Plan: Ran `bin/storage destroy` with various flags locally. Will destroy `secure002` and refresh replication.

Maniphest Tasks: T13336

Differential Revision: https://secure.phabricator.com/D20784
This commit is contained in:
epriestley 2019-09-04 10:02:51 -07:00
parent f7290bbbf2
commit 764db4869c
3 changed files with 87 additions and 54 deletions

View file

@ -221,6 +221,9 @@ final class PhabricatorDatabaseRef
return $this->replicaRefs; return $this->replicaRefs;
} }
public function getDisplayName() {
return $this->getRefKey();
}
public function getRefKey() { public function getRefKey() {
$host = $this->getHost(); $host = $this->getHost();

View file

@ -89,6 +89,10 @@ final class PhabricatorStorageManagementAPI extends Phobject {
return $this->namespace.'_'.$fragment; return $this->namespace.'_'.$fragment;
} }
public function getDisplayName() {
return $this->getRef()->getDisplayName();
}
public function getDatabaseList(array $patches, $only_living = false) { public function getDatabaseList(array $patches, $only_living = false) {
assert_instances_of($patches, 'PhabricatorStoragePatch'); assert_instances_of($patches, 'PhabricatorStoragePatch');

View file

@ -21,41 +21,59 @@ final class PhabricatorStorageManagementDestroyWorkflow
} }
public function didExecute(PhutilArgumentParser $args) { public function didExecute(PhutilArgumentParser $args) {
$console = PhutilConsole::getConsole(); $api = $this->getSingleAPI();
$host_display = $api->getDisplayName();
if (!$this->isDryRun() && !$this->isForce()) { if (!$this->isDryRun() && !$this->isForce()) {
if ($args->getArg('unittest-fixtures')) { if ($args->getArg('unittest-fixtures')) {
$console->writeOut( $warning = pht(
phutil_console_wrap(
pht(
'Are you completely sure you really want to destroy all unit '. 'Are you completely sure you really want to destroy all unit '.
'test fixure data? This operation can not be undone.'))); 'test fixure data on host "%s"? This operation can not be undone.',
$host_display);
echo tsprintf(
'%B',
id(new PhutilConsoleBlock())
->addParagraph($warning)
->drawConsoleString());
if (!phutil_console_confirm(pht('Destroy all unit test data?'))) { if (!phutil_console_confirm(pht('Destroy all unit test data?'))) {
$console->writeOut("%s\n", pht('Cancelled.')); $this->logFail(
pht('CANCELLED'),
pht('User cancelled operation.'));
exit(1); exit(1);
} }
} else { } else {
$console->writeOut( $warning = pht(
phutil_console_wrap(
pht(
'Are you completely sure you really want to permanently destroy '. 'Are you completely sure you really want to permanently destroy '.
'all storage for Phabricator data? This operation can not be '. 'all storage for Phabricator data on host "%s"? This operation '.
'undone and your data will not be recoverable if you proceed.'))); 'can not be undone and your data will not be recoverable if '.
'you proceed.',
$host_display);
echo tsprintf(
'%B',
id(new PhutilConsoleBlock())
->addParagraph($warning)
->drawConsoleString());
if (!phutil_console_confirm(pht('Permanently destroy all data?'))) { if (!phutil_console_confirm(pht('Permanently destroy all data?'))) {
$console->writeOut("%s\n", pht('Cancelled.')); $this->logFail(
pht('CANCELLED'),
pht('User cancelled operation.'));
exit(1); exit(1);
} }
if (!phutil_console_confirm(pht('Really destroy all data forever?'))) { if (!phutil_console_confirm(pht('Really destroy all data forever?'))) {
$console->writeOut("%s\n", pht('Cancelled.')); $this->logFail(
pht('CANCELLED'),
pht('User cancelled operation.'));
exit(1); exit(1);
} }
} }
} }
$apis = $this->getMasterAPIs();
foreach ($apis as $api) {
$patches = $this->getPatches(); $patches = $this->getPatches();
if ($args->getArg('unittest-fixtures')) { if ($args->getArg('unittest-fixtures')) {
@ -76,15 +94,24 @@ final class PhabricatorStorageManagementDestroyWorkflow
$databases[] = $api->getDatabaseName('directory'); $databases[] = $api->getDatabaseName('directory');
} }
asort($databases);
foreach ($databases as $database) { foreach ($databases as $database) {
if ($this->isDryRun()) { if ($this->isDryRun()) {
$console->writeOut( $this->logInfo(
"%s\n", pht('DRY RUN'),
pht("DRYRUN: Would drop database '%s'.", $database)); pht(
'Would drop database "%s" on host "%s".',
$database,
$host_display));
} else { } else {
$console->writeOut( $this->logWarn(
"%s\n", pht('DESTROY'),
pht("Dropping database '%s'...", $database)); pht(
'Dropping database "%s" on host "%s"...',
$database,
$host_display));
queryfx( queryfx(
$api->getConn(null), $api->getConn(null),
'DROP DATABASE IF EXISTS %T', 'DROP DATABASE IF EXISTS %T',
@ -93,12 +120,11 @@ final class PhabricatorStorageManagementDestroyWorkflow
} }
if (!$this->isDryRun()) { if (!$this->isDryRun()) {
$console->writeOut( $this->logOkay(
"%s\n", pht('DONE'),
pht( pht(
'Storage on "%s" was destroyed.', 'Storage on "%s" was destroyed.',
$api->getRef()->getRefKey())); $host_display));
}
} }
return 0; return 0;