Refactored code for better container management

This commit is contained in:
Andras Bacsai 2023-11-08 15:40:06 +01:00
parent 51423394ba
commit 9698a051d9
5 changed files with 51 additions and 49 deletions

View File

@ -3,7 +3,6 @@
namespace App\Actions\Application;
use App\Models\Application;
use App\Notifications\Application\StatusChanged;
use Lorisleiva\Actions\Concerns\AsAction;
class StopApplication
@ -12,7 +11,7 @@ class StopApplication
public function handle(Application $application)
{
$server = $application->destination->server;
$containers = getCurrentApplicationContainerStatus($server, $application->id);
$containers = getCurrentApplicationContainerStatus($server, $application->id, 0);
if ($containers->count() > 0) {
foreach ($containers as $container) {
$containerName = data_get($container, 'Names');

View File

@ -31,7 +31,7 @@ public function mount()
$this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail();
$this->status = $this->resource->status;
$this->server = $this->resource->destination->server;
$containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id);
$containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id, 0);
if ($containers->count() > 0) {
$this->container = data_get($containers[0], 'Names');
}

View File

@ -52,7 +52,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
private GithubApp|GitlabApp|string $source = 'other';
private StandaloneDocker|SwarmDocker $destination;
private Server $server;
private ApplicationPreview|null $preview = null;
private ?ApplicationPreview $preview = null;
private string $container_name;
private ?string $currently_running_container_name = null;
@ -139,21 +139,6 @@ public function __construct(int $application_deployment_queue_id)
public function handle(): void
{
// ray()->measure();
$containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id);
if ($containers->count() === 1) {
$this->currently_running_container_name = data_get($containers[0], 'Names');
} else {
$foundContainer = $containers->filter(function ($container) {
return !str(data_get($container, 'Names'))->startsWith("{$this->application->uuid}-pr-");
})->first();
if ($foundContainer) {
$this->currently_running_container_name = data_get($foundContainer, 'Names');
}
}
if ($this->pull_request_id !== 0 && $this->pull_request_id !== null) {
$this->currently_running_container_name = $this->container_name;
}
$this->application_deployment_queue->update([
'status' => ApplicationDeploymentStatus::IN_PROGRESS->value,
]);
@ -502,6 +487,7 @@ private function health_check()
}
private function deploy_pull_request()
{
$this->newVersionIsHealthy = true;
$this->generate_image_names();
$this->execute_remote_command([
"echo 'Starting pull request (#{$this->pull_request_id}) deployment of {$this->customRepository}:{$this->application->git_branch}.'",
@ -518,12 +504,7 @@ private function deploy_pull_request()
// $this->generate_build_env_variables();
// $this->add_build_env_variables_to_dockerfile();
$this->build_image();
if ($this->currently_running_container_name) {
$this->execute_remote_command(
["echo -n 'Removing old version of your application.'"],
[executeInDocker($this->deployment_uuid, "docker rm -f $this->currently_running_container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
);
}
$this->stop_running_container();
$this->execute_remote_command(
["echo -n 'Starting preview deployment.'"],
[executeInDocker($this->deployment_uuid, "docker compose --project-directory {$this->workdir} up -d"), "hidden" => true],
@ -980,18 +961,30 @@ private function build_image()
private function stop_running_container(bool $force = false)
{
if ($this->currently_running_container_name) {
if ($this->newVersionIsHealthy || $force) {
$this->execute_remote_command(
["echo -n 'Removing old version of your application.'"],
[executeInDocker($this->deployment_uuid, "docker rm -f $this->currently_running_container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
);
$this->execute_remote_command(["echo -n 'Removing old version of your application.'"]);
if ($this->newVersionIsHealthy || $force) {
$containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id);
if ($this->pull_request_id !== 0) {
$containers = $containers->filter(function ($container) {
return data_get($container, 'Names') === $this->container_name;
});
} else {
$this->execute_remote_command(
["echo -n 'New version is not healthy, rolling back to the old version.'"],
[executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
);
$containers = $containers->filter(function ($container) {
return data_get($container, 'Names') !== $this->container_name;
});
}
$containers->each(function ($container) {
$containerName = data_get($container, 'Names');
$this->execute_remote_command(
[executeInDocker($this->deployment_uuid, "docker rm -f $containerName >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
);
});
} else {
$this->execute_remote_command(
["echo -n 'New version is not healthy, rolling back to the old version.'"],
[executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true],
);
}
}
@ -1057,8 +1050,11 @@ public function failed(Throwable $exception): void
{
$this->execute_remote_command(
["echo 'Oops something is not okay, are you okay? 😢'"],
["echo '{$exception->getMessage()}'"]
["echo '{$exception->getMessage()}'"],
["echo -n 'Deployment failed. Removing the new version of your application.'"],
[executeInDocker($this->deployment_uuid, "docker rm -f $this->container_name >/dev/null 2>&1"), "hidden" => true, "ignore_errors" => true]
);
$this->next(ApplicationDeploymentStatus::FAILED->value);
}
}

View File

@ -10,15 +10,24 @@
function getCurrentApplicationContainerStatus(Server $server, int $id, ?int $pullRequestId = null): Collection
{
if ($pullRequestId) {
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --filter='label=coolify.pullRequestId={$pullRequestId}' --format '{{json .}}' "], $server);
} else {
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --format '{{json .}}'"], $server);
}
if (!$containers) {
return collect([]);
}
return format_docker_command_output_to_json($containers);
ray($id, $pullRequestId);
$containers = collect([]);
$containers = instant_remote_process(["docker ps -a --filter='label=coolify.applicationId={$id}' --format '{{json .}}' "], $server);
$containers = format_docker_command_output_to_json($containers);
$containers = $containers->map(function ($container) use ($pullRequestId) {
$labels = data_get($container, 'Labels');
if (!str($labels)->contains("coolify.pullRequestId=")) {
data_set($container, 'Labels', $labels . ",coolify.pullRequestId={$pullRequestId}");
return $container;
}
if (str($labels)->contains("coolify.pullRequestId=$pullRequestId")) {
return $container;
}
return null;
});
$containers = $containers->filter();
ray($containers);
return $containers;
}
function format_docker_command_output_to_json($rawOutput): Collection
@ -128,9 +137,7 @@ function defaultLabels($id, $name, $pull_request_id = 0, string $type = 'applica
$labels->push("coolify." . $type . "Id=" . $id);
$labels->push("coolify.type=$type");
$labels->push('coolify.name=' . $name);
if ($pull_request_id !== 0) {
$labels->push('coolify.pullRequestId=' . $pull_request_id);
}
$labels->push('coolify.pullRequestId=' . $pull_request_id);
if ($type === 'service') {
$labels->push('coolify.service.subId=' . $subId);
$labels->push('coolify.service.subType=' . $subType);

View File

@ -13,7 +13,7 @@
@forelse ($deployments as $deployment)
<a @class([
'bg-coolgray-200 p-2 border-l border-dashed transition-colors hover:no-underline',
'cursor-not-allowed hover:bg-coolgray-200' =>
'hover:bg-coolgray-200' =>
data_get($deployment, 'status') === 'queued' ||
data_get($deployment, 'status') === 'cancelled by system',
'border-warning hover:bg-warning hover:text-black' =>