feat: restart database

feat: public dbs stay public after restart
feat: patch database conf
This commit is contained in:
Andras Bacsai 2024-07-02 13:39:44 +02:00
parent c39d6dd407
commit 3c13f1ff61
12 changed files with 471 additions and 140 deletions

View File

@ -0,0 +1,29 @@
<?php
namespace App\Actions\Database;
use App\Models\StandaloneClickhouse;
use App\Models\StandaloneDragonfly;
use App\Models\StandaloneKeydb;
use App\Models\StandaloneMariadb;
use App\Models\StandaloneMongodb;
use App\Models\StandaloneMysql;
use App\Models\StandalonePostgresql;
use App\Models\StandaloneRedis;
use Lorisleiva\Actions\Concerns\AsAction;
class RestartDatabase
{
use AsAction;
public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $database)
{
$server = $database->destination->server;
if (! $server->isFunctional()) {
return 'Server is not functional';
}
StopDatabase::run($database);
return StartDatabase::run($database);
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace App\Actions\Database;
use App\Models\StandaloneClickhouse;
use App\Models\StandaloneDragonfly;
use App\Models\StandaloneKeydb;
use App\Models\StandaloneMariadb;
use App\Models\StandaloneMongodb;
use App\Models\StandaloneMysql;
use App\Models\StandalonePostgresql;
use App\Models\StandaloneRedis;
use Lorisleiva\Actions\Concerns\AsAction;
class StartDatabase
{
use AsAction;
public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $database)
{
$server = $database->destination->server;
if (! $server->isFunctional()) {
return 'Server is not functional';
}
switch ($database->getMorphClass()) {
case 'App\Models\StandalonePostgresql':
$activity = StartPostgresql::run($database);
break;
case 'App\Models\StandaloneRedis':
$activity = StartRedis::run($database);
break;
case 'App\Models\StandaloneMongodb':
$activity = StartMongodb::run($database);
break;
case 'App\Models\StandaloneMysql':
$activity = StartMysql::run($database);
break;
case 'App\Models\StandaloneMariadb':
$activity = StartMariadb::run($database);
break;
case 'App\Models\StandaloneKeydb':
$activity = StartKeydb::run($database);
break;
case 'App\Models\StandaloneDragonfly':
$activity = StartDragonfly::run($database);
break;
case 'App\Models\StandaloneClickhouse':
$activity = StartClickhouse::run($database);
break;
}
if ($database->is_public && $database->public_port) {
StartDatabaseProxy::dispatch($database);
}
return $activity;
}
}

View File

@ -29,7 +29,5 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
if ($database->is_public) {
StopDatabaseProxy::run($database);
}
// TODO: make notification for services
// $database->environment->project->team->notify(new StatusChanged($database));
}
}

View File

@ -27,7 +27,6 @@ public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|St
$server = data_get($database, 'service.server');
}
instant_remote_process(["docker rm -f {$uuid}-proxy"], $server);
$database->is_public = false;
$database->save();
DatabaseStatusChanged::dispatch();
}

View File

