coolify/app/Traits/ExecuteRemoteCommand.php

92 lines
4.1 KiB
PHP
Raw Normal View History

2023-06-30 19:22:14 +00:00
<?php
namespace App\Traits;
use App\Enums\ApplicationDeploymentStatus;
2024-09-23 17:51:31 +00:00
use App\Helpers\SshMultiplexingHelper;
2023-06-30 19:22:14 +00:00
use App\Models\Server;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Process;
2025-01-07 13:52:08 +00:00
use RuntimeException;
2023-06-30 19:22:14 +00:00
trait ExecuteRemoteCommand
{
public ?string $save = null;
2024-06-10 20:43:34 +00:00
2023-11-24 14:48:23 +00:00
public static int $batch_counter = 0;
2024-06-10 20:43:34 +00:00
2023-06-30 19:22:14 +00:00
public function execute_remote_command(...$commands)
{
static::$batch_counter++;
2025-01-07 13:52:08 +00:00
$commandsText = $commands instanceof Collection ? $commands : collect($commands);
2023-06-30 19:22:14 +00:00
if ($this->server instanceof Server === false) {
2025-01-07 13:52:08 +00:00
throw new RuntimeException('Server is not set or is not an instance of Server model');
2023-06-30 19:22:14 +00:00
}
$commandsText->each(function ($single_command) {
2025-01-07 13:52:08 +00:00
$command = data_get($single_command, 'command', $single_command[0] ?? null);
2023-06-30 19:22:14 +00:00
if ($command === null) {
2025-01-07 13:52:08 +00:00
throw new RuntimeException('Command is not set');
2023-06-30 19:22:14 +00:00
}
$hidden = data_get($single_command, 'hidden', false);
$customType = data_get($single_command, 'type');
2023-06-30 19:22:14 +00:00
$ignore_errors = data_get($single_command, 'ignore_errors', false);
2024-01-11 11:56:02 +00:00
$append = data_get($single_command, 'append', true);
2023-06-30 19:22:14 +00:00
$this->save = data_get($single_command, 'save');
if ($this->server->isNonRoot()) {
if (str($command)->startsWith('docker exec')) {
$command = str($command)->replace('docker exec', 'sudo docker exec');
} else {
$command = parseLineForSudo($command, $this->server);
}
}
2024-09-17 10:26:11 +00:00
$remote_command = SshMultiplexingHelper::generateSshCommand($this->server, $command);
2025-01-07 13:52:08 +00:00
$invokedProcess = Process::timeout(3600)->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden, $customType, $append) {
$output = str($output)->trim();
if ($output->startsWith('╔')) {
2024-06-10 20:43:34 +00:00
$output = "\n".$output;
}
2023-06-30 19:22:14 +00:00
$new_log_entry = [
'command' => remove_iip($command),
'output' => remove_iip($output),
'type' => $customType ?? $type === 'err' ? 'stderr' : 'stdout',
2023-06-30 19:22:14 +00:00
'timestamp' => Carbon::now('UTC'),
'hidden' => $hidden,
'batch' => static::$batch_counter,
];
2024-06-10 20:43:34 +00:00
if (! $this->application_deployment_queue->logs) {
2023-06-30 19:22:14 +00:00
$new_log_entry['order'] = 1;
} else {
$previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);
2023-06-30 19:22:14 +00:00
$new_log_entry['order'] = count($previous_logs) + 1;
}
$previous_logs[] = $new_log_entry;
$this->application_deployment_queue->logs = json_encode($previous_logs, flags: JSON_THROW_ON_ERROR);
$this->application_deployment_queue->save();
2023-06-30 19:22:14 +00:00
if ($this->save) {
2024-01-11 11:56:02 +00:00
if (data_get($this->saved_outputs, $this->save, null) === null) {
data_set($this->saved_outputs, $this->save, str());
}
if ($append) {
$this->saved_outputs[$this->save] .= str($output)->trim();
$this->saved_outputs[$this->save] = str($this->saved_outputs[$this->save]);
} else {
$this->saved_outputs[$this->save] = str($output)->trim();
}
2023-06-30 19:22:14 +00:00
}
});
$this->application_deployment_queue->update([
2025-01-07 13:52:08 +00:00
'current_process_id' => $invokedProcess->id(),
2023-06-30 19:22:14 +00:00
]);
2025-01-07 13:52:08 +00:00
$processResult = $invokedProcess->wait();
if ($processResult->exitCode() !== 0 && ! $ignore_errors) {
$this->application_deployment_queue->status = ApplicationDeploymentStatus::FAILED->value;
$this->application_deployment_queue->save();
throw new RuntimeException($processResult->errorOutput());
2023-06-30 19:22:14 +00:00
}
});
}
}