diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 2cf06ba8a8..0adb3af9db 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -5560,6 +5560,7 @@ phutil_register_library_map(array( 'PhabricatorFlaggableInterface', 'PhabricatorSubscribableInterface', 'PhabricatorTokenReceiverInterface', + 'PhabricatorDestructibleInterface', ), 'PonderAnswerCommentController' => 'PonderController', 'PonderAnswerEditController' => 'PonderController', @@ -5588,6 +5589,7 @@ phutil_register_library_map(array( 'PhabricatorPolicyInterface', 'PhabricatorTokenReceiverInterface', 'PhabricatorProjectInterface', + 'PhabricatorDestructibleInterface', ), 'PonderQuestionCommentController' => 'PonderController', 'PonderQuestionEditController' => 'PonderController', diff --git a/src/applications/config/check/PhabricatorSetupCheckMySQL.php b/src/applications/config/check/PhabricatorSetupCheckMySQL.php index b4614a11da..670a428d92 100644 --- a/src/applications/config/check/PhabricatorSetupCheckMySQL.php +++ b/src/applications/config/check/PhabricatorSetupCheckMySQL.php @@ -2,15 +2,21 @@ final class PhabricatorSetupCheckMySQL extends PhabricatorSetupCheck { - protected function executeChecks() { + public static function loadRawConfigValue($key) { $conn_raw = id(new PhabricatorUser())->establishConnection('w'); - $max_allowed_packet = queryfx_one( - $conn_raw, - 'SHOW VARIABLES LIKE %s', - 'max_allowed_packet'); - $max_allowed_packet = idx($max_allowed_packet, 'Value', PHP_INT_MAX); + try { + $value = queryfx_one($conn_raw, 'SELECT @@%Q', $key); + $value = $value['@@'.$key]; + } catch (AphrontQueryException $ex) { + $value = null; + } + + return $value; + } + protected function executeChecks() { + $max_allowed_packet = self::loadRawConfigValue('max_allowed_packet'); $recommended_minimum = 1024 * 1024; if ($max_allowed_packet < $recommended_minimum) { $message = pht( @@ -22,11 +28,12 @@ final class PhabricatorSetupCheckMySQL extends PhabricatorSetupCheck { $this->newIssue('mysql.max_allowed_packet') ->setName(pht('Small MySQL "max_allowed_packet"')) - ->setMessage($message); + ->setMessage($message) + ->addMySQLConfig('max_allowed_packet'); } - $mode_string = queryfx_one($conn_raw, 'SELECT @@sql_mode'); - $modes = explode(',', $mode_string['@@sql_mode']); + $modes = self::loadRawConfigValue('sql_mode'); + $modes = explode(',', $modes); if (!in_array('STRICT_ALL_TABLES', $modes)) { $summary = pht( 'MySQL is not in strict mode, but using strict mode is strongly '. @@ -57,16 +64,11 @@ final class PhabricatorSetupCheckMySQL extends PhabricatorSetupCheck { $this->newIssue('mysql.mode') ->setName(pht('MySQL STRICT_ALL_TABLES Mode Not Set')) ->setSummary($summary) - ->setMessage($message); - } - - try { - $stopword_file = queryfx_one($conn_raw, 'SELECT @@ft_stopword_file'); - $stopword_file = $stopword_file['@@ft_stopword_file']; - } catch (AphrontQueryException $ex) { - $stopword_file = null; + ->setMessage($message) + ->addMySQLConfig('sql_mode'); } + $stopword_file = self::loadRawConfigValue('ft_stopword_file'); if (!PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) { if ($stopword_file === null) { $summary = pht( @@ -86,7 +88,8 @@ final class PhabricatorSetupCheckMySQL extends PhabricatorSetupCheck { $this->newIssue('mysql.ft_stopword_file') ->setName(pht('MySQL ft_stopword_file Not Supported')) ->setSummary($summary) - ->setMessage($message); + ->setMessage($message) + ->addMySQLConfig('ft_stopword_file'); } else if ($stopword_file == '(built-in)') { $root = dirname(phutil_get_library_root('phabricator')); @@ -133,20 +136,20 @@ final class PhabricatorSetupCheckMySQL extends PhabricatorSetupCheck { $this->newIssue('mysql.ft_stopword_file') ->setName(pht('MySQL is Using Default Stopword File')) ->setSummary($summary) - ->setMessage($message); + ->setMessage($message) + ->addMySQLConfig('ft_stopword_file'); } } - - $min_len = queryfx_one($conn_raw, 'SELECT @@ft_min_word_len'); - $min_len = $min_len['@@ft_min_word_len']; - if ($min_len == 4) { + $min_len = self::loadRawConfigValue('ft_min_word_len'); + if ($min_len >= 4) { if (!PhabricatorDefaultSearchEngineSelector::shouldUseElasticSearch()) { $namespace = PhabricatorEnv::getEnvConfig('storage.default-namespace'); $summary = pht( - 'MySQL is configured to only index words with at least 4 '. - 'characters.'); + 'MySQL is configured to only index words with at least %d '. + 'characters.', + $min_len); $message = pht( "Your MySQL instance is configured to use the default minimum word ". @@ -178,7 +181,8 @@ final class PhabricatorSetupCheckMySQL extends PhabricatorSetupCheck { $this->newIssue('mysql.ft_min_word_len') ->setName(pht('MySQL is Using Default Minimum Word Length')) ->setSummary($summary) - ->setMessage($message); + ->setMessage($message) + ->addMySQLConfig('ft_min_word_len'); } } diff --git a/src/applications/config/issue/PhabricatorSetupIssue.php b/src/applications/config/issue/PhabricatorSetupIssue.php index c69f529aca..51f24f6cf5 100644 --- a/src/applications/config/issue/PhabricatorSetupIssue.php +++ b/src/applications/config/issue/PhabricatorSetupIssue.php @@ -15,6 +15,7 @@ final class PhabricatorSetupIssue { private $relatedPhabricatorConfig = array(); private $phpConfig = array(); private $commands = array(); + private $mysqlConfig = array(); public function addCommand($command) { $this->commands[] = $command; @@ -85,6 +86,15 @@ final class PhabricatorSetupIssue { return $this->phpConfig; } + public function addMySQLConfig($mysql_config) { + $this->mysqlConfig[] = $mysql_config; + return $this; + } + + public function getMySQLConfig() { + return $this->mysqlConfig; + } + public function addPhabricatorConfig($phabricator_config) { $this->phabricatorConfig[] = $phabricator_config; return $this; diff --git a/src/applications/config/view/PhabricatorSetupIssueView.php b/src/applications/config/view/PhabricatorSetupIssueView.php index ca575adc8d..f8bea6539c 100644 --- a/src/applications/config/view/PhabricatorSetupIssueView.php +++ b/src/applications/config/view/PhabricatorSetupIssueView.php @@ -29,6 +29,11 @@ final class PhabricatorSetupIssueView extends AphrontView { $description[] = $this->renderPHPConfig($configs); } + $configs = $issue->getMySQLConfig(); + if ($configs) { + $description[] = $this->renderMySQLConfig($configs); + } + $configs = $issue->getPhabricatorConfig(); if ($configs) { $description[] = $this->renderPhabricatorConfig($configs); @@ -347,6 +352,58 @@ final class PhabricatorSetupIssueView extends AphrontView { )); } + private function renderMySQLConfig(array $config) { + $values = array(); + foreach ($config as $key) { + $value = PhabricatorSetupCheckMySQL::loadRawConfigValue($key); + if ($value === null) { + $value = phutil_tag( + 'em', + array(), + pht('(Not Supported)')); + } + $values[$key] = $value; + } + + $table = $this->renderValueTable($values); + + $doc_href = PhabricatorEnv::getDoclink('User Guide: Amazon RDS'); + $doc_link = phutil_tag( + 'a', + array( + 'href' => $doc_href, + 'target' => '_blank', + ), + pht('User Guide: Amazon RDS')); + + $info = array(); + $info[] = phutil_tag( + 'p', + array(), + pht( + 'If you are using Amazon RDS, some of the instructions above may '. + 'not apply to you. See %s for discussion of Amazon RDS.', + $doc_link)); + + $table_info = phutil_tag( + 'p', + array(), + pht( + 'The current MySQL configuration has these %d value(s):', + count($config))); + + return phutil_tag( + 'div', + array( + 'class' => 'setup-issue-config', + ), + array( + $table_info, + $table, + $info, + )); + } + private function renderValueTable(array $dict, array $hidden = array()) { $rows = array(); foreach ($dict as $key => $value) { @@ -374,6 +431,8 @@ final class PhabricatorSetupIssueView extends AphrontView { return phutil_tag('em', array(), 'true'); } else if ($value === '') { return phutil_tag('em', array(), 'empty string'); + } else if ($value instanceof PhutilSafeHTML) { + return $value; } else { return PhabricatorConfigJSON::prettyPrintJSON($value); } diff --git a/src/docs/user/userguide/amazon_rds.diviner b/src/docs/user/userguide/amazon_rds.diviner new file mode 100644 index 0000000000..442d499013 --- /dev/null +++ b/src/docs/user/userguide/amazon_rds.diviner @@ -0,0 +1,27 @@ +@title User Guide: Amazon RDS +@group config + +Discusses using Amazon RDS as a database. + +Overview +======== + +Phabricator works with Amazon RDS. However, most of our documentation and setup +checks assume you are using local MySQL, and upstream support is less available +for RDS. + +If you use RDS, you'll need to do a few things a bit differently than you would +with local MySQL, especially when configuring RDS. This document documents some +of the differences you'll encounter when using RDS. + +Configuration +============= + +The documentation and various setup warnings will sometimes direct you to make +configuration changes in `my.cnf`. In Amazon RDS, you don't have direct access +to `my.cnf` and thus can not make these changes in the configuration file. + +Instead, you can use [[ http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html | DB Parameter Groups ]]. +You can access these from your AWS console and use the web interface to make +necessary changes. The web UI will give you a user-friendly key-value table: +just identify the option you need to change, then select a new value for it. diff --git a/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php b/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php index d0888d496e..d717a780ae 100644 --- a/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php +++ b/src/infrastructure/internationalization/translation/PhabricatorBaseEnglishTranslation.php @@ -674,6 +674,11 @@ abstract class PhabricatorBaseEnglishTranslation 'The current Phabricator configuration has these values:', ), + 'The current MySQL configuration has these %d value(s):' => array( + 'The current MySQL configuration has this value:', + 'The current MySQL configuration has these values:', + ), + 'To update these %d value(s), run these command(s) from the command line:' => array( 'To update this value, run this command from the command line:',