@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+87 -54
+3
src/infrastructure/cluster/PhabricatorDatabaseRef.php
··· 221 221 return $this->replicaRefs; 222 222 } 223 223 224 + public function getDisplayName() { 225 + return $this->getRefKey(); 226 + } 224 227 225 228 public function getRefKey() { 226 229 $host = $this->getHost();
+4
src/infrastructure/storage/management/PhabricatorStorageManagementAPI.php
··· 89 89 return $this->namespace.'_'.$fragment; 90 90 } 91 91 92 + public function getDisplayName() { 93 + return $this->getRef()->getDisplayName(); 94 + } 95 + 92 96 public function getDatabaseList(array $patches, $only_living = false) { 93 97 assert_instances_of($patches, 'PhabricatorStoragePatch'); 94 98
+80 -54
src/infrastructure/storage/management/workflow/PhabricatorStorageManagementDestroyWorkflow.php
··· 21 21 } 22 22 23 23 public function didExecute(PhutilArgumentParser $args) { 24 - $console = PhutilConsole::getConsole(); 24 + $api = $this->getSingleAPI(); 25 + 26 + $host_display = $api->getDisplayName(); 25 27 26 28 if (!$this->isDryRun() && !$this->isForce()) { 27 29 if ($args->getArg('unittest-fixtures')) { 28 - $console->writeOut( 29 - phutil_console_wrap( 30 - pht( 31 - 'Are you completely sure you really want to destroy all unit '. 32 - 'test fixure data? This operation can not be undone.'))); 30 + $warning = pht( 31 + 'Are you completely sure you really want to destroy all unit '. 32 + 'test fixure data on host "%s"? This operation can not be undone.', 33 + $host_display); 34 + 35 + echo tsprintf( 36 + '%B', 37 + id(new PhutilConsoleBlock()) 38 + ->addParagraph($warning) 39 + ->drawConsoleString()); 40 + 33 41 if (!phutil_console_confirm(pht('Destroy all unit test data?'))) { 34 - $console->writeOut("%s\n", pht('Cancelled.')); 42 + $this->logFail( 43 + pht('CANCELLED'), 44 + pht('User cancelled operation.')); 35 45 exit(1); 36 46 } 37 47 } else { 38 - $console->writeOut( 39 - phutil_console_wrap( 40 - pht( 41 - 'Are you completely sure you really want to permanently destroy '. 42 - 'all storage for Phabricator data? This operation can not be '. 43 - 'undone and your data will not be recoverable if you proceed.'))); 48 + $warning = pht( 49 + 'Are you completely sure you really want to permanently destroy '. 50 + 'all storage for Phabricator data on host "%s"? This operation '. 51 + 'can not be undone and your data will not be recoverable if '. 52 + 'you proceed.', 53 + $host_display); 54 + 55 + echo tsprintf( 56 + '%B', 57 + id(new PhutilConsoleBlock()) 58 + ->addParagraph($warning) 59 + ->drawConsoleString()); 44 60 45 61 if (!phutil_console_confirm(pht('Permanently destroy all data?'))) { 46 - $console->writeOut("%s\n", pht('Cancelled.')); 62 + $this->logFail( 63 + pht('CANCELLED'), 64 + pht('User cancelled operation.')); 47 65 exit(1); 48 66 } 49 67 50 68 if (!phutil_console_confirm(pht('Really destroy all data forever?'))) { 51 - $console->writeOut("%s\n", pht('Cancelled.')); 69 + $this->logFail( 70 + pht('CANCELLED'), 71 + pht('User cancelled operation.')); 52 72 exit(1); 53 73 } 54 74 } 55 75 } 56 76 57 - $apis = $this->getMasterAPIs(); 58 - foreach ($apis as $api) { 59 - $patches = $this->getPatches(); 77 + $patches = $this->getPatches(); 60 78 61 - if ($args->getArg('unittest-fixtures')) { 62 - $conn = $api->getConn(null); 63 - $databases = queryfx_all( 64 - $conn, 65 - 'SELECT DISTINCT(TABLE_SCHEMA) AS db '. 66 - 'FROM INFORMATION_SCHEMA.TABLES '. 67 - 'WHERE TABLE_SCHEMA LIKE %>', 68 - PhabricatorTestCase::NAMESPACE_PREFIX); 69 - $databases = ipull($databases, 'db'); 70 - } else { 71 - $databases = $api->getDatabaseList($patches); 72 - $databases[] = $api->getDatabaseName('meta_data'); 79 + if ($args->getArg('unittest-fixtures')) { 80 + $conn = $api->getConn(null); 81 + $databases = queryfx_all( 82 + $conn, 83 + 'SELECT DISTINCT(TABLE_SCHEMA) AS db '. 84 + 'FROM INFORMATION_SCHEMA.TABLES '. 85 + 'WHERE TABLE_SCHEMA LIKE %>', 86 + PhabricatorTestCase::NAMESPACE_PREFIX); 87 + $databases = ipull($databases, 'db'); 88 + } else { 89 + $databases = $api->getDatabaseList($patches); 90 + $databases[] = $api->getDatabaseName('meta_data'); 73 91 74 - // These are legacy databases that were dropped long ago. See T2237. 75 - $databases[] = $api->getDatabaseName('phid'); 76 - $databases[] = $api->getDatabaseName('directory'); 77 - } 92 + // These are legacy databases that were dropped long ago. See T2237. 93 + $databases[] = $api->getDatabaseName('phid'); 94 + $databases[] = $api->getDatabaseName('directory'); 95 + } 78 96 79 - foreach ($databases as $database) { 80 - if ($this->isDryRun()) { 81 - $console->writeOut( 82 - "%s\n", 83 - pht("DRYRUN: Would drop database '%s'.", $database)); 84 - } else { 85 - $console->writeOut( 86 - "%s\n", 87 - pht("Dropping database '%s'...", $database)); 88 - queryfx( 89 - $api->getConn(null), 90 - 'DROP DATABASE IF EXISTS %T', 91 - $database); 92 - } 93 - } 97 + asort($databases); 94 98 95 - if (!$this->isDryRun()) { 96 - $console->writeOut( 97 - "%s\n", 99 + foreach ($databases as $database) { 100 + if ($this->isDryRun()) { 101 + $this->logInfo( 102 + pht('DRY RUN'), 103 + pht( 104 + 'Would drop database "%s" on host "%s".', 105 + $database, 106 + $host_display)); 107 + } else { 108 + $this->logWarn( 109 + pht('DESTROY'), 98 110 pht( 99 - 'Storage on "%s" was destroyed.', 100 - $api->getRef()->getRefKey())); 111 + 'Dropping database "%s" on host "%s"...', 112 + $database, 113 + $host_display)); 114 + 115 + queryfx( 116 + $api->getConn(null), 117 + 'DROP DATABASE IF EXISTS %T', 118 + $database); 101 119 } 120 + } 121 + 122 + if (!$this->isDryRun()) { 123 + $this->logOkay( 124 + pht('DONE'), 125 + pht( 126 + 'Storage on "%s" was destroyed.', 127 + $host_display)); 102 128 } 103 129 104 130 return 0;