From c53d88902c0069bf7ce083fd9a62f87a0c4ed632 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 19 Oct 2023 13:32:03 +0200 Subject: [PATCH] feat: standalone mongodb --- app/Actions/Database/StartDatabaseProxy.php | 9 +- app/Actions/Database/StartMongodb.php | 165 ++++++++++++++++++ app/Actions/Database/StopDatabase.php | 4 +- app/Actions/Database/StopDatabaseProxy.php | 3 +- app/Http/Controllers/ProjectController.php | 2 + .../Livewire/Project/Database/Heading.php | 5 + .../Project/Database/Mongodb/General.php | 98 +++++++++++ .../Shared/EnvironmentVariable/All.php | 3 + app/Http/Livewire/Project/Shared/GetLogs.php | 7 +- app/Http/Livewire/Project/Shared/Logs.php | 9 +- app/Jobs/StopResourceJob.php | 6 +- app/Models/Environment.php | 13 +- app/Models/Server.php | 3 +- app/Models/StandaloneDocker.php | 5 + app/Models/StandaloneMongodb.php | 93 ++++++++++ app/Models/StandaloneRedis.php | 2 - bootstrap/helpers/constants.php | 2 +- bootstrap/helpers/databases.php | 16 ++ .../factories/StandaloneMongoDBFactory.php | 23 +++ ...01331_create_standalone_mongodbs_table.php | 56 ++++++ ...mongodb_to_environment_variables_table.php | 28 +++ docker-compose.dev.yml | 8 +- .../database/mongodb/general.blade.php | 52 ++++++ .../database/postgresql/general.blade.php | 2 +- .../project/database/redis/general.blade.php | 2 +- .../livewire/project/new/select.blade.php | 9 + .../project/shared/get-logs.blade.php | 8 +- .../project/database/configuration.blade.php | 3 + 28 files changed, 611 insertions(+), 25 deletions(-) create mode 100644 app/Actions/Database/StartMongodb.php create mode 100644 app/Http/Livewire/Project/Database/Mongodb/General.php create mode 100644 app/Models/StandaloneMongodb.php create mode 100644 database/factories/StandaloneMongoDBFactory.php create mode 100644 database/migrations/2023_10_19_101331_create_standalone_mongodbs_table.php create mode 100644 database/migrations/2023_10_19_101332_add_standalone_mongodb_to_environment_variables_table.php create mode 100644 resources/views/livewire/project/database/mongodb/general.blade.php diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index eccdf1a6a..15009019d 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -2,6 +2,7 @@ namespace App\Actions\Database; +use App\Models\StandaloneMongodb; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; use Lorisleiva\Actions\Concerns\AsAction; @@ -11,13 +12,15 @@ class StartDatabaseProxy { use AsAction; - public function handle(StandaloneRedis|StandalonePostgresql $database) + public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb $database) { $internalPort = null; - if ($database->getMorphClass()=== 'App\Models\StandaloneRedis') { + if ($database->getMorphClass() === 'App\Models\StandaloneRedis') { $internalPort = 6379; - } else if ($database->getMorphClass()=== 'App\Models\StandalonePostgresql') { + } else if ($database->getMorphClass() === 'App\Models\StandalonePostgresql') { $internalPort = 5432; + } else if ($database->getMorphClass() === 'App\Models\StandaloneMongodb') { + $internalPort = 27017; } $containerName = "{$database->uuid}-proxy"; $configuration_dir = database_proxy_dir($database->uuid); diff --git a/app/Actions/Database/StartMongodb.php b/app/Actions/Database/StartMongodb.php new file mode 100644 index 000000000..39d1b99b3 --- /dev/null +++ b/app/Actions/Database/StartMongodb.php @@ -0,0 +1,165 @@ +database = $database; + + $startCommand = "mongod"; + + $container_name = $this->database->uuid; + $this->configuration_dir = database_configuration_dir() . '/' . $container_name; + + $this->commands = [ + "echo '####### Starting {$database->name}.'", + "mkdir -p $this->configuration_dir", + ]; + + $persistent_storages = $this->generate_local_persistent_volumes(); + $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); + $environment_variables = $this->generate_environment_variables(); + $this->add_custom_mongo_conf(); + + $docker_compose = [ + 'version' => '3.8', + 'services' => [ + $container_name => [ + 'image' => $this->database->image, + 'command' => $startCommand, + 'container_name' => $container_name, + 'environment' => $environment_variables, + 'restart' => RESTART_MODE, + 'networks' => [ + $this->database->destination->network, + ], + 'labels' => [ + 'coolify.managed' => 'true', + ], + 'healthcheck' => [ + 'test' => [ + 'CMD-SHELL', + 'mongo --eval "printjson(db.serverStatus())" | grep uptime | grep -v grep' + ], + 'interval' => '5s', + 'timeout' => '5s', + 'retries' => 10, + 'start_period' => '5s' + ], + 'mem_limit' => $this->database->limits_memory, + 'memswap_limit' => $this->database->limits_memory_swap, + 'mem_swappiness' => $this->database->limits_memory_swappiness, + 'mem_reservation' => $this->database->limits_memory_reservation, + 'cpus' => $this->database->limits_cpus, + 'cpuset' => $this->database->limits_cpuset, + 'cpu_shares' => $this->database->limits_cpu_shares, + ] + ], + 'networks' => [ + $this->database->destination->network => [ + 'external' => true, + 'name' => $this->database->destination->network, + 'attachable' => true, + ] + ] + ]; + if (count($this->database->ports_mappings_array) > 0) { + $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; + } + if (count($persistent_storages) > 0) { + $docker_compose['services'][$container_name]['volumes'] = $persistent_storages; + } + if (count($volume_names) > 0) { + $docker_compose['volumes'] = $volume_names; + } + if (!is_null($this->database->mongo_conf)) { + $docker_compose['services'][$container_name]['volumes'][] = [ + 'type' => 'bind', + 'source' => $this->configuration_dir . '/mongod.conf', + 'target' => '/etc/mongo/mongod.conf', + 'read_only' => true, + ]; + $docker_compose['services'][$container_name]['command'] = $startCommand . ' --config /etc/mongo/mongod.conf'; + } + $docker_compose = Yaml::dump($docker_compose, 10); + $docker_compose_base64 = base64_encode($docker_compose); + $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d > $this->configuration_dir/docker-compose.yml"; + $readme = generate_readme_file($this->database->name, now()); + $this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md"; + $this->commands[] = "docker compose -f $this->configuration_dir/docker-compose.yml up -d"; + $this->commands[] = "echo '####### {$database->name} started.'"; + return remote_process($this->commands, $server); + } + + private function generate_local_persistent_volumes() + { + $local_persistent_volumes = []; + foreach ($this->database->persistentStorages as $persistentStorage) { + $volume_name = $persistentStorage->host_path ?? $persistentStorage->name; + $local_persistent_volumes[] = $volume_name . ':' . $persistentStorage->mount_path; + } + return $local_persistent_volumes; + } + + private function generate_local_persistent_volumes_only_volume_names() + { + $local_persistent_volumes_names = []; + foreach ($this->database->persistentStorages as $persistentStorage) { + if ($persistentStorage->host_path) { + continue; + } + $name = $persistentStorage->name; + $local_persistent_volumes_names[$name] = [ + 'name' => $name, + 'external' => false, + ]; + } + return $local_persistent_volumes_names; + } + + private function generate_environment_variables() + { + $environment_variables = collect(); + foreach ($this->database->runtime_environment_variables as $env) { + $environment_variables->push("$env->key=$env->value"); + } + + if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_ROOT_USERNAME'))->isEmpty()) { + $environment_variables->push("MONGO_INITDB_ROOT_USERNAME={$this->database->mongo_initdb_root_username}"); + } + + if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_ROOT_PASSWORD'))->isEmpty()) { + $environment_variables->push("MONGO_INITDB_ROOT_PASSWORD={$this->database->mongo_initdb_root_password}"); + } + + if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('MONGO_INITDB_DATABASE'))->isEmpty()) { + $environment_variables->push("MONGO_INITDB_DATABASE={$this->database->mongo_initdb_database}"); + } + return $environment_variables->all(); + } + private function add_custom_mongo_conf() + { + if (is_null($this->database->mongo_conf)) { + return; + } + $filename = 'mongod.conf'; + $content = $this->database->mongo_conf; + $content_base64 = base64_encode($content); + $this->commands[] = "echo '{$content_base64}' | base64 -d > $this->configuration_dir/{$filename}"; + + } +} diff --git a/app/Actions/Database/StopDatabase.php b/app/Actions/Database/StopDatabase.php index ee1913f06..7e3f5f4c2 100644 --- a/app/Actions/Database/StopDatabase.php +++ b/app/Actions/Database/StopDatabase.php @@ -2,16 +2,16 @@ namespace App\Actions\Database; +use App\Models\StandaloneMongodb; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; -use App\Notifications\Application\StatusChanged; use Lorisleiva\Actions\Concerns\AsAction; class StopDatabase { use AsAction; - public function handle(StandaloneRedis|StandalonePostgresql $database) + public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb $database) { $server = $database->destination->server; instant_remote_process( diff --git a/app/Actions/Database/StopDatabaseProxy.php b/app/Actions/Database/StopDatabaseProxy.php index ba836ec3a..840e8ed56 100644 --- a/app/Actions/Database/StopDatabaseProxy.php +++ b/app/Actions/Database/StopDatabaseProxy.php @@ -2,6 +2,7 @@ namespace App\Actions\Database; +use App\Models\StandaloneMongodb; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; use Lorisleiva\Actions\Concerns\AsAction; @@ -10,7 +11,7 @@ class StopDatabaseProxy { use AsAction; - public function handle(StandaloneRedis|StandalonePostgresql $database) + public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb $database) { instant_remote_process(["docker rm -f {$database->uuid}-proxy"], $database->destination->server); $database->is_public = false; diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php index 7e67a588c..1d1a5b14e 100644 --- a/app/Http/Controllers/ProjectController.php +++ b/app/Http/Controllers/ProjectController.php @@ -63,6 +63,8 @@ class ProjectController extends Controller $database = create_standalone_postgresql($environment->id, $destination_uuid); } else if ($type->value() === 'redis') { $database = create_standalone_redis($environment->id, $destination_uuid); + } else if ($type->value() === 'mongodb') { + $database = create_standalone_mongodb($environment->id, $destination_uuid); } return redirect()->route('project.database.configuration', [ 'project_uuid' => $project->uuid, diff --git a/app/Http/Livewire/Project/Database/Heading.php b/app/Http/Livewire/Project/Database/Heading.php index fc867ce79..1a199ecb7 100644 --- a/app/Http/Livewire/Project/Database/Heading.php +++ b/app/Http/Livewire/Project/Database/Heading.php @@ -2,6 +2,7 @@ namespace App\Http\Livewire\Project\Database; +use App\Actions\Database\StartMongodb; use App\Actions\Database\StartPostgresql; use App\Actions\Database\StartRedis; use App\Actions\Database\StopDatabase; @@ -53,5 +54,9 @@ class Heading extends Component $activity = StartRedis::run($this->database->destination->server, $this->database); $this->emit('newMonitorActivity', $activity->id); } + if ($this->database->type() === 'standalone-mongodb') { + $activity = StartMongodb::run($this->database->destination->server, $this->database); + $this->emit('newMonitorActivity', $activity->id); + } } } diff --git a/app/Http/Livewire/Project/Database/Mongodb/General.php b/app/Http/Livewire/Project/Database/Mongodb/General.php new file mode 100644 index 000000000..c6665f94d --- /dev/null +++ b/app/Http/Livewire/Project/Database/Mongodb/General.php @@ -0,0 +1,98 @@ + 'required', + 'database.description' => 'nullable', + 'database.mongo_conf' => 'nullable', + 'database.mongo_initdb_root_username' => 'required', + 'database.mongo_initdb_root_password' => 'required', + 'database.mongo_initdb_database' => 'required', + 'database.image' => 'required', + 'database.ports_mappings' => 'nullable', + 'database.is_public' => 'nullable|boolean', + 'database.public_port' => 'nullable|integer', + ]; + protected $validationAttributes = [ + 'database.name' => 'Name', + 'database.description' => 'Description', + 'database.mongo_conf' => 'Mongo Configuration', + 'database.mongo_initdb_root_username' => 'Root Username', + 'database.mongo_initdb_root_password' => 'Root Password', + 'database.mongo_initdb_database' => 'Database', + 'database.image' => 'Image', + 'database.ports_mappings' => 'Port Mapping', + 'database.is_public' => 'Is Public', + 'database.public_port' => 'Public Port', + ]; + public function submit() { + try { + $this->validate(); + if ($this->database->mongo_conf === "") { + $this->database->mongo_conf = null; + } + $this->database->save(); + $this->emit('success', 'Database updated successfully.'); + } catch (Exception $e) { + return handleError($e, $this); + } + } + public function instantSave() + { + try { + if ($this->database->is_public && !$this->database->public_port) { + $this->emit('error', 'Public port is required.'); + $this->database->is_public = false; + return; + } + if ($this->database->is_public) { + $this->emit('success', 'Starting TCP proxy...'); + StartDatabaseProxy::run($this->database); + $this->emit('success', 'Database is now publicly accessible.'); + } else { + StopDatabaseProxy::run($this->database); + $this->emit('success', 'Database is no longer publicly accessible.'); + } + $this->getDbUrl(); + $this->database->save(); + } catch(\Throwable $e) { + $this->database->is_public = !$this->database->is_public; + return handleError($e, $this); + } + } + public function refresh(): void + { + $this->database->refresh(); + } + + public function mount() + { + $this->getDbUrl(); + } + public function getDbUrl() { + + if ($this->database->is_public) { + $this->db_url = "mongodb://{$this->database->mongo_initdb_root_username}:{$this->database->mongo_initdb_root_password}@{$this->database->destination->server->getIp}:{$this->database->public_port}/?directConnection=true"; + } else { + $this->db_url = "mongodb://{$this->database->mongo_initdb_root_username}:{$this->database->mongo_initdb_root_password}@{$this->database->uuid}:27017/?directConnection=true"; + } + } + public function render() + { + return view('livewire.project.database.mongodb.general'); + } +} diff --git a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php index ce7c5ae40..f453b4bf3 100644 --- a/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php +++ b/app/Http/Livewire/Project/Shared/EnvironmentVariable/All.php @@ -78,6 +78,9 @@ class All extends Component case 'standalone-redis': $environment->standalone_redis_id = $this->resource->id; break; + case 'standalone-mongodb': + $environment->standalone_mongodb_id = $this->resource->id; + break; case 'service': $environment->service_id = $this->resource->id; break; diff --git a/app/Http/Livewire/Project/Shared/GetLogs.php b/app/Http/Livewire/Project/Shared/GetLogs.php index cd0ee98fd..90983785d 100644 --- a/app/Http/Livewire/Project/Shared/GetLogs.php +++ b/app/Http/Livewire/Project/Shared/GetLogs.php @@ -13,6 +13,7 @@ class GetLogs extends Component public Server $server; public ?string $container = null; public ?bool $streamLogs = false; + public ?bool $showTimeStamps = true; public int $numberOfLines = 100; public function doSomethingWithThisChunkOfOutput($output) { @@ -24,7 +25,11 @@ class GetLogs extends Component public function getLogs($refresh = false) { if ($this->container) { - $sshCommand = generateSshCommand($this->server, "docker logs -n {$this->numberOfLines} -t {$this->container}"); + if ($this->showTimeStamps) { + $sshCommand = generateSshCommand($this->server, "docker logs -n {$this->numberOfLines} -t {$this->container}"); + } else { + $sshCommand = generateSshCommand($this->server, "docker logs -n {$this->numberOfLines} {$this->container}"); + } if ($refresh) { $this->outputs = ''; } diff --git a/app/Http/Livewire/Project/Shared/Logs.php b/app/Http/Livewire/Project/Shared/Logs.php index 15a4e510c..80cdf82c4 100644 --- a/app/Http/Livewire/Project/Shared/Logs.php +++ b/app/Http/Livewire/Project/Shared/Logs.php @@ -5,6 +5,7 @@ namespace App\Http\Livewire\Project\Shared; use App\Models\Application; use App\Models\Server; use App\Models\Service; +use App\Models\StandaloneMongodb; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; use Livewire\Component; @@ -12,7 +13,7 @@ use Livewire\Component; class Logs extends Component { public ?string $type = null; - public Application|StandalonePostgresql|Service|StandaloneRedis $resource; + public Application|Service|StandalonePostgresql|StandaloneRedis|StandaloneMongodb $resource; public Server $server; public ?string $container = null; public $parameters; @@ -38,9 +39,13 @@ class Logs extends Component if (is_null($resource)) { $resource = StandaloneRedis::where('uuid', $this->parameters['database_uuid'])->first(); if (is_null($resource)) { - abort(404); + $resource = StandaloneMongodb::where('uuid', $this->parameters['database_uuid'])->first(); + if (is_null($resource)) { + abort(404); + } } } + $this->resource = $resource; $this->status = $this->resource->status; $this->server = $this->resource->destination->server; diff --git a/app/Jobs/StopResourceJob.php b/app/Jobs/StopResourceJob.php index 0bfc1f2fa..721f7f698 100644 --- a/app/Jobs/StopResourceJob.php +++ b/app/Jobs/StopResourceJob.php @@ -7,6 +7,7 @@ use App\Actions\Database\StopDatabase; use App\Actions\Service\StopService; use App\Models\Application; use App\Models\Service; +use App\Models\StandaloneMongodb; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; use Illuminate\Bus\Queueable; @@ -20,7 +21,7 @@ class StopResourceJob implements ShouldQueue, ShouldBeEncrypted { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; - public function __construct(public Application|Service|StandalonePostgresql|StandaloneRedis $resource) + public function __construct(public Application|Service|StandalonePostgresql|StandaloneRedis|StandaloneMongodb $resource) { } @@ -41,6 +42,9 @@ class StopResourceJob implements ShouldQueue, ShouldBeEncrypted case 'standalone-redis': StopDatabase::run($this->resource); break; + case 'standalone-mongodb': + StopDatabase::run($this->resource); + break; case 'service': StopService::run($this->resource); break; diff --git a/app/Models/Environment.php b/app/Models/Environment.php index f66bf48f2..8f67ed004 100644 --- a/app/Models/Environment.php +++ b/app/Models/Environment.php @@ -14,7 +14,11 @@ class Environment extends Model public function can_delete_environment() { - return $this->applications()->count() == 0 && $this->redis()->count() == 0 && $this->postgresqls()->count() == 0 && $this->services()->count() == 0; + return $this->applications()->count() == 0 && + $this->redis()->count() == 0 && + $this->postgresqls()->count() == 0 && + $this->mongodbs()->count() == 0 && + $this->services()->count() == 0; } public function applications() @@ -30,12 +34,17 @@ class Environment extends Model { return $this->hasMany(StandaloneRedis::class); } + public function mongodbs() + { + return $this->hasMany(StandaloneMongodb::class); + } public function databases() { $postgresqls = $this->postgresqls; $redis = $this->redis; - return $postgresqls->concat($redis); + $mongodbs = $this->mongodbs; + return $postgresqls->concat($redis)->concat($mongodbs); } public function project() diff --git a/app/Models/Server.php b/app/Models/Server.php index 07f975c48..d5d9709a0 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -124,7 +124,8 @@ class Server extends BaseModel return $this->destinations()->map(function ($standaloneDocker) { $postgresqls = $standaloneDocker->postgresqls; $redis = $standaloneDocker->redis; - return $postgresqls->concat($redis); + $mongodbs = $standaloneDocker->mongodbs; + return $postgresqls->concat($redis)->concat($mongodbs); })->flatten(); } public function applications() diff --git a/app/Models/StandaloneDocker.php b/app/Models/StandaloneDocker.php index a594b854a..9e70b7514 100644 --- a/app/Models/StandaloneDocker.php +++ b/app/Models/StandaloneDocker.php @@ -15,10 +15,15 @@ class StandaloneDocker extends BaseModel { return $this->morphMany(StandalonePostgresql::class, 'destination'); } + public function redis() { return $this->morphMany(StandaloneRedis::class, 'destination'); } + public function mongodbs() + { + return $this->morphMany(StandaloneMongodb::class, 'destination'); + } public function server() { diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php new file mode 100644 index 000000000..f8697e2ed --- /dev/null +++ b/app/Models/StandaloneMongodb.php @@ -0,0 +1,93 @@ + 'mongodb-data-' . $database->uuid, + 'mount_path' => '/data', + 'host_path' => null, + 'resource_id' => $database->id, + 'resource_type' => $database->getMorphClass(), + 'is_readonly' => true + ]); + }); + static::deleting(function ($database) { + $database->scheduledBackups()->delete(); + $storages = $database->persistentStorages()->get(); + foreach ($storages as $storage) { + instant_remote_process(["docker volume rm -f $storage->name"], $database->destination->server, false); + } + $database->persistentStorages()->delete(); + $database->environment_variables()->delete(); + }); + } + + public function portsMappings(): Attribute + { + return Attribute::make( + set: fn ($value) => $value === "" ? null : $value, + ); + } + + public function portsMappingsArray(): Attribute + { + return Attribute::make( + get: fn () => is_null($this->ports_mappings) + ? [] + : explode(',', $this->ports_mappings), + + ); + } + + public function type(): string + { + return 'standalone-mongodb'; + } + + public function environment() + { + return $this->belongsTo(Environment::class); + } + + public function fileStorages() + { + return $this->morphMany(LocalFileVolume::class, 'resource'); + } + + public function destination() + { + return $this->morphTo(); + } + + public function environment_variables(): HasMany + { + return $this->hasMany(EnvironmentVariable::class); + } + + public function runtime_environment_variables(): HasMany + { + return $this->hasMany(EnvironmentVariable::class); + } + + public function persistentStorages() + { + return $this->morphMany(LocalPersistentVolume::class, 'resource'); + } + + public function scheduledBackups() + { + return $this->morphMany(ScheduledDatabaseBackup::class, 'database'); + } +} diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index 6517c2ef7..6cd3f0064 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -41,8 +41,6 @@ class StandaloneRedis extends BaseModel ); } - // Normal Deployments - public function portsMappingsArray(): Attribute { return Attribute::make( diff --git a/bootstrap/helpers/constants.php b/bootstrap/helpers/constants.php index f915ea041..586ba531d 100644 --- a/bootstrap/helpers/constants.php +++ b/bootstrap/helpers/constants.php @@ -1,6 +1,6 @@ '* * * * *', 'hourly' => '0 * * * *', diff --git a/bootstrap/helpers/databases.php b/bootstrap/helpers/databases.php index 3c4f0dfd9..0c5c8898e 100644 --- a/bootstrap/helpers/databases.php +++ b/bootstrap/helpers/databases.php @@ -2,6 +2,7 @@ use App\Models\Server; use App\Models\StandaloneDocker; +use App\Models\StandaloneMongodb; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; use Visus\Cuid2\Cuid2; @@ -43,6 +44,21 @@ function create_standalone_redis($environment_id, $destination_uuid): Standalone ]); } +function create_standalone_mongodb($environment_id, $destination_uuid): StandaloneMongodb +{ + $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); + if (!$destination) { + throw new Exception('Destination not found'); + } + return StandaloneMongodb::create([ + 'name' => generate_database_name('mongodb'), + 'mongo_initdb_root_password' => \Illuminate\Support\Str::password(symbols: false), + 'environment_id' => $environment_id, + 'destination_id' => $destination->id, + 'destination_type' => $destination->getMorphClass(), + ]); +} + /** * Delete file locally on the filesystem. * @param string $filename diff --git a/database/factories/StandaloneMongoDBFactory.php b/database/factories/StandaloneMongoDBFactory.php new file mode 100644 index 000000000..8ec395e49 --- /dev/null +++ b/database/factories/StandaloneMongoDBFactory.php @@ -0,0 +1,23 @@ + + */ +class StandaloneMongodbFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/database/migrations/2023_10_19_101331_create_standalone_mongodbs_table.php b/database/migrations/2023_10_19_101331_create_standalone_mongodbs_table.php new file mode 100644 index 000000000..30f5c24af --- /dev/null +++ b/database/migrations/2023_10_19_101331_create_standalone_mongodbs_table.php @@ -0,0 +1,56 @@ +id(); + $table->string('uuid')->unique(); + $table->string('name'); + $table->string('description')->nullable(); + + $table->text('mongo_conf')->nullable(); + $table->text('mongo_initdb_root_username')->default('root'); + $table->text('mongo_initdb_root_password'); + $table->text('mongo_initdb_database')->default('default'); + + $table->string('status')->default('exited'); + + $table->string('image')->default('mongo:7'); + + $table->boolean('is_public')->default(false); + $table->integer('public_port')->nullable(); + $table->text('ports_mappings')->nullable(); + + $table->string('limits_memory')->default("0"); + $table->string('limits_memory_swap')->default("0"); + $table->integer('limits_memory_swappiness')->default(60); + $table->string('limits_memory_reservation')->default("0"); + + $table->string('limits_cpus')->default("0"); + $table->string('limits_cpuset')->nullable()->default("0"); + $table->integer('limits_cpu_shares')->default(1024); + + $table->timestamp('started_at')->nullable(); + $table->morphs('destination'); + $table->foreignId('environment_id')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('standalone_mongodbs'); + } +}; diff --git a/database/migrations/2023_10_19_101332_add_standalone_mongodb_to_environment_variables_table.php b/database/migrations/2023_10_19_101332_add_standalone_mongodb_to_environment_variables_table.php new file mode 100644 index 000000000..b67c22637 --- /dev/null +++ b/database/migrations/2023_10_19_101332_add_standalone_mongodb_to_environment_variables_table.php @@ -0,0 +1,28 @@ +foreignId('standalone_mongodb_id')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('environment_variables', function (Blueprint $table) { + $table->dropColumn('standalone_mongodb_id'); + }); + } +}; diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 0bf3e8828..9b7af1c02 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -34,7 +34,7 @@ services: POSTGRES_DB: "${DB_DATABASE:-coolify}" POSTGRES_HOST_AUTH_METHOD: "trust" volumes: - - ./_data/coolify/_volumes/database/:/var/lib/postgresql/data + - /data/coolify/_volumes/database/:/var/lib/postgresql/data # - coolify-pg-data-dev:/var/lib/postgresql/data redis: ports: @@ -42,7 +42,7 @@ services: env_file: - .env volumes: - - ./_data/coolify/_volumes/redis/:/data + - /data/coolify/_volumes/redis/:/data # - coolify-redis-data-dev:/data vite: image: node:19 @@ -58,7 +58,7 @@ services: volumes: - /:/host - /var/run/docker.sock:/var/run/docker.sock - - ./_data/coolify/:/data/coolify + - /data/coolify/:/data/coolify # - coolify-data-dev:/data/coolify mailpit: image: "axllent/mailpit:latest" @@ -79,7 +79,7 @@ services: MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}" MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}" volumes: - - ./_data/coolify/_volumes/minio/:/data + - /data/coolify/_volumes/minio/:/data # - coolify-minio-data-dev:/data networks: - coolify diff --git a/resources/views/livewire/project/database/mongodb/general.blade.php b/resources/views/livewire/project/database/mongodb/general.blade.php new file mode 100644 index 000000000..51cb31d23 --- /dev/null +++ b/resources/views/livewire/project/database/mongodb/general.blade.php @@ -0,0 +1,52 @@ +
+
+
+

