commit
2620bfbf08
@ -94,6 +94,14 @@ public function handle(StandaloneMongodb $database)
|
||||
];
|
||||
$docker_compose['services'][$container_name]['command'] = $startCommand . ' --config /etc/mongo/mongod.conf';
|
||||
}
|
||||
$this->add_default_database();
|
||||
$docker_compose['services'][$container_name]['volumes'][] = [
|
||||
'type' => 'bind',
|
||||
'source' => $this->configuration_dir . '/docker-entrypoint-initdb.d',
|
||||
'target' => '/docker-entrypoint-initdb.d',
|
||||
'read_only' => true,
|
||||
];
|
||||
|
||||
$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";
|
||||
@ -160,4 +168,11 @@ private function add_custom_mongo_conf()
|
||||
$content_base64 = base64_encode($content);
|
||||
$this->commands[] = "echo '{$content_base64}' | base64 -d > $this->configuration_dir/{$filename}";
|
||||
}
|
||||
private function add_default_database()
|
||||
{
|
||||
$content = "db = db.getSiblingDB(\"{$this->database->mongo_initdb_database}\");db.createCollection('init_collection');db.createUser({user: \"{$this->database->mongo_initdb_root_username}\", pwd: \"{$this->database->mongo_initdb_root_password}\",roles: [{role:\"readWrite\",db:\"{$this->database->mongo_initdb_database}\"}]});";
|
||||
$content_base64 = base64_encode($content);
|
||||
$this->commands[] = "mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d";
|
||||
$this->commands[] = "echo '{$content_base64}' | base64 -d > $this->configuration_dir/docker-entrypoint-initdb.d/01-default-database.js";
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,9 @@ private function process_file($file)
|
||||
'compose' => $yaml,
|
||||
];
|
||||
if ($env_file) {
|
||||
$payload['envs'] = $env_file;
|
||||
$env_file_content = file_get_contents(base_path("templates/compose/$env_file"));
|
||||
$env_file_base64 = base64_encode($env_file_content);
|
||||
$payload['envs'] = $env_file_base64;
|
||||
}
|
||||
return $payload;
|
||||
}
|
||||
|
@ -3,7 +3,12 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Enums\ApplicationDeploymentStatus;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\Service;
|
||||
use App\Models\StandaloneMongodb;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\StandaloneRedis;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class Init extends Command
|
||||
@ -13,7 +18,9 @@ class Init extends Command
|
||||
|
||||
public function handle()
|
||||
{
|
||||
ray()->clearAll();
|
||||
$this->cleanup_in_progress_application_deployments();
|
||||
$this->cleanup_stucked_resources();
|
||||
}
|
||||
|
||||
private function cleanup_in_progress_application_deployments()
|
||||
@ -30,4 +37,70 @@ private function cleanup_in_progress_application_deployments()
|
||||
echo "Error: {$e->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
private function cleanup_stucked_resources() {
|
||||
// Cleanup any resources that are not attached to any environment or destination or server
|
||||
try {
|
||||
$applications = Application::all();
|
||||
foreach($applications as $application) {
|
||||
if (!$application->environment) {
|
||||
ray('Application without environment', $application->name);
|
||||
$application->delete();
|
||||
}
|
||||
if (!$application->destination()) {
|
||||
ray('Application without destination', $application->name);
|
||||
$application->delete();
|
||||
}
|
||||
}
|
||||
$postgresqls = StandalonePostgresql::all();
|
||||
foreach($postgresqls as $postgresql) {
|
||||
if (!$postgresql->environment) {
|
||||
ray('Postgresql without environment', $postgresql->name);
|
||||
$postgresql->delete();
|
||||
}
|
||||
if (!$postgresql->destination()) {
|
||||
ray('Postgresql without destination', $postgresql->name);
|
||||
$postgresql->delete();
|
||||
}
|
||||
}
|
||||
$redis = StandaloneRedis::all();
|
||||
foreach($redis as $redis) {
|
||||
if (!$redis->environment) {
|
||||
ray('Redis without environment', $redis->name);
|
||||
$redis->delete();
|
||||
}
|
||||
if (!$redis->destination()) {
|
||||
ray('Redis without destination', $redis->name);
|
||||
$redis->delete();
|
||||
}
|
||||
}
|
||||
$mongodbs = StandaloneMongodb::all();
|
||||
foreach($mongodbs as $mongodb) {
|
||||
if (!$mongodb->environment) {
|
||||
ray('Mongodb without environment', $mongodb->name);
|
||||
$mongodb->delete();
|
||||
}
|
||||
if (!$mongodb->destination()) {
|
||||
ray('Mongodb without destination', $mongodb->name);
|
||||
$mongodb->delete();
|
||||
}
|
||||
}
|
||||
$services = Service::all();
|
||||
foreach($services as $service) {
|
||||
if (!$service->environment) {
|
||||
ray('Service without environment', $service->name);
|
||||
$service->delete();
|
||||
}
|
||||
if (!$service->server) {
|
||||
ray('Service without server', $service->name);
|
||||
$service->delete();
|
||||
}
|
||||
if (!$service->destination()) {
|
||||
ray('Service without destination', $service->name);
|
||||
$service->delete();
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: {$e->getMessage()}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class SyncBunny extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'sync:bunny {--only-template} {--only-version}';
|
||||
protected $signature = 'sync:bunny {templates?} {release?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -31,8 +31,8 @@ class SyncBunny extends Command
|
||||
public function handle()
|
||||
{
|
||||
$that = $this;
|
||||
$only_template = $this->option('only-template');
|
||||
$only_version = $this->option('only-version');
|
||||
$only_template = $this->argument('templates');
|
||||
$only_version = $this->argument('release');
|
||||
$bunny_cdn = "https://cdn.coollabs.io";
|
||||
$bunny_cdn_path = "coolify";
|
||||
$bunny_cdn_storage_name = "coolcdn";
|
||||
|
@ -55,18 +55,21 @@ public function clone()
|
||||
'selectedServer' => 'required',
|
||||
'newProjectName' => 'required',
|
||||
]);
|
||||
$foundProject = Project::where('name', $this->newProjectName)->first();
|
||||
if ($foundProject) {
|
||||
throw new \Exception('Project with the same name already exists.');
|
||||
}
|
||||
$newProject = Project::create([
|
||||
'name' => $this->newProjectName,
|
||||
'team_id' => currentTeam()->id,
|
||||
'description' => $this->project->description . ' (clone)',
|
||||
]);
|
||||
if ($this->environment->id !== 1) {
|
||||
if ($this->environment->name !== 'production') {
|
||||
$newProject->environments()->create([
|
||||
'name' => $this->environment->name,
|
||||
]);
|
||||
$newProject->environments()->find(1)->delete();
|
||||
}
|
||||
$newEnvironment = $newProject->environments->first();
|
||||
$newEnvironment = $newProject->environments->where('name', $this->environment->name)->first();
|
||||
// Clone Applications
|
||||
$applications = $this->environment->applications;
|
||||
$databases = $this->environment->databases();
|
||||
@ -80,7 +83,6 @@ public function clone()
|
||||
'environment_id' => $newEnvironment->id,
|
||||
'destination_id' => $this->selectedServer,
|
||||
]);
|
||||
$newApplication->environment_id = $newProject->environments->first()->id;
|
||||
$newApplication->save();
|
||||
$environmentVaribles = $application->environment_variables()->get();
|
||||
foreach ($environmentVaribles as $environmentVarible) {
|
||||
@ -105,7 +107,6 @@ public function clone()
|
||||
'environment_id' => $newEnvironment->id,
|
||||
'destination_id' => $this->selectedServer,
|
||||
]);
|
||||
$newDatabase->environment_id = $newProject->environments->first()->id;
|
||||
$newDatabase->save();
|
||||
$environmentVaribles = $database->environment_variables()->get();
|
||||
foreach ($environmentVaribles as $environmentVarible) {
|
||||
@ -128,7 +129,6 @@ public function clone()
|
||||
'environment_id' => $newEnvironment->id,
|
||||
'destination_id' => $this->selectedServer,
|
||||
]);
|
||||
$newService->environment_id = $newProject->environments->first()->id;
|
||||
$newService->save();
|
||||
$newService->parse();
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ public function delete()
|
||||
'environment_id' => 'required|int',
|
||||
]);
|
||||
$environment = Environment::findOrFail($this->environment_id);
|
||||
if ($environment->applications->count() > 0) {
|
||||
return $this->emit('error', 'Environment has resources defined, please delete them first.');
|
||||
if ($environment->isEmpty()) {
|
||||
$environment->delete();
|
||||
return redirect()->route('project.show', ['project_uuid' => $this->parameters['project_uuid']]);
|
||||
}
|
||||
$environment->delete();
|
||||
return redirect()->route('project.show', ['project_uuid' => $this->parameters['project_uuid']]);
|
||||
return $this->emit('error', 'Environment has defined resources, please delete them first.');
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
class ComposeModal extends Component
|
||||
{
|
||||
public string $raw;
|
||||
public string $actual;
|
||||
public ?string $raw = null;
|
||||
public ?string $actual = null;
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.service.compose-modal');
|
||||
|
@ -170,18 +170,25 @@ public function handle(): void
|
||||
private function backup_standalone_mongodb(string $databaseWithCollections): void
|
||||
{
|
||||
try {
|
||||
$url = $this->database->getDbUrl();
|
||||
$url = $this->database->getDbUrl(useInternal: true);
|
||||
if ($databaseWithCollections === 'all') {
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --gzip --archive > $this->backup_location";
|
||||
} else {
|
||||
$collectionsToExclude = str($databaseWithCollections)->after(':')->explode(',');
|
||||
$databaseName = str($databaseWithCollections)->before(':');
|
||||
if (str($databaseWithCollections)->contains(':')) {
|
||||
$databaseName = str($databaseWithCollections)->before(':');
|
||||
$collectionsToExclude = str($databaseWithCollections)->after(':')->explode(',');
|
||||
} else {
|
||||
$databaseName = $databaseWithCollections;
|
||||
$collectionsToExclude = collect();
|
||||
}
|
||||
$commands[] = "mkdir -p " . $this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --excludeCollection " . $collectionsToExclude->implode(' --excludeCollection ') . " --archive > $this->backup_location";
|
||||
if ($collectionsToExclude->count() === 0) {
|
||||
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --archive > $this->backup_location";
|
||||
} else {
|
||||
$commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --db $databaseName --gzip --excludeCollection " . $collectionsToExclude->implode(' --excludeCollection ') . " --archive > $this->backup_location";
|
||||
}
|
||||
}
|
||||
|
||||
ray($commands);
|
||||
$this->backup_output = instant_remote_process($commands, $this->server);
|
||||
$this->backup_output = trim($this->backup_output);
|
||||
if ($this->backup_output === '') {
|
||||
|
@ -7,12 +7,8 @@
|
||||
|
||||
class Environment extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'project_id',
|
||||
];
|
||||
|
||||
public function can_delete_environment()
|
||||
protected $guarded = [];
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->applications()->count() == 0 &&
|
||||
$this->redis()->count() == 0 &&
|
||||
|
@ -18,7 +18,7 @@ protected static function booted()
|
||||
'project_id' => $project->id,
|
||||
]);
|
||||
Environment::create([
|
||||
'name' => 'Production',
|
||||
'name' => 'production',
|
||||
'project_id' => $project->id,
|
||||
]);
|
||||
});
|
||||
|
@ -15,8 +15,16 @@ protected static function booted()
|
||||
{
|
||||
static::created(function ($database) {
|
||||
LocalPersistentVolume::create([
|
||||
'name' => 'mongodb-data-' . $database->uuid,
|
||||
'mount_path' => '/data',
|
||||
'name' => 'mongodb-configdb-' . $database->uuid,
|
||||
'mount_path' => '/data/configdb',
|
||||
'host_path' => null,
|
||||
'resource_id' => $database->id,
|
||||
'resource_type' => $database->getMorphClass(),
|
||||
'is_readonly' => true
|
||||
]);
|
||||
LocalPersistentVolume::create([
|
||||
'name' => 'mongodb-db-' . $database->uuid,
|
||||
'mount_path' => '/data/db',
|
||||
'host_path' => null,
|
||||
'resource_id' => $database->id,
|
||||
'resource_type' => $database->getMorphClass(),
|
||||
@ -55,8 +63,8 @@ public function type(): string
|
||||
{
|
||||
return 'standalone-mongodb';
|
||||
}
|
||||
public function getDbUrl() {
|
||||
if ($this->is_public) {
|
||||
public function getDbUrl(bool $useInternal = false) {
|
||||
if ($this->is_public && !$useInternal) {
|
||||
return "mongodb://{$this->mongo_initdb_root_username}:{$this->mongo_initdb_root_password}@{$this->destination->server->getIp}:{$this->public_port}/?directConnection=true";
|
||||
} else {
|
||||
return "mongodb://{$this->mongo_initdb_root_username}:{$this->mongo_initdb_root_password}@{$this->uuid}:27017/?directConnection=true";
|
||||
|
@ -62,9 +62,9 @@ public function type(): string
|
||||
{
|
||||
return 'standalone-postgresql';
|
||||
}
|
||||
public function getDbUrl(): string
|
||||
public function getDbUrl(bool $useInternal = false): string
|
||||
{
|
||||
if ($this->is_public) {
|
||||
if ($this->is_public && !$useInternal) {
|
||||
return "postgres://{$this->postgres_user}:{$this->postgres_password}@{$this->destination->server->getIp}:{$this->public_port}/{$this->postgres_db}";
|
||||
} else {
|
||||
return "postgres://{$this->postgres_user}:{$this->postgres_password}@{$this->uuid}:5432/{$this->postgres_db}";
|
||||
|
@ -3,11 +3,11 @@
|
||||
return [
|
||||
|
||||
// @see https://docs.sentry.io/product/sentry-basics/dsn-explainer/
|
||||
'dsn' => 'https://72f02655749d5d687297b6b9f078b8b9@o1082494.ingest.sentry.io/4505347448045568',
|
||||
'dsn' => 'https://c35fe90ee56e18b220bb55e8217d4839@o1082494.ingest.sentry.io/4505347448045568',
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.98',
|
||||
'release' => '4.0.0-beta.99',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.98';
|
||||
return '4.0.0-beta.99';
|
||||
|
@ -96,8 +96,7 @@ function upgrade() {
|
||||
}
|
||||
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text);
|
||||
Livewire.emit('success', 'Copied to clipboard.');
|
||||
navigator?.clipboard?.writeText(text) && Livewire.emit('success', 'Copied to clipboard.');
|
||||
}
|
||||
|
||||
Livewire.on('reloadWindow', (timeout) => {
|
||||
|
@ -2,17 +2,21 @@
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>Resources</h1>
|
||||
@if ($environment->can_delete_environment())
|
||||
@if ($environment->isEmpty())
|
||||
<a class="font-normal text-white normal-case border-none rounded hover:no-underline btn btn-primary btn-sm no-animation"
|
||||
href="{{ route('project.clone', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => request()->route('environment_name')]) }}">
|
||||
Clone
|
||||
</a>
|
||||
<livewire:project.delete-environment :environment_id="$environment->id" />
|
||||
@else
|
||||
<a href="{{ route('project.resources.new', ['project_uuid' => request()->route('project_uuid'), 'environment_name' => request()->route('environment_name')]) }} "
|
||||
class="font-normal text-white normal-case border-none rounded hover:no-underline btn btn-primary btn-sm no-animation">+
|
||||
New</a>
|
||||
<a class="font-normal text-white normal-case border-none rounded hover:no-underline btn btn-primary btn-sm no-animation"
|
||||
href="{{ route('project.clone', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => request()->route('environment_name')]) }}">
|
||||
Clone
|
||||
</a>
|
||||
@endif
|
||||
<a class="font-normal text-white normal-case border-none rounded hover:no-underline btn btn-primary btn-sm no-animation"
|
||||
href="{{ route('project.clone', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => request()->route('environment_name')]) }}">
|
||||
Clone
|
||||
</a>
|
||||
</div>
|
||||
<nav class="flex pt-2 pb-10">
|
||||
<ol class="flex items-center">
|
||||
@ -36,7 +40,7 @@ class="font-normal text-white normal-case border-none rounded hover:no-underline
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
@if ($environment->can_delete_environment())
|
||||
@if ($environment->isEmpty())
|
||||
<a href="{{ route('project.resources.new', ['project_uuid' => request()->route('project_uuid'), 'environment_name' => request()->route('environment_name')]) }} "
|
||||
class="items-center justify-center box">+ Add New Resource</a>
|
||||
@endif
|
||||
|
File diff suppressed because one or more lines are too long
@ -4,7 +4,7 @@
|
||||
"version": "3.12.36"
|
||||
},
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.98"
|
||||
"version": "4.0.0-beta.99"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user