Skip to content

Commit

Permalink
Merge pull request #108 from catalyst/settings-check-api-310
Browse files Browse the repository at this point in the history
Connection timeout + check API integration
  • Loading branch information
matthewhilton committed Sep 14, 2023
2 parents 10e0121 + c23d159 commit 4c2e4db
Show file tree
Hide file tree
Showing 10 changed files with 364 additions and 56 deletions.
95 changes: 95 additions & 0 deletions classes/admin_setting_check.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace search_elastic;

use admin_setting;
use core\check\check;
use core\check\result;
use core\output\notification;

/**
* Admin setting for check api.
*
* @package search_elastic
* @copyright Matthew Hilton <matthew.hilton@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_check extends admin_setting {
/** @var check $check The check to display */
private $check;

/**
* Creates check setting.
*
* @param string $name name of setting
* @param string $heading title of setting
* @param check $check check to display
*/
public function __construct(string $name, string $heading, check $check) {
$this->nosave = true;
$this->check = $check;
parent::__construct($name, $heading, '', '');
}

/**
* Returns setting (unused)
*
* @return true
*/
public function get_setting() {
return true;
}

/**
* Writes the setting (unused)
*
* @param mixed $data
*/
public function write_setting($data) {
return '';
}

/**
* Ouputs the admin setting HTML to be rendered.
*
* @param mixed $data
* @param string $query
* @return string html
*/
public function output_html($data, $query = '') {
global $OUTPUT;

// Run the check and get the result.
$checkresult = $this->check->get_result();

$resulthtml = $OUTPUT->check_result($checkresult);
$resultinfo = $checkresult->get_summary();
$out = $resulthtml . ' ' . $resultinfo;

switch($checkresult->get_status()){
case result::CRITICAL:
case result::ERROR:
$out = $OUTPUT->notification($out, notification::NOTIFY_ERROR, false);
break;

case result::OK:
$out = $OUTPUT->notification($out, notification::NOTIFY_SUCCESS, false);
break;
}
return format_admin_setting($this, $this->visiblename, '', $out);
}
}
82 changes: 82 additions & 0 deletions classes/check/server_ready_check.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

namespace search_elastic\check;

use action_link;
use core\check\check;
use core\check\result;
use moodle_url;
use search_elastic\engine;

/**
* Elasticsearch plugin server ready check.
*
* @package search_elastic
* @copyright Matthew Hilton <matthew.hilton@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class server_ready_check extends check {
/** @var object|false Custom Guzzle stack to use for requests. Used only for unit testing. */
private $stack;

/**
* Create check.
* @param object|false $stack Custom HTTP stack for unit testing.
*/
public function __construct($stack = false) {
$this->stack = $stack;
}

/**
* Performs check and returns result.
*
* @return result
*/
public function get_result(): result {
// Check the plugin is configured.
if (empty(get_config('search_elastic', 'hostname'))) {
return new result(result::NA, get_string('connection:na', 'search_elastic'));
}

// Query the server to see the HTTP response.
$engine = new engine();
$url = $engine->get_url();
$status = $engine->get_server_status_code($this->stack);
$resultstatus = $status === 200 ? result::OK : result::ERROR;

// Format the check details nicely.
$statusdetails = get_string('connection:status', 'search_elastic', [
'url' => $url,
'status' => $status
]);

return new result($resultstatus, $statusdetails);
}

/**
* Returns the link to action this check if it failed.
*
* @return action_link A link to the elasticsearch engine plugin settings
*/
public function get_action_link(): action_link {
$configstr = get_string('adminsettings', 'search_elastic');
$configurl = new moodle_url('/admin/settings.php', ['section' => 'elasticsettings']);

return new action_link($configurl, $configstr);
}
}