@ -2,15 +2,10 @@
namespace App\Http\Controllers\Api;
use App\Actions\Database\StartClickhouse;
use App\Actions\Database\StartDragonfly;
use App\Actions\Database\StartKeydb;
use App\Actions\Database\StartMariadb;
use App\Actions\Database\StartMongodb;
use App\Actions\Database\StartMysql;
use App\Actions\Database\StartPostgresql;
use App\Actions\Database\StartRedis;
use App\Actions\Database\StartDatabase;
use App\Actions\Database\StartDatabaseProxy;
use App\Actions\Database\StopDatabase;
use App\Actions\Database\StopDatabaseProxy;
use App\Enums\NewDatabaseTypes;
use App\Http\Controllers\Controller;
use App\Models\Project;
@ -82,9 +77,114 @@ public function database_by_uuid(Request $request)
]);
}
public function update_by_uuid(Request $request)
{
$allowedFields = ['name', 'description', 'image', 'public_port', 'is_public', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database', 'mysql_root_password', 'mysql_user', 'mysql_database', 'mysql_conf'];
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
return invalidTokenResponse();
}
$return = validateIncomingRequest($request);
if ($return instanceof \Illuminate\Http\JsonResponse) {
return $return;
}
$validator = customApiValidator($request->all(), [
'name' => 'string|max:255',
'description' => 'string|nullable',
'image' => 'string',
'is_public' => 'boolean',
'public_port' => 'numeric|nullable',
'limits_memory' => 'string',
'limits_memory_swap' => 'string',
'limits_memory_swappiness' => 'numeric',
'limits_memory_reservation' => 'string',
'limits_cpus' => 'string',
'limits_cpuset' => 'string|nullable',
'limits_cpu_shares' => 'numeric',
'postgres_user' => 'string',
'postgres_password' => 'string',
'postgres_db' => 'string',
'postgres_initdb_args' => 'string',
'postgres_host_auth_method' => 'string',
'postgres_conf' => 'string',
'clickhouse_admin_user' => 'string',
'clickhouse_admin_password' => 'string',
'dragonfly_password' => 'string',
'redis_password' => 'string',
'redis_conf' => 'string',
'keydb_password' => 'string',
'keydb_conf' => 'string',
'mariadb_conf' => 'string',
'mariadb_root_password' => 'string',
'mariadb_user' => 'string',
'mariadb_password' => 'string',
'mariadb_database' => 'string',
'mongo_conf' => 'string',
'mongo_initdb_root_username' => 'string',
'mongo_initdb_root_password' => 'string',
'mongo_initdb_init_database' => 'string',
'mysql_root_password' => 'string',
'mysql_user' => 'string',
'mysql_database' => 'string',
'mysql_conf' => 'string',
]);
$extraFields = array_diff(array_keys($request->all()), $allowedFields);
if ($validator->fails() || ! empty($extraFields)) {
$errors = $validator->errors();
if (! empty($extraFields)) {
foreach ($extraFields as $field) {
$errors->add($field, 'This field is not allowed.');
}
}
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => $errors,
], 422);
}
$uuid = $request->uuid;
removeUnnecessaryFieldsFromRequest($request);
$database = queryDatabaseByUuidWithinTeam($uuid, $teamId);
if (! $database) {
return response()->json(['success' => false, 'message' => 'Database not found.'], 404);
}
if ($request->is_public && $request->public_port) {
if (isPublicPortAlreadyUsed($database->destination->server, $request->public_port, $database->id)) {
return response()->json(['success' => false, 'message' => 'Public port already used by another database.'], 400);
}
}
$whatToDoWithDatabaseProxy = null;
if ($request->is_public === false && $database->is_public === true) {
$whatToDoWithDatabaseProxy = 'stop';
}
if ($request->is_public === true && $request->public_port && $database->is_public === false) {
$whatToDoWithDatabaseProxy = 'start';
}
$database->update($request->all());
if ($whatToDoWithDatabaseProxy === 'start') {
StartDatabaseProxy::dispatch($database);
} elseif ($whatToDoWithDatabaseProxy === 'stop') {
StopDatabaseProxy::dispatch($database);
}
return response()->json([
'success' => true,
'message' => 'Database updated.',
'data' => $this->removeSensitiveData($database),
]);
}
public function create_database(Request $request)
{
$allowedFields = ['type', 'name', 'description', 'image', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'postgres_user', 'postgres_password', 'postgres_db', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares'];
$allowedFields = ['type', 'name', 'description', 'image', 'public_port', 'is_public', 'project_uuid', 'environment_name', 'server_uuid', 'destination_uuid', 'instant_deploy', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'postgres_user', 'postgres_password', 'postgres_db', 'postgres_initdb_args', 'postgres_host_auth_method', 'postgres_conf', 'clickhouse_admin_user', 'clickhouse_admin_password', 'dragonfly_password', 'redis_password', 'redis_conf', 'keydb_password', 'keydb_conf', 'mariadb_conf', 'mariadb_root_password', 'mariadb_user', 'mariadb_password', 'mariadb_database', 'mongo_conf', 'mongo_initdb_root_username', 'mongo_initdb_root_password', 'mongo_initdb_init_database', 'mysql_root_password', 'mysql_user', 'mysql_database', 'mysql_conf'];
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
return invalidTokenResponse();
@ -103,9 +203,8 @@ public function create_database(Request $request)
'environment_name' => 'string|required',
'server_uuid' => 'string|required',
'destination_uuid' => 'string',
'postgres_user' => 'string',
'postgres_password' => 'string',
'postgres_db' => 'string',
'is_public' => 'boolean',
'public_port' => 'numeric|nullable',
'limits_memory' => 'string',
'limits_memory_swap' => 'string',
'limits_memory_swappiness' => 'numeric',
@ -113,6 +212,32 @@ public function create_database(Request $request)
'limits_cpus' => 'string',
'limits_cpuset' => 'string|nullable',
'limits_cpu_shares' => 'numeric',
'postgres_user' => 'string',
'postgres_password' => 'string',
'postgres_db' => 'string',
'postgres_initdb_args' => 'string',
'postgres_host_auth_method' => 'string',
'postgres_conf' => 'string',
'clickhouse_admin_user' => 'string',
'clickhouse_admin_password' => 'string',
'dragonfly_password' => 'string',
'redis_password' => 'string',
'redis_conf' => 'string',
'keydb_password' => 'string',
'keydb_conf' => 'string',
'mariadb_conf' => 'string',
'mariadb_root_password' => 'string',
'mariadb_user' => 'string',
'mariadb_password' => 'string',
'mariadb_database' => 'string',
'mongo_conf' => 'string',
'mongo_initdb_root_username' => 'string',
'mongo_initdb_root_password' => 'string',
'mongo_initdb_init_database' => 'string',
'mysql_root_password' => 'string',
'mysql_user' => 'string',
'mysql_database' => 'string',
'mysql_conf' => 'string',
'instant_deploy' => 'boolean',
]);
@ -133,7 +258,9 @@ public function create_database(Request $request)
}
$serverUuid = $request->server_uuid;
$instantDeploy = $request->instant_deploy ?? false;
if ($request->is_public && ! $request->public_port) {
$request->offsetSet('is_public', false);
}
$project = Project::whereTeamId($teamId)->whereUuid($request->project_uuid)->first();
if (! $project) {
return response()->json(['succes' => false, 'message' => 'Project not found.'], 404);
@ -154,12 +281,41 @@ public function create_database(Request $request)
return response()->json(['success' => false, 'message' => 'Server has multiple destinations and you do not set destination_uuid.'], 400);
}
$destination = $destinations->first();
if ($request->has('public_port') && $request->is_public) {
if (isPublicPortAlreadyUsed($server, $request->public_port)) {
return response()->json(['success' => false, 'message' => 'Public port already used by another database.'], 400);
}
}
if ($request->type === NewDatabaseTypes::POSTGRESQL->value) {
removeUnnecessaryFieldsFromRequest($request);
if ($request->has('postgres_conf')) {
if (! isBase64Encoded($request->postgres_conf)) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'postgres_conf' => 'The postgres_conf should be base64 encoded.',
],
], 422);
}
$postgresConf = base64_decode($request->postgres_conf);
if (mb_detect_encoding($postgresConf, 'ASCII', true) === false) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'postgres_conf' => 'The postgres_conf should be base64 encoded.',
],
], 422);
}
$request->offsetSet('postgres_conf', $postgresConf);
}
$database = create_standalone_postgresql($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartPostgresql::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([
@ -169,9 +325,34 @@ public function create_database(Request $request)
]);
} elseif ($request->type === NewDatabaseTypes::MARIADB->value) {
removeUnnecessaryFieldsFromRequest($request);
if ($request->has('mariadb_conf')) {
if (! isBase64Encoded($request->mariadb_conf)) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'mariadb_conf' => 'The mariadb_conf should be base64 encoded.',
],
], 422);
}
$mariadbConf = base64_decode($request->mariadb_conf);
if (mb_detect_encoding($mariadbConf, 'ASCII', true) === false) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'mariadb_conf' => 'The mariadb_conf should be base64 encoded.',
],
], 422);
}
$request->offsetSet('mariadb_conf', $mariadbConf);
}
$database = create_standalone_mariadb($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartMariadb::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([
@ -181,9 +362,34 @@ public function create_database(Request $request)
]);
} elseif ($request->type === NewDatabaseTypes::MYSQL->value) {
removeUnnecessaryFieldsFromRequest($request);
if ($request->has('mysql_conf')) {
if (! isBase64Encoded($request->mysql_conf)) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'mysql_conf' => 'The mysql_conf should be base64 encoded.',
],
], 422);
}
$mysqlConf = base64_decode($request->mysql_conf);
if (mb_detect_encoding($mysqlConf, 'ASCII', true) === false) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'mysql_conf' => 'The mysql_conf should be base64 encoded.',
],
], 422);
}
$request->offsetSet('mysql_conf', $mysqlConf);
}
$database = create_standalone_mysql($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartMysql::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([
@ -193,9 +399,34 @@ public function create_database(Request $request)
]);
} elseif ($request->type === NewDatabaseTypes::REDIS->value) {
removeUnnecessaryFieldsFromRequest($request);
if ($request->has('redis_conf')) {
if (! isBase64Encoded($request->redis_conf)) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'redis_conf' => 'The redis_conf should be base64 encoded.',
],
], 422);
}
$redisConf = base64_decode($request->redis_conf);
if (mb_detect_encoding($redisConf, 'ASCII', true) === false) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'redis_conf' => 'The redis_conf should be base64 encoded.',
],
], 422);
}
$request->offsetSet('redis_conf', $redisConf);
}
$database = create_standalone_redis($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartRedis::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([
@ -207,7 +438,10 @@ public function create_database(Request $request)
removeUnnecessaryFieldsFromRequest($request);
$database = create_standalone_dragonfly($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartDragonfly::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([
@ -217,9 +451,34 @@ public function create_database(Request $request)
]);
} elseif ($request->type === NewDatabaseTypes::KEYDB->value) {
removeUnnecessaryFieldsFromRequest($request);
if ($request->has('keydb_conf')) {
if (! isBase64Encoded($request->keydb_conf)) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'keydb_conf' => 'The keydb_conf should be base64 encoded.',
],
], 422);
}
$keydbConf = base64_decode($request->keydb_conf);
if (mb_detect_encoding($keydbConf, 'ASCII', true) === false) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'keydb_conf' => 'The keydb_conf should be base64 encoded.',
],
], 422);
}
$request->offsetSet('keydb_conf', $keydbConf);
}
$database = create_standalone_keydb($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartKeydb::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([
@ -231,7 +490,10 @@ public function create_database(Request $request)
removeUnnecessaryFieldsFromRequest($request);
$database = create_standalone_clickhouse($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartClickhouse::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([
@ -241,9 +503,34 @@ public function create_database(Request $request)
]);
} elseif ($request->type === NewDatabaseTypes::MONGODB->value) {
removeUnnecessaryFieldsFromRequest($request);
if ($request->has('mongo_conf')) {
if (! isBase64Encoded($request->mongo_conf)) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'mongo_conf' => 'The mongo_conf should be base64 encoded.',
],
], 422);
}
$mongoConf = base64_decode($request->mongo_conf);
if (mb_detect_encoding($mongoConf, 'ASCII', true) === false) {
return response()->json([
'success' => false,
'message' => 'Validation failed.',
'errors' => [
'mongo_conf' => 'The mongo_conf should be base64 encoded.',
],
], 422);
}
$request->offsetSet('mongo_conf', $mongoConf);
}
$database = create_standalone_mongodb($environment->id, $destination->uuid, $request->all());
if ($instantDeploy) {
StartMongodb::dispatch($database);
StartDatabase::dispatch($database);
if ($request->is_public && $request->public_port) {
StartDatabaseProxy::dispatch($database);
}
}
return response()->json([

View File

@ -2,14 +2,7 @@
namespace App\Http\Controllers\Api;
use App\Actions\Database\StartClickhouse;
use App\Actions\Database\StartDragonfly;
use App\Actions\Database\StartKeydb;
use App\Actions\Database\StartMariadb;
use App\Actions\Database\StartMongodb;
use App\Actions\Database\StartMysql;
use App\Actions\Database\StartPostgresql;
use App\Actions\Database\StartRedis;
use App\Actions\Database\StartDatabase;
use App\Actions\Service\StartService;
use App\Http\Controllers\Controller;
use App\Models\ApplicationDeploymentQueue;
@ -192,66 +185,28 @@ public function deploy_resource($resource, bool $force = false): array
if (gettype($resource) !== 'object') {
return ['success' => false, 'message' => "Resource ($resource) not found.", 'deployment_uuid' => $deployment_uuid];
}
$type = $resource?->getMorphClass();
if ($type === 'App\Models\Application') {
$deployment_uuid = new Cuid2(7);
queue_application_deployment(
application: $resource,
deployment_uuid: $deployment_uuid,
force_rebuild: $force,
);
$message = "Application {$resource->name} deployment queued.";
} elseif ($type === 'App\Models\StandalonePostgresql') {
StartPostgresql::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\StandaloneRedis') {
StartRedis::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\StandaloneKeydb') {
StartKeydb::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\StandaloneDragonfly') {
StartDragonfly::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\StandaloneClickhouse') {
StartClickhouse::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\StandaloneMongodb') {
StartMongodb::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\StandaloneMysql') {
StartMysql::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\StandaloneMariadb') {
StartMariadb::run($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
} elseif ($type === 'App\Models\Service') {
StartService::run($resource);
$message = "Service {$resource->name} started. It could take a while, be patient.";
switch ($resource?->getMorphClass()) {
case 'App\Models\Application':
$deployment_uuid = new Cuid2(7);
queue_application_deployment(
application: $resource,
deployment_uuid: $deployment_uuid,
force_rebuild: $force,
);
$message = "Application {$resource->name} deployment queued.";
break;
case 'App\Models\Service':
StartService::run($resource);
$message = "Service {$resource->name} started. It could take a while, be patient.";
break;
default:
// Database resource
StartDatabase::dispatch($resource);
$resource->update([
'started_at' => now(),
]);
$message = "Database {$resource->name} started.";
break;
}
return ['success' => true, 'message' => $message, 'deployment_uuid' => $deployment_uuid];

View File

@ -2,14 +2,8 @@
namespace App\Livewire\Project\Database;
use App\Actions\Database\StartClickhouse;
use App\Actions\Database\StartDragonfly;
use App\Actions\Database\StartKeydb;
use App\Actions\Database\StartMariadb;
use App\Actions\Database\StartMongodb;
use App\Actions\Database\StartMysql;
use App\Actions\Database\StartPostgresql;
use App\Actions\Database\StartRedis;
use App\Actions\Database\RestartDatabase;
use App\Actions\Database\StartDatabase;
use App\Actions\Database\StopDatabase;
use App\Actions\Docker\GetContainersStatus;
use Livewire\Component;
@ -47,7 +41,6 @@ public function activityFinished()
public function check_status($showNotification = false)
{
GetContainersStatus::run($this->database->destination->server);
// dispatch_sync(new ContainerStatusJob($this->database->destination->server));
$this->database->refresh();
if ($showNotification) {
$this->dispatch('success', 'Database status updated.');
@ -67,32 +60,15 @@ public function stop()
$this->check_status();
}
public function restart()
{
$activity = RestartDatabase::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
}
public function start()
{
if ($this->database->type() === 'standalone-postgresql') {
$activity = StartPostgresql::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
} elseif ($this->database->type() === 'standalone-redis') {
$activity = StartRedis::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
} elseif ($this->database->type() === 'standalone-mongodb') {
$activity = StartMongodb::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
} elseif ($this->database->type() === 'standalone-mysql') {
$activity = StartMysql::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
} elseif ($this->database->type() === 'standalone-mariadb') {
$activity = StartMariadb::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
} elseif ($this->database->type() === 'standalone-keydb') {
$activity = StartKeydb::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
} elseif ($this->database->type() === 'standalone-dragonfly') {
$activity = StartDragonfly::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
} elseif ($this->database->type() === 'standalone-clickhouse') {
$activity = StartClickhouse::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
}
$activity = StartDatabase::run($this->database);
$this->dispatch('activityMonitor', $activity->id);
}
}

View File

@ -27,10 +27,7 @@ class General extends Component
public function getListeners()
{
$userId = auth()->user()->id;
return [
"echo-private:user.{$userId},DatabaseStatusChanged" => 'database_stopped',
'refresh',
'save_init_script',
'delete_init_script',
@ -77,11 +74,6 @@ public function mount()
$this->server = data_get($this->database, 'destination.server');
}
public function database_stopped()
{
$this->dispatch('success', 'Database proxy stopped. Database is no longer publicly accessible.');
}
public function instantSaveAdvanced()
{
try {

View File

@ -151,6 +151,14 @@ function validateIncomingRequest(Request $request)
'error' => 'Invalid JSON.',
], 400);
}
// check if valid json is empty
if (empty($request->json()->all())) {
return response()->json([
'success' => false,
'message' => 'Invalid request.',
'error' => 'Empty JSON.',
], 400);
}
}
function removeUnnecessaryFieldsFromRequest(Request $request)

View File

@ -178,9 +178,6 @@ function create_standalone_clickhouse($environment_id, $destination_uuid, ?array
return $database;
}
/**
* Delete file locally on the filesystem.
*/
function delete_backup_locally(?string $filename, Server $server): void
{
if (empty($filename)) {
@ -188,3 +185,17 @@ function delete_backup_locally(?string $filename, Server $server): void
}
instant_remote_process(["rm -f \"{$filename}\""], $server, throwError: false);
}
function isPublicPortAlreadyUsed(Server $server, int $port, ?string $id = null): bool
{
if ($id) {
$foundDatabase = $server->databases()->where('public_port', $port)->where('is_public', true)->where('id', '!=', $id)->first();
} else {
$foundDatabase = $server->databases()->where('public_port', $port)->where('is_public', true)->first();
}
if ($foundDatabase) {
return true;
}
return false;
}

View File

@ -7,7 +7,8 @@
</x-slot:content>
</x-slide-over>
<div class="navbar-main">
<nav class="flex items-center flex-shrink-0 gap-6 overflow-x-scroll sm:overflow-x-hidden scrollbar min-h-10 whitespace-nowrap">
<nav
class="flex items-center flex-shrink-0 gap-6 overflow-x-scroll sm:overflow-x-hidden scrollbar min-h-10 whitespace-nowrap">
<a class="{{ request()->routeIs('project.database.configuration') ? 'dark:text-white' : '' }}"
href="{{ route('project.database.configuration', $parameters) }}">
<button>Configuration</button>
@ -33,6 +34,19 @@
</nav>
<div class="flex flex-wrap items-center gap-2">
@if (!str($database->status)->startsWith('exited'))
<x-modal-confirmation @click="$wire.dispatch('restartEvent')">
<x-slot:button-title>
<svg class="w-5 h-5 dark:text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<path d="M19.933 13.041a8 8 0 1 1-9.925-8.788c3.899-1 7.935 1.007 9.425 4.747" />
<path d="M20 4v5h-5" />
</g>
</svg>
Restart
</x-slot:button-title>
This database will be restarted. <br>Please think again.
</x-modal-confirmation>
<x-modal-confirmation @click="$wire.dispatch('stopEvent')">
<x-slot:button-title>
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24"
@ -69,6 +83,10 @@
$wire.$dispatch('info', 'Stopping database.');
$wire.$call('stop');
});
$wire.$on('restartEvent', () => {
$wire.$dispatch('info', 'Restarting database.');
$wire.$call('restart');
});
</script>
@endscript
</div>

View File

@ -120,7 +120,8 @@
Route::get('/databases', [DatabasesController::class, 'databases']);
Route::post('/databases', [DatabasesController::class, 'create_database'])->middleware([ReadOnlyApiToken::class]);
Route::get('/databases/{uuid}', [DatabasesController::class, 'database_by_uuid']);
// Route::patch('/databases/{uuid}', [DatabasesController::class, 'update_by_uuid']);
Route::patch('/databases/{uuid}', [DatabasesController::class, 'update_by_uuid'])->middleware([ReadOnlyApiToken::class]);
Route::delete('/databases/{uuid}', [DatabasesController::class, 'delete_by_uuid'])->middleware([ReadOnlyApiToken::class]);
Route::delete('/envs/{env_uuid}', [EnvironmentVariablesController::class, 'delete_env_by_uuid'])->middleware([ReadOnlyApiToken::class]);