This commit is contained in:
Andras Bacsai 2023-05-16 11:39:18 +02:00
parent 752c86d8f7
commit a275ac5f41
11 changed files with 69 additions and 59 deletions

View File

@ -2,12 +2,15 @@
namespace App\Data; namespace App\Data;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes; use App\Enums\ProxyTypes;
use Spatie\LaravelData\Data; use Spatie\LaravelData\Data;
class ServerMetadata extends Data class ServerMetadata extends Data
{ {
public function __construct( public function __construct(
public ?ProxyTypes $proxy, public ?ProxyTypes $proxy_type,
) {} public ?ProxyStatus $proxy_status
) {
}
} }

View File

@ -8,3 +8,8 @@ enum ProxyTypes: string
case NGINX = 'NGINX'; case NGINX = 'NGINX';
case CADDY = 'CADDY'; case CADDY = 'CADDY';
} }
enum ProxyStatus: string
{
case EXITED = 'exited';
case RUNNING = 'running';
}

View File

@ -8,27 +8,26 @@ use Livewire\Component;
class Create extends Component class Create extends Component
{ {
protected string|null $from = null;
public string $name; public string $name;
public string|null $description = null; public string|null $description = null;
public string $value; public string $value;
public string $currentRoute;
public function mount()
{
$this->currentRoute = Route::current()->uri();
}
public function createPrivateKey() public function createPrivateKey()
{ {
$this->value = trim($this->value); $this->value = trim($this->value);
if (!str_ends_with($this->value, "\n")) { if (!str_ends_with($this->value, "\n")) {
$this->value .= "\n"; $this->value .= "\n";
} }
$new_private_key = PrivateKey::create([ $private_key = PrivateKey::create([
'name' => $this->name, 'name' => $this->name,
'description' => $this->description, 'description' => $this->description,
'private_key' => $this->value, 'private_key' => $this->value,
'team_id' => session('currentTeam')->id 'team_id' => session('currentTeam')->id
]); ]);
redirect()->route('server.new'); if ($this->from === 'server') {
return redirect()->route('server.new');
}
return redirect()->route('private-key.show', ['private_key_uuid' => $private_key->uuid]);
} }
} }

View File

@ -5,6 +5,7 @@ namespace App\Http\Livewire\Server;
use App\Models\PrivateKey as ModelsPrivateKey; use App\Models\PrivateKey as ModelsPrivateKey;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Storage;
use Livewire\Component; use Livewire\Component;
class PrivateKey extends Component class PrivateKey extends Component
@ -13,9 +14,13 @@ class PrivateKey extends Component
public $parameters; public $parameters;
public function setPrivateKey($private_key_id) public function setPrivateKey($private_key_id)
{ {
Server::where('uuid', $this->parameters['server_uuid'])->update([ $server = Server::where('uuid', $this->parameters['server_uuid']);
$server->update([
'private_key_id' => $private_key_id 'private_key_id' => $private_key_id
]); ]);
// Delete the old ssh mux file to force a new one to be created
Storage::disk('local')->delete(".ssh/ssh_mux_{$server->first()->ip}_{$server->first()->port}_{$server->first()->user}");
return redirect()->route('server.show', $this->parameters['server_uuid']); return redirect()->route('server.show', $this->parameters['server_uuid']);
} }
public function mount() public function mount()

View File