48 changes: 32 additions & 16 deletions classes/engine.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private function log($msg) {
*
* @return url|bool Returns url if succes or false on error.
*/
private function get_url() {
public function get_url() {
$returnval = false;

if (!empty($this->config->hostname) && !empty($this->config->port)) {
Expand Down Expand Up @@ -255,26 +255,42 @@ private function create_index() {
* Is the Elasticsearch server endpoint configured in Moodle
* and available.
*
* @param object $stack The Guzzle client stack to use.
* @return true|string Returns true if all good or an error string.
* @param object|false $stack Optional custom Guzzle HTTP stack.
* @return string|bool true if server is ready, else error string.
*/
public function is_server_ready($stack=false) {
$url = $this->get_url();
$returnval = true;
$client = new \search_elastic\esrequest($stack);

if (!$url) {
$returnval = get_string('noconfig', 'search_elastic');
} else {
$response = $client->get($url);
$responsecode = $response->getStatusCode();
public function is_server_ready($stack = false) {
// Not configured yet.
if (empty($this->get_url())) {
return get_string('connection:na', 'search_elastic');
}

if (isset($responsecode) && $responsecode != 200) {
$returnval = get_string('noserver', 'search_elastic');
// Test a connection to the configured server.
$status = $this->get_server_status_code($stack);

if ($status !== 200) {
return get_string('connection:status', 'search_elastic', [
'url' => $this->get_url(),
'status' => $status
]);
}

return $returnval;
return true;
}

/**
* Tests connection to the server and returns the HTTP status code.
*
* @param object|false $stack Optional custom Guzzle HTTP stack.
* @return int HTTP response code.
*/
public function get_server_status_code($stack = false): int {
$url = $this->get_url();
$client = new \search_elastic\esrequest($stack);

$response = $client->get($url);
$responsecode = $response->getStatusCode();

return $responsecode;
}

/**
Expand Down
5 changes: 4 additions & 1 deletion classes/esrequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ public function __construct($handler = false) {
$this->config = get_config('search_elastic');
$this->signing = (isset($this->config->signing) ? (bool)$this->config->signing : false);

$config = [
'connect_timeout' => intval($this->config->connecttimeout)
];

// Allow the caller to instantiate the Guzzle client with a custom handler.
$config = [];
if ($handler) {
$config['handler'] = $handler;
}
Expand Down
6 changes: 6 additions & 0 deletions lang/en/search_elastic.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
$string['boostsettings'] = 'Boosting settings';
$string['boostvalue'] = '';
$string['boostvalue_help'] = 'Set the value you want this search area to be boosted by in the search results. Higher boost values give more priority.';
$string['checkserver_ready_check'] = 'Elastic server connection';
$string['connectiontest'] = 'Server connection test';
$string['complexhelptext'] = 'The field to be searched may be specified by prefixing the search query with \'title:\', \'content:\', \'name:\', or \'intro:\'. For example, searching for \'title:news\' would return results with the word \'news\' in the title.
<br>
Boolean operators (\'AND\', \'OR\') may be used to combine or exclude keywords.
Expand All @@ -44,6 +46,10 @@
<br>
For more information, follow this link: {$a}';
$string['complexhelpurl'] = 'https://lucene.apache.org/core/2_9_4/queryparsersyntax.html';
$string['connection:na'] = 'Server not configured';
$string['connection:status'] = 'The configured elastic server at {$a->url} returned the status code {$a->status}';
$string['connecttimeout'] = 'Connect timeout (seconds)';
$string['connecttimeout_help'] = 'Guzzle connection timeout. Use 0 to disable. See https://docs.guzzlephp.org/en/stable/request-options.html#connect-timeout';
$string['enrichdesc'] = 'Global Search can enrich the indexed data used in search by extracting text and other data from files.
The data extracted from files in Moodle is controlled by the following groups of settings.';
$string['enrichsettings'] = 'Data enrichment settings';
Expand Down
8 changes: 8 additions & 0 deletions lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,11 @@ function search_elastic_extend_navigation_user() {
redirect(new moodle_url('/search/engine/elastic/index.php'));
}
}

/**
* Returns the status checks for this plugin.
* @return array
*/
function search_elastic_status_checks(): array {
return [new \search_elastic\check\server_ready_check()];
}
23 changes: 14 additions & 9 deletions settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,24 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

use search_elastic\admin_setting_check;
use search_elastic\check\server_ready_check;

defined('MOODLE_INTERNAL') || die();

if ($hassiteconfig) {
$ADMIN->add('searchplugins', new admin_category('search_elastic', get_string('pluginname', 'search_elastic')));
$settings = new admin_settingpage('elasticsettings', get_string('adminsettings', 'search_elastic'));

// Check status of the server.
$engine = new \search_elastic\engine();
$status = $engine->is_server_ready();
if ($status === true) {
$statustext = $OUTPUT->notification(get_string('reachable', 'search_elastic'), \core\output\notification::NOTIFY_SUCCESS);
} else {
$statustext = $OUTPUT->notification($status);
$settings->add(new admin_setting_heading('basicsettings', get_string('basicsettings', 'search_elastic'), ''));

// Only check status when when in full tree (i.e. not search)
// and only when viewing the elastic settings - this is because it can take a long time to run.
// We don't want it to run unnecessarily.
if ($ADMIN->fulltree && optional_param('section', null, PARAM_TEXT) == 'elasticsettings') {
$settings->add(new admin_setting_check('search_elastic/connectiontest', get_string('connectiontest', 'search_elastic'),
new server_ready_check()));
}

$settings->add(new admin_setting_heading('basicsettings', get_string('basicsettings', 'search_elastic'), $statustext));
$settings->add(new admin_setting_configtext('search_elastic/hostname', get_string ('hostname', 'search_elastic'),
get_string ('hostname_help', 'search_elastic'), 'http://127.0.0.1', PARAM_URL));

Expand All @@ -53,6 +55,9 @@
$settings->add(new admin_setting_configtext('search_elastic/apikey', get_string ('apikey', 'search_elastic'),
get_string ('apikey_help', 'search_elastic'), ''));

$settings->add(new admin_setting_configtext('search_elastic/connecttimeout', get_string('connecttimeout', 'search_elastic'),
get_string('connecttimeout_help', 'search_elastic'), 5, PARAM_INT));

$settings->add(new admin_setting_heading('signingsettings', get_string('signingsettings', 'search_elastic'), ''));
$settings->add(new admin_setting_configcheckbox('search_elastic/signing', get_string('signing', 'search_elastic'),
get_string ('signing_help', 'search_elastic'), 0));
Expand Down

0 comments on commit 4c2e4db

Please sign in to comment.