fix dragonfly view

This commit is contained in:
Andras Bacsai
2024-11-04 14:22:42 +01:00
parent 7fb1a1fc75
commit ffb1e10248
2 changed files with 157 additions and 100 deletions

View File

@@ -7,60 +7,111 @@ use App\Actions\Database\StopDatabaseProxy;
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneDragonfly; use App\Models\StandaloneDragonfly;
use Exception; use Exception;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Rule;
use Livewire\Component; use Livewire\Component;
class General extends Component class General extends Component
{ {
protected $listeners = ['refresh'];
public Server $server; public Server $server;
public StandaloneDragonfly $database; public StandaloneDragonfly $database;
public ?string $db_url = null; #[Rule(['required', 'string'])]
public string $name;
public ?string $db_url_public = null; #[Rule(['nullable', 'string'])]
public ?string $description = null;
protected $rules = [ #[Rule(['required', 'string'])]
'database.name' => 'required', public string $dragonflyPassword;
'database.description' => 'nullable',
'database.dragonfly_password' => 'required',
'database.image' => 'required',
'database.ports_mappings' => 'nullable',
'database.is_public' => 'nullable|boolean',
'database.public_port' => 'nullable|integer',
'database.is_log_drain_enabled' => 'nullable|boolean',
'database.custom_docker_run_options' => 'nullable',
];
protected $validationAttributes = [ #[Rule(['required', 'string'])]
'database.name' => 'Name', public string $image;
'database.description' => 'Description',
'database.dragonfly_password' => 'Redis Password', #[Rule(['nullable', 'string'])]
'database.image' => 'Image', public ?string $portsMappings = null;
'database.ports_mappings' => 'Port Mapping',
'database.is_public' => 'Is Public', #[Rule(['nullable', 'boolean'])]
'database.public_port' => 'Public Port', public ?bool $isPublic = null;
'database.custom_docker_run_options' => 'Custom Docker Run Options',
]; #[Rule(['nullable', 'integer'])]
public ?int $publicPort = null;
#[Rule(['nullable', 'string'])]
public ?string $customDockerRunOptions = null;
#[Rule(['nullable', 'string'])]
public ?string $dbUrl = null;
#[Rule(['nullable', 'string'])]
public ?string $dbUrlPublic = null;
#[Rule(['nullable', 'boolean'])]
public bool $isLogDrainEnabled = false;
public function getListeners()
{
$teamId = Auth::user()->currentTeam()->id;
return [
"echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped',
];
}
public function mount() public function mount()
{ {
$this->db_url = $this->database->internal_db_url; try {
$this->db_url_public = $this->database->external_db_url; $this->syncData();
$this->server = data_get($this->database, 'destination.server'); $this->server = data_get($this->database, 'destination.server');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function syncData(bool $toModel = false)
{
if ($toModel) {
$this->validate();
$this->database->name = $this->name;
$this->database->description = $this->description;
$this->database->dragonfly_password = $this->dragonflyPassword;
$this->database->image = $this->image;
$this->database->ports_mappings = $this->portsMappings;
$this->database->is_public = $this->isPublic;
$this->database->public_port = $this->publicPort;
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
$this->database->save();
$this->dbUrl = $this->database->internal_db_url;
$this->dbUrlPublic = $this->database->external_db_url;
} else {
$this->name = $this->database->name;
$this->description = $this->database->description;
$this->dragonflyPassword = $this->database->dragonfly_password;
$this->image = $this->database->image;
$this->portsMappings = $this->database->ports_mappings;
$this->isPublic = $this->database->is_public;
$this->publicPort = $this->database->public_port;
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
$this->dbUrl = $this->database->internal_db_url;
$this->dbUrlPublic = $this->database->external_db_url;
}
} }
public function instantSaveAdvanced() public function instantSaveAdvanced()
{ {
try { try {
if (! $this->server->isLogDrainEnabled()) { if (! $this->server->isLogDrainEnabled()) {
$this->database->is_log_drain_enabled = false; $this->isLogDrainEnabled = false;
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
return; return;
} }
$this->database->save(); $this->syncData(true);
$this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'Database updated.');
$this->dispatch('success', 'You need to restart the service for the changes to take effect.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.');
} catch (Exception $e) { } catch (Exception $e) {
@@ -68,11 +119,50 @@ class General extends Component
} }
} }
public function instantSave()
{
try {
if ($this->isPublic && ! $this->publicPort) {
$this->dispatch('error', 'Public port is required.');
$this->isPublic = false;
return;
}
if ($this->isPublic) {
if (! str($this->database->status)->startsWith('running')) {
$this->dispatch('error', 'Database must be started to be publicly accessible.');
$this->isPublic = false;
return;
}
StartDatabaseProxy::run($this->database);
$this->dispatch('success', 'Database is now publicly accessible.');
} else {
StopDatabaseProxy::run($this->database);
$this->dispatch('success', 'Database is no longer publicly accessible.');
}
$this->dbUrlPublic = $this->database->external_db_url;
$this->syncData(true);
} catch (\Throwable $e) {
$this->isPublic = ! $this->isPublic;
$this->syncData(true);
return handleError($e, $this);
}
}
public function databaseProxyStopped()
{
$this->syncData();
}
public function submit() public function submit()
{ {
try { try {
$this->validate(); if (str($this->publicPort)->isEmpty()) {
$this->database->save(); $this->publicPort = null;
}
$this->syncData(true);
$this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'Database updated.');
} catch (Exception $e) { } catch (Exception $e) {
return handleError($e, $this); return handleError($e, $this);
@@ -84,45 +174,4 @@ class General extends Component
} }
} }
} }
public function instantSave()
{
try {
if ($this->database->is_public && ! $this->database->public_port) {
$this->dispatch('error', 'Public port is required.');
$this->database->is_public = false;
return;
}
if ($this->database->is_public) {
if (! str($this->database->status)->startsWith('running')) {
$this->dispatch('error', 'Database must be started to be publicly accessible.');
$this->database->is_public = false;
return;
}
StartDatabaseProxy::run($this->database);
$this->dispatch('success', 'Database is now publicly accessible.');
} else {
StopDatabaseProxy::run($this->database);
$this->dispatch('success', 'Database is no longer publicly accessible.');
}
$this->db_url_public = $this->database->external_db_url;
$this->database->save();
} catch (\Throwable $e) {
$this->database->is_public = ! $this->database->is_public;
return handleError($e, $this);
}
}
public function refresh(): void
{
$this->database->refresh();
}
public function render()
{
return view('livewire.project.database.dragonfly.general');
}
} }

