refactor server view (phuuu)
This commit is contained in:
@@ -5,7 +5,7 @@ namespace App\Actions\Server;
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class InstallLogDrain
|
||||
class StartLogDrain
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
@@ -13,12 +13,16 @@ class InstallLogDrain
|
||||
{
|
||||
if ($server->settings->is_logdrain_newrelic_enabled) {
|
||||
$type = 'newrelic';
|
||||
StopLogDrain::run($server);
|
||||
} elseif ($server->settings->is_logdrain_highlight_enabled) {
|
||||
$type = 'highlight';
|
||||
StopLogDrain::run($server);
|
||||
} elseif ($server->settings->is_logdrain_axiom_enabled) {
|
||||
$type = 'axiom';
|
||||
StopLogDrain::run($server);
|
||||
} elseif ($server->settings->is_logdrain_custom_enabled) {
|
||||
$type = 'custom';
|
||||
StopLogDrain::run($server);
|
||||
} else {
|
||||
$type = 'none';
|
||||
}
|
||||
@@ -151,6 +155,8 @@ services:
|
||||
- ./parsers.conf:/parsers.conf
|
||||
ports:
|
||||
- 127.0.0.1:24224:24224
|
||||
labels:
|
||||
- coolify.managed=true
|
||||
restart: unless-stopped
|
||||
');
|
||||
$readme = base64_encode('# New Relic Log Drain
|
||||
@@ -202,15 +208,11 @@ Files:
|
||||
throw new \Exception('Unknown log drain type.');
|
||||
}
|
||||
$restart_command = [
|
||||
"echo 'Stopping old Fluent Bit'",
|
||||
"cd $config_path && docker compose down --remove-orphans || true",
|
||||
"echo 'Starting Fluent Bit'",
|
||||
"cd $config_path && docker compose up -d --remove-orphans",
|
||||
"cd $config_path && docker compose up -d",
|
||||
];
|
||||
$command = array_merge($command, $add_envs_command, $restart_command);
|
||||
|
||||
StopLogDrain::run($server);
|
||||
|
||||
return instant_remote_process($command, $server);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e);
|
||||
@@ -12,7 +12,7 @@ class StopLogDrain
|
||||
public function handle(Server $server)
|
||||
{
|
||||
try {
|
||||
return instant_remote_process(['docker rm -f coolify-log-drain || true'], $server);
|
||||
return instant_remote_process(['docker rm -f coolify-log-drain'], $server, false);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use App\Actions\Database\StartDatabaseProxy;
|
||||
use App\Actions\Database\StopDatabaseProxy;
|
||||
use App\Actions\Proxy\CheckProxy;
|
||||
use App\Actions\Proxy\StartProxy;
|
||||
use App\Actions\Server\InstallLogDrain;
|
||||
use App\Actions\Server\StartLogDrain;
|
||||
use App\Actions\Shared\ComplexStatusCheck;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
@@ -362,7 +362,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
|
||||
private function checkLogDrainContainer()
|
||||
{
|
||||
if ($this->server->isLogDrainEnabled() && $this->foundLogDrainContainer === false) {
|
||||
InstallLogDrain::dispatch($this->server);
|
||||
StartLogDrain::dispatch($this->server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Jobs;
|
||||
use App\Actions\Docker\GetContainersStatus;
|
||||
use App\Actions\Proxy\CheckProxy;
|
||||
use App\Actions\Proxy\StartProxy;
|
||||
use App\Actions\Server\InstallLogDrain;
|
||||
use App\Actions\Server\StartLogDrain;
|
||||
use App\Models\Server;
|
||||
use App\Notifications\Container\ContainerRestarted;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@@ -109,10 +109,10 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
if ($foundLogDrainContainer) {
|
||||
$status = data_get($foundLogDrainContainer, 'State.Status');
|
||||
if ($status !== 'running') {
|
||||
InstallLogDrain::dispatch($this->server);
|
||||
StartLogDrain::dispatch($this->server);
|
||||
}
|
||||
} else {
|
||||
InstallLogDrain::dispatch($this->server);
|
||||
StartLogDrain::dispatch($this->server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ class ServerStorageCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
if (is_null($this->percentage)) {
|
||||
$this->percentage = $this->server->storageCheck();
|
||||
loggy('Server storage check percentage: '.$this->percentage);
|
||||
}
|
||||
if (! $this->percentage) {
|
||||
return 'No percentage could be retrieved.';
|
||||
|
||||
@@ -4,45 +4,82 @@ namespace App\Livewire\Server;
|
||||
|
||||
use App\Jobs\DockerCleanupJob;
|
||||
use App\Models\Server;
|
||||
use Livewire\Attributes\Rule;
|
||||
use Livewire\Component;
|
||||
|
||||
class Advanced extends Component
|
||||
{
|
||||
public Server $server;
|
||||
|
||||
protected $rules = [
|
||||
'server.settings.concurrent_builds' => 'required|integer|min:1',
|
||||
'server.settings.dynamic_timeout' => 'required|integer|min:1',
|
||||
'server.settings.force_docker_cleanup' => 'required|boolean',
|
||||
'server.settings.docker_cleanup_frequency' => 'required_if:server.settings.force_docker_cleanup,true|string',
|
||||
'server.settings.docker_cleanup_threshold' => 'required_if:server.settings.force_docker_cleanup,false|integer|min:1|max:100',
|
||||
'server.settings.server_disk_usage_notification_threshold' => 'required|integer|min:50|max:100',
|
||||
'server.settings.delete_unused_volumes' => 'boolean',
|
||||
'server.settings.delete_unused_networks' => 'boolean',
|
||||
];
|
||||
public array $parameters = [];
|
||||
|
||||
protected $validationAttributes = [
|
||||
#[Rule(['integer', 'min:1'])]
|
||||
public int $concurrentBuilds = 1;
|
||||
|
||||
'server.settings.concurrent_builds' => 'Concurrent Builds',
|
||||
'server.settings.dynamic_timeout' => 'Dynamic Timeout',
|
||||
'server.settings.force_docker_cleanup' => 'Force Docker Cleanup',
|
||||
'server.settings.docker_cleanup_frequency' => 'Docker Cleanup Frequency',
|
||||
'server.settings.docker_cleanup_threshold' => 'Docker Cleanup Threshold',
|
||||
'server.settings.server_disk_usage_notification_threshold' => 'Server Disk Usage Notification Threshold',
|
||||
'server.settings.delete_unused_volumes' => 'Delete Unused Volumes',
|
||||
'server.settings.delete_unused_networks' => 'Delete Unused Networks',
|
||||
];
|
||||
#[Rule(['integer', 'min:1'])]
|
||||
public int $dynamicTimeout = 1;
|
||||
|
||||
#[Rule('boolean')]
|
||||
public bool $forceDockerCleanup = false;
|
||||
|
||||
#[Rule('string')]
|
||||
public string $dockerCleanupFrequency = '*/10 * * * *';
|
||||
|
||||
#[Rule(['integer', 'min:1', 'max:99'])]
|
||||
public int $dockerCleanupThreshold = 10;
|
||||
|
||||
#[Rule(['integer', 'min:1', 'max:99'])]
|
||||
public int $serverDiskUsageNotificationThreshold = 50;
|
||||
|
||||
#[Rule('boolean')]
|
||||
public bool $deleteUnusedVolumes = false;
|
||||
|
||||
#[Rule('boolean')]
|
||||
public bool $deleteUnusedNetworks = false;
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return redirect()->route('server.show');
|
||||
}
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false)
|
||||
{
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->server->settings->concurrent_builds = $this->concurrentBuilds;
|
||||
$this->server->settings->dynamic_timeout = $this->dynamicTimeout;
|
||||
$this->server->settings->force_docker_cleanup = $this->forceDockerCleanup;
|
||||
$this->server->settings->docker_cleanup_frequency = $this->dockerCleanupFrequency;
|
||||
$this->server->settings->docker_cleanup_threshold = $this->dockerCleanupThreshold;
|
||||
$this->server->settings->server_disk_usage_notification_threshold = $this->serverDiskUsageNotificationThreshold;
|
||||
$this->server->settings->delete_unused_volumes = $this->deleteUnusedVolumes;
|
||||
$this->server->settings->delete_unused_networks = $this->deleteUnusedNetworks;
|
||||
$this->server->settings->save();
|
||||
} else {
|
||||
$this->concurrentBuilds = $this->server->settings->concurrent_builds;
|
||||
$this->dynamicTimeout = $this->server->settings->dynamic_timeout;
|
||||
$this->forceDockerCleanup = $this->server->settings->force_docker_cleanup;
|
||||
$this->dockerCleanupFrequency = $this->server->settings->docker_cleanup_frequency;
|
||||
$this->dockerCleanupThreshold = $this->server->settings->docker_cleanup_threshold;
|
||||
$this->serverDiskUsageNotificationThreshold = $this->server->settings->server_disk_usage_notification_threshold;
|
||||
$this->deleteUnusedVolumes = $this->server->settings->delete_unused_volumes;
|
||||
$this->deleteUnusedNetworks = $this->server->settings->delete_unused_networks;
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
try {
|
||||
$this->validate();
|
||||
$this->server->settings->save();
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Server updated.');
|
||||
$this->dispatch('refreshServerShow');
|
||||
// $this->dispatch('refreshServerShow');
|
||||
} catch (\Throwable $e) {
|
||||
$this->server->settings->refresh();
|
||||
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
@@ -60,12 +97,11 @@ class Advanced extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$frequency = $this->server->settings->docker_cleanup_frequency;
|
||||
if (empty($frequency) || ! validate_cron_expression($frequency)) {
|
||||
$this->server->settings->docker_cleanup_frequency = '*/10 * * * *';
|
||||
throw new \Exception('Invalid Cron / Human expression for Docker Cleanup Frequency. Resetting to default 10 minutes.');
|
||||
if (! validate_cron_expression($this->dockerCleanupFrequency)) {
|
||||
$this->dockerCleanupFrequency = $this->server->settings->getOriginal('docker_cleanup_frequency');
|
||||
throw new \Exception('Invalid Cron / Human expression for Docker Cleanup Frequency.');
|
||||
}
|
||||
$this->server->settings->save();
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Server updated.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
|
||||
@@ -19,6 +19,15 @@ class Charts extends Component
|
||||
|
||||
public bool $poll = true;
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function pollData()
|
||||
{
|
||||
if ($this->poll || $this->interval <= 10) {
|
||||
|
||||
@@ -3,27 +3,33 @@
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Livewire\Attributes\Rule;
|
||||
use Livewire\Component;
|
||||
|
||||
class CloudflareTunnels extends Component
|
||||
{
|
||||
public Server $server;
|
||||
|
||||
protected $rules = [
|
||||
'server.settings.is_cloudflare_tunnel' => 'required|boolean',
|
||||
];
|
||||
#[Rule(['required', 'boolean'])]
|
||||
public bool $isCloudflareTunnelsEnabled;
|
||||
|
||||
protected $validationAttributes = [
|
||||
'server.settings.is_cloudflare_tunnel' => 'Cloudflare Tunnel',
|
||||
];
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->isCloudflareTunnelsEnabled = $this->server->settings->is_cloudflare_tunnel;
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
try {
|
||||
$this->validate();
|
||||
$this->server->settings->is_cloudflare_tunnel = $this->isCloudflareTunnelsEnabled;
|
||||
$this->server->settings->save();
|
||||
$this->dispatch('success', 'Server updated.');
|
||||
$this->dispatch('refreshServerShow');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
@@ -31,6 +37,7 @@ class CloudflareTunnels extends Component
|
||||
|
||||
public function manualCloudflareConfig()
|
||||
{
|
||||
$this->isCloudflareTunnelsEnabled = true;
|
||||
$this->server->settings->is_cloudflare_tunnel = true;
|
||||
$this->server->settings->save();
|
||||
$this->server->refresh();
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Livewire\Server;
|
||||
|
||||
use App\Actions\Server\DeleteServer;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -13,7 +14,16 @@ class Delete extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $server;
|
||||
public Server $server;
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($password)
|
||||
{
|
||||
|
||||
@@ -3,27 +3,87 @@
|
||||
namespace App\Livewire\Server\Destination;
|
||||
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\SwarmDocker;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public ?Server $server = null;
|
||||
public Server $server;
|
||||
|
||||
public $parameters = [];
|
||||
public Collection $networks;
|
||||
|
||||
public function mount()
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($this->server)) {
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
$this->networks = collect();
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
loggy($this->server);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
private function createNetworkAndAttachToProxy()
|
||||
{
|
||||
$connectProxyToDockerNetworks = connectProxyToNetworks($this->server);
|
||||
instant_remote_process($connectProxyToDockerNetworks, $this->server, false);
|
||||
}
|
||||
|
||||
public function add($name)
|
||||
{
|
||||
if ($this->server->isSwarm()) {
|
||||
$found = $this->server->swarmDockers()->where('network', $name)->first();
|
||||
if ($found) {
|
||||
$this->dispatch('error', 'Network already added to this server.');
|
||||
|
||||
return;
|
||||
} else {
|
||||
SwarmDocker::create([
|
||||
'name' => $this->server->name.'-'.$name,
|
||||
'network' => $this->name,
|
||||
'server_id' => $this->server->id,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$found = $this->server->standaloneDockers()->where('network', $name)->first();
|
||||
if ($found) {
|
||||
$this->dispatch('error', 'Network already added to this server.');
|
||||
|
||||
return;
|
||||
} else {
|
||||
StandaloneDocker::create([
|
||||
'name' => $this->server->name.'-'.$name,
|
||||
'network' => $name,
|
||||
'server_id' => $this->server->id,
|
||||
]);
|
||||
}
|
||||
$this->createNetworkAndAttachToProxy();
|
||||
}
|
||||
}
|
||||
|
||||
public function scan()
|
||||
{
|
||||
if ($this->server->isSwarm()) {
|
||||
$alreadyAddedNetworks = $this->server->swarmDockers;
|
||||
} else {
|
||||
$alreadyAddedNetworks = $this->server->standaloneDockers;
|
||||
}
|
||||
$networks = instant_remote_process(['docker network ls --format "{{json .}}"'], $this->server, false);
|
||||
$this->networks = format_docker_command_output_to_json($networks)->filter(function ($network) {
|
||||
return $network['Name'] !== 'bridge' && $network['Name'] !== 'host' && $network['Name'] !== 'none';
|
||||
})->filter(function ($network) use ($alreadyAddedNetworks) {
|
||||
return ! $alreadyAddedNetworks->contains('network', $network['Name']);
|
||||
});
|
||||
if ($this->networks->count() === 0) {
|
||||
$this->dispatch('success', 'No new destinations found on this server.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->dispatch('success', 'Scan done.');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.server.destination.show');
|
||||
|
||||
@@ -111,7 +111,7 @@ class Form extends Component
|
||||
{
|
||||
if ($field === 'server.settings.docker_cleanup_frequency') {
|
||||
$frequency = $this->server->settings->docker_cleanup_frequency;
|
||||
if (empty($frequency) || ! validate_cron_expression($frequency)) {
|
||||
if (! validate_cron_expression($frequency)) {
|
||||
$this->dispatch('error', 'Invalid Cron / Human expression for Docker Cleanup Frequency. Resetting to default 10 minutes.');
|
||||
$this->server->settings->docker_cleanup_frequency = '*/10 * * * *';
|
||||
}
|
||||
|
||||
@@ -2,84 +2,96 @@
|
||||
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Actions\Server\InstallLogDrain;
|
||||
use App\Actions\Server\StartLogDrain;
|
||||
use App\Actions\Server\StopLogDrain;
|
||||
use App\Models\Server;
|
||||
use Livewire\Attributes\Rule;
|
||||
use Livewire\Component;
|
||||
|
||||
class LogDrains extends Component
|
||||
{
|
||||
public Server $server;
|
||||
|
||||
public $parameters = [];
|
||||
#[Rule(['boolean'])]
|
||||
public bool $isLogDrainNewRelicEnabled = false;
|
||||
|
||||
protected $rules = [
|
||||
'server.settings.is_logdrain_newrelic_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_newrelic_license_key' => 'required|string',
|
||||
'server.settings.logdrain_newrelic_base_uri' => 'required|string',
|
||||
'server.settings.is_logdrain_highlight_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_highlight_project_id' => 'required|string',
|
||||
'server.settings.is_logdrain_axiom_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_axiom_dataset_name' => 'required|string',
|
||||
'server.settings.logdrain_axiom_api_key' => 'required|string',
|
||||
'server.settings.is_logdrain_custom_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_custom_config' => 'required|string',
|
||||
'server.settings.logdrain_custom_config_parser' => 'nullable',
|
||||
];
|
||||
#[Rule(['boolean'])]
|
||||
public bool $isLogDrainCustomEnabled = false;
|
||||
|
||||
protected $validationAttributes = [
|
||||
'server.settings.is_logdrain_newrelic_enabled' => 'New Relic log drain',
|
||||
'server.settings.logdrain_newrelic_license_key' => 'New Relic license key',
|
||||
'server.settings.logdrain_newrelic_base_uri' => 'New Relic base URI',
|
||||
'server.settings.is_logdrain_highlight_enabled' => 'Highlight log drain',
|
||||
'server.settings.logdrain_highlight_project_id' => 'Highlight project ID',
|
||||
'server.settings.is_logdrain_axiom_enabled' => 'Axiom log drain',
|
||||
'server.settings.logdrain_axiom_dataset_name' => 'Axiom dataset name',
|
||||
'server.settings.logdrain_axiom_api_key' => 'Axiom API key',
|
||||
'server.settings.is_logdrain_custom_enabled' => 'Custom log drain',
|
||||
'server.settings.logdrain_custom_config' => 'Custom log drain configuration',
|
||||
'server.settings.logdrain_custom_config_parser' => 'Custom log drain configuration parser',
|
||||
];
|
||||
#[Rule(['boolean'])]
|
||||
public bool $isLogDrainAxiomEnabled = false;
|
||||
|
||||
public function mount()
|
||||
#[Rule(['string', 'nullable'])]
|
||||
public ?string $logDrainNewRelicLicenseKey = null;
|
||||
|
||||
#[Rule(['url', 'nullable'])]
|
||||
public ?string $logDrainNewRelicBaseUri = null;
|
||||
|
||||
#[Rule(['string', 'nullable'])]
|
||||
public ?string $logDrainAxiomDatasetName = null;
|
||||
|
||||
#[Rule(['string', 'nullable'])]
|
||||
public ?string $logDrainAxiomApiKey = null;
|
||||
|
||||
#[Rule(['string', 'nullable'])]
|
||||
public ?string $logDrainCustomConfig = null;
|
||||
|
||||
#[Rule(['string', 'nullable'])]
|
||||
public ?string $logDrainCustomConfigParser = null;
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($server)) {
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
$this->server = $server;
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureLogDrain()
|
||||
public function syncData(bool $toModel = false)
|
||||
{
|
||||
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->server->settings->is_logdrain_newrelic_enabled = $this->isLogDrainNewRelicEnabled;
|
||||
$this->server->settings->is_logdrain_axiom_enabled = $this->isLogDrainAxiomEnabled;
|
||||
$this->server->settings->is_logdrain_custom_enabled = $this->isLogDrainCustomEnabled;
|
||||
|
||||
$this->server->settings->logdrain_newrelic_license_key = $this->logDrainNewRelicLicenseKey;
|
||||
$this->server->settings->logdrain_newrelic_base_uri = $this->logDrainNewRelicBaseUri;
|
||||
$this->server->settings->logdrain_axiom_dataset_name = $this->logDrainAxiomDatasetName;
|
||||
$this->server->settings->logdrain_axiom_api_key = $this->logDrainAxiomApiKey;
|
||||
$this->server->settings->logdrain_custom_config = $this->logDrainCustomConfig;
|
||||
$this->server->settings->logdrain_custom_config_parser = $this->logDrainCustomConfigParser;
|
||||
|
||||
$this->server->settings->save();
|
||||
} else {
|
||||
$this->isLogDrainNewRelicEnabled = $this->server->settings->is_logdrain_newrelic_enabled;
|
||||
$this->isLogDrainAxiomEnabled = $this->server->settings->is_logdrain_axiom_enabled;
|
||||
$this->isLogDrainCustomEnabled = $this->server->settings->is_logdrain_custom_enabled;
|
||||
|
||||
$this->logDrainNewRelicLicenseKey = $this->server->settings->logdrain_newrelic_license_key;
|
||||
$this->logDrainNewRelicBaseUri = $this->server->settings->logdrain_newrelic_base_uri;
|
||||
$this->logDrainAxiomDatasetName = $this->server->settings->logdrain_axiom_dataset_name;
|
||||
$this->logDrainAxiomApiKey = $this->server->settings->logdrain_axiom_api_key;
|
||||
$this->logDrainCustomConfig = $this->server->settings->logdrain_custom_config;
|
||||
$this->logDrainCustomConfigParser = $this->server->settings->logdrain_custom_config_parser;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
try {
|
||||
InstallLogDrain::run($this->server);
|
||||
if (! $this->server->isLogDrainEnabled()) {
|
||||
$this->dispatch('serverRefresh');
|
||||
$this->syncData(true);
|
||||
if ($this->server->isLogDrainEnabled()) {
|
||||
StartLogDrain::run($this->server);
|
||||
$this->dispatch('success', 'Log drain service started.');
|
||||
} else {
|
||||
StopLogDrain::run($this->server);
|
||||
$this->dispatch('success', 'Log drain service stopped.');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->dispatch('serverRefresh');
|
||||
$this->dispatch('success', 'Log drain service started.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSave(string $type)
|
||||
{
|
||||
try {
|
||||
$ok = $this->submit($type);
|
||||
if (! $ok) {
|
||||
return;
|
||||
}
|
||||
$this->configureLogDrain();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
@@ -88,79 +100,10 @@ class LogDrains extends Component
|
||||
public function submit(string $type)
|
||||
{
|
||||
try {
|
||||
$this->resetErrorBag();
|
||||
if ($type === 'newrelic') {
|
||||
$this->validate([
|
||||
'server.settings.is_logdrain_newrelic_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_newrelic_license_key' => 'required|string',
|
||||
'server.settings.logdrain_newrelic_base_uri' => 'required|string',
|
||||
]);
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_highlight_enabled' => false,
|
||||
'is_logdrain_axiom_enabled' => false,
|
||||
'is_logdrain_custom_enabled' => false,
|
||||
]);
|
||||
} elseif ($type === 'highlight') {
|
||||
$this->validate([
|
||||
'server.settings.is_logdrain_highlight_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_highlight_project_id' => 'required|string',
|
||||
]);
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_newrelic_enabled' => false,
|
||||
'is_logdrain_axiom_enabled' => false,
|
||||
'is_logdrain_custom_enabled' => false,
|
||||
]);
|
||||
} elseif ($type === 'axiom') {
|
||||
$this->validate([
|
||||
'server.settings.is_logdrain_axiom_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_axiom_dataset_name' => 'required|string',
|
||||
'server.settings.logdrain_axiom_api_key' => 'required|string',
|
||||
]);
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_newrelic_enabled' => false,
|
||||
'is_logdrain_highlight_enabled' => false,
|
||||
'is_logdrain_custom_enabled' => false,
|
||||
]);
|
||||
} elseif ($type === 'custom') {
|
||||
$this->validate([
|
||||
'server.settings.is_logdrain_custom_enabled' => 'required|boolean',
|
||||
'server.settings.logdrain_custom_config' => 'required|string',
|
||||
'server.settings.logdrain_custom_config_parser' => 'nullable',
|
||||
]);
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_newrelic_enabled' => false,
|
||||
'is_logdrain_highlight_enabled' => false,
|
||||
'is_logdrain_axiom_enabled' => false,
|
||||
]);
|
||||
}
|
||||
if (! $this->server->isLogDrainEnabled()) {
|
||||
StopLogDrain::dispatch($this->server);
|
||||
}
|
||||
$this->server->settings->save();
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Settings saved.');
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
if ($type === 'newrelic') {
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_newrelic_enabled' => false,
|
||||
]);
|
||||
} elseif ($type === 'highlight') {
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_highlight_enabled' => false,
|
||||
]);
|
||||
} elseif ($type === 'axiom') {
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_axiom_enabled' => false,
|
||||
]);
|
||||
} elseif ($type === 'custom') {
|
||||
$this->server->settings->update([
|
||||
'is_logdrain_custom_enabled' => false,
|
||||
]);
|
||||
}
|
||||
handleError($e, $this);
|
||||
|
||||
return false;
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,26 +8,63 @@ use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
public ?Server $server = null;
|
||||
public Server $server;
|
||||
|
||||
public $privateKeys = [];
|
||||
|
||||
public $parameters = [];
|
||||
|
||||
public function mount()
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first();
|
||||
if (is_null($this->server)) {
|
||||
return redirect()->route('server.index');
|
||||
}
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->privateKeys = PrivateKey::ownedByCurrentTeam()->get()->where('is_git_related', false);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function setPrivateKey($privateKeyId)
|
||||
{
|
||||
$ownedPrivateKey = PrivateKey::ownedByCurrentTeam()->find($privateKeyId);
|
||||
if (is_null($ownedPrivateKey)) {
|
||||
$this->dispatch('error', 'You are not allowed to use this private key.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$originalPrivateKeyId = $this->server->getOriginal('private_key_id');
|
||||
try {
|
||||
$this->server->update(['private_key_id' => $privateKeyId]);
|
||||
['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(justCheckingNewKey: true);
|
||||
if ($uptime) {
|
||||
$this->dispatch('success', 'Private key updated successfully.');
|
||||
} else {
|
||||
throw new \Exception($error);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->server->update(['private_key_id' => $originalPrivateKeyId]);
|
||||
$this->server->validateConnection();
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function checkConnection()
|
||||
{
|
||||
try {
|
||||
['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection();
|
||||
if ($uptime) {
|
||||
$this->dispatch('success', 'Server is reachable.');
|
||||
} else {
|
||||
$this->dispatch('error', 'Server is not reachable.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help.<br><br>Error: '.$error);
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.server.private-key.show');
|
||||
|
||||
@@ -3,38 +3,203 @@
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Livewire\Attributes\Rule;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Server $server;
|
||||
|
||||
public array $parameters;
|
||||
#[Rule(['required'])]
|
||||
public string $name;
|
||||
|
||||
protected $listeners = ['refreshServerShow'];
|
||||
#[Rule(['nullable'])]
|
||||
public ?string $description;
|
||||
|
||||
public function mount()
|
||||
#[Rule(['required'])]
|
||||
public string $ip;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public string $user;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public string $port;
|
||||
|
||||
#[Rule(['nullable'])]
|
||||
public ?string $validationLogs = null;
|
||||
|
||||
#[Rule(['nullable', 'url'])]
|
||||
public ?string $wildcardDomain;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isReachable;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isUsable;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isSwarmManager;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isSwarmWorker;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isBuildServer;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isMetricsEnabled;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public string $sentinelToken;
|
||||
|
||||
#[Rule(['nullable'])]
|
||||
public ?string $sentinelUpdatedAt;
|
||||
|
||||
#[Rule(['required', 'integer', 'min:1'])]
|
||||
public int $sentinelMetricsRefreshRateSeconds;
|
||||
|
||||
#[Rule(['required', 'integer', 'min:1'])]
|
||||
public int $sentinelMetricsHistoryDays;
|
||||
|
||||
#[Rule(['required', 'integer', 'min:10'])]
|
||||
public int $sentinelPushIntervalSeconds;
|
||||
|
||||
#[Rule(['nullable', 'url'])]
|
||||
public ?string $sentinelCustomUrl;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isSentinelEnabled;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public bool $isSentinelDebugEnabled;
|
||||
|
||||
#[Rule(['required'])]
|
||||
public string $serverTimezone;
|
||||
|
||||
public array $timezones;
|
||||
|
||||
public function getListeners()
|
||||
{
|
||||
$teamId = auth()->user()->currentTeam()->id;
|
||||
|
||||
return [
|
||||
"echo-private:team.{$teamId},CloudflareTunnelConfigured" => '$refresh',
|
||||
'refreshServerShow' => '$refresh',
|
||||
];
|
||||
}
|
||||
|
||||
public function mount(string $server_uuid)
|
||||
{
|
||||
try {
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->firstOrFail();
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||
$this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray();
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshServerShow()
|
||||
public function syncData(bool $toModel = false)
|
||||
{
|
||||
$this->server->refresh();
|
||||
$this->dispatch('$refresh');
|
||||
if ($toModel) {
|
||||
$this->validate();
|
||||
$this->server->name = $this->name;
|
||||
$this->server->description = $this->description;
|
||||
$this->server->ip = $this->ip;
|
||||
$this->server->user = $this->user;
|
||||
$this->server->port = $this->port;
|
||||
$this->server->validation_logs = $this->validationLogs;
|
||||
$this->server->save();
|
||||
|
||||
$this->server->settings->is_swarm_manager = $this->isSwarmManager;
|
||||
$this->server->settings->is_swarm_worker = $this->isSwarmWorker;
|
||||
$this->server->settings->is_build_server = $this->isBuildServer;
|
||||
$this->server->settings->is_metrics_enabled = $this->isMetricsEnabled;
|
||||
$this->server->settings->sentinel_token = $this->sentinelToken;
|
||||
$this->server->settings->sentinel_metrics_refresh_rate_seconds = $this->sentinelMetricsRefreshRateSeconds;
|
||||
$this->server->settings->sentinel_metrics_history_days = $this->sentinelMetricsHistoryDays;
|
||||
$this->server->settings->sentinel_push_interval_seconds = $this->sentinelPushIntervalSeconds;
|
||||
$this->server->settings->sentinel_custom_url = $this->sentinelCustomUrl;
|
||||
$this->server->settings->is_sentinel_enabled = $this->isSentinelEnabled;
|
||||
$this->server->settings->is_sentinel_debug_enabled = $this->isSentinelDebugEnabled;
|
||||
$this->server->settings->server_timezone = $this->serverTimezone;
|
||||
$this->server->settings->save();
|
||||
} else {
|
||||
$this->name = $this->server->name;
|
||||
$this->description = $this->server->description;
|
||||
$this->ip = $this->server->ip;
|
||||
$this->user = $this->server->user;
|
||||
$this->port = $this->server->port;
|
||||
$this->wildcardDomain = $this->server->settings->wildcard_domain;
|
||||
$this->isReachable = $this->server->settings->is_reachable;
|
||||
$this->isUsable = $this->server->settings->is_usable;
|
||||
$this->isSwarmManager = $this->server->settings->is_swarm_manager;
|
||||
$this->isSwarmWorker = $this->server->settings->is_swarm_worker;
|
||||
$this->isBuildServer = $this->server->settings->is_build_server;
|
||||
$this->isMetricsEnabled = $this->server->settings->is_metrics_enabled;
|
||||
$this->sentinelToken = $this->server->settings->sentinel_token;
|
||||
$this->sentinelMetricsRefreshRateSeconds = $this->server->settings->sentinel_metrics_refresh_rate_seconds;
|
||||
$this->sentinelMetricsHistoryDays = $this->server->settings->sentinel_metrics_history_days;
|
||||
$this->sentinelPushIntervalSeconds = $this->server->settings->sentinel_push_interval_seconds;
|
||||
$this->sentinelCustomUrl = $this->server->settings->sentinel_custom_url;
|
||||
$this->isSentinelEnabled = $this->server->settings->is_sentinel_enabled;
|
||||
$this->isSentinelDebugEnabled = $this->server->settings->is_sentinel_debug_enabled;
|
||||
$this->sentinelUpdatedAt = $this->server->settings->updated_at;
|
||||
$this->serverTimezone = $this->server->settings->server_timezone;
|
||||
}
|
||||
}
|
||||
|
||||
public function validateServer($install = true)
|
||||
{
|
||||
try {
|
||||
$this->validationLogs = $this->server->validation_logs = null;
|
||||
$this->server->save();
|
||||
$this->dispatch('init', $install);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkLocalhostConnection()
|
||||
{
|
||||
$this->syncData(true);
|
||||
['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection();
|
||||
if ($uptime) {
|
||||
$this->dispatch('success', 'Server is reachable.');
|
||||
$this->server->settings->is_reachable = $this->isReachable = true;
|
||||
$this->server->settings->is_usable = $this->isUsable = true;
|
||||
$this->server->settings->save();
|
||||
$this->dispatch('proxyStatusUpdated');
|
||||
} else {
|
||||
$this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help. <br><br>Error: '.$error);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function regenerateSentinelToken()
|
||||
{
|
||||
try {
|
||||
$this->server->settings->generateSentinelToken();
|
||||
$this->dispatch('success', 'Token regenerated & Sentinel restarted.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
$this->submit();
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->dispatch('serverRefresh', false);
|
||||
try {
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Server updated');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Server;
|
||||
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
|
||||
class ShowPrivateKey extends Component
|
||||
{
|
||||
public Server $server;
|
||||
|
||||
public $privateKeys;
|
||||
|
||||
public $parameters;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
}
|
||||
|
||||
public function setPrivateKey($privateKeyId)
|
||||
{
|
||||
$ownedPrivateKey = PrivateKey::ownedByCurrentTeam()->find($privateKeyId);
|
||||
if (is_null($ownedPrivateKey)) {
|
||||
$this->dispatch('error', 'You are not allowed to use this private key.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$originalPrivateKeyId = $this->server->getOriginal('private_key_id');
|
||||
try {
|
||||
$this->server->update(['private_key_id' => $privateKeyId]);
|
||||
['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection(justCheckingNewKey: true);
|
||||
if ($uptime) {
|
||||
$this->dispatch('success', 'Private key updated successfully.');
|
||||
} else {
|
||||
throw new \Exception($error);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->server->update(['private_key_id' => $originalPrivateKeyId]);
|
||||
$this->server->validateConnection();
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
} finally {
|
||||
$this->dispatch('refreshServerShow');
|
||||
$this->server->refresh();
|
||||
}
|
||||
}
|
||||
|
||||
public function checkConnection()
|
||||
{
|
||||
try {
|
||||
['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection();
|
||||
if ($uptime) {
|
||||
$this->dispatch('success', 'Server is reachable.');
|
||||
} else {
|
||||
$this->dispatch('error', 'Server is not reachable.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help.<br><br>Error: '.$error);
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
} finally {
|
||||
$this->dispatch('refreshServerShow');
|
||||
$this->server->refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,11 @@ class Server extends BaseModel
|
||||
$payload['ip'] = str($server->ip)->trim();
|
||||
}
|
||||
$server->forceFill($payload);
|
||||
|
||||
});
|
||||
static::saved(function ($server) {
|
||||
if ($server->privateKey->isDirty()) {
|
||||
refresh_server_connection($server->privateKey);
|
||||
}
|
||||
});
|
||||
static::created(function ($server) {
|
||||
ServerSetting::create([
|
||||
@@ -1027,7 +1031,6 @@ $schema://$host {
|
||||
$this->refresh();
|
||||
$unreachableNotificationSent = (bool) $this->unreachable_notification_sent;
|
||||
$isReachable = (bool) $this->settings->is_reachable;
|
||||
loggy('Server setting is_reachable changed to '.$isReachable.' for server '.$this->id.'. Unreachable notification sent: '.$unreachableNotificationSent);
|
||||
// If the server is reachable, send the reachable notification if it was sent before
|
||||
if ($isReachable === true) {
|
||||
if ($unreachableNotificationSent === true) {
|
||||
|
||||
@@ -117,7 +117,6 @@ class ServerSetting extends Model
|
||||
$domain = 'http://'.$settings->public_ipv6.':8000';
|
||||
}
|
||||
$this->sentinel_custom_url = $domain;
|
||||
loggy('Sentinel URL: '.$domain);
|
||||
if ($save) {
|
||||
$this->save();
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components\Server;
|
||||
|
||||
use App\Models\Server;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class Sidebar extends Component
|
||||
{
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct(public Server $server, public $parameters)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.server.sidebar');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user