@ -17,13 +17,22 @@ class Proxy extends Component
public ProxyTypes $selectedProxy = ProxyTypes::TRAEFIK_V2; public ProxyTypes $selectedProxy = ProxyTypes::TRAEFIK_V2;
public $proxy_settings = null; public $proxy_settings = null;
public function mount()
{
$this->proxyStatus();
}
public function serverValidated() public function serverValidated()
{ {
$this->server->settings->refresh(); $this->server->settings->refresh();
} }
public function installProxy() public function installProxy()
{ {
$this->saveConfiguration($this->server); if (
$this->server->extra_attributes->last_applied_proxy_settings &&
$this->server->extra_attributes->last_saved_proxy_settings !== $this->server->extra_attributes->last_applied_proxy_settings
) {
$this->saveConfiguration($this->server);
}
$activity = resolve(InstallProxy::class)($this->server); $activity = resolve(InstallProxy::class)($this->server);
$this->emit('newMonitorActivity', $activity->id); $this->emit('newMonitorActivity', $activity->id);
} }
@ -32,6 +41,7 @@ class Proxy extends Component
{ {
$this->server->extra_attributes->proxy_status = checkContainerStatus(server: $this->server, container_id: 'coolify-proxy'); $this->server->extra_attributes->proxy_status = checkContainerStatus(server: $this->server, container_id: 'coolify-proxy');
$this->server->save(); $this->server->save();
$this->server->refresh();
} }
public function setProxy() public function setProxy()
{ {

View File

@ -95,7 +95,7 @@ if (!function_exists('savePrivateKeyForServer')) {
function savePrivateKeyForServer(Server $server) function savePrivateKeyForServer(Server $server)
{ {
$temp_file = "id.root@{$server->ip}"; $temp_file = "id.root@{$server->ip}";
Storage::disk('ssh-keys')->put($temp_file, $server->privateKey->private_key, 'private'); Storage::disk('ssh-keys')->put($temp_file, $server->privateKey->private_key);
return '/var/www/html/storage/app/ssh-keys/' . $temp_file; return '/var/www/html/storage/app/ssh-keys/' . $temp_file;
} }
} }
@ -103,9 +103,11 @@ if (!function_exists('savePrivateKeyForServer')) {
if (!function_exists('generateSshCommand')) { if (!function_exists('generateSshCommand')) {
function generateSshCommand(string $private_key_location, string $server_ip, string $user, string $port, string $command, bool $isMux = true) function generateSshCommand(string $private_key_location, string $server_ip, string $user, string $port, string $command, bool $isMux = true)
{ {
$delimiter = 'EOF-COOLIFY-SSH';
Storage::disk('local')->makeDirectory('.ssh'); Storage::disk('local')->makeDirectory('.ssh');
$delimiter = 'EOF-COOLIFY-SSH';
$ssh_command = "ssh "; $ssh_command = "ssh ";
if ($isMux && config('coolify.mux_enabled')) { if ($isMux && config('coolify.mux_enabled')) {
$ssh_command .= '-o ControlMaster=auto -o ControlPersist=1m -o ControlPath=/var/www/html/storage/app/.ssh/ssh_mux_%h_%p_%r '; $ssh_command .= '-o ControlMaster=auto -o ControlPersist=1m -o ControlPath=/var/www/html/storage/app/.ssh/ssh_mux_%h_%p_%r ';
} }
@ -159,7 +161,6 @@ if (!function_exists('instantRemoteProcess')) {
{ {
$command_string = implode("\n", $command); $command_string = implode("\n", $command);
$private_key_location = savePrivateKeyForServer($server); $private_key_location = savePrivateKeyForServer($server);
$ssh_command = generateSshCommand($private_key_location, $server->ip, $server->user, $server->port, $command_string); $ssh_command = generateSshCommand($private_key_location, $server->ip, $server->user, $server->port, $command_string);
$process = Process::run($ssh_command); $process = Process::run($ssh_command);
$output = trim($process->output()); $output = trim($process->output());

View File

@ -3,6 +3,7 @@
namespace Database\Seeders; namespace Database\Seeders;
use App\Data\ServerMetadata; use App\Data\ServerMetadata;
use App\Enums\ProxyStatus;
use App\Enums\ProxyTypes; use App\Enums\ProxyTypes;
use App\Models\PrivateKey; use App\Models\PrivateKey;
use App\Models\Server; use App\Models\Server;
@ -26,7 +27,8 @@ class ServerSeeder extends Seeder
'team_id' => $root_team->id, 'team_id' => $root_team->id,
'private_key_id' => $private_key_1->id, 'private_key_id' => $private_key_1->id,
'extra_attributes' => ServerMetadata::from([ 'extra_attributes' => ServerMetadata::from([
'proxy_type' => ProxyTypes::TRAEFIK_V2->value 'proxy_type' => ProxyTypes::TRAEFIK_V2->value,
'proxy_status' => ProxyStatus::EXITED->value
]), ]),
]); ]);
Server::create([ Server::create([

View File

@ -39,7 +39,6 @@
</div> </div>
<div class="pt-3"> <div class="pt-3">
@isset($uptime) @isset($uptime)
<p>Connection: OK</p>
<p>Uptime: {{ $uptime }}</p> <p>Uptime: {{ $uptime }}</p>
@endisset @endisset
@isset($dockerVersion) @isset($dockerVersion)

View File

@ -1,27 +1,25 @@
<div> <div>
@if ($server->settings->is_validated) @if ($server->settings->is_validated)
@if ($this->server->extra_attributes->proxy_status !== 'running') <div class="flex items-center gap-2">
<select wire:model="selectedProxy"> <h3>Proxy</h3>
<option value="{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }}"> <div>{{ $server->extra_attributes->proxy_status }}</div>
{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }} </div>
</option>
</select> @if ($server->extra_attributes->proxy_type)
<x-inputs.button isBold wire:click="setProxy">Set Proxy</x-inputs.button>
@endif
@if ($this->server->extra_attributes->proxy_type)
<div wire:poll="proxyStatus"> <div wire:poll="proxyStatus">
@if ( @if (
$this->server->extra_attributes->last_applied_proxy_settings && $server->extra_attributes->last_applied_proxy_settings &&
$this->server->extra_attributes->last_saved_proxy_settings !== $server->extra_attributes->last_saved_proxy_settings !== $server->extra_attributes->last_applied_proxy_settings)
$this->server->extra_attributes->last_applied_proxy_settings)
<div class="text-red-500">Configuration out of sync.</div> <div class="text-red-500">Configuration out of sync.</div>
@endif @endif
@if ($this->server->extra_attributes->proxy_status !== 'running') @if ($server->extra_attributes->proxy_status !== 'running')
<x-inputs.button isBold wire:click="installProxy"> <x-inputs.button isBold wire:click="installProxy">
Install Start
</x-inputs.button> </x-inputs.button>
@else
<x-inputs.button isWarning wire:click="stopProxy">Stop</x-inputs.button>
@endif @endif
<x-inputs.button isBold wire:click="stopProxy">Stop</x-inputs.button>
<span x-data="{ showConfiguration: false }"> <span x-data="{ showConfiguration: false }">
<x-inputs.button isBold x-on:click.prevent="showConfiguration = !showConfiguration">Show <x-inputs.button isBold x-on:click.prevent="showConfiguration = !showConfiguration">Show
Configuration Configuration
@ -35,16 +33,14 @@
<div wire:loading wire:target="checkProxySettingsInSync"> <div wire:loading wire:target="checkProxySettingsInSync">
<x-proxy.loading /> <x-proxy.loading />
</div> </div>
@isset($this->proxy_settings) @isset($proxy_settings)
<form wire:submit.prevent='saveConfiguration'> <form wire:submit.prevent='saveConfiguration'>
<x-inputs.button isBold>Save</x-inputs.button> <div class="pb-2">
<x-inputs.button x-on:click="showConfiguration = false" isBold <x-inputs.button isBold>Save</x-inputs.button>
wire:click.prevent="installProxy"> <x-inputs.button wire:click.prevent="resetProxy">
Apply Reset Configuration
</x-inputs.button> </x-inputs.button>
<x-inputs.button isBold wire:click.prevent="resetProxy"> </div>
Default
</x-inputs.button>
<textarea wire:model.defer="proxy_settings" class="w-full" rows="30"></textarea> <textarea wire:model.defer="proxy_settings" class="w-full" rows="30"></textarea>
</form> </form>
@endisset @endisset
@ -52,6 +48,13 @@
</template> </template>
</span> </span>
</div> </div>
@else
<select wire:model="selectedProxy">
<option value="{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }}">
{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }}
</option>
</select>
<x-inputs.button isBold wire:click="setProxy">Set Proxy</x-inputs.button>
@endif @endif
@else @else
<p>Server is not validated. Validate first.</p> <p>Server is not validated. Validate first.</p>

View File

@ -2,7 +2,7 @@
@if ($private_keys->count() === 0) @if ($private_keys->count() === 0)
<h2>Create private key</h2> <h2>Create private key</h2>
<div>You need to create a private key before you can create a server.</div> <div>You need to create a private key before you can create a server.</div>
<livewire:private-key.create /> <livewire:private-key.create from="server" />
@else @else
<livewire:server.new.by-ip :private_keys="$private_keys" /> <livewire:server.new.by-ip :private_keys="$private_keys" />
@endif @endif

View File

@ -1,12 +1,5 @@
<x-layout> <x-layout>
<div class="text-3xl font-bold">Server</div> <div class="text-3xl font-bold">Server</div>
<div class="flex flex-col pb-4">
@if ($server->settings->is_validated)
<div class="text-green-400">Validated</div>
@else
<div class="text-red-400">Not validated</div>
@endif
</div>
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }"> <div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }">
<div class="flex gap-4"> <div class="flex gap-4">
<a :class="activeTab === 'general' && 'text-purple-500'" <a :class="activeTab === 'general' && 'text-purple-500'"
@ -39,7 +32,7 @@
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h3>Destinations</h3> <h3>Destinations</h3>
<a href="{{ route('destination.new', ['server_id' => $server->id]) }}"> <a href="{{ route('destination.new', ['server_id' => $server->id]) }}">
<x-inputs.button isBold>New</x-inputs.button> <x-inputs.button>Add a new</x-inputs.button>
</a> </a>
</div> </div>
@if ($server->standaloneDockers->count() > 0) @if ($server->standaloneDockers->count() > 0)
@ -51,17 +44,7 @@
@endif @endif
</div> </div>
<div x-cloak x-show="activeTab === 'proxy'"> <div x-cloak x-show="activeTab === 'proxy'">
<div class="flex items-center gap-2">
<h3>Proxy</h3>
@if ($server->settings->is_validated)
<div>{{ $server->extra_attributes->proxy_status }}</div>
@endif
</div>
<livewire:server.proxy :server="$server" /> <livewire:server.proxy :server="$server" />
</div> </div>
</div> </div>
</x-layout> </x-layout>