View File

@@ -7,50 +7,58 @@
</x-forms.button> </x-forms.button>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input label="Name" id="database.name" /> <x-forms.input label="Name" id="name" />
<x-forms.input label="Description" id="database.description" /> <x-forms.input label="Description" id="description" />
<x-forms.input label="Image" id="database.image" required /> <x-forms.input label="Image" id="image" required />
</div> </div>
<x-forms.input <x-forms.input
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>" helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k" placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
id="database.custom_docker_run_options" label="Custom Docker Options" /> id="customDockerRunOptions" label="Custom Docker Options" />
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3> <h3 class="py-2">Network</h3>
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings" <x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" /> helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
</div> </div>
<x-forms.input label="Dragonfly URL (internal)" <x-forms.input label="Dragonfly URL (internal)"
helper="If you change the user/password/port, this could be different. This is with the default values." helper="If you change the user/password/port, this could be different. This is with the default values."
type="password" readonly wire:model="db_url" /> type="password" readonly wire:model="dbUrl" />
@if ($db_url_public)
@if ($dbUrlPublic)
<x-forms.input label="Dragonfly URL (public)" <x-forms.input label="Dragonfly URL (public)"
helper="If you change the user/password/port, this could be different. This is with the default values." helper="If you change the user/password/port, this could be different. This is with the default values."
type="password" readonly wire:model="db_url_public" /> type="password" readonly wire:model="dbUrlPublic" />
@else
<x-forms.input label="Dragonfly URL (public)"
helper="If you change the user/password/port, this could be different. This is with the default values."
readonly value="Starting the database will generate this." />
@endif @endif
</div> </div>
<div> <div>
<h3 class="py-2">Proxy</h3> <div class="flex flex-col py-2 w-64">
<div class="flex items-end gap-2"> <div class="flex items-center gap-2 pb-2">
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}" <h3>Proxy</h3>
id="database.public_port" label="Public Port" /> @if ($isPublic)
<x-slide-over fullScreen> <x-slide-over fullScreen>
<x-slot:title>Proxy Logs</x-slot:title> <x-slot:title>Proxy Logs</x-slot:title>
<x-slot:content> <x-slot:content>
<livewire:project.shared.get-logs :server="$server" :resource="$database" <livewire:project.shared.get-logs :server="$server" :resource="$database"
container="{{ data_get($database, 'uuid') }}-proxy" lazy /> container="{{ data_get($database, 'uuid') }}-proxy" lazy />
</x-slot:content> </x-slot:content>
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true" <x-forms.button disabled="{{ !$isPublic }}"
class="w-28">Proxy Logs</x-forms.button> @click="slideOverOpen=true">Logs</x-forms.button>
</x-slide-over> </x-slide-over>
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" /> @endif
</div>
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
</div> </div>
</div> <x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
<h3 class="pt-4">Advanced</h3>
<div class="flex flex-col">
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" />
</div> </div>
</form> </form>
<h3 class="pt-4">Advanced</h3>
<div class="flex flex-col">
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
</div>
</div> </div>