Skip to content

Commit d37f63c

Browse files
authored
Merge pull request coollabsio#2789 from coollabsio/next
v4.0.0-beta.308
2 parents 82057e1 + 574bafd commit d37f63c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1783
-1915
lines changed

app/Actions/Application/StopApplication.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ public function handle(Application $application)
3838
}
3939
}
4040
}
41+
if ($application->build_pack === 'dockercompose') {
42+
// remove network
43+
$uuid = $application->uuid;
44+
instant_remote_process(["docker network disconnect {$uuid} coolify-proxy"], $server, false);
45+
instant_remote_process(["docker network rm {$uuid}"], $server, false);
46+
}
4147
}
4248
}
4349
}

app/Actions/Proxy/StartProxy.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ class StartProxy
1111
{
1212
use AsAction;
1313

14-
public function handle(Server $server, bool $async = true): string|Activity
14+
public function handle(Server $server, bool $async = true, bool $force = false): string|Activity
1515
{
1616
try {
1717
$proxyType = $server->proxyType();
18-
if (is_null($proxyType) || $proxyType === 'NONE' || $server->proxy->force_stop || $server->isBuildServer()) {
18+
if ((is_null($proxyType) || $proxyType === 'NONE' || $server->proxy->force_stop || $server->isBuildServer()) && $force === false) {
1919
return 'OK';
2020
}
2121
$commands = collect([]);

app/Actions/Server/CleanupDocker.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class CleanupDocker
1111

1212
public function handle(Server $server, bool $force = true)
1313
{
14+
15+
// cleanup docker images, containers, and builder caches
1416
if ($force) {
1517
instant_remote_process(['docker image prune -af'], $server, false);
1618
instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false);
@@ -20,5 +22,15 @@ public function handle(Server $server, bool $force = true)
2022
instant_remote_process(['docker container prune -f --filter "label=coolify.managed=true"'], $server, false);
2123
instant_remote_process(['docker builder prune -f'], $server, false);
2224
}
25+
// cleanup networks
26+
$networks = collectDockerNetworksByServer($server);
27+
$proxyNetworks = collectProxyDockerNetworksByServer($server);
28+
$diff = $proxyNetworks->diff($networks);
29+
if ($diff->count() > 0) {
30+
$diff->map(function ($network) use ($server) {
31+
instant_remote_process(["docker network disconnect $network coolify-proxy"], $server);
32+
instant_remote_process(["docker network rm $network"], $server);
33+
});
34+
}
2335
}
2436
}

app/Actions/Service/StopService.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,16 @@ public function handle(Service $service)
1919
ray('Stopping service: '.$service->name);
2020
$applications = $service->applications()->get();
2121
foreach ($applications as $application) {
22-
instant_remote_process(["docker rm -f {$application->name}-{$service->uuid}"], $service->server);
22+
instant_remote_process(["docker rm -f {$application->name}-{$service->uuid}"], $service->server, false);
2323
$application->update(['status' => 'exited']);
2424
}
2525
$dbs = $service->databases()->get();
2626
foreach ($dbs as $db) {
27-
instant_remote_process(["docker rm -f {$db->name}-{$service->uuid}"], $service->server);
27+
instant_remote_process(["docker rm -f {$db->name}-{$service->uuid}"], $service->server, false);
2828
$db->update(['status' => 'exited']);
2929
}
30-
instant_remote_process(["docker network disconnect {$service->uuid} coolify-proxy 2>/dev/null"], $service->server, false);
31-
instant_remote_process(["docker network rm {$service->uuid} 2>/dev/null"], $service->server, false);
32-
// TODO: make notification for databases
33-
// $service->environment->project->team->notify(new StatusChanged($service));
30+
instant_remote_process(["docker network disconnect {$service->uuid} coolify-proxy"], $service->server);
31+
instant_remote_process(["docker network rm {$service->uuid}"], $service->server);
3432
} catch (\Exception $e) {
3533
echo $e->getMessage();
3634
ray($e->getMessage());

app/Http/Controllers/Api/ApplicationsController.php

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,9 @@ private function create_application(Request $request, $type)
683683
if (! $request->has('name')) {
684684
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch));
685685
}
686+
if ($request->build_pack === 'dockercompose') {
687+
$request->offsetSet('ports_exposes', '80');
688+
}
686689
$validator = customApiValidator($request->all(), [
687690
sharedDataApplications(),
688691
'git_repository' => 'string|required',
@@ -756,6 +759,9 @@ private function create_application(Request $request, $type)
756759
if (! $request->has('name')) {
757760
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch));
758761
}
762+
if ($request->build_pack === 'dockercompose') {
763+
$request->offsetSet('ports_exposes', '80');
764+
}
759765
$validator = customApiValidator($request->all(), [
760766
sharedDataApplications(),
761767
'git_repository' => 'string|required',
@@ -847,6 +853,9 @@ private function create_application(Request $request, $type)
847853
if (! $request->has('name')) {
848854
$request->offsetSet('name', generate_application_name($request->git_repository, $request->git_branch));
849855
}
856+
if ($request->build_pack === 'dockercompose') {
857+
$request->offsetSet('ports_exposes', '80');
858+
}
850859
$validator = customApiValidator($request->all(), [
851860
sharedDataApplications(),
852861
'git_repository' => 'string|required',
@@ -1231,6 +1240,16 @@ public function application_by_uuid(Request $request)
12311240
format: 'uuid',
12321241
)
12331242
),
1243+
new OA\Parameter(
1244+
name: 'cleanup',
1245+
in: 'query',
1246+
description: 'Delete configurations and volumes.',
1247+
required: false,
1248+
schema: new OA\Schema(
1249+
type: 'boolean',
1250+
default: true,
1251+
)
1252+
),
12341253
],
12351254
responses: [
12361255
new OA\Response(
@@ -1264,15 +1283,12 @@ public function application_by_uuid(Request $request)
12641283
public function delete_by_uuid(Request $request)
12651284
{
12661285
$teamId = getTeamIdFromToken();
1267-
$cleanup = $request->query->get('cleanup') ?? false;
1286+
$cleanup = filter_var($request->query->get('cleanup', true), FILTER_VALIDATE_BOOLEAN);
12681287
if (is_null($teamId)) {
12691288
return invalidTokenResponse();
12701289
}
1271-
1272-
if ($request->collect()->count() == 0) {
1273-
return response()->json([
1274-
'message' => 'Invalid request.',
1275-
], 400);
1290+
if (! $request->uuid) {
1291+
return response()->json(['message' => 'UUID is required.'], 404);
12761292
}
12771293
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
12781294

@@ -1281,7 +1297,10 @@ public function delete_by_uuid(Request $request)
12811297
'message' => 'Application not found',
12821298
], 404);
12831299
}
1284-
DeleteResourceJob::dispatch($application, $cleanup);
1300+
DeleteResourceJob::dispatch(
1301+
resource: $application,
1302+
deleteConfigurations: $cleanup,
1303+
deleteVolumes: $cleanup);
12851304

12861305
return response()->json([
12871306
'message' => 'Application deletion request queued.',

app/Http/Controllers/Api/DatabasesController.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use App\Actions\Database\StopDatabaseProxy;
1010
use App\Enums\NewDatabaseTypes;
1111
use App\Http\Controllers\Controller;
12+
use App\Jobs\DeleteResourceJob;
1213
use App\Models\Project;
1314
use App\Models\Server;
1415
use Illuminate\Http\Request;
@@ -1528,6 +1529,16 @@ public function create_database(Request $request, NewDatabaseTypes $type)
15281529
format: 'uuid',
15291530
)
15301531
),
1532+
new OA\Parameter(
1533+
name: 'cleanup',
1534+
in: 'query',
1535+
description: 'Delete configurations and volumes.',
1536+
required: false,
1537+
schema: new OA\Schema(
1538+
type: 'boolean',
1539+
default: true,
1540+
)
1541+
),
15311542
],
15321543
responses: [
15331544
new OA\Response(
@@ -1561,6 +1572,7 @@ public function create_database(Request $request, NewDatabaseTypes $type)
15611572
public function delete_by_uuid(Request $request)
15621573
{
15631574
$teamId = getTeamIdFromToken();
1575+
$cleanup = filter_var($request->query->get('cleanup', true), FILTER_VALIDATE_BOOLEAN);
15641576
if (is_null($teamId)) {
15651577
return invalidTokenResponse();
15661578
}
@@ -1571,8 +1583,10 @@ public function delete_by_uuid(Request $request)
15711583
if (! $database) {
15721584
return response()->json(['message' => 'Database not found.'], 404);
15731585
}
1574-
StopDatabase::dispatch($database);
1575-
$database->forceDelete();
1586+
DeleteResourceJob::dispatch(
1587+
resource: $database,
1588+
deleteConfigurations: $cleanup,
1589+
deleteVolumes: $cleanup);
15761590

15771591
return response()->json([
15781592
'message' => 'Database deletion request queued.',

app/Jobs/ApplicationDeploymentJob.php

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ private function deploy_docker_compose_buildpack()
462462
if ($this->env_filename) {
463463
$command .= " --env-file {$this->workdir}/{$this->env_filename}";
464464
}
465-
$command .= " --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build";
465+
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build";
466466
$this->execute_remote_command(
467467
[executeInDocker($this->deployment_uuid, $command), 'hidden' => true],
468468
);
@@ -516,7 +516,7 @@ private function deploy_docker_compose_buildpack()
516516
if ($this->env_filename) {
517517
$command .= " --env-file {$this->workdir}/{$this->env_filename}";
518518
}
519-
$command .= " --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d";
519+
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d";
520520
$this->execute_remote_command(
521521
[executeInDocker($this->deployment_uuid, $command), 'hidden' => true],
522522
);
@@ -2034,12 +2034,12 @@ private function build_by_compose_file()
20342034
if ($this->application->build_pack === 'dockerimage') {
20352035
$this->application_deployment_queue->addLogEntry('Pulling latest images from the registry.');
20362036
$this->execute_remote_command(
2037-
[executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} pull"), 'hidden' => true],
2038-
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} build"), 'hidden' => true],
2037+
[executeInDocker($this->deployment_uuid, "docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} pull"), 'hidden' => true],
2038+
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} build"), 'hidden' => true],
20392039
);
20402040
} else {
20412041
$this->execute_remote_command(
2042-
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build"), 'hidden' => true],
2042+
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build"), 'hidden' => true],
20432043
);
20442044
}
20452045
$this->application_deployment_queue->addLogEntry('New images built.');
@@ -2050,17 +2050,17 @@ private function start_by_compose_file()
20502050
if ($this->application->build_pack === 'dockerimage') {
20512051
$this->application_deployment_queue->addLogEntry('Pulling latest images from the registry.');
20522052
$this->execute_remote_command(
2053-
[executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} pull"), 'hidden' => true],
2054-
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} up --build -d"), 'hidden' => true],
2053+
[executeInDocker($this->deployment_uuid, "docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} pull"), 'hidden' => true],
2054+
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} up --build -d"), 'hidden' => true],
20552055
);
20562056
} else {
20572057
if ($this->use_build_server) {
20582058
$this->execute_remote_command(
2059-
["{$this->coolify_variables} docker compose --project-directory {$this->configuration_dir} -f {$this->configuration_dir}{$this->docker_compose_location} up --build -d", 'hidden' => true],
2059+
["{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->configuration_dir} -f {$this->configuration_dir}{$this->docker_compose_location} up --build -d", 'hidden' => true],
20602060
);
20612061
} else {
20622062
$this->execute_remote_command(
2063-
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up --build -d"), 'hidden' => true],
2063+
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up --build -d"), 'hidden' => true],
20642064
);
20652065
}
20662066
}

app/Jobs/DeleteResourceJob.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,18 @@ class DeleteResourceJob implements ShouldBeEncrypted, ShouldQueue
2828
{
2929
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
3030

31-
public function __construct(public Application|Service|StandalonePostgresql|StandaloneRedis|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource, public bool $deleteConfigurations = false) {}
31+
public function __construct(
32+
public Application|Service|StandalonePostgresql|StandaloneRedis|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource,
33+
public bool $deleteConfigurations = false,
34+
public bool $deleteVolumes = false) {}
3235

3336
public function handle()
3437
{
3538
try {
36-
$this->resource->forceDelete();
39+
$persistentStorages = collect();
3740
switch ($this->resource->type()) {
3841
case 'application':
42+
$persistentStorages = $this->resource?->persistentStorages()?->get();
3943
StopApplication::run($this->resource);
4044
break;
4145
case 'standalone-postgresql':
@@ -46,13 +50,18 @@ public function handle()
4650
case 'standalone-keydb':
4751
case 'standalone-dragonfly':
4852
case 'standalone-clickhouse':
53+
$persistentStorages = $this->resource?->persistentStorages()?->get();
4954
StopDatabase::run($this->resource);
5055
break;
5156
case 'service':
5257
StopService::run($this->resource);
5358
DeleteService::run($this->resource);
5459
break;
5560
}
61+
62+
if ($this->deleteVolumes && $this->resource->type() !== 'service') {
63+
$this->resource?->delete_volumes($persistentStorages);
64+
}
5665
if ($this->deleteConfigurations) {
5766
$this->resource?->delete_configurations();
5867
}
@@ -61,6 +70,7 @@ public function handle()
6170
send_internal_notification('ContainerStoppingJob failed with: '.$e->getMessage());
6271
throw $e;
6372
} finally {
73+
$this->resource->forceDelete();
6474
Artisan::queue('cleanup:stucked-resources');
6575
}
6676
}

app/Livewire/Project/Shared/Danger.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ class Danger extends Component
1616

1717
public bool $delete_configurations = true;
1818

19+
public bool $delete_volumes = true;
20+
1921
public ?string $modalId = null;
2022

2123
public function mount()
@@ -31,7 +33,7 @@ public function delete()
3133
try {
3234
// $this->authorize('delete', $this->resource);
3335
$this->resource->delete();
34-
DeleteResourceJob::dispatch($this->resource, $this->delete_configurations);
36+
DeleteResourceJob::dispatch($this->resource, $this->delete_configurations, $this->delete_volumes);
3537

3638
return redirect()->route('project.resource.index', [
3739
'project_uuid' => $this->projectUuid,

app/Livewire/Server/Proxy/Deploy.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public function startProxy()
8484
try {
8585
$this->server->proxy->force_stop = false;
8686
$this->server->save();
87-
$activity = StartProxy::run($this->server);
87+
$activity = StartProxy::run($this->server, force: true);
8888
$this->dispatch('activityMonitor', $activity->id, ProxyStatusChanged::class);
8989
} catch (\Throwable $e) {
9090
return handleError($e, $this);

0 commit comments

Comments
 (0)