General

+ + Save + +
+
+ + + +
+ @if ($database->started_at) +
+ + + +
+ @else +
Please verify these values. You can only modify them before the initial + start. After that, you need to modify it in the database. +
+
+ + + +
+ @endif +
+

Network

+
+ + + +
+ +
+ + +
diff --git a/resources/views/livewire/project/database/postgresql/general.blade.php b/resources/views/livewire/project/database/postgresql/general.blade.php index 61a95f9f8..dfe64b993 100644 --- a/resources/views/livewire/project/database/postgresql/general.blade.php +++ b/resources/views/livewire/project/database/postgresql/general.blade.php @@ -62,7 +62,7 @@ label="Public Port" /> - +
diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index 17f440fbb..1789d0c15 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -21,7 +21,7 @@ label="Public Port" />
- + diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index 8d6636fb1..9659ff995 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -103,6 +103,15 @@ The open source, in-memory data store for cache, streaming engine, and message broker. +
+
+
+ New MongoDB +
+
+ MongoDB is a source-available cross-platform document-oriented database program. +
+
{{--
diff --git a/resources/views/livewire/project/shared/get-logs.blade.php b/resources/views/livewire/project/shared/get-logs.blade.php index 31f6e6bc3..eed8f143b 100644 --- a/resources/views/livewire/project/shared/get-logs.blade.php +++ b/resources/views/livewire/project/shared/get-logs.blade.php @@ -5,13 +5,15 @@ @endif
+
+ + +
Refresh
-
- -
+
diff --git a/resources/views/project/database/configuration.blade.php b/resources/views/project/database/configuration.blade.php index bed2f96ef..8fbfa8f0c 100644 --- a/resources/views/project/database/configuration.blade.php +++ b/resources/views/project/database/configuration.blade.php @@ -40,6 +40,9 @@ @if ($database->type() === 'standalone-redis') @endif + @if ($database->type() === 'standalone-mongodb') + + @endif