fix: services file/dir read from server

ui: fix storages layout
This commit is contained in:
Andras Bacsai 2023-10-04 09:58:39 +02:00
parent 1a5e3a7836
commit 4ac8e1cc67
14 changed files with 165 additions and 130 deletions

View File

@ -29,7 +29,10 @@ public function mount()
$this->parameters = get_route_parameters();
$this->query = request()->query();
$this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail();
$this->refreshStack();
$this->applications = $this->service->applications->sort();
$this->databases = $this->service->databases->sort();
ray($this->applications);
ray($this->databases);
}
public function saveCompose($raw)
{

View File

@ -0,0 +1,35 @@
<?php
namespace App\Http\Livewire\Project\Service;
use App\Models\LocalPersistentVolume;
use Livewire\Component;
class Storage extends Component
{
protected $listeners = ['addNewVolume'];
public $resource;
public function render()
{
return view('livewire.project.service.storage');
}
public function addNewVolume($data)
{
try {
LocalPersistentVolume::create([
'name' => $data['name'],
'mount_path' => $data['mount_path'],
'host_path' => $data['host_path'],
'resource_id' => $this->resource->id,
'resource_type' => $this->resource->getMorphClass(),
]);
$this->resource->refresh();
$this->emit('success', 'Storage added successfully');
$this->emit('clearAddStorage');
$this->emit('refreshStorages');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
}

View File

@ -33,7 +33,7 @@ public function submit()
{
$this->validate();
$name = $this->uuid . '-' . $this->name;
$this->emitUp('submit', [
$this->emit('addNewVolume', [
'name' => $name,
'mount_path' => $this->mount_path,
'host_path' => $this->host_path,

View File

@ -7,30 +7,11 @@
class All extends Component
{
public bool $isHeaderVisible = true;
public $resource;
protected $listeners = ['refreshStorages', 'submit'];
protected $listeners = ['refreshStorages'];
public function refreshStorages()
{
$this->resource->refresh();
}
public function submit($data)
{
try {
LocalPersistentVolume::create([
'name' => $data['name'],
'mount_path' => $data['mount_path'],
'host_path' => $data['host_path'],
'resource_id' => $this->resource->id,
'resource_type' => $this->resource->getMorphClass(),
]);
$this->resource->refresh();
$this->emit('success', 'Storage added successfully');
$this->emit('clearAddStorage');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
}

View File

@ -44,6 +44,10 @@ public function persistentStorages()
{
return $this->morphMany(LocalPersistentVolume::class, 'resource');
}
public function fileStorages()
{
return $this->morphMany(LocalFileVolume::class, 'resource');
}
public function type()
{

View File

@ -31,23 +31,18 @@ public function saveStorageOnServer(ServiceApplication|ServiceDatabase $service)
}
$isFile = instant_remote_process(["test -f $path && echo OK || echo NOK"], $server);
$isDir = instant_remote_process(["test -d $path && echo OK || echo NOK"], $server);
ray($isFile);
if ($isFile == 'OK' && $fileVolume->is_directory) {
throw new \Exception("File $path is a file on the server, but you are trying to mark it as a directory. Please delete the file on the server or mark it as directory.");
} else if ($isDir == 'OK' && !$fileVolume->is_directory) {
throw new \Exception("File $path is a directory on the server, but you are trying to mark it as a file. Please delete the directory on the server or mark it as directory.");
}
if (($isFile == 'NOK' && !$fileVolume->is_directory) || $isFile == 'OK') {
$rootDir = Str::of($path)->dirname();
$commands->push("mkdir -p $rootDir > /dev/null 2>&1 || true");
$commands->push("touch $path > /dev/null 2>&1 || true");
if ($content) {
$content = base64_encode($content);
$commands->push("echo '$content' | base64 -d > $path");
}
} else if ($isDir == 'NOK' && $fileVolume->is_directory) {
if (!$fileVolume->is_directory && $isDir == 'NOK') {
$content = base64_encode($content);
$commands->push("echo '$content' | base64 -d > $path");
} else if ($isDir == 'NOK' && $fileVolume->is_directory) {
$commands->push("mkdir -p $path > /dev/null 2>&1 || true");
}
ray($commands->toArray());
return instant_remote_process($commands, $server);
}
}

View File

@ -76,6 +76,11 @@ public function environment()
return $this->belongsTo(Environment::class);
}
public function fileStorages()
{
return $this->morphMany(LocalFileVolume::class, 'resource');
}
public function destination()
{
return $this->morphTo();

View File

@ -85,28 +85,39 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase $oneS
} else {
$fileLocation = $path;
}
ray($path,$fileLocation);
// Exists and is a file
$isFile = instant_remote_process(["test -f $fileLocation && echo OK || echo NOK"], $server);
// Exists and is a directory
$isDir = instant_remote_process(["test -d $fileLocation && echo OK || echo NOK"], $server);
if ($isFile === 'NOK' &&!$fileVolume->is_directory && $isInit) {
$fileVolume->saveStorageOnServer($oneService);
continue;
}
if ($isFile == 'OK' && !$fileVolume->is_directory) {
if ($isFile == 'OK') {
// If its a file & exists
$filesystemContent = instant_remote_process(["cat $fileLocation"], $server);
if (base64_encode($filesystemContent) != base64_encode($content)) {
$fileVolume->content = $filesystemContent;
$fileVolume->save();
}
} else {
if ($isDir == 'OK') {
$fileVolume->content = null;
$fileVolume->is_directory = true;
$fileVolume->save();
} else {
$fileVolume->content = null;
$fileVolume->is_directory = false;
$fileVolume->save();
}
$fileVolume->content = $filesystemContent;
$fileVolume->is_directory = false;
$fileVolume->save();
} else if ($isDir == 'OK') {
// If its a directory & exists
$fileVolume->content = null;
$fileVolume->is_directory = true;
$fileVolume->save();
} else if ($isFile == 'NOK' && $isDir == 'NOK' && !$fileVolume->is_directory && $isInit && $content) {
// Does not exists (no dir or file), not flagged as directory, is init, has content
$fileVolume->content = $content;
$fileVolume->is_directory = false;
$fileVolume->save();
$content = base64_encode($content);
$dir = Str::of($fileLocation)->dirname();
instant_remote_process([
"mkdir -p $dir",
"echo '$content' | base64 -d > $fileLocation"
], $server);
} else if ($isFile == 'NOK' && $isDir == 'NOK' && $fileVolume->is_directory && $isInit) {
$fileVolume->content = null;
$fileVolume->is_directory = true;
$fileVolume->save();
instant_remote_process(["mkdir -p $fileLocation"], $server);
}
}
} catch (\Throwable $e) {

View File

@ -1,4 +1,4 @@
<div x-data="{ raw: true, activeTab: window.location.hash ? window.location.hash.substring(1) : 'service-stack' }" wire:poll.10000ms="checkStatus">
<div x-data="{ raw: true, activeTab: window.location.hash ? window.location.hash.substring(1) : 'service-stack' }" wire:poll.2000ms="checkStatus">
<livewire:project.service.navbar :service="$service" :parameters="$parameters" :query="$query" />
<livewire:project.service.compose-modal :raw="$service->docker_compose_raw" :actual="$service->docker_compose" />
<div class="flex h-full pt-6">
@ -102,42 +102,18 @@
</div>
<div x-cloak x-show="activeTab === 'storages'">
<div class="flex items-center gap-2">
<h2>Storages</h2>
</div>
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
<span class="text-warning">Please modify storage layout in your <a class="underline"
href="{{ Str::of(url()->current())->beforeLast('/') }}">Docker Compose</a> file.</span>
@foreach ($applications as $application)
@if ($loop->first)
<livewire:project.shared.storages.all :resource="$application" />
@else
<livewire:project.shared.storages.all :resource="$application" :isHeaderVisible="false" />
@endif
@if ($application->fileStorages()->get()->count() > 0)
<h5 class="py-4">Mounted Files/Dirs (binds)</h5>
<div class="flex flex-col gap-4">
@foreach ($application->fileStorages()->get()->sort() as $fileStorage)
<livewire:project.service.file-storage :fileStorage="$fileStorage"
wire:key="{{ $loop->index }}" />
@endforeach
</div>
@endif
<livewire:project.service.storage wire:key="application-{{ $application->id }}"
:resource="$application" />
@endforeach
@foreach ($databases as $database)
@if ($loop->first)
<h3 class="pt-4">{{ Str::headline($database->name) }}</h3>
@if ($applications->count() > 0)
<livewire:project.shared.storages.all :resource="$database" :isHeaderVisible="false" />
@else
<livewire:project.shared.storages.all :resource="$database" />
@endif
@if ($database->fileStorages()->get()->count() > 0)
<h5 class="py-4">Mounted Files/Dirs (binds)</h5>
<div class="flex flex-col gap-4">
@foreach ($database->fileStorages()->get()->sort() as $fileStorage)
<livewire:project.service.file-storage :fileStorage="$fileStorage"
wire:key="{{ $loop->index }}" />
@endforeach
</div>
@endif
@else
<livewire:project.shared.storages.all :resource="$database" :isHeaderVisible="false" />
@endif
<livewire:project.service.storage wire:key="database-{{ $database->id }}" :resource="$database" />
@endforeach
</div>

View File

@ -24,15 +24,14 @@
<livewire:project.service.application :application="$serviceApplication" />
</div>
<div x-cloak x-show="activeTab === 'storages'">
<livewire:project.shared.storages.all :resource="$serviceApplication" />
@if ($serviceApplication->fileStorages()->get()->count() > 0)
<h5 class="py-4">Mounted Files/Dirs (binds)</h5>
<div class="flex flex-col gap-4">
@foreach ($serviceApplication->fileStorages()->get()->sort() as $fileStorage)
<livewire:project.service.file-storage :fileStorage="$fileStorage" wire:key="{{ $loop->index }}" />
@endforeach
</div>
@endif
<div class="flex items-center gap-2">
<h2>Storages</h2>
</div>
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
<span class="text-warning">Please modify storage layout in your <a class="underline"
href="{{ Str::of(url()->current())->beforeLast('/') }}">Docker Compose</a> file.</span>
<livewire:project.service.storage wire:key="application-{{ $serviceApplication->id }}"
:resource="$serviceApplication" />
</div>
@endisset
@isset($serviceDatabase)
@ -40,15 +39,14 @@
<livewire:project.service.database :database="$serviceDatabase" />
</div>
<div x-cloak x-show="activeTab === 'storages'">
<livewire:project.shared.storages.all :resource="$serviceDatabase" />
@if ($serviceDatabase->fileStorages()->get()->count() > 0)
<h5 class="py-4">Mounted Files/Dirs (binds)</h5>
<div class="flex flex-col gap-4">
@foreach ($serviceDatabase->fileStorages()->get()->sort() as $fileStorage)
<livewire:project.service.file-storage :fileStorage="$fileStorage" wire:key="{{ $loop->index }}" />
@endforeach
</div>
@endif
<div class="flex items-center gap-2">
<h2>Storages</h2>
</div>
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
<span class="text-warning">Please modify storage layout in your <a class="underline"
href="{{ Str::of(url()->current())->beforeLast('/') }}">Docker Compose</a> file.</span>
<livewire:project.service.storage wire:key="application-{{ $serviceDatabase->id }}"
:resource="$serviceDatabase" />
</div>
@endisset
</div>

View File

@ -0,0 +1,49 @@
<div>
@if (
$resource->getMorphClass() == 'App\Models\Application' ||
$resource->getMorphClass() == 'App\Models\StandalonePostgresql')
<div class="flex items-center gap-2">
<h2>Storages</h2>
<x-helper
helper="For Preview Deployments, storage has a <span class='text-helper'>-pr-#PRNumber</span> in their
volume
name, example: <span class='text-helper'>-pr-1</span>" />
<x-forms.button class="btn" onclick="newStorage.showModal()">+ Add</x-forms.button>
<livewire:project.shared.storages.add :uuid="$resource->uuid" />
</div>
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
@if (
$resource->persistentStorages()->get()->count() === 0 &&
$resource->fileStorages()->get()->count() == 0)
<div>No storage found.</div>
@else
@if ($resource->persistentStorages()->get()->count() > 0)
<livewire:project.shared.storages.all :resource="$resource" />
@endif
@if ($resource->fileStorages()->get()->count() > 0)
<div class="flex flex-col gap-4 pt-4">
@foreach ($resource->fileStorages()->get()->sort() as $fileStorage)
<livewire:project.service.file-storage :fileStorage="$fileStorage"
wire:key="resource-{{ $resource->uuid }}" />
@endforeach
</div>
@endif
@endif
@else
@if (
$resource->persistentStorages()->get()->count() > 0 ||
$resource->fileStorages()->get()->count() > 0)
<h3 class="pt-4">{{ Str::headline($resource->name) }} </h3>
@endif
@if ($resource->persistentStorages()->get()->count() > 0)
<livewire:project.shared.storages.all :resource="$resource" />
@endif
@if ($resource->fileStorages()->get()->count() > 0)
<div class="flex flex-col gap-4 pt-4">
@foreach ($resource->fileStorages()->get()->sort() as $fileStorage)
<livewire:project.service.file-storage :fileStorage="$fileStorage" wire:key="resource-{{ $resource->uuid }}" />
@endforeach
</div>
@endif
@endif
</div>

View File

@ -1,25 +1,4 @@
<div>
@if ($isHeaderVisible)
<div>
<div class="flex items-center gap-2">
<h2>Storages</h2>
@if ($resource->type() !== 'service')
<x-helper
helper="For Preview Deployments, storage has a <span class='text-helper'>-pr-#PRNumber</span> in their
volume
name, example: <span class='text-helper'>-pr-1</span>" />
<x-forms.button class="btn" onclick="newStorage.showModal()">+ Add</x-forms.button>
<livewire:project.shared.storages.add :uuid="$resource->uuid" />
@endif
</div>
<div class="pb-4">Persistent storage to preserve data between deployments.</div>
@if ($resource->type() === 'service')
<span class="text-warning">Please modify storage layout in your <a class="underline"
href="{{ Str::of(url()->current())->beforeLast('/') }}">Docker Compose</a> file.</span>
<h2 class="pt-4">{{ Str::headline($resource->name) }} </h2>
@endif
</div>
@endif
<div class="flex flex-col gap-4">
@foreach ($resource->persistentStorages as $storage)
@if ($resource->type() === 'service')

View File

@ -14,8 +14,7 @@
@click.prevent="activeTab = 'source'; window.location.hash = 'source'" href="#">Source</a>
@endif
<a :class="activeTab === 'server' && 'text-white'"
@click.prevent="activeTab = 'server'; window.location.hash = 'server'"
href="#">Server
@click.prevent="activeTab = 'server'; window.location.hash = 'server'" href="#">Server
</a>
<a :class="activeTab === 'storages' && 'text-white'"
@click.prevent="activeTab = 'storages'; window.location.hash = 'storages'" href="#">Storages
@ -27,8 +26,8 @@
</a>
@endif
<a :class="activeTab === 'health' && 'text-white'"
@click.prevent="activeTab = 'health'; window.location.hash = 'health'" href="#">Health Checks
</a>
@click.prevent="activeTab = 'health'; window.location.hash = 'health'" href="#">Health Checks
</a>
<a :class="activeTab === 'rollback' && 'text-white'"
@click.prevent="activeTab = 'rollback'; window.location.hash = 'rollback'" href="#">Rollback
</a>
@ -56,7 +55,7 @@
<livewire:project.shared.destination :destination="$application->destination" />
</div>
<div x-cloak x-show="activeTab === 'storages'">
<livewire:project.shared.storages.all :resource="$application" />
<livewire:project.service.storage :resource="$application" />
</div>
<div x-cloak x-show="activeTab === 'previews'">
<livewire:project.application.previews :application="$application" />

View File

@ -47,7 +47,7 @@
<livewire:project.shared.destination :destination="$database->destination" />
</div>
<div x-cloak x-show="activeTab === 'storages'">
<livewire:project.shared.storages.all :resource="$database" />
<livewire:project.service.storage :resource="$database" />
</div>
<div x-cloak x-show="activeTab === 'resource-limits'">
<livewire:project.shared.resource-limits :resource="$database" />