diff --git a/app/Livewire/Destination/Form.php b/app/Livewire/Destination/Form.php deleted file mode 100644 index a1a0a7b94..000000000 --- a/app/Livewire/Destination/Form.php +++ /dev/null @@ -1,46 +0,0 @@ - 'required', - 'destination.network' => 'required', - 'destination.server.ip' => 'required', - ]; - - protected $validationAttributes = [ - 'destination.name' => 'name', - 'destination.network' => 'network', - 'destination.server.ip' => 'IP Address/Domain', - ]; - - public function submit() - { - $this->validate(); - $this->destination->save(); - } - - public function delete() - { - try { - if ($this->destination->getMorphClass() === \App\Models\StandaloneDocker::class) { - if ($this->destination->attachedTo()) { - return $this->dispatch('error', 'You must delete all resources before deleting this destination.'); - } - instant_remote_process(["docker network disconnect {$this->destination->network} coolify-proxy"], $this->destination->server, throwError: false); - instant_remote_process(['docker network rm -f '.$this->destination->network], $this->destination->server); - } - $this->destination->delete(); - - return redirect()->route('destination.all'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } -} diff --git a/app/Livewire/Destination/Index.php b/app/Livewire/Destination/Index.php new file mode 100644 index 000000000..a3df3fd56 --- /dev/null +++ b/app/Livewire/Destination/Index.php @@ -0,0 +1,23 @@ +servers = Server::isUsable()->get(); + } + + public function render() + { + return view('livewire.destination.index'); + } +} diff --git a/app/Livewire/Destination/Show.php b/app/Livewire/Destination/Show.php index 37583a944..f69780479 100644 --- a/app/Livewire/Destination/Show.php +++ b/app/Livewire/Destination/Show.php @@ -3,73 +3,91 @@ namespace App\Livewire\Destination; use App\Models\Server; -use App\Models\StandaloneDocker; -use App\Models\SwarmDocker; -use Illuminate\Support\Collection; +use Livewire\Attributes\Locked; +use Livewire\Attributes\Rule; use Livewire\Component; class Show extends Component { - public Server $server; + #[Locked] + public $destination; - public Collection|array $networks = []; + #[Rule(['string', 'required'])] + public string $name; - private function createNetworkAndAttachToProxy() + #[Rule(['string', 'required'])] + public string $network; + + #[Rule(['string', 'required'])] + public string $serverIp; + + public function mount(string $destination_uuid) { - $connectProxyToDockerNetworks = connectProxyToNetworks($this->server); - instant_remote_process($connectProxyToDockerNetworks, $this->server, false); - } + try { + $destination = Server::isUsable()->whereHas('standaloneDockers', function ($query) use ($destination_uuid) { + $query->where('uuid', $destination_uuid); + })->first()->standaloneDockers()->where('uuid', $destination_uuid)->first(); - public function add($name) - { - if ($this->server->isSwarm()) { - $found = $this->server->swarmDockers()->where('network', $name)->first(); - if ($found) { - $this->dispatch('error', 'Network already added to this server.'); - - return; - } else { - SwarmDocker::create([ - 'name' => $this->server->name.'-'.$name, - 'network' => $this->name, - 'server_id' => $this->server->id, - ]); + if (! $destination) { + $destination = Server::isUsable()->whereHas('swarmDockers', function ($query) use ($destination_uuid) { + $query->where('uuid', $destination_uuid); + })->first()->swarmDockers()->where('uuid', $destination_uuid)->first(); } - } else { - $found = $this->server->standaloneDockers()->where('network', $name)->first(); - if ($found) { - $this->dispatch('error', 'Network already added to this server.'); - - return; - } else { - StandaloneDocker::create([ - 'name' => $this->server->name.'-'.$name, - 'network' => $name, - 'server_id' => $this->server->id, - ]); + if (! $destination) { + throw new \Exception('Destination not found'); } - $this->createNetworkAndAttachToProxy(); + $this->destination = $destination; + $this->syncData(); + } catch (\Throwable $e) { + return handleError($e, $this); } } - public function scan() + public function syncData(bool $toModel = false) { - if ($this->server->isSwarm()) { - $alreadyAddedNetworks = $this->server->swarmDockers; + if ($toModel) { + $this->validate(); + $this->destination->name = $this->name; + $this->destination->network = $this->network; + $this->destination->server->ip = $this->serverIp; + $this->destination->save(); } else { - $alreadyAddedNetworks = $this->server->standaloneDockers; + $this->name = $this->destination->name; + $this->network = $this->destination->network; + $this->serverIp = $this->destination->server->ip; } - $networks = instant_remote_process(['docker network ls --format "{{json .}}"'], $this->server, false); - $this->networks = format_docker_command_output_to_json($networks)->filter(function ($network) { - return $network['Name'] !== 'bridge' && $network['Name'] !== 'host' && $network['Name'] !== 'none'; - })->filter(function ($network) use ($alreadyAddedNetworks) { - return ! $alreadyAddedNetworks->contains('network', $network['Name']); - }); - if ($this->networks->count() === 0) { - $this->dispatch('success', 'No new destinations found on this server.'); + } - return; + public function submit() + { + try { + $this->syncData(true); + $this->dispatch('success', 'Destination saved.'); + } catch (\Throwable $e) { + return handleError($e, $this); } - $this->dispatch('success', 'Scan done.'); + } + + public function delete() + { + try { + if ($this->destination->getMorphClass() === \App\Models\StandaloneDocker::class) { + if ($this->destination->attachedTo()) { + return $this->dispatch('error', 'You must delete all resources before deleting this destination.'); + } + instant_remote_process(["docker network disconnect {$this->destination->network} coolify-proxy"], $this->destination->server, throwError: false); + instant_remote_process(['docker network rm -f '.$this->destination->network], $this->destination->server); + } + $this->destination->delete(); + + return redirect()->route('destination.index'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function render() + { + return view('livewire.destination.show'); } } diff --git a/app/Livewire/Server/Destination/Show.php b/app/Livewire/Server/Destinations.php similarity index 95% rename from app/Livewire/Server/Destination/Show.php rename to app/Livewire/Server/Destinations.php index 71c051a74..c10958bd1 100644 --- a/app/Livewire/Server/Destination/Show.php +++ b/app/Livewire/Server/Destinations.php @@ -1,6 +1,6 @@ + href="{{ route('destination.index') }}" wire:navigate> - - Destinations | Coolify - -
-

Destinations

- @if ($servers->count() > 0) - - - - @endif -
-
Network endpoints to deploy your resources.
-
- @forelse ($destinations as $destination) - @if ($destination->getMorphClass() === 'App\Models\StandaloneDocker') - -
-
{{ $destination->name }}
-
server: {{ $destination->server->name }}
-
-
- @endif - @if ($destination->getMorphClass() === 'App\Models\SwarmDocker') - -
-
{{ $destination->name }}
-
server: {{ $destination->server->name }}
-
-
- @endif - @empty -
- @if ($servers->count() === 0) -
No servers found. Please add one first.
- @else -
No destinations found.
- @endif -
- @endforelse -
- diff --git a/resources/views/destination/show.blade.php b/resources/views/destination/show.blade.php deleted file mode 100644 index ce87114a3..000000000 --- a/resources/views/destination/show.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/resources/views/livewire/destination/form.blade.php b/resources/views/livewire/destination/form.blade.php deleted file mode 100644 index 0b9097f2d..000000000 --- a/resources/views/livewire/destination/form.blade.php +++ /dev/null @@ -1,29 +0,0 @@ -
-
-
-

Destination

- - Save - - @if ($destination->network !== 'coolify') - - @endif -
- - @if ($destination->getMorphClass() === 'App\Models\StandaloneDocker') -
A Docker network in a non-swarm environment.
- @else -
Your swarm docker network. WIP
- @endif -
- - - @if ($destination->getMorphClass() === 'App\Models\StandaloneDocker') - - @endif -
-
-
diff --git a/resources/views/livewire/destination/index.blade.php b/resources/views/livewire/destination/index.blade.php new file mode 100644 index 000000000..df64e953e --- /dev/null +++ b/resources/views/livewire/destination/index.blade.php @@ -0,0 +1,44 @@ +
+ + Destinations | Coolify + +
+

Destinations

+ @if ($servers->count() > 0) + + + + @endif +
+
Network endpoints to deploy your resources.
+
+ @forelse ($servers as $server) + @forelse ($server->destinations() as $destination) + @if ($destination->getMorphClass() === 'App\Models\StandaloneDocker') + +
+
{{ $destination->name }}
+
Server: {{ $destination->server->name }}
+
+
+ @endif + @if ($destination->getMorphClass() === 'App\Models\SwarmDocker') + +
+
{{ $destination->name }}
+
server: {{ $destination->server->name }}
+
+
+ @endif + @empty +
No destinations found.
+ @endforelse + @empty +
No servers found.
+ @endforelse +
+
diff --git a/resources/views/livewire/destination/show.blade.php b/resources/views/livewire/destination/show.blade.php index be36899b6..014e612eb 100644 --- a/resources/views/livewire/destination/show.blade.php +++ b/resources/views/livewire/destination/show.blade.php @@ -1,42 +1,29 @@
- @if ($server->isFunctional()) -
-

Destinations

- - - - Scan for Destinations -
-
Destinations are used to segregate resources by network.
-
- Available for using: - @forelse ($server->standaloneDockers as $docker) - - - - @empty - @endforelse - @forelse ($server->swarmDockers as $docker) - - - - @empty - @endforelse -
-
- @if (count($networks) > 0) -

Found Destinations

+
+
+

Destination

+ + Save + + @if ($network !== 'coolify') + @endif -
- @foreach ($networks as $network) -
- Add - {{ data_get($network, 'Name') }} -
- @endforeach -
- @else -
Server is not validated. Validate first.
- @endif + + @if ($destination->getMorphClass() === 'App\Models\StandaloneDocker') +
A Docker network in a non-swarm environment.
+ @else +
Your swarm docker network. WIP
+ @endif +
+ + + @if ($destination->getMorphClass() === 'App\Models\StandaloneDocker') + + @endif +
+
diff --git a/resources/views/livewire/server/destinations.blade.php b/resources/views/livewire/server/destinations.blade.php new file mode 100644 index 000000000..88503f62d --- /dev/null +++ b/resources/views/livewire/server/destinations.blade.php @@ -0,0 +1,49 @@ +
+ + {{ data_get_str($server, 'name')->limit(10) }} > Destinations | Coolify + + +
+ +
+ @if ($server->isFunctional()) +
+

Destinations

+ + + + Scan for Destinations +
+
Destinations are used to segregate resources by network.
+

Available Destinations

+
+ @foreach ($server->standaloneDockers as $docker) + + {{ data_get($docker, 'network') }} + + @endforeach + @foreach ($server->swarmDockers as $docker) + + {{ data_get($docker, 'network') }} + + @endforeach +
+ @if ($networks->count() > 0) +
+

Found Destinations

+
+ @foreach ($networks as $network) +
+ Add + {{ data_get($network, 'Name') }} +
+ @endforeach +
+
+ @endif + @else +
Server is not validated. Validate first.
+ @endif +
+
+
diff --git a/routes/web.php b/routes/web.php index f619b8205..ae2ce244c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -7,6 +7,8 @@ use App\Http\Controllers\UploadController; use App\Livewire\Admin\Index as AdminIndex; use App\Livewire\Boarding\Index as BoardingIndex; use App\Livewire\Dashboard; +use App\Livewire\Destination\Index as DestinationIndex; +use App\Livewire\Destination\Show as DestinationShow; use App\Livewire\Dev\Compose as Compose; use App\Livewire\ForcePasswordReset; use App\Livewire\Notifications\Discord as NotificationDiscord; @@ -38,7 +40,7 @@ use App\Livewire\Server\Advanced as ServerAdvanced; use App\Livewire\Server\Charts as ServerCharts; use App\Livewire\Server\CloudflareTunnels; use App\Livewire\Server\Delete as DeleteServer; -use App\Livewire\Server\Destination\Show as DestinationShow; +use App\Livewire\Server\Destinations as ServerDestinations; use App\Livewire\Server\Index as ServerIndex; use App\Livewire\Server\LogDrains; use App\Livewire\Server\PrivateKey\Show as PrivateKeyShow; @@ -72,8 +74,6 @@ use App\Livewire\Terminal\Index as TerminalIndex; use App\Models\GitlabApp; use App\Models\ScheduledDatabaseBackupExecution; use App\Models\Server; -use App\Models\StandaloneDocker; -use App\Models\SwarmDocker; use App\Providers\RouteServiceProvider; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; @@ -212,7 +212,7 @@ Route::middleware(['auth', 'verified'])->group(function () { Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key'); Route::get('/resources', ResourcesShow::class)->name('server.resources'); Route::get('/cloudflare-tunnels', CloudflareTunnels::class)->name('server.cloudflare-tunnels'); - Route::get('/destinations', DestinationShow::class)->name('server.destinations'); + Route::get('/destinations', ServerDestinations::class)->name('server.destinations'); Route::get('/log-drains', LogDrains::class)->name('server.log-drains'); Route::get('/metrics', ServerCharts::class)->name('server.charts'); Route::get('/danger', DeleteServer::class)->name('server.delete'); @@ -312,52 +312,8 @@ Route::middleware(['auth'])->group(function () { return response()->json(['message' => $e->getMessage()], 500); } })->name('download.backup'); - Route::get('/destinations', function () { - $servers = Server::isUsable()->get(); - $destinations = collect([]); - foreach ($servers as $server) { - $destinations = $destinations->merge($server->destinations()); - } - $pre_selected_server_uuid = data_get(request()->query(), 'server'); - if ($pre_selected_server_uuid) { - $server = $servers->firstWhere('uuid', $pre_selected_server_uuid); - if ($server) { - $server_id = $server->id; - } - } - - return view('destination.all', [ - 'destinations' => $destinations, - 'servers' => $servers, - 'server_id' => $server_id ?? null, - ]); - })->name('destination.all'); - // Route::get('/destination/new', function () { - // $servers = Server::isUsable()->get(); - // $pre_selected_server_uuid = data_get(request()->query(), 'server'); - // if ($pre_selected_server_uuid) { - // $server = $servers->firstWhere('uuid', $pre_selected_server_uuid); - // if ($server) { - // $server_id = $server->id; - // } - // } - // return view('destination.new', [ - // "servers" => $servers, - // "server_id" => $server_id ?? null, - // ]); - // })->name('destination.new'); - Route::get('/destination/{destination_uuid}', function () { - $standalone_dockers = StandaloneDocker::where('uuid', request()->destination_uuid)->first(); - $swarm_dockers = SwarmDocker::where('uuid', request()->destination_uuid)->first(); - if (! $standalone_dockers && ! $swarm_dockers) { - abort(404); - } - $destination = $standalone_dockers ? $standalone_dockers : $swarm_dockers; - - return view('destination.show', [ - 'destination' => $destination->load(['server']), - ]); - })->name('destination.show'); + Route::get('/destinations', DestinationIndex::class)->name('destination.index'); + Route::get('/destination/{destination_uuid}', DestinationShow::class)->name('destination.show'); }); Route::any('/{any}', function () {