Files
coolify/resources/views/livewire/server/transfer.blade.php
T

204 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div>
<x-slot:title>
{{ data_get_str($server, 'name')->limit(10) }} > Transfer | Coolify
</x-slot>
<livewire:server.navbar :server="$server" />
<div
class="server-settings-workspace application-settings-workspace mt-4 grid w-full max-w-none min-w-0 gap-8 lg:mt-0 xl:grid-cols-[210px_minmax(0,1fr)] xl:gap-8">
<x-server.sidebar :server="$server" activeMenu="transfer" />
<div class="application-settings-form flex w-full flex-col gap-6">
@if ($this->isLocalhost)
<x-application.settings-section id="server-transfer-section" title="Transfer server"
helper="Move this server’s control-plane config to another Coolify instance (same physical host).">
<x-callout type="warning" title="Localhost cannot be transferred">
The Coolify host (localhost) cannot be transferred between instances.
</x-callout>
</x-application.settings-section>
@else
<x-application.settings-section id="server-transfer-section" title="Transfer server"
helper="Move this server’s control-plane config to another Coolify instance (same physical host).">
<x-slot:actions>
@php
$exportTooltip = $exportId ? "Export ID: {$exportId}" : null;
@endphp
@if (data_get($this->migration, 'status') === 'running')
<x-status-badge label="Transferring" type="warning" :data-tooltip="$exportTooltip" />
@elseif ($server->isTransferredAway())
<x-status-badge label="Transferred away" type="warning" :data-tooltip="$exportTooltip" />
@else
<x-status-badge label="Managed here" type="success" :data-tooltip="$exportTooltip" />
@endif
</x-slot:actions>
<div class="flex flex-col gap-4">
@if ($server->isTransferredAway())
<div>
<h3 class="text-sm font-semibold text-neutral-950 dark:text-fg">Transfer back</h3>
<p class="mt-1 text-xs leading-5 text-neutral-500 dark:text-fg-dim">
Undo the transfer. The instance that manages the server now transfers it back here,
with all changes made there. This archive is replaced only when the import here
succeeds. If the other instance is lost, use Enable management on the server page.
</p>
</div>
<div class="flex flex-col gap-3 md:max-w-xl">
<x-forms.input id="managerUrl" label="Instance that manages the server now" required
placeholder="https://coolify.example.com"
helper="The Coolify instance that this server was transferred to." />
<x-forms.input id="managerToken" type="password" label="API token of that instance" required
placeholder="Paste token from that instance" autocomplete="off"
helper="A token with root, or with read:sensitive and write, from an admin or owner of that instance." />
<x-forms.input id="thisInstanceUrl" label="URL of this instance" required
helper="The URL at which the other instance reaches this instance. This instance gives it a token that expires in 3 hours." />
</div>
<div>
<x-modal-confirmation title="Transfer this server back?" submitAction="transferBack"
:confirmWithText="false" :confirmWithPassword="false" step2ButtonText="Transfer back"
:actions="[
'The other instance checks the server, this instance, and the tokens. If a check fails, nothing changes.',
'The other instance transfers the server, its resources, and its credentials back here.',
'This archive is replaced by the transferred server, and the other instance keeps an archive.',
]">
<x-slot:trigger>
<x-forms.button canGate="update" :canResource="$server" wire:loading.attr="disabled"
wire:target="transferBack">
<span wire:loading.remove wire:target="transferBack">Transfer back</span>
<span wire:loading wire:target="transferBack">Running checks…</span>
</x-forms.button>
</x-slot:trigger>
</x-modal-confirmation>
</div>
@if ($transferBackAt = data_get($server->server_metadata, 'transfer.transfer_back.requested_at'))
<x-callout type="info" title="Transfer back started">
{{ data_get($server->server_metadata, 'transfer.transfer_back.from') }} started the transfer back at
{{ \Illuminate\Support\Carbon::parse($transferBackAt)->format('H:i') }}. Reload this page in a minute.
When the transfer finishes, this instance manages the server again. If it does not, read
the transfer log of the server on the other instance.
</x-callout>
@endif
@else
<div>
<h3 class="text-sm font-semibold text-neutral-950 dark:text-fg">Transfer to another instance
</h3>
<p class="mt-1 text-xs leading-5 text-neutral-500 dark:text-fg-dim">
Enter the target Coolify URL and an API token from that instance (root recommended).
This exports the server and imports it on the target, which then manages it. Management
is then disabled here.
</p>
</div>
<div class="flex flex-col gap-3 md:max-w-xl">
<x-forms.input id="targetUrl" label="Target instance URL" required
placeholder="https://coolify.example.com"
helper="Base URL of the other Coolify instance (no trailing path). It must use https." />
<x-forms.input id="targetToken" type="password" label="Target API token" required
placeholder="Paste token from target instance" autocomplete="off"
helper="Create a token on the target with root (or write + create servers). It is only used for this request." />
</div>
<div>
<x-modal-confirmation title="Transfer this server?" submitAction="migrateServer"
:confirmWithText="false" :confirmWithPassword="false" step2ButtonText="Transfer server"
:actions="[
'Coolify first checks this server, the target instance, and the token. If a check fails, nothing is changed.',
'The server will be transferred to the target instance.',
'Automations for this server will be disabled on this instance.',
]">
<x-slot:trigger>
<x-forms.button canGate="update" :canResource="$server" wire:loading.attr="disabled"
wire:target="migrateServer">
<span wire:loading.remove wire:target="migrateServer">Transfer server</span>
<span wire:loading wire:target="migrateServer">Running checks…</span>
</x-forms.button>
</x-slot:trigger>
</x-modal-confirmation>
</div>
@endif
@php $migration = $this->migration; @endphp
@if (data_get($migration, 'status') === 'running')
<div wire:poll.5s="refreshMigration">
<x-callout type="info" title="Transfer in progress">
The server is being transferred to {{ data_get($migration, 'target_url') }}. You can
leave this page; the transfer continues in the background.
</x-callout>
</div>
@elseif (data_get($migration, 'status') === 'failed')
<x-callout type="danger"
:title="data_get($migration, 'phase') === 'checks' ? 'A check failed. The transfer did not start.' : 'Transfer failed'">
@if (count((array) data_get($migration, 'log', [])) > 0)
See the transfer log below for details.
@else
{{ data_get($migration, 'error') }}
@endif
</x-callout>
@elseif (data_get($migration, 'status') === 'unknown')
<x-callout type="warning" title="Transfer result unknown">
The transfer stopped before this instance could confirm the result. Check whether
{{ data_get($migration, 'target_url') }} manages this server. If it does, call
<code>POST /api/v1/servers/{{ $server->uuid }}/transfer/complete</code> on this instance.
If it does not, transfer again.
</x-callout>
@elseif (data_get($migration, 'status') === 'succeeded')
<x-callout type="success" title="Transfer finished">
{{ data_get($migration, 'target_url') }} now manages this server. Automations are
disabled on this instance.
</x-callout>
@php $checklist = $this->postTransferChecklist; @endphp
@if (count($checklist) > 0 || data_get($migration, 'target_server_url'))
<div data-testid="post-transfer-checklist">
<h3 class="text-sm font-semibold text-neutral-950 dark:text-fg">Finish the transfer on the target</h3>
<p class="mt-1 text-xs leading-5 text-neutral-500 dark:text-fg-dim">
The target shows these steps on the server page, checks them where it can, and keeps
their state.
@if ($targetServerUrl = data_get($migration, 'target_server_url'))
<a href="{{ $targetServerUrl }}" target="_blank" rel="noopener noreferrer"
class="underline">Open the server on the target</a>.
@endif
</p>
@if (count($checklist) > 0)
<ul class="mt-2 list-disc space-y-1 pl-5 text-xs leading-5 text-neutral-600 dark:text-fg-dim">
@foreach ($checklist as $step)
<li wire:key="post-transfer-step-{{ hash('xxh128', $step) }}">{{ $step }}</li>
@endforeach
</ul>
@endif
</div>
@endif
@endif
@if (count((array) data_get($migration, 'log', [])) > 0)
<div>
<h3 class="text-sm font-semibold text-neutral-950 dark:text-fg">Transfer log</h3>
<ol class="mt-2 flex flex-col gap-1 rounded-lg border border-neutral-200 bg-neutral-50 p-3 font-mono text-xs dark:border-coolgray-300 dark:bg-coolgray-100"
data-testid="transfer-log">
@foreach ((array) data_get($migration, 'log', []) as $entry)
<li wire:key="transfer-log-{{ $loop->index }}-{{ data_get($entry, 'at') }}" @class([
'flex gap-3',
'text-success' => data_get($entry, 'level') === 'success',
'text-error' => data_get($entry, 'level') === 'error',
'text-warning' => data_get($entry, 'level') === 'warning',
'text-neutral-600 dark:text-fg-dim' => data_get($entry, 'level') === 'info',
])>
<span class="shrink-0 text-neutral-400">{{ \Illuminate\Support\Carbon::parse(data_get($entry, 'at'))->format('H:i:s') }}</span>
<span class="break-words">{{ data_get($entry, 'message') }}</span>
</li>
@endforeach
</ol>
</div>
@endif
@if (count($lastWarnings) > 0)
<x-callout type="warning" title="Warnings">
<ul class="mt-2 list-disc space-y-1 pl-5 text-sm">
@foreach ($lastWarnings as $warning)
<li>{{ $warning }}</li>
@endforeach
</ul>
</x-callout>
@endif
</div>
</x-application.settings-section>
@endif
</div>
</div>
</div>