Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Database Hosts to have multiple Nodes #724

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,13 @@ public function form(Form $form): Form
->revealable()
->maxLength(255)
->required(),
Select::make('node_id')
Select::make('node_ids')
->multiple()
->searchable()
->preload()
->helperText('This setting only defaults to this database host when adding a database to a server on the selected node.')
->label('Linked Node')
->relationship('node', 'name'),
->label('Linked Nodes')
->relationship('nodes', 'name'),
]),
]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ public function form(Form $form): Form
->password()
->revealable()
->maxLength(255),
Select::make('node_id')
Select::make('nodes')
->multiple()
->searchable()
->preload()
->helperText('This setting only defaults to this database host when adding a database to a server on the selected node.')
->label('Linked Node')
->relationship('node', 'name'),
->label('Linked Nodes')
->relationship('nodes', 'name'),
]),
]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ public function table(Table $table): Table
->counts('databases')
->icon('tabler-database')
->label('Databases'),
TextColumn::make('node.name')
TextColumn::make('nodes.name')
->icon('tabler-server-2')
->badge()
->placeholder('No Nodes')
->sortable(),
])
Expand Down
15 changes: 6 additions & 9 deletions app/Models/DatabaseHost.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
* @property int $id
Expand Down Expand Up @@ -39,7 +39,7 @@ class DatabaseHost extends Model
* Fields that are mass assignable.
*/
protected $fillable = [
'name', 'host', 'port', 'username', 'password', 'max_databases', 'node_id',
'name', 'host', 'port', 'username', 'password', 'max_databases',
];

/**
Expand All @@ -51,15 +51,15 @@ class DatabaseHost extends Model
'port' => 'required|numeric|between:1,65535',
'username' => 'required|string|max:32',
'password' => 'nullable|string',
'node_id' => 'sometimes|nullable|integer|exists:nodes,id',
'node_ids' => 'nullable|array',
'node_ids.*' => 'required|integer,exists:nodes,id',
];

protected function casts(): array
{
return [
'id' => 'integer',
'max_databases' => 'integer',
'node_id' => 'integer',
'password' => 'encrypted',
'created_at' => 'immutable_datetime',
'updated_at' => 'immutable_datetime',
Expand All @@ -71,12 +71,9 @@ public function getRouteKeyName(): string
return 'id';
}

/**
* Gets the node associated with a database host.
*/
public function node(): BelongsTo
public function nodes(): BelongsToMany
{
return $this->belongsTo(Node::class);
return $this->belongsToMany(Node::class);
}

/**
Expand Down
6 changes: 6 additions & 0 deletions app/Models/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Exceptions\Service\HasActiveServersException;
use App\Repositories\Daemon\DaemonConfigurationRepository;
use Exception;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Notifications\Notifiable;
Expand Down Expand Up @@ -381,4 +382,9 @@ public function ipAddresses(): array
return $ips->all();
});
}

public function databaseHosts(): BelongsToMany
{
return $this->belongsToMany(DatabaseHost::class);
}
}
12 changes: 6 additions & 6 deletions app/Services/Databases/DeployServerDatabaseService.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ public function handle(Server $server, array $data): Database
Assert::notEmpty($data['database'] ?? null);
Assert::notEmpty($data['remote'] ?? null);

$hosts = DatabaseHost::query()->get()->toBase();
$hosts = DatabaseHost::query()->get();
if ($hosts->isEmpty()) {
throw new NoSuitableDatabaseHostException();
} else {
$nodeHosts = $hosts->where('node_id', $server->node_id)->toBase();
}

if ($nodeHosts->isEmpty() && !config('panel.client_features.databases.allow_random')) {
throw new NoSuitableDatabaseHostException();
}
$nodeHosts = $server->node->databaseHosts()->get();
// TODO: @areyouscared remove allow random feature for database hosts
if ($nodeHosts->isEmpty() && !config('panel.client_features.databases.allow_random')) {
throw new NoSuitableDatabaseHostException();
}

return $this->managementService->create($server, [
Expand Down
3 changes: 2 additions & 1 deletion app/Services/Databases/Hosts/HostCreationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ public function handle(array $data): DatabaseHost
'port' => array_get($data, 'port'),
'username' => array_get($data, 'username'),
'max_databases' => array_get($data, 'max_databases'),
'node_id' => array_get($data, 'node_id'),
]);

$host->nodes()->sync(array_get($data, 'node_ids', []));

// Confirm access using the provided credentials before saving data.
$this->dynamic->set('dynamic', $host);
$this->databaseManager->connection('dynamic')->getPdo();
Expand Down
12 changes: 5 additions & 7 deletions app/Transformers/Api/Application/DatabaseHostTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
use App\Models\Node;
use App\Models\Database;
use App\Models\DatabaseHost;
use League\Fractal\Resource\Item;
use League\Fractal\Resource\Collection;
use League\Fractal\Resource\NullResource;

class DatabaseHostTransformer extends BaseTransformer
{
protected array $availableIncludes = [
'databases',
'node',
'nodes',
];

/**
Expand All @@ -35,7 +34,6 @@ public function transform(DatabaseHost $model): array
'host' => $model->host,
'port' => $model->port,
'username' => $model->username,
'node' => $model->node_id,
'created_at' => $model->created_at->toAtomString(),
'updated_at' => $model->updated_at->toAtomString(),
];
Expand All @@ -56,16 +54,16 @@ public function includeDatabases(DatabaseHost $model): Collection|NullResource
}

/**
* Include the node associated with this host.
* Include the nodes associated with this host.
*/
public function includeNode(DatabaseHost $model): Item|NullResource
public function includeNodes(DatabaseHost $model): Collection|NullResource
{
if (!$this->authorize(Node::RESOURCE_NAME)) {
return $this->null();
}

$model->loadMissing('node');
$model->loadMissing('nodes');

return $this->item($model->getRelation('node'), $this->makeTransformer(NodeTransformer::class), Node::RESOURCE_NAME);
return $this->collection($model->getRelation('nodes'), $this->makeTransformer(NodeTransformer::class), Node::RESOURCE_NAME);
}
}
26 changes: 15 additions & 11 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public function up(): void
$table->dropIndex('permissions_server_id_foreign');
$table->dropForeign('permissions_user_id_foreign');
$table->dropIndex('permissions_user_id_foreign');
} else {
$table->dropForeign(['server_id']);
$table->dropForeign(['user_id']);
}

