Choose the server and network to clone the resources to.
@foreach ($servers->sortBy('id') as $server)
@@ -29,7 +61,7 @@
@endforeach
-
@foreach ($environment->applications->sortBy('name') as $application)
From 5877cead8912e4fd10fdd49557efc298e9973047 Mon Sep 17 00:00:00 2001
From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Date: Wed, 8 Jan 2025 23:16:15 +0100
Subject: [PATCH 12/19] feat: move volume data cloning to a Job
---
app/Jobs/VolumeCloneJob.php | 39 +++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 app/Jobs/VolumeCloneJob.php
diff --git a/app/Jobs/VolumeCloneJob.php b/app/Jobs/VolumeCloneJob.php
new file mode 100644
index 000000000..95ac14197
--- /dev/null
+++ b/app/Jobs/VolumeCloneJob.php
@@ -0,0 +1,39 @@
+onQueue('high');
+ }
+
+ public function handle()
+ {
+ try {
+ instant_remote_process([
+ "docker volume create $this->targetVolume",
+ "docker run --rm -v $this->sourceVolume:/source -v $this->targetVolume:/target alpine sh -c 'cp -a /source/. /target/ && chown -R 1000:1000 /target'",
+ ], $this->server);
+ } catch (\Exception $e) {
+ logger()->error("Failed to copy volume data for {$this->sourceVolume}: ".$e->getMessage());
+ throw $e;
+ }
+ }
+}
From e01401a4dda318687980bb26071869797f77183f Mon Sep 17 00:00:00 2001
From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Date: Thu, 9 Jan 2025 13:49:44 +0100
Subject: [PATCH 13/19] fix: volume and fileStorages cloning
- fix: volume naming
- fix: clone file and directory mounts for services
- fix: clone volumes for services
- fix: clone scheduled tasks for service applications
- fix: clone backup schedules for service databases
- feat: clone Volume data for services and applications
---
app/Livewire/Project/CloneMe.php | 135 +++++++++++++++++++++++++++++--
1 file changed, 127 insertions(+), 8 deletions(-)
diff --git a/app/Livewire/Project/CloneMe.php b/app/Livewire/Project/CloneMe.php
index bcecbc76f..e794ff2ea 100644
--- a/app/Livewire/Project/CloneMe.php
+++ b/app/Livewire/Project/CloneMe.php
@@ -5,6 +5,8 @@ namespace App\Livewire\Project;
use App\Actions\Application\StopApplication;
use App\Actions\Database\StartDatabase;
use App\Actions\Database\StopDatabase;
+use App\Actions\Service\StartService;
+use App\Actions\Service\StopService;
use App\Jobs\VolumeCloneJob;
use App\Models\Environment;
use App\Models\Project;
@@ -59,7 +61,6 @@ class CloneMe extends Component
public function toggleVolumeCloning(bool $value)
{
$this->cloneVolumeData = $value;
- $this->dispatch('refresh');
}
public function render()
@@ -195,12 +196,19 @@ class CloneMe extends Component
$persistentVolumes = $application->persistentStorages()->get();
foreach ($persistentVolumes as $volume) {
+ $newName = '';
+ if (str_starts_with($volume->name, $application->uuid)) {
+ $newName = str($volume->name)->replace($application->uuid, $newApplication->uuid);
+ } else {
+ $newName = $newApplication->uuid.'-'.$volume->name;
+ }
+
$newPersistentVolume = $volume->replicate([
'id',
'created_at',
'updated_at',
])->fill([
- 'name' => $newApplication->uuid.'-'.str($volume->name)->afterLast('-'),
+ 'name' => $newName,
'resource_id' => $newApplication->id,
]);
$newPersistentVolume->save();
@@ -222,7 +230,7 @@ class CloneMe extends Component
no_questions_asked: true
);
} catch (\Exception $e) {
- logger()->error("Failed to copy volume data for {$volume->name}: ".$e->getMessage());
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
}
}
}
@@ -295,9 +303,11 @@ class CloneMe extends Component
} elseif (str_starts_with($originalName, 'dragonfly-data-')) {
$newName = 'dragonfly-data-'.$newDatabase->uuid;
} else {
- $newName = str($originalName)
- ->replaceFirst($database->uuid, $newDatabase->uuid)
- ->toString();
+ if (str_starts_with($volume->name, $database->uuid)) {
+ $newName = str($volume->name)->replace($database->uuid, $newDatabase->uuid);
+ } else {
+ $newName = $newDatabase->uuid.'-'.$volume->name;
+ }
}
$newPersistentVolume = $volume->replicate([
@@ -321,8 +331,7 @@ class CloneMe extends Component
StartDatabase::dispatch($database);
} catch (\Exception $e) {
- // Log error but continue with cloning
- logger()->error("Failed to copy volume data for {$volume->name}: ".$e->getMessage());
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
}
}
}
@@ -418,12 +427,122 @@ class CloneMe extends Component
$application->update([
'status' => 'exited',
]);
+
+ $persistentVolumes = $application->persistentStorages()->get();
+ foreach ($persistentVolumes as $volume) {
+ $newName = '';
+ if (str_starts_with($volume->name, $application->uuid)) {
+ $newName = str($volume->name)->replace($application->uuid, $application->uuid);
+ } else {
+ $newName = $application->uuid.'-'.$volume->name;
+ }
+
+ $newPersistentVolume = $volume->replicate([
+ 'id',
+ 'created_at',
+ 'updated_at',
+ ])->fill([
+ 'name' => $newName,
+ 'resource_id' => $application->id,
+ ]);
+ $newPersistentVolume->save();
+
+ if ($this->cloneVolumeData) {
+ try {
+ StopService::dispatch($application, false, false);
+ $sourceVolume = $volume->name;
+ $targetVolume = $newPersistentVolume->name;
+ $server = $application->service->destination->server;
+
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+
+ StartService::dispatch($application);
+ } catch (\Exception $e) {
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
+ }
+ }
+ }
+
+ $fileStorages = $application->fileStorages()->get();
+ foreach ($fileStorages as $storage) {
+ $newStorage = $storage->replicate([
+ 'id',
+ 'created_at',
+ 'updated_at',
+ ])->fill([
+ 'resource_id' => $application->id,
+ ]);
+ $newStorage->save();
+ }
}
foreach ($newService->databases() as $database) {
$database->update([
'status' => 'exited',
]);
+
+ $persistentVolumes = $database->persistentStorages()->get();
+ foreach ($persistentVolumes as $volume) {
+ $newName = '';
+ if (str_starts_with($volume->name, $database->uuid)) {
+ $newName = str($volume->name)->replace($database->uuid, $database->uuid);
+ } else {
+ $newName = $database->uuid.'-'.$volume->name;
+ }
+
+ $newPersistentVolume = $volume->replicate([
+ 'id',
+ 'created_at',
+ 'updated_at',
+ ])->fill([
+ 'name' => $newName,
+ 'resource_id' => $database->id,
+ ]);
+ $newPersistentVolume->save();
+
+ if ($this->cloneVolumeData) {
+ try {
+ StopService::dispatch($database->service, false, false);
+ $sourceVolume = $volume->name;
+ $targetVolume = $newPersistentVolume->name;
+ $server = $database->service->destination->server;
+
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+
+ StartService::dispatch($database->service);
+ } catch (\Exception $e) {
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
+ }
+ }
+ }
+
+ $fileStorages = $database->fileStorages()->get();
+ foreach ($fileStorages as $storage) {
+ $newStorage = $storage->replicate([
+ 'id',
+ 'created_at',
+ 'updated_at',
+ ])->fill([
+ 'resource_id' => $database->id,
+ ]);
+ $newStorage->save();
+ }
+
+ $scheduledBackups = $database->scheduledBackups()->get();
+ foreach ($scheduledBackups as $backup) {
+ $uuid = (string) new Cuid2;
+ $newBackup = $backup->replicate([
+ 'id',
+ 'created_at',
+ 'updated_at',
+ ])->fill([
+ 'uuid' => $uuid,
+ 'database_id' => $database->id,
+ 'database_type' => $database->getMorphClass(),
+ 'team_id' => currentTeam()->id,
+ ]);
+ $newBackup->save();
+ }
}
$newService->parse();
From 1c357f987d3cc50678ba7207fd606f24d2d7b62a Mon Sep 17 00:00:00 2001
From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Date: Thu, 9 Jan 2025 13:56:00 +0100
Subject: [PATCH 14/19] fix: view text and helpers
---
resources/views/livewire/project/clone-me.blade.php | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/resources/views/livewire/project/clone-me.blade.php b/resources/views/livewire/project/clone-me.blade.php
index da7c8aa84..f613ca2c7 100644
--- a/resources/views/livewire/project/clone-me.blade.php
+++ b/resources/views/livewire/project/clone-me.blade.php
@@ -19,10 +19,10 @@
@if(!$cloneVolumeData)
@@ -30,12 +30,12 @@
@else
+ helper="Volume Data will be cloned to the new resources. Containers will be temporarily stopped during the cloning process." />
@endif
From 34873b2c5972c323dbb504fc194ab728b6fec070 Mon Sep 17 00:00:00 2001
From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Date: Thu, 9 Jan 2025 14:13:09 +0100
Subject: [PATCH 15/19] feat: volume cloning for ResourceOperations
---
.../Project/Shared/ResourceOperations.php | 140 +++++++++++++++++-
.../shared/resource-operations.blade.php | 36 ++++-
2 files changed, 166 insertions(+), 10 deletions(-)
diff --git a/app/Livewire/Project/Shared/ResourceOperations.php b/app/Livewire/Project/Shared/ResourceOperations.php
index cb9f7db85..705a8b49a 100644
--- a/app/Livewire/Project/Shared/ResourceOperations.php
+++ b/app/Livewire/Project/Shared/ResourceOperations.php
@@ -2,6 +2,12 @@
namespace App\Livewire\Project\Shared;
+use App\Actions\Application\StopApplication;
+use App\Actions\Database\StartDatabase;
+use App\Actions\Database\StopDatabase;
+use App\Actions\Service\StartService;
+use App\Actions\Service\StopService;
+use App\Jobs\VolumeCloneJob;
use App\Models\Environment;
use App\Models\Project;
use App\Models\StandaloneDocker;
@@ -21,6 +27,8 @@ class ResourceOperations extends Component
public $servers;
+ public bool $cloneVolumeData = false;
+
public function mount()
{
$parameters = get_route_parameters();
@@ -30,6 +38,11 @@ class ResourceOperations extends Component
$this->servers = currentTeam()->servers;
}
+ public function toggleVolumeCloning(bool $value)
+ {
+ $this->cloneVolumeData = $value;
+ }
+
public function cloneTo($destination_id)
{
$new_destination = StandaloneDocker::find($destination_id);
@@ -118,19 +131,43 @@ class ResourceOperations extends Component
$persistentVolumes = $this->resource->persistentStorages()->get();
foreach ($persistentVolumes as $volume) {
- $volumeName = str($volume->name)->replace($this->resource->uuid, $new_resource->uuid)->value();
- if ($volumeName === $volume->name) {
- $volumeName = $new_resource->uuid.'-'.str($volume->name)->afterLast('-');
+ $newName = '';
+ if (str_starts_with($volume->name, $this->resource->uuid)) {
+ $newName = str($volume->name)->replace($this->resource->uuid, $new_resource->uuid);
+ } else {
+ $newName = $new_resource->uuid.'-'.str($volume->name)->afterLast('-');
}
+
$newPersistentVolume = $volume->replicate([
'id',
'created_at',
'updated_at',
])->fill([
- 'name' => $volumeName,
+ 'name' => $newName,
'resource_id' => $new_resource->id,
]);
$newPersistentVolume->save();
+
+ if ($this->cloneVolumeData) {
+ try {
+ StopApplication::dispatch($this->resource, false, false);
+ $sourceVolume = $volume->name;
+ $targetVolume = $newPersistentVolume->name;
+ $server = $this->resource->destination->server;
+
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+
+ queue_application_deployment(
+ deployment_uuid: (string) new Cuid2,
+ application: $this->resource,
+ server: $server,
+ destination: $this->resource->destination,
+ no_questions_asked: true
+ );
+ } catch (\Exception $e) {
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
+ }
+ }
}
$fileStorages = $this->resource->fileStorages()->get();
@@ -217,9 +254,11 @@ class ResourceOperations extends Component
} elseif (str_starts_with($originalName, 'dragonfly-data-')) {
$newName = 'dragonfly-data-'.$new_resource->uuid;
} else {
- $newName = str($originalName)
- ->replaceFirst($this->resource->uuid, $new_resource->uuid)
- ->toString();
+ if (str_starts_with($volume->name, $this->resource->uuid)) {
+ $newName = str($volume->name)->replace($this->resource->uuid, $new_resource->uuid);
+ } else {
+ $newName = $new_resource->uuid.'-'.$volume->name;
+ }
}
$newPersistentVolume = $volume->replicate([
@@ -231,6 +270,21 @@ class ResourceOperations extends Component
'resource_id' => $new_resource->id,
]);
$newPersistentVolume->save();
+
+ if ($this->cloneVolumeData) {
+ try {
+ StopDatabase::dispatch($this->resource);
+ $sourceVolume = $volume->name;
+ $targetVolume = $newPersistentVolume->name;
+ $server = $this->resource->destination->server;
+
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+
+ StartDatabase::dispatch($this->resource);
+ } catch (\Exception $e) {
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
+ }
+ }
}
$fileStorages = $this->resource->fileStorages()->get();
@@ -293,7 +347,7 @@ class ResourceOperations extends Component
'name' => $this->resource->name.'-clone-'.$uuid,
'destination_id' => $new_destination->id,
'destination_type' => $new_destination->getMorphClass(),
- 'server_id' => $new_destination->server_id, // server_id is probably not needed anymore because of the new polymorphic relationships (here it is needed for clone to work - but maybe we can drop the column)
+ 'server_id' => $new_destination->server_id, // server_id is probably not needed anymore because of the new polymorphic relationships (here it is needed for clone to a different server to work - but maybe we can drop the column)
]);
$new_resource->save();
@@ -334,12 +388,82 @@ class ResourceOperations extends Component
$application->update([
'status' => 'exited',
]);
+
+ $persistentVolumes = $application->persistentStorages()->get();
+ foreach ($persistentVolumes as $volume) {
+ $newName = '';
+ if (str_starts_with($volume->name, $volume->resource->uuid)) {
+ $newName = str($volume->name)->replace($volume->resource->uuid, $application->uuid);
+ } else {
+ $newName = $application->uuid.'-'.str($volume->name)->afterLast('-');
+ }
+
+ $newPersistentVolume = $volume->replicate([
+ 'id',
+ 'created_at',
+ 'updated_at',
+ ])->fill([
+ 'name' => $newName,
+ 'resource_id' => $application->id,
+ ]);
+ $newPersistentVolume->save();
+
+ if ($this->cloneVolumeData) {
+ try {
+ StopService::dispatch($application, false, false);
+ $sourceVolume = $volume->name;
+ $targetVolume = $newPersistentVolume->name;
+ $server = $application->service->destination->server;
+
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+
+ StartService::dispatch($application);
+ } catch (\Exception $e) {
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
+ }
+ }
+ }
}
foreach ($new_resource->databases() as $database) {
$database->update([
'status' => 'exited',
]);
+
+ $persistentVolumes = $database->persistentStorages()->get();
+ foreach ($persistentVolumes as $volume) {
+ $newName = '';
+ if (str_starts_with($volume->name, $volume->resource->uuid)) {
+ $newName = str($volume->name)->replace($volume->resource->uuid, $database->uuid);
+ } else {
+ $newName = $database->uuid.'-'.str($volume->name)->afterLast('-');
+ }
+
+ $newPersistentVolume = $volume->replicate([
+ 'id',
+ 'created_at',
+ 'updated_at',
+ ])->fill([
+ 'name' => $newName,
+ 'resource_id' => $database->id,
+ ]);
+ $newPersistentVolume->save();
+
+ if ($this->cloneVolumeData) {
+ try {
+ StopService::dispatch($database->service, false, false);
+ $sourceVolume = $volume->name;
+ $targetVolume = $newPersistentVolume->name;
+ $server = $database->service->destination->server;
+
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+
+ StartService::dispatch($database->service);
+ } catch (\Exception $e) {
+ \Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
+ }
+ }
+ }
}
$new_resource->parse();
diff --git a/resources/views/livewire/project/shared/resource-operations.blade.php b/resources/views/livewire/project/shared/resource-operations.blade.php
index f70af3339..afb6d2cc1 100644
--- a/resources/views/livewire/project/shared/resource-operations.blade.php
+++ b/resources/views/livewire/project/shared/resource-operations.blade.php
@@ -1,8 +1,40 @@
Resource Operations
-
You can easily make different kind of operations on this resource.
+
You can easily make different kind of operations on this resource.
+
+
+
Clone Volume Data
+
+ Clone your volume data to the new resources volumes. This process requires a brief container downtime to ensure data consistency.
+
+
+ @if(!$cloneVolumeData)
+
+
+
+ @else
+
+
+
+ @endif
+
+
+
Clone
-
To another project / environment on a different server.
+
To another project / environment on a different / same server.
@foreach ($servers->sortBy('id') as $server)
From 76f13125fff4dd495727b82240d26d171b7b40c3 Mon Sep 17 00:00:00 2001
From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Date: Mon, 13 Jan 2025 11:13:15 +0100
Subject: [PATCH 16/19] feat: remote server volume cloning
---
app/Jobs/VolumeCloneJob.php | 77 ++++++++++++++++++++++++++++++++++---
1 file changed, 71 insertions(+), 6 deletions(-)
diff --git a/app/Jobs/VolumeCloneJob.php b/app/Jobs/VolumeCloneJob.php
index 95ac14197..f37a9704e 100644
--- a/app/Jobs/VolumeCloneJob.php
+++ b/app/Jobs/VolumeCloneJob.php
@@ -15,10 +15,13 @@ class VolumeCloneJob implements ShouldBeEncrypted, ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+ protected string $cloneDir = '/data/coolify/clone';
+
public function __construct(
protected string $sourceVolume,
protected string $targetVolume,
- protected Server $server,
+ protected Server $sourceServer,
+ protected ?Server $targetServer,
protected LocalPersistentVolume $persistentVolume
) {
$this->onQueue('high');
@@ -27,13 +30,75 @@ class VolumeCloneJob implements ShouldBeEncrypted, ShouldQueue
public function handle()
{
try {
- instant_remote_process([
- "docker volume create $this->targetVolume",
- "docker run --rm -v $this->sourceVolume:/source -v $this->targetVolume:/target alpine sh -c 'cp -a /source/. /target/ && chown -R 1000:1000 /target'",
- ], $this->server);
+ if (! $this->targetServer || $this->targetServer->id === $this->sourceServer->id) {
+ $this->cloneLocalVolume();
+ } else {
+ $this->cloneRemoteVolume();
+ }
} catch (\Exception $e) {
- logger()->error("Failed to copy volume data for {$this->sourceVolume}: ".$e->getMessage());
+ \Log::error("Failed to copy volume data for {$this->sourceVolume}: ".$e->getMessage());
throw $e;
}
}
+
+ protected function cloneLocalVolume()
+ {
+ instant_remote_process([
+ "docker volume create $this->targetVolume",
+ "docker run --rm -v $this->sourceVolume:/source -v $this->targetVolume:/target alpine sh -c 'cp -a /source/. /target/ && chown -R 1000:1000 /target'",
+ ], $this->sourceServer);
+ }
+
+ protected function cloneRemoteVolume()
+ {
+ $sourceCloneDir = "{$this->cloneDir}/{$this->sourceVolume}";
+ $targetCloneDir = "{$this->cloneDir}/{$this->targetVolume}";
+
+ try {
+ instant_remote_process([
+ "mkdir -p $sourceCloneDir",
+ "chmod 777 $sourceCloneDir",
+ "docker run --rm -v $this->sourceVolume:/source -v $sourceCloneDir:/clone alpine sh -c 'cd /source && tar czf /clone/volume-data.tar.gz .'",
+ ], $this->sourceServer);
+
+ instant_remote_process([
+ "mkdir -p $targetCloneDir",
+ "chmod 777 $targetCloneDir",
+ ], $this->targetServer);
+
+ instant_scp(
+ "$sourceCloneDir/volume-data.tar.gz",
+ "$targetCloneDir/volume-data.tar.gz",
+ $this->sourceServer,
+ $this->targetServer
+ );
+
+ instant_remote_process([
+ "docker volume create $this->targetVolume",
+ "docker run --rm -v $this->targetVolume:/target -v $targetCloneDir:/clone alpine sh -c 'cd /target && tar xzf /clone/volume-data.tar.gz && chown -R 1000:1000 /target'",
+ ], $this->targetServer);
+
+ } catch (\Exception $e) {
+ \Log::error("Failed to clone volume {$this->sourceVolume} to {$this->targetVolume}: ".$e->getMessage());
+ throw $e;
+ } finally {
+ try {
+ instant_remote_process([
+ "rm -rf $sourceCloneDir",
+ ], $this->sourceServer, false);
+ } catch (\Exception $e) {
+ \Log::warning('Failed to clean up source server clone directory: '.$e->getMessage());
+ }
+
+ try {
+ if ($this->targetServer) {
+ instant_remote_process([
+ "rm -rf $targetCloneDir",
+ ], $this->targetServer, false);
+ }
+ } catch (\Exception $e) {
+ \Log::warning('Failed to clean up target server clone directory: '.$e->getMessage());
+ }
+ }
+ }
}
From 43dacd83c9f1afa9bbddad9211d223b72b3572d6 Mon Sep 17 00:00:00 2001
From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Date: Mon, 13 Jan 2025 11:13:35 +0100
Subject: [PATCH 17/19] chore: use the new job dispatch
---
app/Livewire/Project/CloneMe.php | 22 +++++++++++--------
.../Project/Shared/ResourceOperations.php | 22 +++++++++++--------
2 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/app/Livewire/Project/CloneMe.php b/app/Livewire/Project/CloneMe.php
index e794ff2ea..c71f6db64 100644
--- a/app/Livewire/Project/CloneMe.php
+++ b/app/Livewire/Project/CloneMe.php
@@ -218,14 +218,15 @@ class CloneMe extends Component
StopApplication::dispatch($application, false, false);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $application->destination->server;
+ $sourceServer = $application->destination->server;
+ $targetServer = $newApplication->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
queue_application_deployment(
deployment_uuid: (string) new Cuid2,
application: $application,
- server: $server,
+ server: $sourceServer,
destination: $application->destination,
no_questions_asked: true
);
@@ -325,9 +326,10 @@ class CloneMe extends Component
StopDatabase::dispatch($database);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $database->destination->server;
+ $sourceServer = $database->destination->server;
+ $targetServer = $newDatabase->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
StartDatabase::dispatch($database);
} catch (\Exception $e) {
@@ -452,9 +454,10 @@ class CloneMe extends Component
StopService::dispatch($application, false, false);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $application->service->destination->server;
+ $sourceServer = $application->service->destination->server;
+ $targetServer = $newService->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
StartService::dispatch($application);
} catch (\Exception $e) {
@@ -505,9 +508,10 @@ class CloneMe extends Component
StopService::dispatch($database->service, false, false);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $database->service->destination->server;
+ $sourceServer = $database->service->destination->server;
+ $targetServer = $newService->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
StartService::dispatch($database->service);
} catch (\Exception $e) {
diff --git a/app/Livewire/Project/Shared/ResourceOperations.php b/app/Livewire/Project/Shared/ResourceOperations.php
index 705a8b49a..e19f1272d 100644
--- a/app/Livewire/Project/Shared/ResourceOperations.php
+++ b/app/Livewire/Project/Shared/ResourceOperations.php
@@ -153,14 +153,15 @@ class ResourceOperations extends Component
StopApplication::dispatch($this->resource, false, false);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $this->resource->destination->server;
+ $sourceServer = $this->resource->destination->server;
+ $targetServer = $new_resource->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
queue_application_deployment(
deployment_uuid: (string) new Cuid2,
application: $this->resource,
- server: $server,
+ server: $sourceServer,
destination: $this->resource->destination,
no_questions_asked: true
);
@@ -276,9 +277,10 @@ class ResourceOperations extends Component
StopDatabase::dispatch($this->resource);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $this->resource->destination->server;
+ $sourceServer = $this->resource->destination->server;
+ $targetServer = $new_resource->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
StartDatabase::dispatch($this->resource);
} catch (\Exception $e) {
@@ -413,9 +415,10 @@ class ResourceOperations extends Component
StopService::dispatch($application, false, false);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $application->service->destination->server;
+ $sourceServer = $application->service->destination->server;
+ $targetServer = $new_resource->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
StartService::dispatch($application);
} catch (\Exception $e) {
@@ -454,9 +457,10 @@ class ResourceOperations extends Component
StopService::dispatch($database->service, false, false);
$sourceVolume = $volume->name;
$targetVolume = $newPersistentVolume->name;
- $server = $database->service->destination->server;
+ $sourceServer = $database->service->destination->server;
+ $targetServer = $new_resource->destination->server;
- VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $server, $newPersistentVolume);
+ VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
StartService::dispatch($database->service);
} catch (\Exception $e) {
From 36b16e9d6247fd3c056a4be9efa5a73a9e933f7d Mon Sep 17 00:00:00 2001
From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Date: Mon, 13 Jan 2025 11:14:00 +0100
Subject: [PATCH 18/19] chore: disable volume data cloning for now
---
resources/views/livewire/project/clone-me.blade.php | 4 ++--
.../livewire/project/shared/resource-operations.blade.php | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/resources/views/livewire/project/clone-me.blade.php b/resources/views/livewire/project/clone-me.blade.php
index f613ca2c7..59ece57d6 100644
--- a/resources/views/livewire/project/clone-me.blade.php
+++ b/resources/views/livewire/project/clone-me.blade.php
@@ -9,7 +9,7 @@
Clone to a new Project
Clone to a new Environment
-
+{{--
Clone Volume Data
@@ -39,7 +39,7 @@
@endif
-
+
--}}
Servers
Choose the server and network to clone the resources to.
diff --git a/resources/views/livewire/project/shared/resource-operations.blade.php b/resources/views/livewire/project/shared/resource-operations.blade.php
index afb6d2cc1..4bbc28c75 100644
--- a/resources/views/livewire/project/shared/resource-operations.blade.php
+++ b/resources/views/livewire/project/shared/resource-operations.blade.php
@@ -1,7 +1,7 @@
Resource Operations
You can easily make different kind of operations on this resource.
-
+{{--
Clone Volume Data
@@ -31,7 +31,7 @@
@endif
-
+
--}}
Clone
To another project / environment on a different / same server.
From aab5398b80148f0e2f62677d6016da1f19736ec9 Mon Sep 17 00:00:00 2001
From: Andras Bacsai
Date: Tue, 14 Jan 2025 08:49:03 +0100
Subject: [PATCH 19/19] fix: monaco editor disabled state
---
app/Providers/HorizonServiceProvider.php | 15 ---------------
.../components/forms/monaco-editor.blade.php | 7 +++++--
.../project/application/general.blade.php | 19 ++++++++++++-------
3 files changed, 17 insertions(+), 24 deletions(-)
diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php
index 2e2b79a59..f851f1f3b 100644
--- a/app/Providers/HorizonServiceProvider.php
+++ b/app/Providers/HorizonServiceProvider.php
@@ -4,30 +4,15 @@ namespace App\Providers;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
-use Laravel\Horizon\Horizon;
use Laravel\Horizon\HorizonApplicationServiceProvider;
class HorizonServiceProvider extends HorizonApplicationServiceProvider
{
- /**
- * Bootstrap any application services.
- */
public function boot(): void
{
parent::boot();
-
- // Horizon::routeSmsNotificationsTo('15556667777');
- // Horizon::routeMailNotificationsTo('example@example.com');
- // Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
-
- Horizon::night();
}
- /**
- * Register the Horizon gate.
- *
- * This gate determines who can access Horizon in non-local environments.
- */
protected function gate(): void
{
Gate::define('viewHorizon', function ($user) {
diff --git a/resources/views/components/forms/monaco-editor.blade.php b/resources/views/components/forms/monaco-editor.blade.php
index c25080cdd..690e654d4 100644
--- a/resources/views/components/forms/monaco-editor.blade.php
+++ b/resources/views/components/forms/monaco-editor.blade.php
@@ -54,7 +54,10 @@
fontSize: monacoFontSize,
lineNumbersMinChars: 3,
automaticLayout: true,
- language: '{{ $language }}'
+ language: '{{ $language }}',
+ domReadOnly: '{{ $readonly ?? false }}',
+ contextmenu: '!{{ $readonly ?? false }}',
+ renderLineHighlight: '{{ $readonly ?? false }} ? none : all'
});
const observer = new MutationObserver((mutations) => {
@@ -95,7 +98,7 @@
}, 5);" :id="monacoId">