This commit is contained in:
Andras Bacsai 2023-05-16 11:02:51 +02:00
parent 57c64d0b86
commit 752c86d8f7
16 changed files with 165 additions and 92 deletions

View File

@ -2,8 +2,6 @@
namespace App\Http\Livewire\Destination;
use App\Models\StandaloneDocker;
use App\Models\SwarmDocker;
use Livewire\Component;
class Form extends Component
@ -22,8 +20,18 @@ public function submit()
}
public function delete()
{
// instantRemoteProcess(['docker network rm -f ' . $this->destination->network], $this->destination->server);
$this->destination->delete();
return redirect()->route('dashboard');
try {
if ($this->destination->getMorphClass() === 'App\Models\StandaloneDocker') {
if ($this->destination->attachedTo()) {
return $this->emit('error', 'You must delete all resources before deleting this destination.');
}
instantRemoteProcess(["docker network disconnect {$this->destination->network} coolify-proxy"], $this->destination->server, throwError: false);
instantRemoteProcess(['docker network rm -f ' . $this->destination->network], $this->destination->server);
}
$this->destination->delete();
return redirect()->route('dashboard');
} catch (\Exception $e) {
return generalErrorHandler($e);
}
}
}

View File

@ -44,6 +44,10 @@ public function submit()
$this->addError('network', 'Network already added to this server.');
return;
}
$server = Server::find($this->server_id);
instantRemoteProcess(['docker network create --attachable ' . $this->network], $server, throwError: false);
instantRemoteProcess(["docker network connect $this->network coolify-proxy"], $server, throwError: false);
$docker = ModelsStandaloneDocker::create([
'name' => $this->name,
'network' => $this->network,
@ -51,9 +55,7 @@ public function submit()
'team_id' => session('currentTeam')->id
]);
$server = Server::find($this->server_id);
instantRemoteProcess(['docker network create --attachable ' . $this->network], $server, throwError: false);
return redirect()->route('destination.show', $docker->uuid);
}
}

View File

@ -20,7 +20,8 @@ class Form extends Component
'server.ip' => 'required',
'server.user' => 'required',
'server.port' => 'required',
'server.settings.is_validated' => 'required'
'server.settings.is_validated' => 'required',
'server.settings.is_part_of_swarm' => 'required'
];
public function mount()
{

View File

@ -19,24 +19,28 @@ class ByIp extends Component
public string $ip;
public string $user = 'root';
public int $port = 22;
public bool $is_part_of_swarm = false;
protected $rules = [
'name' => 'required',
'ip' => 'required',
'user' => 'required',
'port' => 'required|integer',
'is_part_of_swarm' => 'required|boolean',
];
public function mount()
{
$this->name = generateRandomName();
if ($this->private_keys->count() > 0) {
$this->private_key_id = $this->private_keys->first()->id;
}
$this->private_key_id = $this->private_keys->first()->id;
}
public function setPrivateKey(string $private_key_id)
{
$this->private_key_id = $private_key_id;
}
public function instantSave()
{
$this->emit('saved', 'Application settings updated!');
}
public function submit()
{
try {
@ -51,8 +55,10 @@ public function submit()
'user' => $this->user,
'port' => $this->port,
'team_id' => session('currentTeam')->id,
'private_key_id' => $this->private_key_id
'private_key_id' => $this->private_key_id,
]);
$server->settings->is_part_of_swarm = $this->is_part_of_swarm;
$server->settings->save();
return redirect()->route('server.show', $server->uuid);
} catch (\Exception $e) {
return generalErrorHandler($e);

View File

@ -13,8 +13,16 @@ public function applications()
{
return $this->morphMany(Application::class, 'destination');
}
public function databases()
{
return $this->morphMany(Database::class, 'destination');
}
public function server()
{
return $this->belongsTo(Server::class);
}
public function attachedTo()
{
return $this->applications->count() > 0 || $this->databases->count() > 0;
}
}

View File