$table->dropColumn('server_id');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
public function up(): void
{
Schema::table('servers', function (Blueprint $table) {
if (Schema::getConnection()->getDriverName() !== 'sqlite') {
$table->dropForeign(['pack_id']);
}

$table->dropForeign(['pack_id']);
$table->dropColumn('pack_id');
});
}
Expand Down
7 changes: 4 additions & 3 deletions database/migrations/2024_03_12_154408_remove_nests_table.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ public function up(): void
Schema::table('eggs', function (Blueprint $table) {
if (Schema::getConnection()->getDriverName() !== 'sqlite') {
$table->dropForeign('service_options_nest_id_foreign');
} else {
$table->dropForeign(['nest_id']);
}

$table->dropColumn('nest_id');
});

Schema::table('servers', function (Blueprint $table) {
if (Schema::getConnection()->getDriverName() !== 'sqlite') {
$table->dropForeign('servers_nest_id_foreign');
}
$table->dropForeign(['nest_id']);
$table->dropColumn('nest_id');
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@ public function up(): void
}

Schema::table('nodes', function (Blueprint $table) {
if (Schema::getConnection()->getDriverName() !== 'sqlite') {
$table->dropForeign('nodes_location_id_foreign');
}

$table->dropForeign(['location_id']);
$table->dropColumn('location_id');
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('database_host_node', function (Blueprint $table) {
$table->id();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$table->id();
$table->id();
$table->unsignedInteger('node_id');

$table->foreignId('node_id')->references('id')->on('nodes');
$table->foreignId('database_host_id')->references('id')->on('database_hosts');
$table->timestamps();
});

$databaseNodes = DB::table('database_hosts')->whereNotNull('node_id')->get();
$newJoinEntries = $databaseNodes->map(fn ($record) => [
'node_id' => $record->node_id,
'database_host_id' => $record->id,
'created_at' => now(),
'updated_at' => now(),
]);

DB::table('database_host_node')->insert($newJoinEntries->toArray());

Schema::table('database_hosts', function (Blueprint $table) {
$table->dropForeign(['node_id']);
$table->dropColumn('node_id');
});
}

public function down(): void
{
Schema::table('database_hosts', function (Blueprint $table) {
$table->foreignId('node_id')->nullable()->references('id')->on('nodes');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$table->foreignId('node_id')->nullable()->references('id')->on('nodes');
$table->unsignedInteger('node_id')->nullable();
$table->foreignId('node_id')->references('id')->on('nodes');

});

foreach (DB::table('database_host_node')->get() as $record) {
DB::table('database_hosts')
->where('id', $record->database_host_id)
->update(['node_id' => $record->node_id]);
}

Schema::drop('database_host_node');
}
};
Loading
Loading