wip: swarm

This commit is contained in:
Andras Bacsai 2023-12-15 15:48:01 +01:00
parent 967fca9eca
commit c6b8eabe10
10 changed files with 112 additions and 60 deletions

View File

@ -4,29 +4,32 @@ namespace App\Livewire\Destination\New;
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDocker as ModelsStandaloneDocker; use App\Models\StandaloneDocker as ModelsStandaloneDocker;
use App\Models\SwarmDocker;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
use Livewire\Component; use Livewire\Component;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
class StandaloneDocker extends Component class Docker extends Component
{ {
public string $name; public string $name;
public string $network; public string $network;
public Collection $servers; public Collection $servers;
public Server $server; public Server $server;
public int|null $server_id = null; public ?int $server_id = null;
public bool $is_swarm = false;
protected $rules = [ protected $rules = [
'name' => 'required|string', 'name' => 'required|string',
'network' => 'required|string', 'network' => 'required|string',
'server_id' => 'required|integer' 'server_id' => 'required|integer',
'is_swarm' => 'boolean'
]; ];
protected $validationAttributes = [ protected $validationAttributes = [
'name' => 'name', 'name' => 'name',
'network' => 'network', 'network' => 'network',
'server_id' => 'server' 'server_id' => 'server',
'is_swarm' => 'swarm'
]; ];
public function mount() public function mount()
@ -43,13 +46,13 @@ class StandaloneDocker extends Component
} else { } else {
$this->network = new Cuid2(7); $this->network = new Cuid2(7);
} }
$this->name = Str::kebab("{$this->servers->first()->name}-{$this->network}"); $this->name = str("{$this->servers->first()->name}-{$this->network}")->kebab();
} }
public function generate_name() public function generate_name()
{ {
$this->server = Server::find($this->server_id); $this->server = Server::find($this->server_id);
$this->name = Str::kebab("{$this->server->name}-{$this->network}"); $this->name = str("{$this->server->name}-{$this->network}")->kebab();
} }
public function submit() public function submit()
@ -57,17 +60,30 @@ class StandaloneDocker extends Component
$this->validate(); $this->validate();
try { try {
$this->server = Server::find($this->server_id); $this->server = Server::find($this->server_id);
$found = $this->server->standaloneDockers()->where('network', $this->network)->first(); if ($this->is_swarm) {
if ($found) { $found = $this->server->swarmDockers()->where('network', $this->network)->first();
$this->createNetworkAndAttachToProxy(); if ($found) {
$this->dispatch('error', 'Network already added to this server.'); $this->dispatch('error', 'Network already added to this server.');
return; return;
} else {
$docker = SwarmDocker::create([
'name' => $this->name,
'network' => $this->network,
'server_id' => $this->server_id,
]);
}
} else { } else {
$docker = ModelsStandaloneDocker::create([ $found = $this->server->standaloneDockers()->where('network', $this->network)->first();
'name' => $this->name, if ($found) {
'network' => $this->network, $this->dispatch('error', 'Network already added to this server.');
'server_id' => $this->server_id, return;
]); } else {
$docker = ModelsStandaloneDocker::create([
'name' => $this->name,
'network' => $this->network,
'server_id' => $this->server_id,
]);
}
} }
$this->createNetworkAndAttachToProxy(); $this->createNetworkAndAttachToProxy();
return $this->redirectRoute('destination.show', $docker->uuid, navigate: true); return $this->redirectRoute('destination.show', $docker->uuid, navigate: true);

View File

@ -13,7 +13,11 @@ class Show extends Component
public function scan() public function scan()
{ {
$alreadyAddedNetworks = $this->server->standaloneDockers; if ($this->server->isSwarm()) {
$alreadyAddedNetworks = $this->server->swarmDockers;
} else {
$alreadyAddedNetworks = $this->server->standaloneDockers;
}
$networks = instant_remote_process(['docker network ls --format "{{json .}}"'], $this->server, false); $networks = instant_remote_process(['docker network ls --format "{{json .}}"'], $this->server, false);
$this->networks = format_docker_command_output_to_json($networks)->filter(function ($network) { $this->networks = format_docker_command_output_to_json($networks)->filter(function ($network) {
return $network['Name'] !== 'bridge' && $network['Name'] !== 'host' && $network['Name'] !== 'none'; return $network['Name'] !== 'bridge' && $network['Name'] !== 'host' && $network['Name'] !== 'none';

View File

@ -6,13 +6,12 @@ use App\Models\Project;
use App\Models\Server; use App\Models\Server;
use Countable; use Countable;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Livewire\Component; use Livewire\Component;
class Select extends Component class Select extends Component
{ {
public $current_step = 'type'; public $current_step = 'type';
public ?int $server = null; public ?Server $server = null;
public string $type; public string $type;
public string $server_id; public string $server_id;
public string $destination_uuid; public string $destination_uuid;
@ -31,7 +30,7 @@ class Select extends Component
public ?string $search = null; public ?string $search = null;
protected $queryString = [ protected $queryString = [
'server', 'server_id',
'search' 'search'
]; ];
@ -111,7 +110,7 @@ class Select extends Component
$this->setServer($server); $this->setServer($server);
} }
if (!is_null($this->server)) { if (!is_null($this->server)) {
$foundServer = $this->servers->where('id', $this->server)->first(); $foundServer = $this->servers->where('id', $this->server->id)->first();
if ($foundServer) { if ($foundServer) {
return $this->setServer($foundServer); return $this->setServer($foundServer);
} }
@ -122,6 +121,7 @@ class Select extends Component
public function setServer(Server $server) public function setServer(Server $server)
{ {
$this->server_id = $server->id; $this->server_id = $server->id;
$this->server = $server;
$this->standaloneDockers = $server->standaloneDockers; $this->standaloneDockers = $server->standaloneDockers;
$this->swarmDockers = $server->swarmDockers; $this->swarmDockers = $server->swarmDockers;
$this->current_step = 'destinations'; $this->current_step = 'destinations';

View File

@ -15,10 +15,16 @@ function get_proxy_path()
} }
function connectProxyToNetworks(Server $server) function connectProxyToNetworks(Server $server)
{ {
// Standalone networks if ($server->isSwarm()) {
$networks = collect($server->standaloneDockers)->map(function ($docker) { $networks = collect($server->swarmDockers)->map(function ($docker) {
return $docker['network']; return $docker['network'];
}); });
} else {
// Standalone networks
$networks = collect($server->standaloneDockers)->map(function ($docker) {
return $docker['network'];
});
}
// Service networks // Service networks
foreach ($server->services()->get() as $service) { foreach ($server->services()->get() as $service) {
$networks->push($service->networks()); $networks->push($service->networks());
@ -41,16 +47,30 @@ function connectProxyToNetworks(Server $server)
$networks->push($network); $networks->push($network);
} }
$networks = collect($networks)->flatten()->unique(); $networks = collect($networks)->flatten()->unique();
if ($networks->count() === 0) { if ($server->isSwarm()) {
$networks = collect(['coolify']); if ($networks->count() === 0) {
$networks = collect(['coolify-overlay']);
}
$commands = $networks->map(function ($network) {
return [
"echo 'Connecting coolify-proxy to $network network...'",
"docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --driver overlay --attachable $network >/dev/null",
"docker network connect $network coolify-proxy >/dev/null 2>&1 || true",
];
});
} else {
if ($networks->count() === 0) {
$networks = collect(['coolify']);
}
$commands = $networks->map(function ($network) {
return [
"echo 'Connecting coolify-proxy to $network network...'",
"docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --attachable $network >/dev/null",
"docker network connect $network coolify-proxy >/dev/null 2>&1 || true",
];
});
} }
$commands = $networks->map(function ($network) {
return [
"echo 'Connecting coolify-proxy to $network network...'",
"docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null || docker network create --attachable $network >/dev/null",
"docker network connect $network coolify-proxy >/dev/null 2>&1 || true",
];
});
return $commands->flatten(); return $commands->flatten();
} }
function generate_default_proxy_configuration(Server $server) function generate_default_proxy_configuration(Server $server)

View File

@ -1,3 +1,3 @@
<x-layout> <x-layout>
<livewire:destination.new.standalone-docker :servers="$servers" :server_id="$server_id" /> <livewire:destination.new.docker :servers="$servers" :server_id="$server_id" />
</x-layout> </x-layout>

View File

@ -12,6 +12,7 @@
<option value="{{ $server->id }}">{{ $server->name }}</option> <option value="{{ $server->id }}">{{ $server->name }}</option>
@endforeach @endforeach
</x-forms.select> </x-forms.select>
<x-forms.checkbox type="checkbox" id="is_swarm" label="Is it a Swarm network?" />
<x-forms.button type="submit"> <x-forms.button type="submit">
Save Destination Save Destination
</x-forms.button> </x-forms.button>

View File

@ -11,7 +11,16 @@
<div class="flex gap-2 "> <div class="flex gap-2 ">
Available for using: Available for using:
@forelse ($server->standaloneDockers as $docker) @forelse ($server->standaloneDockers as $docker)
<a wire:navigate href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}"> <a wire:navigate
href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}">
<button class="text-white btn-link">{{ data_get($docker, 'network') }} </button>
</a>
@empty
<div class="">N/A</div>
@endforelse
@forelse ($server->swarmDockers as $docker)
<a wire:navigate
href="{{ route('destination.show', ['destination_uuid' => data_get($docker, 'uuid')]) }}">
<button class="text-white btn-link">{{ data_get($docker, 'network') }} </button> <button class="text-white btn-link">{{ data_get($docker, 'network') }} </button>
</a> </a>
@empty @empty

View File

@ -232,27 +232,29 @@
</ul> </ul>
<div class="flex flex-col justify-center gap-2 text-left xl:flex-row xl:flex-wrap"> <div class="flex flex-col justify-center gap-2 text-left xl:flex-row xl:flex-wrap">
@if ($server->isSwarm())
@foreach ($standaloneDockers as $standaloneDocker) @foreach ($swarmDockers as $swarmDocker)
<div class="box group" wire:click="setDestination('{{ $standaloneDocker->uuid }}')"> <div class="box group" wire:click="setDestination('{{ $swarmDocker->uuid }}')">
<div class="flex flex-col mx-6"> <div class="flex flex-col mx-6">
<div class="font-bold group-hover:text-white"> <div class="font-bold group-hover:text-white">
Standalone Docker <span class="text-xs">({{ $standaloneDocker->name }})</span> Swarm Docker <span class="text-xs">({{ $swarmDocker->name }})</span>
</div> </div>
<div class="text-xs group-hover:text-white">
network: {{ $standaloneDocker->network }}</div>
</div>
</div>
@endforeach
@foreach ($swarmDockers as $swarmDocker)
<div class="box group" wire:click="setDestination('{{ $swarmDocker->uuid }}')">
<div class="flex flex-col mx-6">
<div class="font-bold group-hover:text-white">
Swarm Docker <span class="text-xs">({{ $swarmDocker->name }})</span>
</div> </div>
</div> </div>
</div> @endforeach
@endforeach @else
@foreach ($standaloneDockers as $standaloneDocker)
<div class="box group" wire:click="setDestination('{{ $standaloneDocker->uuid }}')">
<div class="flex flex-col mx-6">
<div class="font-bold group-hover:text-white">
Standalone Docker <span class="text-xs">({{ $standaloneDocker->name }})</span>
</div>
<div class="text-xs group-hover:text-white">
network: {{ $standaloneDocker->network }}</div>
</div>
</div>
@endforeach
@endif
<a wire:navigate href="{{ route('destination.new', ['server_id' => $server_id]) }}" <a wire:navigate href="{{ route('destination.new', ['server_id' => $server_id]) }}"
class="items-center justify-center pb-10 text-center box-without-bg group bg-coollabs hover:bg-coollabs-100"> class="items-center justify-center pb-10 text-center box-without-bg group bg-coollabs hover:bg-coollabs-100">
<div class="flex flex-col mx-6 "> <div class="flex flex-col mx-6 ">

View File

@ -53,8 +53,8 @@
helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<span class='text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>" helper="If you are using Cloudflare Tunnels, enable this. It will proxy all ssh requests to your server through Cloudflare.<span class='text-warning'>Coolify does not install/setup Cloudflare (cloudflared) on your server.</span>"
id="server.settings.is_cloudflare_tunnel" label="Cloudflare Tunnel" /> id="server.settings.is_cloudflare_tunnel" label="Cloudflare Tunnel" />
@endif @endif
{{-- <x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_manager" <x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_manager"
label="Is it a Swarm Manager?" /> --}} label="Is it a Swarm Manager?" />
{{-- <x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_worker" {{-- <x-forms.checkbox instantSave type="checkbox" id="server.settings.is_swarm_worker"
label="Is it a Swarm Worker?" /> --}} label="Is it a Swarm Worker?" /> --}}
</div> </div>

View File

@ -25,10 +25,10 @@
@endif @endif
@endforeach @endforeach
</x-forms.select> </x-forms.select>
{{-- <div class="w-64"> <div class="w-64">
<x-forms.checkbox type="checkbox" id="is_swarm_manager" <x-forms.checkbox type="checkbox" id="is_swarm_manager"
label="Is it a Swarm Manager?" /> label="Is it a Swarm Manager?" />
</div> --}} </div>
<x-forms.button type="submit"> <x-forms.button type="submit">
Save New Server Save New Server
</x-forms.button> </x-forms.button>