Merge pull request #1359 from coollabsio/next

v4.0.0-beta.99
This commit is contained in:
Andras Bacsai 2023-10-24 10:59:36 +02:00 committed by GitHub
commit 2620bfbf08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 152 additions and 48 deletions

View File

@ -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";
}
}

View File

@ -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;
}

View File

@ -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";
}
}
}

View File

@ -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";

View File

@ -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();
}

View File

@ -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.');
}
}

View File

@ -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');

View File

@ -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 === '') {

View File

@ -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 &&

View File

@ -18,7 +18,7 @@ protected static function booted()
'project_id' => $project->id,
]);
Environment::create([
'name' => 'Production',
'name' => 'production',
'project_id' => $project->id,
]);
});

View File

@ -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";

View File

@ -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}";

View File

@ -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'),

View File

@ -1,3 +1,3 @@
<?php
return '4.0.0-beta.98';
return '4.0.0-beta.99';

View File

@ -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) => {

View File

@ -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

View File

@ -4,7 +4,7 @@
"version": "3.12.36"
},
"v4": {
"version": "4.0.0-beta.98"
"version": "4.0.0-beta.99"
}
}
}