fix: complex container status
feat: able to change primary server feat: links inside the logs
This commit is contained in:
parent
6a00d8c88c
commit
5179129a6b
@ -66,6 +66,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
private Server $mainServer;
|
||||
private ?ApplicationPreview $preview = null;
|
||||
private ?string $git_type = null;
|
||||
private bool $only_this_server = false;
|
||||
|
||||
private string $container_name;
|
||||
private ?string $currently_running_container_name = null;
|
||||
@ -115,6 +116,7 @@ public function __construct(int $application_deployment_queue_id)
|
||||
$this->commit = $this->application_deployment_queue->commit;
|
||||
$this->force_rebuild = $this->application_deployment_queue->force_rebuild;
|
||||
$this->restart_only = $this->application_deployment_queue->restart_only;
|
||||
$this->only_this_server = $this->application_deployment_queue->only_this_server;
|
||||
|
||||
$this->git_type = data_get($this->application_deployment_queue, 'git_type');
|
||||
|
||||
@ -887,7 +889,7 @@ private function deploy_to_additional_destinations()
|
||||
destination: $destination,
|
||||
no_questions_asked: true,
|
||||
);
|
||||
$this->application_deployment_queue->addLogEntry("Deploying to additional server: {$server->name}. Click here to see the deployment status: " . route('project.application.deployment.show', [
|
||||
$this->application_deployment_queue->addLogEntry("Deployment to {$server->name}. Logs: " . route('project.application.deployment.show', [
|
||||
'project_uuid' => data_get($this->application, 'environment.project.uuid'),
|
||||
'application_uuid' => data_get($this->application, 'uuid'),
|
||||
'deployment_uuid' => $deployment_uuid,
|
||||
@ -1619,7 +1621,9 @@ private function next(string $status)
|
||||
return;
|
||||
}
|
||||
if ($status === ApplicationDeploymentStatus::FINISHED->value) {
|
||||
if (!$this->only_this_server) {
|
||||
$this->deploy_to_additional_destinations();
|
||||
}
|
||||
$this->application->environment->project->team?->notify(new DeploymentSuccess($this->application, $this->deployment_uuid, $this->preview));
|
||||
}
|
||||
}
|
||||
|
@ -44,17 +44,19 @@ public function uniqueId(): int
|
||||
public function handle()
|
||||
{
|
||||
$applications = $this->server->applications();
|
||||
$skip_these_applications = collect([]);
|
||||
foreach ($applications as $application) {
|
||||
if ($application->additional_servers->count() > 0) {
|
||||
$is_main_server = $application->destination->server->id === $this->server->id;
|
||||
if ($is_main_server) {
|
||||
$skip_these_applications->push($application);
|
||||
ComplexStatusCheck::run($application);
|
||||
$applications = $applications->filter(function ($value, $key) use ($application) {
|
||||
return $value->id !== $application->id;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
$applications = $applications->filter(function ($value, $key) use ($skip_these_applications) {
|
||||
return !$skip_these_applications->pluck('id')->contains($value->id);
|
||||
});
|
||||
|
||||
if (!$this->server->isFunctional()) {
|
||||
return 'Server is not ready.';
|
||||
|
@ -33,15 +33,11 @@ public function check_status($showNotification = false)
|
||||
{
|
||||
if ($this->application->destination->server->isFunctional()) {
|
||||
dispatch(new ContainerStatusJob($this->application->destination->server));
|
||||
// $this->application->refresh();
|
||||
// $this->application->previews->each(function ($preview) {
|
||||
// $preview->refresh();
|
||||
// });
|
||||
} else {
|
||||
dispatch(new ServerStatusJob($this->application->destination->server));
|
||||
}
|
||||
|
||||
if ($showNotification) $this->dispatch('success', "Application status updated.");
|
||||
if ($showNotification) $this->dispatch('success', "Success", "Application status updated.");
|
||||
}
|
||||
|
||||
public function force_deploy_without_cache()
|
||||
|
@ -38,7 +38,7 @@ public function check_status($showNotification = false)
|
||||
{
|
||||
dispatch_sync(new ContainerStatusJob($this->database->destination->server));
|
||||
$this->database->refresh();
|
||||
if ($showNotification) $this->dispatch('success', 'Database status updated.');
|
||||
if ($showNotification) $this->dispatch('success', 'Success', 'Database status updated.');
|
||||
}
|
||||
|
||||
public function mount()
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
use App\Actions\Application\StopApplicationOneServer;
|
||||
use App\Events\ApplicationStatusChanged;
|
||||
use App\Jobs\ContainerStatusJob;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Livewire\Component;
|
||||
@ -19,7 +20,6 @@ public function getListeners()
|
||||
$teamId = auth()->user()->currentTeam()->id;
|
||||
return [
|
||||
"echo-private:team.{$teamId},ApplicationStatusChanged" => 'loadData',
|
||||
"loadData",
|
||||
];
|
||||
}
|
||||
public function mount()
|
||||
@ -41,10 +41,18 @@ public function loadData()
|
||||
$this->networks = $this->networks->reject(function ($network) {
|
||||
return $this->resource->destination->server->id == $network->server->id;
|
||||
});
|
||||
if ($this->resource?->additional_servers?->count() > 0) {
|
||||
$this->networks = $this->networks->reject(function ($network) {
|
||||
return $this->resource->additional_servers->pluck('id')->contains($network->server->id);
|
||||
});
|
||||
}
|
||||
}
|
||||
public function stop(int $server_id)
|
||||
{
|
||||
$server = Server::find($server_id);
|
||||
StopApplicationOneServer::run($this->resource, $server);
|
||||
$this->refreshServers();
|
||||
}
|
||||
public function redeploy(int $network_id, int $server_id)
|
||||
{
|
||||
if ($this->resource->additional_servers->count() > 0 && str($this->resource->docker_registry_image_name)->isEmpty()) {
|
||||
@ -59,6 +67,7 @@ public function redeploy(int $network_id, int $server_id)
|
||||
application: $this->resource,
|
||||
server: $server,
|
||||
destination: $destination,
|
||||
only_this_server: true,
|
||||
no_questions_asked: true,
|
||||
);
|
||||
return redirect()->route('project.application.deployment.show', [
|
||||
@ -68,11 +77,28 @@ public function redeploy(int $network_id, int $server_id)
|
||||
'environment_name' => data_get($this->resource, 'environment.name'),
|
||||
]);
|
||||
}
|
||||
public function promote(int $network_id, int $server_id)
|
||||
{
|
||||
$main_destination = $this->resource->destination;
|
||||
$this->resource->update([
|
||||
'destination_id' => $network_id,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
]);
|
||||
$this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]);
|
||||
$this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]);
|
||||
$this->refreshServers();
|
||||
}
|
||||
public function refreshServers()
|
||||
{
|
||||
ContainerStatusJob::dispatchSync($this->resource->destination->server);
|
||||
$this->loadData();
|
||||
$this->dispatch('refresh');
|
||||
ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id'));
|
||||
}
|
||||
public function addServer(int $network_id, int $server_id)
|
||||
{
|
||||
$this->resource->additional_networks()->attach($network_id, ['server_id' => $server_id]);
|
||||
$this->resource->load(['additional_networks']);
|
||||
$this->dispatch('loadData');
|
||||
$this->loadData();
|
||||
ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id'));
|
||||
}
|
||||
public function removeServer(int $network_id, int $server_id)
|
||||
@ -84,8 +110,7 @@ public function removeServer(int $network_id, int $server_id)
|
||||
$server = Server::find($server_id);
|
||||
StopApplicationOneServer::run($this->resource, $server);
|
||||
$this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]);
|
||||
$this->resource->load(['additional_networks']);
|
||||
$this->dispatch('loadData');
|
||||
$this->loadData();
|
||||
ApplicationStatusChanged::dispatch(data_get($this->resource, 'environment.project.team.id'));
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
@ -274,17 +273,13 @@ public function status(): Attribute
|
||||
foreach ($additional_servers_status as $status) {
|
||||
$server_status = str($status)->before(':')->value();
|
||||
$server_health = str($status)->after(':')->value() ?? 'unhealthy';
|
||||
if ($server_status !== 'running') {
|
||||
if ($main_server_status !== $server_status) {
|
||||
$complex_status = 'degraded';
|
||||
}
|
||||
}
|
||||
if ($server_health !== 'healthy') {
|
||||
if ($main_server_health !== $server_health) {
|
||||
$complex_health = 'unhealthy';
|
||||
}
|
||||
}
|
||||
}
|
||||
return "$complex_status:$complex_health";
|
||||
}
|
||||
},
|
||||
|
@ -11,11 +11,12 @@ class Index extends Component
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public $status = "exited:unhealthy";
|
||||
public function __construct(
|
||||
public string $status = 'exited',
|
||||
)
|
||||
{
|
||||
//
|
||||
public $resource = null,
|
||||
public bool $showRefreshButton = true,
|
||||
) {
|
||||
$this->status = $resource->status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,7 @@
|
||||
use App\Models\StandaloneDocker;
|
||||
use Spatie\Url\Url;
|
||||
|
||||
function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, Server $server = null, StandaloneDocker $destination = null)
|
||||
function queue_application_deployment(Application $application, string $deployment_uuid, int | null $pull_request_id = 0, string $commit = 'HEAD', bool $force_rebuild = false, bool $is_webhook = false, bool $restart_only = false, ?string $git_type = null, bool $no_questions_asked = false, Server $server = null, StandaloneDocker $destination = null, bool $only_this_server = false)
|
||||
{
|
||||
$application_id = $application->id;
|
||||
$deployment_link = Url::fromString($application->link() . "/deployment/{$deployment_uuid}");
|
||||
@ -37,7 +37,8 @@ function queue_application_deployment(Application $application, string $deployme
|
||||
'is_webhook' => $is_webhook,
|
||||
'restart_only' => $restart_only,
|
||||
'commit' => $commit,
|
||||
'git_type' => $git_type
|
||||
'git_type' => $git_type,
|
||||
'only_this_server' => $only_this_server
|
||||
]);
|
||||
|
||||
if ($no_questions_asked) {
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->boolean('only_this_server')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('application_deployment_queues', function (Blueprint $table) {
|
||||
$table->dropColumn('only_this_server');
|
||||
});
|
||||
}
|
||||
};
|
@ -41,7 +41,7 @@
|
||||
@if ($resource->getMorphClass() == 'App\Models\Service')
|
||||
<x-status.services :service="$resource" />
|
||||
@else
|
||||
<x-status.index :status="$resource->status" />
|
||||
<x-status.index :resource="$resource" />
|
||||
@endif
|
||||
</ol>
|
||||
</nav>
|
||||
|
@ -1,4 +1,3 @@
|
||||
@props(['status', 'showRefreshButton' => true])
|
||||
@if (str($status)->startsWith('running'))
|
||||
<x-status.running :status="$status" />
|
||||
@elseif(str($status)->startsWith('restarting') ||
|
||||
@ -6,7 +5,7 @@
|
||||
str($status)->startsWith('degraded'))
|
||||
<x-status.restarting :status="$status" />
|
||||
@else
|
||||
<x-status.stopped :status="$status"/>
|
||||
<x-status.stopped :status="$status" />
|
||||
@endif
|
||||
|
||||
@if (!str($status)->contains('exited') && $showRefreshButton)
|
||||
|
@ -12,5 +12,4 @@
|
||||
data_get($application_deployment_queue, 'status') === 'queued')
|
||||
<x-forms.button isError wire:click.prevent="cancel">Cancel</x-forms.button>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
@ -51,12 +51,17 @@ class="fixed top-4 right-16" x-on:click="toggleScroll"><svg class="icon" viewBox
|
||||
@if (decode_remote_command_output($application_deployment_queue)->count() > 0)
|
||||
@foreach (decode_remote_command_output($application_deployment_queue) as $line)
|
||||
<div @class([
|
||||
'font-mono whitespace-pre-line',
|
||||
'font-mono',
|
||||
'text-warning' => $line['hidden'],
|
||||
'text-red-500' => $line['type'] == 'stderr',
|
||||
])>[{{ $line['timestamp'] }}] @if ($line['hidden'])
|
||||
<br>COMMAND: <br>{{ $line['command'] }} <br><br>OUTPUT:
|
||||
@endif{{ $line['output'] }}@if ($line['hidden'])
|
||||
@endif @if (str($line['output'])->contains('http://') || str($line['output'])->contains('https://'))
|
||||
@php
|
||||
$line['output'] = preg_replace('/(https?:\/\/[^\s]+)/', '<a href="$1" target="_blank" class="underline text-neutral-400">$1</a>', $line['output']);
|
||||
@endphp {!! $line['output'] !!}
|
||||
@else
|
||||
{{ $line['output'] }}
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
|
@ -1,4 +1,4 @@
|
||||
<nav wire:poll.30000ms="check_status">
|
||||
<nav wire:poll.5000ms="check_status">
|
||||
<x-resources.breadcrumbs :resource="$application" :parameters="$parameters" />
|
||||
<div class="navbar-main">
|
||||
<a class="{{ request()->routeIs('project.application.configuration') ? 'text-white' : '' }}"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<div class="grid grid-cols-1 gap-4 py-4">
|
||||
<div class="flex gap-2">
|
||||
<div class="relative flex flex-col text-white cursor-default box-without-bg bg-coolgray-100 w-96">
|
||||
<div class="font-bold">Main Server</div>
|
||||
<div class="text-xl font-bold">Primary Server</div>
|
||||
@if (str($resource->realStatus())->startsWith('running'))
|
||||
<div title="{{ $resource->realStatus() }}" class="absolute bg-success -top-1 -left-1 badge badge-xs">
|
||||
</div>
|
||||
@ -21,7 +21,11 @@
|
||||
</div>
|
||||
@if ($resource?->additional_networks?->count() > 0)
|
||||
<x-forms.button
|
||||
wire:click="redeploy('{{ data_get($resource, 'destination.id') }}','{{ data_get($resource, 'destination.server.id') }}')">Redeploy</x-forms.button>
|
||||
wire:click="redeploy('{{ data_get($resource, 'destination.id') }}','{{ data_get($resource, 'destination.server.id') }}')">Deploy</x-forms.button>
|
||||
@if (str($resource->realStatus())->startsWith('running'))
|
||||
<x-forms.button isError
|
||||
wire:click="stop('{{ data_get($resource, 'destination.server.id') }}')">Stop</x-forms.button>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
@if ($resource?->additional_networks?->count() > 0)
|
||||
@ -41,16 +45,23 @@ class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||
<div>
|
||||
Network: {{ data_get($destination, 'network') }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<x-forms.button
|
||||
wire:click="redeploy('{{ data_get($destination, 'id') }}','{{ data_get($destination, 'server.id') }}')">Redeploy</x-forms.button>
|
||||
wire:click="redeploy('{{ data_get($destination, 'id') }}','{{ data_get($destination, 'server.id') }}')">Deploy</x-forms.button>
|
||||
<x-forms.button
|
||||
wire:click="promote('{{ data_get($destination, 'id') }}','{{ data_get($destination, 'server.id') }}')">Promote
|
||||
to Primary </x-forms.button>
|
||||
@if (data_get_str($destination, 'pivot.status')->startsWith('running'))
|
||||
<x-forms.button isError
|
||||
wire:click="stop('{{ data_get($destination, 'server.id') }}')">Stop</x-forms.button>
|
||||
@endif
|
||||
<x-new-modal
|
||||
action="removeServer({{ data_get($destination, 'id') }},{{ data_get($destination, 'server.id') }})"
|
||||
isErrorButton buttonTitle="Remove Server">
|
||||
This will stop the running application in this server and remove it as a deployment
|
||||
destination.<br><br>Please think again.
|
||||
</x-new-modal>
|
||||
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
|
Loading…
Reference in New Issue
Block a user