mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-26 04:59:31 +00:00
Compare commits
17 Commits
v4.0.0-bet
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af5b9fced1 | ||
|
|
ab5202515e | ||
|
|
f863db7ea5 | ||
|
|
3adc0bdd6e | ||
|
|
97027875bf | ||
|
|
fd9c13009f | ||
|
|
46a72fac47 | ||
|
|
5d6ee04991 | ||
|
|
d523becb29 | ||
|
|
41672f75d0 | ||
|
|
acd8541e68 | ||
|
|
ed6af777a4 | ||
|
|
05f162f4e8 | ||
|
|
5e0adc3777 | ||
|
|
7d06fc4403 | ||
|
|
0e1bcceb8e | ||
|
|
a922f2fedf |
@@ -127,7 +127,7 @@ class General extends Component
|
||||
}
|
||||
if (data_get($this->application, 'dockerfile')) {
|
||||
$port = get_port_from_dockerfile($this->application->dockerfile);
|
||||
if ($port) {
|
||||
if ($port && !$this->application->ports_exposes) {
|
||||
$this->application->ports_exposes = $port;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ CMD ["nginx", "-g", "daemon off;"]
|
||||
'environment_id' => $environment->id,
|
||||
'destination_id' => $destination->id,
|
||||
'destination_type' => $destination_class,
|
||||
'health_check_enabled' => false,
|
||||
'source_id' => 0,
|
||||
'source_type' => GithubApp::class
|
||||
]);
|
||||
|
||||
@@ -21,7 +21,6 @@ class Navbar extends Component
|
||||
}
|
||||
public function serviceStatusUpdated()
|
||||
{
|
||||
ray('serviceStatusUpdated');
|
||||
$this->check_status();
|
||||
}
|
||||
public function check_status()
|
||||
|
||||
40
app/Http/Livewire/Project/Shared/GetLogs.php
Normal file
40
app/Http/Livewire/Project/Shared/GetLogs.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Project\Shared;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Livewire\Component;
|
||||
|
||||
class GetLogs extends Component
|
||||
{
|
||||
public string $outputs = '';
|
||||
public string $errors = '';
|
||||
public Server $server;
|
||||
public ?string $container = null;
|
||||
public ?bool $streamLogs = false;
|
||||
public int $numberOfLines = 100;
|
||||
public function doSomethingWithThisChunkOfOutput($output)
|
||||
{
|
||||
$this->outputs .= $output;
|
||||
}
|
||||
public function instantSave()
|
||||
{
|
||||
}
|
||||
public function getLogs($refresh = false)
|
||||
{
|
||||
if ($this->container) {
|
||||
$sshCommand = generateSshCommand($this->server, "docker logs -n {$this->numberOfLines} -t {$this->container}");
|
||||
if ($refresh) {
|
||||
$this->outputs = '';
|
||||
}
|
||||
Process::run($sshCommand, function (string $type, string $output) {
|
||||
$this->doSomethingWithThisChunkOfOutput($output);
|
||||
});
|
||||
}
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.shared.get-logs');
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ class HealthChecks extends Component
|
||||
|
||||
public $resource;
|
||||
protected $rules = [
|
||||
'resource.health_check_enabled' => 'boolean',
|
||||
'resource.health_check_path' => 'string',
|
||||
'resource.health_check_port' => 'nullable|string',
|
||||
'resource.health_check_host' => 'string',
|
||||
@@ -22,12 +23,19 @@ class HealthChecks extends Component
|
||||
'resource.health_check_start_period' => 'integer',
|
||||
|
||||
];
|
||||
public function instantSave()
|
||||
{
|
||||
$this->resource->save();
|
||||
$this->emit('success', 'Health check updated.');
|
||||
|
||||
|
||||
}
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->validate();
|
||||
$this->resource->save();
|
||||
$this->emit('saved');
|
||||
$this->emit('success', 'Health check updated.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
53
app/Http/Livewire/Project/Shared/Logs.php
Normal file
53
app/Http/Livewire/Project/Shared/Logs.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Project\Shared;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\Server;
|
||||
use App\Models\Service;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use Livewire\Component;
|
||||
|
||||
class Logs extends Component
|
||||
{
|
||||
public ?string $type = null;
|
||||
public Application|StandalonePostgresql|Service $resource;
|
||||
public Server $server;
|
||||
public ?string $container = null;
|
||||
public $parameters;
|
||||
public $query;
|
||||
public $status;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->query = request()->query();
|
||||
if (data_get($this->parameters, 'application_uuid')) {
|
||||
$this->type = 'application';
|
||||
$this->resource = Application::where('uuid', $this->parameters['application_uuid'])->firstOrFail();
|
||||
$this->status = $this->resource->status;
|
||||
$this->server = $this->resource->destination->server;
|
||||
$containers = getCurrentApplicationContainerStatus($this->server, $this->resource->id);
|
||||
if ($containers->count() > 0) {
|
||||
$this->container = data_get($containers[0], 'Names');
|
||||
}
|
||||
} else if (data_get($this->parameters, 'database_uuid')) {
|
||||
$this->type = 'database';
|
||||
$this->resource = StandalonePostgresql::where('uuid', $this->parameters['database_uuid'])->firstOrFail();
|
||||
$this->status = $this->resource->status;
|
||||
$this->server = $this->resource->destination->server;
|
||||
$this->container = $this->resource->uuid;
|
||||
} else if (data_get($this->parameters, 'service_uuid')) {
|
||||
$this->type = 'service';
|
||||
$this->resource = Service::where('uuid', $this->parameters['service_uuid'])->firstOrFail();
|
||||
$this->status = $this->resource->status;
|
||||
$this->server = $this->resource->server;
|
||||
$this->container = data_get($this->parameters, 'service_name') . '-' . $this->resource->uuid;
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.shared.logs');
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ use Livewire\Component;
|
||||
|
||||
class Add extends Component
|
||||
{
|
||||
public $uuid;
|
||||
public $parameters;
|
||||
public string $name;
|
||||
public string $mount_path;
|
||||
@@ -31,8 +32,9 @@ class Add extends Component
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
$name = $this->uuid . '-' . $this->name;
|
||||
$this->emitUp('submit', [
|
||||
'name' => $this->name,
|
||||
'name' => $name,
|
||||
'mount_path' => $this->mount_path,
|
||||
'host_path' => $this->host_path,
|
||||
]);
|
||||
|
||||
@@ -11,7 +11,6 @@ class Show extends Component
|
||||
public LocalPersistentVolume $storage;
|
||||
public bool $isReadOnly = false;
|
||||
public ?string $modalId = null;
|
||||
public ?string $realName = null;
|
||||
|
||||
protected $rules = [
|
||||
'storage.name' => 'required|string',
|
||||
@@ -26,11 +25,6 @@ class Show extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if ($this->storage->resource_type === 'App\Models\ServiceApplication' || $this->storage->resource_type === 'App\Models\ServiceDatabase') {
|
||||
$this->realName = "{$this->storage->service->service->uuid}_{$this->storage->name}";
|
||||
} else {
|
||||
$this->realName = $this->storage->name;
|
||||
}
|
||||
$this->modalId = new Cuid2(7);
|
||||
}
|
||||
|
||||
|
||||
@@ -303,6 +303,10 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
}
|
||||
private function health_check()
|
||||
{
|
||||
if ($this->application->isHealthcheckDisabled()) {
|
||||
$this->newVersionIsHealthy = true;
|
||||
return;
|
||||
}
|
||||
ray('New container name: ', $this->container_name);
|
||||
if ($this->container_name) {
|
||||
$counter = 0;
|
||||
@@ -375,9 +379,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
private function prepare_builder_image()
|
||||
{
|
||||
$pull = "--pull=always";
|
||||
if (isDev()) {
|
||||
$pull = "--pull=never";
|
||||
}
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$runCommand = "docker run {$pull} -d --network {$this->destination->network} -v /:/host --name {$this->deployment_uuid} --rm -v /var/run/docker.sock:/var/run/docker.sock {$helperImage}";
|
||||
|
||||
@@ -573,6 +574,9 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
||||
]
|
||||
]
|
||||
];
|
||||
if ($this->application->isHealthcheckDisabled()) {
|
||||
data_forget($docker_compose, 'services.' . $this->container_name . '.healthcheck');
|
||||
}
|
||||
if (count($this->application->ports_mappings_array) > 0 && $this->pull_request_id === 0) {
|
||||
$docker_compose['services'][$this->container_name]['ports'] = $this->application->ports_mappings_array;
|
||||
}
|
||||
|
||||
@@ -231,4 +231,12 @@ class Application extends BaseModel
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public function isHealthcheckDisabled(): bool
|
||||
{
|
||||
if (data_get($this, 'dockerfile') || data_get($this, 'build_pack') === 'dockerfile' || data_get($this,'health_check_enabled') === false) {
|
||||
ray('dockerfile');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ class Service extends BaseModel
|
||||
|
||||
// Collect/create/update volumes
|
||||
if ($serviceVolumes->count() > 0) {
|
||||
foreach ($serviceVolumes as $volume) {
|
||||
$serviceVolumes = $serviceVolumes->map(function ($volume) use ($savedService, $topLevelVolumes, $isNew) {
|
||||
$type = null;
|
||||
$source = null;
|
||||
$target = null;
|
||||
@@ -276,10 +276,10 @@ class Service extends BaseModel
|
||||
}
|
||||
if ($type->value() === 'bind') {
|
||||
if ($source->value() === "/var/run/docker.sock") {
|
||||
continue;
|
||||
return $volume;
|
||||
}
|
||||
if ($source->value() === '/tmp' || $source->value() === '/tmp/') {
|
||||
continue;
|
||||
return $volume;
|
||||
}
|
||||
LocalFileVolume::updateOrCreate(
|
||||
[
|
||||
@@ -297,7 +297,21 @@ class Service extends BaseModel
|
||||
]
|
||||
);
|
||||
} else if ($type->value() === 'volume') {
|
||||
$topLevelVolumes->put($source->value(), null);
|
||||
$slug = Str::slug($source, '-');
|
||||
if ($isNew) {
|
||||
$name = "{$savedService->service->uuid}-{$slug}";
|
||||
} else {
|
||||
$name = "{$savedService->service->uuid}_{$slug}";
|
||||
}
|
||||
if (is_string($volume)) {
|
||||
$source = Str::of($volume)->before(':');
|
||||
$target = Str::of($volume)->after(':')->beforeLast(':');
|
||||
$source = $name;
|
||||
$volume = "$source:$target";
|
||||
} else if(is_array($volume)) {
|
||||
data_set($volume, 'source', $name);
|
||||
}
|
||||
$topLevelVolumes->put($name, null);
|
||||
LocalPersistentVolume::updateOrCreate(
|
||||
[
|
||||
'mount_path' => $target,
|
||||
@@ -305,7 +319,7 @@ class Service extends BaseModel
|
||||
'resource_type' => get_class($savedService)
|
||||
],
|
||||
[
|
||||
'name' => Str::slug($source, '-'),
|
||||
'name' => $name,
|
||||
'mount_path' => $target,
|
||||
'resource_id' => $savedService->id,
|
||||
'resource_type' => get_class($savedService)
|
||||
@@ -313,7 +327,9 @@ class Service extends BaseModel
|
||||
);
|
||||
}
|
||||
$savedService->getFilesFromServer();
|
||||
}
|
||||
return $volume;
|
||||
});
|
||||
data_set($service, 'volumes', $serviceVolumes->toArray());
|
||||
}
|
||||
|
||||
// Add env_file with at least .env to the service
|
||||
|
||||
@@ -7,7 +7,7 @@ return [
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.55',
|
||||
'release' => '4.0.0-beta.57',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.55';
|
||||
return '4.0.0-beta.57';
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->boolean('health_check_enabled')->default(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->dropColumn('health_check_enabled');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -7,6 +7,10 @@
|
||||
href="{{ route('project.application.deployments', $parameters) }}">
|
||||
<button>Deployments</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('project.application.logs') ? 'text-white' : '' }}"
|
||||
href="{{ route('project.application.logs', $parameters) }}">
|
||||
<button>Logs</button>
|
||||
</a>
|
||||
<x-applications.links :application="$application" />
|
||||
<div class="flex-1"></div>
|
||||
<x-applications.advanced :application="$application" />
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
href="{{ route('project.database.configuration', $parameters) }}">
|
||||
<button>Configuration</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('project.database.logs') ? 'text-white' : '' }}"
|
||||
href="{{ route('project.database.logs', $parameters) }}">
|
||||
<button>Logs</button>
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('project.database.backups.all') ? 'text-white' : '' }}"
|
||||
href="{{ route('project.database.backups.all', $parameters) }}">
|
||||
<button>Backups</button>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
<div class="navbar-main">
|
||||
<a class="{{ request()->routeIs('project.service') ? 'text-white' : '' }}"
|
||||
href="{{ route('project.service', $parameters) }}">
|
||||
<button>Configuration</button>
|
||||
</a>
|
||||
<x-services.links :service="$service" />
|
||||
<div class="flex-1"></div>
|
||||
@if (serviceStatus($service) === 'degraded')
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<x-boarding-step title="Server">
|
||||
<x-slot:question>
|
||||
Do you want to deploy your resources on your <x-highlighted text="Localhost" />
|
||||
or on a<x-highlighted text="Remote Server" />?
|
||||
or on a <x-highlighted text="Remote Server" />?
|
||||
</x-slot:question>
|
||||
<x-slot:actions>
|
||||
<x-forms.button class="justify-center box" wire:target="setServerType('localhost')"
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
<div>Configuration</div>
|
||||
</div>
|
||||
<x-forms.button type="submit">Save</x-forms.button>
|
||||
<x-forms.button class="w-64" onclick="composeModal.showModal()">Edit Compose File</x-forms.button>
|
||||
<x-forms.button class="w-64" onclick="composeModal.showModal()">Edit Compose
|
||||
File</x-forms.button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="service.name" required label="Service Name"
|
||||
@@ -34,57 +35,66 @@
|
||||
</form>
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 xl:grid-cols-3">
|
||||
@foreach ($service->applications as $application)
|
||||
<a @class([
|
||||
<div @class([
|
||||
'border-l border-dashed border-red-500' => Str::of(
|
||||
$application->status)->contains(['exited']),
|
||||
'border-l border-dashed border-success' => Str::of(
|
||||
$application->status)->contains(['running']),
|
||||
'border-l border-dashed border-warning' => Str::of(
|
||||
$application->status)->contains(['starting']),
|
||||
'flex flex-col justify-center box',
|
||||
])
|
||||
href="{{ route('project.service.show', [...$parameters, 'service_name' => $application->name]) }}">
|
||||
@if ($application->human_name)
|
||||
{{ Str::headline($application->human_name) }}
|
||||
@else
|
||||
{{ Str::headline($application->name) }}
|
||||
@endif
|
||||
@if ($application->configuration_required)
|
||||
<span class="text-xs text-error">(configuration required)</span>
|
||||
@endif
|
||||
@if ($application->description)
|
||||
<span class="text-xs">{{ Str::limit($application->description, 60) }}</span>
|
||||
@endif
|
||||
@if ($application->fqdn)
|
||||
<span class="text-xs">{{ Str::limit($application->fqdn, 60) }}</span>
|
||||
@endif
|
||||
<div class="text-xs">{{ $application->status }}</div>
|
||||
</a>
|
||||
'flex gap-2 box group',
|
||||
])>
|
||||
<a class="flex flex-col flex-1 group-hover:text-white hover:no-underline"
|
||||
href="{{ route('project.service.show', [...$parameters, 'service_name' => $application->name]) }}">
|
||||
|
||||
@if ($application->human_name)
|
||||
{{ Str::headline($application->human_name) }}
|
||||
@else
|
||||
{{ Str::headline($application->name) }}
|
||||
@endif
|
||||
@if ($application->configuration_required)
|
||||
<span class="text-xs text-error">(configuration required)</span>
|
||||
@endif
|
||||
@if ($application->description)
|
||||
<span class="text-xs">{{ Str::limit($application->description, 60) }}</span>
|
||||
@endif
|
||||
@if ($application->fqdn)
|
||||
<span class="text-xs">{{ Str::limit($application->fqdn, 60) }}</span>
|
||||
@endif
|
||||
<div class="text-xs">{{ $application->status }}</div>
|
||||
</a>
|
||||
<a class="flex gap-2 p-1 mx-4 text-xs font-bold rounded hover:no-underline hover:text-warning"
|
||||
href="{{ route('project.service.logs', [...$parameters, 'service_name' => $application->name]) }}">Logs</a>
|
||||
</div>
|
||||
@endforeach
|
||||
@foreach ($databases as $database)
|
||||
<a @class([
|
||||
<div @class([
|
||||
'border-l border-dashed border-red-500' => Str::of(
|
||||
$database->status)->contains(['exited']),
|
||||
'border-l border-dashed border-success' => Str::of(
|
||||
$database->status)->contains(['running']),
|
||||
'border-l border-dashed border-warning' => Str::of(
|
||||
$database->status)->contains(['restarting']),
|
||||
'flex flex-col justify-center box',
|
||||
])
|
||||
href="{{ route('project.service.show', [...$parameters, 'service_name' => $database->name]) }}">
|
||||
@if ($database->human_name)
|
||||
{{ Str::headline($database->human_name) }}
|
||||
@else
|
||||
{{ Str::headline($database->name) }}
|
||||
@endif
|
||||
@if ($database->configuration_required)
|
||||
<span class="text-xs text-error">(configuration required)</span>
|
||||
@endif
|
||||
@if ($database->description)
|
||||
<span class="text-xs">{{ Str::limit($database->description, 60) }}</span>
|
||||
@endif
|
||||
<div class="text-xs">{{ $database->status }}</div>
|
||||
</a>
|
||||
'flex gap-2 box group',
|
||||
])>
|
||||
<a class="flex flex-col flex-1 group-hover:text-white hover:no-underline"
|
||||
href="{{ route('project.service.show', [...$parameters, 'service_name' => $database->name]) }}">
|
||||
@if ($database->human_name)
|
||||
{{ Str::headline($database->human_name) }}
|
||||
@else
|
||||
{{ Str::headline($database->name) }}
|
||||
@endif
|
||||
@if ($database->configuration_required)
|
||||
<span class="text-xs text-error">(configuration required)</span>
|
||||
@endif
|
||||
@if ($database->description)
|
||||
<span class="text-xs">{{ Str::limit($database->description, 60) }}</span>
|
||||
@endif
|
||||
<div class="text-xs">{{ $database->status }}</div>
|
||||
</a>
|
||||
<a class="flex gap-2 p-1 mx-4 text-xs font-bold rounded hover:no-underline hover:text-warning"
|
||||
href="{{ route('project.service.logs', [...$parameters, 'service_name' => $database->name]) }}">Logs</a>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
<a :class="activeTab === 'storages' && 'text-white'"
|
||||
@click.prevent="activeTab = 'storages'; window.location.hash = 'storages'" href="#">Storages
|
||||
</a>
|
||||
@if (data_get($parameters, 'service_name'))
|
||||
<a class="{{ request()->routeIs('project.service.logs') ? 'text-white' : '' }}"
|
||||
href="{{ route('project.service.logs', $parameters) }}">
|
||||
<button>Logs</button>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
<div class="w-full pl-8">
|
||||
@isset($serviceApplication)
|
||||
@@ -32,7 +38,6 @@
|
||||
@isset($serviceDatabase)
|
||||
<div x-cloak x-show="activeTab === 'general'" class="h-full">
|
||||
<livewire:project.service.database :database="$serviceDatabase" />
|
||||
|
||||
</div>
|
||||
<div x-cloak x-show="activeTab === 'storages'">
|
||||
<livewire:project.shared.storages.all :resource="$serviceDatabase" />
|
||||
|
||||
22
resources/views/livewire/project/shared/get-logs.blade.php
Normal file
22
resources/views/livewire/project/shared/get-logs.blade.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<div x-init="$wire.getLogs">
|
||||
<div class="flex gap-2">
|
||||
<h2>Logs</h2>
|
||||
@if ($streamLogs)
|
||||
<span wire:poll.2000ms='getLogs(true)' class="loading loading-xs text-warning loading-spinner"></span>
|
||||
@endif
|
||||
</div>
|
||||
<form wire:submit.prevent='getLogs(true)' class="flex items-end gap-2">
|
||||
<x-forms.input label="Only Show Number of Lines" placeholder="1000" required id="numberOfLines"></x-forms.input>
|
||||
<x-forms.button type="submit">Refresh</x-forms.button>
|
||||
</form>
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave label="Stream Logs" id="streamLogs"></x-forms.checkbox>
|
||||
</div>
|
||||
<div class="container w-full pt-4 mx-auto">
|
||||
<div
|
||||
class="scrollbar flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4 pt-6 text-xs text-white">
|
||||
|
||||
<pre class="font-mono whitespace-pre-wrap">{{ $outputs }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -5,24 +5,27 @@
|
||||
</div>
|
||||
<div class="pb-4">Define how your resource's health should be checked.</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="resource.health_check_method" placeholder="GET" label="Method" required />
|
||||
<div class="w-32">
|
||||
<x-forms.checkbox instantSave id="resource.health_check_enabled" label="Enabled" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="resource.health_check_method" placeholder="GET" label="Method" required />
|
||||
|
||||
<x-forms.input id="resource.health_check_scheme" placeholder="http" label="Scheme" required />
|
||||
<x-forms.input id="resource.health_check_host" placeholder="localhost" label="Host" required />
|
||||
<x-forms.input id="resource.health_check_port"
|
||||
helper="If no port is defined, the first exposed port will be used." placeholder="80" label="Port" />
|
||||
<x-forms.input id="resource.health_check_path" placeholder="/health" label="Path" required />
|
||||
<x-forms.input id="resource.health_check_scheme" placeholder="http" label="Scheme" required />
|
||||
<x-forms.input id="resource.health_check_host" placeholder="localhost" label="Host" required />
|
||||
<x-forms.input id="resource.health_check_port"
|
||||
helper="If no port is defined, the first exposed port will be used." placeholder="80" label="Port" />
|
||||
<x-forms.input id="resource.health_check_path" placeholder="/health" label="Path" required />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="resource.health_check_return_code" placeholder="200" label="Return Code" required />
|
||||
<x-forms.input id="resource.health_check_response_text" placeholder="OK" label="Response Text" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="resource.health_check_interval" placeholder="30" label="Interval" required />
|
||||
<x-forms.input id="resource.health_check_timeout" placeholder="30" label="Timeout" required />
|
||||
<x-forms.input id="resource.health_check_retries" placeholder="3" label="Retries" required />
|
||||
<x-forms.input id="resource.health_check_start_period" placeholder="30" label="Start Period" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="resource.health_check_return_code" placeholder="200" label="Return Code" required />
|
||||
<x-forms.input id="resource.health_check_response_text" placeholder="OK" label="Response Text" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="resource.health_check_interval" placeholder="30" label="Interval" required />
|
||||
<x-forms.input id="resource.health_check_timeout" placeholder="30" label="Timeout" required />
|
||||
<x-forms.input id="resource.health_check_retries" placeholder="3" label="Retries" required />
|
||||
<x-forms.input id="resource.health_check_start_period" placeholder="30" label="Start Period" required />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
41
resources/views/livewire/project/shared/logs.blade.php
Normal file
41
resources/views/livewire/project/shared/logs.blade.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<x-layout>
|
||||
@if ($type === 'application')
|
||||
<h1>Logs</h1>
|
||||
<livewire:project.application.heading :application="$resource" />
|
||||
<div class="pt-4">
|
||||
@if (Str::of($status)->startsWith('running'))
|
||||
<livewire:project.shared.get-logs :server="$server" :container="$container" />
|
||||
@else
|
||||
Application is not running.
|
||||
@endif
|
||||
</div>
|
||||
@elseif ($type === 'database')
|
||||
<h1>Logs</h1>
|
||||
<livewire:project.database.heading :database="$resource" />
|
||||
<div class="pt-4">
|
||||
@if (Str::of($status)->startsWith('running'))
|
||||
<livewire:project.shared.get-logs :server="$server" :container="$container" />
|
||||
@else
|
||||
Database is not running.
|
||||
@endif
|
||||
</div>
|
||||
@elseif ($type === 'service')
|
||||
<livewire:project.service.navbar :service="$resource" :parameters="$parameters" :query="$query" />
|
||||
<div class="flex gap-4 pt-6">
|
||||
<div>
|
||||
<a class="{{ request()->routeIs('project.service.show') ? 'text-white' : '' }}"
|
||||
href="{{ route('project.service.show', $parameters) }}">
|
||||
<button><- Back</button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex-1 pl-8">
|
||||
@if (serviceStatus($resource) === 'running')
|
||||
<livewire:project.shared.get-logs :server="$server" :container="$container" />
|
||||
@else
|
||||
Service is not running.
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</x-layout>
|
||||
@@ -8,7 +8,7 @@
|
||||
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 />
|
||||
<livewire:project.shared.storages.add :uuid="$resource->uuid" />
|
||||
@endif
|
||||
</div>
|
||||
<div>Persistent storage to preserve data between deployments.</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
@endonce
|
||||
<form wire:submit.prevent='submit' class="flex flex-col gap-2 pt-4 xl:items-end xl:flex-row">
|
||||
@if ($isReadOnly)
|
||||
<x-forms.input id="realName" label="Volume Name" required readonly />
|
||||
<x-forms.input id="storage.name" label="Volume Name" required readonly />
|
||||
<x-forms.input id="storage.host_path" label="Source Path" readonly />
|
||||
<x-forms.input id="storage.mount_path" label="Destination Path" required readonly />
|
||||
@else
|
||||
|
||||
@@ -10,6 +10,7 @@ use App\Http\Livewire\Boarding\Index as BoardingIndex;
|
||||
use App\Http\Livewire\Project\Service\Index as ServiceIndex;
|
||||
use App\Http\Livewire\Project\Service\Show as ServiceShow;
|
||||
use App\Http\Livewire\Dashboard;
|
||||
use App\Http\Livewire\Project\Shared\Logs;
|
||||
use App\Http\Livewire\Server\All;
|
||||
use App\Http\Livewire\Server\Show;
|
||||
use App\Http\Livewire\Waitlist\Index as WaitlistIndex;
|
||||
@@ -80,14 +81,20 @@ Route::middleware(['auth'])->group(function () {
|
||||
[ApplicationController::class, 'deployment']
|
||||
)->name('project.application.deployment');
|
||||
|
||||
Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}/logs', Logs::class)->name('project.application.logs');
|
||||
|
||||
// Databases
|
||||
Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}', [DatabaseController::class, 'configuration'])->name('project.database.configuration');
|
||||
Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}/backups', [DatabaseController::class, 'backups'])->name('project.database.backups.all');
|
||||
Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}/backups/{backup_uuid}', [DatabaseController::class, 'executions'])->name('project.database.backups.executions');
|
||||
Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}/logs', Logs::class)->name('project.database.logs');
|
||||
|
||||
|
||||
// Services
|
||||
Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}', ServiceIndex::class)->name('project.service');
|
||||
Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}/{service_name}', ServiceShow::class)->name('project.service.show');
|
||||
Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}/{service_name}/logs', Logs::class)->name('project.service.logs');
|
||||
|
||||
});
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
|
||||
@@ -327,7 +327,7 @@ Route::post('/payments/stripe/events', function () {
|
||||
}
|
||||
if ($alreadyCancelAtPeriodEnd !== $cancelAtPeriodEnd) {
|
||||
if ($cancelAtPeriodEnd) {
|
||||
send_internal_notification('Subscription cancelled at period end for team: ' . $subscription->team->id);
|
||||
// send_internal_notification('Subscription cancelled at period end for team: ' . $subscription->team->id);
|
||||
} else {
|
||||
send_internal_notification('Subscription resumed for team: ' . $subscription->team->id);
|
||||
}
|
||||
@@ -346,7 +346,7 @@ Route::post('/payments/stripe/events', function () {
|
||||
'stripe_invoice_paid' => false,
|
||||
'stripe_trial_already_ended' => true,
|
||||
]);
|
||||
send_internal_notification('Subscription cancelled: ' . $subscription->team->id);
|
||||
// send_internal_notification('Subscription cancelled: ' . $subscription->team->id);
|
||||
break;
|
||||
case 'customer.subscription.trial_will_end':
|
||||
$customerId = data_get($data, 'customer');
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"version": "3.12.36"
|
||||
},
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.55"
|
||||
"version": "4.0.0-beta.57"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user