@ -14,6 +14,8 @@ public function up(): void
Schema::create('server_settings', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->boolean('is_part_of_swarm')->default(false);
$table->boolean('is_jump_server')->default(false);
$table->boolean('is_build_server')->default(false);
$table->boolean('is_validated')->default(false);

View File

@ -26,7 +26,7 @@ public function run(): void
'team_id' => $root_team->id,
'private_key_id' => $private_key_1->id,
'extra_attributes' => ServerMetadata::from([
'proxy' => ProxyTypes::TRAEFIK_V2->value
'proxy_type' => ProxyTypes::TRAEFIK_V2->value
]),
]);
Server::create([

View File

@ -19,7 +19,7 @@ public function run(): void
$server_2->settings->save();
$server_3 = Server::find(2)->load(['settings']);
$server_3->settings->is_build_server = false;
$server_3->settings->is_part_of_swarm = true;
$server_3->settings->is_validated = false;
$server_3->settings->save();
}

View File

@ -7,8 +7,8 @@
<x-inputs.input id="destination.network" label="Docker Network" readonly />
@endif
<div>
<x-inputs.button>
Submit
<x-inputs.button isBold type="submit">
Save
</x-inputs.button>
<x-inputs.button isWarning x-on:click.prevent="deleteDestination = true">
Delete

View File

@ -4,10 +4,11 @@
<x-inputs.input id="network" label="Network" required />
<x-inputs.select id="server_id" label="Select a server" required>
@foreach ($servers as $server)
<option disabled>Select a server</option>
<option value="{{ $server->id }}">{{ $server->name }}</option>
@endforeach
</x-inputs.select>
<x-inputs.button type="submit">
<x-inputs.button isBold type="submit">
Submit
</x-inputs.button>
</form>

View File

@ -1,14 +1,16 @@
<div x-data="{ deletePrivateKey: false }">
<x-naked-modal show="deletePrivateKey" message='Are you sure you would like to delete this private key?' />
<form class="flex flex-col gap-2 w-96" wire:submit.prevent='changePrivateKey'>
<form class="flex flex-col gap-2" wire:submit.prevent='changePrivateKey'>
<x-inputs.input id="private_key.name" label="Name" required />
<x-inputs.input id="private_key.description" label="Description" />
<x-inputs.input type="textarea" id="private_key.private_key" label="Private Key" required />
<x-inputs.button type="submit">
Submit
</x-inputs.button>
<x-inputs.button isWarning x-on:click.prevent="deletePrivateKey = true">
Delete
</x-inputs.button>
<x-inputs.input type="textarea" rows="10" id="private_key.private_key" label="Private Key" required />
<div>
<x-inputs.button isBold type="submit">
Save
</x-inputs.button>
<x-inputs.button isWarning x-on:click.prevent="deletePrivateKey = true">
Delete
</x-inputs.button>
</div>
</form>
</div>

View File

@ -1,27 +1,12 @@
<div x-data="{ deleteServer: false }">
<x-naked-modal show="deleteServer" message='Are you sure you would like to delete this server?' />
<form wire:submit.prevent='submit' class="flex flex-col">
<div class="flex flex-col pb-4">
<div class="flex items-center gap-2">
<div class="text-3xl font-bold">Server</div>
<x-inputs.button isBold type="submit">Submit</x-inputs.button>
<x-inputs.button isWarning x-on:click.prevent="deleteServer = true">
Delete
</x-inputs.button>
</div>
<div>
@if ($server->settings->is_validated)
<div class="text-green-400/90">Validated</div>
@else
<div class="text-red-400/90">Not validated</div>
@endif
</div>
</div>
<div class="flex flex-col gap-2 xl:flex-row">
<div class="flex flex-col w-96">
<x-inputs.input id="server.name" label="Name" required />
<x-inputs.input id="server.description" label="Description" />
<x-inputs.input disabled type="checkbox" id="server.settings.is_part_of_swarm"
label="Is it part of a Swarm cluster?" />
</div>
<div class="flex flex-col w-96">
@if ($server->id === 0)
@ -35,19 +20,34 @@
@endif
</div>
</div>
<div class="flex gap-2">
<x-inputs.button isBold wire:click.prevent='validateServer'>Validate Server</x-inputs.button>
<x-inputs.button isBold wire:click.prevent='installDocker'>Install Docker</x-inputs.button>
<div class="flex items-center gap-2">
<x-inputs.button isBold type="submit">Save</x-inputs.button>
<x-inputs.button isBold wire:click.prevent='validateServer'>
@if ($server->settings->is_validated)
Check Connection
@else
Validate Server
@endif
</x-inputs.button>
{{-- <x-inputs.button isBold wire:click.prevent='installDocker'>Install Docker</x-inputs.button> --}}
<x-inputs.button isWarning x-on:click.prevent="deleteServer = true">
Delete
</x-inputs.button>
</div>
<div class="pt-3">
@isset($uptime)
<p>Connection: OK</p>
<p>Uptime: {{ $uptime }}</p>
@endisset
@isset($dockerVersion)
<p>Docker Engine {{ $dockerVersion }}</p>
@endisset
@isset($dockerComposeVersion)
<p>{{ $dockerComposeVersion }}</p>
@endisset
</div>
</form>
@isset($uptime)
<p>Uptime: {{ $uptime }}</p>
@endisset
@isset($dockerVersion)
<p>Docker Engine: {{ $dockerVersion }}</p>
@endisset
@isset($dockerComposeVersion)
<p>Docker Compose: {{ $dockerComposeVersion }}</p>
@endisset
</div>

View File

@ -7,7 +7,7 @@
<x-inputs.input id="user" label="User" />
<x-inputs.input type="number" id="port" label="Port" />
<label>Private Key</label>
<select wire:model.defer="private_key_id">
<x-inputs.select wire:model.defer="private_key_id">
<option disabled>Select a private key</option>
@foreach ($private_keys as $key)
@if ($loop->first)
@ -16,7 +16,9 @@
<option value="{{ $key->id }}">{{ $key->name }}</option>
@endif
@endforeach
</select>
</x-inputs.select>
<x-inputs.input instantSave noDirty type="checkbox" id="is_part_of_swarm"
label="Is it part of a Swarm cluster?" />
<x-inputs.button isBold type="submit">
Save
</x-inputs.button>

View File

@ -1,9 +1,8 @@
<div x-data="{ deleteSource: false }">
<x-naked-modal show="deleteSource" message='Are you sure you would like to delete this source?' />
<h3>Change Github App</h3>
<form wire:submit.prevent='submit'>
<x-inputs.input id="github_app.name" label="App Name" required />
<x-inputs.input noDirty type="checkbox" label="System Wide?" instantSave id="is_system_wide" />
@if ($github_app->app_id)
<x-inputs.input id="github_app.organization" label="Organization" disabled
placeholder="Personal user if empty" />
@ -14,19 +13,24 @@
<x-inputs.input id="github_app.html_url" label="HTML Url" disabled />
<x-inputs.input id="github_app.custom_user" label="User" required />
<x-inputs.input type="number" id="github_app.custom_port" label="Port" required />
@if ($github_app->app_id)
<x-inputs.input type="number" id="github_app.app_id" label="App Id" disabled />
<x-inputs.input type="number" id="github_app.installation_id" label="Installation Id" disabled />
<x-inputs.input id="github_app.client_id" label="Client Id" type="password" disabled />
<x-inputs.input id="github_app.client_secret" label="Client Secret" type="password" disabled />
<x-inputs.input id="github_app.webhook_secret" label="Webhook Secret" type="password" disabled />
<x-inputs.button type="submit">Save</x-inputs.button>
<x-inputs.button isWarning x-on:click.prevent="deleteSource = true">
Delete
</x-inputs.button>
@else
<x-inputs.input noDirty type="checkbox" label="System Wide?" instantSave id="is_system_wide" />
<div class="py-2">
<x-inputs.button type="submit">Save</x-inputs.button>
<x-inputs.button isBold type="submit">Save</x-inputs.button>
<x-inputs.button isWarning x-on:click.prevent="deleteSource = true">
Delete
</x-inputs.button>
</div>
@else
<x-inputs.input noDirty type="checkbox" label="System Wide?" instantSave id="is_system_wide" />
<div class="py-2">
<x-inputs.button isBold type="submit">Save</x-inputs.button>
<x-inputs.button isWarning x-on:click.prevent="deleteSource = true">
Delete
</x-inputs.button>

View File

@ -1,30 +1,67 @@
<x-layout>
<livewire:server.form :server_id="$server->id" />
<div class="flex items-center gap-2">
<h2>Private Key</h2>
<a href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}">
<x-inputs.button isBold>Change</x-inputs.button>
</a>
</div>
<p>{{ $server->privateKey->name }}</p>
<div class="flex items-center gap-2">
<h2>Destinations</h2>
<a href="{{ route('destination.new', ['server_id' => $server->id]) }}">
<x-inputs.button isBold>New</x-inputs.button>
</a>
</div>
@if ($server->standaloneDockers->count() > 0)
@foreach ($server->standaloneDockers as $docker)
<p>Network: {{ data_get($docker, 'network') }}</p>
@endforeach
@else
<p>No destinations found</p>
@endif
<div class="flex items-center gap-2">
<h2>Proxy</h2>
<div class="text-3xl font-bold">Server</div>
<div class="flex flex-col pb-4">
@if ($server->settings->is_validated)
<div>{{ $server->extra_attributes->proxy_status }}</div>
<div class="text-green-400">Validated</div>
@else
<div class="text-red-400">Not validated</div>
@endif
</div>
<livewire:server.proxy :server="$server" />
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }">
<div class="flex gap-4">
<a :class="activeTab === 'general' && 'text-purple-500'"
@click.prevent="activeTab = 'general'; window.location.hash = 'general'" href="#">General</a>
<a :class="activeTab === 'private-key' && 'text-purple-500'"
@click.prevent="activeTab = 'private-key'; window.location.hash = 'private-key'" href="#">Private
Key</a>
<a :class="activeTab === 'destinations' && 'text-purple-500'"
@click.prevent="activeTab = 'destinations'; window.location.hash = 'destinations'"
href="#">Destinations
</a>
<a :class="activeTab === 'proxy' && 'text-purple-500'"
@click.prevent="activeTab = 'proxy'; window.location.hash = 'proxy'" href="#">Proxy
</a>
</div>
<div x-cloak x-show="activeTab === 'general'">
<h3>General Configurations</h3>
<livewire:server.form :server_id="$server->id" />
</div>
<div x-cloak x-show="activeTab === 'private-key'">
<div class="flex items-center gap-2">
<h3>Private Keys</h3>
<a href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}">
<x-inputs.button>Change</x-inputs.button>
</a>
</div>
<p>{{ $server->privateKey->name }}</p>
</div>
<div x-cloak x-show="activeTab === 'destinations'">
<div class="flex items-center gap-2">
<h3>Destinations</h3>
<a href="{{ route('destination.new', ['server_id' => $server->id]) }}">
<x-inputs.button isBold>New</x-inputs.button>
</a>
</div>
@if ($server->standaloneDockers->count() > 0)
@foreach ($server->standaloneDockers as $docker)
<p>Network: {{ data_get($docker, 'network') }}</p>
@endforeach
@else
<p>No destinations found</p>
@endif
</div>
<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" />
</div>
</div>
</x-layout>

View File

@ -57,11 +57,11 @@ function createGithubApp() {
</script>
@elseif($github_app->app_id && !$github_app->installation_id)
<a href="{{ $installation_url }}">
<x-inputs.button>Install Repositories</x-inputs.button>
<x-inputs.button isBold>Install Repositories</x-inputs.button>
</a>
@elseif($github_app->app_id && $github_app->installation_id)
<a href="{{ $installation_url }}">
<x-inputs.button>Update Repositories</x-inputs.button>
<x-inputs.button isBold>Update Repositories</x-inputs.button>
</a>
@endif
</x-layout>