Skip to content

Commit

Permalink
Test Server Configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
Ioannis committed Oct 7, 2025
1 parent b7d403d commit 2c39279
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 3 deletions.
2 changes: 1 addition & 1 deletion app/plugins/CoreServer/src/CoreServerPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function bootstrap(PluginApplicationInterface $app): void
$oracleEnabled = \Cake\Core\Configure::read('registry.database.oracle.enable');

if($oracleEnabled === true) {
$app->addPlugin(\CakeDC\OracleDriver\Plugin::class, ['bootstrap' => true]);
$app->addPlugin(\Portal89\OracleDriver\Plugin::class, ['bootstrap' => true]);
}
}
catch(\Error $e) {
Expand Down
45 changes: 43 additions & 2 deletions app/plugins/CoreServer/src/Model/Table/SqlServersTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class SqlServersTable extends Table {
use \App\Lib\Traits\PrimaryLinkTrait;
use \App\Lib\Traits\TableMetaTrait;
use \App\Lib\Traits\ValidationTrait;
use \App\Lib\Traits\LabeledLogTrait;

/**
* Perform Cake Model initialization.
Expand Down Expand Up @@ -162,9 +163,11 @@ public function connect(int $serverId, string $name): bool {
// We don't test that the plugin is available here, an error should be thrown
// when we try to connect.

$dbconfig['className'] = 'CakeDC\OracleDriver\Database\OracleConnection';
$dbconfig['driver'] = 'CakeDC\OracleDriver\Database\Driver\OracleOCI'; // For OCI8
$dbconfig['className'] = 'Portal89\OracleDriver\Database\OracleConnection';
$dbconfig['driver'] = 'Portal89\OracleDriver\Database\Driver\OracleOCI'; // For OCI8
$dbconfig['quoteIdentifiers'] = true;
$dbconfig['init'] = [];
$dbconfig['flags'] = [];

// Use 'CakeDC\\OracleDriver\\Database\\Driver\\OraclePDO' for PDO_OCI, but CakeDC
// recommends OCI8
Expand All @@ -190,6 +193,44 @@ public function connect(int $serverId, string $name): bool {
return true;
}

/**
* Try to connect to the configured connection and run a minimal probe.
*
* @param string $name ConnectionManager name (eg: 'server42')
* @return bool True if the probe succeeds, false otherwise
*/
public function pingDb(string $name = 'my_temp_connection'): bool
{
try {
$conn = ConnectionManager::get($name);
// Force immediate connection attempt
$conn->connect();

// Use an engine-appropriate lightweight query
$sql = ($conn->getDriver() instanceof \Portal89\OracleDriver\Database\Driver\OracleOCI)
? 'SELECT 1 FROM DUAL'
: 'SELECT 1';

$val = $conn->execute($sql)->fetchColumn(0);
$ok = ((int)$val === 1);

if (!$ok) {
$this->llog(
'debug',
sprintf("DB ping for connection '%s' returned unexpected value: %s", $name, var_export($val, true))
);
}

return $ok;
} catch (\Throwable $e) {
$this->llog(
'error',
sprintf("DB ping failed for connection '%s': %s", $name, $e->getMessage())
);
return false;
}
}

/**
* Application Rule to determine if Oracle is enabled (if selected).
*
Expand Down
12 changes: 12 additions & 0 deletions app/resources/locales/en_US/operation.po
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ msgstr "Configure {0}"
msgid "configure.plugin"
msgstr "Configure Plugin"

msgid "connection.test"
msgstr "Test Connection"

msgid "continue"
msgstr "Continue"

Expand Down Expand Up @@ -327,6 +330,15 @@ msgstr "Resend"
msgid "resume"
msgstr "Resume"

msgid "rs.test.ok"
msgstr "Connection OK"

msgid "rs.test.error"
msgstr "Connection Error"

msgid "rs.test.na"
msgstr "Connection N/A"

msgid "save"
msgstr "Save"

Expand Down
62 changes: 62 additions & 0 deletions app/src/Controller/ServersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
namespace App\Controller;

// XXX not doing anything with Log yet
use App\Lib\Util\StringUtilities;
use Cake\Log\Log;

class ServersController extends StandardPluggableController {
Expand All @@ -38,4 +39,65 @@ class ServersController extends StandardPluggableController {
'Servers.description' => 'asc'
]
];


public function testconnection(string $id) {
// We basically implement a redirect here to facilitate view rendering.
// (We only need to map into the plugin on actual link click, instead of
// potentially many times on an index view for links that may not be used.)

/** var Cake\ORM\Table $table */
$table = $this->getCurrentTable();

$serverId = $this->request->getParam('pass')[0];
$serverObj = $table->findById($serverId)
->firstOrFail();

$pluginTable = $this->getTableLocator()->get($serverObj->plugin);
$pluginObj = $pluginTable->find()
->where([StringUtilities::tableToForeignKey($table) => $serverId])
->firstOrFail();

try {
if (method_exists($pluginTable, 'connect')) {
// Set the Connection Manager config
$connection = $pluginTable->connect((int)$serverId, 'server' . $serverId);

if (method_exists($pluginTable, 'pingDb')) {
// This is database. We need to ping the database to be sure
$ok = $pluginTable->pingDb('server' . (int)$serverId);
if ($ok) {
$this->Flash->success(__d('operation', 'rs.test.ok'));
Log::debug("Successfully connected to database server " . $serverId);
} else {
$this->Flash->error(__d('operation', 'rs.test.error'));
Log::error("Failed to connect to database server " . $serverId . ": Database ping failed");
}
} else {
if ($connection) {
$this->Flash->success(__d('operation', 'rs.test.ok'));
Log::debug("Successfully connected to server " . $serverId);
} else {
$this->Flash->error(__d('operation', 'rs.test.error'));
Log::error("Failed to connect to server " . $serverId . ": Connection failed");
}
}

} else {
$this->Flash->error(__d('operation', 'rs.test.na'));
}
} catch (\Exception $e) {
$this->Flash->error($e->getMessage());
}

$redirect = [
'controller' => 'Servers',
'action' => 'index',
'?' => [
'co_id' => $serverObj->co_id
]
];

return $this->redirect($redirect);
}
}
2 changes: 2 additions & 0 deletions app/src/Model/Table/ServersTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public function initialize(array $config): void {
$this->setDisplayField('description');

$this->setPrimaryLink('co_id');
$this->setAllowLookupPrimaryLink(['testconnection']);
$this->setRequiresCO(true);

$this->setAutoViewVars([
Expand All @@ -96,6 +97,7 @@ public function initialize(array $config): void {
// Actions that operate over an entity (ie: require an $id)
'entity' => [
'configure' => ['platformAdmin', 'coAdmin'],
'testconnection' => ['platformAdmin', 'coAdmin'],
'delete' => ['platformAdmin', 'coAdmin'],
'edit' => ['platformAdmin', 'coAdmin'],
'view' => ['platformAdmin', 'coAdmin']
Expand Down
5 changes: 5 additions & 0 deletions app/templates/Servers/columns.inc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ $rowActions = [
'action' => 'configure',
'label' => __d('operation', 'configure.plugin'),
'icon' => 'electrical_services'
],
[
'action' => 'testconnection',
'label' => __d('operation', 'connection.test'),
'icon' => 'fork_right'
]
];

Expand Down

0 comments on commit 2c39279

Please sign in to comment.